mirror of
https://github.com/Nezumi-2711/astrbot_plugin_qq_group_daily_analysis.git
synced 2026-09-22 13:38:43 +00:00
refactor: translate comments to Chinese and fix hardcoded OneBot format
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
"""
|
||||
Analysis Orchestrator - Application layer coordinator
|
||||
分析编排器 - 应用层协调器
|
||||
|
||||
This orchestrator bridges the new DDD architecture with the existing
|
||||
analysis logic, providing a gradual migration path.
|
||||
此编排器连接新的 DDD 架构与现有的分析逻辑,提供渐进式迁移路径。
|
||||
|
||||
Architecture Decision:
|
||||
- The orchestrator uses PlatformAdapter for message fetching (new DDD way)
|
||||
- But delegates to existing analyzers for LLM analysis (preserving working code)
|
||||
- MessageConverter provides bidirectional conversion for compatibility
|
||||
架构决策:
|
||||
- 编排器使用 PlatformAdapter 获取消息(新的 DDD 方式)
|
||||
- 但将 LLM 分析委托给现有分析器(保留已工作的代码)
|
||||
- MessageConverter 提供双向转换以保持兼容性
|
||||
"""
|
||||
|
||||
from typing import Optional, List, Dict, Any
|
||||
@@ -23,7 +22,7 @@ from .message_converter import MessageConverter
|
||||
|
||||
@dataclass
|
||||
class AnalysisConfig:
|
||||
"""Configuration for analysis operation"""
|
||||
"""分析操作配置"""
|
||||
days: int = 1
|
||||
max_messages: int = 1000
|
||||
min_messages_threshold: int = 10
|
||||
@@ -32,17 +31,17 @@ class AnalysisConfig:
|
||||
|
||||
class AnalysisOrchestrator:
|
||||
"""
|
||||
Analysis orchestrator - coordinates the analysis workflow.
|
||||
分析编排器 - 协调分析工作流。
|
||||
|
||||
Responsibilities:
|
||||
1. Use PlatformAdapter to fetch messages (DDD approach)
|
||||
2. Convert messages for compatibility with existing analyzers
|
||||
3. Coordinate analysis flow
|
||||
4. Provide platform capability checks
|
||||
职责:
|
||||
1. 使用 PlatformAdapter 获取消息(DDD 方式)
|
||||
2. 转换消息以兼容现有分析器
|
||||
3. 协调分析流程
|
||||
4. 提供平台能力检查
|
||||
|
||||
This class serves as the bridge between:
|
||||
- New DDD infrastructure (PlatformAdapter, UnifiedMessage)
|
||||
- Existing analysis logic (MessageHandler, LLMAnalyzer, etc.)
|
||||
此类作为以下组件之间的桥梁:
|
||||
- 新的 DDD 基础设施(PlatformAdapter, UnifiedMessage)
|
||||
- 现有分析逻辑(MessageHandler, LLMAnalyzer 等)
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@@ -51,11 +50,11 @@ class AnalysisOrchestrator:
|
||||
config: AnalysisConfig = None,
|
||||
):
|
||||
"""
|
||||
Initialize the orchestrator.
|
||||
初始化编排器。
|
||||
|
||||
Args:
|
||||
adapter: Platform adapter for message operations
|
||||
config: Analysis configuration
|
||||
参数:
|
||||
adapter: 用于消息操作的平台适配器
|
||||
config: 分析配置
|
||||
"""
|
||||
self.adapter = adapter
|
||||
self.config = config or AnalysisConfig()
|
||||
@@ -69,34 +68,34 @@ class AnalysisOrchestrator:
|
||||
analysis_config: AnalysisConfig = None,
|
||||
) -> Optional["AnalysisOrchestrator"]:
|
||||
"""
|
||||
Factory method to create orchestrator for a specific platform.
|
||||
工厂方法 - 为特定平台创建编排器。
|
||||
|
||||
Args:
|
||||
platform_name: Platform name (e.g., "aiocqhttp", "telegram")
|
||||
bot_instance: Bot instance from AstrBot
|
||||
config: Platform-specific config
|
||||
analysis_config: Analysis configuration
|
||||
参数:
|
||||
platform_name: 平台名称(如 "aiocqhttp", "telegram")
|
||||
bot_instance: 来自 AstrBot 的 bot 实例
|
||||
config: 平台特定配置
|
||||
analysis_config: 分析配置
|
||||
|
||||
Returns:
|
||||
AnalysisOrchestrator or None if platform not supported
|
||||
返回:
|
||||
AnalysisOrchestrator 或 None(如果平台不支持)
|
||||
"""
|
||||
adapter = PlatformAdapterFactory.create(platform_name, bot_instance, config)
|
||||
if adapter is None:
|
||||
logger.warning(f"Platform '{platform_name}' not supported for analysis")
|
||||
logger.warning(f"平台 '{platform_name}' 不支持分析功能")
|
||||
return None
|
||||
|
||||
return cls(adapter, analysis_config)
|
||||
|
||||
def get_capabilities(self) -> PlatformCapabilities:
|
||||
"""Get platform capabilities."""
|
||||
"""获取平台能力。"""
|
||||
return self.adapter.get_capabilities()
|
||||
|
||||
def can_analyze(self) -> bool:
|
||||
"""Check if the platform supports analysis."""
|
||||
"""检查平台是否支持分析。"""
|
||||
return self.adapter.get_capabilities().can_analyze()
|
||||
|
||||
def can_send_report(self, format: str = "image") -> bool:
|
||||
"""Check if the platform can send reports in the specified format."""
|
||||
"""检查平台是否能发送指定格式的报告。"""
|
||||
return self.adapter.get_capabilities().can_send_report(format)
|
||||
|
||||
async def fetch_messages(
|
||||
@@ -106,28 +105,28 @@ class AnalysisOrchestrator:
|
||||
max_count: int = None,
|
||||
) -> List[UnifiedMessage]:
|
||||
"""
|
||||
Fetch messages using the platform adapter.
|
||||
使用平台适配器获取消息。
|
||||
|
||||
Args:
|
||||
group_id: Group ID to fetch messages from
|
||||
days: Number of days (defaults to config)
|
||||
max_count: Maximum message count (defaults to config)
|
||||
参数:
|
||||
group_id: 要获取消息的群组 ID
|
||||
days: 天数(默认使用配置值)
|
||||
max_count: 最大消息数量(默认使用配置值)
|
||||
|
||||
Returns:
|
||||
List of UnifiedMessage
|
||||
返回:
|
||||
UnifiedMessage 列表
|
||||
"""
|
||||
days = days or self.config.days
|
||||
max_count = max_count or self.config.max_messages
|
||||
|
||||
# Apply platform capability limits
|
||||
# 应用平台能力限制
|
||||
caps = self.adapter.get_capabilities()
|
||||
effective_days = caps.get_effective_days(days)
|
||||
effective_count = caps.get_effective_count(max_count)
|
||||
|
||||
if effective_days < days:
|
||||
logger.info(
|
||||
f"Platform limits: requested {days} days, "
|
||||
f"using {effective_days} days"
|
||||
f"平台限制:请求 {days} 天,"
|
||||
f"实际使用 {effective_days} 天"
|
||||
)
|
||||
|
||||
return await self.adapter.fetch_messages(
|
||||
@@ -143,24 +142,25 @@ class AnalysisOrchestrator:
|
||||
max_count: int = None,
|
||||
) -> List[dict]:
|
||||
"""
|
||||
Fetch messages and convert to raw dict format.
|
||||
获取消息并转换为原始字典格式。
|
||||
|
||||
This provides backward compatibility with existing analyzers
|
||||
that expect raw dict messages.
|
||||
此方法提供与现有分析器的向后兼容性,
|
||||
这些分析器期望原始字典格式的消息。
|
||||
|
||||
Args:
|
||||
group_id: Group ID to fetch messages from
|
||||
days: Number of days
|
||||
max_count: Maximum message count
|
||||
参数:
|
||||
group_id: 要获取消息的群组 ID
|
||||
days: 天数
|
||||
max_count: 最大消息数量
|
||||
|
||||
Returns:
|
||||
List of raw message dicts (OneBot format)
|
||||
返回:
|
||||
原始消息字典列表(通用格式,由适配器决定具体格式)
|
||||
"""
|
||||
unified_messages = await self.fetch_messages(group_id, days, max_count)
|
||||
return MessageConverter.batch_to_onebot(unified_messages)
|
||||
# 使用适配器的原生格式转换,而非硬编码 OneBot 格式
|
||||
return self.adapter.convert_to_raw_format(unified_messages)
|
||||
|
||||
async def get_group_info(self, group_id: str):
|
||||
"""Get group information."""
|
||||
"""获取群组信息。"""
|
||||
return await self.adapter.get_group_info(group_id)
|
||||
|
||||
async def get_member_avatars(
|
||||
@@ -169,19 +169,19 @@ class AnalysisOrchestrator:
|
||||
size: int = 100,
|
||||
) -> Dict[str, Optional[str]]:
|
||||
"""
|
||||
Batch get user avatar URLs.
|
||||
批量获取用户头像 URL。
|
||||
|
||||
Args:
|
||||
user_ids: List of user IDs
|
||||
size: Avatar size
|
||||
参数:
|
||||
user_ids: 用户 ID 列表
|
||||
size: 头像尺寸
|
||||
|
||||
Returns:
|
||||
Dict mapping user_id to avatar URL (or None)
|
||||
返回:
|
||||
用户 ID 到头像 URL 的映射字典(URL 可能为 None)
|
||||
"""
|
||||
return await self.adapter.batch_get_avatar_urls(user_ids, size)
|
||||
|
||||
async def send_text(self, group_id: str, text: str) -> bool:
|
||||
"""Send text message to group."""
|
||||
"""发送文本消息到群组。"""
|
||||
return await self.adapter.send_text(group_id, text)
|
||||
|
||||
async def send_image(
|
||||
@@ -190,7 +190,7 @@ class AnalysisOrchestrator:
|
||||
image_path: str,
|
||||
caption: str = "",
|
||||
) -> bool:
|
||||
"""Send image to group."""
|
||||
"""发送图片到群组。"""
|
||||
return await self.adapter.send_image(group_id, image_path, caption)
|
||||
|
||||
async def send_file(
|
||||
@@ -199,29 +199,29 @@ class AnalysisOrchestrator:
|
||||
file_path: str,
|
||||
filename: str = None,
|
||||
) -> bool:
|
||||
"""Send file to group."""
|
||||
"""发送文件到群组。"""
|
||||
return await self.adapter.send_file(group_id, file_path, filename)
|
||||
|
||||
def validate_message_count(self, messages: List[UnifiedMessage]) -> bool:
|
||||
"""
|
||||
Check if message count meets minimum threshold.
|
||||
检查消息数量是否达到最小阈值。
|
||||
|
||||
Args:
|
||||
messages: List of messages
|
||||
参数:
|
||||
messages: 消息列表
|
||||
|
||||
Returns:
|
||||
True if count is sufficient
|
||||
返回:
|
||||
如果数量足够返回 True
|
||||
"""
|
||||
return len(messages) >= self.config.min_messages_threshold
|
||||
|
||||
def get_analysis_text(self, messages: List[UnifiedMessage]) -> str:
|
||||
"""
|
||||
Convert messages to analysis text format for LLM.
|
||||
将消息转换为 LLM 分析文本格式。
|
||||
|
||||
Args:
|
||||
messages: List of UnifiedMessage
|
||||
参数:
|
||||
messages: UnifiedMessage 列表
|
||||
|
||||
Returns:
|
||||
Formatted text for LLM analysis
|
||||
返回:
|
||||
格式化的 LLM 分析文本
|
||||
"""
|
||||
return MessageConverter.unified_to_analysis_text(messages)
|
||||
|
||||
+45
-33
@@ -2,7 +2,7 @@
|
||||
Bot实例管理模块
|
||||
统一管理bot实例的获取、设置和使用
|
||||
|
||||
Refactored to integrate with DDD PlatformAdapter architecture.
|
||||
已重构以集成 DDD PlatformAdapter 架构,支持多平台扩展。
|
||||
"""
|
||||
|
||||
from typing import Any, Optional
|
||||
@@ -16,14 +16,14 @@ class BotManager:
|
||||
"""
|
||||
Bot实例管理器 - 统一管理所有bot相关操作
|
||||
|
||||
Integrates with DDD architecture by creating PlatformAdapter instances
|
||||
alongside raw bot instances for cross-platform support.
|
||||
与 DDD 架构集成,为每个 bot 实例创建对应的 PlatformAdapter,
|
||||
实现跨平台支持。
|
||||
"""
|
||||
|
||||
def __init__(self, config_manager):
|
||||
self.config_manager = config_manager
|
||||
self._bot_instances = {} # {platform_id: bot_instance}
|
||||
self._adapters = {} # {platform_id: PlatformAdapter} - DDD integration
|
||||
self._adapters = {} # {platform_id: PlatformAdapter} - DDD 集成
|
||||
self._platforms = {} # 存储平台对象以访问配置
|
||||
self._bot_qq_ids = [] # 支持多个QQ号
|
||||
self._context = None
|
||||
@@ -38,7 +38,7 @@ class BotManager:
|
||||
"""
|
||||
设置bot实例,支持指定平台ID
|
||||
|
||||
Also creates a PlatformAdapter if the platform is supported.
|
||||
同时会创建对应的 PlatformAdapter(如果平台被支持)。
|
||||
"""
|
||||
if not platform_id:
|
||||
platform_id = self._get_platform_id_from_instance(bot_instance)
|
||||
@@ -46,7 +46,7 @@ class BotManager:
|
||||
if bot_instance and platform_id:
|
||||
self._bot_instances[platform_id] = bot_instance
|
||||
|
||||
# Create PlatformAdapter for DDD integration
|
||||
# 为 DDD 集成创建 PlatformAdapter
|
||||
if platform_name is None:
|
||||
platform_name = self._detect_platform_name(bot_instance)
|
||||
|
||||
@@ -59,7 +59,7 @@ class BotManager:
|
||||
)
|
||||
if adapter:
|
||||
self._adapters[platform_id] = adapter
|
||||
logger.debug(f"Created PlatformAdapter for {platform_id} ({platform_name})")
|
||||
logger.debug(f"已为 {platform_id} ({platform_name}) 创建 PlatformAdapter")
|
||||
|
||||
# 自动提取QQ号
|
||||
bot_qq_id = self._extract_bot_qq_id(bot_instance)
|
||||
@@ -123,38 +123,50 @@ class BotManager:
|
||||
|
||||
def _detect_platform_name(self, bot_instance) -> Optional[str]:
|
||||
"""
|
||||
Detect platform name from bot instance for adapter creation.
|
||||
从 bot 实例检测平台名称,用于创建适配器。
|
||||
|
||||
Returns platform name like 'aiocqhttp', 'telegram', etc.
|
||||
返回平台名称如 'aiocqhttp', 'discord' 等。
|
||||
|
||||
检测优先级:
|
||||
1. bot 实例的 platform 属性
|
||||
2. 已知的 API 特征检测
|
||||
3. 类名模式匹配(作为后备方案)
|
||||
"""
|
||||
# Check for aiocqhttp/OneBot
|
||||
if hasattr(bot_instance, "call_action"):
|
||||
return "aiocqhttp"
|
||||
|
||||
# Check for platform attribute
|
||||
# 优先使用 platform 属性
|
||||
if hasattr(bot_instance, "platform"):
|
||||
platform = bot_instance.platform
|
||||
if isinstance(platform, str):
|
||||
return platform
|
||||
|
||||
# Check class name patterns
|
||||
class_name = type(bot_instance).__name__.lower()
|
||||
if "cqhttp" in class_name or "onebot" in class_name:
|
||||
# 检查已知的 API 特征(平台无关的方式)
|
||||
# OneBot/aiocqhttp 特征: 有 call_action 方法
|
||||
if hasattr(bot_instance, "call_action"):
|
||||
return "aiocqhttp"
|
||||
if "telegram" in class_name:
|
||||
return "telegram"
|
||||
if "discord" in class_name:
|
||||
return "discord"
|
||||
|
||||
# 使用工厂的已注册平台列表进行类名匹配
|
||||
class_name = type(bot_instance).__name__.lower()
|
||||
for platform_name in PlatformAdapterFactory.get_supported_platforms():
|
||||
if platform_name in class_name:
|
||||
return platform_name
|
||||
|
||||
# 通用类名模式匹配(用于尚未注册的平台)
|
||||
known_patterns = {
|
||||
"cqhttp": "aiocqhttp",
|
||||
"onebot": "aiocqhttp",
|
||||
}
|
||||
for pattern, platform in known_patterns.items():
|
||||
if pattern in class_name:
|
||||
return platform
|
||||
|
||||
return None
|
||||
|
||||
# ==================== DDD Integration Methods ====================
|
||||
# ==================== DDD 集成方法 ====================
|
||||
|
||||
def get_adapter(self, platform_id: str = None) -> Optional[PlatformAdapter]:
|
||||
"""
|
||||
Get PlatformAdapter for the specified platform.
|
||||
获取指定平台的 PlatformAdapter。
|
||||
|
||||
This is the primary method for DDD-based operations.
|
||||
这是 DDD 架构操作的主要方法。
|
||||
"""
|
||||
if platform_id:
|
||||
return self._adapters.get(platform_id)
|
||||
@@ -164,25 +176,25 @@ class BotManager:
|
||||
return list(self._adapters.values())[0]
|
||||
|
||||
logger.error(
|
||||
f"Multiple adapters exist {list(self._adapters.keys())} "
|
||||
"but no platform_id specified."
|
||||
f"存在多个适配器 {list(self._adapters.keys())},"
|
||||
"但未指定 platform_id。"
|
||||
)
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
def get_all_adapters(self) -> dict:
|
||||
"""Get all PlatformAdapter instances {platform_id: adapter}"""
|
||||
"""获取所有 PlatformAdapter 实例 {platform_id: adapter}"""
|
||||
return self._adapters.copy()
|
||||
|
||||
def has_adapter(self, platform_id: str = None) -> bool:
|
||||
"""Check if adapter exists for the platform"""
|
||||
"""检查指定平台是否有适配器"""
|
||||
if platform_id:
|
||||
return platform_id in self._adapters
|
||||
return bool(self._adapters)
|
||||
|
||||
def can_analyze(self, platform_id: str = None) -> bool:
|
||||
"""Check if the platform supports analysis using DDD capabilities"""
|
||||
"""使用 DDD 能力检查平台是否支持分析"""
|
||||
adapter = self.get_adapter(platform_id)
|
||||
if adapter:
|
||||
return adapter.get_capabilities().can_analyze()
|
||||
@@ -192,7 +204,7 @@ class BotManager:
|
||||
"""
|
||||
自动发现所有可用的bot实例
|
||||
|
||||
Also creates PlatformAdapter for each discovered bot.
|
||||
同时为每个发现的 bot 创建对应的 PlatformAdapter。
|
||||
"""
|
||||
if not self._context or not hasattr(self._context, "platform_manager"):
|
||||
return {}
|
||||
@@ -216,7 +228,7 @@ class BotManager:
|
||||
):
|
||||
platform_id = platform.metadata.id
|
||||
|
||||
# Detect platform name from metadata
|
||||
# 从元数据检测平台名称
|
||||
platform_name = None
|
||||
if hasattr(platform.metadata, "name"):
|
||||
platform_name = platform.metadata.name
|
||||
@@ -227,10 +239,10 @@ class BotManager:
|
||||
self._platforms[platform_id] = platform
|
||||
discovered[platform_id] = bot_client
|
||||
|
||||
# Log adapter creation results
|
||||
# 记录适配器创建结果
|
||||
if self._adapters:
|
||||
logger.info(
|
||||
f"Created {len(self._adapters)} PlatformAdapter(s): "
|
||||
f"已创建 {len(self._adapters)} 个 PlatformAdapter: "
|
||||
f"{list(self._adapters.keys())}"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user