fix(多适配器支持):

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自动选择正确的适配器获取消息
避免重复:每个群只通过其所属的适配器获取一次消息
完整日志:显示发现的适配器数量和平台信息
This commit is contained in:
SXP-Simon
2025-11-18 14:38:52 +08:00
committed by Helian Nuits
parent db82bd4c4e
commit 4f2f5a83af
3 changed files with 78 additions and 52 deletions
+10 -6
View File
@@ -70,17 +70,21 @@ class QQGroupDailyAnalysis(Star):
async def _delayed_start_scheduler(self):
"""延迟启动调度器,给系统时间初始化"""
try:
# 等待10秒让系统完全初始化
await asyncio.sleep(10)
# 等待30秒让系统完全初始化
await asyncio.sleep(30)
# 初始化bot管理器
if await bot_manager.initialize_from_config():
logger.info("Bot管理器初始化成功,启用自动分析功能")
# 初始化所有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}")
+45 -32
View File
@@ -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)
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
@@ -71,10 +85,12 @@ class BotManager:
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
+20 -11
View File
@@ -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