mozi-bot 1.1.2 → 1.2.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.
Files changed (47) hide show
  1. package/README.md +251 -31
  2. package/dist/channels/index.d.ts +4 -0
  3. package/dist/channels/index.d.ts.map +1 -1
  4. package/dist/channels/index.js +4 -0
  5. package/dist/channels/index.js.map +1 -1
  6. package/dist/channels/qq/api.d.ts +37 -0
  7. package/dist/channels/qq/api.d.ts.map +1 -0
  8. package/dist/channels/qq/api.js +145 -0
  9. package/dist/channels/qq/api.js.map +1 -0
  10. package/dist/channels/qq/index.d.ts +36 -0
  11. package/dist/channels/qq/index.d.ts.map +1 -0
  12. package/dist/channels/qq/index.js +145 -0
  13. package/dist/channels/qq/index.js.map +1 -0
  14. package/dist/channels/qq/websocket.d.ts +67 -0
  15. package/dist/channels/qq/websocket.d.ts.map +1 -0
  16. package/dist/channels/qq/websocket.js +372 -0
  17. package/dist/channels/qq/websocket.js.map +1 -0
  18. package/dist/channels/wecom/api.d.ts +30 -0
  19. package/dist/channels/wecom/api.d.ts.map +1 -0
  20. package/dist/channels/wecom/api.js +98 -0
  21. package/dist/channels/wecom/api.js.map +1 -0
  22. package/dist/channels/wecom/crypto.d.ts +25 -0
  23. package/dist/channels/wecom/crypto.d.ts.map +1 -0
  24. package/dist/channels/wecom/crypto.js +74 -0
  25. package/dist/channels/wecom/crypto.js.map +1 -0
  26. package/dist/channels/wecom/events.d.ts +34 -0
  27. package/dist/channels/wecom/events.d.ts.map +1 -0
  28. package/dist/channels/wecom/events.js +127 -0
  29. package/dist/channels/wecom/events.js.map +1 -0
  30. package/dist/channels/wecom/index.d.ts +39 -0
  31. package/dist/channels/wecom/index.d.ts.map +1 -0
  32. package/dist/channels/wecom/index.js +184 -0
  33. package/dist/channels/wecom/index.js.map +1 -0
  34. package/dist/cli/index.js +21 -6
  35. package/dist/cli/index.js.map +1 -1
  36. package/dist/config/index.d.ts +94 -0
  37. package/dist/config/index.d.ts.map +1 -1
  38. package/dist/config/index.js +49 -2
  39. package/dist/config/index.js.map +1 -1
  40. package/dist/gateway/server.d.ts +2 -0
  41. package/dist/gateway/server.d.ts.map +1 -1
  42. package/dist/gateway/server.js +47 -0
  43. package/dist/gateway/server.js.map +1 -1
  44. package/dist/types/index.d.ts +20 -1
  45. package/dist/types/index.d.ts.map +1 -1
  46. package/dist/types/index.js.map +1 -1
  47. package/package.json +4 -2
@@ -0,0 +1,145 @@
1
+ /**
2
+ * QQ 通道适配器
3
+ *
4
+ * 使用 WebSocket 长连接模式,无需公网部署
5
+ */
6
+ import { BaseChannelAdapter } from "../common/base.js";
7
+ import { QQApiClient } from "./api.js";
8
+ import { QQWebSocketClient } from "./websocket.js";
9
+ import { getChildLogger } from "../../utils/logger.js";
10
+ /** QQ 通道元数据 */
11
+ const QQ_META = {
12
+ id: "qq",
13
+ name: "QQ",
14
+ description: "QQ 机器人 (官方 API)",
15
+ capabilities: {
16
+ chatTypes: ["direct", "group"],
17
+ supportsMedia: true,
18
+ supportsReply: true,
19
+ supportsMention: true,
20
+ supportsReaction: false,
21
+ supportsThread: false,
22
+ supportsEdit: false,
23
+ maxMessageLength: 4096,
24
+ },
25
+ };
26
+ export class QQChannel extends BaseChannelAdapter {
27
+ id = "qq";
28
+ meta = QQ_META;
29
+ config;
30
+ apiClient;
31
+ wsClient = null;
32
+ initialized = false;
33
+ constructor(config) {
34
+ super();
35
+ this.config = config;
36
+ this.apiClient = new QQApiClient(config);
37
+ this.logger = getChildLogger("qq");
38
+ }
39
+ /** 初始化通道 */
40
+ async initialize() {
41
+ if (this.initialized)
42
+ return;
43
+ this.logger.info("Initializing QQ channel");
44
+ // 验证配置
45
+ if (!this.config.appId || !this.config.clientSecret) {
46
+ throw new Error("QQ appId and clientSecret are required");
47
+ }
48
+ // 测试获取 token
49
+ try {
50
+ await this.apiClient.getAccessToken();
51
+ this.logger.info("Successfully authenticated with QQ");
52
+ }
53
+ catch (error) {
54
+ this.logger.error({ error }, "Failed to authenticate with QQ");
55
+ throw error;
56
+ }
57
+ // 启动 WebSocket 连接
58
+ await this.startWebSocket();
59
+ this.initialized = true;
60
+ }
61
+ /** 启动 WebSocket 连接 */
62
+ async startWebSocket() {
63
+ this.logger.info("Starting QQ WebSocket client");
64
+ this.wsClient = new QQWebSocketClient(this.config);
65
+ // 设置事件处理器
66
+ this.wsClient.setEventHandler(async (context) => {
67
+ await this.handleInboundMessage(context);
68
+ });
69
+ // 启动连接
70
+ await this.wsClient.start();
71
+ }
72
+ /** 关闭通道 */
73
+ async shutdown() {
74
+ this.logger.info("Shutting down QQ channel");
75
+ if (this.wsClient) {
76
+ await this.wsClient.stop();
77
+ this.wsClient = null;
78
+ }
79
+ this.initialized = false;
80
+ }
81
+ /** 发送消息 */
82
+ async sendMessage(message) {
83
+ try {
84
+ const { chatId, content, replyToId } = message;
85
+ // 根据 chatId 前缀判断消息类型
86
+ if (chatId.startsWith("group:")) {
87
+ // QQ 群消息
88
+ const groupOpenId = chatId.replace("group:", "");
89
+ await this.apiClient.sendGroupMessage(groupOpenId, content, replyToId);
90
+ }
91
+ else if (chatId.startsWith("c2c:")) {
92
+ // QQ 私聊消息
93
+ const openId = chatId.replace("c2c:", "");
94
+ await this.apiClient.sendDirectMessage(openId, content, replyToId);
95
+ }
96
+ else if (chatId.startsWith("dms:")) {
97
+ // 频道私信
98
+ const guildId = chatId.replace("dms:", "");
99
+ await this.apiClient.sendDMMessage(guildId, content, replyToId);
100
+ }
101
+ else {
102
+ // 默认作为频道消息处理
103
+ await this.apiClient.sendChannelMessage(chatId, content, replyToId);
104
+ }
105
+ return { success: true };
106
+ }
107
+ catch (error) {
108
+ const errorMessage = error instanceof Error ? error.message : String(error);
109
+ this.logger.error({ error, message }, "Failed to send message");
110
+ return { success: false, error: errorMessage };
111
+ }
112
+ }
113
+ /** 发送文本消息 */
114
+ async sendText(chatId, text, replyToId) {
115
+ return this.sendMessage({ chatId, content: text, replyToId });
116
+ }
117
+ /** 检查通道状态 */
118
+ async isHealthy() {
119
+ try {
120
+ // 检查 API 认证
121
+ await this.apiClient.getAccessToken();
122
+ // 检查 WebSocket 连接状态
123
+ if (this.wsClient) {
124
+ return this.wsClient.checkConnected();
125
+ }
126
+ return true;
127
+ }
128
+ catch {
129
+ return false;
130
+ }
131
+ }
132
+ /** 获取 API 客户端 */
133
+ getApiClient() {
134
+ return this.apiClient;
135
+ }
136
+ /** 检查是否使用长连接 */
137
+ isUsingWebSocket() {
138
+ return this.wsClient !== null;
139
+ }
140
+ }
141
+ /** 创建 QQ 通道 */
142
+ export function createQQChannel(config) {
143
+ return new QQChannel(config);
144
+ }
145
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/channels/qq/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * QQ 机器人 WebSocket 客户端
3
+ * 实现与 QQ 机器人网关的长连接
4
+ */
5
+ import type { QQConfig, InboundMessageContext } from "../../types/index.js";
6
+ /** 事件处理器类型 */
7
+ type EventHandler = (context: InboundMessageContext) => Promise<void>;
8
+ export declare class QQWebSocketClient {
9
+ private config;
10
+ private apiClient;
11
+ private ws;
12
+ private sessionId;
13
+ private sequence;
14
+ private heartbeatInterval;
15
+ private heartbeatTimer;
16
+ private reconnectAttempts;
17
+ private maxReconnectAttempts;
18
+ private eventHandler;
19
+ private isConnected;
20
+ constructor(config: QQConfig);
21
+ /** 设置事件处理器 */
22
+ setEventHandler(handler: EventHandler): void;
23
+ /** 启动连接 */
24
+ start(): Promise<void>;
25
+ /** 连接到网关 */
26
+ private connect;
27
+ /** 处理 WebSocket 消息 */
28
+ private handlePayload;
29
+ /** 处理 Hello 消息 */
30
+ private handleHello;
31
+ /** 发送鉴权请求 */
32
+ private identify;
33
+ /** 恢复连接 */
34
+ private resume;
35
+ /** 获取订阅的事件 intents */
36
+ private getIntents;
37
+ /** 处理事件分发 */
38
+ private handleDispatch;
39
+ /** 处理频道消息 */
40
+ private handleChannelMessage;
41
+ /** 处理频道私信 */
42
+ private handleDirectMessage;
43
+ /** 处理 QQ 群消息 */
44
+ private handleGroupMessage;
45
+ /** 处理 QQ 私聊消息 */
46
+ private handleC2CMessage;
47
+ /** 清理消息内容 (去除 @ 标记等) */
48
+ private cleanContent;
49
+ /** 开始心跳 */
50
+ private startHeartbeat;
51
+ /** 停止心跳 */
52
+ private stopHeartbeat;
53
+ /** 发送心跳 */
54
+ private sendHeartbeat;
55
+ /** 发送消息 */
56
+ private send;
57
+ /** 处理断开连接 */
58
+ private handleDisconnect;
59
+ /** 重新连接 */
60
+ private reconnect;
61
+ /** 停止连接 */
62
+ stop(): Promise<void>;
63
+ /** 检查是否已连接 */
64
+ checkConnected(): boolean;
65
+ }
66
+ export {};
67
+ //# sourceMappingURL=websocket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../../src/channels/qq/websocket.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAgE5E,cAAc;AACd,KAAK,YAAY,GAAG,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEtE,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,oBAAoB,CAAM;IAClC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,WAAW,CAAS;gBAEhB,MAAM,EAAE,QAAQ;IAK5B,cAAc;IACd,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAI5C,WAAW;IACL,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B,YAAY;YACE,OAAO;IA2CrB,sBAAsB;YACR,aAAa;IAgC3B,kBAAkB;YACJ,WAAW;IAezB,aAAa;YACC,QAAQ;IAsBtB,WAAW;YACG,MAAM;IAgBpB,sBAAsB;IACtB,OAAO,CAAC,UAAU;IAelB,aAAa;YACC,cAAc;IA4C5B,aAAa;YACC,oBAAoB;IAqBlC,aAAa;YACC,mBAAmB;IAkBjC,gBAAgB;YACF,kBAAkB;IAkBhC,iBAAiB;YACH,gBAAgB;IAkB9B,wBAAwB;IACxB,OAAO,CAAC,YAAY;IAKpB,WAAW;IACX,OAAO,CAAC,cAAc;IAQtB,WAAW;IACX,OAAO,CAAC,aAAa;IAOrB,WAAW;IACX,OAAO,CAAC,aAAa;IAUrB,WAAW;IACX,OAAO,CAAC,IAAI;IAMZ,aAAa;YACC,gBAAgB;IAe9B,WAAW;YACG,SAAS;IAcvB,WAAW;IACL,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,cAAc;IACd,cAAc,IAAI,OAAO;CAG1B"}
@@ -0,0 +1,372 @@
1
+ /**
2
+ * QQ 机器人 WebSocket 客户端
3
+ * 实现与 QQ 机器人网关的长连接
4
+ */
5
+ import WebSocket from "ws";
6
+ import { getChildLogger } from "../../utils/logger.js";
7
+ import { QQApiClient } from "./api.js";
8
+ const logger = getChildLogger("qq-ws");
9
+ /** WebSocket OpCode */
10
+ var OpCode;
11
+ (function (OpCode) {
12
+ /** 服务端进行消息推送 */
13
+ OpCode[OpCode["Dispatch"] = 0] = "Dispatch";
14
+ /** 客户端发送心跳 */
15
+ OpCode[OpCode["Heartbeat"] = 1] = "Heartbeat";
16
+ /** 客户端发送鉴权 */
17
+ OpCode[OpCode["Identify"] = 2] = "Identify";
18
+ /** 客户端恢复连接 */
19
+ OpCode[OpCode["Resume"] = 6] = "Resume";
20
+ /** 服务端通知客户端重新连接 */
21
+ OpCode[OpCode["Reconnect"] = 7] = "Reconnect";
22
+ /** 当鉴权或重连失败时 */
23
+ OpCode[OpCode["InvalidSession"] = 9] = "InvalidSession";
24
+ /** 服务端返回的 Hello */
25
+ OpCode[OpCode["Hello"] = 10] = "Hello";
26
+ /** 服务端返回的心跳响应 */
27
+ OpCode[OpCode["HeartbeatAck"] = 11] = "HeartbeatAck";
28
+ })(OpCode || (OpCode = {}));
29
+ export class QQWebSocketClient {
30
+ config;
31
+ apiClient;
32
+ ws = null;
33
+ sessionId = null;
34
+ sequence = null;
35
+ heartbeatInterval = null;
36
+ heartbeatTimer = null;
37
+ reconnectAttempts = 0;
38
+ maxReconnectAttempts = 10;
39
+ eventHandler = null;
40
+ isConnected = false;
41
+ constructor(config) {
42
+ this.config = config;
43
+ this.apiClient = new QQApiClient(config);
44
+ }
45
+ /** 设置事件处理器 */
46
+ setEventHandler(handler) {
47
+ this.eventHandler = handler;
48
+ }
49
+ /** 启动连接 */
50
+ async start() {
51
+ try {
52
+ const gatewayUrl = await this.apiClient.getGatewayUrl();
53
+ logger.info({ gatewayUrl }, "Got gateway URL");
54
+ await this.connect(gatewayUrl);
55
+ }
56
+ catch (error) {
57
+ logger.error({ error }, "Failed to start WebSocket client");
58
+ throw error;
59
+ }
60
+ }
61
+ /** 连接到网关 */
62
+ async connect(gatewayUrl) {
63
+ return new Promise((resolve, reject) => {
64
+ this.ws = new WebSocket(gatewayUrl);
65
+ this.ws.on("open", () => {
66
+ logger.info("WebSocket connected");
67
+ });
68
+ this.ws.on("message", async (data) => {
69
+ try {
70
+ const payload = JSON.parse(data.toString());
71
+ await this.handlePayload(payload);
72
+ // 在收到 Ready 事件后 resolve
73
+ if (payload.t === "READY") {
74
+ resolve();
75
+ }
76
+ }
77
+ catch (error) {
78
+ logger.error({ error, data: data.toString() }, "Failed to handle message");
79
+ }
80
+ });
81
+ this.ws.on("close", (code, reason) => {
82
+ logger.warn({ code, reason: reason.toString() }, "WebSocket closed");
83
+ this.isConnected = false;
84
+ this.stopHeartbeat();
85
+ this.handleDisconnect();
86
+ });
87
+ this.ws.on("error", (error) => {
88
+ logger.error({ error }, "WebSocket error");
89
+ reject(error);
90
+ });
91
+ // 设置连接超时
92
+ setTimeout(() => {
93
+ if (!this.isConnected) {
94
+ reject(new Error("Connection timeout"));
95
+ }
96
+ }, 30000);
97
+ });
98
+ }
99
+ /** 处理 WebSocket 消息 */
100
+ async handlePayload(payload) {
101
+ // 更新序列号
102
+ if (payload.s !== undefined) {
103
+ this.sequence = payload.s;
104
+ }
105
+ switch (payload.op) {
106
+ case OpCode.Hello:
107
+ await this.handleHello(payload.d);
108
+ break;
109
+ case OpCode.Dispatch:
110
+ await this.handleDispatch(payload.t, payload.d);
111
+ break;
112
+ case OpCode.HeartbeatAck:
113
+ logger.debug("Heartbeat acknowledged");
114
+ break;
115
+ case OpCode.Reconnect:
116
+ logger.info("Received reconnect request");
117
+ await this.reconnect();
118
+ break;
119
+ case OpCode.InvalidSession:
120
+ logger.warn("Invalid session, re-identifying");
121
+ this.sessionId = null;
122
+ await this.identify();
123
+ break;
124
+ }
125
+ }
126
+ /** 处理 Hello 消息 */
127
+ async handleHello(data) {
128
+ this.heartbeatInterval = data.heartbeat_interval;
129
+ logger.info({ heartbeatInterval: this.heartbeatInterval }, "Received Hello");
130
+ // 开始心跳
131
+ this.startHeartbeat();
132
+ // 发送鉴权
133
+ if (this.sessionId) {
134
+ await this.resume();
135
+ }
136
+ else {
137
+ await this.identify();
138
+ }
139
+ }
140
+ /** 发送鉴权请求 */
141
+ async identify() {
142
+ const token = await this.apiClient.getAccessToken();
143
+ const intents = this.getIntents();
144
+ const payload = {
145
+ op: OpCode.Identify,
146
+ d: {
147
+ token: `QQBot ${token}`,
148
+ intents,
149
+ shard: [0, 1],
150
+ properties: {
151
+ $os: "linux",
152
+ $browser: "mozi",
153
+ $device: "mozi",
154
+ },
155
+ },
156
+ };
157
+ this.send(payload);
158
+ logger.info({ intents }, "Identify sent");
159
+ }
160
+ /** 恢复连接 */
161
+ async resume() {
162
+ const token = await this.apiClient.getAccessToken();
163
+ const payload = {
164
+ op: OpCode.Resume,
165
+ d: {
166
+ token: `QQBot ${token}`,
167
+ session_id: this.sessionId,
168
+ seq: this.sequence,
169
+ },
170
+ };
171
+ this.send(payload);
172
+ logger.info("Resume sent");
173
+ }
174
+ /** 获取订阅的事件 intents */
175
+ getIntents() {
176
+ let intents = 0;
177
+ // 基础事件
178
+ intents |= 1 << 0; // GUILDS
179
+ intents |= 1 << 1; // GUILD_MEMBERS
180
+ intents |= 1 << 9; // GUILD_MESSAGE_REACTIONS
181
+ intents |= 1 << 10; // DIRECT_MESSAGE
182
+ intents |= 1 << 12; // INTERACTION
183
+ intents |= 1 << 25; // GROUP_AND_C2C_EVENT (群聊和私聊)
184
+ intents |= 1 << 30; // PUBLIC_GUILD_MESSAGES (公域消息)
185
+ return intents;
186
+ }
187
+ /** 处理事件分发 */
188
+ async handleDispatch(eventType, data) {
189
+ logger.debug({ eventType }, "Received event");
190
+ switch (eventType) {
191
+ case "READY":
192
+ const readyData = data;
193
+ this.sessionId = readyData.session_id;
194
+ this.isConnected = true;
195
+ this.reconnectAttempts = 0;
196
+ logger.info({ sessionId: this.sessionId, user: readyData.user }, "Ready");
197
+ break;
198
+ case "RESUMED":
199
+ this.isConnected = true;
200
+ this.reconnectAttempts = 0;
201
+ logger.info("Resumed");
202
+ break;
203
+ // 频道消息
204
+ case "AT_MESSAGE_CREATE":
205
+ case "MESSAGE_CREATE":
206
+ await this.handleChannelMessage(data);
207
+ break;
208
+ // 私信消息
209
+ case "DIRECT_MESSAGE_CREATE":
210
+ await this.handleDirectMessage(data);
211
+ break;
212
+ // 群聊消息 (QQ 群)
213
+ case "GROUP_AT_MESSAGE_CREATE":
214
+ await this.handleGroupMessage(data);
215
+ break;
216
+ // 私聊消息 (QQ 单聊)
217
+ case "C2C_MESSAGE_CREATE":
218
+ await this.handleC2CMessage(data);
219
+ break;
220
+ default:
221
+ logger.debug({ eventType, data }, "Unhandled event");
222
+ }
223
+ }
224
+ /** 处理频道消息 */
225
+ async handleChannelMessage(data) {
226
+ if (!this.eventHandler)
227
+ return;
228
+ // 过滤机器人自己的消息
229
+ if (data.author.id === this.sessionId)
230
+ return;
231
+ const context = {
232
+ channelId: "qq",
233
+ messageId: data.id,
234
+ chatId: data.channel_id,
235
+ chatType: "group",
236
+ senderId: data.author.id,
237
+ senderName: data.author.username,
238
+ content: this.cleanContent(data.content),
239
+ timestamp: new Date(data.timestamp).getTime(),
240
+ raw: data,
241
+ };
242
+ await this.eventHandler(context);
243
+ }
244
+ /** 处理频道私信 */
245
+ async handleDirectMessage(data) {
246
+ if (!this.eventHandler)
247
+ return;
248
+ const context = {
249
+ channelId: "qq",
250
+ messageId: data.id,
251
+ chatId: data.guild_id,
252
+ chatType: "direct",
253
+ senderId: data.author.id,
254
+ senderName: data.author.username,
255
+ content: this.cleanContent(data.content),
256
+ timestamp: new Date(data.timestamp).getTime(),
257
+ raw: data,
258
+ };
259
+ await this.eventHandler(context);
260
+ }
261
+ /** 处理 QQ 群消息 */
262
+ async handleGroupMessage(data) {
263
+ if (!this.eventHandler)
264
+ return;
265
+ const context = {
266
+ channelId: "qq",
267
+ messageId: data.id,
268
+ chatId: `group:${data.group_openid}`,
269
+ chatType: "group",
270
+ senderId: data.author.member_openid || data.author.id,
271
+ senderName: data.author.username,
272
+ content: this.cleanContent(data.content),
273
+ timestamp: new Date(data.timestamp).getTime(),
274
+ raw: data,
275
+ };
276
+ await this.eventHandler(context);
277
+ }
278
+ /** 处理 QQ 私聊消息 */
279
+ async handleC2CMessage(data) {
280
+ if (!this.eventHandler)
281
+ return;
282
+ const context = {
283
+ channelId: "qq",
284
+ messageId: data.id,
285
+ chatId: `c2c:${data.author.union_openid || data.author.id}`,
286
+ chatType: "direct",
287
+ senderId: data.author.union_openid || data.author.id,
288
+ senderName: data.author.username,
289
+ content: this.cleanContent(data.content),
290
+ timestamp: new Date(data.timestamp).getTime(),
291
+ raw: data,
292
+ };
293
+ await this.eventHandler(context);
294
+ }
295
+ /** 清理消息内容 (去除 @ 标记等) */
296
+ cleanContent(content) {
297
+ // 去除 @ 机器人的内容
298
+ return content.replace(/<@!\d+>/g, "").trim();
299
+ }
300
+ /** 开始心跳 */
301
+ startHeartbeat() {
302
+ if (!this.heartbeatInterval)
303
+ return;
304
+ this.heartbeatTimer = setInterval(() => {
305
+ this.sendHeartbeat();
306
+ }, this.heartbeatInterval);
307
+ }
308
+ /** 停止心跳 */
309
+ stopHeartbeat() {
310
+ if (this.heartbeatTimer) {
311
+ clearInterval(this.heartbeatTimer);
312
+ this.heartbeatTimer = null;
313
+ }
314
+ }
315
+ /** 发送心跳 */
316
+ sendHeartbeat() {
317
+ const payload = {
318
+ op: OpCode.Heartbeat,
319
+ d: this.sequence,
320
+ };
321
+ this.send(payload);
322
+ logger.debug({ sequence: this.sequence }, "Heartbeat sent");
323
+ }
324
+ /** 发送消息 */
325
+ send(payload) {
326
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
327
+ this.ws.send(JSON.stringify(payload));
328
+ }
329
+ }
330
+ /** 处理断开连接 */
331
+ async handleDisconnect() {
332
+ if (this.reconnectAttempts >= this.maxReconnectAttempts) {
333
+ logger.error("Max reconnect attempts reached");
334
+ return;
335
+ }
336
+ this.reconnectAttempts++;
337
+ const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 60000);
338
+ logger.info({ attempt: this.reconnectAttempts, delay }, "Reconnecting...");
339
+ await new Promise((resolve) => setTimeout(resolve, delay));
340
+ await this.reconnect();
341
+ }
342
+ /** 重新连接 */
343
+ async reconnect() {
344
+ try {
345
+ this.stopHeartbeat();
346
+ if (this.ws) {
347
+ this.ws.close();
348
+ this.ws = null;
349
+ }
350
+ await this.start();
351
+ }
352
+ catch (error) {
353
+ logger.error({ error }, "Failed to reconnect");
354
+ await this.handleDisconnect();
355
+ }
356
+ }
357
+ /** 停止连接 */
358
+ async stop() {
359
+ this.stopHeartbeat();
360
+ if (this.ws) {
361
+ this.ws.close();
362
+ this.ws = null;
363
+ }
364
+ this.isConnected = false;
365
+ logger.info("WebSocket client stopped");
366
+ }
367
+ /** 检查是否已连接 */
368
+ checkConnected() {
369
+ return this.isConnected;
370
+ }
371
+ }
372
+ //# sourceMappingURL=websocket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../../src/channels/qq/websocket.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 企业微信 API 客户端
3
+ * 基于企业微信服务端 API
4
+ */
5
+ import type { WeComConfig } from "../../types/index.js";
6
+ /** 发送消息响应 */
7
+ interface SendMessageResponse {
8
+ errcode: number;
9
+ errmsg: string;
10
+ msgid?: string;
11
+ }
12
+ export declare class WeComApiClient {
13
+ private config;
14
+ private client;
15
+ private tokenCache;
16
+ constructor(config: WeComConfig);
17
+ /** 获取 Access Token */
18
+ getAccessToken(): Promise<string>;
19
+ /** 发送应用消息 (文本) */
20
+ sendTextMessage(userId: string, content: string): Promise<SendMessageResponse>;
21
+ /** 发送群聊消息 */
22
+ sendGroupTextMessage(chatId: string, content: string): Promise<SendMessageResponse>;
23
+ /** 获取用户信息 */
24
+ getUserInfo(userId: string): Promise<{
25
+ name: string;
26
+ userid: string;
27
+ }>;
28
+ }
29
+ export {};
30
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/channels/wecom/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAaxD,aAAa;AACb,UAAU,mBAAmB;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAA2B;gBAEjC,MAAM,EAAE,WAAW;IAW/B,sBAAsB;IAChB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAiCvC,kBAAkB;IACZ,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,mBAAmB,CAAC;IAsB/B,aAAa;IACP,oBAAoB,CACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,mBAAmB,CAAC;IAqB/B,aAAa;IACP,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAW7E"}