7.8 KiB
0.1.3:单条通知详情为空导致整组暂停
后续修正(0.1.4):本次只修好了整组阻塞,未解决空详情的根因。同一批 ID 经网页原生请求函数可以取得完整详情;原有简化请求没有使用站点完整请求上下文。详见 0.1.4 调研与验证。
现场现象与安全操作
用户反馈正在运行的 Windows 程序中,大号持续提示:
整组暂停,5 秒后复查;通知详情暂不可用,ID 已保存。
排查对象为 Windows 0.1.2 实际运行实例,不是单纯依靠模拟推断。优先使用 Windows MCP 查看程序并操作“停止全部”,日志和数据库通过 SSH 只读检查。
现场确认:
- 大号身份核验成功后才出现详情异常;
inbox有 1 条 pending ID;- 大号规则启用了关注和私信,但实际任务表为空;
- 为避免排查过程中恢复接口后误触发动作,先暂停两个账号的业务,保留浏览器登录;未关闭规则、未删除通知、未更改账号归属。
通过独立命名的 browser-harness 会话、仅监听本机的临时 SSH CDP 转发访问该浏览器,未导航到他人主页,未自动登录。诊断结束已关闭临时转发,不关闭用户浏览器。
只读请求证据
- 自身资料接口成功,返回 UID 与该大号既有绑定相符。
- 对 pending ID 请求通知详情,使用当前程序的
type=0,并用type=328对照:两次都是 HTTP 200、status_code=0,但:
{"notice_list_v2": null, "status_code": 0}
- 同账号通知列表接口正常返回 10 条,所属身份均正确。该 pending ID 不在本次返回的 10 条中。
- 从这 10 条里选择一个同账号的正常 ID,请求详情可返回 1 条。
全部请求使用 is_mark_read=0。没有执行关注、私信或标记已读。
当时的证据只能证明简化请求对部分 ID 返回空,不足以证明这些通知本身不可用;尚未与网页原生请求层对照,判断不充分。不能因此断言通知已删除或上游暂未生成。0.1.4 已补做同 ID 请求对照和新增点赞/评论验证。日志和本文不保存真实 UID、通知 ID、昵称、消息正文、Cookie 或签名参数。
整组暂停的直接原因(不是空详情的根因)
原 Session.details() 将下列情况都视为整体故障:
- 成功响应但
notice_list_v2=null; - 空列表;
- 一批 ID 中只返回部分详情。
Engine.main_loop() 每轮优先读 pending ID,遇到上述错误便清除 ready 状态、暂停整组、拆除监听并重连。因为该 ID 持续 pending,重连又立即请求同一 ID,形成反复暂停。一个不可用 ID 也会阻挡同一批中已经可用的详情及后续新通知。
修复
1. 区分单 ID 缺失与真正故障
src/account_session.py:
- HTTP 成功、业务码为 0 且有列表字段时,null 按空列表处理;允许返回请求 ID 的有效子集。
- 缺失 ID 交给调度层单独重试,不把它解释为身份失效。
- HTTP/业务错误、非法 JSON、列表字段缺失或格式异常仍报错。
- 返回其他身份的通知或未请求的 ID 仍拒绝,不能以容错为由放宽身份隔离。
- 继续在 Python 中解析响应,保留 64 位 ID 精度。
- 详情 API 错误显示安全的业务码,不打印原始响应或敏感参数。
2. 每个 ID 持久化退避
src/account_store.py 的 inbox 新增:
retry_count INTEGER NOT NULL DEFAULT 0
next_retry_at REAL NOT NULL DEFAULT 0
首次启动旧库时仅通过事务内的 ALTER TABLE ADD COLUMN 补齐字段,保留所有旧 ID、状态和其他业务数据。
- 到期 ID 按
next_retry_at, rowid排序,每批最多 20 个。 - 某 ID 缺失时保留 pending,延迟依次为 30、60、120、240、300 秒,此后上限 300 秒。
- 新 ID 初始时间为 0,可优先进入可执行批次;重连和重复推送不会重置旧 ID 的退避时间。
- 已成功入库的 ID 保持 done,不重复生成任务。
- 暂不自动丢弃长期不可用 ID,避免未经确认地丢通知。若未来积累量较大,再增加明确的人工丢弃/保留期策略。
这里是最早允许重试的时间,实际发起时机还取决于主循环、网络和其他请求,不是精确计时器。
3. 监听保持可用
src/account_engine.py 新增 collect_details():
- 只请求到期批次;
- 将已返回且通过校验的详情正常入库;
- 仅将缺失 ID 延期;
- 继续接收新推送与分配正常通知,不拆除健康的 SDK 监听。
界面可显示:
正在监听通知(1 条详情待重试,不阻塞新通知)
真正的接口故障、身份异常或连接异常仍沿用整组暂停策略。关注/私信的 unknown 防重发、账号归属事务、固定指纹种子及 Patchright 接入均未改变。
验证
自动化测试
Linux 与 Windows 的完整 pytest 均 51 项通过;配置化 Pyright 0 error / 0 warning,5 个修改相关文件的 LSP 错误检查通过。
本次新增回归测试覆盖:
- null、空列表、部分列表是可恢复的单 ID 缺失;
- 业务错误、格式异常、外账号和未请求 ID 仍失败关闭;
- 部分响应只入库可用记录,只延期缺失记录;
- 延期在数据库重开后保留,新通知不会被旧 ID 拖住;
- 重试上限为 300 秒且不删除 ID;
- 旧 inbox 结构升级不丢 pending ID;
- 一条详情不可用后,监听仍 ready,下一条推送能入库,仅安装/清理一次监听,不发生故障重连。
.venv/bin/python -m pytest -q
uv tool run pyright --project pyrightconfig.json \
src/account_session.py src/account_store.py src/account_engine.py src/test_accounts.py
实际账号、只读接口验证修复
修复代码在 Windows 通过 Patchright 接入原浏览器,只执行 GET 读取;调度与入库全部放在随用随删的临时数据库中,不调用业务启动方法。
同批请求现场不可用 ID 和一个正常对照 ID,得到:
{
"identity_verified": true,
"pending_detail_count": 1,
"missing_retained": 1,
"available_control_processed": true,
"retry_not_immediate": true,
"real_database_unchanged": true,
"real_write_actions": 0
}
实际运行数据库以 mode=ro 打开,并核对验证前后的 inbox/任务记录相同。没有使用真实账户验证关注或私信。
Windows 构建与浏览器矩阵
- 51 项 Windows pytest 通过;
- 原有真实 fingerprint-chromium 离线矩阵通过,包括端口/目录隔离、固定种子、webdriver false、Patchright SDK 主上下文、登录回填、重启持久化及安全删除;
- GUI/CLI 打包冒烟及中文安装包构建成功;
- 本地全部 21 个 Python 文件摘要与 Windows 发布清单一致;
- 浏览器和运行依赖版本保持 0.1.2 已锁定的版本,不改变账号登录目录策略。
发布与当前运行状态
已发布到:
C:\Users\rogee\Desktop\抖音账号助手-0.1.3\
DouyinAccounts-0.1.3-Windows-x64-Setup.exe
SHA256SUMS.txt
使用说明.txt
SHA256 1fd9c548584d44a47938b5c45f323f52f72f1df0119a8580ed1d6999e9776825
未代用户安装、修改正在运行的安装目录,或恢复实际关注/私信任务。现场程序保持暂停,浏览器保留;启用规则也保留。用户退出旧程序、覆盖安装 0.1.3 后可自行启动选中组,随后会按原有规则处理通知。
Windows 工作目录 C:\Users\rogee\douyin-pc-build-20260906 的验证记录:
tests-detail-retry.logbrowser-matrix-detail-retry.jsonbuild-detail-retry.log.build-cache\smoke-packaged.jsondist\DouyinAccounts\build-manifest.jsonrelease\SHA256SUMS.txt
本次仍只发布完整 Windows 安装包,安装体验由用户验收。所有源代码改动保持未提交状态。