cortico-world-wechat 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -52
- package/README.md +79 -28
- package/describe.json +24 -24
- package/package.json +54 -53
- package/src/format.js +66 -50
- package/src/index.js +49 -49
- package/src/keys.js +170 -36
- package/src/python-runtime.js +310 -0
- package/src/wechat-crypto.js +84 -84
- package/src/wechat-db.js +313 -313
- package/src/wechat-listener.js +319 -319
- package/src/world.js +441 -409
- package/test/decrypt-verify.mjs +56 -56
- package/test/format.test.mjs +51 -33
- package/test/listener.test.mjs +60 -60
- package/test/runtime.test.mjs +181 -0
- package/test/world.test.mjs +204 -194
- package/tools/fetch-keys.py +99 -4
- package/tools/runtime-manifest.json +86 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,52 +1,100 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
本文件的 `## <版本号>` 段落会显示在扩展市场的发布时间线上(索引仓的 Action 按同样规则切段)。
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
## 0.1.
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
本文件的 `## <版本号>` 段落会显示在扩展市场的发布时间线上(索引仓的 Action 按同样规则切段)。
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## 0.1.6
|
|
7
|
+
|
|
8
|
+
- **装完即用:不再需要用户自己装 Python。** 取密钥这一步仍然用上游 `wechatauto-replica`
|
|
9
|
+
(微信的库密钥只在其进程内存里,Node 重写实测性能不可接受),但**解释器由扩展自带**:
|
|
10
|
+
首次需要时按 `tools/runtime-manifest.json` 下载嵌入式 Python 3.13 + 5 个 wheel
|
|
11
|
+
(合计约 15MB,默认走国内镜像、官方保底),逐个校验 sha256 后解压到
|
|
12
|
+
`%LOCALAPPDATA%\WeChatNotifier\runtime\<版本>-<指纹>\`,**不经过 pip、不需要编译器**。
|
|
13
|
+
这消掉了三个必踩错误:`wechat-notifier-venv\...\python.exe` 不存在(spawn ENOENT)、
|
|
14
|
+
`No module named 'wechatauto'`、以及 Python 3.13 上 `winsdk` 没有轮子导致的安装失败。
|
|
15
|
+
实测从零到取出密钥约 6 秒(含下载)。
|
|
16
|
+
- **只装取密钥真正用到的包**:`tools/fetch-keys.py` 改成按路径直接加载 `wechatauto/db.py`,
|
|
17
|
+
不执行包的 `__init__`(它会拉起 guia/moment/media/wx,于是需要 pywin32/opencv/Pillow/
|
|
18
|
+
uiautomation/**winsdk**)。依赖从 12 个包降到 5 个,下载量从约 80MB 降到约 15MB。
|
|
19
|
+
直接加载失败时回退到原来的 `from wechatauto import WeChatDB`,并打一行日志说明走了回退。
|
|
20
|
+
- **新增配置项**:`pythonPath`(指定解释器)、`autoProvisionPython`(是否允许自动下载运行时)、
|
|
21
|
+
`runtimeMirror`(自建镜像或离线包目录)、`dbStorage`(手动指定微信数据目录;接受
|
|
22
|
+
`...\xwechat_files`、账号目录、以及账号目录下的 `db_storage` 三种写法)。
|
|
23
|
+
- **解释器候选顺序**(先到先用,每个都要用 `fetch-keys.py --probe` 证明自己真能取密钥):配置 `pythonPath` →
|
|
24
|
+
自带运行时 → 旧的 `wechat-notifier-venv` → `WECHAT_NOTIFIER_PYTHON` → PATH 里的 `python`
|
|
25
|
+
(排除应用商店的占位 exe)。已按老办法装好环境的用户不受影响,也不会重复下载。
|
|
26
|
+
> 探针不是"能不能导入 cryptography":那样会把"有 Python、有 cryptography、但没装
|
|
27
|
+
> wechatauto"的机器判成可用并选中,然后取密钥报 `No module named 'wechatauto'`、
|
|
28
|
+
> 且**不会**回退到自带运行时——正是要消掉的老症状。现在探测与取密钥共用同一条加载路径。
|
|
29
|
+
- `tools/fetch-keys.py` 新增两个参数:`--probe`(只探测本解释器能否加载 WeChatDB)与可选的
|
|
30
|
+
微信数据目录(自动探测失败时兜底,接受 `...\xwechat_files`、账号目录、账号目录下的 `db_storage`)。
|
|
31
|
+
- 新增依赖 `fflate`(纯 JS,约 30KB):解压 wheel 与 embed zip,避免为此引入 pip 或外部解压工具。
|
|
32
|
+
- 新增 `test/runtime.test.mjs`(6 例,全离线:清单自洽、指纹、来源顺序、准备流程、校验失败、
|
|
33
|
+
换清单换目录)与 `scripts/update-runtime-manifest.mjs`(升级构件版本时重新生成清单并探测镜像)。
|
|
34
|
+
- 失败路径不留半成品:下载/校验/解压任何一步失败都清掉临时目录,正式目录保持原样;
|
|
35
|
+
就绪与否看清单指纹,换了清单就换目录,多进程并发首启也安全。
|
|
36
|
+
- **修复单测的副作用(既有缺陷)**:`test/world.test.mjs` 最后一个用例自己 new World 时漏了
|
|
37
|
+
`mode: 'bridge'`,于是走 in-process 分支 —— 在本机有 `keys.json` 时它"碰巧通过",
|
|
38
|
+
没有 `keys.json` 时则会去下载运行时、取密钥,并写进开发者真实的 `%LOCALAPPDATA%`。
|
|
39
|
+
现在显式写 bridge,测试不再依赖也不改动开发者环境(实测:跑完单测后真实目录仍为空)。
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## 0.1.5
|
|
43
|
+
|
|
44
|
+
- **转达口径(行为变更)**:推给桌宠的文本从「通知」改为「转达请求」。
|
|
45
|
+
此前她收到 `XX 发来消息:<原文>。跟胡闹说一声。` 会把原文当成对她说的、直接接着聊
|
|
46
|
+
(实测:原文「你在干嘛呢?」,她答「在呢在呢!」)。原因是问句本身在邀请回答,
|
|
47
|
+
而"转达"只是附加从句。现在把动作要求前置,并写明**别自己回答**。
|
|
48
|
+
- **分档转达**:正文不超过 `relayQuoteMax`(默认 40 字)时**照原文转达**,保证不失真;
|
|
49
|
+
超出、或没有文字正文时,改为只要求**一句话转述要点**,不搬运长文
|
|
50
|
+
(省上下文,也避免她复述长文时跑偏)。
|
|
51
|
+
- 新增配置项 `relayQuoteMax`,可调整分档阈值。
|
|
52
|
+
- 统一加 `【微信】` 前缀,便于识别与排查(此前只有长消息分支带前缀)。
|
|
53
|
+
|
|
54
|
+
## 0.1.4
|
|
55
|
+
|
|
56
|
+
- **补充作者字段 `author`**(`静音胡闹 <2310468741@qq.com>`),此前漏填,npm 页面上作者为空。
|
|
57
|
+
说明:npm 的 "published by" 显示的是**账号名**,无法用该字段改写;本字段只影响作者展示。
|
|
58
|
+
- 无功能变化。
|
|
59
|
+
|
|
60
|
+
## 0.1.3
|
|
61
|
+
|
|
62
|
+
- **修复:读取失败不会自愈**。此前一旦某次读取失败(并发写、微信正在写库、缓存半成品),
|
|
63
|
+
扩展会每秒重试、每秒失败,直到重启 Coopanion —— 实测踩到过该状态。
|
|
64
|
+
现在:缓存不可用即丢弃并全量重建;WAL 合并改为"临时文件 + 验证通过才原子替换",
|
|
65
|
+
合并失败只降级为"少一次增量",不再污染缓存。
|
|
66
|
+
- **修复:多进程共用同一解密缓存会互相踩**(扩展 + 排查脚本同时跑 → 永久 ile is not a database)。
|
|
67
|
+
缓存目录改为按进程隔离(cache/p<pid>)。
|
|
68
|
+
- **修复:用 mtime 判断"主库是否变化"导致每秒全量解密 20MB**。微信活着时 mtime 每秒都在变;
|
|
69
|
+
改为按**文件大小**判断全量重建,内容增量靠 WAL 合并补齐。实测二次读取 5224 页库仅需 13ms。
|
|
70
|
+
- 依赖内容自省的 describe.json、 est/ 均未变。
|
|
71
|
+
|
|
72
|
+
## 0.1.2
|
|
73
|
+
|
|
74
|
+
- 文档重写:安装给出三条路径(npm / 离线包 / 源码,按推荐顺序)、配置项逐条说明、
|
|
75
|
+
"没反应时按顺序查"的排查表、以及"消息正文会进入模型上下文"的明确提示。
|
|
76
|
+
- 无功能变化。
|
|
77
|
+
|
|
78
|
+
## 0.1.1
|
|
79
|
+
|
|
80
|
+
- **打包内容调整**(无功能变化):
|
|
81
|
+
- 把打包脚本移出 npm 包(仓库里保留在 `scripts/`)——它是构建用的,最终用户用不到;
|
|
82
|
+
- npm 包内补上 `test/`,方便使用者自行验证(尤其是微信升级后跑 `test/decrypt-verify.mjs`,
|
|
83
|
+
它用 `PRAGMA integrity_check` 判断页布局是否仍被正确解密)。
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## 0.1.0
|
|
87
|
+
|
|
88
|
+
首个公开版本。
|
|
89
|
+
|
|
90
|
+
- **World 扩展(主体)**:监听、解密、轮询、限流、推送全部在扩展内,随 Coopanion 启动,
|
|
91
|
+
没有独立常驻进程、没有 exe、没有开机自启任务。
|
|
92
|
+
- **解密**:纯 `node:crypto` 按页解密微信 4.x 本地库(AES-256-CBC raw CBC),并合并 `-wal` 增量帧。
|
|
93
|
+
- **轮询**:以 `sort_seq` 为水位(落盘),按会话增量读取新消息。
|
|
94
|
+
- **限流**:全局最短间隔、同会话冷却、静默时段(被吞掉即丢弃、不补发)。
|
|
95
|
+
- **取密钥**:微信的库密钥只存在于其进程内存中,由 `tools/fetch-keys.py` 按需取出
|
|
96
|
+
(短命进程,取完即退;失效时自动重取)。这是本项目唯一用到 Python 的地方。
|
|
97
|
+
- 实测:真机库解密 `PRAGMA integrity_check = ok`;测试 26 例(7 监听逻辑 + 6 文本格式化 + 13 World 行为)。
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
package/README.md
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
> 随 Coopanion 一起启动 —— 没有独立常驻进程、没有 exe、没有开机自启任务。
|
|
7
7
|
>
|
|
8
8
|
> 唯一的例外是**取密钥**:微信的库密钥只存在于微信进程内存中,需要一个短命脚本把它取出来
|
|
9
|
-
>
|
|
10
|
-
>
|
|
9
|
+
> (几秒完成、取完即退,失效时由扩展自动重拉)。这一步仍然用 Python(取舍理由见下),
|
|
10
|
+
> 但**解释器由扩展自带**:首次需要时自己下载约 15MB 的嵌入式 Python + 5 个 wheel,
|
|
11
|
+
> 用户不需要装 Python、不需要 pip、不需要编译器。
|
|
11
12
|
|
|
12
13
|
| | |
|
|
13
14
|
|---|---|
|
|
@@ -17,17 +18,15 @@
|
|
|
17
18
|
|
|
18
19
|
---
|
|
19
20
|
|
|
20
|
-
##
|
|
21
|
+
## 快速开始(两步)
|
|
21
22
|
|
|
22
23
|
```powershell
|
|
23
24
|
# ① 装扩展:在 Coopanion 的扩展页搜 cortico-world-wechat 点安装
|
|
24
25
|
# (或命令行:进 Coopanion 的 data\extensions 目录执行下面这行)
|
|
25
26
|
pnpm add cortico-world-wechat
|
|
26
27
|
|
|
27
|
-
# ②
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
# ③ 重启 Coopanion(扩展在启动时装载,不热更)
|
|
28
|
+
# ② 重启 Coopanion(扩展在启动时装载,不热更)
|
|
29
|
+
# 首次需要取密钥时,扩展会自己准备好运行时(约 15MB,仅一次)——你不用装任何东西
|
|
31
30
|
```
|
|
32
31
|
|
|
33
32
|
装好并重启后,随便发一条微信消息,桌宠应当冒泡汇报。
|
|
@@ -44,12 +43,14 @@ pnpm add cortico-world-wechat
|
|
|
44
43
|
└─ host.pushEvent ──▶ 桌宠(气泡 / TTS)
|
|
45
44
|
▲
|
|
46
45
|
└── keys.json ◀── tools/fetch-keys.py(短命,仅取密钥)
|
|
46
|
+
└─ 解释器:自带运行时(首次自动下载,约 15MB)
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
| 部件 | 位置 | 说明 |
|
|
50
50
|
|---|---|---|
|
|
51
51
|
| **World 扩展(主体)** | `cortico-world-wechat/src/` | 监听、解密、轮询、推送全在这里 |
|
|
52
52
|
| 取密钥工具(例外) | `cortico-world-wechat/tools/fetch-keys.py` | 密钥缺失/失效时被自动拉起,几秒后退出 |
|
|
53
|
+
| 取密钥用的 Python | `%LOCALAPPDATA%\WeChatNotifier\runtime\<版本>-<指纹>\` | 扩展自己准备的嵌入式 Python + 5 个 wheel,与用户装的 Python 无关 |
|
|
53
54
|
| 密钥与状态 | `%LOCALAPPDATA%\WeChatNotifier\`(`keys.json`、`watermarks.json`、`cache\`) | 含密钥,**切勿入库** |
|
|
54
55
|
|
|
55
56
|
### 为什么取密钥保留 Python
|
|
@@ -63,6 +64,26 @@ pnpm add cortico-world-wechat
|
|
|
63
64
|
如果将来要彻底去掉 Python,正确路径是复刻上游那套"标记 + 指针链"(只扫 Weixin.dll,秒级),
|
|
64
65
|
而不是宽扫 —— 这条路记录在 `设计文档.md` 里备用。
|
|
65
66
|
|
|
67
|
+
### Python 从哪来(自带运行时)
|
|
68
|
+
|
|
69
|
+
"取密钥要 Python"不等于"用户要装 Python"。扩展自己准备一份最小运行时:
|
|
70
|
+
|
|
71
|
+
| 步骤 | 做什么 |
|
|
72
|
+
|---|---|
|
|
73
|
+
| 1 | 按顺序找可用解释器:配置 `pythonPath` → 自带运行时 → 旧的 `wechat-notifier-venv` → `WECHAT_NOTIFIER_PYTHON` → PATH 里的 `python`(每个都要用 `fetch-keys.py --probe` 证明自己真能取密钥才算可用——只测"有没有 cryptography"会把"有 Python 但没装 wechatauto"的机器误判成可用,然后卡在老症状上) |
|
|
74
|
+
| 2 | 一个都没有时,按 [`tools/runtime-manifest.json`](tools/runtime-manifest.json) 下载 6 个构件:嵌入式 Python 3.13(约 10.5MB)+ `cryptography` / `cffi` / `pycparser` / `colorama` / `wechatauto-replica`(合计约 4.4MB) |
|
|
75
|
+
| 3 | 每个构件**边下边算 sha256**,与清单不符即整批作废;解压到临时目录、写好 `_pth` 与就绪标记后才原子改名到正式目录 |
|
|
76
|
+
| 4 | 默认走国内镜像(华为 / 腾讯 / 清华 / 阿里),官方源保底;每个来源都实测可达才写进清单 |
|
|
77
|
+
|
|
78
|
+
两点值得知道:
|
|
79
|
+
|
|
80
|
+
- **只装取密钥真正用到的包**。`fetch-keys.py` 直接加载 `wechatauto/db.py`,不执行包的
|
|
81
|
+
`__init__`,因此 pywin32 / opencv / Pillow / uiautomation / **winsdk** 全都不需要
|
|
82
|
+
(winsdk 在 Python 3.13 上没有轮子、只能源码编译 —— 正是过去"装不上"的根因)。
|
|
83
|
+
依赖从 12 个包降到 5 个,下载量从约 80MB 降到约 15MB。
|
|
84
|
+
- **不经过 pip**。wheel 就是 zip,解压进 `Lib\site-packages` 即可,所以不需要编译器、
|
|
85
|
+
也不会因为 pip 版本/网络源出问题。实测从零到取出密钥共约 6 秒(含下载)。
|
|
86
|
+
|
|
66
87
|
---
|
|
67
88
|
|
|
68
89
|
## 安装(三种方式,按推荐顺序)
|
|
@@ -98,6 +119,7 @@ pwsh -File install.ps1 -KeysOnly # 只看"怎么准备密钥"
|
|
|
98
119
|
$src = '<本仓库>\cortico-world-wechat'
|
|
99
120
|
$dst = 'D:\MyApp\Coopanion\data\extensions\node_modules\cortico-world-wechat'
|
|
100
121
|
robocopy $src $dst /E /XD node_modules
|
|
122
|
+
|
|
101
123
|
# 依赖装到 Coopanion 的 extensions 下(不要装进扩展目录,避免嵌套)
|
|
102
124
|
cd 'D:\MyApp\Coopanion\data\extensions'
|
|
103
125
|
pnpm add better-sqlite3-multiple-ciphers
|
|
@@ -118,6 +140,7 @@ pnpm add better-sqlite3-multiple-ciphers
|
|
|
118
140
|
"autoFetchKeys": true,
|
|
119
141
|
"pollIntervalSec": 1,
|
|
120
142
|
"previewMaxChars": 60,
|
|
143
|
+
"relayQuoteMax": 40,
|
|
121
144
|
"throttle": { "global_min_gap_sec": 20, "per_chat_cooldown_sec": 120 },
|
|
122
145
|
"quietHours": { "enabled": true, "start": "23:30", "end": "08:00" }
|
|
123
146
|
}
|
|
@@ -129,8 +152,13 @@ pnpm add better-sqlite3-multiple-ciphers
|
|
|
129
152
|
| `notifySelf` | `false` | 是否提醒"自己发的消息" |
|
|
130
153
|
| `notifyGroup` | `true` | 是否提醒群消息 |
|
|
131
154
|
| `autoFetchKeys` | `true` | 密钥缺失/失效时自动拉起取密钥工具 |
|
|
155
|
+
| `pythonPath` | `''` | 指定 Python 解释器(留空=自动挑:自带运行时 → 旧 venv → 环境变量 → PATH) |
|
|
156
|
+
| `autoProvisionPython` | `true` | 是否允许自动下载自带运行时(关掉就必须自己给 `pythonPath`) |
|
|
157
|
+
| `runtimeMirror` | `''` | 自带运行时的下载基地址(留空=内置镜像;可指向自建镜像或离线包目录) |
|
|
158
|
+
| `dbStorage` | `''` | 微信数据目录(留空=让取密钥脚本自动探测;探测不到时才需要填) |
|
|
132
159
|
| `pollIntervalSec` | `1` | 轮询间隔(秒) |
|
|
133
160
|
| `previewMaxChars` | `60` | 正文截断长度(隐私 + 上下文成本) |
|
|
161
|
+
| `relayQuoteMax` | `40` | 转达分档:正文不超过它就照原文转达,超过只转述要点 |
|
|
134
162
|
| `throttle.*` | 20 / 120 | 全局最短间隔、同会话冷却(秒) |
|
|
135
163
|
| `quietHours.*` | `23:30–08:00` | 静音时段;**被吞掉即丢弃、不补发** |
|
|
136
164
|
|
|
@@ -138,23 +166,39 @@ pnpm add better-sqlite3-multiple-ciphers
|
|
|
138
166
|
|
|
139
167
|
## 准备密钥
|
|
140
168
|
|
|
141
|
-
|
|
169
|
+
**一般不用你做任何事。** 扩展启动时发现没有 `keys.json`,会自己完成:
|
|
170
|
+
|
|
171
|
+
1. 挑一个可用解释器(顺序见上);
|
|
172
|
+
2. 都不存在且没关掉自动准备时,下载并解压自带运行时到
|
|
173
|
+
`%LOCALAPPDATA%\WeChatNotifier\runtime\<版本>-<指纹>\`;
|
|
174
|
+
3. 用它对微信进程内存做一次**只读**扫描,把各库密钥写进
|
|
175
|
+
`%LOCALAPPDATA%\WeChatNotifier\keys.json`(实测冷启动合计约 6 秒)。
|
|
176
|
+
|
|
177
|
+
微信重新登录 / 升级导致密钥变化时会自动重取。
|
|
178
|
+
|
|
179
|
+
### 手动跑(排查用)
|
|
142
180
|
|
|
143
181
|
```powershell
|
|
144
|
-
#
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
# 取密钥(微信需已登录)
|
|
152
|
-
& $py "<扩展目录>\tools\fetch-keys.py"
|
|
153
|
-
# 产出 %LOCALAPPDATA%\WeChatNotifier\keys.json(24 个库密钥)
|
|
182
|
+
# 用自带运行时(路径里的指纹以日志里那条为准)
|
|
183
|
+
& "$env:LOCALAPPDATA\WeChatNotifier\runtime\<版本>-<指纹>\python.exe" `
|
|
184
|
+
"<扩展目录>\tools\fetch-keys.py" "$env:LOCALAPPDATA\WeChatNotifier\keys.json"
|
|
185
|
+
|
|
186
|
+
# 自动探测不到数据目录时,把路径作为第二个参数(三种写法都收:
|
|
187
|
+
# ...\xwechat_files、...\xwechat_files\<账号>、或账号目录下的 db_storage)
|
|
188
|
+
& <上面的 python.exe> "<扩展目录>\tools\fetch-keys.py" <输出路径> "D:\...\xwechat_files"
|
|
154
189
|
```
|
|
155
190
|
|
|
156
|
-
|
|
157
|
-
|
|
191
|
+
### 用自己装的 Python
|
|
192
|
+
|
|
193
|
+
装好 64 位 Python 与 `wechatauto-replica` 后,配置 `pythonPath` 指向它即可(优先于自带运行时)。
|
|
194
|
+
老办法留下的 `%LOCALAPPDATA%\wechat-notifier-venv` 也会被自动使用,不用改配置。
|
|
195
|
+
|
|
196
|
+
### 内网 / 下载不了
|
|
197
|
+
|
|
198
|
+
把 6 个构件放到本地目录或自建 HTTP 服务(文件名与
|
|
199
|
+
[`tools/runtime-manifest.json`](tools/runtime-manifest.json) 一致),配置 `runtimeMirror`
|
|
200
|
+
指向它;下载后**仍然逐个校验 sha256**。清单本身可以用
|
|
201
|
+
`node scripts/update-runtime-manifest.mjs` 重新生成(会探测各镜像可达性)。
|
|
158
202
|
|
|
159
203
|
---
|
|
160
204
|
|
|
@@ -163,6 +207,8 @@ $py = "$env:LOCALAPPDATA\wechat-notifier-venv\Scripts\python.exe"
|
|
|
163
207
|
日志在 `D:\MyApp\Coopanion\data\logs\core.log`,搜 `wechat-notifier`:
|
|
164
208
|
|
|
165
209
|
```
|
|
210
|
+
[wechat-notifier] [py] 自带运行时已就绪:C:\Users\...\WeChatNotifier\runtime\3.13.15-xxxxxxxx\python.exe
|
|
211
|
+
[wechat-notifier] [keys] 使用解释器(自带运行时):...\runtime\3.13.15-xxxxxxxx\python.exe
|
|
166
212
|
[wechat-notifier] 读库模式:db_storage=...\xwechat_files\<账号>\db_storage
|
|
167
213
|
[wechat-notifier] 消息分片 4 个
|
|
168
214
|
[wechat-notifier] [listener] 联系人 8269 条
|
|
@@ -177,8 +223,8 @@ $py = "$env:LOCALAPPDATA\wechat-notifier-venv\Scripts\python.exe"
|
|
|
177
223
|
|
|
178
224
|
| 现象 | 原因 | 处理 |
|
|
179
225
|
|---|---|---|
|
|
180
|
-
| 日志里 `keysError` 非空 | 取不到密钥 |
|
|
181
|
-
| 日志停在"
|
|
226
|
+
| 日志里 `keysError` 非空 | 取不到密钥 | 确认微信**已登录**;杀软放行读内存;日志会写明是"打不开进程""没有候选密钥"还是"密钥对不上库" |
|
|
227
|
+
| 日志停在"首次取密钥需要 Python" | 运行时下载失败 | 日志会列出每个来源的失败原因;用 `runtimeMirror` 换源,或用 `pythonPath` 指定本机 Python |
|
|
182
228
|
| 有"放行"但桌宠不吭声 | 问题在桌宠侧 | 看 core.log 有无 `收到 … 推给她`;有则说明已推,检查她的 persona / TTS 开关 |
|
|
183
229
|
| 完全没日志 | 扩展没装载 | 扩展在**启动时**装载:改完配置或代码必须**重启 Coopanion** |
|
|
184
230
|
| 几分钟没有任何"放行" | 可能确实没人发消息 | 用手机发一条;记得看是否被限流吞掉(日志会写 `限流吞掉 … global_gap`) |
|
|
@@ -190,10 +236,11 @@ $py = "$env:LOCALAPPDATA\wechat-notifier-venv\Scripts\python.exe"
|
|
|
190
236
|
```bash
|
|
191
237
|
cd cortico-world-wechat
|
|
192
238
|
|
|
193
|
-
# 纯逻辑(
|
|
239
|
+
# 纯逻辑(36 例:正文规范化、限流、类型映射、WS 服务、状态端点、事件推送、自带运行时准备)
|
|
194
240
|
node test/listener.test.mjs
|
|
195
241
|
node test/format.test.mjs
|
|
196
242
|
node test/world.test.mjs
|
|
243
|
+
node test/runtime.test.mjs
|
|
197
244
|
|
|
198
245
|
# 集成(需要真机微信库 + keys.json):验证解密正确性
|
|
199
246
|
# 微信升级后先跑这个 —— integrity_check = ok 才说明页布局仍被正确解密
|
|
@@ -207,6 +254,7 @@ node test/decrypt-verify.mjs 'contact\contact.db'
|
|
|
207
254
|
## 发布与分发
|
|
208
255
|
|
|
209
256
|
- npm:`npm publish`(版本号改 `package.json` 并在 `CHANGELOG.md` 加 `## <版本>` 段)
|
|
257
|
+
- 运行时清单:升级嵌入式 Python 或 wheel 版本后,跑 `node scripts/update-runtime-manifest.mjs`
|
|
210
258
|
- 离线包:`pwsh -File release/build-package.ps1 -Version <版本>`
|
|
211
259
|
- 官方扩展市场:机制与清单见 [docs/发布到官方市场.md](docs/发布到官方市场.md)
|
|
212
260
|
|
|
@@ -216,13 +264,14 @@ node test/decrypt-verify.mjs 'contact\contact.db'
|
|
|
216
264
|
|
|
217
265
|
1. 仅 Windows x64;微信必须**已登录**(密钥在其进程内存里)。
|
|
218
266
|
2. 取密钥需要读微信进程内存,**可能被杀软拦截**(当前未遇)。
|
|
219
|
-
3.
|
|
267
|
+
3. 首次取密钥需要联网下载自带运行时(约 15MB);内网环境用 `runtimeMirror` 指到本地或内网源。
|
|
268
|
+
4. 依赖上游 [`wechatauto-replica`](https://pypi.org/project/wechatauto-replica/) 取密钥;
|
|
220
269
|
微信大版本升级后若取不到密钥,先跑它的体检命令排查。
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
270
|
+
5. 只读微信库:不回消息、不写库、不驱动微信窗口。
|
|
271
|
+
6. 消息频率高,**限流是必需的**(每次推送都会真实唤醒桌宠、走一次 LLM 调用)。
|
|
272
|
+
7. **消息正文会进入桌宠的模型上下文**(随 `pushEvent` 交给她处理)——扩展在市场里已声明
|
|
224
273
|
`sensitive-data` 警示标签,装之前请知悉。
|
|
225
|
-
|
|
274
|
+
8. 主要在**一台机器、一个微信版本(4.1.15.13)、单账号**上验证过;市场标签为 `experimental`。
|
|
226
275
|
|
|
227
276
|
---
|
|
228
277
|
|
|
@@ -236,6 +285,8 @@ node test/decrypt-verify.mjs 'contact\contact.db'
|
|
|
236
285
|
| **必须 `setAutoPadding(false)`** | Node 默认校验 PKCS#7,SQLCipher 页是 raw CBC → `bad decrypt` | 关闭自动填充 |
|
|
237
286
|
| **WAL 帧只合并同 salt 的** | checkpoint 会重置 WAL,旧世代帧合并会用过期页覆盖新数据 | 比对 WAL 头 salt |
|
|
238
287
|
| **`real_sender_id` 要按所在分片解析** | 用别的表解析会把发送者显示成无关的人(上游 issue #34) | 查该分片自己的 `Name2Id` |
|
|
288
|
+
| **嵌入式 Python 不加载 site-packages** | 不写 `python313._pth` 里那行,解压出来的 wheel 永远 import 不到 | `_pth` 显式加 `Lib\site-packages` 与 `import site` |
|
|
289
|
+
| **`from wechatauto import …` 会拉起整套重依赖** | 走包 `__init__` 就需要 pywin32/opencv/Pillow/uiautomation/winsdk(winsdk 在 3.13 无轮子) | `fetch-keys.py` 按路径直接加载 `wechatauto/db.py` |
|
|
239
290
|
|
|
240
291
|
---
|
|
241
292
|
|
package/describe.json
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
{
|
|
2
|
-
"tools": [],
|
|
3
|
-
"events": [
|
|
4
|
-
{
|
|
5
|
-
"type": "wechat-notifier.notice",
|
|
6
|
-
"description": {
|
|
7
|
-
"zh": "微信里有人给你发消息了。",
|
|
8
|
-
"en": "Someone sent you a WeChat message."
|
|
9
|
-
},
|
|
10
|
-
"trigger": "flush",
|
|
11
|
-
"tags": [
|
|
12
|
-
"speak"
|
|
13
|
-
]
|
|
14
|
-
}
|
|
15
|
-
],
|
|
16
|
-
"prompts": [
|
|
17
|
-
{
|
|
18
|
-
"key": "wechat_notifier_duty",
|
|
19
|
-
"title": "微信消息提示的职责说明",
|
|
20
|
-
"role": "envPrompt",
|
|
21
|
-
"content": "微信消息提示是给你看的:微信里有人给你发消息了。看到要主动用 pet_say 简短汇报给胡闹(一句话说清\"谁在哪个会话说了什么\",别念全文),不要只是记下来就结束这一轮。自己发的消息不用汇报。"
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"tools": [],
|
|
3
|
+
"events": [
|
|
4
|
+
{
|
|
5
|
+
"type": "wechat-notifier.notice",
|
|
6
|
+
"description": {
|
|
7
|
+
"zh": "微信里有人给你发消息了。",
|
|
8
|
+
"en": "Someone sent you a WeChat message."
|
|
9
|
+
},
|
|
10
|
+
"trigger": "flush",
|
|
11
|
+
"tags": [
|
|
12
|
+
"speak"
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"prompts": [
|
|
17
|
+
{
|
|
18
|
+
"key": "wechat_notifier_duty",
|
|
19
|
+
"title": "微信消息提示的职责说明",
|
|
20
|
+
"role": "envPrompt",
|
|
21
|
+
"content": "微信消息提示是给你看的:微信里有人给你发消息了。看到要主动用 pet_say 简短汇报给胡闹(一句话说清\"谁在哪个会话说了什么\",别念全文),不要只是记下来就结束这一轮。自己发的消息不用汇报。"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
package/package.json
CHANGED
|
@@ -1,53 +1,54 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "cortico-world-wechat",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"author": "静音胡闹 <2310468741@qq.com>",
|
|
5
|
-
"description": "把 Windows 微信新消息播报给桌宠:扩展自己解密并轮询微信本地库,把新消息推进桌宠的事件流,由桌宠决定怎么汇报。",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"main": "src/index.js",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": "./src/index.js",
|
|
11
|
-
"./package.json": "./package.json"
|
|
12
|
-
},
|
|
13
|
-
"files": [
|
|
14
|
-
"src",
|
|
15
|
-
"tools",
|
|
16
|
-
"test",
|
|
17
|
-
"describe.json",
|
|
18
|
-
"CHANGELOG.md",
|
|
19
|
-
"README.md"
|
|
20
|
-
],
|
|
21
|
-
"os": [
|
|
22
|
-
"win32"
|
|
23
|
-
],
|
|
24
|
-
"engines": {
|
|
25
|
-
"node": "^22.19.0 || >=24.0.0"
|
|
26
|
-
},
|
|
27
|
-
"dependencies": {
|
|
28
|
-
"better-sqlite3-multiple-ciphers": "^13.0.3",
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"cortico",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "cortico-world-wechat",
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"author": "静音胡闹 <2310468741@qq.com>",
|
|
5
|
+
"description": "把 Windows 微信新消息播报给桌宠:扩展自己解密并轮询微信本地库,把新消息推进桌宠的事件流,由桌宠决定怎么汇报。",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "src/index.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./src/index.js",
|
|
11
|
+
"./package.json": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"src",
|
|
15
|
+
"tools",
|
|
16
|
+
"test",
|
|
17
|
+
"describe.json",
|
|
18
|
+
"CHANGELOG.md",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"os": [
|
|
22
|
+
"win32"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"better-sqlite3-multiple-ciphers": "^13.0.3",
|
|
29
|
+
"fflate": "^0.8.3",
|
|
30
|
+
"ws": "^8.21.3"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"cortico-world",
|
|
34
|
+
"cortico",
|
|
35
|
+
"wechat",
|
|
36
|
+
"weixin",
|
|
37
|
+
"notifier"
|
|
38
|
+
],
|
|
39
|
+
"cortico": {
|
|
40
|
+
"displayName": "微信消息提示",
|
|
41
|
+
"kind": "world",
|
|
42
|
+
"api": 6,
|
|
43
|
+
"describe": "describe.json",
|
|
44
|
+
"tags": [
|
|
45
|
+
"im",
|
|
46
|
+
"external-setup",
|
|
47
|
+
"experimental",
|
|
48
|
+
"sensitive-data"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"test": "node --test test/format.test.mjs test/world.test.mjs test/runtime.test.mjs"
|
|
53
|
+
}
|
|
54
|
+
}
|