openclaw-wechat-channel 0.1.2 → 0.3.0
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.md +111 -43
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +62 -32
- package/openclaw.plugin.json +10 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -27,32 +27,57 @@ openclaw plugins install openclaw-wechat-channel
|
|
|
27
27
|
### Upgrade
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
openclaw plugins update wechat
|
|
30
|
+
openclaw plugins update openclaw-wechat-channel
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
### Configuration
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
+
# Set Wechatify Server proxy URL (required)
|
|
37
|
+
openclaw config set channels.wechat.proxyUrl "http://your-proxy-server:19088"
|
|
38
|
+
|
|
36
39
|
# Set API Key (required)
|
|
37
40
|
openclaw config set channels.wechat.apiKey "your-api-key"
|
|
38
41
|
|
|
42
|
+
# Set webhook host — your OpenClaw server's public IP or domain (optional, auto-detected if omitted)
|
|
43
|
+
openclaw config set channels.wechat.webhookHost "your-public-ip"
|
|
44
|
+
|
|
39
45
|
# Set webhook port (optional, default: 18790)
|
|
40
46
|
openclaw config set channels.wechat.webhookPort 18790
|
|
41
47
|
|
|
48
|
+
# Set webhook path (optional, default: /webhook/wechat)
|
|
49
|
+
openclaw config set channels.wechat.webhookPath "/webhook/wechat"
|
|
50
|
+
|
|
42
51
|
# Enable the channel
|
|
43
52
|
openclaw config set channels.wechat.enabled true
|
|
44
53
|
```
|
|
45
54
|
|
|
46
|
-
### Configuration
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
### Configuration Reference
|
|
56
|
+
|
|
57
|
+
| Parameter | Required | Default | Description |
|
|
58
|
+
|---|---|---|---|
|
|
59
|
+
| `apiKey` | Yes | — | Wechatify Server API Key |
|
|
60
|
+
| `proxyUrl` | Yes | — | Wechatify Server address, e.g. `http://your-server:19088` |
|
|
61
|
+
| `webhookHost` | No | auto-detect | Public IP or domain of the OpenClaw server for receiving callbacks |
|
|
62
|
+
| `webhookPort` | No | `18790` | Port for the webhook listener |
|
|
63
|
+
| `webhookPath` | No | `/webhook/wechat` | Path for the webhook endpoint |
|
|
64
|
+
| `enabled` | No | `true` | Enable/disable the channel |
|
|
65
|
+
|
|
66
|
+
Example (`~/.openclaw/openclaw.json`):
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"channels": {
|
|
71
|
+
"wechat": {
|
|
72
|
+
"enabled": true,
|
|
73
|
+
"apiKey": "your-api-key",
|
|
74
|
+
"proxyUrl": "http://your-proxy-server:19088",
|
|
75
|
+
"webhookHost": "your-public-ip",
|
|
76
|
+
"webhookPort": 18790,
|
|
77
|
+
"webhookPath": "/webhook/wechat"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
56
81
|
```
|
|
57
82
|
|
|
58
83
|
### Features
|
|
@@ -64,16 +89,25 @@ channels:
|
|
|
64
89
|
|
|
65
90
|
### Multi-Account
|
|
66
91
|
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"channels": {
|
|
95
|
+
"wechat": {
|
|
96
|
+
"accounts": {
|
|
97
|
+
"work": {
|
|
98
|
+
"apiKey": "work-api-key",
|
|
99
|
+
"proxyUrl": "http://proxy-1:19088",
|
|
100
|
+
"webhookPort": 18790
|
|
101
|
+
},
|
|
102
|
+
"personal": {
|
|
103
|
+
"apiKey": "personal-api-key",
|
|
104
|
+
"proxyUrl": "http://proxy-2:19088",
|
|
105
|
+
"webhookPort": 18791
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
77
111
|
```
|
|
78
112
|
|
|
79
113
|
---
|
|
@@ -99,32 +133,57 @@ openclaw plugins install openclaw-wechat-channel
|
|
|
99
133
|
### 升级
|
|
100
134
|
|
|
101
135
|
```bash
|
|
102
|
-
openclaw plugins update wechat
|
|
136
|
+
openclaw plugins update openclaw-wechat-channel
|
|
103
137
|
```
|
|
104
138
|
|
|
105
139
|
### 配置
|
|
106
140
|
|
|
107
141
|
```bash
|
|
142
|
+
# 设置 Wechatify Server 代理地址(必填)
|
|
143
|
+
openclaw config set channels.wechat.proxyUrl "http://your-proxy-server:19088"
|
|
144
|
+
|
|
108
145
|
# 设置 API Key(必填)
|
|
109
146
|
openclaw config set channels.wechat.apiKey "your-api-key"
|
|
110
147
|
|
|
111
|
-
# 设置
|
|
148
|
+
# 设置 Webhook 公网地址 — OpenClaw 服务器的公网 IP 或域名(可选,不填则自动检测)
|
|
149
|
+
openclaw config set channels.wechat.webhookHost "your-public-ip"
|
|
150
|
+
|
|
151
|
+
# 设置 Webhook 端口(可选,默认 18790)
|
|
112
152
|
openclaw config set channels.wechat.webhookPort 18790
|
|
113
153
|
|
|
154
|
+
# 设置 Webhook 路径(可选,默认 /webhook/wechat)
|
|
155
|
+
openclaw config set channels.wechat.webhookPath "/webhook/wechat"
|
|
156
|
+
|
|
114
157
|
# 启用通道
|
|
115
158
|
openclaw config set channels.wechat.enabled true
|
|
116
159
|
```
|
|
117
160
|
|
|
118
|
-
###
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
161
|
+
### 配置参考
|
|
162
|
+
|
|
163
|
+
| 参数 | 必填 | 默认值 | 说明 |
|
|
164
|
+
|---|---|---|---|
|
|
165
|
+
| `apiKey` | 是 | — | Wechatify Server 的 API Key |
|
|
166
|
+
| `proxyUrl` | 是 | — | Wechatify Server 地址,如 `http://your-server:19088` |
|
|
167
|
+
| `webhookHost` | 否 | 自动检测 | OpenClaw 服务器的公网 IP 或域名,用于接收消息回调 |
|
|
168
|
+
| `webhookPort` | 否 | `18790` | Webhook 监听端口 |
|
|
169
|
+
| `webhookPath` | 否 | `/webhook/wechat` | Webhook 路径 |
|
|
170
|
+
| `enabled` | 否 | `true` | 是否启用通道 |
|
|
171
|
+
|
|
172
|
+
配置示例(`~/.openclaw/openclaw.json`):
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"channels": {
|
|
177
|
+
"wechat": {
|
|
178
|
+
"enabled": true,
|
|
179
|
+
"apiKey": "your-api-key",
|
|
180
|
+
"proxyUrl": "http://your-proxy-server:19088",
|
|
181
|
+
"webhookHost": "your-public-ip",
|
|
182
|
+
"webhookPort": 18790,
|
|
183
|
+
"webhookPath": "/webhook/wechat"
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
128
187
|
```
|
|
129
188
|
|
|
130
189
|
### 功能
|
|
@@ -136,16 +195,25 @@ channels:
|
|
|
136
195
|
|
|
137
196
|
### 多账号配置
|
|
138
197
|
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"channels": {
|
|
201
|
+
"wechat": {
|
|
202
|
+
"accounts": {
|
|
203
|
+
"work": {
|
|
204
|
+
"apiKey": "work-api-key",
|
|
205
|
+
"proxyUrl": "http://proxy-1:19088",
|
|
206
|
+
"webhookPort": 18790
|
|
207
|
+
},
|
|
208
|
+
"personal": {
|
|
209
|
+
"apiKey": "personal-api-key",
|
|
210
|
+
"proxyUrl": "http://proxy-2:19088",
|
|
211
|
+
"webhookPort": 18791
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
149
217
|
```
|
|
150
218
|
|
|
151
219
|
---
|
package/dist/index.d.mts
CHANGED
|
@@ -17,6 +17,7 @@ interface WechatAccountConfig {
|
|
|
17
17
|
wcId?: string;
|
|
18
18
|
nickName?: string;
|
|
19
19
|
configured?: boolean;
|
|
20
|
+
allowUsers?: string[];
|
|
20
21
|
}
|
|
21
22
|
interface WechatConfig {
|
|
22
23
|
enabled?: boolean;
|
|
@@ -25,6 +26,7 @@ interface WechatConfig {
|
|
|
25
26
|
webhookHost?: string;
|
|
26
27
|
webhookPort?: number;
|
|
27
28
|
webhookPath?: string;
|
|
29
|
+
allowUsers?: string[];
|
|
28
30
|
accounts?: Record<string, WechatAccountConfig | undefined>;
|
|
29
31
|
}
|
|
30
32
|
//#endregion
|
|
@@ -43,6 +45,7 @@ interface ResolvedWeChatAccount {
|
|
|
43
45
|
webhookHost?: string;
|
|
44
46
|
webhookPort: number;
|
|
45
47
|
webhookPath: string;
|
|
48
|
+
allowUsers?: string[];
|
|
46
49
|
config: WechatAccountConfig;
|
|
47
50
|
}
|
|
48
51
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_ACCOUNT_ID, createReplyPrefixContext, emptyPluginConfigSchema } from "openclaw/plugin-sdk";
|
|
2
2
|
import http from "node:http";
|
|
3
|
+
import { H3, defineEventHandler, readBody } from "h3";
|
|
4
|
+
import { toNodeHandler } from "h3/node";
|
|
3
5
|
|
|
4
6
|
//#region src/proxy-client.ts
|
|
5
7
|
var ProxyClient = class {
|
|
@@ -105,14 +107,17 @@ function getWeChatRuntime() {
|
|
|
105
107
|
//#region src/reply-dispatcher.ts
|
|
106
108
|
function createWeChatReplyDispatcher(params) {
|
|
107
109
|
const core = getWeChatRuntime();
|
|
108
|
-
const { cfg, agentId, runtime, apiKey, replyTo, accountId } = params;
|
|
110
|
+
const { cfg, agentId, runtime, apiKey, proxyUrl, replyTo, accountId } = params;
|
|
109
111
|
const prefixContext = createReplyPrefixContext({
|
|
110
112
|
cfg,
|
|
111
113
|
agentId
|
|
112
114
|
});
|
|
113
115
|
const textChunkLimit = core.channel.text.resolveTextChunkLimit(cfg, "wechat", accountId, { fallbackLimit: 2e3 });
|
|
114
116
|
const chunkMode = core.channel.text.resolveChunkMode(cfg, "wechat");
|
|
115
|
-
const client = new ProxyClient({
|
|
117
|
+
const client = new ProxyClient({
|
|
118
|
+
apiKey,
|
|
119
|
+
baseUrl: proxyUrl
|
|
120
|
+
});
|
|
116
121
|
const { dispatcher, replyOptions, markDispatchIdle } = core.channel.reply.createReplyDispatcherWithTyping({
|
|
117
122
|
responsePrefix: prefixContext.responsePrefix,
|
|
118
123
|
responsePrefixContextProvider: prefixContext.responsePrefixContextProvider,
|
|
@@ -155,6 +160,7 @@ const DEDUP_WINDOW_MS = 1800 * 1e3;
|
|
|
155
160
|
const DEDUP_MAX_SIZE = 1e3;
|
|
156
161
|
const DEDUP_CLEANUP_INTERVAL_MS = 300 * 1e3;
|
|
157
162
|
let lastCleanup = Date.now();
|
|
163
|
+
const notifiedNonWhitelistUsers = /* @__PURE__ */ new Set();
|
|
158
164
|
function tryRecordMessage(messageId) {
|
|
159
165
|
const now = Date.now();
|
|
160
166
|
if (now - lastCleanup > DEDUP_CLEANUP_INTERVAL_MS) {
|
|
@@ -177,6 +183,18 @@ async function handleWeChatMessage(params) {
|
|
|
177
183
|
log(`wechat: skipping duplicate message ${message.id}`);
|
|
178
184
|
return;
|
|
179
185
|
}
|
|
186
|
+
const allowUsers = account.allowUsers;
|
|
187
|
+
if (allowUsers && allowUsers.length > 0 && message.sender.id !== account.wcId && !allowUsers.includes(message.sender.id)) {
|
|
188
|
+
log(`wechat[${accountId}]: ignoring message from ${message.sender.id} (not in allowUsers)`);
|
|
189
|
+
if (account.wcId && !notifiedNonWhitelistUsers.has(message.sender.id)) {
|
|
190
|
+
notifiedNonWhitelistUsers.add(message.sender.id);
|
|
191
|
+
await new ProxyClient({
|
|
192
|
+
apiKey: account.apiKey,
|
|
193
|
+
baseUrl: account.proxyUrl
|
|
194
|
+
}).sendText(account.wcId, `‼️ ${message.sender.id} 不在白名单中,配置 allowUsers 后即可回复`).catch(() => {});
|
|
195
|
+
}
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
180
198
|
const isGroup = !!message.group;
|
|
181
199
|
log(`wechat[${accountId}]: received ${message.type} from ${message.sender.id}${isGroup ? ` in group ${message.group.id}` : ""}`);
|
|
182
200
|
if (message.type !== "text") {
|
|
@@ -240,6 +258,7 @@ async function handleWeChatMessage(params) {
|
|
|
240
258
|
agentId: route.agentId,
|
|
241
259
|
runtime,
|
|
242
260
|
apiKey: account.apiKey,
|
|
261
|
+
proxyUrl: account.proxyUrl,
|
|
243
262
|
replyTo,
|
|
244
263
|
accountId: account.accountId
|
|
245
264
|
});
|
|
@@ -260,23 +279,17 @@ async function handleWeChatMessage(params) {
|
|
|
260
279
|
//#endregion
|
|
261
280
|
//#region src/callback-server.ts
|
|
262
281
|
async function startCallbackServer(options) {
|
|
263
|
-
const { port, onMessage, abortSignal } = options;
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
console.error("Failed to process webhook:", err);
|
|
275
|
-
res.writeHead(400).end("Bad Request");
|
|
276
|
-
}
|
|
277
|
-
});
|
|
278
|
-
} else res.writeHead(404).end("Not Found");
|
|
279
|
-
});
|
|
282
|
+
const { port, apiKey, onMessage, abortSignal } = options;
|
|
283
|
+
const app = new H3();
|
|
284
|
+
app.post("/webhook/wechat", defineEventHandler(async (event) => {
|
|
285
|
+
const incomingKey = event.req.headers.get("x-api-key");
|
|
286
|
+
if (apiKey && incomingKey !== apiKey) throw createHttpError(401, "Unauthorized");
|
|
287
|
+
const message = convertToMessageContext(await readBody(event));
|
|
288
|
+
if (message) onMessage(message);
|
|
289
|
+
return "OK";
|
|
290
|
+
}));
|
|
291
|
+
const handler = toNodeHandler(app);
|
|
292
|
+
const server = http.createServer(handler);
|
|
280
293
|
return new Promise((resolve, reject) => {
|
|
281
294
|
server.listen(port, "0.0.0.0", () => {
|
|
282
295
|
const addr = server.address();
|
|
@@ -299,6 +312,11 @@ async function startCallbackServer(options) {
|
|
|
299
312
|
});
|
|
300
313
|
});
|
|
301
314
|
}
|
|
315
|
+
function createHttpError(statusCode, message) {
|
|
316
|
+
const error = new Error(message);
|
|
317
|
+
error.statusCode = statusCode;
|
|
318
|
+
return error;
|
|
319
|
+
}
|
|
302
320
|
function normalizePayload(payload) {
|
|
303
321
|
const { messageType, wcId } = payload;
|
|
304
322
|
if (payload.fromUser) return {
|
|
@@ -402,6 +420,7 @@ function displayLoginSuccess(nickName, wcId) {
|
|
|
402
420
|
|
|
403
421
|
//#endregion
|
|
404
422
|
//#region src/channel.ts
|
|
423
|
+
const runningServers = /* @__PURE__ */ new Map();
|
|
405
424
|
const PLUGIN_META = {
|
|
406
425
|
id: "wechat",
|
|
407
426
|
label: "WeChat",
|
|
@@ -426,7 +445,8 @@ function resolveWeChatAccount({ cfg, accountId }) {
|
|
|
426
445
|
proxyUrl: wechatCfg?.proxyUrl,
|
|
427
446
|
webhookHost: wechatCfg?.webhookHost,
|
|
428
447
|
webhookPort: wechatCfg?.webhookPort,
|
|
429
|
-
webhookPath: wechatCfg?.webhookPath
|
|
448
|
+
webhookPath: wechatCfg?.webhookPath,
|
|
449
|
+
allowUsers: wechatCfg?.allowUsers
|
|
430
450
|
};
|
|
431
451
|
const defaultAccount = wechatCfg?.accounts?.default;
|
|
432
452
|
accountCfg = {
|
|
@@ -454,6 +474,7 @@ function resolveWeChatAccount({ cfg, accountId }) {
|
|
|
454
474
|
webhookHost: accountCfg.webhookHost,
|
|
455
475
|
webhookPort: accountCfg.webhookPort || 18790,
|
|
456
476
|
webhookPath: accountCfg.webhookPath || "/webhook/wechat",
|
|
477
|
+
allowUsers: accountCfg.allowUsers,
|
|
457
478
|
config: accountCfg
|
|
458
479
|
};
|
|
459
480
|
}
|
|
@@ -491,6 +512,10 @@ const wechatPlugin = {
|
|
|
491
512
|
webhookHost: { type: "string" },
|
|
492
513
|
webhookPort: { type: "integer" },
|
|
493
514
|
webhookPath: { type: "string" },
|
|
515
|
+
allowUsers: {
|
|
516
|
+
type: "array",
|
|
517
|
+
items: { type: "string" }
|
|
518
|
+
},
|
|
494
519
|
accounts: {
|
|
495
520
|
type: "object",
|
|
496
521
|
additionalProperties: {
|
|
@@ -505,7 +530,11 @@ const wechatPlugin = {
|
|
|
505
530
|
webhookPort: { type: "integer" },
|
|
506
531
|
webhookPath: { type: "string" },
|
|
507
532
|
wcId: { type: "string" },
|
|
508
|
-
nickName: { type: "string" }
|
|
533
|
+
nickName: { type: "string" },
|
|
534
|
+
allowUsers: {
|
|
535
|
+
type: "array",
|
|
536
|
+
items: { type: "string" }
|
|
537
|
+
}
|
|
509
538
|
},
|
|
510
539
|
required: ["apiKey"]
|
|
511
540
|
}
|
|
@@ -584,15 +613,8 @@ const wechatPlugin = {
|
|
|
584
613
|
name: account.name || account.nickName || account.accountId,
|
|
585
614
|
wcId: account.wcId,
|
|
586
615
|
isLoggedIn: account.isLoggedIn
|
|
587
|
-
})
|
|
588
|
-
resolveAllowFrom: ({ cfg, accountId }) => {
|
|
589
|
-
return [];
|
|
590
|
-
},
|
|
591
|
-
formatAllowFrom: ({ allowFrom }) => allowFrom.map(String)
|
|
616
|
+
})
|
|
592
617
|
},
|
|
593
|
-
security: { collectWarnings: ({ cfg, accountId }) => {
|
|
594
|
-
return [];
|
|
595
|
-
} },
|
|
596
618
|
setup: {
|
|
597
619
|
resolveAccountId: () => DEFAULT_ACCOUNT_ID,
|
|
598
620
|
applyAccountConfig: ({ cfg, accountId }) => {
|
|
@@ -640,7 +662,7 @@ const wechatPlugin = {
|
|
|
640
662
|
},
|
|
641
663
|
directory: {
|
|
642
664
|
self: async () => null,
|
|
643
|
-
listPeers: async ({ cfg,
|
|
665
|
+
listPeers: async ({ cfg, limit, accountId }) => {
|
|
644
666
|
const account = resolveWeChatAccount({
|
|
645
667
|
cfg,
|
|
646
668
|
accountId: accountId || DEFAULT_ACCOUNT_ID
|
|
@@ -655,7 +677,7 @@ const wechatPlugin = {
|
|
|
655
677
|
name: id
|
|
656
678
|
}));
|
|
657
679
|
},
|
|
658
|
-
listGroups: async ({ cfg,
|
|
680
|
+
listGroups: async ({ cfg, limit, accountId }) => {
|
|
659
681
|
const account = resolveWeChatAccount({
|
|
660
682
|
cfg,
|
|
661
683
|
accountId: accountId || DEFAULT_ACCOUNT_ID
|
|
@@ -688,7 +710,7 @@ const wechatPlugin = {
|
|
|
688
710
|
lastError: snapshot.lastError ?? null,
|
|
689
711
|
port: snapshot.port ?? null
|
|
690
712
|
}),
|
|
691
|
-
probeAccount: async ({ account
|
|
713
|
+
probeAccount: async ({ account }) => {
|
|
692
714
|
const client = new ProxyClient({
|
|
693
715
|
apiKey: account.apiKey,
|
|
694
716
|
baseUrl: account.proxyUrl
|
|
@@ -790,6 +812,12 @@ const wechatPlugin = {
|
|
|
790
812
|
log?.info(`Using webhook URL: ${webhookUrl}`);
|
|
791
813
|
log?.info(`Registering webhook with proxy service for wcId: ${account.wcId}`);
|
|
792
814
|
await client.registerWebhook(account.wcId, webhookUrl);
|
|
815
|
+
const prevStop = runningServers.get(accountId);
|
|
816
|
+
if (prevStop) {
|
|
817
|
+
prevStop();
|
|
818
|
+
runningServers.delete(accountId);
|
|
819
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
820
|
+
}
|
|
793
821
|
const { stop } = await startCallbackServer({
|
|
794
822
|
port,
|
|
795
823
|
apiKey: account.apiKey,
|
|
@@ -807,10 +835,12 @@ const wechatPlugin = {
|
|
|
807
835
|
abortSignal
|
|
808
836
|
});
|
|
809
837
|
abortSignal?.addEventListener("abort", stop);
|
|
838
|
+
runningServers.set(accountId, stop);
|
|
810
839
|
log?.info(`WeChat account ${accountId} started successfully on port ${port}`);
|
|
811
840
|
log?.info(`Webhook URL: ${webhookUrl}`);
|
|
812
841
|
return { async stop() {
|
|
813
842
|
stop();
|
|
843
|
+
runningServers.delete(accountId);
|
|
814
844
|
setStatus({
|
|
815
845
|
accountId,
|
|
816
846
|
port,
|
package/openclaw.plugin.json
CHANGED
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
"channels": ["wechat"],
|
|
4
4
|
"configSchema": {
|
|
5
5
|
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
6
7
|
"properties": {
|
|
8
|
+
"enabled": { "type": "boolean" },
|
|
9
|
+
"apiKey": { "type": "string" },
|
|
10
|
+
"proxyUrl": { "type": "string" },
|
|
11
|
+
"webhookHost": { "type": "string" },
|
|
12
|
+
"webhookPort": { "type": "integer" },
|
|
13
|
+
"webhookPath": { "type": "string" },
|
|
7
14
|
"accounts": {
|
|
8
15
|
"type": "object",
|
|
9
16
|
"additionalProperties": {
|
|
@@ -13,8 +20,10 @@
|
|
|
13
20
|
"enabled": { "type": "boolean" },
|
|
14
21
|
"name": { "type": "string" },
|
|
15
22
|
"apiKey": { "type": "string" },
|
|
23
|
+
"proxyUrl": { "type": "string" },
|
|
24
|
+
"webhookHost": { "type": "string" },
|
|
16
25
|
"webhookPort": { "type": "integer" },
|
|
17
|
-
"
|
|
26
|
+
"webhookPath": { "type": "string" },
|
|
18
27
|
"wcId": { "type": "string" },
|
|
19
28
|
"nickName": { "type": "string" }
|
|
20
29
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-wechat-channel",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"packageManager": "pnpm@10.30.0",
|
|
6
6
|
"description": "OpenClaw WeChat channel plugin via Proxy API",
|
|
7
7
|
"license": "MIT",
|
|
@@ -63,6 +63,9 @@
|
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"openclaw": ">=2026.2.9"
|
|
65
65
|
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"h3": "2.0.1-rc.14"
|
|
68
|
+
},
|
|
66
69
|
"devDependencies": {
|
|
67
70
|
"@antfu/eslint-config": "^7.4.3",
|
|
68
71
|
"@types/node": "^25.3.0",
|