Files
codex 8fe630f356 fix: 私信发送确认误判——用 is-me class + 今日时间截断取代宽泛选择器
问题:snapshot_last_own_message 用 [class*='message']/[class*='bubble'] 等宽泛
选择器扫全页并靠位置猜自己消息,抓到的是整个聊天区容器节点。导致
confirm_message_sent 永远比不上单条气泡文本,100% 误报失败,每条消息
纯浪费 ~80 秒空转 + 进入失败队列反复重试。

改动:
1. snapshot_last_own_message 完全重写——直接用抖音 DOM 结构:
   - 找所有 box-item- 行
   - 从底部往上扫 time- 时间分隔符,碰到 昨天/星期/2026- 就标记今日边界
   - 今日区域内从底部找第一个 is-me 行,从 <pre> 取文本
2. 新增 count_today_own_message_matches——只数今日 is-me 气泡里精确匹配
   指定文本的条数。用于发送前后增量比较,挡住手机并发发消息把最后一条
   顶掉导致主路径漏判的场景。
3. confirm_message_sent 加 count 兜底——主路径(最后一条自己消息==本次
   发送文本)未命中时,回退到 count 增量判断;超时前再兜底一次。
4. 保留 _detect_send_failure_indicator——轮询中一旦发现红色感叹号/
   重试按钮/发送失败文字立即判失败,不写 sentAt。

原文件备份:tasks.py.bak-20260624-snapshot-fix(容器内)
2026-06-25 10:04:55 +08:00
..
2026-05-29 18:00:47 +08:00

DouYinSparkFlow - 核心应用

抖音多账号火花自动维护系统 - 核心源码模块

这是 DouYin SparkFlow 的核心应用源码目录包含所有业务逻辑、Web 界面和自动化任务实现。


📁 目录结构

core/ - 核心功能模块

核心业务逻辑实现,包括浏览器自动化、消息发送、好友管理等。

文件 说明 大小
browser.py 浏览器控制和页面操作 3.4 KB
friends.py 好友列表管理和刷新逻辑 5.2 KB
login.py 登录流程控制 2.8 KB
msg_builder.py 消息内容构建(一言、祝福等) 4.5 KB
protocol_dispatch.py 协议分发和路由 9.7 KB
protocol_sender.mjs 消息发送协议Node.js 脚本) 21 KB
tasks.py 任务调度核心(定时任务、状态管理) 83 KB

webui/ - Web 管理界面

基于 FastAPI 的 Web 管理控制台,提供可视化操作界面。

后端模块

文件 说明
app.py FastAPI 主应用,路由定义
auth.py 用户认证和会话管理
login_sessions.py 登录会话生命周期管理
ops.py 操作接口(启动/停止任务、刷新好友等)

前端资源

webui/
├── static/              # 静态资源
│   ├── app.css         # 主题样式(亮色/暗色)
│   ├── app.js          # 主题切换脚本
│   ├── styles.css      # 基础样式
│   └── multiPagePlugins/  # 浏览器扩展插件
└── templates/          # HTML 模板
    ├── base.html       # 基础布局模板
    ├── dashboard.html  # 仪表盘(主界面)
    ├── login.html      # 登录页
    ├── login_workspace.html  # 登录工作区
    ├── accounts.html   # 账号管理
    ├── send_console.html  # 发送控制台
    ├── logs.html       # 日志查看
    └── settings.html   # 系统设置

utils/ - 工具模块

通用辅助功能和配置管理。

文件 说明
config.py 配置文件加载和管理
logger.py 日志系统配置
hitokoto.py 一言 API 接口封装
github_action_config.py GitHub Actions 配置生成

scripts/ - 辅助脚本

文件 说明
cron_runner.py Cron 任务运行器
start_login_desktop.sh 登录桌面启动脚本

docs/ - 文档和资源

文件/目录 说明
usage.md 详细使用教程(含截图)
images/ 界面截图和示意图

🚀 运行方式

开发环境运行

1. 安装依赖

# 核心依赖
pip install -r requirements.txt

# Web UI 依赖
pip install -r requirements-web.txt

# 安装 Playwright 浏览器
playwright install chromium

2. 启动方式

Web 管理模式(推荐):

python main.py --web
# 访问 http://localhost:8787

命令行模式

python main.py
# 直接运行任务调度

登录桌面服务

python login_desktop_server.py
# 启动登录桌面 API用于扫码登录

Docker 容器运行

参考根目录的 docker-compose.yml 配置:

# 构建镜像
docker build -f Dockerfile.server -t douyin-sparkflow:local .

# 运行容器
docker run -d \
  -p 8787:8787 \
  -v $(pwd):/app \
  douyin-sparkflow:local

⚙️ 配置文件

config.json - 应用配置

主配置文件,控制任务行为和系统设置。

{
  "send_window_start": "09:00",
  "send_window_end": "22:00",
  "send_interval_min": 300,
  "message_template": "hitokoto",
  "enable_send_confirm": true,
  "friend_refresh_interval": 3600,
  "browser_headless": false,
  "browser_timeout": 30000,
  "max_retry_count": 3,
  "cooldown_on_failure": 600
}

配置项说明

配置项 类型 默认值 说明
send_window_start string "09:00" 发送窗口开始时间
send_window_end string "22:00" 发送窗口结束时间
send_interval_min int 300 最小发送间隔(秒)
message_template string "hitokoto" 消息模板类型
enable_send_confirm bool true 是否启用发送确认
friend_refresh_interval int 3600 好友列表刷新间隔(秒)
browser_headless bool false 浏览器无头模式
browser_timeout int 30000 浏览器操作超时(毫秒)
max_retry_count int 3 失败重试次数
cooldown_on_failure int 600 失败后冷却时间(秒)

usersData.json - 用户数据

存储账号信息、好友列表、发送记录等运行时数据。

⚠️ 此文件包含敏感数据,不应提交到 Git 仓库

示例结构:

{
  "accounts": [
    {
      "id": "user_123",
      "nickname": "用户昵称",
      "friends": [...],
      "last_send_time": "2026-06-20T10:30:00",
      "send_history": [...]
    }
  ]
}

webui_settings.json - Web UI 设置

Web 管理界面的配置(管理员密码、端口等)。

⚠️ 此文件包含敏感数据,不应提交到 Git 仓库


🔌 API 接口

Web UI 提供以下 RESTful API 接口:

账号管理

  • GET /api/accounts - 获取账号列表
  • POST /api/accounts/refresh - 刷新好友列表
  • DELETE /api/accounts/{id} - 删除账号

任务控制

  • POST /api/tasks/start - 启动定时任务
  • POST /api/tasks/stop - 停止定时任务
  • GET /api/tasks/status - 获取任务状态

登录管理

  • GET /api/login/qrcode - 获取登录二维码
  • GET /api/login/status - 检查登录状态
  • POST /api/login/logout - 登出账号

消息发送

  • POST /api/send/manual - 手动发送消息
  • GET /api/send/history - 获取发送历史

详细 API 文档请查看 webui/app.py 中的路由定义。


🔧 核心工作流程

1. 登录流程

用户扫码 → browser.py 打开登录页
       → login.py 生成二维码
       → 用户扫码确认
       → 保存登录态到 state/
       → 返回登录成功

2. 好友列表刷新

触发刷新 → friends.py 启动浏览器
        → 访问好友列表页面
        → 解析好友数据(昵称、火花状态等)
        → 保存到 usersData.json
        → 关闭浏览器

3. 消息发送流程

定时触发 → tasks.py 检查发送条件
        → 筛选需要发送的好友
        → msg_builder.py 构建消息内容
        → protocol_sender.mjs 发送消息
        → 等待发送确认
        → 记录发送历史
        → 更新下次发送时间

4. 任务调度逻辑

tasks.py 是核心调度器,负责:

  • 定时检查发送窗口
  • 🔄 循环遍历所有账号
  • 📊 统计发送成功/失败
  • 🛡️ 失败保护(冷却机制)
  • 📝 日志记录

🐛 调试和开发

日志系统

日志文件位于 logs/ 目录:

logs/
├── app.log              # 应用主日志
├── webui.log           # Web UI 日志
├── tasks.log           # 任务调度日志
└── browser.log         # 浏览器操作日志

查看实时日志:

tail -f logs/app.log

开发建议

  1. 修改模板文件:编辑 webui/templates/*.html,刷新浏览器即可看到效果(自动重载已启用)
  2. 修改 Python 代码:需要重启服务才能生效
  3. 调试浏览器操作:设置 browser_headless: false 可以看到浏览器窗口
  4. 测试消息发送:使用 Web UI 的"手动发送"功能,避免等待定时任务

常见问题

Q: 登录二维码不显示?
A: 检查 login_desktop_server.py 是否正常运行,端口 18090 是否被占用。

Q: 浏览器启动失败?
A: 确保已安装 Playwrightplaywright install chromium

Q: 消息发送失败?
A: 检查网络连接,查看 logs/tasks.log 中的错误信息。

Q: Web UI 无法访问?
A: 检查端口 8787 是否被占用,防火墙是否允许该端口。


📦 依赖说明

requirements.txt - 核心依赖

playwright>=1.40.0      # 浏览器自动化
apscheduler>=3.10.0     # 任务调度

requirements-web.txt - Web 依赖

fastapi>=0.104.0        # Web 框架
uvicorn>=0.24.0         # ASGI 服务器
jinja2>=3.1.0           # 模板引擎

完整依赖列表请查看对应的 requirements*.txt 文件。


🔐 安全注意事项

敏感文件保护

以下文件绝对不要提交到 Git 仓库:

  • usersData.json - 包含账号数据和好友信息
  • webui_settings.json - 包含管理员密码
  • .env - 包含环境变量和密钥
  • state/ - 包含浏览器登录态
  • logs/ - 可能包含敏感日志
  • .im_sdk_cache/ - IM SDK 缓存

已在 .gitignore 中配置忽略这些文件。

密码安全

  • 修改 webui_settings.json 中的默认管理员密码
  • 不要在配置文件中明文存储密码
  • 使用环境变量管理敏感配置

📚 相关文档


🤝 贡献指南

欢迎提交代码改进和功能建议!

开发规范:

  • Python 代码遵循 PEP 8 规范
  • 提交前运行测试确保功能正常
  • 添加必要的代码注释
  • 更新相关文档

📄 许可证

MIT License - 详见 LICENSE 文件


返回 项目主页

Made with ❤️ by halfwaystudent