xabot-cli 1.4.2

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.
Files changed (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +126 -0
  3. package/README.zh-CN.md +126 -0
  4. package/dist/bridge/index.d.ts +93 -0
  5. package/dist/bridge/index.d.ts.map +1 -0
  6. package/dist/bridge/index.js +811 -0
  7. package/dist/bridge/index.js.map +1 -0
  8. package/dist/bridge/input-parser.d.ts +16 -0
  9. package/dist/bridge/input-parser.d.ts.map +1 -0
  10. package/dist/bridge/input-parser.js +20 -0
  11. package/dist/bridge/input-parser.js.map +1 -0
  12. package/dist/cli/chat.d.ts +38 -0
  13. package/dist/cli/chat.d.ts.map +1 -0
  14. package/dist/cli/chat.js +147 -0
  15. package/dist/cli/chat.js.map +1 -0
  16. package/dist/cli/feishu.d.ts +3 -0
  17. package/dist/cli/feishu.d.ts.map +1 -0
  18. package/dist/cli/feishu.js +79 -0
  19. package/dist/cli/feishu.js.map +1 -0
  20. package/dist/cli/health.d.ts +15 -0
  21. package/dist/cli/health.d.ts.map +1 -0
  22. package/dist/cli/health.js +26 -0
  23. package/dist/cli/health.js.map +1 -0
  24. package/dist/cli/index.d.ts +13 -0
  25. package/dist/cli/index.d.ts.map +1 -0
  26. package/dist/cli/index.js +43 -0
  27. package/dist/cli/index.js.map +1 -0
  28. package/dist/cli/run.d.ts +20 -0
  29. package/dist/cli/run.d.ts.map +1 -0
  30. package/dist/cli/run.js +43 -0
  31. package/dist/cli/run.js.map +1 -0
  32. package/dist/cli/wechat.d.ts +3 -0
  33. package/dist/cli/wechat.d.ts.map +1 -0
  34. package/dist/cli/wechat.js +86 -0
  35. package/dist/cli/wechat.js.map +1 -0
  36. package/dist/core/client.d.ts +31 -0
  37. package/dist/core/client.d.ts.map +1 -0
  38. package/dist/core/client.js +2 -0
  39. package/dist/core/client.js.map +1 -0
  40. package/dist/core/error.d.ts +11 -0
  41. package/dist/core/error.d.ts.map +1 -0
  42. package/dist/core/error.js +21 -0
  43. package/dist/core/error.js.map +1 -0
  44. package/dist/core/fs-utils.d.ts +17 -0
  45. package/dist/core/fs-utils.d.ts.map +1 -0
  46. package/dist/core/fs-utils.js +84 -0
  47. package/dist/core/fs-utils.js.map +1 -0
  48. package/dist/core/logger.d.ts +10 -0
  49. package/dist/core/logger.d.ts.map +1 -0
  50. package/dist/core/logger.js +44 -0
  51. package/dist/core/logger.js.map +1 -0
  52. package/dist/core/pairing.d.ts +10 -0
  53. package/dist/core/pairing.d.ts.map +1 -0
  54. package/dist/core/pairing.js +22 -0
  55. package/dist/core/pairing.js.map +1 -0
  56. package/dist/core/types.d.ts +50 -0
  57. package/dist/core/types.d.ts.map +1 -0
  58. package/dist/core/types.js +11 -0
  59. package/dist/core/types.js.map +1 -0
  60. package/dist/index.d.ts +13 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +9 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/platforms/feishu/client.d.ts +49 -0
  65. package/dist/platforms/feishu/client.d.ts.map +1 -0
  66. package/dist/platforms/feishu/client.js +296 -0
  67. package/dist/platforms/feishu/client.js.map +1 -0
  68. package/dist/platforms/feishu/message.d.ts +49 -0
  69. package/dist/platforms/feishu/message.d.ts.map +1 -0
  70. package/dist/platforms/feishu/message.js +131 -0
  71. package/dist/platforms/feishu/message.js.map +1 -0
  72. package/dist/platforms/feishu/upload.d.ts +11 -0
  73. package/dist/platforms/feishu/upload.d.ts.map +1 -0
  74. package/dist/platforms/feishu/upload.js +60 -0
  75. package/dist/platforms/feishu/upload.js.map +1 -0
  76. package/dist/platforms/wechat/client.d.ts +53 -0
  77. package/dist/platforms/wechat/client.d.ts.map +1 -0
  78. package/dist/platforms/wechat/client.js +301 -0
  79. package/dist/platforms/wechat/client.js.map +1 -0
  80. package/dist/platforms/wechat/crypto.d.ts +23 -0
  81. package/dist/platforms/wechat/crypto.d.ts.map +1 -0
  82. package/dist/platforms/wechat/crypto.js +46 -0
  83. package/dist/platforms/wechat/crypto.js.map +1 -0
  84. package/dist/platforms/wechat/login.d.ts +19 -0
  85. package/dist/platforms/wechat/login.d.ts.map +1 -0
  86. package/dist/platforms/wechat/login.js +71 -0
  87. package/dist/platforms/wechat/login.js.map +1 -0
  88. package/dist/platforms/wechat/message.d.ts +102 -0
  89. package/dist/platforms/wechat/message.d.ts.map +1 -0
  90. package/dist/platforms/wechat/message.js +212 -0
  91. package/dist/platforms/wechat/message.js.map +1 -0
  92. package/dist/platforms/wechat/upload.d.ts +10 -0
  93. package/dist/platforms/wechat/upload.d.ts.map +1 -0
  94. package/dist/platforms/wechat/upload.js +86 -0
  95. package/dist/platforms/wechat/upload.js.map +1 -0
  96. package/dist/xacpp/establish-handler.d.ts +58 -0
  97. package/dist/xacpp/establish-handler.d.ts.map +1 -0
  98. package/dist/xacpp/establish-handler.js +152 -0
  99. package/dist/xacpp/establish-handler.js.map +1 -0
  100. package/dist/xacpp/index.d.ts +3 -0
  101. package/dist/xacpp/index.d.ts.map +1 -0
  102. package/dist/xacpp/index.js +3 -0
  103. package/dist/xacpp/index.js.map +1 -0
  104. package/dist/xacpp/initiator-session-handler.d.ts +30 -0
  105. package/dist/xacpp/initiator-session-handler.d.ts.map +1 -0
  106. package/dist/xacpp/initiator-session-handler.js +233 -0
  107. package/dist/xacpp/initiator-session-handler.js.map +1 -0
  108. package/dist/xacpp/session-handler.d.ts +17 -0
  109. package/dist/xacpp/session-handler.d.ts.map +1 -0
  110. package/dist/xacpp/session-handler.js +27 -0
  111. package/dist/xacpp/session-handler.js.map +1 -0
  112. package/dist/xacpp/stdin-router.d.ts +23 -0
  113. package/dist/xacpp/stdin-router.d.ts.map +1 -0
  114. package/dist/xacpp/stdin-router.js +46 -0
  115. package/dist/xacpp/stdin-router.js.map +1 -0
  116. package/package.json +44 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/platforms/wechat/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,gBAAgB,EAAgC,MAAM,qBAAqB,CAAC;AAQrF,MAAM,WAAW,YAAY;IAC3B,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yBAAyB;IACzB,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACxC;AAOD;;;;;;GAMG;AACH,qBAAa,YAAa,YAAW,cAAc;IACjD,QAAQ,CAAC,QAAQ,EAAG,QAAQ,CAAU;IAEtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA6B;IAC/D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiB;IAC/C,OAAO,CAAC,cAAc,CAAyC;IAC/D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4D;IAE1F,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAgC;gBAErC,MAAM,EAAE,YAAY;YAYlB,IAAI;IAoBZ,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAOhB,QAAQ;IAqGhB,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;YAkC5D,SAAS;IAsBvB,QAAQ,IAAI,aAAa,CAAC,OAAO,CAAC;IA4BlC,qEAAqE;IACrE,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAUlC,gBAAgB,IAAI,gBAAgB;IAI9B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;YAUpB,iBAAiB;YAoBjB,gBAAgB;IASxB,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/F,sBAAsB,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E,sBAAsB,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAInG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAa7B"}
@@ -0,0 +1,301 @@
1
+ import { StreamCapability, messageId, channelId, userId } from '../../core/types.js';
2
+ import { XabotError } from '../../core/error.js';
3
+ import { toStandardMessage, fromMessageContent, fromMessageContentWithUpload, processInboundMedia } from './message.js';
4
+ import { uploadMedia } from './upload.js';
5
+ import { randomBytes } from 'node:crypto';
6
+ import { createLogger } from '../../core/logger.js';
7
+ const log = createLogger('WechatClient');
8
+ const DEFAULT_BASE_URL = 'https://ilinkai.weixin.qq.com';
9
+ const DEFAULT_POLL_TIMEOUT_MS = 35_000;
10
+ const MAX_RETRY_DELAY_MS = 30_000;
11
+ const TYPING_TICKET_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
12
+ /**
13
+ * WeChat iLink Bot platform client using HTTP long polling.
14
+ *
15
+ * Connects to ilinkai.weixin.qq.com:
16
+ * - Long-polls POST /ilink/bot/getupdates for incoming messages
17
+ * - Sends messages via POST /ilink/bot/sendmessage
18
+ */
19
+ export class WechatClient {
20
+ platform = 'wechat';
21
+ config;
22
+ token;
23
+ baseUrl;
24
+ pollTimeoutMs;
25
+ xWechatUin;
26
+ getUpdatesBuf = '';
27
+ contextTokenStore = new Map();
28
+ messageBuffer = [];
29
+ messageResolve = null;
30
+ typingTickets = new Map();
31
+ connected = false;
32
+ abortCtrl = null;
33
+ constructor(config) {
34
+ this.config = config;
35
+ this.token = config.token;
36
+ this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
37
+ this.pollTimeoutMs = config.longPollTimeoutMs ?? DEFAULT_POLL_TIMEOUT_MS;
38
+ this.xWechatUin = randomBytes(4).toString('base64');
39
+ }
40
+ // --------------------------------------------------------------------------
41
+ // Internal helpers
42
+ // --------------------------------------------------------------------------
43
+ async post(path, body) {
44
+ const url = `${this.baseUrl}${path}`;
45
+ const headers = {
46
+ 'Content-Type': 'application/json',
47
+ AuthorizationType: 'ilink_bot_token',
48
+ Authorization: `Bearer ${this.token}`,
49
+ 'X-WECHAT-UIN': this.xWechatUin,
50
+ };
51
+ return fetch(url, {
52
+ method: 'POST',
53
+ headers,
54
+ body: JSON.stringify(body),
55
+ signal: AbortSignal.timeout(this.pollTimeoutMs + 30_000),
56
+ });
57
+ }
58
+ // --------------------------------------------------------------------------
59
+ // PlatformClient implementation
60
+ // --------------------------------------------------------------------------
61
+ async connect() {
62
+ if (this.connected)
63
+ return;
64
+ this.abortCtrl = new AbortController();
65
+ this.connected = true;
66
+ void this.pollLoop();
67
+ }
68
+ async pollLoop() {
69
+ const ctrl = this.abortCtrl;
70
+ let retryDelay = 1000;
71
+ while (!ctrl.signal.aborted) {
72
+ try {
73
+ const res = await this.post('/ilink/bot/getupdates', {
74
+ get_updates_buf: this.getUpdatesBuf,
75
+ base_info: { channel_version: '1' },
76
+ });
77
+ if (!res.ok) {
78
+ throw XabotError.platform(`WechatClient poll error: HTTP ${res.status}`);
79
+ }
80
+ const data = (await res.json());
81
+ // Real API returns { msgs, get_updates_buf } without ret field on success.
82
+ // Only check ret/errcode when they are present.
83
+ if (data.ret !== undefined && data.ret !== 0) {
84
+ if (data.errcode === -14) {
85
+ log.warn('session expired (errcode=-14)');
86
+ if (this.config.onTokenExpired) {
87
+ try {
88
+ const newToken = await this.config.onTokenExpired();
89
+ this.renewToken(newToken);
90
+ retryDelay = 1000;
91
+ continue;
92
+ }
93
+ catch (err) {
94
+ log.error('token renewal failed: %s', err);
95
+ void this.close();
96
+ break;
97
+ }
98
+ }
99
+ void this.close();
100
+ break;
101
+ }
102
+ throw XabotError.platform(`WechatClient poll error: ret=${data.ret}, errcode=${data.errcode}`);
103
+ }
104
+ this.getUpdatesBuf = data.get_updates_buf ?? '';
105
+ for (const msg of data.msgs ?? []) {
106
+ if (msg.message_type !== 1)
107
+ continue;
108
+ this.contextTokenStore.set(msg.from_user_id, msg.context_token);
109
+ let standardMsg;
110
+ const item = msg.item_list[0];
111
+ if (!item)
112
+ continue;
113
+ if (item.type === 1) {
114
+ standardMsg = toStandardMessage(msg);
115
+ }
116
+ else {
117
+ let content;
118
+ let fallback = false;
119
+ try {
120
+ content = await processInboundMedia(item);
121
+ }
122
+ catch (err) {
123
+ const reason = err instanceof Error ? err.message : String(err);
124
+ log.warn('inbound media failed: %s', reason);
125
+ content = { type: 'text', text: `[${reason}]` };
126
+ fallback = true;
127
+ }
128
+ standardMsg = toStandardMessage(msg);
129
+ standardMsg.content = content;
130
+ standardMsg.fallback = fallback;
131
+ }
132
+ if (this.messageResolve) {
133
+ const resolve = this.messageResolve;
134
+ this.messageResolve = null;
135
+ resolve(standardMsg);
136
+ }
137
+ else {
138
+ this.messageBuffer.push(standardMsg);
139
+ }
140
+ }
141
+ retryDelay = 1000;
142
+ }
143
+ catch (err) {
144
+ if (ctrl.signal.aborted)
145
+ break;
146
+ log.error('poll error: %s', err);
147
+ if (err instanceof Error && err.message.includes('401')) {
148
+ log.error('auth failed (401), stopping');
149
+ void this.close();
150
+ break;
151
+ }
152
+ const delay = Math.min(retryDelay, MAX_RETRY_DELAY_MS);
153
+ retryDelay = Math.min(retryDelay * 2, MAX_RETRY_DELAY_MS);
154
+ await new Promise((r) => setTimeout(r, delay));
155
+ }
156
+ }
157
+ }
158
+ async send(chatId, content) {
159
+ if (!this.connected) {
160
+ throw XabotError.platform('WechatClient: not connected');
161
+ }
162
+ const contextToken = this.contextTokenStore.get(chatId) ?? '';
163
+ let effective;
164
+ if (content.type === 'text') {
165
+ effective = content;
166
+ }
167
+ else {
168
+ const src = content.source;
169
+ if (src.localUri) {
170
+ try {
171
+ const mediaType = content.type === 'audio' ? 'file' : content.type;
172
+ const result = await uploadMedia(this.baseUrl, this.token, this.xWechatUin, src.localUri, mediaType, chatId);
173
+ log.info('upload success: %s (chatId=%s)', content.type, chatId);
174
+ const body = fromMessageContentWithUpload(chatId, content, contextToken, result);
175
+ return this._sendBody(body);
176
+ }
177
+ catch (err) {
178
+ log.warn('upload failed, fallback to text: %s', err);
179
+ effective = { type: 'text', text: `[${content.type}]` };
180
+ }
181
+ }
182
+ else {
183
+ log.warn('send: %s has no localUri, sending placeholder', content.type);
184
+ effective = { type: 'text', text: `[${content.type} 无法发送]` };
185
+ }
186
+ }
187
+ const body = fromMessageContent(chatId, effective, contextToken);
188
+ return this._sendBody(body);
189
+ }
190
+ async _sendBody(body) {
191
+ const res = await this.post('/ilink/bot/sendmessage', body);
192
+ if (!res.ok) {
193
+ throw XabotError.platform(`WechatClient send failed: HTTP ${res.status}`);
194
+ }
195
+ const data = (await res.json());
196
+ if (data.ret !== undefined && data.ret !== 0) {
197
+ throw XabotError.platform(`WechatClient send failed: ret=${data.ret}, errcode=${data.errcode}`);
198
+ }
199
+ return messageId(data.msg?.client_id ?? String(Date.now()));
200
+ }
201
+ messages() {
202
+ const self = this;
203
+ return {
204
+ [Symbol.asyncIterator]() {
205
+ return {
206
+ async next() {
207
+ if (self.messageBuffer.length > 0) {
208
+ return { value: self.messageBuffer.shift(), done: false };
209
+ }
210
+ if (self.abortCtrl?.signal.aborted) {
211
+ return { value: undefined, done: true };
212
+ }
213
+ return new Promise((resolve) => {
214
+ self.messageResolve = (msg) => {
215
+ self.messageResolve = null;
216
+ if (self.abortCtrl?.signal.aborted) {
217
+ resolve({ value: undefined, done: true });
218
+ }
219
+ else {
220
+ resolve({ value: msg, done: false });
221
+ }
222
+ };
223
+ });
224
+ },
225
+ };
226
+ },
227
+ };
228
+ }
229
+ /** Replace token and reset poll state — used after token renewal. */
230
+ renewToken(newToken) {
231
+ this.token = newToken;
232
+ this.getUpdatesBuf = '';
233
+ this.connected = true;
234
+ if (!this.abortCtrl || this.abortCtrl.signal.aborted) {
235
+ this.abortCtrl = new AbortController();
236
+ void this.pollLoop();
237
+ }
238
+ }
239
+ streamCapability() {
240
+ return StreamCapability.NonStreaming;
241
+ }
242
+ async healthCheck() {
243
+ if (!this.connected || !this.token) {
244
+ throw XabotError.platform('WechatClient: not connected or no token');
245
+ }
246
+ }
247
+ // --------------------------------------------------------------------------
248
+ // Typing indicator
249
+ // --------------------------------------------------------------------------
250
+ async fetchTypingTicket(userId) {
251
+ const cached = this.typingTickets.get(userId);
252
+ if (cached && Date.now() < cached.expiresAt)
253
+ return cached.ticket;
254
+ const res = await this.post('/ilink/bot/getconfig', {
255
+ ilink_user_id: userId,
256
+ base_info: { channel_version: '2.0.0' },
257
+ });
258
+ if (!res.ok)
259
+ throw new Error(`getconfig failed: HTTP ${res.status}`);
260
+ const data = (await res.json());
261
+ if (!data.typing_ticket)
262
+ throw new Error('getconfig returned no typing_ticket');
263
+ this.typingTickets.set(userId, {
264
+ ticket: data.typing_ticket,
265
+ expiresAt: Date.now() + TYPING_TICKET_TTL_MS,
266
+ });
267
+ return data.typing_ticket;
268
+ }
269
+ async sendTypingStatus(userId, status) {
270
+ const ticket = await this.fetchTypingTicket(userId);
271
+ await this.post('/ilink/bot/sendtyping', {
272
+ ilink_user_id: userId,
273
+ typing_ticket: ticket,
274
+ status,
275
+ });
276
+ }
277
+ async setTypingIndicator(_chatId, senderId, _messageId) {
278
+ await this.sendTypingStatus(senderId, 1);
279
+ }
280
+ async refreshTypingIndicator(_chatId, senderId) {
281
+ await this.sendTypingStatus(senderId, 1);
282
+ }
283
+ async releaseTypingIndicator(_chatId, senderId, _messageId) {
284
+ await this.sendTypingStatus(senderId, 2);
285
+ }
286
+ async close() {
287
+ if (!this.abortCtrl)
288
+ return;
289
+ this.abortCtrl.abort();
290
+ this.connected = false;
291
+ if (this.messageResolve) {
292
+ this.messageResolve({});
293
+ this.messageResolve = null;
294
+ }
295
+ this.abortCtrl = null;
296
+ this.messageBuffer.length = 0;
297
+ this.contextTokenStore.clear();
298
+ this.typingTickets.clear();
299
+ }
300
+ }
301
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/platforms/wechat/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /** AES-128-ECB encrypt (Node.js auto-padding handles PKCS7). */
2
+ export declare function aesEcbEncrypt(data: Buffer, key: Buffer): Buffer;
3
+ /** AES-128-ECB decrypt (Node.js auto-padding handles PKCS7). */
4
+ export declare function aesEcbDecrypt(data: Buffer, key: Buffer): Buffer;
5
+ /** Generate a 16-byte random AES key. */
6
+ export declare function generateAesKey(): Buffer;
7
+ /** Image/video: base64(hex_string_of_16_bytes). */
8
+ export declare function encodeAesKeyForMedia(key: Buffer): string;
9
+ /** File: base64(raw_16_bytes). */
10
+ export declare function encodeAesKeyForFile(key: Buffer): string;
11
+ /**
12
+ * Parse an AES key from its base64-encoded form.
13
+ *
14
+ * The iLink protocol uses two conventions:
15
+ * - base64(raw 16 bytes) → decode directly
16
+ * - base64(hex string) → base64 decode then hex decode
17
+ *
18
+ * We auto-detect by decoded length: 16 bytes = raw key, 32 bytes = hex-encoded key.
19
+ */
20
+ export declare function parseAesKey(aesKeyBase64: string): Buffer;
21
+ /** Decrypt encrypted media buffer with the parsed AES key. */
22
+ export declare function decryptBuffer(encrypted: Buffer, aesKeyEncoded: string): Buffer;
23
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../../src/platforms/wechat/crypto.ts"],"names":[],"mappings":"AAEA,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,yCAAyC;AACzC,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,mDAAmD;AACnD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,kCAAkC;AAClC,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,8DAA8D;AAC9D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAG9E"}
@@ -0,0 +1,46 @@
1
+ import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';
2
+ /** AES-128-ECB encrypt (Node.js auto-padding handles PKCS7). */
3
+ export function aesEcbEncrypt(data, key) {
4
+ const cipher = createCipheriv('aes-128-ecb', key, null);
5
+ return Buffer.concat([cipher.update(data), cipher.final()]);
6
+ }
7
+ /** AES-128-ECB decrypt (Node.js auto-padding handles PKCS7). */
8
+ export function aesEcbDecrypt(data, key) {
9
+ const decipher = createDecipheriv('aes-128-ecb', key, null);
10
+ return Buffer.concat([decipher.update(data), decipher.final()]);
11
+ }
12
+ /** Generate a 16-byte random AES key. */
13
+ export function generateAesKey() {
14
+ return randomBytes(16);
15
+ }
16
+ /** Image/video: base64(hex_string_of_16_bytes). */
17
+ export function encodeAesKeyForMedia(key) {
18
+ return Buffer.from(key.toString('hex')).toString('base64');
19
+ }
20
+ /** File: base64(raw_16_bytes). */
21
+ export function encodeAesKeyForFile(key) {
22
+ return key.toString('base64');
23
+ }
24
+ /**
25
+ * Parse an AES key from its base64-encoded form.
26
+ *
27
+ * The iLink protocol uses two conventions:
28
+ * - base64(raw 16 bytes) → decode directly
29
+ * - base64(hex string) → base64 decode then hex decode
30
+ *
31
+ * We auto-detect by decoded length: 16 bytes = raw key, 32 bytes = hex-encoded key.
32
+ */
33
+ export function parseAesKey(aesKeyBase64) {
34
+ const decoded = Buffer.from(aesKeyBase64, 'base64');
35
+ if (decoded.length === 16)
36
+ return decoded;
37
+ if (decoded.length === 32)
38
+ return Buffer.from(decoded.toString('ascii'), 'hex');
39
+ throw new Error(`Invalid AES key: base64-decoded to ${decoded.length} bytes, expected 16 or 32`);
40
+ }
41
+ /** Decrypt encrypted media buffer with the parsed AES key. */
42
+ export function decryptBuffer(encrypted, aesKeyEncoded) {
43
+ const key = parseAesKey(aesKeyEncoded);
44
+ return aesEcbDecrypt(encrypted, key);
45
+ }
46
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../../src/platforms/wechat/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE5E,gEAAgE;AAChE,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,GAAW;IACrD,MAAM,MAAM,GAAG,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACxD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,GAAW;IACrD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,cAAc;IAC5B,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC7D,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,OAAO,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,YAAoB;IAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IACpD,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE;QAAE,OAAO,OAAO,CAAC;IAC1C,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;IAChF,MAAM,IAAI,KAAK,CAAC,sCAAsC,OAAO,CAAC,MAAM,2BAA2B,CAAC,CAAC;AACnG,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,aAAqB;IACpE,MAAM,GAAG,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IACvC,OAAO,aAAa,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,19 @@
1
+ export interface LoginResult {
2
+ token: string;
3
+ baseUrl: string;
4
+ }
5
+ export interface LoginOptions {
6
+ /** 输出 writer,默认 process.stderr.write */
7
+ writer?: (chunk: string) => void;
8
+ /** 打开 URL,默认调用系统浏览器 */
9
+ openUrl?: (url: string) => void;
10
+ }
11
+ /**
12
+ * 执行扫码登录。
13
+ * 1. 获取二维码
14
+ * 2. 自动打开浏览器
15
+ * 3. 轮询扫码状态
16
+ * 4. confirmed 后返回 { token, baseUrl }
17
+ */
18
+ export declare function login(options?: LoginOptions): Promise<LoginResult>;
19
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/platforms/wechat/login.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,wCAAwC;IACxC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,uBAAuB;IACvB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAgDD;;;;;;GAMG;AACH,wBAAsB,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAmCxE"}
@@ -0,0 +1,71 @@
1
+ import { spawn } from 'node:child_process';
2
+ import process from 'node:process';
3
+ const BASE_URL = 'https://ilinkai.weixin.qq.com';
4
+ const POLL_INTERVAL_MS = 2_000;
5
+ function defaultOpenUrl(url) {
6
+ if (process.platform === 'win32') {
7
+ // PowerShell 是 GUI subsystem 进程,不弹控制台窗口
8
+ // Start-Process 用 Shell API 打开默认浏览器
9
+ spawn('powershell', ['-Command', `Start-Process '${url}'`], { stdio: 'ignore' });
10
+ }
11
+ else if (process.platform === 'darwin') {
12
+ spawn('open', [url], { stdio: 'ignore' });
13
+ }
14
+ else {
15
+ spawn('xdg-open', [url], { stdio: 'ignore' });
16
+ }
17
+ }
18
+ async function getQRCode() {
19
+ const url = `${BASE_URL}/ilink/bot/get_bot_qrcode?bot_type=3`;
20
+ const res = await fetch(url);
21
+ if (!res.ok) {
22
+ throw new Error(`getQRCode failed: ${res.status} ${res.statusText}`);
23
+ }
24
+ return res.json();
25
+ }
26
+ async function pollQRCodeStatus(qrcode) {
27
+ const url = `${BASE_URL}/ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(qrcode)}`;
28
+ const res = await fetch(url);
29
+ if (!res.ok) {
30
+ throw new Error(`pollQRCodeStatus failed: ${res.status} ${res.statusText}`);
31
+ }
32
+ return res.json();
33
+ }
34
+ /**
35
+ * 执行扫码登录。
36
+ * 1. 获取二维码
37
+ * 2. 自动打开浏览器
38
+ * 3. 轮询扫码状态
39
+ * 4. confirmed 后返回 { token, baseUrl }
40
+ */
41
+ export async function login(options) {
42
+ const writer = options?.writer ?? ((chunk) => process.stderr.write(chunk));
43
+ const open = options?.openUrl ?? defaultOpenUrl;
44
+ const { qrcode, qrcode_img_content } = await getQRCode();
45
+ writer('请使用微信扫描二维码登录\n');
46
+ open(qrcode_img_content);
47
+ writer('等待扫码中...\n');
48
+ let scanned = false;
49
+ while (true) {
50
+ const status = await pollQRCodeStatus(qrcode);
51
+ if (status.status === 'confirmed') {
52
+ if (!status.bot_token) {
53
+ throw new Error('Login confirmed but no bot_token returned');
54
+ }
55
+ writer('登录成功!请在微信输入配对码完成配对\n');
56
+ return {
57
+ token: status.bot_token,
58
+ baseUrl: status.baseurl ?? BASE_URL,
59
+ };
60
+ }
61
+ if (status.status === 'expired') {
62
+ throw new Error('QR code expired, please try again');
63
+ }
64
+ if (status.status === 'scaned' && !scanned) {
65
+ scanned = true;
66
+ writer('已扫码,请在手机上确认...\n');
67
+ }
68
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
69
+ }
70
+ }
71
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/platforms/wechat/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import { type Message, type MessageContent } from '../../core/types.js';
2
+ import type { WechatUploadResult } from './upload.js';
3
+ export interface WeixinMessage {
4
+ from_user_id: string;
5
+ to_user_id: string;
6
+ message_type: number;
7
+ context_token: string;
8
+ item_list: WeixinMessageItem[];
9
+ message_id?: number;
10
+ msg_id?: string;
11
+ create_time_ms?: number;
12
+ }
13
+ export type WeixinMessageItem = {
14
+ type: 1;
15
+ text_item: {
16
+ text: string;
17
+ };
18
+ } | {
19
+ type: 2;
20
+ image_item: {
21
+ media: {
22
+ full_url: string;
23
+ aes_key?: string;
24
+ };
25
+ };
26
+ } | {
27
+ type: 3;
28
+ voice_item: {
29
+ media: {
30
+ full_url: string;
31
+ aes_key?: string;
32
+ };
33
+ };
34
+ } | {
35
+ type: 4;
36
+ file_item: {
37
+ file_name?: string;
38
+ media: {
39
+ full_url: string;
40
+ aes_key?: string;
41
+ };
42
+ };
43
+ } | {
44
+ type: 5;
45
+ video_item: {
46
+ media: {
47
+ full_url: string;
48
+ aes_key?: string;
49
+ };
50
+ };
51
+ } | {
52
+ type: number;
53
+ [key: string]: unknown;
54
+ };
55
+ export interface WeixinSendMessageBody {
56
+ from_user_id: string;
57
+ to_user_id: string;
58
+ client_id: string;
59
+ message_type: 2;
60
+ message_state: 2;
61
+ context_token: string;
62
+ item_list: WeixinOutgoingItem[];
63
+ }
64
+ export interface WeixinMediaPayload {
65
+ media: {
66
+ encrypt_query_param: string;
67
+ aes_key: string;
68
+ encrypt_type: number;
69
+ };
70
+ [key: string]: unknown;
71
+ }
72
+ export type WeixinOutgoingItem = {
73
+ type: 1;
74
+ text_item: {
75
+ text: string;
76
+ };
77
+ } | {
78
+ type: 2;
79
+ image_item: WeixinMediaPayload;
80
+ } | {
81
+ type: 4;
82
+ file_item: {
83
+ file_name: string;
84
+ } & WeixinMediaPayload;
85
+ } | {
86
+ type: 5;
87
+ video_item: WeixinMediaPayload;
88
+ };
89
+ export interface WeixinSendRequest {
90
+ msg: WeixinSendMessageBody;
91
+ base_info: {
92
+ channel_version: string;
93
+ };
94
+ }
95
+ export declare function fromMessageContent(toUserId: string, content: MessageContent, contextToken: string): WeixinSendRequest;
96
+ /** Build a WeChat send request with media upload result. */
97
+ export declare function fromMessageContentWithUpload(toUserId: string, content: MessageContent, contextToken: string, uploadResult: WechatUploadResult): WeixinSendRequest;
98
+ export declare function toStandardMessage(msg: WeixinMessage): Message;
99
+ export declare function processInboundMedia(item: WeixinMessageItem): Promise<MessageContent>;
100
+ export declare function extractContextToken(msg: WeixinMessage): string;
101
+ export declare function extractText(msg: WeixinMessage): string;
102
+ //# sourceMappingURL=message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../src/platforms/wechat/message.ts"],"names":[],"mappings":"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"}