From c5ca2a8393f12c407d317119ad83025f61b536bc Mon Sep 17 00:00:00 2001 From: SXP-Simon Date: Tue, 18 Nov 2025 14:15:54 +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):=20=E5=A4=84=E7=90=86=20Bot=20=E5=AE=9E?= =?UTF-8?q?=E4=BE=8B=E4=B8=8E=E5=B9=B3=E5=8F=B0=20ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/bot_manager.py | 46 ++++++++++++---- src/scheduler/auto_scheduler.py | 97 ++++++++++++++++++++++++--------- 2 files changed, 106 insertions(+), 37 deletions(-) diff --git a/src/core/bot_manager.py b/src/core/bot_manager.py index 3ee3954..344cff8 100644 --- a/src/core/bot_manager.py +++ b/src/core/bot_manager.py @@ -4,7 +4,7 @@ Bot实例管理模块 """ from typing import Dict, Any - +from astrbot.api import logger class BotManager: """Bot实例管理器 - 统一管理所有bot相关操作""" @@ -15,7 +15,7 @@ class BotManager: self._bot_qq_ids = [] # 支持多个QQ号 self._context = None self._is_initialized = False - self._default_platform = "aiocqhttp" # 默认平台 + self._default_platform = "default" # 默认平台 def set_context(self, context): """设置AstrBot上下文""" @@ -44,12 +44,38 @@ class BotManager: self._bot_qq_ids = [str(bot_qq_ids)] def get_bot_instance(self, platform_id=None): - """获取指定平台的bot实例,如果不指定则返回默认平台的实例""" + """获取指定平台的bot实例,如果不指定则返回第一个可用的实例""" if platform_id: - return self._bot_instances.get(platform_id) + # 如果指定了平台ID,尝试获取 + instance = self._bot_instances.get(platform_id) + if instance: + return instance + + # 如果指定的平台不存在,记录警告并尝试回退 + if self._bot_instances: + first_platform = list(self._bot_instances.keys())[0] + logger.warning( + f"平台 '{platform_id}' 不存在,回退到第一个可用平台 '{first_platform}'" + ) + return self._bot_instances[first_platform] + + # 没有任何平台可用 + logger.error(f"平台 '{platform_id}' 不存在,且没有任何可用的bot实例") + return None - # 返回默认平台的实例 - return self._bot_instances.get(self._default_platform) + # 没有指定平台ID,返回第一个可用的实例 + if self._bot_instances: + first_platform = list(self._bot_instances.keys())[0] + if len(self._bot_instances) > 1: + logger.debug( + f"未指定平台,使用第一个可用平台 '{first_platform}' " + f"(共有 {len(self._bot_instances)} 个平台: {list(self._bot_instances.keys())})" + ) + return self._bot_instances[first_platform] + + # 没有任何平台可用 + logger.error("没有任何可用的bot实例") + return None def has_bot_instance(self) -> bool: """检查是否有可用的bot实例""" @@ -65,7 +91,7 @@ class BotManager: def _get_platform_id_from_instance(self, bot_instance): """从bot实例获取平台ID""" - if hasattr(bot_instance, "platform") and bot_instance.platform: + if hasattr(bot_instance, "platform") and isinstance(bot_instance.platform, str): return bot_instance.platform return self._default_platform @@ -122,10 +148,10 @@ class BotManager: if hasattr(event, "bot") and event.bot: # 从事件中获取平台ID platform_id = None - if hasattr(event, "platform") and event.platform: + if hasattr(event, "platform") and isinstance(event.platform, str): platform_id = event.platform - elif hasattr(event, "metadata") and hasattr(event.metadata, "platform"): - platform_id = event.metadata.platform + elif hasattr(event, "metadata") and hasattr(event.metadata, "id"): + platform_id = event.metadata.id self.set_bot_instance(event.bot, platform_id) # 每次都尝试从bot实例提取QQ号 diff --git a/src/scheduler/auto_scheduler.py b/src/scheduler/auto_scheduler.py index dd382bc..bb848cb 100644 --- a/src/scheduler/auto_scheduler.py +++ b/src/scheduler/auto_scheduler.py @@ -41,27 +41,50 @@ class AutoScheduler: elif bot_qq_ids: self.bot_manager.set_bot_qq_ids([bot_qq_ids]) - def _get_platform_id_for_group(self, group_id): + async 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 - if hasattr(context, "platform_manager") and hasattr( - context.platform_manager, "platform_insts" - ): - platforms = context.platform_manager.platform_insts - for platform in platforms: - # 检查平台是否有群列表 - 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" # 默认值 + # 首先检查已注册的bot实例 + if hasattr(self.bot_manager, "_bot_instances") and self.bot_manager._bot_instances: + # 如果只有一个实例,直接返回 + if len(self.bot_manager._bot_instances) == 1: + platform_id = list(self.bot_manager._bot_instances.keys())[0] + logger.debug(f"只有一个适配器,使用平台: {platform_id}") + return platform_id + + # 如果有多个实例,尝试通过API检查群属于哪个适配器 + logger.info(f"检测到多个适配器,正在验证群 {group_id} 属于哪个平台...") + for platform_id, bot_instance in self.bot_manager._bot_instances.items(): + try: + # 尝试调用 get_group_info 来验证群是否存在 + if hasattr(bot_instance, "call_action"): + result = await bot_instance.call_action( + "get_group_info", group_id=int(group_id) + ) + if result and result.get("group_id"): + logger.info(f"✅ 群 {group_id} 属于平台 {platform_id}") + return platform_id + else: + logger.debug(f"平台 {platform_id} 返回了无效结果: {result}") + else: + logger.debug(f"平台 {platform_id} 的 bot 实例没有 call_action 方法") + except Exception as e: + # 如果调用失败,继续尝试下一个 + logger.debug(f"平台 {platform_id} 无法获取群 {group_id} 信息: {e}") + continue + + # 如果所有适配器都尝试失败,记录警告并返回第一个 + logger.warning(f"⚠️ 无法确定群 {group_id} 属于哪个平台,使用第一个适配器") + first_platform = list(self.bot_manager._bot_instances.keys())[0] + logger.warning(f"使用默认平台: {first_platform}") + return first_platform + + # 回退到默认值 + logger.warning(f"⚠️ 没有注册的bot实例,使用默认平台 'default'") + return "default" + except Exception as e: + logger.error(f"❌ 获取平台ID失败: {e}") + return "default" async def start_scheduler(self): """启动定时任务调度器""" @@ -220,11 +243,16 @@ class AutoScheduler: logger.info(f"开始为群 {group_id} 执行自动分析(并发任务)") # 获取该群对应的平台ID和bot实例 - platform_id = self._get_platform_id_for_group(group_id) + platform_id = await self._get_platform_id_for_group(group_id) + + if not platform_id: + logger.error(f"❌ 群 {group_id} 无法获取平台ID,跳过分析") + return + bot_instance = self.bot_manager.get_bot_instance(platform_id) if not bot_instance: - logger.warning(f"群 {group_id} 未找到对应的bot实例(平台: {platform_id})") + logger.error(f"❌ 群 {group_id} 未找到对应的bot实例(平台: {platform_id})") return # 获取群聊消息 @@ -377,11 +405,16 @@ class AutoScheduler: """发送图片消息到群""" try: # 获取该群对应的平台ID和bot实例 - platform_id = self._get_platform_id_for_group(group_id) + platform_id = await self._get_platform_id_for_group(group_id) + + if not platform_id: + logger.error(f"❌ 群 {group_id} 无法获取平台ID,无法发送图片") + return + bot_instance = self.bot_manager.get_bot_instance(platform_id) if not bot_instance: - logger.error(f"群 {group_id} 发送图片失败:缺少bot实例(平台: {platform_id})") + logger.error(f"❌ 群 {group_id} 发送图片失败:缺少bot实例(平台: {platform_id})") return # 发送图片消息到群 @@ -402,11 +435,16 @@ class AutoScheduler: """发送文本消息到群""" try: # 获取该群对应的平台ID和bot实例 - platform_id = self._get_platform_id_for_group(group_id) + platform_id = await self._get_platform_id_for_group(group_id) + + if not platform_id: + logger.error(f"❌ 群 {group_id} 无法获取平台ID,无法发送文本") + return + bot_instance = self.bot_manager.get_bot_instance(platform_id) if not bot_instance: - logger.error(f"群 {group_id} 发送文本失败:缺少bot实例(平台: {platform_id})") + logger.error(f"❌ 群 {group_id} 发送文本失败:缺少bot实例(平台: {platform_id})") return # 发送文本消息到群 @@ -422,11 +460,16 @@ class AutoScheduler: """发送PDF文件到群""" try: # 获取该群对应的平台ID和bot实例 - platform_id = self._get_platform_id_for_group(group_id) + platform_id = await self._get_platform_id_for_group(group_id) + + if not platform_id: + logger.error(f"❌ 群 {group_id} 无法获取平台ID,无法发送PDF") + return + bot_instance = self.bot_manager.get_bot_instance(platform_id) if not bot_instance: - logger.error(f"群 {group_id} 发送PDF失败:缺少bot实例(平台: {platform_id})") + logger.error(f"❌ 群 {group_id} 发送PDF失败:缺少bot实例(平台: {platform_id})") return # 发送PDF文件到群