Belugary
c29e8dd868
fix: ImageResolver 支持微信 4.0+ V2 加密图片格式 ( #61 )
...
ImageResolver.decode_image 之前只调 xor_decrypt_file(老格式 XOR-only
路径),微信 4.0+(2025-08+)已经改用 V2 AES-128-ECB + XOR 混合加密,
导致 mcp_server.py 注册的 decode_image MCP 工具对 V2 .dat 文件返回的
"解密"内容是错的——Claude AI 通过 MCP 调用看不到 V2 时代的图片。
monitor_web.py 早已正确处理 V2(line 41-42, 791-795:从 _cfg 读
image_aes_key / image_xor_key 后调 decrypt_dat_file 自动 magic 分发),
本次把 MCP 路径补齐,行为与 monitor_web.py 对齐。
改动:
- ImageResolver.__init__ 增加 aes_key=None, xor_key=0x88 关键字参数
(默认值保持向后兼容,老调用方无需改动)
- ImageResolver.decode_image 把 xor_decrypt_file 换成 decrypt_dat_file,
按 magic 自动分发 V2 / V1 / 老 XOR
- V2 文件 + 缺 aes_key 时早期返回结构化错误信息,避免在 v2_decrypt_file
内静默失败成笼统的"解密失败"
- v2_decrypt_file 入口接受 xor_key 字符串形式(int(_, 0) 解析),
与 aes_key 已有的 str→bytes 处理对称,允许 config.json 写 "0x88"
- mcp_server.py 实例化时从 _cfg 读 image_aes_key / image_xor_key 注入
兼容性:
- ImageResolver 老调用方(不传 keys)继续走老 XOR 路径,零 breaking
- V1 magic(\x07\x08V1)不会被 is_v2_format 拦截,走 decrypt_dat_file
内置固定 key,所以 aes_key=None 也能解 V1 文件
- 整 repo 只有 mcp_server.py 一处生产调用 ImageResolver(...),已 grep 确认
测试覆盖(11 个新测试,tests/test_decode_image_v2.py):
- v2_decrypt_file 合成数据 round-trip 字节级相等
- decrypt_dat_file 按 magic 自动分发 V2 / V1 / 老 XOR 三条路径
- aes_key 接受 str(来自 config.json)和 bytes 两种形式
- xor_key 接受 str(如 "0x88")和 int 两种形式
- V2 wxgf 裸流返回 fmt='hevc'(HEVC→JPEG 转换是 monitor_web 职责,
不在 ImageResolver 内做,保留 .hevc 输出)
- ImageResolver 端到端:from local_id to decrypted file
- ImageResolver(aes_key=None) + V1 文件走固定 key 路径
- ImageResolver(aes_key=None) + V2 文件返回 success=False + 友好错误
- ImageResolver 默认参数 + 老 XOR .dat 保持向后兼容
测试 46 个全部通过(11 新 + 35 旧)。
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-05 17:05:53 +08:00
btc-z
66eddaff0e
feat: transcribe_voice 新增 OpenAI Whisper API 后端 ( #66 )
...
默认 local,零行为变化。opt-in 双因素:transcription_backend=openai
且 openai_api_key 都齐才生效;任一缺失静默回退 local + stderr 一行警告。
首次进入云路径会 stderr 警告"语音将上传至 OpenAI 服务器"。
新增 config.json 字段:
- transcription_backend: "local" (默认) | "openai"
- local_whisper_model: "base" (替换 mcp_server.py 里硬编码 DEFAULT_WHISPER_MODEL)
- openai_api_key: "" (默认空;openai 包为 optional,按需 pip install)
关键技术选择:
- _transcribe(wav, backend) 单一 if/else 分发,不引入插件/工厂层
(Rule of Three —— 只有一个云后端时不值得抽象)
- 文件 > 25MB 在 OpenAI() 实例化之前提前拒绝,避免无谓上传
- 错误分类清晰: 缺 key / 缺 openai 包 / 401 / 429 / APIError 各自的提示
- PR #58 缓存 schema 自然扩展: 条目加 backend 字段,命中需 backend+model_size 都匹配
- 旧条目缺 backend 字段视为 "local",向前兼容 PR #58 已落盘的所有数据
- transcribe_chat.py 批量 CLI 与 MCP 工具共享同一份配置,保持一致
新增 2 个测试 (tests/test_openai_backend.py),只覆盖回归风险最高的两条:
- 文件 > 25MB 必须在 SDK 实例化前拒绝(隐私契约的防线)
- backend 不匹配的旧条目不命中(避免切后端时返回错后端结果)
其余路径要么琐碎(默认值读取)、要么坏掉时声音很大(SDK 错误、ImportError),
要么已被 PR #58 现有测试隐式覆盖(缺 backend 字段的旧条目),不再单独写测试。
顺手把 README 里 PR #53 漏掉的 voice 三件套(get_voice_messages /
decode_voice / transcribe_voice)补进 MCP 工具表,并新增"⚠️ 语音转录隐私"
章节说清数据流向、成本(约 \$0.006/分钟)、25MB 上限、回退行为。
Closes ylytdeng/wechat-decrypt#59
2026-05-01 13:56:32 +08:00
Belugary
989badd14f
feat: 给 transcribe_voice 工具加持久化缓存 ( #58 )
...
Whisper 本地推理在 CPU 下每条语音数秒到数十秒,且同一段 voice_data
产出相同 text,非常适合缓存。新增 voice_transcriptions.json 持久化
存储,命中时跳过 DB 查询、SILK 解码和 Whisper 推理全链路。
关键技术选择:
- 缓存 key 用 json.dumps([username, local_id]),即使 username 含
分隔符也不冲突
- 写入走 tmp + os.replace 原子替换,进程中断不会损坏主文件
- 条目记录 model_size,Whisper 默认模型升级后旧条目自动失效
- 空转录也缓存(配合 model_size 失效),避免静音片段每次重跑
- threading.Lock 防御并发 load/save 竞态
- 首次 OSError 写 stderr 警告一次,后续静默避免刷屏
小的行为改进:resolve_username 移到 whisper/pysilk 导入探测之前,
bad chat_name 情况下不再需要 whisper 已安装也能给出"找不到聊天对象"
的错误提示。
15 个新测试:持久化 roundtrip、UTF-8 保留、corrupt JSON 容错、原子
写、写前失败不污染主文件、并发 load/save、缓存命中跳过重活、model
不匹配视为 miss、key 对含分隔符 username 的防御。全部通过。
2026-04-25 00:19:08 +08:00
btc-z
02bc9c1840
feat: 新增语音 MCP 工具 + macOS 密钥提取修复 ( #53 )
...
* feat: 新增语音 MCP 工具 + macOS 密钥提取修复
- 新增 get_voice_messages / decode_voice / transcribe_voice MCP 工具
- 语音数据存储在 media_0.db VoiceInfo 表(SILK v3 格式)
- decode_voice 解码为 WAV 文件(saved to decoded_voices/)
- transcribe_voice 通过 Whisper 自动识别语言转录
- 新增 get_chat_history oldest_first 参数,支持从最早消息开始分页
- 修复 macOS 下 check_wechat_running / ensure_keys 逻辑
- 改用 pgrep 检测微信进程,绕过不支持 macOS 的 Python 扫描器
- 无 all_keys.json 时打印清晰引导,提示运行 C 版扫描器
- 新增 Makefile(build / keys / decrypt / web 快捷命令)
- .gitignore 补充 find_all_keys_macos 二进制和 decoded_voices/
* fix: 语音查询支持多分片 media DB + 文件名唯一化
解决 PR #53 review 的阻塞项 #1,顺手修 #3、#6。
#1 `_get_media_db_path()` 硬编码 `media_0.db`
- 新增模块级 `MEDIA_DB_KEYS`,镜像 `MSG_DB_KEYS` 的分片发现逻辑
- `_fetch_voice_row` 遍历所有分片,按 `(chat_name_id, local_id)`
首个命中即返回;单条语音在 media DB 家族内唯一,命中即可停
- `get_voice_messages` 从每个分片各取 `LIMIT limit`,合并排序后
截断到 `limit`。选择"每分片取 limit 条再合并"而非"按
max(create_time) 排序后逐个取到 limit 即停止":后者假设分片
间时间不重叠,一旦 WeChat 改分片策略就会静默丢消息;前者工作
量 O(N 分片 × limit),在任何分片布局下都正确
#3 输出文件名冲突
- `_silk_to_wav` 增加 `local_id` 参数,输出 `{user}_{time}_{lid}.wav`,
同一秒内两条语音不会互相覆盖;两个调用方都已在作用域内持有
`local_id`
#6 `_fetch_voice_row` 的 `local_id=None` 死分支
- 随 #1 的重写一并删除,`local_id` 改为必填位置参数
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
* refactor: macOS 密钥提取分层下沉到 find_all_keys.py
解决 PR #53 review 的阻塞项 #2。
review 里提到"跟 PR #51 冲突"实测不存在 —— PR #51 当前 0 文件改动
(fork 分支已与上游同步),但架构建议本身是对的:macOS 处理应集中
在 `find_all_keys.py`,而不是在 `main.py` 提前 return 截胡。
- `main.py:ensure_keys()` 移除 darwin 专属提前返回分支,macOS 走
和其他平台相同的 `extract_keys()` 路径
- `find_all_keys.py:_load_impl()` 在 darwin 分支抛出带
`sudo ./find_all_keys_macos` 操作指引的 RuntimeError;非 macOS
的平台兜底分支保留
- `main.py` 里已有 `except RuntimeError` 会打印并 `sys.exit(1)`,
用户可见行为不变
未来若有 PR 在 `find_all_keys.py` 加 macOS 自动编译 / dispatch,
直接替换这段 RuntimeError 即可,不再需要改 `main.py`。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
* chore: Makefile 支持 PYTHON 变量覆盖
解决 PR #53 review 的非阻塞项 #7。
原 Makefile 硬编码 `.venv/bin/python3`,没有 venv 的用户跑 `make
decrypt` 直接报错。引入 `PYTHON ?= .venv/bin/python3`:默认行为
不变(仍走 venv),想用系统 Python 的用户 `PYTHON=python3 make
decrypt` 即可。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
* docs: 回应 PR #53 review #4 — 澄清 silk-python 与 pysilk 包名关系
验证:本项目 import 的 `pysilk` 实际由 `pip install silk-python`
(synodriver/pysilk) 提供;pypi 上另有同名 `pysilk==0.0.1` 是无内容
的占位包,不可用。错误消息里 `pip install silk-python` 已经是对的,
但 reader 看到 `import pysilk` 仍会困惑,所以:
- `_silk_to_wav` 的 import 处加一行注释,点名所用的是
synodriver 版本,并提醒 pypi 上还有 pilk / pysilk 两个同类包
- `decode_voice` / `transcribe_voice` 的 docstring 加 "依赖:" 行,
明确 "pip install silk-python (import 名为 pysilk)",MCP 客户端
读 tool 描述就能看到正确的安装命令
未新增 requirements.txt 条目:voice 支持是可选功能(tool 内
try/except ImportError 懒加载),保持非必需依赖的语义。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com >
2026-04-23 14:10:22 +08:00
ylytdeng
7eb29b03e8
feat: 新增联系人标签查询功能
...
解析 contact.db 的 contact_label 表和 extra_buffer protobuf Field #30,
支持查询标签列表及指定标签下的成员。
- mcp_server.py: 新增 get_contact_tags / get_tag_members MCP 工具
- monitor_web.py: 新增 /api/tags JSON 端点,支持 ?name= 过滤
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-06 09:54:21 +08:00
ylytdeng
944546beb1
fix: 统一所有 JSON 文件读写为 UTF-8 编码
...
Windows 中文环境默认编码为 GBK,未指定 encoding 会导致
config.json/all_keys.json 解析失败。修复 9 个文件共 17 处。
Closes #32
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-03-20 14:32:37 +08:00
dsjzazs
7c42ff5d38
Investigate get_chat_history limit
2026-03-14 16:59:17 +08:00
dsjzazs
9ae558a31e
Fix global search pagination
2026-03-14 16:36:55 +08:00
dsjzazs
b623711410
Add MCP search unit tests
2026-03-14 14:07:51 +08:00
dsjzazs
7e7f7a2516
feat: 增强消息查询功能,支持时间范围和分页
2026-03-14 10:21:21 +08:00
Banghao Chi
fd67536ef7
Refine chat history message parsing
2026-03-08 20:52:33 -05:00
Banghao Chi
fa273b810d
Improve chat history formatting
2026-03-08 15:30:10 -05:00
PeanutSplash
6d9b2c0fe4
refactor(find_all_keys): extract shared key scan logic
2026-03-07 21:35:24 +08:00
PeanutSplash
872e3f58dc
fix: handle exited PIDs and narrow message DB keys
2026-03-07 21:35:24 +08:00
PeanutSplash
f9c338b48d
feat: add Linux support with cross-platform memory scanning
...
- Add Linux memory scanner (`find_all_keys_linux.py`) using `/proc/<pid>/mem`,
same approach as Windows/macOS — no GDB, no function offsets, no restart needed
- Extract Windows-specific code to `find_all_keys_windows.py`
- Make `find_all_keys.py` a platform dispatcher (Windows / Linux)
- Add `key_utils.py` for cross-platform path matching (`/` vs `\` in all_keys.json)
- Update `config.py` with Linux auto-detection of db_storage paths
- Update all consumers (decrypt_db, monitor, monitor_web, mcp_server) to use
`get_key_info()` for platform-agnostic key lookup
Tested on remote Linux container: 15/15 DBs scanned, decrypted, and verified.
2026-03-07 21:35:24 +08:00
ylytdeng
2b03a81a8f
fix: 统一路径分隔符为正斜杠,修复 macOS/Linux 兼容性
...
all_keys.json 中的 key 统一使用 `/` 作为路径分隔符,
消除 Windows 反斜杠硬编码,确保跨平台兼容。
涉及文件: find_all_keys.py, decrypt_db.py, monitor.py,
monitor_web.py, mcp_server.py, decode_image.py, latency_test.py
Fixes #17
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-07 00:53:48 +08:00
ylytdeng
73598751a0
fix: MCP DBCache 使用固定文件名 + 持久化缓存,重启秒恢复
...
- 缓存文件改用 md5(rel_key) 固定命名,放在 Temp/wechat_mcp_cache/
- mtime 映射持久化到 _mtimes.json,重启后验证一致直接复用
- 避免 mkstemp 随机文件名导致崩溃后临时文件堆积
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-04 15:10:25 +08:00
ylytdeng
da7525db95
Add image decryption and inline preview for WeChat V2 format
...
Support all three .dat encryption formats:
- Old XOR format: single-byte XOR, auto-detect key from magic bytes
- V1 format: AES-ECB with fixed key (md5("0")[:16]) + XOR tail
- V2 format (2025-08+): AES-128-ECB + raw middle + XOR tail
New files:
- decode_image.py: unified image decryption module (XOR/V1/V2)
- find_image_key.py: extract AES key from WeChat process memory
- find_image_key_monitor.py: continuous monitoring version for key capture
monitor_web.py changes:
- Inline image preview in Web UI with async decryption
- MonitorDBCache for mtime-based DB decryption caching
- username-to-DB mapping for image resolution chain
- /img/ endpoint for serving decoded images
- SSE image_update events for real-time preview updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-02 00:30:01 +08:00
joshua-deng
5057206222
Add MCP server for Claude AI integration
...
New mcp_server.py provides 5 tools (get_recent_sessions, get_chat_history,
search_messages, get_contacts, get_new_messages) via FastMCP stdio transport.
Features on-demand decryption with mtime-based caching and WAL support.
2026-02-28 12:22:50 +08:00