@aster110/cc2wechat 1.0.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/dist/server.js ADDED
@@ -0,0 +1,412 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { ListToolsRequestSchema, CallToolRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { loginWithQRWeb } from './auth.js';
6
+ import { getActiveAccount, saveAccount, loadSyncBuf, saveSyncBuf } from './store.js';
7
+ import { getUpdates, sendMessage, sendTyping, getConfig, uploadAndSendMedia, } from './wechat-api.js';
8
+ import fs from 'node:fs';
9
+ import { MessageItemType } from './types.js';
10
+ // ---------------------------------------------------------------------------
11
+ // State
12
+ // ---------------------------------------------------------------------------
13
+ let pollingActive = false;
14
+ let pollingAbort = null;
15
+ /** Cache: userId -> typing_ticket */
16
+ const typingTicketCache = new Map();
17
+ // ---------------------------------------------------------------------------
18
+ // Message text extraction
19
+ // ---------------------------------------------------------------------------
20
+ function extractText(msg) {
21
+ const parts = [];
22
+ for (const item of msg.item_list ?? []) {
23
+ if (item.type === MessageItemType.TEXT && item.text_item?.text) {
24
+ parts.push(item.text_item.text);
25
+ }
26
+ else if (item.type === MessageItemType.IMAGE) {
27
+ parts.push('[Image]');
28
+ }
29
+ else if (item.type === MessageItemType.VOICE && item.voice_item?.text) {
30
+ parts.push(`[Voice] ${item.voice_item.text}`);
31
+ }
32
+ else if (item.type === MessageItemType.FILE && item.file_item?.file_name) {
33
+ parts.push(`[File: ${item.file_item.file_name}]`);
34
+ }
35
+ else if (item.type === MessageItemType.VIDEO) {
36
+ parts.push('[Video]');
37
+ }
38
+ }
39
+ return parts.join('\n') || '[Empty message]';
40
+ }
41
+ // ---------------------------------------------------------------------------
42
+ // Text chunking for WeChat 4000-char limit
43
+ // ---------------------------------------------------------------------------
44
+ const MAX_CHUNK_LENGTH = 3900;
45
+ function chunkText(text) {
46
+ if (text.length <= MAX_CHUNK_LENGTH)
47
+ return [text];
48
+ const chunks = [];
49
+ let remaining = text;
50
+ while (remaining.length > 0) {
51
+ if (remaining.length <= MAX_CHUNK_LENGTH) {
52
+ chunks.push(remaining);
53
+ break;
54
+ }
55
+ // Try to break at newline
56
+ let breakAt = remaining.lastIndexOf('\n', MAX_CHUNK_LENGTH);
57
+ if (breakAt < MAX_CHUNK_LENGTH * 0.5) {
58
+ // No good newline break, try space
59
+ breakAt = remaining.lastIndexOf(' ', MAX_CHUNK_LENGTH);
60
+ }
61
+ if (breakAt < MAX_CHUNK_LENGTH * 0.3) {
62
+ breakAt = MAX_CHUNK_LENGTH;
63
+ }
64
+ chunks.push(remaining.slice(0, breakAt));
65
+ remaining = remaining.slice(breakAt).trimStart();
66
+ }
67
+ return chunks;
68
+ }
69
+ // ---------------------------------------------------------------------------
70
+ // Strip markdown for WeChat plain text
71
+ // ---------------------------------------------------------------------------
72
+ function stripMarkdown(text) {
73
+ let result = text;
74
+ // Code blocks: strip fences, keep content
75
+ result = result.replace(/```[^\n]*\n?([\s\S]*?)```/g, (_, code) => code.trim());
76
+ // Images: remove
77
+ result = result.replace(/!\[[^\]]*\]\([^)]*\)/g, '');
78
+ // Links: keep display text
79
+ result = result.replace(/\[([^\]]+)\]\([^)]*\)/g, '$1');
80
+ // Bold/italic
81
+ result = result.replace(/\*\*(.+?)\*\*/g, '$1');
82
+ result = result.replace(/\*(.+?)\*/g, '$1');
83
+ result = result.replace(/__(.+?)__/g, '$1');
84
+ result = result.replace(/_(.+?)_/g, '$1');
85
+ // Headings
86
+ result = result.replace(/^#{1,6}\s+/gm, '');
87
+ // Horizontal rules
88
+ result = result.replace(/^[-*_]{3,}$/gm, '');
89
+ // Blockquotes
90
+ result = result.replace(/^>\s?/gm, '');
91
+ return result.trim();
92
+ }
93
+ // ---------------------------------------------------------------------------
94
+ // MCP Server
95
+ // ---------------------------------------------------------------------------
96
+ const server = new Server({ name: 'wechat-channel', version: '1.0.0' }, {
97
+ capabilities: {
98
+ experimental: { 'claude/channel': {} },
99
+ tools: {},
100
+ },
101
+ });
102
+ // -- Tools --
103
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
104
+ tools: [
105
+ {
106
+ name: 'reply',
107
+ description: 'Reply to a WeChat message. Supports text and image/file. Set media to a local file path to send an image or file.',
108
+ inputSchema: {
109
+ type: 'object',
110
+ properties: {
111
+ user_id: {
112
+ type: 'string',
113
+ description: 'The WeChat user ID to reply to (from_user_id from the incoming message)',
114
+ },
115
+ context_token: {
116
+ type: 'string',
117
+ description: 'The context_token from the incoming message (required for reply association)',
118
+ },
119
+ content: {
120
+ type: 'string',
121
+ description: 'Text content',
122
+ },
123
+ media: {
124
+ type: 'string',
125
+ description: 'Optional: absolute path to a local file (image/video/file) to send',
126
+ },
127
+ },
128
+ required: ['user_id', 'context_token', 'content'],
129
+ },
130
+ },
131
+ {
132
+ name: 'login',
133
+ description: 'Login to WeChat by scanning a QR code. Run this first if not already logged in.',
134
+ inputSchema: {
135
+ type: 'object',
136
+ properties: {},
137
+ },
138
+ },
139
+ ],
140
+ }));
141
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
142
+ const { name, arguments: args } = request.params;
143
+ if (name === 'login') {
144
+ try {
145
+ const result = await loginWithQRWeb();
146
+ saveAccount({
147
+ accountId: result.accountId,
148
+ token: result.token,
149
+ baseUrl: result.baseUrl,
150
+ savedAt: new Date().toISOString(),
151
+ });
152
+ // Start polling after login
153
+ startPolling();
154
+ return {
155
+ content: [
156
+ {
157
+ type: 'text',
158
+ text: `WeChat login successful! Account: ${result.accountId}. Polling started.`,
159
+ },
160
+ ],
161
+ };
162
+ }
163
+ catch (err) {
164
+ return {
165
+ content: [
166
+ { type: 'text', text: `Login failed: ${String(err)}` },
167
+ ],
168
+ isError: true,
169
+ };
170
+ }
171
+ }
172
+ if (name === 'reply') {
173
+ const userId = args.user_id;
174
+ const contextToken = args.context_token;
175
+ const content = args.content;
176
+ const media = args.media;
177
+ if (!userId || !contextToken || !content) {
178
+ return {
179
+ content: [
180
+ { type: 'text', text: 'Missing required fields: user_id, context_token, content' },
181
+ ],
182
+ isError: true,
183
+ };
184
+ }
185
+ // Validate media path if provided
186
+ if (media && !fs.existsSync(media)) {
187
+ return {
188
+ content: [
189
+ { type: 'text', text: `Media file not found: ${media}` },
190
+ ],
191
+ isError: true,
192
+ };
193
+ }
194
+ const account = getActiveAccount();
195
+ if (!account) {
196
+ return {
197
+ content: [
198
+ { type: 'text', text: 'Not logged in. Use the login tool first.' },
199
+ ],
200
+ isError: true,
201
+ };
202
+ }
203
+ try {
204
+ // Send typing indicator
205
+ const ticket = typingTicketCache.get(userId);
206
+ if (ticket) {
207
+ await sendTyping(account.token, userId, ticket, 1, account.baseUrl).catch(() => { });
208
+ }
209
+ // Strip markdown and chunk
210
+ const plainText = stripMarkdown(content);
211
+ const chunks = chunkText(plainText);
212
+ for (const chunk of chunks) {
213
+ await sendMessage(account.token, userId, chunk, contextToken, account.baseUrl);
214
+ }
215
+ // Send media if provided
216
+ let mediaSent = false;
217
+ if (media) {
218
+ await uploadAndSendMedia({
219
+ token: account.token,
220
+ toUser: userId,
221
+ contextToken,
222
+ filePath: media,
223
+ baseUrl: account.baseUrl,
224
+ });
225
+ mediaSent = true;
226
+ }
227
+ // Cancel typing
228
+ if (ticket) {
229
+ await sendTyping(account.token, userId, ticket, 2, account.baseUrl).catch(() => { });
230
+ }
231
+ const parts = [`Reply sent to ${userId} (${chunks.length} chunk${chunks.length > 1 ? 's' : ''})`];
232
+ if (mediaSent)
233
+ parts.push(`Media sent: ${media}`);
234
+ return {
235
+ content: [
236
+ {
237
+ type: 'text',
238
+ text: parts.join('. '),
239
+ },
240
+ ],
241
+ };
242
+ }
243
+ catch (err) {
244
+ return {
245
+ content: [
246
+ { type: 'text', text: `Failed to send reply: ${String(err)}` },
247
+ ],
248
+ isError: true,
249
+ };
250
+ }
251
+ }
252
+ return {
253
+ content: [{ type: 'text', text: `Unknown tool: ${name}` }],
254
+ isError: true,
255
+ };
256
+ });
257
+ // ---------------------------------------------------------------------------
258
+ // Long-polling loop
259
+ // ---------------------------------------------------------------------------
260
+ const SESSION_EXPIRED_ERRCODE = -14;
261
+ const MAX_CONSECUTIVE_FAILURES = 3;
262
+ const BACKOFF_DELAY_MS = 30_000;
263
+ const RETRY_DELAY_MS = 2_000;
264
+ const SESSION_PAUSE_MS = 5 * 60_000;
265
+ function sleep(ms, signal) {
266
+ return new Promise((resolve, reject) => {
267
+ const t = setTimeout(resolve, ms);
268
+ signal?.addEventListener('abort', () => {
269
+ clearTimeout(t);
270
+ reject(new Error('aborted'));
271
+ }, { once: true });
272
+ });
273
+ }
274
+ async function pollLoop(account) {
275
+ let buf = loadSyncBuf(account.accountId);
276
+ let consecutiveFailures = 0;
277
+ let nextTimeoutMs = 35_000;
278
+ process.stderr.write(`[wechat-channel] Polling started for account ${account.accountId}\n`);
279
+ while (pollingActive && !pollingAbort?.signal.aborted) {
280
+ try {
281
+ const resp = await getUpdates(account.token, buf, account.baseUrl, nextTimeoutMs);
282
+ // Update timeout if server suggests one
283
+ if (resp.longpolling_timeout_ms != null && resp.longpolling_timeout_ms > 0) {
284
+ nextTimeoutMs = resp.longpolling_timeout_ms;
285
+ }
286
+ // Check for API errors
287
+ const isApiError = (resp.ret !== undefined && resp.ret !== 0) ||
288
+ (resp.errcode !== undefined && resp.errcode !== 0);
289
+ if (isApiError) {
290
+ const isSessionExpired = resp.errcode === SESSION_EXPIRED_ERRCODE || resp.ret === SESSION_EXPIRED_ERRCODE;
291
+ if (isSessionExpired) {
292
+ process.stderr.write(`[wechat-channel] Session expired (errcode ${SESSION_EXPIRED_ERRCODE}), pausing ${Math.ceil(SESSION_PAUSE_MS / 60_000)} min\n`);
293
+ consecutiveFailures = 0;
294
+ await sleep(SESSION_PAUSE_MS, pollingAbort?.signal);
295
+ continue;
296
+ }
297
+ consecutiveFailures++;
298
+ process.stderr.write(`[wechat-channel] getUpdates error: ret=${resp.ret} errcode=${resp.errcode} errmsg=${resp.errmsg ?? ''} (${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES})\n`);
299
+ if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
300
+ consecutiveFailures = 0;
301
+ await sleep(BACKOFF_DELAY_MS, pollingAbort?.signal);
302
+ }
303
+ else {
304
+ await sleep(RETRY_DELAY_MS, pollingAbort?.signal);
305
+ }
306
+ continue;
307
+ }
308
+ consecutiveFailures = 0;
309
+ // Save sync buf
310
+ if (resp.get_updates_buf != null && resp.get_updates_buf !== '') {
311
+ saveSyncBuf(account.accountId, resp.get_updates_buf);
312
+ buf = resp.get_updates_buf;
313
+ }
314
+ // Process messages
315
+ const msgs = resp.msgs ?? [];
316
+ for (const msg of msgs) {
317
+ // Only process user messages (message_type === 1)
318
+ if (msg.message_type !== 1)
319
+ continue;
320
+ const text = extractText(msg);
321
+ const fromUser = msg.from_user_id ?? 'unknown';
322
+ const contextToken = msg.context_token ?? '';
323
+ process.stderr.write(`[wechat-channel] Message from ${fromUser}: ${text.slice(0, 100)}\n`);
324
+ // Cache typing ticket for this user
325
+ try {
326
+ const cfg = await getConfig(account.token, fromUser, contextToken, account.baseUrl);
327
+ if (cfg.typing_ticket) {
328
+ typingTicketCache.set(fromUser, cfg.typing_ticket);
329
+ }
330
+ }
331
+ catch {
332
+ // non-critical
333
+ }
334
+ // Send typing indicator
335
+ const ticket = typingTicketCache.get(fromUser);
336
+ if (ticket) {
337
+ await sendTyping(account.token, fromUser, ticket, 1, account.baseUrl).catch(() => { });
338
+ }
339
+ // Push to Claude Code via channel notification
340
+ server.notification({
341
+ method: 'notifications/claude/channel',
342
+ params: {
343
+ content: `${text}\n\n[System: Reply via the "reply" tool. user_id and context_token are in the message metadata above.]`,
344
+ meta: {
345
+ source: 'wechat',
346
+ sender: fromUser,
347
+ user_id: fromUser,
348
+ context_token: contextToken,
349
+ message_id: String(msg.message_id ?? ''),
350
+ session_id: msg.session_id ?? '',
351
+ },
352
+ },
353
+ });
354
+ }
355
+ }
356
+ catch (err) {
357
+ if (pollingAbort?.signal.aborted)
358
+ return;
359
+ consecutiveFailures++;
360
+ process.stderr.write(`[wechat-channel] Poll error (${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES}): ${String(err)}\n`);
361
+ if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
362
+ consecutiveFailures = 0;
363
+ await sleep(BACKOFF_DELAY_MS, pollingAbort?.signal);
364
+ }
365
+ else {
366
+ await sleep(RETRY_DELAY_MS, pollingAbort?.signal);
367
+ }
368
+ }
369
+ }
370
+ }
371
+ function startPolling() {
372
+ const account = getActiveAccount();
373
+ if (!account) {
374
+ process.stderr.write('[wechat-channel] No account found, skipping polling\n');
375
+ return;
376
+ }
377
+ if (pollingActive) {
378
+ process.stderr.write('[wechat-channel] Polling already active\n');
379
+ return;
380
+ }
381
+ pollingActive = true;
382
+ pollingAbort = new AbortController();
383
+ // Run poll loop in background (don't await)
384
+ pollLoop(account).catch((err) => {
385
+ if (!pollingAbort?.signal.aborted) {
386
+ process.stderr.write(`[wechat-channel] Poll loop crashed: ${String(err)}\n`);
387
+ }
388
+ pollingActive = false;
389
+ });
390
+ }
391
+ // ---------------------------------------------------------------------------
392
+ // Main
393
+ // ---------------------------------------------------------------------------
394
+ async function main() {
395
+ const transport = new StdioServerTransport();
396
+ await server.connect(transport);
397
+ process.stderr.write('[wechat-channel] MCP server started\n');
398
+ // Auto-start polling if we have saved credentials
399
+ const account = getActiveAccount();
400
+ if (account) {
401
+ process.stderr.write(`[wechat-channel] Found saved account: ${account.accountId}\n`);
402
+ startPolling();
403
+ }
404
+ else {
405
+ process.stderr.write('[wechat-channel] No saved account. Use the login tool to connect.\n');
406
+ }
407
+ }
408
+ main().catch((err) => {
409
+ process.stderr.write(`[wechat-channel] Fatal: ${String(err)}\n`);
410
+ process.exit(1);
411
+ });
412
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface AccountData {
2
+ accountId: string;
3
+ token: string;
4
+ baseUrl?: string;
5
+ savedAt: string;
6
+ }
7
+ export declare function loadAccounts(): AccountData[];
8
+ export declare function saveAccount(account: AccountData): void;
9
+ export declare function getActiveAccount(): AccountData | null;
10
+ export declare function removeAccount(accountId: string): void;
11
+ export declare function loadSyncBuf(accountId: string): string;
12
+ export declare function saveSyncBuf(accountId: string, buf: string): void;
package/dist/store.js ADDED
@@ -0,0 +1,61 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ const CHANNEL_DIR = path.join(os.homedir(), '.claude', 'channels', 'wechat-channel');
5
+ function ensureDir(dir) {
6
+ fs.mkdirSync(dir, { recursive: true });
7
+ }
8
+ function accountsFilePath() {
9
+ return path.join(CHANNEL_DIR, 'accounts.json');
10
+ }
11
+ export function loadAccounts() {
12
+ try {
13
+ const raw = fs.readFileSync(accountsFilePath(), 'utf-8');
14
+ const parsed = JSON.parse(raw);
15
+ return Array.isArray(parsed) ? parsed : [];
16
+ }
17
+ catch {
18
+ return [];
19
+ }
20
+ }
21
+ export function saveAccount(account) {
22
+ ensureDir(CHANNEL_DIR);
23
+ const accounts = loadAccounts().filter((a) => a.accountId !== account.accountId);
24
+ accounts.push(account);
25
+ const filePath = accountsFilePath();
26
+ fs.writeFileSync(filePath, JSON.stringify(accounts, null, 2), 'utf-8');
27
+ try {
28
+ fs.chmodSync(filePath, 0o600);
29
+ }
30
+ catch {
31
+ // best-effort
32
+ }
33
+ }
34
+ export function getActiveAccount() {
35
+ const accounts = loadAccounts();
36
+ return accounts.length > 0 ? accounts[accounts.length - 1] : null;
37
+ }
38
+ export function removeAccount(accountId) {
39
+ const accounts = loadAccounts().filter((a) => a.accountId !== accountId);
40
+ ensureDir(CHANNEL_DIR);
41
+ fs.writeFileSync(accountsFilePath(), JSON.stringify(accounts, null, 2), 'utf-8');
42
+ }
43
+ // ---------------------------------------------------------------------------
44
+ // Sync buf (long-poll cursor)
45
+ // ---------------------------------------------------------------------------
46
+ function syncBufFilePath(accountId) {
47
+ return path.join(CHANNEL_DIR, `sync-buf-${accountId}.txt`);
48
+ }
49
+ export function loadSyncBuf(accountId) {
50
+ try {
51
+ return fs.readFileSync(syncBufFilePath(accountId), 'utf-8');
52
+ }
53
+ catch {
54
+ return '';
55
+ }
56
+ }
57
+ export function saveSyncBuf(accountId, buf) {
58
+ ensureDir(CHANNEL_DIR);
59
+ fs.writeFileSync(syncBufFilePath(accountId), buf, 'utf-8');
60
+ }
61
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ /** Common request metadata attached to every CGI request. */
2
+ export interface BaseInfo {
3
+ channel_version?: string;
4
+ }
5
+ export declare const MessageType: {
6
+ readonly NONE: 0;
7
+ readonly USER: 1;
8
+ readonly BOT: 2;
9
+ };
10
+ export declare const MessageItemType: {
11
+ readonly NONE: 0;
12
+ readonly TEXT: 1;
13
+ readonly IMAGE: 2;
14
+ readonly VOICE: 3;
15
+ readonly FILE: 4;
16
+ readonly VIDEO: 5;
17
+ };
18
+ export declare const MessageState: {
19
+ readonly NEW: 0;
20
+ readonly GENERATING: 1;
21
+ readonly FINISH: 2;
22
+ };
23
+ export declare const TypingStatus: {
24
+ readonly TYPING: 1;
25
+ readonly CANCEL: 2;
26
+ };
27
+ export interface TextItem {
28
+ text?: string;
29
+ }
30
+ export interface CDNMedia {
31
+ encrypt_query_param?: string;
32
+ aes_key?: string;
33
+ encrypt_type?: number;
34
+ }
35
+ export interface ImageItem {
36
+ media?: CDNMedia;
37
+ thumb_media?: CDNMedia;
38
+ aeskey?: string;
39
+ url?: string;
40
+ mid_size?: number;
41
+ thumb_size?: number;
42
+ thumb_height?: number;
43
+ thumb_width?: number;
44
+ hd_size?: number;
45
+ }
46
+ export interface VoiceItem {
47
+ media?: CDNMedia;
48
+ encode_type?: number;
49
+ bits_per_sample?: number;
50
+ sample_rate?: number;
51
+ playtime?: number;
52
+ text?: string;
53
+ }
54
+ export interface FileItem {
55
+ media?: CDNMedia;
56
+ file_name?: string;
57
+ md5?: string;
58
+ len?: string;
59
+ }
60
+ export interface VideoItem {
61
+ media?: CDNMedia;
62
+ video_size?: number;
63
+ play_length?: number;
64
+ video_md5?: string;
65
+ thumb_media?: CDNMedia;
66
+ thumb_size?: number;
67
+ thumb_height?: number;
68
+ thumb_width?: number;
69
+ }
70
+ export interface RefMessage {
71
+ message_item?: MessageItem;
72
+ title?: string;
73
+ }
74
+ export interface MessageItem {
75
+ type?: number;
76
+ create_time_ms?: number;
77
+ update_time_ms?: number;
78
+ is_completed?: boolean;
79
+ msg_id?: string;
80
+ ref_msg?: RefMessage;
81
+ text_item?: TextItem;
82
+ image_item?: ImageItem;
83
+ voice_item?: VoiceItem;
84
+ file_item?: FileItem;
85
+ video_item?: VideoItem;
86
+ }
87
+ export interface WeixinMessage {
88
+ seq?: number;
89
+ message_id?: number;
90
+ from_user_id?: string;
91
+ to_user_id?: string;
92
+ client_id?: string;
93
+ create_time_ms?: number;
94
+ update_time_ms?: number;
95
+ delete_time_ms?: number;
96
+ session_id?: string;
97
+ group_id?: string;
98
+ message_type?: number;
99
+ message_state?: number;
100
+ item_list?: MessageItem[];
101
+ context_token?: string;
102
+ }
103
+ export interface GetUpdatesReq {
104
+ get_updates_buf?: string;
105
+ }
106
+ export interface GetUpdatesResp {
107
+ ret?: number;
108
+ errcode?: number;
109
+ errmsg?: string;
110
+ msgs?: WeixinMessage[];
111
+ get_updates_buf?: string;
112
+ longpolling_timeout_ms?: number;
113
+ }
114
+ export interface SendMessageReq {
115
+ msg?: WeixinMessage;
116
+ }
117
+ export interface SendTypingReq {
118
+ ilink_user_id?: string;
119
+ typing_ticket?: string;
120
+ status?: number;
121
+ }
122
+ export interface GetConfigResp {
123
+ ret?: number;
124
+ errmsg?: string;
125
+ typing_ticket?: string;
126
+ }
package/dist/types.js ADDED
@@ -0,0 +1,23 @@
1
+ export const MessageType = {
2
+ NONE: 0,
3
+ USER: 1,
4
+ BOT: 2,
5
+ };
6
+ export const MessageItemType = {
7
+ NONE: 0,
8
+ TEXT: 1,
9
+ IMAGE: 2,
10
+ VOICE: 3,
11
+ FILE: 4,
12
+ VIDEO: 5,
13
+ };
14
+ export const MessageState = {
15
+ NEW: 0,
16
+ GENERATING: 1,
17
+ FINISH: 2,
18
+ };
19
+ export const TypingStatus = {
20
+ TYPING: 1,
21
+ CANCEL: 2,
22
+ };
23
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,GAAG,EAAE,CAAC;CACE,CAAC;AAEX,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACA,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,GAAG,EAAE,CAAC;IACN,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,CAAC;CACD,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;CACD,CAAC"}