feat: 添加黑白名单过滤系统以控制消息处理
This commit is contained in:
@@ -54,6 +54,100 @@ NEW_napcat_adapter/
|
|||||||
2. **启动插件**: 插件自动在系统启动时加载
|
2. **启动插件**: 插件自动在系统启动时加载
|
||||||
3. **WebSocket连接**: 自动连接到 Napcat OneBot 11 服务器
|
3. **WebSocket连接**: 自动连接到 Napcat OneBot 11 服务器
|
||||||
|
|
||||||
|
### 黑白名单过滤系统
|
||||||
|
|
||||||
|
本适配器内置了完整的黑白名单过滤系统,支持群聊和私聊消息的精细控制。
|
||||||
|
|
||||||
|
#### 🛡️ 过滤功能说明
|
||||||
|
|
||||||
|
1. **群聊过滤**
|
||||||
|
- **黑名单模式** (`blacklist`): 屏蔽指定群聊的消息
|
||||||
|
- **白名单模式** (`whitelist`): 只接收指定群聊的消息
|
||||||
|
|
||||||
|
2. **私聊过滤**
|
||||||
|
- **黑名单模式** (`blacklist`): 屏蔽指定用户的私聊消息
|
||||||
|
- **白名单模式** (`whitelist`): 只接收指定用户的私聊消息
|
||||||
|
|
||||||
|
3. **全局封禁**
|
||||||
|
- **用户封禁列表**: 无论在群聊还是私聊中都会被过滤
|
||||||
|
- **机器人过滤**: 自动屏蔽其他QQ机器人的消息
|
||||||
|
|
||||||
|
#### 📝 配置示例
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[features]
|
||||||
|
# 群聊配置:只允许特定群聊的消息
|
||||||
|
group_list_type = "whitelist"
|
||||||
|
group_list = ["123456789", "987654321"]
|
||||||
|
|
||||||
|
# 私聊配置:屏蔽特定用户的消息
|
||||||
|
private_list_type = "blacklist"
|
||||||
|
private_list = ["111111111", "222222222"]
|
||||||
|
|
||||||
|
# 全局封禁:这些用户的所有消息都会被过滤
|
||||||
|
ban_user_id = ["333333333", "444444444"]
|
||||||
|
|
||||||
|
# 屏蔽其他QQ机器人
|
||||||
|
ban_qq_bot = true
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 🎯 常见使用场景
|
||||||
|
|
||||||
|
1. **个人机器人**(只服务特定群组和用户):
|
||||||
|
```toml
|
||||||
|
group_list_type = "whitelist"
|
||||||
|
private_list_type = "whitelist"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **群管机器人**(屏蔽捣乱用户):
|
||||||
|
```toml
|
||||||
|
group_list_type = "blacklist"
|
||||||
|
ban_user_id = ["捣乱用户1", "捣乱用户2"]
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **公开服务机器人**(无限制接收所有消息):
|
||||||
|
```toml
|
||||||
|
# 保持默认的 blacklist 模式,名单为空即可
|
||||||
|
group_list_type = "blacklist"
|
||||||
|
private_list_type = "blacklist"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 📋 配置参数详解
|
||||||
|
|
||||||
|
| 参数 | 类型 | 默认值 | 说明 |
|
||||||
|
|------|------|--------|------|
|
||||||
|
| `group_list_type` | string | "blacklist" | 群聊过滤模式:"blacklist" 或 "whitelist" |
|
||||||
|
| `group_list` | array | [] | 群聊QQ号列表 |
|
||||||
|
| `private_list_type` | string | "blacklist" | 私聊过滤模式:"blacklist" 或 "whitelist" |
|
||||||
|
| `private_list` | array | [] | 用户QQ号列表 |
|
||||||
|
| `ban_user_id` | array | [] | 全局封禁的用户QQ号列表 |
|
||||||
|
| `ban_qq_bot` | boolean | false | 是否屏蔽其他QQ机器人消息 |
|
||||||
|
|
||||||
|
#### ⚡ 过滤逻辑流程
|
||||||
|
|
||||||
|
1. **消息接收** → 检查全局封禁列表
|
||||||
|
2. **通过** → 检查是否为机器人消息(如果启用 ban_qq_bot)
|
||||||
|
3. **通过** → 根据消息类型应用对应过滤规则:
|
||||||
|
- **群聊消息**: 应用群聊黑白名单规则
|
||||||
|
- **私聊消息**: 应用私聊黑白名单规则
|
||||||
|
4. **通过所有过滤** → 正常处理消息
|
||||||
|
5. **任一过滤失败** → 丢弃消息,记录调试日志
|
||||||
|
|
||||||
|
#### 🔧 配置文件位置
|
||||||
|
|
||||||
|
- **示例配置**: `src/plugins/built_in/napcat_adapter/config.example.toml`
|
||||||
|
- **实际配置**: `config/plugins/NEW_napcat_adapter.toml`
|
||||||
|
|
||||||
|
#### 📊 日志信息
|
||||||
|
|
||||||
|
被过滤的消息会在调试日志中记录:
|
||||||
|
```
|
||||||
|
[DEBUG] napcat_adapter: 群聊 123456789 在黑名单中,消息被过滤
|
||||||
|
[DEBUG] napcat_adapter: 私聊用户 111111111 在黑名单中,消息被过滤
|
||||||
|
[DEBUG] napcat_adapter: 用户 333333333 在全局封禁列表中,消息被过滤
|
||||||
|
[DEBUG] napcat_adapter: 检测到机器人消息 555555555,消息被过滤
|
||||||
|
```
|
||||||
|
|
||||||
## 🔑 核心数据结构
|
## 🔑 核心数据结构
|
||||||
|
|
||||||
### MessageEnvelope (mofox-wire v2.x)
|
### MessageEnvelope (mofox-wire v2.x)
|
||||||
|
|||||||
@@ -39,6 +39,79 @@ class MessageHandler:
|
|||||||
"""设置插件配置"""
|
"""设置插件配置"""
|
||||||
self.plugin_config = config
|
self.plugin_config = config
|
||||||
|
|
||||||
|
def _should_process_message(self, raw: Dict[str, Any]) -> bool:
|
||||||
|
"""
|
||||||
|
检查消息是否应该被处理(黑白名单过滤)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
raw: OneBot 原始消息数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True表示应该处理,False表示应该过滤
|
||||||
|
"""
|
||||||
|
if not self.plugin_config:
|
||||||
|
return True # 如果没有配置,默认处理所有消息
|
||||||
|
|
||||||
|
features_config = self.plugin_config.get("features", {})
|
||||||
|
|
||||||
|
# 获取消息基本信息
|
||||||
|
message_type = raw.get("message_type")
|
||||||
|
sender_info = raw.get("sender", {})
|
||||||
|
user_id = str(sender_info.get("user_id", ""))
|
||||||
|
|
||||||
|
# 检查全局封禁用户列表
|
||||||
|
ban_user_ids = features_config.get("ban_user_id", [])
|
||||||
|
if user_id in ban_user_ids:
|
||||||
|
logger.debug(f"用户 {user_id} 在全局封禁列表中,消息被过滤")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 检查是否屏蔽其他QQ机器人
|
||||||
|
if features_config.get("ban_qq_bot", False):
|
||||||
|
# 判断是否为机器人消息:通常通过sender中的role字段或其他标识
|
||||||
|
role = sender_info.get("role", "")
|
||||||
|
if role == "admin" or "bot" in str(sender_info).lower():
|
||||||
|
logger.debug(f"检测到机器人消息 {user_id},消息被过滤")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 群聊消息处理
|
||||||
|
if message_type == "group":
|
||||||
|
group_id = str(raw.get("group_id", ""))
|
||||||
|
|
||||||
|
# 获取群聊配置
|
||||||
|
group_list_type = features_config.get("group_list_type", "blacklist")
|
||||||
|
group_list = features_config.get("group_list", [])
|
||||||
|
|
||||||
|
if group_list_type == "blacklist":
|
||||||
|
# 黑名单模式:如果在黑名单中就过滤
|
||||||
|
if group_id in group_list:
|
||||||
|
logger.debug(f"群聊 {group_id} 在黑名单中,消息被过滤")
|
||||||
|
return False
|
||||||
|
else: # whitelist
|
||||||
|
# 白名单模式:如果不在白名单中就过滤
|
||||||
|
if group_id not in group_list:
|
||||||
|
logger.debug(f"群聊 {group_id} 不在白名单中,消息被过滤")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 私聊消息处理
|
||||||
|
elif message_type == "private":
|
||||||
|
# 获取私聊配置
|
||||||
|
private_list_type = features_config.get("private_list_type", "blacklist")
|
||||||
|
private_list = features_config.get("private_list", [])
|
||||||
|
|
||||||
|
if private_list_type == "blacklist":
|
||||||
|
# 黑名单模式:如果在黑名单中就过滤
|
||||||
|
if user_id in private_list:
|
||||||
|
logger.debug(f"私聊用户 {user_id} 在黑名单中,消息被过滤")
|
||||||
|
return False
|
||||||
|
else: # whitelist
|
||||||
|
# 白名单模式:如果不在白名单中就过滤
|
||||||
|
if user_id not in private_list:
|
||||||
|
logger.debug(f"私聊用户 {user_id} 不在白名单中,消息被过滤")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 通过所有过滤条件
|
||||||
|
return True
|
||||||
|
|
||||||
async def handle_raw_message(self, raw: Dict[str, Any]):
|
async def handle_raw_message(self, raw: Dict[str, Any]):
|
||||||
"""
|
"""
|
||||||
处理原始消息并转换为 MessageEnvelope
|
处理原始消息并转换为 MessageEnvelope
|
||||||
@@ -47,13 +120,18 @@ class MessageHandler:
|
|||||||
raw: OneBot 原始消息数据
|
raw: OneBot 原始消息数据
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
MessageEnvelope (dict)
|
MessageEnvelope (dict) or None (if message is filtered)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
message_type = raw.get("message_type")
|
message_type = raw.get("message_type")
|
||||||
message_id = str(raw.get("message_id", ""))
|
message_id = str(raw.get("message_id", ""))
|
||||||
message_time = time.time()
|
message_time = time.time()
|
||||||
|
|
||||||
|
# 黑白名单过滤
|
||||||
|
if not self._should_process_message(raw):
|
||||||
|
logger.debug(f"消息被黑白名单过滤丢弃: message_id={message_id}")
|
||||||
|
return None
|
||||||
|
|
||||||
msg_builder = MessageBuilder()
|
msg_builder = MessageBuilder()
|
||||||
|
|
||||||
# 构造用户信息
|
# 构造用户信息
|
||||||
|
|||||||
Reference in New Issue
Block a user