Commit Graph
42 Commits
Author SHA1 Message Date
nezumi 5aefec8dcf feat(i18n): add Vietnamese localization 2026-07-22 18:02:17 +07:00
SXP-Simon 3a03c1f272 feat(filter_bot_messages): 新增 filter_bot 开关,控制 bot 消息是否纳入分析
Fixes #205

默认排除 bot 自身发言(filter_bot_messages=True),可通过 /分析设置 filter_bot 切换。
修改涉及三层:
1. 配置层:ConfigManager getter/setter + _conf_schema.json 面板选项
2. 适配器层:BotManager 传入配置,OneBotAdapter.fetch_messages 认 switch
3. 分析层:clean_messages 和 analyze_user_activity 的 bot_self_ids 受 switch 控制
2026-07-21 15:42:47 +08:00
clown145andSXP-Simon f2bcd6801e [v4.11.1] - 🛠️ 修复 QQ 官方机器人昵称与提及清洗 (#207)
Fix QQ official nickname and mention handling 

* fix: restore QQ official nicknames and sanitize mentions

* fix: protect QQ official identities and whitespace

* docs: update QQ official nickname guidance

* chore: bump version to v4.11.1

* docs: remove obsolete PDF guidance

* chore: finalize v4.11.1 release prep

* fix(qqofficial): 修复 _sanitize_qq_official_mentions .strip() 吞换行,补充 allow_alphanumeric_user_ids 注释

- .strip() → .strip(' \t'):仅清除首尾空白/制表符,保留用户创作的 \n 换行
- allow_alphanumeric_user_ids:在参数定义处补充注释,说明该标记还控制 ID 正则化和回退显示名
- 响应 Sourcery 代码审查 #207 指出的问题

* chore:  删除不必要的描述

---------

Co-authored-by: SXP-Simon <sxp20061207@163.com>
2026-07-21 14:53:31 +08:00
clown145andSXP-Simon c18224cb82 [v4.11.0] - 新增 QQ 官方机器人群聊分析与专用 Markdown 报告 (@clown145 #206)
* feat: add QQ official bot group analysis support

* fix: use text progress replies for QQ official bot

* fix: harden QQ official proactive reporting

* feat: enhance QQ official markdown reports

* refactor: isolate QQ official markdown reporting

* fix: restore platform adapter exports

* style: format QQ official changes

* fix(main): 添加 html_render 类型声明和 Callable 导入

为 self.html_render 属性添加显式类型声明,解决定时任务中可能因缺少类型注解导致的隐式错误。

* fix(analysis): 消除 execute_daily_analysis 中重复的 bot_self_ids 赋值

去除第二次冗余的 config_manager.get_bot_self_ids() 调用,直接复用已获取的变量。

* cleanup(domain): 移除未使用的分析器适配器和死代码服务文件

删除 golden_quote_analyzer.py、topic_analyzer.py、user_title_analyzer.py(均为未被引用的接口+适配器包装)report_generator.py(旧的文本报告生成器)statistics_calculator.py(与 StatisticsService 功能重复)更新 domain/services/__init__.py 移除对上述文件的引用。

* cleanup(domain): 移除冗余的实体和值对象文件,收敛数据模型至 domain/models/data_models.py

删除 analysis_result.py(与 data_models.py 重复的 SummaryTopic/UserTitle/GoldenQuote 等类定义)value_objects/golden_quote.py、statistics.py、topic.py、user_title.py(均为未被引用的 frozen dataclass 迁移残留)。所有活跃代码已统一导入 domain/models/data_models.py。

* refactor(llm): 抽取 _make_session_id 辅助方法消除重复代码

在 5 个方法(analyze_topics、analyze_user_titles、analyze_golden_quotes、analyze_all_concurrent、analyze_incremental_concurrent)中出现完全相同的 datetime.now().strftime(...) + umo 拼接逻辑,已提取为 _make_session_id 静态方法。

* refactor(message): 正则表达式提升为模块级常量避免重复编译

DISCORD_CUSTOM_EMOJI_PATTERN 和 COMMAND_PATTERN 从类属性移至模块级常量,避免每次实例化 MessageCleanerService 时重新编译正则。

* arch(domain): 定义 IActivityVisualizer 接口并通过依赖注入消除领域层反向依赖

创建 IActivityVisualizer 接口于 domain/repositories/visualization_repository.py,StatisticsService 改由依赖注入接收该接口;ActivityVisualizer 继承接口。消除原 StatisticsService 直接 import infrastructure.visualization 的 DDD 违规。

* fix(main): 补全 Callable 导入和 html_render 类型声明

初次提交(877adb6)因 git add -p 交互式分块时 BOM 导致错误的 hunk 被暂存,Callable 导入和 html_render 类型声明丢失。本次补全这两项修改。

* fix(platform): 补充 QQOfficialAdapter、TelegramAdapter、DiscordAdapter 导出

* refactor(main): 提取内嵌的文本报告生成/发送函数为独立类方法

将 _send_analysis_report 方法中的 generate_text_reports() 和 send_text_reports() 内嵌异步函数提取为 _generate_text_reports 和 _send_text_reports 私有方法。减少闭包复杂度,提升可维护性。

* cleanup(config): 移除废弃的 get_qq_official_t2i_activity_histogram_enabled 向后兼容方法

删除 config_manager.py 中的旧名别名方法,简化 qq_official_markdown.py 中对应的 getattr 回退逻辑为直接方法调用,移除测试中专门验证旧名兼容性的 LegacyDisabledConfig 测试用例。该兼容层仅在迁移期间临时存在,现已完成过渡。

* fix(types): 修复 Pylance 类型告警 — platform_key 未绑定、int(object) 和 template.filename 可能为 None

platform_group_registry.py: 将 platform_key 定义提前,消除 Pylance reportPossiblyUnboundVariable 告警。
qq_official_markdown.py: 将 int(value or 0) 改为 int(value) if value is not None else 0,消除 reportArgumentType 告警。
templates.py: 在使用 template.filename 前增加 None 检查,消除 str|None 不可分配给 str 的告警。
qq_official_adapter.py: 为 post_group_message 添加类型忽略注解,消除 await 不可等待对象的告警。

* fix(types): 修复残留的 Pylance 类型告警

platform_group_registry.py: 将 (platform_key, group_id) 改为 (str(platform_key), group_id),消除 str|None 不可分配给 str 的 reportArgumentType
qq_official_markdown.py: int(value) 添加 # type: ignore[arg-type],消除 object 不可分配给 ConvertibleToInt
qq_official_adapter.py: 移除无意义的中间变量,await 行直接添加 # type: ignore[arg-type]

* docs(message): 更新 MessageProcessingService 的文档和注释,消除 Telegram 特殊性表述

类 docstring:移除 '维护 Telegram 群组注册表' 等过时描述,补充 QQ 官方去重职责。
group_registry.upsert 注释:改为泛化的跨平台描述,不再限定 Telegram。
_extract_event_timestamp / _reserve_event_id / _commit_event_id / _release_event_id:英文 docstring 统一为中文。

* docs(message): 修正类注释中只提 QQ 官方的问题,明示 Telegram 也由本服务处理

Telegram 和 QQ 官方消息都经过 MessageProcessingService.process_message()。修正前类 docstring 只提了 QQ 官方的事件去重,缺少 Telegram 作为主要调用者的说明。

* fix(types): 修正 _sanitize_analysis_result_for_export 返回类型注解

函数声明 -> dict 但 _sanitize_export_identity_text 可返回 str|dict|list,Pylance 报 reportReturnType。
改为 -> dict[str, Any] 准确表达实际返回类型,补充缺失的 from typing import Any。

* fix(types): 抑制 Pylance reportReturnType 误报

_sanitize_analysis_result_for_export 的 analysis_result 参数运行时始终为 dict,但 _to_plain_export_data 递归返回 Any 导致 Pylance 推导出 str|dict|list 联合类型。
添加 # type: ignore[return-type] 抑制此误报。

* fix(report): 渲染匿名模式下的未知引用 token 不再静默丢弃

当 hide_user_names=True 且 [id] 不在 known_ids 中时,之前返回空 Markup 导致 token 被静默移除,可能扭曲文本语义。改为返回转义后的原始 [id] 字符串,保留文本布局和语义,同时不泄露身份信息。
参考 Sourcery AI code review 建议。

* fix(import): 避免从 astrbot.core 直接导入 File,优先使用公开 API

astrbot.core 是内部模块,不在公开 API 契约中,可能随版本变化。
改为 try 优先导入 astrbot.api.message_components.File(公开 API),
失败时回退到 astrbot.core.message.components.File(向后兼容)。
同时修复 main.py 和 qq_official_adapter.py 两处导入。

* fix(import): 回退 try/except 伪装,改为直接导入 + 风险注释

astrbot.api.message_components 不存在,try/except 永远走 except 分支,是无效代码。
改为直接 from astrbot.core.message.components import File,用注释说明这是内部 API 可能变化。

* fix(ruff): 代码质量

* docs(README): 调整文档说明,删除 lark 相关的描述和功能标识

* docs(desc): 更新 desc

* fix(message): 将 TG 和 QQ 官方消息缓存成功日志降为 debug

* perf(message): 将 _extract_event_timestamp 延迟到 QQ 官方分支内计算

该时间戳仅用于 QQ 官方消息的 history_content 元数据,但对所有平台都执行了深度 getattr 链。
改为只在 QQ 官方分支内延迟计算,消除 Telegram 等平台上每次消息的白算开销。

* chore(CHANGELOG)

---------

Co-authored-by: SXP-Simon <sxp20061207@163.com>
2026-07-20 03:24:50 +08:00
Helian Nuits e8af00e016 feat(muted): 被禁言避免触发分析功能浪费 token (#191) (#203)
* feat(AnalysisApplicationService): 增加针对禁言的优化

* fix: 优先从 Event 中提取 bot_self_id

* fix: 禁言异常处理

* fix: 不传递 no_cache=True 以免超时

* fix: 如果 bot_instance 没变,且已经有适配器,跳过重新创建,防止丢失内部状态

* fix: set_reaction 方法操作异常拦截

* fix: 修复错误的禁言发送消息,改为日志提示

* chore: add .tmp_refs to .gitignore

* refactor(onebot): optimize and prune group mute cache

* fix(onebot): resolve pylance type mismatch warning in min key

* fix(onebot): annotate params dict with precise union type to resolve pylance warning
2026-07-08 11:44:19 +08:00
SXP-Simon 43f80d24f8 feat(feishu): 完善日志和健壮性 2026-03-29 01:02:15 +08:00
SXP-Simon bc916e259d Revert "fix: 统一定时分析名单准入并修复白名单绕过问题 (情况如 #133 所述)"
This reverts commit a3d72e43ab.
2026-03-29 00:36:08 +08:00
SXP-Simon 0cba280a82 feat(feishu): 尝试接入飞书 2026-03-29 00:29:37 +08:00
SXP-Simon a3d72e43ab fix: 统一定时分析名单准入并修复白名单绕过问题 (情况如 #133 所述) 2026-03-28 21:53:01 +08:00
SXP-Simon aa3ae494ce fix(tg): 修复 Telegram 平台自动分析就绪检查失败以及 ID 匹配诊断逻辑
- 优化 BotManager 的 is_ready_for_auto_analysis 逻辑:将其改为非硬性限制。即使未成功提取机器人 ID (bot_self_ids),也允许定时任务继续运行,从而解决了 Telegram 在 Docker 部署下因 ID 获取延迟导致报告被跳过的问题。
- 强化日志诊断:在 Telegram 消息拦截 (save)、平台发现 (discovery) 和消息拉取 (fetch) 的关键路径中增加 platform_id 显式日志,方便排查多账号环境下的 ID 冲突。
- 在 BotManager 就绪检查中加入调试输出,明确告知分析任务被跳过的具体原因。
2026-03-26 13:33:09 +08:00
SXP-Simon fcffe7d35a fix(quality_summary): 优化增量分析逻辑,优化提示词 2026-03-23 13:38:12 +08:00
SXP-Simon 9a35ed9600 feat(chat_quality_analysis): chat_quality_analysis 模块 2026-03-23 00:42:18 +08:00
SXP-Simon cd6a6294e1 feat(增量分析): 更新增量分析配置,增加安全上限并优化消息拉取逻辑 2026-03-20 23:59:24 +08:00
SXP-Simon b4abee55d4 fix: 修复 TraceContext 兼容性与服务返回结果缺失导致的崩溃问题
【链路追踪系统】
- 在 TraceContext 中补全 generate()、set() 和 get() 兼容性接口,确保旧代码无缝迁移。
- 重新实现 TraceLogFilter 日志过滤器,恢复日志流中的 TraceID 显示。
- 统一全插件 import 路径至 src/shared/trace_context.py,并删除冗余的旧文件。

【应用服务层】
- 修复 KeyError: 'group_id':在 execute_daily_analysis 和 execute_incremental_final_report 的返回结果中补全 group_id 和 platform_id。
- 完善 execute_incremental_analysis 的返回字段,保持 API 返回格式的一致性。

【基础设施与工具】
- 在 AutoScheduler 中增加对适配器获取失败的防御性检查。
- 修复 uto_scheduler.py 和 dispatcher.py 中的静态类型检查报错。
2026-03-12 14:51:59 +08:00
SXP-Simon efea9d5b5d fix: 修复生成报告时的 KeyError: 'group_id' 崩溃问题
- 在 execute_daily_analysis 返回结果中补全 group_id 和 platform_id
- 在 execute_incremental_final_report 返回结果中补全对应字段
- 确保 main.py 中的报表分发逻辑能正确获取目标群组信息
2026-03-12 14:08:18 +08:00
SXP-Simon 0b90a8b9ac fix(analysis): 修复可选参数 days 以支持自定义分析天数 2026-03-10 12:33:12 +08:00
SXP-Simon 2e5071a55d fix(concurrency): 优化群组任务锁的获取逻辑,确保锁的创建 2026-03-03 21:07:51 +08:00
SXP-Simon 9b26a3e5c9 fix(perf): 引入原子化任务注册表,消除异步锁状态检查的竞态盲区
- 【深度优化】将原有的 'if lock.locked()' 探测逻辑重构为基于同步集合的「任务注册表」模式。
- 【原理解修】规避了 asyncio 环境下异步锁获取的非原子性问题:
    - 痛点:虽然 asyncio 是单线程,但 `async with lock` 内部的 `acquire()` 是一个 `await` 点;
    - 风险:在高并发瞬间,多个协程可能在执行 `await lock.acquire()` 时让出控制权,导致它们都通过了之前的 `locked()` 检查,最终在锁上排队而非直接跳过。
- 【原子性方案】利用 asyncio 事件循环中“同步代码块不可被中断”的特性,将任务的「检查」与「占位」合并为连续的同步操作。
- 【确定性控制】确保重复请求在触达任何 `await` 点之前即被同步拦截,从而 100% 保证并发冲突时触发“直接跳过”的语义,彻底杜绝意外排队现象。
2026-03-03 21:07:51 +08:00
SXP-Simon 7850697f1a refactor(perf): 建立三级资源防线并优化并发限流配置
- 【异常处理优化】引入自定义任务重复异常,精准区分“因重复运行而跳过”与“实际分析取消”两种不同语义,提升调度健壮性。
- 【三级并发控制架构】针对不同层级的资源消耗,建立了完整的限流保护体系:
    - 入口层:控制同时处于活跃状态的任务总数,防止瞬时加载大量消息导致服务器内存溢出 (OOM);
    - 接口层:全局限制 LLM API 并发请求数,确保严格遵守服务商的频率限制 (RPM);
    - 渲染层:全局限制浏览器图片生成进程,保护物理 CPU 与内存不被高能耗渲染任务耗尽。
- 【配置体验升级】新增「并发限流设置」配置组,统一收纳核心性能参数,并提供面向普通用户的防坑说明与更稳健的默认值。
- 【代码清理】移除陈旧的兼容逻辑与冗余参数,统一配置命名规范。
- 【功能精化】重排增量分析逻辑,确保在任务入口与分段处理流程中均有可靠的信号量保护。
- 【细节完善】优化群文件及群相册上传设置的文案描述,明确功能支持范围与权限要求。
2026-03-03 21:07:51 +08:00
SXP-Simon ee0bf037b8 feat: 实现群聊分析任务锁及全局资源并发限流控制
1. 任务锁定机制 (Group Task Locking):
   - 在应用服务层实现基于群组和任务类型的异步锁,使用 asynccontextmanager 生成器函数确保同一群聊在同一时间只能执行一个分析任务。
   - 使用弱引用字典 (WeakValueDictionary) 管理锁实例,防止长期的内存占用。
   - 在指令入口增加对 CancelledError 的捕获,当任务冲突时向用户反馈“任务正在执行中”的友好提示。

2. 全局并发限流重构 (Resource-level Throttling):
   - 资源层限流下沉:将并发控制中心从调度层迁移至具体的资源处理层(T2I/LLM)。
   - T2I 渲染保护:在报告生成器中引入全局信号量,严格控制 T2I 引擎的瞬时负载。
   - LLM API 保护:在应用服务层引入全局信号量,平滑所有分析请求对 LLM 提供商接口的请求频率。
   - 调度逻辑简化:移除调度器内部冗余的信号量,使其仅专注于分发逻辑与 Stagger(交错启动)平滑。

3. 调度与反馈优化:
   - 自动分析调度器增加对“跳过”任务的独立统计,并在执行报告中清晰展示“成功、跳过、失败”的具体数量。
   - 优化了管理测试指令和增量分析指令的异常处理逻辑。

4. 消息重复发送防护:
   - 在重试组件中增加基于消息历史记录的探活逻辑。在重试发送前先核实记录,确认是否已因网络抖动导致“假失败”但已实达,有效拦截重复消息。
2026-03-03 21:07:51 +08:00
SXP-Simon c242bd3887 fix(analysis_application_service): 解决增量分析传参错误导致用户称号失效的问题 2026-02-23 01:07:46 +08:00
clown145andSXP-Simon 00863ff979 feat: 模板预览路由化并增强 Telegram 按钮交互稳定性 (#83)
* feat: 路由化模板预览并完善Telegram交互回退

* fix: 忽略模板预览文档回退的重复编辑异常

* fix: 在回调阶段主动清理并校验模板预览会话过期

* fix: 处理Telegram回调注册在平台热替换场景的重绑与清理

* fix(set_report_template): 删除冗余的检查

---------

Co-authored-by: SXP-Simon <sxp20061207@163.com>
2026-02-12 19:02:46 +08:00
clown145 727da8025d fix: 清理TelegramAdapter无用变量并通过lint 2026-02-12 15:41:07 +08:00
SXP-Simon b4eec978fe refactor(Telegram): 重构 Telegram 逻辑并提取消息处理与注册表服务
- 提取消息处理服务及 Telegram 注册表,显著精简主插件逻辑。
- Telegram 群组获取回退逻辑下沉至适配器,移除调度中心硬编码。
- 优化依赖注入机制,使适配器层级可访问插件 KV 存储。
- 修正消息内容定义兼容性并清理冗余代码。
2026-02-12 15:41:07 +08:00
SXP-Simon ced38e6a9e fix: 修复了导致增量分析报告发送失败的几个核心问题:
修复报告分发器初始化错误:
在 AutoScheduler 中,初始化 ReportDispatcher 时漏传了 report_generator,导致在尝试生成报告(图片或文本)时出现 'NoneType' object has no attribute 'generate_image_report' 错误。
已更新 AutoScheduler 的构造函数并正确传递 report_generator。
修复 LLM 分析器在增量模式下的数据结构错误:UserTitleAnalyzer 报错:在增量模式下,用户活动数据被简化存储,导致 UserTitleAnalyzer 找不到 'hours' 键(Error: 'hours')。
补全数据维度:更新了 AnalysisApplicationService 的增量数据转换逻辑,保留了完整的每小时活跃分布 (hours) 和回复数 (reply_count)。
统一字段名:增量模式下使用了 nickname 字段以匹配分析器的预期(之前被错误转为了 name)。
增强容错性:优化了 UserTitleAnalyzer 的逻辑,现在它能安全地处理 hours 缺失或旧版本数据 schema,不再会因为找不到键而崩溃。
修复增量数据合并逻辑:
更新了 IncrementalMergeService,现在它能正确合并多个批次中的每小时发言统计和回复数统计,确保最终生成的报告数据准确。
2026-02-11 12:54:02 +08:00
SXP-Simon 472c78e622 feat(话题分析): 用户头像引用展示
- TopicAnalyzer: Prompt中包含 [user_id],引导LLM使用ID引用用户
- ReportGenerator: 解析话题详情中的 [uid] 并替换为内联头像HTML
- Templates: 更新所有主题的 topic_item.html 以支持富文本详情展示
- _conf_schema.json: 更新默认 Prompt,指导 LLM 使用 [用户ID] 引用用户
- ReportGenerator: 实现胶囊样式渲染 (头像+昵称),提升视觉体验
2026-02-10 20:57:51 +08:00
SXP-Simon 4e0b8fe24b fix(增量分析): 增量分析现已支持按配置开关控制话题/金句分析 2026-02-10 19:58:49 +08:00
SXP-Simon 83b82de2bb refactor(增量分析): 从按天存储改为滑动窗口批次架构
- IncrementalBatch: 独立批次实体,每次增量分析产生一个,按批次独立存储到KV
- IncrementalState: 聚合视图,不再持久化,报告时由merge_batches合并产生
- IncrementalStore: 批次索引+数据KV持久化,支持按时间窗口查询和过期清理
- IncrementalMergeService: 新增merge_batches方法,负责批次合并和话题/金句去重
- AnalysisApplicationService: 增量分析存独立批次,最终报告按窗口查询合并
- AutoScheduler: 报告发送后清理2×窗口外的过期批次
- main.py: /增量状态命令改为滑动窗口查询展示
- 消除天然日期隔离问题,24h图表展示完整数据
2026-02-10 18:15:46 +08:00
SXP-Simon bddaf4fef8 feat(增量分析): 扩展AnalysisApplicationService支持增量分析和最终报告生成 2026-02-10 15:06:40 +08:00
SXP-Simon f8412559ef fix: 分析器和消息处理 2026-02-09 14:15:43 +08:00
SXP-Simon e1ad6c9fc9 fix: 正确的导入各重构模块 2026-02-09 13:08:23 +08:00
SXP-Simon 2005f0633f refactor(DDD): 整理架构 2026-02-09 12:47:43 +08:00
SXP-Simon 80d74577e7 fix(pre-commit): style 2026-02-09 01:39:13 +08:00
SXP-Simon e73fd99e26 feat(logger) 2026-02-08 23:28:56 +08:00
SXP-Simon 25a6a261b5 Refactor: Cleanup commented out code in analysis_orchestrator.py 2026-02-08 21:54:34 +08:00
SXP-Simon ec29304069 Refactor: Translate comments and logs to Chinese in application layer 2026-02-08 21:53:49 +08:00
SXP-Simon 6f7b20d962 fix: 正确注册命令 2026-02-08 19:39:50 +08:00
SXP-Simon 0d34a9df3a feat: 添加发送者字段填充,确保向后兼容旧分析器 2026-02-08 19:04:51 +08:00
SXP-Simon e8833be891 refactor: translate comments to Chinese and fix hardcoded OneBot format 2026-02-08 16:23:32 +08:00
SXP-Simon 39e5d6169d chore: 注释 2026-02-08 15:06:33 +08:00
SXP-Simon 7ef58f9d53 feat: complete DDD Phase 2 - add domain services, infrastructure layers, and shared components
- domain/value_objects: Add Topic, UserTitle, GoldenQuote, Statistics value objects
- domain/services: Add StatisticsCalculator, ReportGenerator domain services
- domain/exceptions: Add comprehensive domain exception hierarchy
- infrastructure/persistence: Add HistoryRepository for data storage
- infrastructure/llm: Add LLMClient wrapper for AstrBot providers
- infrastructure/config: Add ConfigManager for centralized configuration
- infrastructure/resilience: Add CircuitBreaker, RateLimiter, retry utilities
- application: Add SchedulingService, ReportingService application services
- shared: Add constants and TraceContext for request tracing

All imports verified in Docker container.
2026-02-08 14:39:19 +08:00
SXP-Simon c1d3bf5ece feat: add DDD architecture layers (domain, infrastructure, application)
- Domain layer: UnifiedMessage, PlatformCapabilities, repository interfaces
- Infrastructure layer: PlatformAdapter base, OneBotAdapter, factory
- Application layer: AnalysisOrchestrator, MessageConverter

This provides cross-platform abstraction for group analysis plugin.
2026-02-08 14:13:09 +08:00