Implement sensitive word filter

This commit is contained in:
jie65535 committed 2023-03-05 18:50:24 +08:00
1 parent 2a696b4854
commit 61b9be9888
6 files changed
+756 -38

No files matched your search

+23 -2
View File
@@ -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 <groupId>` 来设置要互联的群聊
7. 在GC中使用 `/sc op <userId(QQ)>` 来设置管理员账号
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)
@@ -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
}
@@ -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 发言频率限制
@@ -107,6 +107,7 @@ public class ChatServerCommands implements CommandHandler {
}
case "reload" -> {
plugin.loadConfig();
plugin.loadSensitiveWordList();
CommandHandler.sendMessage(sender, "OK");
}
case "group" -> {
@@ -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 <https://www.gnu.org/licenses/>.
*/
package com.github.jie65535.openchat.utils;
import java.util.HashMap;
import java.util.Map;
public class SensitiveWordFilter {
// 定义一个内部类表示图中的节点
private static class Node {
// 用一个哈希表存储该节点的后继节点
private final Map<Character, Node> 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;
}
}
+576
View File
@@ -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
政府
制服狩
中国人权
中日断交
朱镕基
猪容鸡
诸世纪
主席
主席像
自焚
自拍美穴
自慰抠穴
自慰
总竖鸡
总理
总书记
钻插
做爱
妞上门
嫖妓指南
嫖鸡
嫖俄罗
門服務
陰道
陰唇
陰戶
掰穴
騷浪