wechat-to-anything 0.6.3 → 0.6.5

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/README.en.md ADDED
@@ -0,0 +1,165 @@
1
+ <p align="center">
2
+ <img src="docs/banner.png" alt="wechat-to-anything" />
3
+ </p>
4
+
5
+ <h1 align="center">wechat-to-anything</h1>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/wechat-to-anything"><img src="https://img.shields.io/npm/v/wechat-to-anything?style=flat-square&color=cb3837" alt="npm" /></a>
9
+ <a href="https://github.com/kellyvv/wechat-to-anything"><img src="https://img.shields.io/github/stars/kellyvv/wechat-to-anything?style=flat-square&color=yellow" alt="stars" /></a>
10
+ <a href="LICENSE"><img src="https://img.shields.io/github/license/kellyvv/wechat-to-anything?style=flat-square" alt="license" /></a>
11
+ <a href="https://github.com/kellyvv/wechat-to-anything"><img src="https://img.shields.io/badge/node-%3E%3D22-brightgreen?style=flat-square" alt="node" /></a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="#quick-start">Quick Start</a> · <a href="#full-multimodal-matrix">Multimodal</a> · <a href="#media-protocol">Media Protocol</a> · <a href="#multi-agent-mode">Multi-Agent</a> · <a href="#bring-your-own-agent">Custom Agent</a>
16
+ </p>
17
+
18
+ <p align="center">
19
+ <a href="README.md">中文</a> | English
20
+ </p>
21
+
22
+ > ⭐ If this project helps you, please give it a Star!
23
+
24
+ **The first open-source project** to support full multimodal bidirectional communication between WeChat and AI Agents — text, images, voice, video, and files, both sending and receiving.
25
+
26
+ <p align="center">
27
+ <img src="docs/wechat-image-send.png" width="250" alt="Agent sends files, images, voice" />
28
+ <img src="docs/wechat-image-receive.png" width="250" alt="Agent sends images, video, voice" />
29
+ <a href="https://github.com/kellyvv/wechat-to-anything/raw/main/docs/wechat-voice-demo.mp4">
30
+ <img src="docs/wechat-voice-demo.gif" width="250" alt="Voice demo (click for audio)" />
31
+ </a>
32
+ </p>
33
+
34
+ ## Features
35
+
36
+ - 🔌 **Zero-config setup** — One `npx` command, no cloning, no configuration
37
+ - 🧠 **Agent-agnostic** — Works with any OpenAI-compatible API (Codex / Gemini / Claude / custom)
38
+ - 📡 **Full multimodal** — Text, images, voice, video, files — bidirectional
39
+ - 🤖 **Multi-Agent** — Connect multiple Agents simultaneously, route with `@` prefix
40
+ - ⌨️ **Typing indicator** — Shows "typing..." while Agent is thinking
41
+
42
+ ### Full Multimodal Matrix
43
+
44
+ | Modality | WeChat → Agent | Agent → WeChat |
45
+ |------|:---:|:---:|
46
+ | 📝 Text | ✅ | ✅ |
47
+ | 📷 Image | ✅ Auto-detect | ✅ HD original |
48
+ | 🎤 Voice | ✅ Speech-to-text | ✅ Voice bubble |
49
+ | 🎬 Video | ✅ Auto-receive | ✅ With thumbnail |
50
+ | 📄 File | ✅ Content extraction | ✅ Downloadable |
51
+
52
+ ## Quick Start
53
+
54
+ ```bash
55
+ # Pick your favorite Agent:
56
+ npx wechat-to-anything --codex # OpenAI Codex
57
+ npx wechat-to-anything --gemini # Google Gemini
58
+ npx wechat-to-anything --claude # Claude Code
59
+ npx wechat-to-anything --openclaw # OpenClaw
60
+
61
+ # Or pass a URL directly:
62
+ npx wechat-to-anything http://your-agent:8000/v1
63
+ ```
64
+
65
+ > First time: A QR code pops up in terminal → Scan with WeChat → Done. Login is cached automatically.
66
+
67
+ ### Dependencies
68
+
69
+ ```bash
70
+ # 1. Node.js >= 22
71
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
72
+ nvm install 22
73
+
74
+ # 2. Python 3 + pip
75
+ brew install python3 # macOS
76
+ apt install python3 python3-pip # Linux
77
+
78
+ # 3. ffmpeg
79
+ brew install ffmpeg # macOS
80
+ apt install ffmpeg # Linux
81
+
82
+ # 4. pilk
83
+ pip install pilk
84
+ ```
85
+
86
+ ## How It Works
87
+
88
+ ```
89
+ WeChat User ←→ Tencent ilinkai API ←→ wechat-to-anything ←→ Your Agent (HTTP)
90
+ ```
91
+
92
+ Directly calls Tencent's ilinkai API to send/receive WeChat messages. No middleware, no reverse engineering, no web client. Your Agent just needs an OpenAI-compatible HTTP endpoint.
93
+
94
+ ## Bring Your Own Agent
95
+
96
+ Any language — just expose `POST /v1/chat/completions`:
97
+
98
+ ```python
99
+ @app.post("/v1/chat/completions")
100
+ def chat(request):
101
+ message = request.json["messages"][-1]["content"]
102
+ reply = your_agent(message)
103
+ return {"choices": [{"message": {"role": "assistant", "content": reply}}]}
104
+ ```
105
+
106
+ Then: `npx wechat-to-anything http://your-agent:8000/v1`
107
+
108
+ ## Media Protocol
109
+
110
+ Include specific formats in Agent responses to automatically send media:
111
+
112
+ | Type | Agent Response Format | Notes |
113
+ |------|----------------------|-------|
114
+ | Image | `![desc](URL or path)` | URL, local path, or data URI |
115
+ | Voice | `[audio:path or URL]` | MP3/WAV/OGG, requires `ffmpeg` + `pilk` |
116
+ | Video | `[video:path or URL]` | Requires `ffmpeg` |
117
+ | File | `[file:path or URL]` | Any file type |
118
+
119
+ **Image receiving** (WeChat → Agent) follows the [OpenAI Vision API](https://platform.openai.com/docs/guides/vision):
120
+
121
+ ```json
122
+ {
123
+ "messages": [{
124
+ "role": "user",
125
+ "content": [
126
+ { "type": "text", "text": "What is this?" },
127
+ { "type": "image_url", "image_url": { "url": "data:image/jpeg;base64,..." } }
128
+ ]
129
+ }]
130
+ }
131
+ ```
132
+
133
+ > Examples: [image-test.mjs](examples/image-test.mjs) · [voice-test.mjs](examples/voice-test.mjs) · [video-test-local.mjs](examples/video-test-local.mjs) · [file-test.mjs](examples/file-test.mjs)
134
+
135
+ ## Multi-Agent Mode
136
+
137
+ Connect multiple Agents simultaneously, route with `@` prefix. Supports OpenAI format and [ACP](https://agentcommunicationprotocol.dev/):
138
+
139
+ ```bash
140
+ npx wechat-to-anything \
141
+ --agent codex=http://localhost:3001/v1 \
142
+ --agent gemini=http://localhost:3002/v1 \
143
+ --agent bee=acp://localhost:8000/chat \
144
+ --default codex
145
+ ```
146
+
147
+ | WeChat Message | Effect |
148
+ |---|---|
149
+ | `Hello` | Sent to default Agent |
150
+ | `@codex write a sort` | Routes to Codex |
151
+ | `@gemini review code` | Routes to Gemini |
152
+ | `@list` | List all Agents |
153
+ | `@switch gemini` | Switch default |
154
+
155
+ ## Credentials
156
+
157
+ Login credentials are saved in `~/.wechat-to-anything/credentials.json`. Delete to re-login.
158
+
159
+ ## Star History
160
+
161
+ If this project helped you, please give it a ⭐ Star — it's the best support!
162
+
163
+ ## License
164
+
165
+ [MIT](LICENSE)
package/README.md CHANGED
@@ -1,79 +1,99 @@
1
- # wechat-to-anything
1
+ <p align="center">
2
+ <img src="docs/banner.png" alt="wechat-to-anything" />
3
+ </p>
2
4
 
3
- > 把微信变成任何 AI Agent 的前端。零依赖,一条命令。
4
- >
5
- > ⭐ 如果这个项目对你有帮助,请给个 Star!本项目仅用于技术学习和交流,开源不易。
5
+ <h1 align="center">wechat-to-anything</h1>
6
6
 
7
- 微信双向支持 Agent 多种模态消息发送和接收,支持文本、图片、语音、视频、文件。
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/wechat-to-anything"><img src="https://img.shields.io/npm/v/wechat-to-anything?style=flat-square&color=cb3837" alt="npm" /></a>
9
+ <a href="https://github.com/kellyvv/wechat-to-anything"><img src="https://img.shields.io/github/stars/kellyvv/wechat-to-anything?style=flat-square&color=yellow" alt="stars" /></a>
10
+ <a href="LICENSE"><img src="https://img.shields.io/github/license/kellyvv/wechat-to-anything?style=flat-square" alt="license" /></a>
11
+ <a href="https://github.com/kellyvv/wechat-to-anything"><img src="https://img.shields.io/badge/node-%3E%3D22-brightgreen?style=flat-square" alt="node" /></a>
12
+ </p>
8
13
 
9
14
  <p align="center">
10
- <img src="docs/wechat-image-send.png" width="250" alt="发送图片给 Agent 识别" />
11
- <img src="docs/wechat-image-receive.png" width="250" alt="Agent 发送图片到微信" />
12
- <a href="https://github.com/kellyvv/wechat-to-anything/raw/main/docs/wechat-voice-demo.mp4">
13
- <img src="docs/wechat-voice-demo.gif" width="250" alt="语音发送演示(点击播放有声版)" />
14
- </a>
15
+ <a href="#快速开始">快速开始</a> · <a href="#全模态支持矩阵">全模态</a> · <a href="#多媒体协议">多媒体协议</a> · <a href="#多-agent-模式">多 Agent</a> · <a href="#接入自己的-agent">自定义 Agent</a>
15
16
  </p>
16
17
 
17
- ## 原理
18
+ <p align="center">
19
+ 中文 | <a href="README.en.md">English</a>
20
+ </p>
18
21
 
19
- ```
20
- 微信 ←→ ilinkai API (腾讯) ←→ wechat-to-anything ←→ 你的 Agent (HTTP)
21
- ```
22
+ > ⭐ 如果这个项目对你有帮助,请给个 Star!
23
+
24
+ **全网首个**支持微信与任何 AI Agent 全模态双向通信的开源项目 —— 文本、图片、语音、视频、文件,发送和接收全覆盖。
22
25
 
23
- 直接调用腾讯 ilinkai 接口收发微信消息,无中间层。你的 Agent 只需暴露一个 OpenAI 兼容的 HTTP 接口(`POST /v1/chat/completions`),任何语言都行。
26
+ <p align="center">
27
+ <img src="docs/wechat-image-send.png" width="250" alt="Agent 发送文件、图片、语音" />
28
+ <img src="docs/wechat-image-receive.png" width="250" alt="Agent 发送图片、视频、语音" />
29
+ <a href="https://github.com/kellyvv/wechat-to-anything/raw/main/docs/wechat-voice-demo.mp4">
30
+ <img src="docs/wechat-voice-demo.gif" width="250" alt="语音演示(点击播放有声版)" />
31
+ </a>
32
+ </p>
24
33
 
25
- ### 多种模态支持
34
+ ## 特性
26
35
 
27
- | 方向 | 图片 | 语音 | 视频 | 文件 |
28
- |---|---|---|---|---|
29
- | **微信 Agent** | ✅ 自动识别 | ✅ 语音转文字 | ✅ 自动接收 | ✅ 提取文本 |
30
- | **Agent 微信** | 自动发图 | ✅ 语音消息 | ✅ 视频消息 | 文本回复 |
36
+ - 🔌 **零依赖接入** `npx` 一条命令,无需 clone、无需配置
37
+ - 🧠 **Agent 无关** — 支持任何 OpenAI 兼容 API(Codex / Gemini / Claude / 自建)
38
+ - 📡 **全模态** 文本、图片、语音、视频、文件,双向全覆盖
39
+ - 🤖 **多 Agent** 同时接入多个 Agent,`@` 路由切换
40
+ - ⌨️ **打字指示器** — Agent 思考时显示"对方正在输入"
31
41
 
32
- ## 前置条件
42
+ ### 全模态支持矩阵
33
43
 
34
- - Node.js >= 22(`nvm install 22`)
44
+ | 模态 | 微信 Agent | Agent → 微信 |
45
+ |------|:---:|:---:|
46
+ | 📝 文本 | ✅ | ✅ |
47
+ | 📷 图片 | ✅ 自动识别 | ✅ HD 原图 |
48
+ | 🎤 语音 | ✅ 语音转文字 | ✅ 语音气泡 |
49
+ | 🎬 视频 | ✅ 自动接收 | ✅ 带缩略图 |
50
+ | 📄 文件 | ✅ 提取内容 | ✅ 可下载 |
35
51
 
36
52
  ## 快速开始
37
53
 
38
54
  ```bash
39
- # 一条命令,选你喜欢的 Agent:
55
+ # 选你喜欢的 Agent:
40
56
  npx wechat-to-anything --codex # OpenAI Codex
41
57
  npx wechat-to-anything --gemini # Google Gemini
42
58
  npx wechat-to-anything --claude # Claude Code
43
59
  npx wechat-to-anything --openclaw # OpenClaw
44
60
 
45
- # Agent 同时用:
46
- npx wechat-to-anything --codex --gemini
61
+ # 或直接传 URL:
62
+ npx wechat-to-anything http://your-agent:8000/v1
47
63
  ```
48
64
 
49
- > 需要先安装对应 CLI:`npm i -g @openai/codex` / `@google/gemini-cli` / `@anthropic-ai/claude-code` / `openclaw`
50
- >
51
- > 也支持直接传 URL:`npx wechat-to-anything http://your-agent:8000/v1`
65
+ > 首次使用:终端弹出二维码 微信扫码 完成。之后自动复用登录。
52
66
 
53
- ### 接入 OpenClaw
67
+ ### 环境依赖
54
68
 
55
69
  ```bash
56
- # 1. 安装并配置 OpenClaw
57
- npm i -g openclaw
58
- openclaw configure # 设置模型(如 Gemini / OpenAI)
70
+ # 1. Node.js >= 22
71
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
72
+ nvm install 22
73
+
74
+ # 2. Python 3 + pip
75
+ brew install python3 # macOS
76
+ apt install python3 python3-pip # Linux
59
77
 
60
- # 2. 启动 Gateway
61
- openclaw gateway
78
+ # 3. ffmpeg
79
+ brew install ffmpeg # macOS
80
+ apt install ffmpeg # Linux
62
81
 
63
- # 3. 启动桥(另一个终端)
64
- npx wechat-to-anything --openclaw
82
+ # 4. pilk
83
+ pip install pilk
65
84
  ```
66
85
 
67
- > OpenClaw 的 Gateway 需要先配好模型 provider(运行 `openclaw configure`)。
68
- > 如果 OpenClaw 已有 `openclaw-weixin` 插件,需先禁用以避免消息冲突。
86
+ ## 原理
69
87
 
70
- ### 首次使用
88
+ ```
89
+ 微信用户 ←→ 腾讯 ilinkai API ←→ wechat-to-anything ←→ 你的 Agent (HTTP)
90
+ ```
71
91
 
72
- 终端会弹出二维码 微信扫码 完成。之后自动复用登录凭证。
92
+ 直接调用腾讯 ilinkai 接口收发微信消息,无中间层、无逆向、无网页版。Agent 只需暴露一个 OpenAI 兼容的 HTTP 接口。
73
93
 
74
- ## 接入你自己的 Agent
94
+ ## 接入自己的 Agent
75
95
 
76
- 暴露 `POST /v1/chat/completions` 即可,任何语言:
96
+ 任何语言,暴露 `POST /v1/chat/completions` 即可:
77
97
 
78
98
  ```python
79
99
  @app.post("/v1/chat/completions")
@@ -83,38 +103,20 @@ def chat(request):
83
103
  return {"choices": [{"message": {"role": "assistant", "content": reply}}]}
84
104
  ```
85
105
 
86
- 然后 `npx wechat-to-anything http://your-agent:8000/v1`。
87
-
88
- ## 多 Agent 模式
89
-
90
- 同时接入多个 Agent,通过 `@` 前缀路由消息。支持 OpenAI 兼容格式和 [ACP (Agent Communication Protocol)](https://agentcommunicationprotocol.dev/) 两种协议:
91
-
92
- ```bash
93
- npx wechat-to-anything \
94
- --agent codex=http://localhost:3001/v1 \
95
- --agent gemini=http://localhost:3002/v1 \
96
- --agent bee=acp://localhost:8000/chat \
97
- --default codex
98
- ```
99
-
100
- > `http://` → OpenAI 格式,`acp://` → ACP 协议,自动识别。
106
+ 然后:`npx wechat-to-anything http://your-agent:8000/v1`
101
107
 
102
- 微信里使用:
103
-
104
- | 消息 | 效果 |
105
- |---|---|
106
- | `你好` | 发给默认 Agent |
107
- | `@codex 写个排序` | 路由到 Codex |
108
- | `@gemini 审查代码` | 路由到 Gemini |
109
- | `@bee 分析数据` | 路由到 ACP Agent |
110
- | `@list` | 查看已注册的 Agent |
111
- | `@切换 gemini` | 切换默认 Agent |
108
+ ## 多媒体协议
112
109
 
113
- Agent 模式下回复自动带 `[agentName]` 前缀标识来源。每个用户独立维护默认 Agent。
110
+ Agent 回复中包含特定格式即可自动发送多媒体:
114
111
 
115
- ## 多媒体格式
112
+ | 类型 | Agent 回复格式 | 说明 |
113
+ |------|--------------|------|
114
+ | 图片 | `![描述](URL或路径)` | 支持 URL、本地路径、data URI |
115
+ | 语音 | `[audio:路径或URL]` | MP3/WAV/OGG,需 `ffmpeg` + `pilk` |
116
+ | 视频 | `[video:路径或URL]` | 需 `ffmpeg` |
117
+ | 文件 | `[file:路径或URL]` | 任意文件类型 |
116
118
 
117
- **图片(微信 → Agent)**:遵循 [OpenAI Vision API](https://platform.openai.com/docs/guides/vision),`content` 为数组:
119
+ **图片接收**(微信 → Agent)遵循 [OpenAI Vision API](https://platform.openai.com/docs/guides/vision)
118
120
 
119
121
  ```json
120
122
  {
@@ -128,35 +130,32 @@ npx wechat-to-anything \
128
130
  }
129
131
  ```
130
132
 
131
- **图片(Agent 微信)**:回复中包含 `![desc](https://...)` 自动发图(HD 原图质量,自动生成缩略图)。支持 URL、本地路径、data URI。
132
-
133
- **语音(Agent → 微信)**:回复中包含 `[audio:path 或 URL]` 自动发语音气泡。支持 MP3、WAV、OGG 等。需要 `ffmpeg` 和 `pip install pilk`。
133
+ > 示例:[image-test.mjs](examples/image-test.mjs) · [voice-test.mjs](examples/voice-test.mjs) · [video-test-local.mjs](examples/video-test-local.mjs) · [file-test.mjs](examples/file-test.mjs)
134
134
 
135
- ```python
136
- @app.post("/v1/chat/completions")
137
- def chat(request):
138
- audio_path = your_tts(message) # → /tmp/reply.mp3
139
- reply = f"[audio:{audio_path}]\n这是文字版内容"
140
- return {"choices": [{"message": {"role": "assistant", "content": reply}}]}
141
- ```
135
+ ## 多 Agent 模式
142
136
 
143
- **视频(Agent 微信)**:回复中包含 `[video:path 或 URL]` 自动发视频消息(含缩略图)。需要 `ffmpeg`。
137
+ 同时接入多个 Agent,`@` 前缀路由。支持 OpenAI 格式和 [ACP 协议](https://agentcommunicationprotocol.dev/):
144
138
 
145
- ```python
146
- @app.post("/v1/chat/completions")
147
- def chat(request):
148
- reply = "[video:/tmp/demo.mp4]\n这是视频描述"
149
- return {"choices": [{"message": {"role": "assistant", "content": reply}}]}
139
+ ```bash
140
+ npx wechat-to-anything \
141
+ --agent codex=http://localhost:3001/v1 \
142
+ --agent gemini=http://localhost:3002/v1 \
143
+ --agent bee=acp://localhost:8000/chat \
144
+ --default codex
150
145
  ```
151
146
 
152
- > 示例:[examples/image-test.mjs](examples/image-test.mjs) · [examples/voice-test.mjs](examples/voice-test.mjs) · [examples/video-test-local.mjs](examples/video-test-local.mjs)
147
+ | 微信消息 | 效果 |
148
+ |---|---|
149
+ | `你好` | 发给默认 Agent |
150
+ | `@codex 写个排序` | 路由到 Codex |
151
+ | `@gemini 审查代码` | 路由到 Gemini |
152
+ | `@list` | 查看所有 Agent |
153
+ | `@切换 gemini` | 切换默认 |
153
154
 
154
155
  ## 凭证
155
156
 
156
157
  登录凭证保存在 `~/.wechat-to-anything/credentials.json`,删除即可重新登录。
157
158
 
158
-
159
-
160
159
  ## Star History
161
160
 
162
161
  如果这个项目帮到了你,请给个 ⭐ Star,这是对我们最大的支持!
@@ -17,10 +17,10 @@ import { randomBytes } from "node:crypto";
17
17
  /**
18
18
  * 统一调用接口 — 根据 URL 自动选择适配器
19
19
  */
20
- export async function callAgentAuto(url, messages) {
21
- if (url.startsWith("acp://")) return callACP(url, messages);
20
+ export async function callAgentAuto(url, messages, userId) {
21
+ if (url.startsWith("acp://")) return callACP(url, messages, userId);
22
22
  if (url.startsWith("cli://")) return callCLI(url, messages);
23
- return callOpenAI(url, messages);
23
+ return callOpenAI(url, messages, userId);
24
24
  }
25
25
 
26
26
  /**
@@ -50,11 +50,11 @@ export async function checkAgent(url) {
50
50
 
51
51
  // ========== OpenAI 适配器 ==========
52
52
 
53
- async function callOpenAI(agentUrl, messages) {
53
+ async function callOpenAI(agentUrl, messages, userId) {
54
54
  const res = await fetch(`${agentUrl}/chat/completions`, {
55
55
  method: "POST",
56
56
  headers: { "Content-Type": "application/json" },
57
- body: JSON.stringify({ messages }),
57
+ body: JSON.stringify({ messages, user: userId || undefined }),
58
58
  signal: AbortSignal.timeout(300_000),
59
59
  });
60
60
  if (!res.ok) {
@@ -74,7 +74,7 @@ function parseACPUrl(acpUrl) {
74
74
  return { httpUrl: `http://${withoutScheme.slice(0, slashIdx)}`, agentName: withoutScheme.slice(slashIdx + 1) };
75
75
  }
76
76
 
77
- async function callACP(acpUrl, messages) {
77
+ async function callACP(acpUrl, messages, userId) {
78
78
  const { httpUrl, agentName } = parseACPUrl(acpUrl);
79
79
  const input = messages.map((msg) => {
80
80
  if (typeof msg.content === "string") {
package/cli/bridge.mjs CHANGED
@@ -325,7 +325,7 @@ export async function start(agents, defaultAgent) {
325
325
  // 调用 Agent
326
326
  try {
327
327
  if (typing) await typing.onReplyStart();
328
- const reply = await callAgentAuto(agentUrl, agentMessages);
328
+ const reply = await callAgentAuto(agentUrl, agentMessages, from);
329
329
  if (typing) typing.onIdle();
330
330
  const agentTag = multiMode ? `[${targetAgent}] ` : "";
331
331
 
package/cli/cdn.mjs CHANGED
@@ -355,6 +355,7 @@ export async function uploadToCdn(filePath, toUserId, token, mediaType = 1) {
355
355
  aeskey: aeskey.toString("hex"),
356
356
  fileSize: rawsize,
357
357
  fileSizeCiphertext: filesize,
358
+ rawMd5: rawfilemd5,
358
359
  filekey,
359
360
  };
360
361
  }
package/cli/weixin.mjs CHANGED
@@ -286,8 +286,11 @@ export async function sendVoiceMessage(token, to, contextToken, audioBase64, dur
286
286
 
287
287
  /**
288
288
  * 发送文件消息(通过 CDN 引用)
289
+ * 格式参考微信原始 file_item: 44-char aes_key, 无 encrypt_type, 有 md5
289
290
  */
290
291
  export async function sendFileMessage(token, to, contextToken, uploaded, fileName) {
292
+ // aes_key: hex string → UTF-8 bytes → base64 = 44 chars(微信格式)
293
+ const aesKeyB64 = Buffer.from(uploaded.aeskey).toString("base64");
291
294
  await apiPost(
292
295
  "ilink/bot/sendmessage",
293
296
  {
@@ -302,10 +305,10 @@ export async function sendFileMessage(token, to, contextToken, uploaded, fileNam
302
305
  file_item: {
303
306
  media: {
304
307
  encrypt_query_param: uploaded.downloadParam,
305
- aes_key: Buffer.from(uploaded.aeskey, "hex").toString("base64"),
306
- encrypt_type: 1,
308
+ aes_key: aesKeyB64,
307
309
  },
308
310
  file_name: fileName,
311
+ md5: uploaded.rawMd5 || "",
309
312
  len: String(uploaded.fileSize),
310
313
  },
311
314
  }],
@@ -459,6 +462,7 @@ export function extractMedia(msg) {
459
462
  }
460
463
  // 文件
461
464
  if (item.type === 4 && item.file_item?.media?.encrypt_query_param) {
465
+
462
466
  return {
463
467
  type: "file",
464
468
  encryptQueryParam: item.file_item.media.encrypt_query_param,
Binary file
Binary file
Binary file
@@ -0,0 +1,39 @@
1
+ /**
2
+ * 文件发送测试脚本
3
+ *
4
+ * 用法: node examples/file-test.mjs [文件路径]
5
+ *
6
+ * 通过 CDN 上传文件,发送到自己的微信(用于测试)。
7
+ * 需要先扫码登录获取 credentials。
8
+ */
9
+ import { readFileSync } from "fs";
10
+ import { homedir, tmpdir } from "os";
11
+ import { join, basename } from "path";
12
+
13
+ const creds = JSON.parse(readFileSync(homedir() + "/.wechat-to-anything/credentials.json", "utf-8"));
14
+
15
+ // 测试文件:命令行指定或自动生成
16
+ let filePath = process.argv[2];
17
+ let fileName;
18
+ if (filePath) {
19
+ fileName = basename(filePath);
20
+ } else {
21
+ const { writeFileSync } = await import("fs");
22
+ filePath = join(tmpdir(), "wxta-test-file.txt");
23
+ writeFileSync(filePath, `Hello from wechat-to-anything!\n测试文件 ${new Date().toISOString()}\n`);
24
+ fileName = "wxta-test-file.txt";
25
+ console.log("未指定文件,已生成测试文件:", filePath);
26
+ }
27
+
28
+ const { uploadToCdn } = await import("../cli/cdn.mjs");
29
+ const { getUpdates, sendFileMessage } = await import("../cli/weixin.mjs");
30
+
31
+ const msgs = await getUpdates(creds.token);
32
+ const ct = msgs?.context_token || "";
33
+
34
+ console.log("上传文件:", fileName);
35
+ const uploaded = await uploadToCdn(filePath, creds.userId, creds.token, 3);
36
+ console.log("✅ CDN 上传完成 | 大小:", uploaded.fileSize, "bytes | md5:", uploaded.rawMd5);
37
+
38
+ await sendFileMessage(creds.token, creds.userId, ct, uploaded, fileName);
39
+ console.log("✅ 发送成功!请检查微信");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wechat-to-anything",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
4
4
  "description": "一条命令,把微信变成任何 AI Agent 的入口",
5
5
  "type": "module",
6
6
  "bin": {