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