diff --git a/README.md b/README.md index 435bbc1..2aa2a5b 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,20 @@ ### 群服互联参考流程 1. 装好插件启动后,记录下首次生成的 `Token`,或者自己填写一个 `Token` -2. 下载 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 并初始化配置 +2. 下载 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 并初始化配置,打开配置文件 `config.yml` 3. 在 `access-token: ''` 填写前面所述的 `Token` 内容 4. 在 `ws-reverse` 选项下的 `universal` 填写GC的服务器地址加路径,例如 `ws://127.0.0.1:443/openchat` -5. 配置你的Bot账号和登录协议,建议使用 `Android Watch` 登录。具体参考文档 [配置](https://docs.go-cqhttp.org/guide/config.html)。 +5. 配置你的Bot账号和登录协议,建议使用 `Android Watch` 登录。具体参考文档 [配置](https://docs.go-cqhttp.org/guide/config.html)。(在 `device.json` 中 `"protocol": 5` 修改为 `"protocol": 2` ) +6. 在GC中使用 `/sc group ` 来设置要互联的群聊 +7. 在GC中使用 `/sc op ` 来设置管理员账号 +8. 现在,理论上已经完成了群服互联,在群里可以看到玩家上下线和聊天,同时玩家也可以在游戏里看到群里聊天, +你还可以在群里用默认前缀 `/` 来执行命令, +但是暂时**不会**回复结果,你可能需要自己看控制台来查看执行结果。 + + +_值得注意的是,本插件支持的是 [OneBot-v11](https://github.com/botuniverse/onebot-11) 协议,理论上所有支持OneBot-v11 [反向WebSocket](https://github.com/botuniverse/onebot-11/blob/master/communication/ws-reverse.md) 的机器人框架都可以连接,不仅限于cqhttp。_ + +_TODO: 计划会出一个极简的纯对话协议,比OneBot更简单,方便第三方对接。_ --- @@ -194,3 +204,14 @@ } ``` +# 敏感词过滤系统 +目前实现了一个最基础的敏感词过滤功能, 并附带了一个精简的敏感词库, +在首次启动时会把词库释放到插件数据目录下。 + +文件名叫 `SensitiveWordList.txt`,每行包含一个敏感词,你可以自己维护这个文件,修改后可以用 `/sc reload` 重新读取。 + +当检测到游戏内玩家聊天中包含敏感词,将不会进行转发,并且会在控制台中打印。 + +目前暂未设定惩罚机制,仅仅只是发出去别人看不到,自己不知道这个没发出去。 + +如果你有更好的建议,欢迎[提交 issue](https://github.com/jie65535/gc-openchat-plugin/issues/new) \ No newline at end of file diff --git a/src/main/java/com/github/jie65535/openchat/OpenChatPlugin.java b/src/main/java/com/github/jie65535/openchat/OpenChatPlugin.java index 1b4012a..04510a9 100644 --- a/src/main/java/com/github/jie65535/openchat/OpenChatPlugin.java +++ b/src/main/java/com/github/jie65535/openchat/OpenChatPlugin.java @@ -19,16 +19,17 @@ package com.github.jie65535.openchat; import com.github.jie65535.openchat.commands.ChatPlayerCommands; import com.github.jie65535.openchat.commands.ChatServerCommands; +import com.github.jie65535.openchat.utils.SensitiveWordFilter; import emu.grasscutter.plugin.Plugin; import emu.grasscutter.server.event.EventHandler; import emu.grasscutter.server.event.HandlerPriority; import emu.grasscutter.server.event.player.PlayerJoinEvent; import emu.grasscutter.utils.JsonUtils; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; +import java.io.*; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.Objects; public final class OpenChatPlugin extends Plugin { private static OpenChatPlugin instance; @@ -36,6 +37,45 @@ public final class OpenChatPlugin extends Plugin { return instance; } + + @Override + public void onLoad() { + instance = this; + loadConfig(); + loadData(); + loadSensitiveWordList(); + getLogger().info("[OpenChat] Loaded."); + } + + @Override + public void onEnable() { + // Register event listeners. + new EventHandler<>(PlayerJoinEvent.class) + .priority(HandlerPriority.NORMAL) + .listener(EventListeners::onJoin) + .register(this); + + // Register commands. + getHandle().registerCommand(new ChatServerCommands()); + getHandle().registerCommand(new ChatPlayerCommands()); + + // Set my chat system. + getServer().setChatSystem(new OpenChatSystem(this)); + + // Log a plugin status message. + getLogger().info("[OpenChat] Enabled, see https://github.com/jie65535/gc-openchat-plugin"); + } + + @Override + public void onDisable() { + saveData(); + saveConfig(); + getLogger().info("[OpenChat] Disabled."); + } + + + // region config + private OpenChatConfig config; public OpenChatConfig getConfig() { return config; @@ -65,6 +105,10 @@ public final class OpenChatPlugin extends Plugin { } } + // endregion + + // region data + private OpenChatData data; public OpenChatData getData() { return data; @@ -93,37 +137,33 @@ public final class OpenChatPlugin extends Plugin { } } - @Override - public void onLoad() { - instance = this; - loadConfig(); - loadData(); - getLogger().info("[OpenChat] Loaded."); + // endregion + + // region SensitiveWordFilter + + private final SensitiveWordFilter sensitiveWordFilter = new SensitiveWordFilter(); + + public SensitiveWordFilter getSensitiveWordFilter() { + return sensitiveWordFilter; + } + private static final String SENSITIVE_WORD_LIST_FILE_NAME = "SensitiveWordList.txt"; + public void loadSensitiveWordList() { + try { + var sensitiveWordListFile = new File(getDataFolder(), SENSITIVE_WORD_LIST_FILE_NAME); + if (!sensitiveWordListFile.exists()) { + var in = OpenChatPlugin.class.getClassLoader().getResourceAsStream(SENSITIVE_WORD_LIST_FILE_NAME); + Files.copy(Objects.requireNonNull(in), sensitiveWordListFile.toPath()); + in.close(); + } + var wordList = Files.readAllLines(sensitiveWordListFile.toPath()); + for (var word : wordList) { + sensitiveWordFilter.addWord(word); + } + getLogger().info("[OpenChat] {} sensitive words loaded", wordList.size()); + } catch (Exception ex) { + getLogger().error("[OpenChat] Failed to load sensitive word list!", ex); + } } - @Override - public void onEnable() { - // Register event listeners. - new EventHandler<>(PlayerJoinEvent.class) - .priority(HandlerPriority.NORMAL) - .listener(EventListeners::onJoin) - .register(this); - - // Register commands. - getHandle().registerCommand(new ChatServerCommands()); - getHandle().registerCommand(new ChatPlayerCommands()); - - // Set my chat system. - getServer().setChatSystem(new OpenChatSystem(this)); - - // Log a plugin status message. - getLogger().info("[OpenChat] Enabled, see https://github.com/jie65535/gc-openchat-plugin"); - } - - @Override - public void onDisable() { - saveData(); - saveConfig(); - getLogger().info("[OpenChat] Disabled."); - } + // endregion } diff --git a/src/main/java/com/github/jie65535/openchat/OpenChatSystem.java b/src/main/java/com/github/jie65535/openchat/OpenChatSystem.java index e80bf0b..9708752 100644 --- a/src/main/java/com/github/jie65535/openchat/OpenChatSystem.java +++ b/src/main/java/com/github/jie65535/openchat/OpenChatSystem.java @@ -318,8 +318,7 @@ public class OpenChatSystem extends ChatSystem { * @return 是否合法合规 */ private boolean checkMessageModeration(String message) { - // TODO see https://github.com/houbb/sensitive-word - return !message.isEmpty(); + return !plugin.getSensitiveWordFilter().isSensitive(message); } // region 发言频率限制 diff --git a/src/main/java/com/github/jie65535/openchat/commands/ChatServerCommands.java b/src/main/java/com/github/jie65535/openchat/commands/ChatServerCommands.java index f0ea684..1c9db77 100644 --- a/src/main/java/com/github/jie65535/openchat/commands/ChatServerCommands.java +++ b/src/main/java/com/github/jie65535/openchat/commands/ChatServerCommands.java @@ -107,6 +107,7 @@ public class ChatServerCommands implements CommandHandler { } case "reload" -> { plugin.loadConfig(); + plugin.loadSensitiveWordList(); CommandHandler.sendMessage(sender, "OK"); } case "group" -> { diff --git a/src/main/java/com/github/jie65535/openchat/utils/SensitiveWordFilter.java b/src/main/java/com/github/jie65535/openchat/utils/SensitiveWordFilter.java new file mode 100644 index 0000000..3c42365 --- /dev/null +++ b/src/main/java/com/github/jie65535/openchat/utils/SensitiveWordFilter.java @@ -0,0 +1,81 @@ +/* + * gc-openchat + * Copyright (C) 2022 jie65535 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.github.jie65535.openchat.utils; + +import java.util.HashMap; +import java.util.Map; + +public class SensitiveWordFilter { + + // 定义一个内部类表示图中的节点 + private static class Node { + // 用一个哈希表存储该节点的后继节点 + private final Map children = new HashMap<>(); + // 用一个布尔值表示该节点是否是某个敏感词的结尾 + private boolean isEnd = false; + } + + // 定义一个根节点 + private final Node root = new Node(); + + // 定义一个添加敏感词的方法 + public void addWord(String word) { + if (word == null || word.isEmpty()) { + return; + } + // 从根节点开始遍历 + Node current = root; + for (char c : word.toCharArray()) { + // 如果当前节点没有以c为键的后继节点,就创建一个新的节点并添加到哈希表中 + if (!current.children.containsKey(c)) { + current.children.put(c, new Node()); + } + // 更新当前节点为后继节点 + current = current.children.get(c); + } + // 标记当前节点为某个敏感词的结尾 + current.isEnd = true; + } + + // 定义一个检测聊天消息是否包含敏感词的方法 + public boolean isSensitive(String message) { + if (message == null || message.isEmpty()) { + return false; + } + // 遍历聊天消息中的每个字符作为起始位置 + for (int i = 0; i < message.length(); i++) { + // 从根节点开始遍历 + Node current = root; + for (int j = i; j < message.length(); j++) { + char c = message.charAt(j); + // 如果当前节点没有以c为键的后继节点,说明没有匹配到敏感词,跳出循环 + if (!current.children.containsKey(c)) { + break; + } + // 更新当前节点为后继节点 + current = current.children.get(c); + // 如果当前节点是某个敏感词的结尾,说明匹配到了敏感词,返回true + if (current.isEnd) { + return true; + } + } + } + // 遍历完聊天消息没有匹配到任何敏感词,返回false + return false; + } +} diff --git a/src/main/resources/SensitiveWordList.txt b/src/main/resources/SensitiveWordList.txt new file mode 100644 index 0000000..f337963 --- /dev/null +++ b/src/main/resources/SensitiveWordList.txt @@ -0,0 +1,576 @@ +18禁 +a片 +caonima +cnm +caotama +cao你 +cao你妈 +fa轮 +fuck +hjt +jb +jzm +nmsl +sb +vpn +zhengfu +zheng府 +zf +zedong +亂倫 +噴精 +姦淫 +屄 +屄毛 +幹炮 +幹砲 +擠乳汁 +溫家寶 +無毛穴 +獸交 +爱女人 +爱液 +扒穴 +拔屄自拍 +白虎阴穴 +白虎少妇 +白浆四溅 +包二奶 +薄熙来 +薄码 +暴奸 +爆乳娘 +爆草 +爆操 +被操 +被插 +被干 +逼痒 +逼奸 +博彩 +擦你妈 +操我 +操死 +操死你 +操你妈 +操你奶 +操你姐 +操逼 +操你祖宗 +操你大爷 +操你妹 +操穴 +操屄 +操他妈 +操你全家 +操烂 +操妻 +操你嘴 +操死她 +操b +操它妈 +曹刚川 +草你祖宗 +草你大爷 +草你妈 +草你吗 +草bi +草她妈 +草拟吗 +草你娘 +草他妈 +厕所盗摄 +厕奴 +插阴茎 +插逼 +插妹妹 +插穴止痒 +插死她 +插比 +插b +插你 +陈同海 +陈水扁 +陈良宇 +成人片 +成人网站 +成人图 +成人电 +成人文 +成人视 +成人自拍 +成人小 +惩公安 +吃鸡巴 +抽插 +臭鸡八 +臭鸡吧 +床上写真 +催情藥 +催情药 +催眠水 +催情粉 +大奶子 +大肉棒 +大奶头 +大明运气咒 +大力抽送 +大血逼 +大雞巴 +大鸡巴 +大傻b +戴秉国 +盗撮 +邓小瓶 +邓小平 +邓爷爷 +东北独立 +杜世成 +杜德印 +法lun +法伦功 +法维权 +法一轮 +法正乾 +法车仑 +法轮佛 +法轮 +翻墙 +反共复清 +反华示威 +肥逼 +粉穴 +风艳阁 +干你妈 +干的爽 +干穴 +干你娘 +干你妹 +干死你 +干你全家 +肛交 +肛门 +肛门拳交 +给你爽 +根达亚文明 +共残主义 +狗娘养 +灌满精液 +郭金龙 +国峰 +国锋 +含屌 +喝血社会 +黑毛屄 +胡云松 +胡王八 +胡谨涛 +胡錦濤 +胡海峰 +胡主席 +胡春华 +胡温 +虎精逃 +华国 +黄色电影 +回良玉 +混蛋 +激情电 +激情妹 +激情炮 +激情短 +激情小说 +鸡巴 +鸡奸 +集体自杀 +挤乳汁 +几吧 +妓女 +家宝 +奸幼 +奸杀 +奸污 +践货 +贱人 +贱比 +江泽民 +江澤民 +江x +江某某 +脚奴 +街头扒衣 +金毛穴 +锦涛 +精子射在 +警察说保 +警方包庇 +警车雷达 +警察殴打 +警察的幌 +就去日 +菊花洞 +巨乳 +恐怖份子 +恐怖分子 +抠穴 +口淫 +口交 +口活 +口内爆射 +狂乳激揺 +拉登 +浪逼 +浪叫 +雷管 +李小鹏 +李鹏 +李克强 +李洪志 +李世民 +習近平 +莲花逼 +炼大法 +梁光烈 +两会又三 +两会代 +刘延东 +露逼 +露b +乱伦类 +乱奸 +乱伦小 +轮子功 +轮奸 +轮功 +伦理毛 +伦理电影 +伦理片 +伦理大 +裸舞视 +裸体 +裸聊网 +妈个逼 +妈了个逼 +妈了逼 +麻果配 +麻果丸 +麻古 +玛雅历法 +卖淫 +满狗 +肏屄 +氓培训 +猫贼洞 +毛主席 +毛遮洞 +毛则东 +毛泽东 +毛贼东 +毛澤東 +美女高潮 +美艳少妇 +妹按摩 +妹上门 +门按摩 +门保健 +蒙汗药 +孟建柱 +迷昏口 +迷奸 +迷魂香 +迷幻型 +迷幻药 +迷情药 +迷幻藥 +迷魂药 +迷藥 +迷奸药 +迷昏药 +迷昏藥 +迷魂藥 +迷情水 +谜奸药 +秘唇 +蜜穴 +密穴 +民抗议 +明慧网 +摸阴蒂 +某锦涛 +母奸 +母子乱伦 +母子奸情 +奶子 +男奴 +男女交欢 +内射 +嫩穴 +嫩b +嫩逼 +嫩屄 +嫩bb +嫩阴 +你妈死了 +你日妈 +你妈逼 +娘西皮 +娘了个比 +娘两腿之间 +浓精 +怒的志愿 +女优 +女任职名 +女人和狗 +女技师 +女激情 +女優 +女上门 +女被人家搞 +拍肩神药 +炮友 +喷尿 +屁眼 +平叫到床 +平惨案 +仆不怕饮 +普通嘌 +期货配 +奇迹的黄 +奇淫散 +强暴 +强硬发言 +强奸你妹 +强奸 +强权政府 +巧淫奸戏 +情色 +全裸 +全家死绝 +全家死光 +群奸暴 +群体性事 +群起抗暴 +群交 +绕过封锁 +人类灭亡 +人兽 +人妻 +人妻做爱 +人妻熟女 +人妻榨乳 +人体炸弹 +人妻色诱 +日中断交 +日你妹 +日烂 +日你全家 +日死你 +日你妈 +日逼 +肉棒 +肉壶 +肉蒲团 +肉便器 +肉茎 +肉淫器吞精 +肉棍 +肉穴 +肉逼 +肉棍干骚妇 +肉唇 +肉洞 +乳交 +软弱的国 +三秒倒 +三级片 +三挫 +三唑 +搔逼 +骚妇 +骚浪美女 +骚贱 +骚嘴 +骚姐姐 +骚母 +骚洞 +骚穴 +骚逼 +骚妹 +骚浪 +骚乳 +骚女 +骚水 +色妹妹 +色电影 +色视频 +色猫 +色小说 +色书库 +傻臂 +傻逼 +傻b +傻避 +煞笔 +煞逼 +少妇 +舌头穴 +射颜 +射爽 +社会主义灭亡 +沈跃跃 +十八禁 +兽奸 +熟妇人妻 +爽片 +爽穴 +死全家 +死逼 +苏树林 +酥穴 +塔利班 +蘚鮑 +台湾 +台独 +台湾独立 +体奸 +天黯门 +天岸门 +天案们 +天安门大屠杀 +天氨门 +天安门 +天胺门 +天案门 +舔脚 +舔屄 +铁凝 +偷窥图片 +推背图 +退党 +吞精 +王胜俊 +王岐山 +王洛林 +王太华 +王鸿举 +瘟总理 +瘟加饱 +瘟假饱 +温影帝 +温家堡 +温切斯特 +温家宝 +温家某 +吴定富 +吴邦国 +吸精少女 +习近平 +洗肠射尿 +下流地带 +下贱 +销魂洞 +小穴 +小平遗言 +小逼崽子 +小平遗嘱 +新唐人 +性虐 +性奴 +性爱 +性爱图库 +颜射 +艳妇淫女 +要射精了 +要泄了 +要射了 +要人权 +耀邦 +叶剑英 +夜激情 +液体炸 +一夜欢 +遗嘱小平 +阴屄 +阴b +阴茎 +阴唇 +阴部 +阴締 +淫贱 +淫叫 +淫液 +淫娃 +淫魔舞 +淫情 +淫肉 +淫蜜 +淫蕩 +淫汁 +淫姐 +淫妞 +淫逼 +淫亂潮吹 +淫荡 +淫騷妹 +淫情女 +淫奴 +淫兽 +淫兽学 +淫水 +淫妇 +淫穴 +淫水爱液 +淫母 +淫亂 +幼交 +玉穴 +原味内裤 +原味内衣 +援交妹 +杂种操的 +则民爷爷 +泽民 +炸立交 +炸弹遥控 +炸药的制 +炸药 +炸弹 +炸药配 +炸弹教 +炸鸟巢 +炸广州 +炸药制 +炸学校 +张志国 +张德江 +张荣坤 +政治局常委 +政fu +政府 +制服狩 +中国人权 +中日断交 +朱镕基 +猪容鸡 +诸世纪 +主席 +主席像 +自焚 +自拍美穴 +自慰抠穴 +自慰 +总竖鸡 +总理 +总书记 +钻插 +做爱 +妞上门 +嫖妓指南 +嫖鸡 +嫖俄罗 +門服務 +陰道 +陰唇 +陰戶 +掰穴 +騷浪 \ No newline at end of file