feat(filter_bot_messages): 新增 filter_bot 开关,控制 bot 消息是否纳入分析

Fixes #205

默认排除 bot 自身发言(filter_bot_messages=True),可通过 /分析设置 filter_bot 切换。
修改涉及三层:
1. 配置层:ConfigManager getter/setter + _conf_schema.json 面板选项
2. 适配器层:BotManager 传入配置,OneBotAdapter.fetch_messages 认 switch
3. 分析层:clean_messages 和 analyze_user_activity 的 bot_self_ids 受 switch 控制
This commit is contained in:
SXP-Simon
2026-07-21 15:42:47 +08:00
parent b88082f662
commit 3a03c1f272
6 changed files with 52 additions and 8 deletions
+6
View File
@@ -51,6 +51,12 @@
"type": "string"
}
},
"filter_bot_messages": {
"type": "bool",
"description": "分析时是否过滤机器人自己的消息",
"default": true,
"hint": "默认开启,bot 自身的发言不会出现在分析报告中。关闭后 bot 的发言也会被纳入话题分析、金句提取等。"
},
"enable_user_card": {
"type": "bool",
"description": "使用用户群名片",
+18 -7
View File
@@ -918,6 +918,7 @@ class GroupDailyAnalysis(Star):
- status: 查看当前状态
- reload: 重新加载配置并重启定时任务
- test: 测试自动分析功能
- filter_bot: 切换是否在分析中包含机器人自己的消息
- incremental_debug: 切换增量分析立即报告模式(调试用)
"""
group_id = self._get_group_id_from_event(event)
@@ -968,6 +969,13 @@ class GroupDailyAnalysis(Star):
status_text = "已启用" if new_state else "已禁用"
yield event.plain_result(f"✅ 增量分析立即报告模式: {status_text}")
elif action == "filter_bot":
current = self.config_manager.get_filter_bot_messages()
new_state = not current
self.config_manager.set_filter_bot_messages(new_state)
status_text = "已启用" if new_state else "已禁用"
yield event.plain_result(f"✅ 过滤机器人消息: {status_text}")
else: # status
check_target = getattr(event, "unified_msg_origin", None)
if not check_target:
@@ -1000,18 +1008,21 @@ class GroupDailyAnalysis(Star):
f"活跃时段{active_start}:00-{active_end}:00)"
)
debug_report = self.config_manager.get_incremental_report_immediately()
debug_status = "✅ 开启" if debug_report else "❌ 关闭"
debug_report = self.config_manager.get_incremental_report_immediately()
debug_status = "✅ 开启" if debug_report else "❌ 关闭"
filter_bot = self.config_manager.get_filter_bot_messages()
filter_bot_status = "✅ 开启" if filter_bot else "❌ 关闭"
yield event.plain_result(f"""📊 当前群分析功能状态:
yield event.plain_result(f"""📊 当前群分析功能状态:
• 群分析功能: {status} (模式: {mode})
• 自动分析: {auto_status} ({auto_time})
• 增量分析: {incremental_status_text}
• 调试模式: {debug_status} (增量立即报告)
• 输出格式: {output_format}
• 增量分析: {incremental_status_text}
• 调试模式: {debug_status} (增量立即报告)
• 过滤机器人: {filter_bot_status}
• 输出格式: {output_format}
• 最小消息数: {min_threshold}
💡 可用命令: enable, disable, status, reload, test, incremental_debug
💡 可用命令: enable, disable, status, reload, test, filter_bot, incremental_debug
💡 支持的输出格式: image, text (图片包含活跃度可视化)
💡 其他命令: /设置格式, /增量状态""")
@@ -189,6 +189,13 @@ class AnalysisApplicationService:
cleaner = MessageCleanerService()
bot_self_ids = self.config_manager.get_bot_self_ids()
if not self.config_manager.get_filter_bot_messages():
bot_self_ids = []
logger.debug(
"filter_bot_messages=%s, bot_self_ids=%s",
self.config_manager.get_filter_bot_messages(),
bot_self_ids,
)
# 对于自动任务,强制过滤指令;对于手动任务,也建议过滤以保持报告纯净
unified_messages = cleaner.clean_messages(
@@ -387,6 +394,13 @@ class AnalysisApplicationService:
cleaner = MessageCleanerService()
bot_self_ids = self.config_manager.get_bot_self_ids()
if not self.config_manager.get_filter_bot_messages():
bot_self_ids = []
logger.debug(
"filter_bot_messages=%s, bot_self_ids=%s (incremental)",
self.config_manager.get_filter_bot_messages(),
bot_self_ids,
)
unified_messages = cleaner.clean_messages(
raw_messages, bot_self_ids=bot_self_ids, filter_commands=True
)
@@ -304,6 +304,15 @@ class ConfigManager:
ids = basic.get("bot_qq_ids", [])
return ids
def get_filter_bot_messages(self) -> bool:
"""获取是否过滤机器人自己的消息。"""
return self._get_group("basic").get("filter_bot_messages", True)
def set_filter_bot_messages(self, enabled: bool):
"""设置是否过滤机器人自己的消息。"""
self._ensure_group("basic")["filter_bot_messages"] = enabled
self.config.save_config()
def get_html_output_dir(self) -> str:
"""获取HTML输出目录"""
@@ -62,6 +62,9 @@ class OneBotAdapter(PlatformAdapter):
)
if not self.bot_self_ids and config:
self.bot_self_ids = [str(id) for id in config.get("bot_qq_ids", [])]
self.filter_bot_messages = (
config.get("filter_bot_messages", True) if config else True
)
# LLBot 探测标志
self._is_llbot = False
@@ -226,7 +229,7 @@ class OneBotAdapter(PlatformAdapter):
# 身份过滤(排除机器人自己)
sender_id = str(raw_msg.get("sender", {}).get("user_id", ""))
if sender_id in self.bot_self_ids:
if self.filter_bot_messages and sender_id in self.bot_self_ids:
continue
# 时间范围判定
@@ -73,6 +73,7 @@ class BotManager:
adapter_config = {
"bot_self_ids": self._bot_self_ids.copy(),
"platform_id": str(platform_id),
"filter_bot_messages": self.config_manager.get_filter_bot_messages(),
"plugin_instance": self._plugin_instance,
}
platform_instance = self._platforms.get(str(platform_id))