Refactor: Translate comments and logs to Chinese in application layer

This commit is contained in:
SXP-Simon
2026-02-08 21:53:49 +08:00
parent b9a33926be
commit ec29304069
3 changed files with 132 additions and 132 deletions
+20 -20
View File
@@ -1,8 +1,8 @@
""" """
Message Converter - Bridges raw platform messages to UnifiedMessage 消息转换器 - 连接原始平台消息和 UnifiedMessage
This module provides backward compatibility by converting between 该模块通过在原始平台消息格式和新的 UnifiedMessage 格式之间进行转换,
raw platform message formats and the new UnifiedMessage format. 提供向后兼容性。
""" """
from typing import List, Dict, Any, Optional from typing import List, Dict, Any, Optional
@@ -17,29 +17,29 @@ from ..domain.value_objects.unified_message import (
class MessageConverter: class MessageConverter:
""" """
Converts between raw platform messages and UnifiedMessage format. 在原始平台消息和 UnifiedMessage 格式之间进行转换。
This provides a migration path: existing code can continue using 这提供了一个迁移路径:现有代码可以继续使用原始字典,
raw dicts while new code uses UnifiedMessage. 而新代码使用 UnifiedMessage
""" """
@staticmethod @staticmethod
def from_onebot_message(raw_msg: dict, group_id: str) -> Optional[UnifiedMessage]: def from_onebot_message(raw_msg: dict, group_id: str) -> Optional[UnifiedMessage]:
""" """
Convert OneBot v11 raw message to UnifiedMessage. OneBot v11 原始消息转换为 UnifiedMessage
Args: Args:
raw_msg: Raw message dict from OneBot API raw_msg: 来自 OneBot API 的原始消息字典
group_id: Group ID group_id: 群组 ID
Returns: Returns:
UnifiedMessage or None if conversion fails UnifiedMessage None(如果转换失败)
""" """
try: try:
sender = raw_msg.get("sender", {}) sender = raw_msg.get("sender", {})
message_chain = raw_msg.get("message", []) message_chain = raw_msg.get("message", [])
# Handle string message format # 处理字符串消息格式
if isinstance(message_chain, str): if isinstance(message_chain, str):
message_chain = [{"type": "text", "data": {"text": message_chain}}] message_chain = [{"type": "text", "data": {"text": message_chain}}]
@@ -104,7 +104,7 @@ class MessageConverter:
raw_data=seg raw_data=seg
)) ))
# Extract reply_to from contents # 从内容中提取 reply_to
reply_to = None reply_to = None
for c in contents: for c in contents:
if c.type == MessageContentType.REPLY and c.raw_data: if c.type == MessageContentType.REPLY and c.raw_data:
@@ -130,9 +130,9 @@ class MessageConverter:
@staticmethod @staticmethod
def to_onebot_message(unified: UnifiedMessage) -> dict: def to_onebot_message(unified: UnifiedMessage) -> dict:
""" """
Convert UnifiedMessage back to OneBot v11 raw format. UnifiedMessage 转换回 OneBot v11 原始格式。
For backward compatibility with existing code that expects raw dicts. 用于与期望原始字典的现有代码向后兼容。
""" """
message_chain = [] message_chain = []
@@ -154,7 +154,7 @@ class MessageConverter:
elif content.type == MessageContentType.VIDEO: elif content.type == MessageContentType.VIDEO:
message_chain.append({"type": "video", "data": {"url": content.url}}) message_chain.append({"type": "video", "data": {"url": content.url}})
# Ensure sender fields are populated, even if missing in original # 确保填充发送者字段,即使原始数据中缺失
sender_data = { sender_data = {
"user_id": unified.sender_id, "user_id": unified.sender_id,
"nickname": unified.sender_name, "nickname": unified.sender_name,
@@ -167,14 +167,14 @@ class MessageConverter:
"group_id": unified.group_id, "group_id": unified.group_id,
"message": message_chain, "message": message_chain,
"time": unified.timestamp, "time": unified.timestamp,
# Add these helper fields for old analyzers that might expect them directly # 添加这些辅助字段,以便旧分析器可以直接使用
"raw_message": unified.text_content, "raw_message": unified.text_content,
"user_id": unified.sender_id, "user_id": unified.sender_id,
} }
@staticmethod @staticmethod
def batch_from_onebot(raw_messages: List[dict], group_id: str) -> List[UnifiedMessage]: def batch_from_onebot(raw_messages: List[dict], group_id: str) -> List[UnifiedMessage]:
"""Convert a batch of OneBot messages to UnifiedMessage list.""" """将一批 OneBot 消息转换为 UnifiedMessage 列表。"""
result = [] result = []
for raw_msg in raw_messages: for raw_msg in raw_messages:
unified = MessageConverter.from_onebot_message(raw_msg, group_id) unified = MessageConverter.from_onebot_message(raw_msg, group_id)
@@ -184,15 +184,15 @@ class MessageConverter:
@staticmethod @staticmethod
def batch_to_onebot(unified_messages: List[UnifiedMessage]) -> List[dict]: def batch_to_onebot(unified_messages: List[UnifiedMessage]) -> List[dict]:
"""Convert a batch of UnifiedMessage to OneBot raw format.""" """将一批 UnifiedMessage 转换为 OneBot 原始格式。"""
return [MessageConverter.to_onebot_message(msg) for msg in unified_messages] return [MessageConverter.to_onebot_message(msg) for msg in unified_messages]
@staticmethod @staticmethod
def unified_to_analysis_text(messages: List[UnifiedMessage]) -> str: def unified_to_analysis_text(messages: List[UnifiedMessage]) -> str:
""" """
Convert UnifiedMessage list to analysis text format for LLM. UnifiedMessage 列表转换为 LLM 分析文本格式。
This is the format expected by the existing LLM analyzers. 这是现有 LLM 分析器期望的格式。
""" """
lines = [] lines = []
for msg in messages: for msg in messages:
+61 -61
View File
@@ -1,7 +1,7 @@
""" """
Reporting Service - Application service for generating and sending reports 报告服务 - 生成和发送报告的应用服务
This service coordinates report generation and delivery to groups. 该服务协调报告的生成并将其发送到群组。
""" """
from datetime import datetime from datetime import datetime
@@ -20,10 +20,10 @@ from ..infrastructure.persistence import HistoryRepository
class ReportingService: class ReportingService:
""" """
Application service for generating and managing reports. 生成和管理报告的应用服务。
This service coordinates between domain services and infrastructure 该服务协调领域服务和基础设施
to produce and deliver analysis reports. 以生成和发送分析报告。
""" """
def __init__( def __init__(
@@ -32,11 +32,11 @@ class ReportingService:
history_repository: HistoryRepository, history_repository: HistoryRepository,
): ):
""" """
Initialize the reporting service. 初始化报告服务。
Args: Args:
config: Configuration manager config: 配置管理器
history_repository: Repository for storing reports history_repository: 用于存储报告的仓库
""" """
self.config = config self.config = config
self.history = history_repository self.history = history_repository
@@ -52,19 +52,19 @@ class ReportingService:
date_str: Optional[str] = None, date_str: Optional[str] = None,
) -> str: ) -> str:
""" """
Generate a complete analysis report. 生成完整的分析报告。
Args: Args:
group_id: Group identifier group_id: 群组标识符
group_name: Group display name group_name: 群组显示名称
statistics: Group statistics statistics: 群组统计
topics: List of discussion topics topics: 讨论话题列表
user_titles: List of user titles user_titles: 用户称号列表
golden_quotes: List of golden quotes golden_quotes: 金句列表
date_str: Report date (defaults to today) date_str: 报告日期(默认为今天)
Returns: Returns:
Formatted report string 格式化的报告字符串
""" """
date_str = date_str or datetime.now().strftime("%Y-%m-%d") date_str = date_str or datetime.now().strftime("%Y-%m-%d")
@@ -73,7 +73,7 @@ class ReportingService:
date_str=date_str, date_str=date_str,
) )
# Generate report based on configuration # 根据配置生成报告
report = generator.generate_full_report( report = generator.generate_full_report(
statistics=statistics, statistics=statistics,
topics=topics if self.config.get_include_topics() else [], topics=topics if self.config.get_include_topics() else [],
@@ -94,17 +94,17 @@ class ReportingService:
date_str: Optional[str] = None, date_str: Optional[str] = None,
) -> str: ) -> str:
""" """
Generate a brief summary report. 生成简要摘要报告。
Args: Args:
group_id: Group identifier group_id: 群组标识符
statistics: Group statistics statistics: 群组统计
top_topic: Most significant topic top_topic: 最重要的话题
top_quote: Best golden quote top_quote: 最佳金句
date_str: Report date date_str: 报告日期
Returns: Returns:
Brief summary string 简要摘要字符串
""" """
date_str = date_str or datetime.now().strftime("%Y-%m-%d") date_str = date_str or datetime.now().strftime("%Y-%m-%d")
@@ -122,15 +122,15 @@ class ReportingService:
date_str: Optional[str] = None, date_str: Optional[str] = None,
) -> bool: ) -> bool:
""" """
Save a report to history. 保存报告到历史记录。
Args: Args:
group_id: Group identifier group_id: 群组标识符
report_data: Report data dictionary report_data: 报告数据字典
date_str: Report date date_str: 报告日期
Returns: Returns:
True if saved successfully 如果保存成功则返回 True
""" """
date_str = date_str or datetime.now().strftime("%Y-%m-%d") date_str = date_str or datetime.now().strftime("%Y-%m-%d")
@@ -146,14 +146,14 @@ class ReportingService:
date_str: str, date_str: str,
) -> Optional[Dict[str, Any]]: ) -> Optional[Dict[str, Any]]:
""" """
Get a saved report. 获取已保存的报告。
Args: Args:
group_id: Group identifier group_id: 群组标识符
date_str: Report date date_str: 报告日期
Returns: Returns:
Report data or None 报告数据或 None
""" """
return self.history.get_analysis_result(group_id, date_str) return self.history.get_analysis_result(group_id, date_str)
@@ -163,26 +163,26 @@ class ReportingService:
limit: int = 7, limit: int = 7,
) -> List[Dict[str, Any]]: ) -> List[Dict[str, Any]]:
""" """
Get recent reports for a group. 获取群组的最近报告。
Args: Args:
group_id: Group identifier group_id: 群组标识符
limit: Maximum number of reports limit: 最大报告数
Returns: Returns:
List of report data dictionaries 报告数据字典列表
""" """
return self.history.get_recent_results(group_id, limit) return self.history.get_recent_results(group_id, limit)
def has_report_for_today(self, group_id: str) -> bool: def has_report_for_today(self, group_id: str) -> bool:
""" """
Check if a report exists for today. 检查今天是否已存在报告。
Args: Args:
group_id: Group identifier group_id: 群组标识符
Returns: Returns:
True if report exists 如果报告存在则返回 True
""" """
today = datetime.now().strftime("%Y-%m-%d") today = datetime.now().strftime("%Y-%m-%d")
return self.history.has_analysis_for_date(group_id, today) return self.history.has_analysis_for_date(group_id, today)
@@ -194,37 +194,37 @@ class ReportingService:
format_type: Optional[str] = None, format_type: Optional[str] = None,
) -> str: ) -> str:
""" """
Format a report for a specific platform. 为特定平台格式化报告。
Args: Args:
report: Raw report text report: 原始报告文本
platform: Target platform platform: 目标平台
format_type: Override format type format_type: 覆盖格式类型
Returns: Returns:
Platform-formatted report 平台格式化的报告
""" """
format_type = format_type or self.config.get_report_format() format_type = format_type or self.config.get_report_format()
# For now, return as-is. Can be extended for platform-specific formatting # 目前保持原样返回。可以扩展为平台特定的格式化
if format_type == "markdown": if format_type == "markdown":
return report return report
elif format_type == "text": elif format_type == "text":
# Strip markdown formatting # 去除 markdown 格式
return self._strip_markdown(report) return self._strip_markdown(report)
else: else:
return report return report
def _strip_markdown(self, text: str) -> str: def _strip_markdown(self, text: str) -> str:
"""Strip markdown formatting from text.""" """从文本中去除 markdown 格式。"""
# Simple markdown stripping # 简单的 markdown 去除
import re import re
# Remove bold # 去除加粗
text = re.sub(r"\*\*(.*?)\*\*", r"\1", text) text = re.sub(r"\*\*(.*?)\*\*", r"\1", text)
# Remove italic # 去除斜体
text = re.sub(r"\*(.*?)\*", r"\1", text) text = re.sub(r"\*(.*?)\*", r"\1", text)
# Remove headers # 去除标题
text = re.sub(r"^#+\s*", "", text, flags=re.MULTILINE) text = re.sub(r"^#+\s*", "", text, flags=re.MULTILINE)
return text return text
@@ -239,18 +239,18 @@ class ReportingService:
golden_quotes: List[GoldenQuote], golden_quotes: List[GoldenQuote],
) -> Dict[str, Any]: ) -> Dict[str, Any]:
""" """
Create a report data dictionary for storage. 创建用于存储的报告数据字典。
Args: Args:
group_id: Group identifier group_id: 群组标识符
group_name: Group display name group_name: 群组显示名称
statistics: Group statistics statistics: 群组统计
topics: List of topics topics: 话题列表
user_titles: List of user titles user_titles: 用户称号列表
golden_quotes: List of golden quotes golden_quotes: 金句列表
Returns: Returns:
Report data dictionary 报告数据字典
""" """
return { return {
"group_id": group_id, "group_id": group_id,
+51 -51
View File
@@ -1,8 +1,8 @@
""" """
Scheduling Service - Application service for scheduled analysis 调度服务 - 计划分析的应用服务
This service manages scheduled analysis tasks and coordinates 该服务管理计划的分析任务并与
with the analysis orchestrator. 分析编排器协调。
""" """
import asyncio import asyncio
@@ -16,13 +16,13 @@ from ..shared.constants import TASK_STATE_PENDING, TASK_STATE_RUNNING, TASK_STAT
class ScheduledTask: class ScheduledTask:
"""Represents a scheduled analysis task.""" """表示一个计划的分析任务。"""
def __init__( def __init__(
self, self,
task_id: str, task_id: str,
group_id: str, group_id: str,
scheduled_time: str, # HH:MM format scheduled_time: str, # HH:MM 格式
callback: Callable, callback: Callable,
enabled: bool = True, enabled: bool = True,
): ):
@@ -36,7 +36,7 @@ class ScheduledTask:
self._calculate_next_run() self._calculate_next_run()
def _calculate_next_run(self) -> None: def _calculate_next_run(self) -> None:
"""Calculate the next run time.""" """计算下一次运行时间。"""
if not self.enabled: if not self.enabled:
self.next_run = None self.next_run = None
return return
@@ -46,50 +46,50 @@ class ScheduledTask:
now = datetime.now() now = datetime.now()
next_run = now.replace(hour=hours, minute=minutes, second=0, microsecond=0) next_run = now.replace(hour=hours, minute=minutes, second=0, microsecond=0)
# If the time has passed today, schedule for tomorrow # 如果今天的时间已过,计划明天运行
if next_run <= now: if next_run <= now:
next_run += timedelta(days=1) next_run += timedelta(days=1)
self.next_run = next_run self.next_run = next_run
except ValueError: except ValueError:
logger.error(f"Invalid scheduled time format: {self.scheduled_time}") logger.error(f"无效的计划时间格式: {self.scheduled_time}")
self.next_run = None self.next_run = None
def should_run(self) -> bool: def should_run(self) -> bool:
"""Check if the task should run now.""" """检查任务现在是否应该运行。"""
if not self.enabled or not self.next_run: if not self.enabled or not self.next_run:
return False return False
now = datetime.now() now = datetime.now()
# Check if we're within the execution window (5 minute tolerance) # 检查我们是否在执行窗口内(5分钟容差)
if self.next_run <= now <= self.next_run + timedelta(minutes=5): if self.next_run <= now <= self.next_run + timedelta(minutes=5):
# Check if we haven't run today # 检查我们今天是否还没有运行
if self.last_run is None or self.last_run.date() != now.date(): if self.last_run is None or self.last_run.date() != now.date():
return True return True
return False return False
def mark_completed(self) -> None: def mark_completed(self) -> None:
"""Mark the task as completed and schedule next run.""" """将任务标记为完成并计划下一次运行。"""
self.last_run = datetime.now() self.last_run = datetime.now()
self._calculate_next_run() self._calculate_next_run()
class SchedulingService: class SchedulingService:
""" """
Application service for managing scheduled analysis tasks. 管理计划分析任务的应用服务。
This service runs a background loop that checks for and 该服务运行一个后台循环,检查并
executes scheduled tasks. 执行计划的任务。
""" """
def __init__(self, config: ConfigManager): def __init__(self, config: ConfigManager):
""" """
Initialize the scheduling service. 初始化调度服务。
Args: Args:
config: Configuration manager config: 配置管理器
""" """
self.config = config self.config = config
self._tasks: Dict[str, ScheduledTask] = {} self._tasks: Dict[str, ScheduledTask] = {}
@@ -99,11 +99,11 @@ class SchedulingService:
def register_callback(self, name: str, callback: Callable) -> None: def register_callback(self, name: str, callback: Callable) -> None:
""" """
Register a callback for scheduled tasks. 为计划任务注册回调。
Args: Args:
name: Callback name name: 回调名称
callback: Async callback function callback: 异步回调函数
""" """
self._callbacks[name] = callback self._callbacks[name] = callback
@@ -114,22 +114,22 @@ class SchedulingService:
callback_name: str = "analyze", callback_name: str = "analyze",
) -> str: ) -> str:
""" """
Add a scheduled task for a group. 为群组添加计划任务。
Args: Args:
group_id: Group identifier group_id: 群组标识符
scheduled_time: Time in HH:MM format (uses config default if not provided) scheduled_time: HH:MM 格式的时间(如果未提供,则使用配置默认值)
callback_name: Name of registered callback to use callback_name: 要使用的注册回调的名称
Returns: Returns:
Task ID 任务 ID
""" """
scheduled_time = scheduled_time or self.config.get_analysis_time() scheduled_time = scheduled_time or self.config.get_analysis_time()
task_id = f"task_{group_id}" task_id = f"task_{group_id}"
callback = self._callbacks.get(callback_name) callback = self._callbacks.get(callback_name)
if not callback: if not callback:
logger.warning(f"Callback '{callback_name}' not registered") logger.warning(f"回调 '{callback_name}' 未注册")
return task_id return task_id
task = ScheduledTask( task = ScheduledTask(
@@ -141,28 +141,28 @@ class SchedulingService:
) )
self._tasks[task_id] = task self._tasks[task_id] = task
logger.info(f"Added scheduled task {task_id} for {scheduled_time}") logger.info(f" {scheduled_time} 添加了计划任务 {task_id}")
return task_id return task_id
def remove_task(self, task_id: str) -> bool: def remove_task(self, task_id: str) -> bool:
""" """
Remove a scheduled task. 移除计划任务。
Args: Args:
task_id: Task identifier task_id: 任务标识符
Returns: Returns:
True if task was removed 如果任务被移除则返回 True
""" """
if task_id in self._tasks: if task_id in self._tasks:
del self._tasks[task_id] del self._tasks[task_id]
logger.info(f"Removed scheduled task {task_id}") logger.info(f"移除了计划任务 {task_id}")
return True return True
return False return False
def enable_task(self, task_id: str) -> bool: def enable_task(self, task_id: str) -> bool:
"""Enable a scheduled task.""" """启用计划任务。"""
if task_id in self._tasks: if task_id in self._tasks:
self._tasks[task_id].enabled = True self._tasks[task_id].enabled = True
self._tasks[task_id]._calculate_next_run() self._tasks[task_id]._calculate_next_run()
@@ -170,7 +170,7 @@ class SchedulingService:
return False return False
def disable_task(self, task_id: str) -> bool: def disable_task(self, task_id: str) -> bool:
"""Disable a scheduled task.""" """禁用计划任务。"""
if task_id in self._tasks: if task_id in self._tasks:
self._tasks[task_id].enabled = False self._tasks[task_id].enabled = False
self._tasks[task_id].next_run = None self._tasks[task_id].next_run = None
@@ -179,13 +179,13 @@ class SchedulingService:
def get_task_status(self, task_id: str) -> Optional[Dict[str, Any]]: def get_task_status(self, task_id: str) -> Optional[Dict[str, Any]]:
""" """
Get status of a scheduled task. 获取计划任务的状态。
Args: Args:
task_id: Task identifier task_id: 任务标识符
Returns: Returns:
Task status dictionary or None 任务状态字典或 None
""" """
task = self._tasks.get(task_id) task = self._tasks.get(task_id)
if not task: if not task:
@@ -201,20 +201,20 @@ class SchedulingService:
} }
def list_tasks(self) -> List[Dict[str, Any]]: def list_tasks(self) -> List[Dict[str, Any]]:
"""List all scheduled tasks.""" """列出所有计划任务。"""
return [self.get_task_status(tid) for tid in self._tasks.keys()] return [self.get_task_status(tid) for tid in self._tasks.keys()]
async def start(self) -> None: async def start(self) -> None:
"""Start the scheduling service.""" """启动调度服务。"""
if self._running: if self._running:
return return
self._running = True self._running = True
self._task = asyncio.create_task(self._run_loop()) self._task = asyncio.create_task(self._run_loop())
logger.info("Scheduling service started") logger.info("调度服务已启动")
async def stop(self) -> None: async def stop(self) -> None:
"""Stop the scheduling service.""" """停止调度服务。"""
self._running = False self._running = False
if self._task: if self._task:
self._task.cancel() self._task.cancel()
@@ -222,37 +222,37 @@ class SchedulingService:
await self._task await self._task
except asyncio.CancelledError: except asyncio.CancelledError:
pass pass
logger.info("Scheduling service stopped") logger.info("调度服务已停止")
async def _run_loop(self) -> None: async def _run_loop(self) -> None:
"""Main scheduling loop.""" """主调度循环。"""
while self._running: while self._running:
try: try:
await self._check_and_run_tasks() await self._check_and_run_tasks()
# Check every minute # 每分钟检查一次
await asyncio.sleep(60) await asyncio.sleep(60)
except asyncio.CancelledError: except asyncio.CancelledError:
break break
except Exception as e: except Exception as e:
logger.error(f"Error in scheduling loop: {e}") logger.error(f"调度循环出错: {e}")
await asyncio.sleep(60) await asyncio.sleep(60)
async def _check_and_run_tasks(self) -> None: async def _check_and_run_tasks(self) -> None:
"""Check for and execute due tasks.""" """检查并执行到期任务。"""
for task in list(self._tasks.values()): for task in list(self._tasks.values()):
if task.should_run(): if task.should_run():
try: try:
logger.info(f"Executing scheduled task {task.task_id}") logger.info(f"正在执行计划任务 {task.task_id}")
await task.callback(task.group_id) await task.callback(task.group_id)
task.mark_completed() task.mark_completed()
logger.info(f"Completed scheduled task {task.task_id}") logger.info(f"计划任务 {task.task_id} 已完成")
except Exception as e: except Exception as e:
logger.error(f"Failed to execute task {task.task_id}: {e}") logger.error(f"执行任务 {task.task_id} 失败: {e}")
def setup_from_config(self) -> None: def setup_from_config(self) -> None:
"""Set up scheduled tasks from configuration.""" """根据配置设置计划任务。"""
if not self.config.get_auto_analysis_enabled(): if not self.config.get_auto_analysis_enabled():
logger.info("Auto analysis is disabled") logger.info("自动分析已禁用")
return return
enabled_groups = self.config.get_enabled_groups() enabled_groups = self.config.get_enabled_groups()
@@ -261,4 +261,4 @@ class SchedulingService:
for group_id in enabled_groups: for group_id in enabled_groups:
self.add_task(group_id, analysis_time) self.add_task(group_id, analysis_time)
logger.info(f"Set up {len(enabled_groups)} scheduled tasks") logger.info(f"设置了 {len(enabled_groups)} 个计划任务")