@zhin.js/adapter-onebot11 1.0.98 → 1.1.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 (88) hide show
  1. package/CHANGELOG.md +745 -3
  2. package/PERMITS.md +14 -0
  3. package/README.md +59 -367
  4. package/adapters/onebot11/index.js +40 -0
  5. package/adapters/onebot11/index.ts +53 -0
  6. package/agents/onebot11/agent.json +20 -0
  7. package/agents/onebot11/boundaries.md +3 -0
  8. package/agents/onebot11/conventions.md +3 -0
  9. package/agents/onebot11/skills/onebot11/SKILL.md +15 -0
  10. package/agents/onebot11/skills/onebot11/tools/set_title/index.js +25 -0
  11. package/agents/onebot11/skills/onebot11/tools/set_title/index.ts +24 -0
  12. package/agents/onebot11/system.md +3 -0
  13. package/commands/onebot11/endpoint/add/[id]/index.js +3 -0
  14. package/commands/onebot11/endpoint/add/[id]/index.ts +3 -0
  15. package/commands/onebot11/endpoint/definition.js +25 -0
  16. package/commands/onebot11/endpoint/definition.ts +23 -0
  17. package/commands/onebot11/endpoint/list/index.js +3 -0
  18. package/commands/onebot11/endpoint/list/index.ts +3 -0
  19. package/commands/onebot11/endpoint/remove/[id]/index.js +3 -0
  20. package/commands/onebot11/endpoint/remove/[id]/index.ts +3 -0
  21. package/lib/client.d.ts +20 -0
  22. package/lib/client.js +30 -0
  23. package/lib/content-port.d.ts +4 -0
  24. package/lib/content-port.js +63 -0
  25. package/lib/endpoint-management.d.ts +15 -0
  26. package/lib/endpoint-management.js +47 -0
  27. package/lib/index.d.ts +10 -16
  28. package/lib/index.js +7 -53
  29. package/lib/onebot11-runtime-state.d.ts +1 -0
  30. package/lib/onebot11-runtime-state.js +6 -0
  31. package/lib/protocol.d.ts +143 -0
  32. package/lib/protocol.js +327 -0
  33. package/lib/side-event-dispatch.d.ts +7 -0
  34. package/lib/side-event-dispatch.js +36 -0
  35. package/lib/ws-endpoint.d.ts +22 -0
  36. package/lib/ws-endpoint.js +209 -0
  37. package/lib/ws-transport.d.ts +12 -0
  38. package/lib/ws-transport.js +59 -0
  39. package/lib/ws-types.d.ts +18 -0
  40. package/lib/ws-types.js +1 -0
  41. package/lib/wss-auth.d.ts +2 -0
  42. package/lib/wss-auth.js +16 -0
  43. package/lib/wss-endpoint.d.ts +25 -0
  44. package/lib/wss-endpoint.js +186 -0
  45. package/package.json +82 -23
  46. package/plugin.js +18 -0
  47. package/schema.json +114 -0
  48. package/src/client.ts +78 -0
  49. package/src/content-port.ts +66 -0
  50. package/src/endpoint-management.ts +72 -0
  51. package/src/index.ts +60 -65
  52. package/src/onebot11-runtime-state.ts +7 -0
  53. package/src/protocol.ts +452 -0
  54. package/src/side-event-dispatch.ts +48 -0
  55. package/src/ws-endpoint.ts +272 -0
  56. package/src/ws-transport.ts +85 -0
  57. package/src/ws-types.ts +21 -0
  58. package/src/wss-auth.ts +17 -0
  59. package/src/wss-endpoint.ts +239 -0
  60. package/lib/adapter.d.ts +0 -32
  61. package/lib/adapter.d.ts.map +0 -1
  62. package/lib/adapter.js +0 -92
  63. package/lib/adapter.js.map +0 -1
  64. package/lib/bot-ws-client.d.ts +0 -40
  65. package/lib/bot-ws-client.d.ts.map +0 -1
  66. package/lib/bot-ws-client.js +0 -397
  67. package/lib/bot-ws-client.js.map +0 -1
  68. package/lib/bot-ws-server.d.ts +0 -42
  69. package/lib/bot-ws-server.d.ts.map +0 -1
  70. package/lib/bot-ws-server.js +0 -344
  71. package/lib/bot-ws-server.js.map +0 -1
  72. package/lib/index.d.ts.map +0 -1
  73. package/lib/index.js.map +0 -1
  74. package/lib/onebot-get-msg.d.ts +0 -3
  75. package/lib/onebot-get-msg.d.ts.map +0 -1
  76. package/lib/onebot-get-msg.js +0 -27
  77. package/lib/onebot-get-msg.js.map +0 -1
  78. package/lib/types.d.ts +0 -54
  79. package/lib/types.d.ts.map +0 -1
  80. package/lib/types.js +0 -5
  81. package/lib/types.js.map +0 -1
  82. package/plugin.yml +0 -3
  83. package/skills/onebot11/SKILL.md +0 -80
  84. package/src/adapter.ts +0 -104
  85. package/src/bot-ws-client.ts +0 -421
  86. package/src/bot-ws-server.ts +0 -382
  87. package/src/onebot-get-msg.ts +0 -33
  88. package/src/types.ts +0 -58
package/src/adapter.ts DELETED
@@ -1,104 +0,0 @@
1
- /**
2
- * OneBot11 适配器:单一适配器支持正向 WS / 反向 WS,由 config.connection 区分
3
- */
4
- import { formatCompact, Adapter, Plugin } from 'zhin.js';
5
- import type { Router } from '@zhin.js/host-router';
6
- import { OneBot11WsClient } from './bot-ws-client.js';
7
- import { OneBot11WsServer } from './bot-ws-server.js';
8
- import type {
9
- OneBot11WsClientConfig,
10
- OneBot11WsServerConfig,
11
- OneBot11BotConfig,
12
- } from './types.js';
13
-
14
- export type OneBot11Bot = OneBot11WsClient | OneBot11WsServer;
15
-
16
- export class OneBot11Adapter extends Adapter<OneBot11Bot> {
17
- #router?: Router;
18
-
19
- constructor(plugin: Plugin) {
20
- super(plugin, 'onebot11', []);
21
- }
22
-
23
- createBot(config: OneBot11BotConfig): OneBot11Bot {
24
- const connection = config.connection ?? 'ws';
25
- switch (connection) {
26
- case 'ws':
27
- return new OneBot11WsClient(this, config as OneBot11WsClientConfig);
28
- case 'wss':
29
- if (!this.#router) {
30
- throw new Error('OneBot11 connection: wss 需要 router,请安装并在配置中启用 @zhin.js/host-router');
31
- }
32
- return new OneBot11WsServer(this, this.#router, config as OneBot11WsServerConfig);
33
- default:
34
- throw new Error(`Unknown OneBot11 connection: ${connection}`);
35
- }
36
- }
37
-
38
- async kickMember(botId: string, sceneId: string, userId: string) {
39
- const bot = this.bots.get(botId);
40
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
41
- return bot.kickMember(Number(sceneId), Number(userId), false);
42
- }
43
-
44
- async muteMember(botId: string, sceneId: string, userId: string, duration = 600) {
45
- const bot = this.bots.get(botId);
46
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
47
- return bot.muteMember(Number(sceneId), Number(userId), duration);
48
- }
49
-
50
- async muteAll(botId: string, sceneId: string, enable = true) {
51
- const bot = this.bots.get(botId);
52
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
53
- return bot.muteAll(Number(sceneId), enable);
54
- }
55
-
56
- async setAdmin(botId: string, sceneId: string, userId: string, enable = true) {
57
- const bot = this.bots.get(botId);
58
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
59
- return bot.setAdmin(Number(sceneId), Number(userId), enable);
60
- }
61
-
62
- async setMemberNickname(botId: string, sceneId: string, userId: string, nickname: string) {
63
- const bot = this.bots.get(botId);
64
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
65
- return bot.setCard(Number(sceneId), Number(userId), nickname);
66
- }
67
-
68
- async setGroupName(botId: string, sceneId: string, name: string) {
69
- const bot = this.bots.get(botId);
70
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
71
- return bot.setGroupName(Number(sceneId), name);
72
- }
73
-
74
- async listMembers(botId: string, sceneId: string) {
75
- const bot = this.bots.get(botId);
76
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
77
- const members = await bot.getMemberList(Number(sceneId));
78
- return {
79
- members: members.map((m: any) => ({
80
- user_id: m.user_id,
81
- nickname: m.nickname,
82
- card: m.card,
83
- role: m.role,
84
- title: m.title,
85
- })),
86
- count: members.length,
87
- };
88
- }
89
-
90
- async getGroupInfo(botId: string, sceneId: string) {
91
- const bot = this.bots.get(botId);
92
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
93
- return bot.getGroupInfo(Number(sceneId));
94
- }
95
-
96
- async start(): Promise<void> {
97
- this.#router = (this.plugin.inject as (key: string) => Router | undefined)('router');
98
- (this.plugin.useContext as (key: string, fn: (router: Router) => void) => void)('router', (router: Router) => {
99
- this.#router = router;
100
- });
101
- await super.start();
102
- }
103
-
104
- }
@@ -1,421 +0,0 @@
1
- /**
2
- * OneBot11 WebSocket 客户端连接 Bot
3
- */
4
- import WebSocket from 'ws';
5
- import { EventEmitter } from 'events';
6
- import { clearInterval } from 'node:timers';
7
- import { formatCompact, Bot, Message, Notice, Request, segment, SendContent, SendOptions, type QuotedMessagePayload } from 'zhin.js';
8
- import { parseOneBotGetMsgResponse } from './onebot-get-msg.js';
9
- import type {
10
- OneBot11WsClientConfig,
11
- OneBot11Message,
12
- ApiResponse,
13
- } from './types.js';
14
- import type { OneBot11Adapter } from './adapter.js';
15
-
16
-
17
- export class OneBot11WsClient extends EventEmitter implements Bot<OneBot11WsClientConfig, OneBot11Message> {
18
- $connected: boolean;
19
- private ws?: WebSocket;
20
- private reconnectTimer?: NodeJS.Timeout;
21
- private heartbeatTimer?: NodeJS.Timeout;
22
- private requestId = 0;
23
- private pendingRequests = new Map<string, {
24
- resolve: (value: any) => void;
25
- reject: (error: Error) => void;
26
- timeout: NodeJS.Timeout;
27
- }>();
28
- get logger() {
29
- return this.adapter.plugin.logger;
30
- }
31
-
32
- constructor(public adapter: OneBot11Adapter, public $config: OneBot11WsClientConfig) {
33
- super();
34
- this.$connected = false;
35
- }
36
-
37
- get $id() {
38
- return this.$config.name;
39
- }
40
-
41
- async $connect(): Promise<void> {
42
- return new Promise((resolve, reject) => {
43
- const headers: Record<string, string> = {};
44
- if (this.$config.access_token) {
45
- headers['Authorization'] = `Bearer ${this.$config.access_token}`;
46
- const url=new URL(this.$config.url);
47
- url.searchParams.set('access_token', this.$config.access_token);
48
- this.$config.url = url.toString();
49
- }
50
- this.ws = new WebSocket(this.$config.url, { headers });
51
-
52
- this.ws.on('open', () => {
53
- this.$connected = true;
54
- if (!this.$config.access_token) {
55
- this.logger.warn(formatCompact({ bot: this.$id, ok: false, error: 'missing access_token' }));
56
- }
57
- this.logger.info(formatCompact({ bot: this.$id, mode: 'ws' }));
58
- this.startHeartbeat();
59
- resolve();
60
- });
61
-
62
- this.ws.on('message', (data) => {
63
- try {
64
- const message = JSON.parse(data.toString());
65
- this.handleWebSocketMessage(message);
66
- } catch (error) {
67
- this.emit('error', error);
68
- }
69
- });
70
-
71
- this.ws.on('close', (code, reason) => {
72
- this.$connected = false;
73
- const reasonStr = reason?.toString?.() || String(reason);
74
- const codeHint = code === 1005 ? ' [无状态,多为服务端/代理未发 close 帧即断开]' : code === 1006 ? ' [异常关闭]' : '';
75
- this.logger.warn(formatCompact( {
76
- op: 'disconnect',
77
- bot: this.$config.name,
78
- code,
79
- error: `${reasonStr || 'closed'}${codeHint}`,
80
- reconnect_ms: this.$config.reconnect_interval || 5000,
81
- }));
82
- reject({ code, reason });
83
- this.scheduleReconnect();
84
- });
85
-
86
- this.ws.on('error', (error) => {
87
- this.logger.warn(formatCompact( {
88
- op: 'ws_error',
89
- bot: this.$config.name,
90
- ok: false,
91
- error: error instanceof Error ? error.message : String(error),
92
- }));
93
- reject(error);
94
- });
95
- });
96
- }
97
-
98
- async $disconnect(): Promise<void> {
99
- if (this.reconnectTimer) {
100
- clearTimeout(this.reconnectTimer);
101
- this.reconnectTimer = undefined;
102
- }
103
- if (this.heartbeatTimer) {
104
- clearInterval(this.heartbeatTimer);
105
- this.heartbeatTimer = undefined;
106
- }
107
- for (const [, request] of this.pendingRequests) {
108
- clearTimeout(request.timeout);
109
- request.reject(new Error('Connection closed'));
110
- }
111
- this.pendingRequests.clear();
112
- if (this.ws) {
113
- this.ws.close();
114
- this.ws = undefined;
115
- }
116
- }
117
-
118
- $formatMessage(onebotMsg: OneBot11Message) {
119
- const content = Array.isArray(onebotMsg.message) ? [...onebotMsg.message] : [];
120
- const quoteId = Message.quoteIdFromContent(content);
121
- Message.alignReplySegments(content, quoteId);
122
-
123
- const message = Message.from(onebotMsg, {
124
- $id: onebotMsg.message_id.toString(),
125
- $adapter: 'onebot11',
126
- $bot: `${this.$config.name}`,
127
- $sender: {
128
- id: onebotMsg.user_id.toString(),
129
- name: onebotMsg.user_id.toString(),
130
- },
131
- $channel: {
132
- id: (onebotMsg.group_id || onebotMsg.user_id).toString(),
133
- type: onebotMsg.group_id ? 'group' : 'private',
134
- },
135
- $content: content,
136
- $quote_id: quoteId,
137
- $raw: onebotMsg.raw_message,
138
- $timestamp: onebotMsg.time,
139
- $recall: async () => {
140
- await this.$recallMessage(message.$id);
141
- },
142
- $reply: async (content: SendContent, quote?: boolean | string): Promise<string> => {
143
- if (!Array.isArray(content)) content = [content];
144
- if (quote) content.unshift({ type: 'reply', data: { message_id: message.$id } });
145
- return await this.adapter.sendMessage({
146
- ...message.$channel,
147
- context: 'onebot11',
148
- bot: `${this.$config.name}`,
149
- content,
150
- });
151
- },
152
- });
153
- return message;
154
- }
155
-
156
- async $sendMessage(options: SendOptions): Promise<string> {
157
- const messageData: any = { message: options.content };
158
- if (options.type === 'group') {
159
- const result = await this.callApi('send_group_msg', {
160
- group_id: parseInt(options.id),
161
- ...messageData,
162
- });
163
- this.logger.debug(`${this.$config.name} send ${options.type}(${options.id}):${segment.raw(options.content)}`);
164
- return result.message_id.toString();
165
- }
166
- if (options.type === 'private') {
167
- const result = await this.callApi('send_private_msg', {
168
- user_id: parseInt(options.id),
169
- ...messageData,
170
- });
171
- this.logger.debug(`${this.$config.name} send ${options.type}(${options.id}):${segment.raw(options.content)}`);
172
- return result.message_id.toString();
173
- }
174
- throw new Error('Either group_id or user_id must be provided');
175
- }
176
-
177
- async $recallMessage(id: string): Promise<void> {
178
- await this.callApi('delete_msg', { message_id: parseInt(id) });
179
- }
180
-
181
- async $getMsg(messageId: string): Promise<QuotedMessagePayload> {
182
- const idParam = /^\d+$/.test(messageId) ? Number(messageId) : messageId;
183
- const data = await this.callApi('get_msg', { message_id: idParam });
184
- return parseOneBotGetMsgResponse(messageId, data);
185
- }
186
-
187
- async kickMember(groupId: number, userId: number, rejectAddRequest: boolean = false): Promise<boolean> {
188
- try {
189
- await this.callApi('set_group_kick', {
190
- group_id: groupId,
191
- user_id: userId,
192
- reject_add_request: rejectAddRequest,
193
- });
194
- this.logger.debug(formatCompact( { op: 'kick', bot: this.$id, group: groupId, user: userId }));
195
- return true;
196
- } catch (error) {
197
- this.logger.error(`OneBot11 Bot ${this.$id} 踢出成员失败:`, error);
198
- throw error;
199
- }
200
- }
201
-
202
- async muteMember(groupId: number, userId: number, duration: number = 600): Promise<boolean> {
203
- try {
204
- await this.callApi('set_group_ban', {
205
- group_id: groupId,
206
- user_id: userId,
207
- duration,
208
- });
209
- this.logger.debug(formatCompact( { op: duration > 0 ? 'mute' : 'unmute', bot: this.$id, group: groupId, user: userId, duration }));
210
- return true;
211
- } catch (error) {
212
- this.logger.error(`OneBot11 Bot ${this.$id} 禁言操作失败:`, error);
213
- throw error;
214
- }
215
- }
216
-
217
- async muteAll(groupId: number, enable: boolean = true): Promise<boolean> {
218
- try {
219
- await this.callApi('set_group_whole_ban', { group_id: groupId, enable });
220
- this.logger.debug(formatCompact( { op: 'mute_all', bot: this.$id, group: groupId, enable }));
221
- return true;
222
- } catch (error) {
223
- this.logger.error(`OneBot11 Bot ${this.$id} 全员禁言操作失败:`, error);
224
- throw error;
225
- }
226
- }
227
-
228
- async setAdmin(groupId: number, userId: number, enable: boolean = true): Promise<boolean> {
229
- try {
230
- await this.callApi('set_group_admin', { group_id: groupId, user_id: userId, enable });
231
- this.logger.debug(formatCompact( { op: 'set_admin', bot: this.$id, group: groupId, user: userId, enable }));
232
- return true;
233
- } catch (error) {
234
- this.logger.error(`OneBot11 Bot ${this.$id} 设置管理员失败:`, error);
235
- throw error;
236
- }
237
- }
238
-
239
- async setCard(groupId: number, userId: number, card: string): Promise<boolean> {
240
- try {
241
- await this.callApi('set_group_card', { group_id: groupId, user_id: userId, card });
242
- this.logger.debug(formatCompact( { op: 'set_card', bot: this.$id, group: groupId, user: userId }));
243
- return true;
244
- } catch (error) {
245
- this.logger.error(`OneBot11 Bot ${this.$id} 设置群名片失败:`, error);
246
- throw error;
247
- }
248
- }
249
-
250
- async setTitle(groupId: number, userId: number, title: string, duration: number = -1): Promise<boolean> {
251
- try {
252
- await this.callApi('set_group_special_title', {
253
- group_id: groupId,
254
- user_id: userId,
255
- special_title: title,
256
- duration,
257
- });
258
- this.logger.debug(formatCompact( { op: 'set_title', bot: this.$id, group: groupId, user: userId }));
259
- return true;
260
- } catch (error) {
261
- this.logger.error(`OneBot11 Bot ${this.$id} 设置头衔失败:`, error);
262
- throw error;
263
- }
264
- }
265
-
266
- async setGroupName(groupId: number, name: string): Promise<boolean> {
267
- try {
268
- await this.callApi('set_group_name', { group_id: groupId, group_name: name });
269
- this.logger.debug(formatCompact( { op: 'set_group_name', bot: this.$id, group: groupId }));
270
- return true;
271
- } catch (error) {
272
- this.logger.error(`OneBot11 Bot ${this.$id} 设置群名失败:`, error);
273
- throw error;
274
- }
275
- }
276
-
277
- async getMemberList(groupId: number): Promise<any[]> {
278
- try {
279
- return await this.callApi('get_group_member_list', { group_id: groupId });
280
- } catch (error) {
281
- this.logger.error(`OneBot11 Bot ${this.$id} 获取群成员列表失败:`, error);
282
- throw error;
283
- }
284
- }
285
-
286
- async getGroupInfo(groupId: number): Promise<any> {
287
- try {
288
- return await this.callApi('get_group_info', { group_id: groupId });
289
- } catch (error) {
290
- this.logger.error(`OneBot11 Bot ${this.$id} 获取群信息失败:`, error);
291
- throw error;
292
- }
293
- }
294
-
295
- private async callApi(action: string, params: any = {}): Promise<any> {
296
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
297
- throw new Error('WebSocket is not connected');
298
- }
299
- const echo = `req_${++this.requestId}`;
300
- const message = { action, params, echo };
301
- return new Promise((resolve, reject) => {
302
- const timeout = setTimeout(() => {
303
- this.pendingRequests.delete(echo);
304
- reject(new Error(`API call timeout: ${action}`));
305
- }, 30000);
306
- this.pendingRequests.set(echo, { resolve, reject, timeout });
307
- this.ws!.send(JSON.stringify(message));
308
- });
309
- }
310
-
311
- private handleWebSocketMessage(message: any): void {
312
- if (message.echo && this.pendingRequests.has(message.echo)) {
313
- const request = this.pendingRequests.get(message.echo)!;
314
- this.pendingRequests.delete(message.echo);
315
- clearTimeout(request.timeout);
316
- const response = message as ApiResponse;
317
- if (response.status === 'ok') return request.resolve(response.data);
318
- return request.reject(new Error(`API error: ${response.retcode}`));
319
- }
320
- if (message.post_type === 'message') {
321
- this.handleOneBot11Message(message);
322
- } else if (message.post_type === 'notice') {
323
- this.handleOneBot11Notice(message);
324
- } else if (message.post_type === 'request') {
325
- this.handleOneBot11Request(message);
326
- }
327
- }
328
-
329
- private handleOneBot11Notice(event: any): void {
330
- const noticeTypeMap: Record<string, string> = {
331
- group_increase: 'group_member_increase',
332
- group_decrease: 'group_member_decrease',
333
- group_admin: 'group_admin_change',
334
- group_ban: 'group_ban',
335
- group_recall: 'group_recall',
336
- friend_recall: 'friend_recall',
337
- friend_add: 'friend_add',
338
- notify: event.sub_type === 'poke' ? (event.group_id ? 'group_poke' : 'friend_poke') : `notify_${event.sub_type}`,
339
- group_upload: 'group_upload',
340
- };
341
- const $type = noticeTypeMap[event.notice_type] || event.notice_type;
342
- const isGroup = !!event.group_id;
343
- const notice = Notice.from(event, {
344
- $id: `${event.time}_${event.notice_type}_${event.group_id || event.user_id}`,
345
- $adapter: 'onebot11',
346
- $bot: this.$config.name,
347
- $type,
348
- $subType: event.sub_type,
349
- $channel: {
350
- id: (event.group_id || event.user_id)?.toString() || '',
351
- type: isGroup ? 'group' : 'private',
352
- },
353
- $operator: event.operator_id ? { id: event.operator_id.toString(), name: event.operator_id.toString() } : undefined,
354
- $target: event.user_id ? { id: event.user_id.toString(), name: event.user_id.toString() } : undefined,
355
- $timestamp: event.time || Math.floor(Date.now() / 1000),
356
- });
357
- this.adapter.emit('notice.receive', notice);
358
- }
359
-
360
- private handleOneBot11Request(event: any): void {
361
- const typeMap: Record<string, string> = {
362
- friend: 'friend_add',
363
- group: event.sub_type === 'invite' ? 'group_invite' : 'group_add',
364
- };
365
- const $type = typeMap[event.request_type] || event.request_type;
366
- const request = Request.from(event, {
367
- $id: event.flag || `${event.time}_${event.request_type}_${event.user_id}`,
368
- $adapter: 'onebot11',
369
- $bot: this.$config.name,
370
- $type,
371
- $subType: event.sub_type,
372
- $channel: {
373
- id: (event.group_id || event.user_id)?.toString() || '',
374
- type: event.group_id ? 'group' : 'private',
375
- },
376
- $sender: { id: event.user_id?.toString() || '', name: event.user_id?.toString() || '' },
377
- $comment: event.comment,
378
- $timestamp: event.time || Math.floor(Date.now() / 1000),
379
- $approve: async (remark?: string) => {
380
- await this.callApi(
381
- event.request_type === 'friend' ? 'set_friend_add_request' : 'set_group_add_request',
382
- { flag: event.flag, approve: true, remark },
383
- );
384
- },
385
- $reject: async (reason?: string) => {
386
- await this.callApi(
387
- event.request_type === 'friend' ? 'set_friend_add_request' : 'set_group_add_request',
388
- { flag: event.flag, approve: false, reason },
389
- );
390
- },
391
- });
392
- this.adapter.emit('request.receive', request);
393
- }
394
-
395
- private handleOneBot11Message(onebotMsg: OneBot11Message): void {
396
- const message = this.$formatMessage(onebotMsg);
397
- this.adapter.emit('message.receive', message);
398
- this.logger.debug(`${this.$config.name} recv ${message.$channel.type}(${message.$channel.id}):${segment.raw(message.$content)}`);
399
- }
400
-
401
- private startHeartbeat(): void {
402
- const interval = this.$config.heartbeat_interval || 30000;
403
- this.heartbeatTimer = setInterval(() => {
404
- if (this.ws && this.ws.readyState === WebSocket.OPEN) this.ws.ping();
405
- }, interval);
406
- }
407
-
408
- private scheduleReconnect(): void {
409
- if (this.reconnectTimer) return;
410
- const interval = this.$config.reconnect_interval || 5000;
411
- this.reconnectTimer = setTimeout(async () => {
412
- this.reconnectTimer = undefined;
413
- try {
414
- await this.$connect();
415
- } catch (error) {
416
- this.emit('error', new Error(`Reconnection failed: ${error}`));
417
- this.scheduleReconnect();
418
- }
419
- }, interval);
420
- }
421
- }