feat: 添加黑白名单过滤系统以控制消息处理

This commit is contained in:
Windpicker-owo
2025-11-27 18:55:16 +08:00
parent 43483b934e
commit ee39ba0fd2
2 changed files with 173 additions and 1 deletions

View File

@@ -54,6 +54,100 @@ NEW_napcat_adapter/
2. **启动插件**: 插件自动在系统启动时加载
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)

View File

@@ -39,6 +39,79 @@ class MessageHandler:
"""设置插件配置"""
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]):
"""
处理原始消息并转换为 MessageEnvelope
@@ -47,13 +120,18 @@ class MessageHandler:
raw: OneBot 原始消息数据
Returns:
MessageEnvelope (dict)
MessageEnvelope (dict) or None (if message is filtered)
"""
message_type = raw.get("message_type")
message_id = str(raw.get("message_id", ""))
message_time = time.time()
# 黑白名单过滤
if not self._should_process_message(raw):
logger.debug(f"消息被黑白名单过滤丢弃: message_id={message_id}")
return None
msg_builder = MessageBuilder()
# 构造用户信息