Merge branch 'MoFox-Studio:dev' into dev
This commit is contained in:
10
bot.py
10
bot.py
@@ -249,7 +249,7 @@ class ShutdownManager:
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"麦麦关闭失败: {e}")
|
||||
logger.error(f"麦麦关闭失败: {e}", exc_info=True)
|
||||
return False
|
||||
|
||||
|
||||
@@ -602,12 +602,11 @@ class MaiBotMain:
|
||||
async def wait_for_user_input():
|
||||
"""等待用户输入(异步方式)"""
|
||||
try:
|
||||
# 在非生产环境下,使用异步方式等待输入
|
||||
if os.getenv("ENVIRONMENT") != "production":
|
||||
logger.info("程序执行完成,按 Ctrl+C 退出...")
|
||||
# 使用 Event 替代 sleep 循环,避免阻塞事件循环
|
||||
shutdown_event = asyncio.Event()
|
||||
await shutdown_event.wait()
|
||||
# 使用非阻塞循环
|
||||
while True:
|
||||
await asyncio.sleep(0.1)
|
||||
except KeyboardInterrupt:
|
||||
logger.info("用户中断程序")
|
||||
return True
|
||||
@@ -616,6 +615,7 @@ async def wait_for_user_input():
|
||||
return False
|
||||
|
||||
|
||||
|
||||
async def main_async():
|
||||
"""主异步函数"""
|
||||
exit_code = 0
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
# 构造用户信息
|
||||
|
||||
Reference in New Issue
Block a user