From 4f2f5a83af3eca3cffccff00b0684b25d28f32d6 Mon Sep 17 00:00:00 2001 From: SXP-Simon Date: Tue, 18 Nov 2025 13:06:51 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E5=A4=9A=E9=80=82=E9=85=8D=E5=99=A8?= =?UTF-8?q?=E6=94=AF=E6=8C=81):?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. BotManager 多实例管理 (src/core/bot_manager.py) 将单实例存储改为字典:self._bot_instances = {} (platform_id -> bot_instance) 添加 platform_id 参数支持:set_bot_instance(bot_instance, platform_id=None) 修改 get_bot_instance(platform_id=None) 支持按平台获取实例 更新 auto_discover_bot_instances() 发现并注册所有适配器 改进状态信息,显示发现的平台数量 2. AutoScheduler 多平台支持 (src/scheduler/auto_scheduler.py) 添加 _get_platform_id_for_group(group_id) 方法,根据群ID查找对应平台 修改消息获取逻辑,使用正确的平台和bot实例 更新 unified_msg_origin 构造,使用正确的平台ID 3. main.py 初始化逻辑更新 修改 _delayed_start_scheduler() 显示发现的适配器数量 日志输出每个平台的详细信息 现在插件可以: 自动发现所有适配器:启动时扫描所有平台,注册每个适配器的bot实例 智能路由:根据群ID自动选择正确的适配器获取消息 避免重复:每个群只通过其所属的适配器获取一次消息 完整日志:显示发现的适配器数量和平台信息 --- main.py | 18 +++++--- src/core/bot_manager.py | 81 +++++++++++++++++++-------------- src/scheduler/auto_scheduler.py | 31 ++++++++----- 3 files changed, 78 insertions(+), 52 deletions(-) diff --git a/main.py b/main.py index 0c95072..0970bdc 100644 --- a/main.py +++ b/main.py @@ -70,17 +70,21 @@ class QQGroupDailyAnalysis(Star): async def _delayed_start_scheduler(self): """延迟启动调度器,给系统时间初始化""" try: - # 等待10秒让系统完全初始化 - await asyncio.sleep(10) - - # 初始化bot管理器 - if await bot_manager.initialize_from_config(): - logger.info("Bot管理器初始化成功,启用自动分析功能") + # 等待30秒让系统完全初始化 + await asyncio.sleep(30) + # 初始化所有bot实例 + discovered = await bot_manager.initialize_from_config() + if discovered: + platform_count = len(discovered) + logger.info(f"Bot管理器初始化成功,发现 {platform_count} 个适配器") + for platform_id, bot_instance in discovered.items(): + logger.info(f" - 平台 {platform_id}: {type(bot_instance).__name__}") + # 启动调度器 await auto_scheduler.start_scheduler() else: - logger.warning("Bot管理器初始化失败,无法启用自动分析功能") + logger.warning("Bot管理器初始化失败,未发现任何适配器") status = bot_manager.get_status_info() logger.info(f"Bot管理器状态: {status}") diff --git a/src/core/bot_manager.py b/src/core/bot_manager.py index f85231e..cab1ce1 100644 --- a/src/core/bot_manager.py +++ b/src/core/bot_manager.py @@ -11,25 +11,27 @@ class BotManager: def __init__(self, config_manager): self.config_manager = config_manager - self._bot_instance = None - self._bot_qq_id = None + self._bot_instances = {} # 改为字典:{platform_id: bot_instance} self._bot_qq_ids = [] # 支持多个QQ号 self._context = None self._is_initialized = False + self._default_platform = "aiocqhttp" # 默认平台 def set_context(self, context): """设置AstrBot上下文""" self._context = context - def set_bot_instance(self, bot_instance): - """设置bot实例""" - if bot_instance: - self._bot_instance = bot_instance + def set_bot_instance(self, bot_instance, platform_id=None): + """设置bot实例,支持指定平台ID""" + if not platform_id: + platform_id = self._get_platform_id_from_instance(bot_instance) + + if bot_instance and platform_id: + self._bot_instances[platform_id] = bot_instance # 自动提取QQ号 - if not self._bot_qq_id: - bot_qq_id = self._extract_bot_qq_id(bot_instance) - if bot_qq_id: - self._bot_qq_id = str(bot_qq_id) + bot_qq_id = self._extract_bot_qq_id(bot_instance) + if bot_qq_id and bot_qq_id not in self._bot_qq_ids: + self._bot_qq_ids.append(str(bot_qq_id)) def set_bot_qq_ids(self, bot_qq_ids): """设置bot QQ号(支持单个QQ号或QQ号列表)""" @@ -41,28 +43,40 @@ class BotManager: self._bot_qq_id = str(bot_qq_ids) self._bot_qq_ids = [str(bot_qq_ids)] - def get_bot_instance(self): - """获取当前bot实例""" - return self._bot_instance + def get_bot_instance(self, platform_id=None): + """获取指定平台的bot实例,如果不指定则返回默认平台的实例""" + if platform_id: + return self._bot_instances.get(platform_id) + + # 返回默认平台的实例 + return self._bot_instances.get(self._default_platform) def has_bot_instance(self) -> bool: """检查是否有可用的bot实例""" - return self._bot_instance is not None + return bool(self._bot_instances) def has_bot_qq_id(self) -> bool: """检查是否有配置的bot QQ号""" - return bool(self._bot_qq_ids) or self._bot_qq_id is not None + return bool(self._bot_qq_ids) def is_ready_for_auto_analysis(self) -> bool: """检查是否准备好进行自动分析""" return self.has_bot_instance() and self.has_bot_qq_id() - async def auto_discover_bot_instance(self): - """自动发现可用的bot实例""" + def _get_platform_id_from_instance(self, bot_instance): + """从bot实例获取平台ID""" + if hasattr(bot_instance, "platform") and bot_instance.platform: + return bot_instance.platform + return self._default_platform + + async def auto_discover_bot_instances(self): + """自动发现所有可用的bot实例""" if not self._context or not hasattr(self._context, "platform_manager"): - return None + return {} platforms = getattr(self._context.platform_manager, "platform_insts", []) + discovered = {} + for platform in platforms: # 获取bot实例 bot_client = None @@ -70,11 +84,13 @@ class BotManager: bot_client = platform.get_client() elif hasattr(platform, "bot"): bot_client = platform.bot - - if bot_client: - self.set_bot_instance(bot_client) - return bot_client - return None + + if bot_client and hasattr(platform, "metadata") and hasattr(platform.metadata, "id"): + platform_id = platform.metadata.id + self.set_bot_instance(bot_client, platform_id) + discovered[platform_id] = bot_client + + return discovered async def initialize_from_config(self): """从配置初始化bot管理器""" @@ -83,19 +99,21 @@ class BotManager: if bot_qq_ids: self.set_bot_qq_ids(bot_qq_ids) - # 自动发现bot实例 - await self.auto_discover_bot_instance() + # 自动发现所有bot实例 + discovered = await self.auto_discover_bot_instances() self._is_initialized = True # 返回是否成功初始化(至少有bot实例) - return self.has_bot_instance() + return bool(discovered) def get_status_info(self) -> Dict[str, Any]: """获取bot管理器状态信息""" return { "has_bot_instance": self.has_bot_instance(), "has_bot_qq_id": self.has_bot_qq_id(), - "bot_qq_id": self._bot_qq_id, + "bot_qq_ids": self._bot_qq_ids, + "platform_count": len(self._bot_instances), + "platforms": list(self._bot_instances.keys()), "ready_for_auto_analysis": self.is_ready_for_auto_analysis(), } @@ -133,14 +151,9 @@ class BotManager: def should_filter_bot_message(self, sender_id: str) -> bool: """判断是否应该过滤bot自己的消息(支持多个QQ号)""" - if not self._bot_qq_ids and not self._bot_qq_id: + if not self._bot_qq_ids: return False sender_id_str = str(sender_id) # 检查是否在QQ号列表中 - if self._bot_qq_ids and sender_id_str in self._bot_qq_ids: - return True - # 向后兼容:检查单个QQ号 - if self._bot_qq_id and sender_id_str == self._bot_qq_id: - return True - return False + return sender_id_str in self._bot_qq_ids diff --git a/src/scheduler/auto_scheduler.py b/src/scheduler/auto_scheduler.py index 83af9c8..c0b6573 100644 --- a/src/scheduler/auto_scheduler.py +++ b/src/scheduler/auto_scheduler.py @@ -41,8 +41,8 @@ class AutoScheduler: elif bot_qq_ids: self.bot_manager.set_bot_qq_ids([bot_qq_ids]) - def _get_platform_id(self): - """获取平台ID""" + def _get_platform_id_for_group(self, group_id): + """根据群ID获取对应的平台ID""" try: if hasattr(self.bot_manager, "_context") and self.bot_manager._context: context = self.bot_manager._context @@ -51,11 +51,14 @@ class AutoScheduler: ): platforms = context.platform_manager.platform_insts for platform in platforms: - if hasattr(platform, "metadata") and hasattr( - platform.metadata, "id" - ): - platform_id = platform.metadata.id - return platform_id + # 检查平台是否有群列表 + if hasattr(platform, "get_groups"): + try: + groups = platform.get_groups() + if any(str(g.get("group_id", "")) == str(group_id) for g in groups): + return platform.metadata.id if hasattr(platform.metadata, "id") else "aiocqhttp" + except: + continue return "aiocqhttp" # 默认值 except Exception: return "aiocqhttp" # 默认值 @@ -216,12 +219,18 @@ class AutoScheduler: logger.info(f"开始为群 {group_id} 执行自动分析(并发任务)") + # 获取该群对应的平台ID和bot实例 + platform_id = self._get_platform_id_for_group(group_id) + bot_instance = self.bot_manager.get_bot_instance(platform_id) + + if not bot_instance: + logger.warning(f"群 {group_id} 未找到对应的bot实例(平台: {platform_id})") + return + # 获取群聊消息 analysis_days = self.config_manager.get_analysis_days() - bot_instance = self.bot_manager.get_bot_instance() - messages = await self.message_handler.fetch_group_messages( - bot_instance, group_id, analysis_days + bot_instance, group_id, analysis_days, platform_id ) if not messages: @@ -239,7 +248,7 @@ class AutoScheduler: logger.info(f"群 {group_id} 获取到 {len(messages)} 条消息,开始分析") # 进行分析 - 构造正确的 unified_msg_origin - platform_id = self._get_platform_id() + platform_id = self._get_platform_id_for_group(group_id) umo = f"{platform_id}:GroupMessage:{group_id}" if platform_id else None analysis_result = await self.analyzer.analyze_messages( messages, group_id, umo