Repository navigation
Releases: wc985732-lang/qq-live-digest
Release list
v0.5.0 — 界面与主题(卡片瘦身 + 深/浅双主题)
[0.5.0] - 2026-10-10
界面
- 卡片瘦身(headless Edge 实测,390×844 视口 DPR2,55 条待办):卡片内的
「详细要求 / 查看完整原文 / 纠错」原本各占一整行(296×18px 纯文字、零内边距,手机实测相邻间距
仅 7px,既容易误触、又把卡片撑得老高),现在并成一行胶囊按钮(详细 / 原文 / 纠错,
min-height:44px,短标签给眼睛看、完整名称放aria-label+title给读屏)。
单卡高度 194px → 129px,55 条待办整页 10 830px → 7 837px,首屏可见卡片 3 张 → 4 张。
开关补上按下态(:active)与键盘焦点环(:focus-visible)——此前全局关闭了系统点击高亮又没有按下反馈。 - 「查看完整原文」展开后正文限高
45vh并内部滚动(overscroll-behavior:contain),
不再把卡片从约 130px 撑到约 470px、挤走后续待办;展开时标题切换为「收起」。 - 深/浅双主题:配色改为语义 token(
--bg / --bg-top / --glass-* / --card / --card-2 / --line / --text / --muted / --dim / --accent / --tint-* / --hero-*…),深色是:root默认值,
浅色只覆盖同名 token。设置页新增「外观:跟随系统 / 浅色 / 深色」,选择存localStorage,
<head>里的内联脚本在首帧前落到data-theme(不会先画一帧深色再切),跟随系统
prefers-color-scheme变化,并同步meta[name=theme-color]、iOS 状态栏样式与 manifest 颜色。
原深色配色正文对卡片仅 3.53:1、次级 2.76:1(均低于 WCAG AA 4.5:1),重排后为
14.55 / 7.80 / 5.02(浅色 16.90 / 5.98 / 4.51)。 - 群名胶囊并入卡片顶部信息行(原来单独占一行,约 29px/卡),不再每张卡多一行。
- 勾选圆点本体只有 29px,加一层透明子元素把命中区撑到 45px(视觉与位置不变)。
- 清理设计 token:删掉已无引用的
--ink-on-solid、--urgent,并替换掉var(--surface)/
var(--grad)等旧变量残留(未定义的var()会被浏览器当无效值静默丢弃)。
修复
- 待办台卡片里的「已逾期」红胶囊是重复信息(同一条任务的截止时间胶囊已经写着「…已过」且同色),
而且会把卡片顶部信息行挤到第二行(+23px/卡)——已删除。 - 跨天(非今天)的过期截止时间此前显示成「09-28 18:00 截止」,读起来像还没到点;
改为「09-28 18:00 已过」,与overdue标志一致。 - 修正
qq_live_digest/doctor.py中run_checks()列表里一行的缩进层级(纯排版,无行为变化)。
测试
- 新增回归测试:待办台重启会沿用已生成的 token、不轮换(轮换会让已保存的带 token 链接 / PWA 静默失效)。
- 新增回归测试:锁定待办台卡片开关的 44px 命中区、勾选圆点的 45px 命中区、原文限高与展开态文案切换。
- 新增回归测试:跨天过期截止时间必须显示「已过」,且不再渲染重复的「已逾期」胶囊。
- 新增回归测试:浅色 token 块、
data-theme引导脚本、设置页三态外观开关与 manifest 颜色一致;
同时禁止var(--surface)/var(--grad)之类旧 token 引用回流。
截图
深色 · 改动前后对比
浅色主题 + 设置页「外观」开关
浅色主题(待办台主视图)
截图由 headless Edge 在本机跑真实服务渲染(390×844 视口、DPR2;数据是程序生成的虚构示例)。
升级说明
无破坏性变更,也无新增配置项:pip install -r requirements.txt 后按原方式重启即可。
主题偏好只存在浏览器 localStorage,服务端不落任何新字段,PWA 缓存策略也未变。
v0.4.1 — 安全加固(审计修复)
v0.4.1 — 安全加固
对 v0.3.1 → v0.4.0 的新增面做了一轮安全 / 正确性审计,本版修完全部问题并补齐回归测试。含两处破坏性行为变更,升级前请先看「兼容性」。
安全
- 邮件推送(SMTP)证书校验:走 587 + STARTTLS 时未传 TLS 上下文,
smtplib默认CERT_NONE(既不校验证书也不校验主机名),账号口令与摘要正文可被中间人窃听。现在SMTP_SSL与starttls()都使用ssl.create_default_context()。 - 待办台鉴权反转 + 缺 CSRF 校验:过去
QQ_DIGEST_WEB_HOST为回环地址且未配 token 时不生成 token(本机部署等于免鉴权),写请求也没有跨站校验。现在无论监听哪里都会生成 token 并落库;写请求校验Origin(跨站返回 403);页面拿到 token 后立即从地址栏 / 历史 / Referer 移除。 - 归档待办泄露:
conflicts、ICS 导出、/api/deadlines、/api/todos过去只排除done,被忽略 / 过期归档的待办仍会出现在冲突提醒与日历里。现新增统一的任务状态口径,日历与冲突一律跳过归档态。 - OneBot 鉴权边界:未设上报 token 时不再允许监听非回环地址(这种配置等于局域网内任何人都能伪造群消息),接收器会直接拒绝启动。
- token 比较改为恒定时间(
hmac.compare_digest),消除逐字符比较的计时侧信道。 - 搜索的 LIKE 通配符注入:
search_messages未转义%/_,传%即等于扫全库;现在转义并显式ESCAPE。 - 推送凭据遮蔽:Telegram 错误信息遮蔽 bot_token;Ntfy 在非 https 端点下丢弃
NTFY_TOKEN。
修复
mcp.call_tool遇到未知 Tool 不再抛KeyError,改为返回isError结果。- ICS 续行按 74 字节折行(含前导空格不超过 RFC 5545 的 75 字节)。
- 事件合并:两侧都没有日期 / 来源 / 截止硬锚点时收紧判据,减少「换个说法的闲聊」被误合并。
doctor口径与本次政策对齐:待办台「对外 + 未显式配 token」由 FAIL 降为 WARN;OneBot「对外 + 无 token」由 WARN 升为 FAIL。- 收敛重复实现(掩码 / 任务状态 / 整数限幅各收敛为一份);REST 的坏参数不再 500;
logging_setup不再残留未关闭的文件句柄。
兼容性
两处破坏性行为变更:
- 待办台现在总是需要 token。 过去
QQ_DIGEST_WEB_HOST为回环地址且未设QQ_DIGEST_WEB_TOKEN时页面不鉴权;现在无论监听哪里都会生成 token 并存入 SQLitemeta表。用python main.py tasks打印带 token 的访问地址;对外部署建议用QQ_DIGEST_WEB_TOKEN显式固定。 - OneBot 未设 token 时不再监听非回环地址。
QQ_DIGEST_ONEBOT_HOST不是127.0.0.1/localhost/::1且QQ_DIGEST_ONEBOT_TOKEN为空时,接收器拒绝启动。请补 token,或改回只监听回环。
另有 doctor 的退出码语义变化(见「修复」末条),若有脚本依赖该退出码请相应调整。
测试
603 个用例通过(较 v0.4.0 的 591 增加 12 例,含 11 个安全 / 边界回归测试)。另做了一次真实冒烟:回环自动生成 token 并落库、无 token → 401 / 有 token → 200、跨站写 → 403、0.0.0.0 无 token 拒启、dismissed 待办不进冲突与日历。
完整改动:v0.4.0...v0.4.1
v0.4.0 — Phase 2 信息中枢(A11 / A15 / A1 / A2 / A13 / A12 / A14 / A16 / A22)
v0.4.0 — Phase 2 信息中枢
Phase 2「产品化 / 信息中枢」的九项全部落地,Phase 2 验收清单至此全部 ✅。无破坏性变更。
亮点
- 事件级跨群聚合(
A11):把同一事件在多个群的转发合成一条(结构化事件键=对象+动作+时间+截止+来源),误合并可用python main.py events --split <事件键>覆盖拆分。默认关闭(QQ_DIGEST_EVENT_MERGE=0),打开后才改变推送口径。 - 只读 REST API(
A15):待办台同端口提供/api/api/notifications/api/tasks/api/deadlines/api/panel/health,X-Token/?token=鉴权,只发 SELECT。 - MCP 接口(
A1只读 +A2确认后可写待办):python main.py mcp(stdio)给 Cursor / Claude 用,现共 5 只读 + 2 可写 = 7 个 Tool。可写只碰tasks(完成 / 新建),必须显式confirm=true,每次调用逐次写audit_log审计;没有任何 QQ 发送 / 删群 / 改设置的入口。 - ICS / 日历导出(
A13):python main.py ics(别名calendar)与GET /api/calendar.ics把有明确时间的待办导成 iCalendar(RFC 5545,CRLF)。只读。 - 时间冲突检测(
A12):截止时间落在同一时间窗(默认 30 分钟)的待办按组提醒,python main.py conflicts与GET /api/conflicts。只提醒,不擅自改任务。 - 多端推送扩展(
A14):补上 ntfy / Telegram / Discord / 企业微信(群机器人)/ 邮件(SMTP),与既有通道共用「主通道失败 → 回退其它通道」与deliveries去重;不配即与以前完全一致。 - PWA 离线(
A16):待办台可安装、断网仍能打开并回放最近一次的通知 / 待办(离线只读),写操作在离线时直接拦下并提示。 - Prompt / 模型 A-B 对比(
A22):python main.py ab在同一份固定评测集上对比两套配置的准确率 / 成本 / 延迟并给出胜者。
兼容性
- 无破坏性变更。 新功能均有开关或按需触发:
A11默认关闭、A13/A12只读、A14不配即与以前一致、A16只影响网页待办台、A22只在显式调用时跑。 data/数据库只新增audit_log表(MCP 审计)与event_splits表(事件拆分覆盖),无迁移。
测试
591 个用例通过(较 v0.3.1 的 478 增加 113 例)。评测基线未漂移:500 条 / seed=20261008 上召回 98.8%、误报 0.5%、待办 59/59、截止 59/59、跨群去重 4/4、延迟中位 0.0 / P95 31.6 分钟 —— 与同一时刻的 v0.3.1 逐项一致(顺带修掉一处 ICS DTSTAMP 断言依赖运行机器时区的脆弱测试)。
完整改动:v0.3.1...v0.4.0
v0.3.1 — Phase 1 收尾(A9 + A32)
v0.3.1 — Phase 1 收尾(A9 + A32)
Phase 1「AI 可控、可测、可替换」的两条收尾项落地,Phase 1 验收清单至此全部 ✅。无破坏性变更。
亮点
- 群级个性化策略(
A9):每个群可以在全局配置之上覆盖少量开关(安静群 / 本群额外关键词 / 进摘要最低分 / 模型档 / 免打扰时段),没写的字段一律继承全局,只改一个群不会牵连别的群。配置写在QQ_DIGEST_GROUP_POLICIES(JSON,键可以是群号或群名);python main.py groups(别名policies,--json)逐群打印最终生效的开关与本群覆盖了哪些字段;doctor的「群白名单」一行会提示有几个群配了策略。坏 JSON / 认不出的字段 / 非法时段只丢自己,不抛异常。 - 消息处理可观测面板(
A32):一条命令看清消息是怎么被处理的——收了多少条(含群数与最活跃的几个群)、判了多少条与过滤率、攒出多少候选(推送 / 保留 / 待确认)、调了几次模型与 token 用量、推送成功率、候选待办的人工确认情况。python main.py observe(别名panel,--days/--json)给终端视图;待办台服务同端口提供网页版/panel与/api/panel(token 与待办台相同,不新起端口),doctor新增「可观测面板」一行。实现是qq_live_digest/observe.py(纯聚合,只发 SELECT,不写库、不联网)。默认脱敏:群号一律掩码、不带消息正文 / 发送者 / 任何密钥,输出可直接贴出来。
口径写进 README:过滤率分母只算已决状态(待投递 / 延后未决是过程态)、推送成功率的分母不算待发、数据不足时给 0.0 而不是假装 100%。
兼容性
- 无破坏性变更。
data/数据库无 schema 变更(只新增只读聚合查询)。 - 不配
QQ_DIGEST_GROUP_POLICIES时行为与 v0.3.0 完全一致。
测试
478 个用例通过(新增 tests/test_observe.py 21 例,含脱敏断言,全程不联网)。评测基线未漂移(500 条 / seed=20261008:召回 100%、误报 0.5%、待办与截止时间 100%、跨群去重 100%、延迟中位 0.0 / P95 31.6 分钟)。
完整改动:v0.3.0...v0.3.1
v0.3.0 — AI 可控、可测、可替换(Phase 1)
v0.3.0 — AI 可控、可测、可替换(Phase 1 主体)
这个版本把「大模型」从黑盒变成可核算、可解释、可替换的一层:花的钱能看清、判的理由能读懂、换供应商只改配置。
亮点
- 模型 Provider 抽象(
A4):业务代码只依赖qq_live_digest/providers.py的LLMProvider/LLMResult,换供应商只改配置(QQ_DIGEST_LLM_PROVIDER,none可彻底关闭模型调用);文档见docs/PROVIDERS.md。 - Token / 成本统计(
A5):每次模型调用落一行llm_calls(provider / 模型 / 输入输出 token / 耗时 / 失败原因 / 是否重试 / 是否降级),python main.py llm-stats(别名cost)给出日 / 周 / 月视图,按QQ_DIGEST_LLM_PRICE_IN/_OUT在展示时折算费用,改价不重写历史。 - 置信度与可解释性(
A7):每条候选给出 0–1 的confidence与一组人话化的触发规则(权重写在解释里),推送正文会附「为什么…(把握较高 82%)」。 - 模型分级路由(
A6):本地规则 → 轻量模型 → 高能力模型,难例判据只用确定性信号,路由原因随用量落库,llm-stats可查「路由分布」。 - 脱敏评测集与可复现指标(
A21):python main.py benchmark(别名bench)在虚构群聊上跑真实链路,输出召回 / 误报 / 待办 / 截止 / 去重 / 延迟 / 成本 / 置信度分布,离线、确定性,可当 CI 回归门槛。
第一版评测基线(500 条 / seed=20261008):召回 100%、误报 0.5%、待办与截止时间 100%、跨群去重 100%、延迟中位 0.0 / P95 31.6 分钟。详见 docs/BENCHMARK.md。
尚未完成(随后续小版本)
A8低置信度人工确认:移动端已有候选确认 / 完成 / 忽略 / 纠错,但「低置信度自动进待确认 + 反馈回收」这条闭环还没做完。A9群级个性化策略:目前只有全局白名单 / 安静群 / 单通道,尚未做到每群独立配静默、关键词、等级、模型档与渠道。
兼容性
- 无破坏性变更。
data/数据库增量迁移(新增llm_calls表;老库自动补route/route_reason列)。 - 不配
QQ_DIGEST_LLM_MODEL_LIGHT时分级路由不启用,行为与 v0.2.0 完全一致。 - 费用单价默认 0(不折算),需按自身实际价目设置。
测试
403 个用例通过(新增 providers / llmstats / confidence / benchmark / routing 五个测试文件)。
完整改动:v0.2.0...v0.3.0
v0.2.0 — 可解释 + 可贡献(Phase 0)
v0.2.0 — 可解释 + 可贡献(Phase 0)
这个版本不堆「更 AI」的功能,而是把系统变得可解释、可测试、易安装、易贡献。
亮点
- 决策日志:每条消息「为什么被推 / 没被推」结构化落库,
python main.py decisions可查;
夜间静默、额度用尽、大模型失败挡住的消息记为「延后未决」,拿到最终结论即自动更新。 - 测试数据模拟器:
python main.py simulate用虚构群聊回放生产同一条链路,离线、确定性(--seed)、
可导出 JSONL fixture。实测:500 条消息 → 过滤 377 + 去重 54 → 68 条要点 → 23 次通知 → 63 项待办。 - 26 秒脱敏演示:片子由代码渲染而非录屏,画面里的数字全部取自那次真实回放;输入全为虚构数据并逐帧带水印,可公开发布。
- 全链路诊断:
python main.py doctor一键检查 NapCat / OneBot / 群白名单 / 推送 / LLM / 访问层。 - 安全边界:数据流向与加固清单、依赖供应链核查、27 个安全回归用例并入 CI;
并处置了第三方安全审计(唯一真实缺陷是「缺 qq-botpy 时整个进程退出」,现已降级为单通道不可用)。 - 可贡献:CONTRIBUTING、Issue/PR 模板、FAQ、故障演练手册(
docs/DR-DRILL.md)、ROADMAP v1。
兼容性
- 无破坏性变更。
data/数据库增量迁移(新增decisions表),旧库可直接用。 - 未安装
qq-botpy时,仅「QQ 官方机器人」通道不可用,其余功能与整套测试照常运行。
测试
268 个用例通过;屏蔽 qq-botpy 时同样 268 通过(1 skip)。
完整改动:v0.1.0...v0.2.0
v0.1.0
首个公开版本:把 QQ 群里真正要紧的通知过滤、提炼后推到微信,并汇总成手机待办台。
功能
- NapCat / OneBot v11 只读接入,只处理
QQ_DIGEST_GROUPS白名单内的群(留空 = 不处理任何群) - 本地规则 + 可选大模型双层筛选:过滤闲聊,提取通知 / 待办 / 截止时间
- 推送通道:WxPusher / Server酱 / PushPlus / Webhook,失败自动回退
- 手机待办台 PWA:待确认卡片、完成 / 忽略 / 稍后提醒、截止提醒、每周复盘
- 群文件与截图解析:PDF / Word / Excel / PPT / zip,扫描版 PDF 走 OCR
- 跨群重复通知去重、失败重试与降级、夜间静默与推送预算
安全
- 附件下载仅允许 http(s),解析 DNS 后拒绝本机 / 内网 / 云元数据地址,重定向逐跳复检(SSRF 加固)
- 群白名单 fail-closed:未配置时不接收任何群
- 仓库与全部 Git 历史不含任何凭证,
pip-audit0 漏洞
环境
- Windows 10/11、Python 3.12+、NapCat(或兼容 OneBot v11 的实现)
- 至少一个推送通道;MIT License
验证
- 158 项单元测试通过;GitHub Actions(Windows + Python 3.12)绿色




