13 KiB
Windows 多账号桌面应用:实现、验证与交付记录
1. 交付结论与边界
基准:2026-09-06-11-05-PLAN.md;业务决策:2026-09-06-11-24-implementation-decisions.md。
已实现并构建 Windows x64 0.1.0 初版,仅向指定 Windows 机器发布。最终交付是一个中文安装程序,包含 Python、Qt/PySide6、Playwright 及其 Node 驱动、psutil、Chrome for Testing。普通使用者无需安装开发工具或下载运行环境。
没有执行产品安装程序,也没有自动登录、关注、私信或标记通知已读。 安装/卸载/覆盖升级的人工体验、多真实账号组合及真实写操作验收,仍由用户完成。不能将离线矩阵或只读线上验证表述为真实写操作已经验收。
Windows 桌面发布位置:
C:\Users\rogee\Desktop\抖音账号助手-0.1.0\
DouyinAccounts-0.1.0-Windows-x64-Setup.exe
SHA256SUMS.txt
使用说明.txt
安装程序:234,266,549 字节(约 223.4 MiB)。
SHA256 bdbfb8a642092eb5775a94ca47b153d37a96e3819b74582b0633e0450e1a188f
目前未购买代码签名证书,可能出现未知发布者/SmartScreen 提示;不要以关闭系统防护作为安装步骤。
2. 已确认的业务语义
- 规则在界面配置,默认关闭;配置通知类型、关注/私信、正文及关注成功后再私信。
- 一条通知交给一个关联小号,组内轮询。不向所有小号广播。一条聚合通知内的多个有效来源用户,各产生相应步骤。
- 小号最多归属一个大号。切换/解除时,在同一 SQLite 事务中检查执行中任务、取消旧组待执行任务并更新归属。
- 执行中禁止切换;历史与 unknown 结果保留,不改派、不重发,不变更登录目录。
- 小号失效时原任务等待;大号失效或监听连接不可用时整组暂停。
- 停止只暂停领取和监听,并等待在途请求落库;保留 Chrome。关闭浏览器和删除登录数据是独立操作。
- 保存上次启动所选组;软件打开不自动执行,用户需再次点击启动。
- 修改规则不改写已有任务快照;关闭规则会暂停该组待执行任务。
3. 代码与实现落点
| 文件 | 职责 |
|---|---|
src/account_browser.py |
独立目录/进程/端口;全局与单账号配置;官方 Chrome 优先、随包浏览器兜底;进程创建时间、命令行、CDP 监听归属验证;旧实例安全关闭;账号目录删除;单实例锁与目录权限 |
src/account_session.py |
显式 loopback CDP 与期望 UID;唯一首页/自身页选择;实时自身身份核验;SDK 订阅及释放;通知详情;关注写前检查和写后核对;IM SDK 调用 |
src/account_store.py |
SQLite WAL/事务/外键;账号与规则;推送 ID inbox;事件去重;组内轮询;持久化任务、依赖与状态迁移;归属事务;unknown 人工确认 |
src/account_engine.py |
单 asyncio 循环拥有运行状态与数据库连接;按账号监听/串行执行;组级暂停;重连恢复;停止等待;结果落库;脱敏滚动日志 |
src/accounts_app.py |
PySide6 中文窗口;大号分组与小号;头像、昵称、UID、登录/身份/运行状态;规则、切换、设置、关闭、删除;任务状态及全库计数;独立后台线程;安全退出;离线冒烟入口 |
src/cdp_explicit.py |
独立脚本兼容传输层,要求明确 CDP 地址和期望 UID;不使用全局首个标签,不依赖 browser-harness |
src/accounts_cli.py |
打包后的 CLI 调度入口 |
src/test_accounts.py |
离线存储/身份/组隔离/时序/结果分类测试 |
src/test_browser_matrix.py |
真 Chrome、假站点数据的进程/CDP/存储/生命周期矩阵 |
build_windows.py / installer.iss |
Windows 原生 onedir、浏览器校验与收集、许可与清单、打包冒烟、中文单文件安装包 |
现有 get_current_user.py、get_notifications.py、follow_user.py、douyin_im.py、verify_notification_mark_read.py 均接入显式 CDP 参数;订阅内部模块复用同一传输层。现有 CLI 仍可独立运行。订阅支持 --sub 和 --subscribe。
安全与持久化细节
- 账号目录以随机内部 ID 命名,不以昵称、UID 或固定测试环境命名。不同浏览器可执行路径使用不同目录,不迁移 Cookie。
- 只连接
http://127.0.0.1:端口/ localhost / IPv6 loopback;浏览器实际监听与进程归属也核验。 - 高级参数使用小型允许列表;禁止覆盖端口、user-data-dir、关闭 web security/sandbox、加载扩展等破坏隔离的参数。
- 重启时 running → unknown,绝不重发。关注超时尝试只读核对;无法确认仍 unknown。IM 缺失或不明确结果不按成功处理。
- 私信任务可依赖前置关注。前置失败取消依赖任务;前置 unknown 等人工确认,不自行推进。
- 小号在身份异步核验期间切换归属的竞态已加校验与专门回归测试。
- 通知详情读取原始文本后由 Python 解 JSON,避免 JavaScript 丢失 64 位数字 ID 精度。
- 日志仅保留内部账号 ID、任务 ID、动作、状态及安全错误;不记录消息正文、Cookie、token、签名 URL 或原始请求。
- Windows 数据目录移除继承权限,授予当前用户与 SYSTEM;其他平台设为 0700。
- 安装目录与数据目录分开。卸载脚本没有删除账号数据的逻辑;实际卸载体验仍待人工验证。
4. 自动验证证据
Linux 开发环境
uv venv .venv
uv pip install --python .venv/bin/python -r requirements-desktop.txt
uv tool run pyright --project pyrightconfig.json \
src/account_store.py src/account_browser.py src/account_session.py \
src/account_engine.py src/accounts_app.py src/accounts_cli.py \
src/cdp_explicit.py src/test_accounts.py src/test_browser_matrix.py
.venv/bin/python -m unittest discover -s src -v
.venv/bin/python src/test_subscribe_notifications.py
QT_QPA_PLATFORM=offscreen .venv/bin/python src/accounts_app.py --smoke-test /tmp/douyin-linux-smoke-final.json
.venv/bin/python src/accounts_cli.py notifications --help
结果:配置化 Pyright 0 error / 0 warning;22 项 unittest 通过;既有 Node SDK/通知桥检查通过;Qt/SQLite/Playwright 核心冒烟通过;CLI 帮助转发正确。
附加编辑器 LSP 曾持续误报 PySide6 与新同目录模块无法导入。已记录为环境/缓存误报;未以关闭实际类型检查代替验证。独立配置化 Pyright、Python 导入、Windows 打包执行均验证通过。部分辅助导入行保留窄范围 Pyright 缓存兼容注释。
Windows 原生源代码测试
构建工作目录:C:\Users\rogee\douyin-pc-build-20260906。
- Python 3.12 x64 原生构建。
- 同一 22 项 unittest 通过。
- SDK/订阅桥检查通过。
- 不启动业务、不创建真实账号的 GUI 源码冒烟通过。
Windows 真 Chrome 离线矩阵
使用随包 Chrome,而不是本机已登录浏览器;每次创建临时独立目录。所有 Douyin 页面/API 由 Playwright 路由返回固定假数据;浏览器首次 URL 也替换为 about:blank,零真实写操作。
通过项:
- 两个账号不同端口;
- 同一运行实例可核验并重连;
- 可在不依赖登录状态的情况下核验旧实例;
- 旧浏览器运行时配置变化被拒绝;
- 两个上下文的 UID 与 localStorage 隔离;
- 错误 UID 拒绝;
- 多个匹配标签拒绝;
- 浏览器运行时禁止删除登录目录;
- CDP 断开保留 Chrome;
- 页面刷新后重新核验;
- 关闭、重启 Chrome 后 localStorage 保留;
- 只关闭自有实例,退出后能删除自己的目录。
测试中发现并修复了测试路由回调参数绑定、跨 CDP 连接关闭标签事件到达的时序,以及测试异常清理问题。最终矩阵全部通过,未将失败尝试记作成功。最终复查没有遗留 douyin-browser-test-* Chrome 进程。
Windows 打包验证
- GUI onedir、CLI onedir 均原生 PyInstaller 构建成功;
- 已收集 Python DLL、Qt DLL/plugins、Playwright Node 驱动、VC runtime DLL 和浏览器目录;
- 打包 GUI 的 Qt/核心/SQLite/Playwright 冒烟通过,accounts=0、real_write_actions=0;
- 打包 CLI
--help通过; - 在 Windows 真实打包目录上,清空环境变量并模拟 frozen 入口,浏览器查找函数成功返回随包 Chrome(
bundled-discovery-check.json);这是函数级检查,不冒充干净机器整包验收; - 中文与空格路径下,限制 PATH、设置无效外部 PYTHONHOME / PLAYWRIGHT_BROWSERS_PATH 的冒烟通过;
- 所有 20 个 Python 源文件的本地 SHA256 与 Windows 发布清单一致;
- Inno Setup 生成中文安装包成功,桌面副本 SHA256 与构建产物一致。
限制:不是重装的干净 Windows。 另做了两次通过环境变量隐藏系统 Chrome 的尝试,但程序仍选中系统 Chrome,未通过“实际走自动浏览器兜底”的该项断言,因此不将它记作空白系统测试通过。随包 Chrome 的真实运行已由上述离线矩阵独立验证;无系统 Chrome 的完整安装验收仍留给用户/干净虚拟机。
5. 线上只读验证
通过原有 localhost:9222 已登录浏览器开展,先使用 browser-harness 确认唯一自身页与真实登录。随后测试生产原生 CDP 接入:
- 期望 UID 与自身接口返回一致;
- 原生 Session 连接成功,官方网页通知 SDK 监听安装与卸载成功;
- 读取 10 条通知成功;
- 按一条通知 ID 读取详情成功;
- 验证评论、点赞通知的来源用户字段形态;
- 全程 0 次关注、0 次私信、0 次标记已读。
未保存 UID、通知 ID、用户名、消息正文到本仓库验证文档;临时身份文件用 0600 并在结束时清理。
6. Windows 交付与构建依赖来源
优先检查 Windows MCP(可用),构建/批量命令使用 SSH,符合 ../windows/AGENTS.md。未把连接账号/地址写入运行时配置或安装包。
运行时锁定:
- Playwright 1.55.0;PySide6/shiboken6/Essentials/Addons 6.9.2;psutil 7.0.0;
- greenlet 3.5.5;pyee 13.0.1;typing_extensions 4.16.0;
- Chrome for Testing 152.0.7977.82,官方 Google 分发,锁文件见
packaging/chrome-lock.json。
构建:PyInstaller 6.15.0、hooks-contrib 2026.7;其余版本见 requirements-build-windows.txt。
Inno Setup 6.7.3 从官方 jrsoftware/issrc GitHub release 下载;初始网站跳转所得文件未通过签名检查,未执行。正式 release 文件通过 Authenticode Valid 检查,发布者为 Pyrsys B.V.;再与 GitHub asset digest 核对,才安装构建工具。
https://github.com/jrsoftware/issrc/releases/download/is-6_7_3/innosetup-6.7.3.exe
SHA256 9c73c3bae7ed48d44112a0f48e66742c00090bdb5bef71d9d3c056c66e97b732
中文语言文件从官方仓库取得,保留版权/译者头:
https://raw.githubusercontent.com/jrsoftware/issrc/refs/heads/main/Files/Languages/ChineseSimplified.isl
SHA256 e0b0b350e2245f3c5e65586dfe43d574f6e7f06f2261149aba284954b3fc9a8d
语言文件摘要以本地文件 sha256sum packaging/ChineseSimplified.isl 为最终校验依据;源文件已随仓库保存,无需构建时再抓取最新翻译。
7. 未完成人工验收与已知限制
- 多个真实大号/小号组合的登录、身份异常、SDK 账号兼容性和实际写请求;目前多账号矩阵使用假身份。
- 安装、卸载、覆盖升级、SmartScreen、低权限/磁盘不足/杀毒误报等安装体验。
- 完全无系统 Chrome、无预装开发/运行环境的干净 Windows 安装测试。
- 用户必须先知道数字 UID;尚未提供“仅扫码即登记”的首次账号引导。
- 页面刷新/断网期间尚未写入 inbox 的推送可能丢失;已写入的 ID 会恢复补取详情。没有宣称零丢事件或全历史自动回补。
- SDK 内部对象仍依赖平台实现;结构变化会暂停,而不是绕过身份核验或盲目发送。
- 本版同一 UID 只能登记一次。任务界面显示最近 500 条,计数覆盖数据库全部任务。
- CLI 与桌面应用不应同时对同一账号进行写操作;CLI 不加入桌面的队列事务。
- 数据保存在本机,不做跨 Windows 用户的 Cookie 解密迁移。后续数据库结构变更需要另写迁移,不代表任意未来版本都已验证兼容。
8. 过程状态
开始分支 main,基准提交 2389d9c7b68e85bc3d3fdba481be8f0066375ba5,初始工作区干净。先尝试后台开发/审查工作流,但 pi 安装缺少后台 server/client 依赖,工作流 6d397511-d446-4cba-8033-793199c7b315 未能启动子任务,未产生代码。已向用户报告并获得“当前会话直接完成”的明确许可,之后未切换到其他外部代理。
最终代码未经 git commit;保留全部改动供用户审阅。没有伪称独立子代理审查成功。本文件记录自审、自动化测试及实际发布证据。