Files
douyin-pc/docs/2026-09-06-20-09-daily-observability-and-worker-deletion.md

12 KiB
Raw Permalink Blame History

0.1.5:按日执行日志、UI 最近 2000 条与小号删除

用户问题与目标

0.1.4 已能收到通知并取得详情,但“正在监听通知”只表示循环处于等待状态。现场出现的通知实际已入库,随后因为触发者就是唯一执行小号自身而被安全规则跳过;任务表只展示真正创建的任务,因此界面看起来完全没有反应。

本次实现两项明确需求:

  1. 记录“推送 → 详情 → 规则 → 分配 → 任务 → 结果”的可观察执行过程,完整日志按天写文件,UI 仅保留最近 2000 条。
  2. 小号除切换归属外,可以删除。按用户确认的方案,删除浏览器和登录数据、从活动账号列表移除、取消待执行任务,但保留历史任务和日志。

没有增加远程日志服务、日志数据库或新的第三方依赖。日志是本机普通 UTF-8 文件,便于用户直接查看和备份。

每日日志设计

文件位置与保留

%LOCALAPPDATA%\DouyinAccounts\logs\YYYY-MM-DD.log
  • 以 Windows 电脑本地日期分文件;跨过本地午夜后的下一条记录会进入新文件。
  • 每条写入后 flush,减少异常退出时丢失的尾部记录。
  • UI 上限不会截断文件。
  • 不自动删除历史日期文件;由用户按自身磁盘和审计需求备份、归档或删除。
  • 旧版 activity.log 及其备份不迁移、不删除。旧版本没有记录的过程不能可靠补造,启动时只写数量摘要,不伪造旧执行日志。

格式示例使用本地账号名称、内部任务编号和脱敏标识:

2026-09-06 20:00:00.123 [INFO] [推送到达] 已收到推送,解析支持的通知 ID 大号=主号 服务号=20313 有效ID数=1
2026-09-06 20:00:00.456 [INFO] [详情入库] 详情已取得且所属身份一致 大号=主号 通知标识=N0123456789ab 事件=12 通知类型=点赞 目标数量=1
2026-09-06 20:00:00.457 [INFO] [任务跳过] 触发者就是执行小号自身,禁止关注自己或私信自己 大号=主号 小号=执行号 事件=12 目标=UID尾号 ***1234
2026-09-06 20:00:00.458 [INFO] [分配完成] 分配流程已完成;不代表动作已执行 大号=主号 小号=执行号 事件=12 生成任务数=0 跳过目标数=1

以上标识均为示例,不来自真实账号。

覆盖的业务阶段

src/account_engine.pysrc/account_store.py 现在记录:

  • 程序启动、历史数量摘要和正常退出;
  • 用户操作请求、完成和失败;
  • 账号创建、身份绑定、规则更新、归属变更;
  • 手动启动账号组、停止请求、浏览器和登录数据删除;
  • SDK 推送到达、有效 ID 数、重复推送去重;
  • 到期详情请求、返回数量、耗时、空详情延期及下次允许重试时间;
  • 详情身份/ID/业务码验证完成、通知类型、目标数量;
  • 规则未开启、类型未勾选、没有有效来源用户;
  • 没有已绑定小号时保留等待;相同等待原因和数量不会在每轮重复刷日志;
  • 组内轮询选定的小号;
  • 执行小号操作自己、目标为来源大号时的明确安全跳过原因;
  • 任务入队、动作类型和依赖;
  • 任务领取、开始执行、完成耗时、成功、明确失败、结果不确定;
  • 前置关注等待、取消依赖任务、程序中断转“待核对”、用户人工确认;
  • 监听正常但没有新通知时,每 60 秒记录一次心跳,包含本连接推送数、新增通知数、详情待重试数量和最近推送距今时间。

日志明确区分:

  • “详情入库”不是动作执行;
  • “分配完成”不是关注或私信成功;
  • 只有“任务结果:动作成功”才代表程序确认成功;
  • unknown/待核对 不自动重发,依赖动作继续等待人工确认。

日志失败与事务一致性

  • 日志目录不可创建、磁盘写入失败或权限异常时,程序业务不因日志失败崩溃;UI 显示错误,并说明当前只有内存中的最近 2000 条。
  • 文件恢复可写后,后续记录继续写入当天文件。失败期间缺失的文件记录不冒充已补写。
  • Store 事务中的日志先缓存,SQLite 提交成功后才落文件;回滚事务对应的日志丢弃,避免出现“数据库没成功、日志却说成功”。
  • 删除目录失败时,账号数据库记录保留,用户可排除文件占用后重试。

敏感数据边界

日志不保存:

  • Cookie、Authorization、Session、Token、msTokena_bogus、密码和密钥;
  • 私信正文或规则模板全文;
  • 原始 HTTP/SDK 请求参数、请求头、响应正文和完整 URL;
  • 完整通知 ID、目标 UID、平台资料 JSON。

通知 ID 使用 SHA-256 的 12 位稳定摘要,仅用于同一通知跨阶段关联;目标 UID 只显示最多最后四位;账号使用用户设置的本地名称。换行、控制字符和双向文本控制符会清理,防止伪造多条日志。任何传入 text/body/headers/params/result/profile 字段只记录为已隐藏。

UI:只展示最近 2000 条

“运行记录”页调整为:

  • 标签显示“运行记录(最近 2000 条)”;
  • 启动时从多个日期文件倒序读取,但不把完整历史全部加载进内存;最多恢复最后 2000 行;
  • Backend 只向 UI 推送新增行,不在每 300 毫秒快照中重复发送 2000 行;
  • QPlainTextEdit.maximumBlockCount=2000,超过后 Qt 自动移除最旧的显示行;
  • 默认自动滚动到最新记录,可关闭后查看旧行;
  • 提供“打开日志文件夹”按钮;
  • 日志文件错误直接显示在页首。

任务页此前只展示最近 500 条,现一并改为最近 2000 条。SQLite 任务记录没有因 UI 上限而删除;已删除小号的历史任务仍显示原本地名称并标注“已删除”。

小号删除语义

用户流程

  1. 先停止小号所属组,等待在途动作结束。
  2. 在账号页选中小号,点击“删除小号”。
  3. 阅读二次确认框;默认按钮为“否”。
  4. 确认后程序关闭该小号浏览器,再删除其独立 profile 目录。
  5. 文件删除成功后,数据库在一个事务中取消待执行任务、清除身份和资料,并将小号从活动列表移除。

大号不提供该操作。“删除登录数据”仍维持原语义:清空浏览器登录目录,但不删除账号、不解除 UID 绑定。

安全限制

  • 小号本身或所属大号组仍在运行时拒绝删除。
  • running 任务时拒绝删除。
  • pending 任务改为 cancelled,原因明确为“小号已删除”,不改派到其他小号,也不重发。
  • unknown、succeeded、failed、cancelled 等历史任务均保留。
  • 历史日志不删除。
  • 数据库保留最小软删除行供外键和历史名称引用:deleted=1,UID 置空,owner 置空,昵称/头像/profile 清空,规则重置关闭,浏览器配置设置删除。
  • 账号查询、分配和 UI 活动列表排除软删除行。
  • UID 唯一约束因此释放,同一个抖音 UID 可以作为全新小号重新添加;获得新的内部 ID、随机端口、固定指纹种子和独立空白登录目录,不复用旧 Cookie。
  • 只调用 BrowserManager.erase(该小号 ID),路径仍经过根目录约束;不会删除兄弟账号或大号目录。
  • 如果浏览器/文件被占用导致目录删除失败,删除流程停止,账号仍在列表,可重试。

数据库迁移

0.1.5 在 accounts 表缺少该字段时执行:

ALTER TABLE accounts ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0;

所有旧账号默认 deleted=0。已有账号、绑定、归属、任务、通知和登录目录保持不变。删除小号不会物理删除账号行,因为历史 tasks 通过外键引用它。

自动化验证

Linux 与 Windows pytest

完整测试套件:61 项通过。新增测试包括:

  • 单日日志超过 2500 行时文件完整、UI/内存只保留最近 2000 行;
  • 跨日本地日期创建两个文件,重启恢复最后 2000 行;
  • UI 增量追加并始终限制 2000 个 block;
  • 自动滚动开关和删除二次确认默认取消;
  • URL、token、authorization、正文、复杂头部和控制字符不进入日志;
  • 日志目录不可写时只发一次明确错误,恢复后继续写;
  • SQLite 回滚不写成功日志;
  • 通知接收、去重、详情延期、规则匹配、无目标、无小号、自操作跳过、任务入队、执行、unknown、依赖等待、人工核对与成功结果阶段;
  • 相同等待条件不在循环内重复刷屏;
  • 任务 UI 查询仅返回最新 2000 条,数据库保留 2101 条;
  • 删除执行中的小号被拒绝;删除取消 pending、保留 unknown 与历史;
  • 删除清空 UID/profile/browser settings,活动列表隐藏,历史名称保留并标记;
  • 删除后同 UID 可以重新添加;
  • 旧库增加 deleted 字段且数据保持;
  • 模拟目录删除失败时账号和目录保留;
  • 引擎关闭已连接浏览器后才删除,兄弟账号文件不受影响。

Windows fingerprint-chromium 矩阵

真实离线 fingerprint-chromium/Patchright 矩阵全部通过,新增:

worker_delete_closes_owned_browser_erases_profile_preserves_history_and_siblings

该检查在临时目录中:启动一个测试小号浏览器、创建待执行任务、调用产品的 delete_worker、确认浏览器进程退出和 profile 目录消失、任务转 cancelled、主号及另外两个测试浏览器仍运行、历史名称仍可读取、同 UID 可重新添加。随后显式关闭剩余测试浏览器并确认所有临时进程退出。

原有矩阵继续覆盖:浏览器二进制锁定、目录/端口隔离、固定种子、Patchright 主上下文、通知 SDK 原生详情请求和 64 位 ID、登录回填、重连、错误身份拒绝、安全清理等。报告中的真实写动作计数为 0。

构建和发布校验

  • 8 个修改相关文件和 follow_user.py 的主 Python LSP0 error。
  • Windows 0.1.5 构建成功。
  • 打包后 GUI smokeQt、core、SQLite、Patchright、浏览器路径全部通过;使用空白临时目录,accounts=0real_write_actions=0。
  • 本地全部 23 个 Python 源文件 SHA256 与 Windows build-manifest.json 一致。
  • Python 3.12.10、fingerprint-chromium 148.0.7778.215、Patchright 1.62.3 等现有锁定运行时不变;没有新增依赖。

本地复测:

python -m pip install -r requirements-test.txt
python -m pytest -q

Windows 浏览器矩阵和构建:

.venv\Scripts\python.exe src\test_browser_matrix.py --chrome .build-cache\fingerprint-runtime\chrome.exe --report browser-matrix-activity-delete.json
.venv\Scripts\python.exe build_windows.py

空白 Windows 环境安装与构建说明仍见 docs/2026-09-06-12-35-windows-install-build-guide.md

发布

C:\Users\rogee\Desktop\抖音账号助手-0.1.5\
  DouyinAccounts-0.1.5-Windows-x64-Setup.exe
  SHA256SUMS.txt
  使用说明.txt
  • 安装包大小:222,654,258 字节。
  • SHA256fdce1e988a94f1a9328dac848581a4dd36aabe6c12aca3a82908fe1fc3f9f105
  • 桌面发布副本已重新计算并核对哈希。
  • 构建记录:tests-activity-delete.logbrowser-matrix-activity-delete.jsonbuild-activity-delete.log.build-cache/smoke-packaged.jsondist/DouyinAccounts/build-manifest.json

未代用户安装 0.1.5,也没有用真实账号做删除测试。发布时实际任务表为空;实际账号、浏览器和登录目录未因构建/测试而删除。退出旧程序后覆盖安装即可迁移,业务仍需用户手动启动。首次验收建议先查看“运行记录”是否出现启动摘要,再用第三个账号触发点赞/评论,观察每个阶段;删除功能建议先用可重新登录的测试小号验收。