phoenixray2000
5e0eaa33fa
feat(export): 增加微信聊天增量 JSON 导出 ( #122 )
...
新增 export_all_chats --delta-only 按时间窗口导出每个会话的增量 JSON.
- --delta-only 写入 deltas/<run_id>/manifest.json + 有消息的会话文件, 便于后续按批次消费
- 沿用现有 CSV plan 选择逻辑, 可通过 --from-plan-csv 控制范围
- 空时间窗口会话直接跳过, 不再生成 message_count=0 的 delta 文件
- 增量 JSON 保留会话级 metadata, 不改变现有 CSV 导出默认流程
- manifest.json 只记录实际有消息的会话, 无法解析的留在 errors 中便于定位
测试: tests/test_export_all_chats_delta.py 7 个 case (run_id 时间戳形状 / 文件名安全化 / msg_uid 哈希组成 / 写窗口不覆盖全量 JSON / 空窗口跳过 / CLI 参数校验 / manifest 记录文件).
跟 #114 (CSV plan) 互补 — CSV plan 选 "哪些会话" 而 delta 选 "哪个时间窗口".
2026-05-29 13:18:53 +08:00
phoenixray2000
f3c32d4ca2
feat: 支持双模式 exe 入口
2026-05-19 02:21:57 +08:00
ylytdeng
9e38684bc6
revert: 恢复 tkinter app_gui.py, 改成 Web UI / 桌面 GUI 共存
...
## 用户反馈
上次 commit e826b1a "删除 tkinter, 完全切到 Web UI" 误解了用户意图。
用户原意是 "完全用 webUI, **用户可以选择**" → 指 Web UI 内部给用户
充分选择, 不是删 tkinter。
用户澄清: "我的意思是共存", 即两套 GUI 都保留, 用户按场景挑。
## 改动
### 恢复
- \`app_gui.py\` (939 行, 从 e826b1a^ restore, 含之前修的 --task bug fix)
### 保留 e826b1a 的合理部分 (不回滚)
- \`monitor_web.py\` 的 \`_start_monitor_if_ready\` 重构 (无 keys 仍能开
Web UI) - 这个 standalone 改进, 跟 GUI 选哪个无关, 保留
- \`WeChatDecrypt.spec\` 入口 \`monitor_web.py\` (Web UI 体验更好, 默认
打包它; 想打 tkinter exe 改 spec 那一行就行)
- \`build.bat\` 简化 (单一 source of truth = spec, 不重复 add-data 清单)
### README 改共存叙事
- Windows 快速开始拆 2 个 details:
- "Web UI (推荐, 跨平台 + 实时监听)"
- "桌面 GUI / EXE (tkinter, 适合不开浏览器的场景)"
- 文件清单 \`app_gui.py\` 那行回来, 说明跟 \`monitor_web.py\` 共存关系
- "GUI 工具箱" 章节重写: 先讲 Web UI 推荐路径 + 三 tab 能力, 再讲
桌面 GUI 备用场景 (公司机器禁浏览器 / 全离线 / 喜欢传统桌面应用),
最后讲打包 (默认 Web UI exe, 改 spec 可打 tkinter exe)
### EXE_USAGE.md 共存
- 结尾的 "为什么没 tkinter" 改成 "还有个 tkinter (备用)"
- 说明何时该用哪个 + 怎么打 tkinter 版 exe
## 实测
- app_gui.py syntax OK
- monitor_web.py syntax OK
- 测试 185/185 通过
2026-05-17 19:28:57 +08:00
ylytdeng
e826b1a565
refactor: 删除 tkinter app_gui.py, 完全切到 Web UI 作为唯一入口
...
## 决策背景
用户反馈 "windows GUI 太难看了, 还是完全用 webUI 吧, 用户可以选择"。
tkinter app_gui.py (PR #107 引入, 929 行) 的问题:
- 中文字体下渲染糊 ("WeChat Decrypt 工具箱" 标题模糊)
- 90 年代 Windows 控件风格, 不暗色不现代
- 只能跑 Windows, 不跨平台
- 没法远程访问
- 跟 Web UI 维护两套, 重复
Web UI (monitor_web.py) 已经完全对齐功能:
- 8 个工具按钮 (3 tab 分组: 个人微信 / 企微 / 工具)
- 终止按钮 + 实时日志推送
- 导出筛选模态框 (会话搜索/复选/格式选择, close #112 )
- 跟实时消息监听共享 SSE 通道
- Lucide SVG icon 统一风格 (无 emoji)
- 暗色主题 + design tokens + 玻璃质感顶栏
## 改动
### 删除
- \`app_gui.py\` (929 行 tkinter GUI)
### monitor_web.py
拆 \`main()\` → \`_start_monitor_if_ready()\` + 精简的 \`main()\`:
之前: keys 不存在 → \`sys.exit(1)\` 直接挂
现在: keys 不存在 → 跳过监听线程启动, 仅起 Web UI 服务。
用户从工具箱点 "① 提取密钥 + 解密数据库" 跑完后重启进程, 监听自动激活。
这样 exe 用户第一次双击时不会报错挂掉, 而是看到 Web UI 工具箱可以
直接用。
新启动流程: \`_start_monitor_if_ready\` 检查 keys 文件 / session.db
密钥 / session.db 路径都 OK 才启 monitor_thread, 任一不满足都给友好
提示但不退出。
### WeChatDecrypt.spec
- 入口 \`app_gui.py\` → \`monitor_web.py\`
- datas 清单补全 (加 export_all_chats / chat_export_helpers /
batch_decrypt_images / transcribe_chat 等之前漏的)
- hiddenimports 显式列 Crypto / zstandard / pilk (避免 PyInstaller
漏 detect)
### build.bat
- 删 30 行重复的 --add-data 清单 (跟 .spec 漂移风险)
- 改成 \`pyinstaller --noconfirm WeChatDecrypt.spec\`
- 单一 source of truth 是 .spec
- 完成提示从 "GUI 启动" 改成 "双击 → 浏览器开 Web UI"
### EXE_USAGE.md
完全重写为 Web UI 视角:
- 快速开始: 双击 exe → 浏览器自动打开
- 工具箱 3 tab 各自能力详解
- 导出筛选模态框使用说明
- 任务终止说明
- 输出目录布局
- 远程访问说明
- 结尾解释为什么去掉了 tkinter
### README.md
- 三平台 quick-start 里 "Windows GUI / EXE" → "Windows Web UI / EXE"
- 文件清单: \`app_gui.py\` 那行 → \`monitor_web.py\` (新身份: Web UI
总入口)
- 技术细节里 "GUI 工具箱" 章节重写: 强调 Web UI 优势 (筛选模态框 /
终止按钮 / 跨平台 / 远程访问 / 跟监听共存) + 末尾 1 句历史说明
解释 tkinter 已删除
## 实测
- python monitor_web.py: keys 在 → 正常启动监听 + Web UI
- python monitor_web.py: 假装 keys 不在 → 跳过监听, Web UI 仍能开,
用户从工具箱点 "① 提取密钥" 后重启即激活
- 测试 185/185 通过
## 没改 (留 follow-up)
- 实际打包 .spec 验证 (需要 Win 跑 pyinstaller, 没在 CI 跑)
- monitor_web 启动后**自动**检测 keys 文件 mtime 变化重启监听, 不需要
用户手动重启进程 (现在的设计是"重启进程才激活")
2026-05-17 19:22:47 +08:00
ylytdeng
e5e2269947
fix: PR #107 后续清理 (security/正确性/一致性)
...
针对 4 个 review agent 在 PR #107 (5649 行巨型 PR) 找到的关键问题做最小
侵入修复。已合并代码本身能跑,这次是收紧 security + 消重 + 文档一致性。
## 安全修复
### wxwork_keys.json 落盘权限 (find_wxwork_keys.py)
含明文 16-byte raw key 的 keys 文件,之前 default umask 落盘。改成:
1. 写 tmp 文件
2. chmod 0o600 (Unix 严格 owner-only; Windows 上 chmod 控制只读位,
至少避免世界可读最差情况)
3. atomic rename
旧产物自然过期,新生成的都受保护。
### SNS XXE 防护 (export_sns.py)
朋友圈 XML 来源是不可信输入(他人发的 content),原 `ET.fromstring()`
完全没过滤,可被恶意 entity expansion / 外部实体引用攻击。加跟
`mcp_server._XML_UNSAFE_RE` 同模式的过滤(拒 `<!DOCTYPE>` / `<!ENTITY>`)
+ 200KB 大小上限。`_parse_timeline_xml` 检查后才进 ET.fromstring。
## 正确性 / 消重
### AES 对齐公式统一 (decode_image.py + decrypt_sns.py + export_sns.py)
原本三处各写一份:
- decode_image.py: aes_size -= ~(~aes_size % 16) ← bitwise trick
- decrypt_sns.py: 同上
- export_sns.py: aes_size + (16 - aes_size%16) if … else aes_size+16
两个公式数学等价(对 0/1/15/16/17/100/1000/12345 全部验证一致),但
bitwise trick 难读且漂移风险高。抽 `aligned_aes_block_size()` 到
decode_image.py 作 canonical 实现, 另两处 import 复用。
### 32-bit pointer 假设明确化 (find_wxwork_keys.py)
reviewer 担心 `_read_u32` 在 64-bit 进程上错位,实测 WXWork.exe 5.0.x
是 **32-bit 进程** (`Program Files (x86)\WXWork\` + PE Machine = x86),
所以 4 字节读指针是对的。加注释明确这个假设,腾讯如果升级到 64-bit
要重做整套逆向, 当前实测全部 17 db 解密通过印证。
## 一致性
### main.py show_status() 走 _config_file_path() (main.py)
原硬编码 `config_file = "config.json"` 绕开 PR #107 新引入的
`_config_file_path()`,打包成 exe 后 cwd 不一定是 exe 目录,会读到错
位置。改成 `from config import _config_file_path`。
### EXE_USAGE.md 输出目录写错 (EXE_USAGE.md)
EXE_USAGE 说导出到 `export/`,代码实际 `output_base_dir = wechat_files/
<wxid>/`,联系人下还是 `messages.csv/html/json` 而不是
`message_0.db.csv`。修正成真实结构。
## 文档
README 加两段:
- 安全提示: keys 文件 chmod 0600 + 不要 commit 到 git
- 朋友圈 XML XXE 防护说明
## 测试
185/185 通过 (含已有 wxsqlite3 roundtrip + image v2 + msg types filter
+ pagination hint + chat export helpers 等)。
aligned_aes_block_size 单独验证跟旧公式等价(0/1/15/16/17/100/1000/12345)。
## 未跟进 (后续 follow-up issue)
- 3 处 V1/V2/XOR 解密代码完全重复(decode_image / decrypt_sns /
export_messages 各自实现)——抽出来工作量大,本次先抽 helper 不动
完整解密路径,后续单独 PR
- export_messages HTML base64 内联图片可能爆几 GB,应改成可选 flag
- SNS / wxwork export / batch_decrypt_images / voice_to_mp3 测试缺位
(0 个 test)
2026-05-17 17:00:20 +08:00
xincheng
ecc1cfca64
增加企业微信的解密
2026-05-17 06:24:08 +08:00
xincheng
a84698b9fc
Add GUI, packaging and export/voice tools
...
Introduce a tkinter GUI and tooling to produce a single executable and export/convert message data. Adds app_gui.py (GUI launcher that runs decrypt/export/voice subtasks), export_messages.py (export messages to CSV/HTML/JSON), voice_to_mp3.py (extract SILK_V3 voice blobs and convert to MP3 via pilk + ffmpeg), WeChatDecrypt.spec and build.bat (PyInstaller spec and convenience build script), and EXE_USAGE.md (usage for the standalone exe). Update config.py to detect the application base directory when packaged, update README.md to document the GUI and packaging flow, and add pilk/pyinstaller to requirements.txt. Also expand .gitignore with common IDE/build/temp patterns and add output/data directories to ignore. These changes enable one-file packaging and provide end-user tools for decrypting, exporting and converting audio.
2026-04-04 06:12:03 +08:00