wechat_msg_clicker/project.md
2026-04-23 19:27:24 +08:00

131 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 项目规划WeChat 消息自动点击器
## 项目目标
创建一个长期稳定运行的自动化工具,自动点击微信桌面端中未读消息的图片和文件,触发微信下载原始文件到本地目录,配合信息收集系统完成数据入库流程。
## 项目状态
### 已完成 (v0.1.0 - 2026/04/22)
- [x] 项目结构搭建
- [x] 配置系统YAML 配置文件、默认值、白/黑名单)
- [x] AXUIElement 底层封装ax_bridge.py
- [x] 微信 UI 导航wechat_ui.py— 聊天列表解析、消息类型分类
- [x] UI 状态机state_machine.py— 基于窗口计数的状态检测与恢复
- [x] 拟人行为引擎human_like.py— 高斯分布延迟、长休息、工作时间
- [x] 主自动化逻辑automator.py— 完整扫描-点击-关闭循环
- [x] 入口脚本main.py— 参数解析、信号处理
- [x] 调试工具(--dump-ui, --dry-run
### v0.2.0 修复与增强 (2026/04/22)
- [x] **修复: 聊天项点击失败** — AXStaticText 无 AXPress 动作,改用 CGEvent 鼠标坐标点击
- [x] **修复: AXValue 位置解包** — get_position/get_size 改用 AXValueGetValue 正确提取 CGPoint/CGSize
- [x] **新增: 消息列表滚动** — 进入聊天后向上滚动 5 轮,加载更多历史媒体消息
- [x] **新增: 图片"使用预览打开"流程** — 点击大图 → 点"..." → "使用预览打开" → 关闭 Preview.app确保原始文件保存到本地
- [x] **新增: 文件直接点击下载** — 点击文件气泡触发微信下载
- [x] **新增: Preview.app 管理** — state_machine 添加检测与关闭 macOS Preview.app 的能力
- [x] **新增: 鼠标双击、滚轮滚动** — ax_bridge 扩展 CGEvent 操作
### v0.3.0 修复与调试增强 (2026/04/23)
- [x] **修复: 滚动误点击**`_scroll_at()` 原先用 mouseDown/mouseUp 聚焦导致误点侧边栏按钮,改用 kCGEventMouseMoved 仅移动鼠标不触发点击
- [x] **修复: 未跳转最新消息** — 进入聊天后先 `scroll_to_bottom()` 滚到消息列表底部(最新消息),再向上滚动加载历史
- [x] **修复: "..."按钮误匹配**`_find_more_button_in_preview()` 限制搜索范围,主窗口中只搜索 x>200 区域(排除左侧侧边栏),增加位置日志
- [x] **修复: 重复点击同一图片** — 用消息列表子元素索引(child index)做去重processed_indices 跟踪已处理元素,跨滚动轮次不重复
- [x] **修复: 裁剪图片点击无效** — 只处理完全在消息列表可见区域内的媒体(上下各 30px margin跳过部分被裁剪的元素
- [x] **增强: 全链路调试日志** — click_at_element 记录坐标/角色/标题get_media_messages 输出每个媒体详情find_menu_item 记录搜索过程,状态检测记录所有窗口标题
### v0.4.0 诊断工具与窗口恢复 (2026/04/23)
- [x] **新增: --dump-ui --chat 诊断工具**`python main.py --dump-ui --chat "聊天名"` 进入指定聊天,滚到底部,以 max_depth=10 dump 每个消息子元素的完整 AX 树含索引、position、actions、identifier用于诊断不同图片元素结构差异
- [x] **新增: dump_element 增强** — 输出 AXPosition、AXActions、AXIdentifier 字段
- [x] **新增: 微信窗口最小化自动恢复** — 新增 `WECHAT_MINIMIZED` 状态detect_state 区分"未运行"和"已最小化",通过 AppleScript 自动取消最小化并恢复前台
- [x] **增强: verify_setup 自动恢复** — 启动时找不到主窗口先尝试恢复最小化,再判断失败
### v0.5.0 图片点击与滚动修复 (2026/04/23)
- [x] **修复: 图片点击不生效(根本原因)** — AXStaticText 覆盖整行575px宽实际图片气泡仅在左侧 80~170px 区域。改用 `click_at_element_offset(x=120, y=height/2)` 命中实际缩略图区域(通过逐像素探测确认可点击边界)
- [x] **修复: 滚动方向反转** — macOS CGEvent ScrollWheel 正值=向上滚(看旧消息),负值=向下滚(看新消息)。`scroll_to_bottom` 从 +20 改为 -20历史加载滚动从 -10 改为 +10
- [x] **修复: 可见性判断过严** — 原先要求元素完全在可见区域内30px margin289px 高图片经常被判定裁剪。改为只检查元素**中心点**是否在可见区域内
- [x] **新增: click_at_element_offset** — ax_bridge 新增带偏移量的点击方法,文件/视频点击也使用偏移量
- [x] **已验证: 完整图片处理流程** — 蜗牛聊天 4 张不同尺寸图片289px、155px、180px全部成功缩略图→预览窗口→...按钮→使用预览打开→关闭 Preview→恢复
- [x] **已验证: 带滚动的媒体处理** — scroll_to_bottom 正确到达最新消息向上滚动正确加载历史去重正确processed_indices=[45,47,49,50]
### v0.6.0 最小化窗口恢复修复 (2026/04/23)
- [x] **修复: 最小化时恢复失败(根本原因)** — 原 AppleScript `tell application "WeChat"` 方案存在两个致命问题:(1) 微信的 localizedName 是"微信"不是"WeChat"AppleScript 找错应用或静默失败导致打开了别的窗口;(2) 微信不支持标准 AppleScript `miniaturized` 属性(返回 error -10006
- [x] **修复: 最小化检测遗漏** — 微信窗口最小化后 AXWindows 仍返回该窗口AXMinimized=True`detect_state``ensure_wechat_visible` 未检查此属性,误判窗口已可见
- [x] **改用 AX API 恢复窗口** — 通过 `AXUIElementSetAttributeValue(window, "AXMinimized", False)` 取消最小化,比 AppleScript 更可靠
- [x] **多策略窗口恢复** — unhideCmd+H隐藏→ AXMinimized=False最小化→ activate前台覆盖所有不可见场景
- [x] **恢复重试与验证**`ensure_wechat_visible` 增加 3 次重试循环,每次验证主窗口 AXMinimized=False 后才返回成功
- [x] **已验证** — 两次完整测试通过:最小化微信→运行 `--once --debug`→自动恢复→正常扫描处理
### v0.7.0 默认只点击图片 (2026/04/23)
- [x] **配置变更: click_files 默认关闭**`media.click_files` 默认值从 `true` 改为 `false`,默认只点击图片不点击文件。需要点击文件时在 config.yaml 中设置 `click_files: true`
### 待验证
- [x] ~~验证最小化窗口自动恢复功能(需手动最小化微信窗口测试)~~
- [ ] 有未读图片消息时的完整 --once 自动化流程
- [ ] 长时间运行稳定性测试
### 未来可能的改进
- [ ] 聊天列表滚动支持(处理不在可见区域的聊天)
- [ ] 已处理消息去重(记录已点击的媒体,避免重复)
- [ ] 微信版本适配(检测 UI 结构变化并自动调整)
- [ ] 运行状态 Web 面板(远程监控)
- [ ] 与信息收集系统直接集成
## 技术细节
### 微信 UI 结构 (v4.1.9)
- 主窗口 "微信" 包含侧边栏 + 聊天列表
- 聊天列表:`AXList name="会话"`,子元素为 `AXStaticText`(无 AXPress 动作)
- 聊天项 AXIdentifier 格式:`session_item_聊天名`
- AXStaticText 的 AXPosition/AXSize 需通过 AXValueGetValue 解包
- 点击聊天项打开独立会话窗口
- 消息列表:`AXList name="消息"`
- 图片消息 title = "图片",文件消息 title 以 "文件\n" 开头
### 点击策略
- 聊天项和消息元素均使用 CGEvent 鼠标坐标点击AXStaticText 不支持 AXPress
- 计算元素中心坐标 = position + size/2
- 图片预览中的按钮优先尝试 click_at_element后备 AXPress
### 图片下载流程
1. 点击图片缩略图 → 打开大图预览(微信内窗口)
2. 在预览窗口找到 "..." (更多) 按钮并点击
3. 在弹出菜单中找到 "使用'预览'打开" 并点击
4. 等待 macOS Preview.app 打开(此时原始文件已保存到本地)
5. 关闭 Preview.app 窗口
6. 回到微信,关闭大图预览
### 防封策略
- 高斯分布随机延迟(非均匀)
- ±20% 扫描间隔抖动
- 5% 概率长休息30-120 秒)
- 工作时间限制
- 每次最多 5 个聊天
### 依赖
- pyobjc-framework-Quartz
- pyobjc-framework-ApplicationServices
- pyobjc-framework-Cocoa
- PyYAML
### 系统要求
- macOS Sonoma 14+
- Python 3.11+
- 辅助功能权限(终端/Python 需要授权)
- 微信桌面端 v4.1.9+