@alemonjs/qq-bot 2.1.31 → 2.1.33

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.
@@ -3,7 +3,6 @@ import bodyParser from 'koa-bodyparser';
3
3
  import Router from 'koa-router';
4
4
  import { WebhookAPI } from './webhook.secret.js';
5
5
  import Koa from 'koa';
6
- import { config } from './config.js';
7
6
  import { v4 } from 'uuid';
8
7
  import { WebSocketServer, WebSocket } from 'ws';
9
8
 
@@ -23,10 +22,7 @@ class QQBotClient extends QQBotAPI {
23
22
  #client = [];
24
23
  #ws = null;
25
24
  constructor(opstion) {
26
- super();
27
- for (const key in opstion) {
28
- config.set(key, opstion[key]);
29
- }
25
+ super(opstion);
30
26
  }
31
27
  on(key, val) {
32
28
  if (!this.#events[key]) {
@@ -37,13 +33,13 @@ class QQBotClient extends QQBotAPI {
37
33
  }
38
34
  async #setTimeoutBotConfig() {
39
35
  const callBack = async () => {
40
- const app_id = config.get('app_id');
41
- const secret = config.get('secret');
36
+ const app_id = this.config.get('app_id');
37
+ const secret = this.config.get('secret');
42
38
  if (!app_id || !secret) {
43
39
  return;
44
40
  }
45
41
  const data = await this.getAuthentication();
46
- config.set('access_token', data.access_token);
42
+ this.config.set('access_token', data.access_token);
47
43
  console.info('refresh', data.expires_in, 's');
48
44
  setTimeout(() => void callBack(), data.expires_in * 1000);
49
45
  };
@@ -51,15 +47,16 @@ class QQBotClient extends QQBotAPI {
51
47
  }
52
48
  connect() {
53
49
  try {
54
- const ws = config.get('ws');
50
+ const ws = this.config.get('ws');
51
+ this.updateConnectionStatus({ state: 'connecting', transport: ws ? 'proxy' : 'webhook' });
55
52
  if (!ws) {
56
53
  void this.#setTimeoutBotConfig();
57
54
  this.#app = new Koa();
58
55
  this.#app.use(bodyParser());
59
56
  const router = new Router();
60
- const port = config.get('port');
61
- const secret = config.get('secret');
62
- const route = config.get('route') ?? '/webhook';
57
+ const port = this.config.get('port');
58
+ const secret = this.config.get('secret');
59
+ const route = this.config.get('route') ?? '/webhook';
63
60
  const cfg = {
64
61
  secret: secret ?? '',
65
62
  port: port ? Number(port) : 17157
@@ -96,7 +93,7 @@ class QQBotClient extends QQBotAPI {
96
93
  for (const event of this.#events[body.t] || []) {
97
94
  event(body.d);
98
95
  }
99
- const accessToken = config.get('access_token');
96
+ const accessToken = this.config.get('access_token');
100
97
  for (const client of this.#client) {
101
98
  try {
102
99
  if (accessToken) {
@@ -114,6 +111,7 @@ class QQBotClient extends QQBotAPI {
114
111
  this.#app.use(router.allowedMethods());
115
112
  const server = this.#app.listen(cfg.port, () => {
116
113
  console.log('Server running at http://localhost:' + cfg.port + route);
114
+ this.updateConnectionStatus({ state: 'ready' });
117
115
  });
118
116
  const wss = new WebSocketServer({ server: server });
119
117
  console.log('Server running at ws://localhost:' + cfg.port + '/');
@@ -144,6 +142,7 @@ class QQBotClient extends QQBotAPI {
144
142
  this.#ws = new WebSocket(ws);
145
143
  this.#ws.on('open', () => {
146
144
  this.#count = 0;
145
+ this.updateConnectionStatus({ state: 'ready' });
147
146
  console.log('ws connected');
148
147
  });
149
148
  this.#ws.on('message', data => {
@@ -151,7 +150,7 @@ class QQBotClient extends QQBotAPI {
151
150
  const body = normalizeGatewayMessage(JSON.parse(data.toString()));
152
151
  const accessToken = body['access_token'];
153
152
  if (accessToken) {
154
- config.set('access_token', accessToken);
153
+ this.config.set('access_token', accessToken);
155
154
  }
156
155
  for (const event of this.#events[body.t] || []) {
157
156
  event(body.d);
@@ -162,6 +161,7 @@ class QQBotClient extends QQBotAPI {
162
161
  }
163
162
  });
164
163
  this.#ws.on('close', () => {
164
+ this.updateConnectionStatus({ state: 'offline' });
165
165
  console.log('ws closed');
166
166
  if (this.#count > 5) {
167
167
  return;
@@ -3,7 +3,8 @@ import { QQBotEventMap } from './message.js';
3
3
  import { Options } from './typing.js';
4
4
  export declare class QQBotClients extends QQBotAPI {
5
5
  #private;
6
- constructor(opstion: Options);
6
+ constructor(option: Options);
7
+ disconnect(): void;
7
8
  on<T extends keyof QQBotEventMap>(key: T, val: (event: QQBotEventMap[T]) => any): this;
8
9
  connect(gatewayURL?: string): Promise<void>;
9
10
  }
@@ -1,8 +1,7 @@
1
1
  import WebSocket from 'ws';
2
2
  import { QQBotAPI } from './api.js';
3
- import { config } from './config.js';
4
3
  import { getIntentsMask } from './intents.js';
5
- import { Counter } from 'alemonjs/utils';
4
+ import { FileSessionStore } from './session.js';
6
5
 
7
6
  const normalizeGatewayMessage = (message) => {
8
7
  if (!message?.id || !message?.d || typeof message.d !== 'object' || Array.isArray(message.d)) {
@@ -14,41 +13,192 @@ const normalizeGatewayMessage = (message) => {
14
13
  return message;
15
14
  };
16
15
  class QQBotClients extends QQBotAPI {
17
- #counter = new Counter(1);
18
16
  #isConnected = false;
19
- #heartbeat_interval = 30000;
20
- #IntervalId = null;
17
+ #stopped = false;
18
+ #sessionId = null;
19
+ #sessionStore;
20
+ #sessionLoaded = false;
21
+ #sequence = null;
22
+ #heartbeatAcknowledged = true;
23
+ #heartbeatInterval = 30000;
24
+ #heartbeatTimer = null;
25
+ #accessTokenTimer = null;
26
+ #accessTokenTask = null;
27
+ #reconnectTimer = null;
28
+ #reconnectAttempts = 0;
21
29
  #gatewayUrl = null;
22
- constructor(opstion) {
23
- super();
24
- for (const key in opstion) {
25
- config.set(key, opstion[key]);
30
+ #ws = null;
31
+ #events = {};
32
+ constructor(option) {
33
+ super(option);
34
+ this.#sessionStore = option.sessionStore || new FileSessionStore();
35
+ }
36
+ async #loadSession() {
37
+ if (this.#sessionLoaded)
38
+ return;
39
+ this.#sessionLoaded = true;
40
+ const botId = String(this.config.get('app_id') || '');
41
+ const session = botId ? await this.#sessionStore.load(botId) : null;
42
+ if (session) {
43
+ this.#sessionId = session.sessionId;
44
+ this.#sequence = session.sequence;
45
+ }
46
+ }
47
+ #persistSession() {
48
+ const botId = String(this.config.get('app_id') || '');
49
+ if (!botId || !this.#sessionId || this.#sequence === null)
50
+ return;
51
+ void this.#sessionStore.save({ botId, sessionId: this.#sessionId, sequence: this.#sequence }).catch(err => {
52
+ console.warn('[ws-qqbot] session persistence failed', err);
53
+ });
54
+ }
55
+ #clearSession() {
56
+ const botId = String(this.config.get('app_id') || '');
57
+ this.#sessionId = null;
58
+ this.#sequence = null;
59
+ if (botId)
60
+ void this.#sessionStore.clear(botId).catch(() => undefined);
61
+ }
62
+ #clearHeartbeat() {
63
+ if (this.#heartbeatTimer) {
64
+ clearInterval(this.#heartbeatTimer);
65
+ this.#heartbeatTimer = null;
26
66
  }
27
67
  }
28
- async #setTimeoutBotConfig() {
29
- const accessToken = async () => {
30
- const app_id = config.get('app_id');
31
- const secret = config.get('secret');
32
- if (!app_id || !secret) {
68
+ #startHeartbeat(ws) {
69
+ this.#clearHeartbeat();
70
+ this.#heartbeatTimer = setInterval(() => {
71
+ if (this.#ws !== ws || !this.#isConnected || ws.readyState !== WebSocket.OPEN) {
72
+ this.#clearHeartbeat();
73
+ return;
74
+ }
75
+ if (!this.#heartbeatAcknowledged) {
76
+ this.#requestReconnect('heartbeat acknowledgement timeout');
33
77
  return;
34
78
  }
79
+ try {
80
+ this.#heartbeatAcknowledged = false;
81
+ this.updateConnectionStatus({ heartbeatAcknowledged: false });
82
+ ws.send(JSON.stringify({
83
+ op: 1,
84
+ d: null
85
+ }));
86
+ }
87
+ catch (err) {
88
+ console.error('[ws-qqbot] heartbeat failed', err);
89
+ this.#requestReconnect('heartbeat failed');
90
+ }
91
+ }, this.#heartbeatInterval);
92
+ }
93
+ #getReconnectDelay() {
94
+ const delay = Math.min(1000 * 2 ** Math.min(this.#reconnectAttempts, 5), 30000);
95
+ const jitter = Math.floor(Math.random() * Math.min(1000, Math.floor(delay / 4)));
96
+ return delay + jitter;
97
+ }
98
+ #scheduleReconnect(reason) {
99
+ if (this.#stopped || this.#reconnectTimer) {
100
+ return;
101
+ }
102
+ const delay = this.#getReconnectDelay();
103
+ this.#reconnectAttempts++;
104
+ this.updateConnectionStatus({
105
+ state: 'reconnecting',
106
+ reconnectAttempts: this.#reconnectAttempts,
107
+ heartbeatAcknowledged: this.#heartbeatAcknowledged,
108
+ lastError: reason
109
+ });
110
+ console.info(`[ws-qqbot] ${reason}; reconnecting in ${delay}ms (attempt ${this.#reconnectAttempts})`);
111
+ this.#reconnectTimer = setTimeout(() => {
112
+ this.#reconnectTimer = null;
113
+ void this.connect();
114
+ }, delay);
115
+ }
116
+ #requestReconnect(reason) {
117
+ this.#isConnected = false;
118
+ this.#clearHeartbeat();
119
+ this.cancelStreams();
120
+ this.#scheduleReconnect(reason);
121
+ const ws = this.#ws;
122
+ if (ws && ws.readyState !== WebSocket.CLOSED && ws.readyState !== WebSocket.CLOSING) {
123
+ ws.close();
124
+ }
125
+ }
126
+ disconnect() {
127
+ this.#stopped = true;
128
+ this.#isConnected = false;
129
+ this.#clearHeartbeat();
130
+ if (this.#reconnectTimer) {
131
+ clearTimeout(this.#reconnectTimer);
132
+ }
133
+ if (this.#accessTokenTimer) {
134
+ clearTimeout(this.#accessTokenTimer);
135
+ }
136
+ this.#reconnectTimer = null;
137
+ this.#accessTokenTimer = null;
138
+ const ws = this.#ws;
139
+ this.#ws = null;
140
+ this.cancelStreams();
141
+ if (ws && ws.readyState !== WebSocket.CLOSED) {
142
+ ws.close(1000, 'client stopped');
143
+ }
144
+ this.updateConnectionStatus({ state: 'stopped', heartbeatAcknowledged: false });
145
+ }
146
+ #scheduleAccessTokenRefresh(delay) {
147
+ if (this.#accessTokenTimer) {
148
+ clearTimeout(this.#accessTokenTimer);
149
+ }
150
+ this.#accessTokenTimer = setTimeout(() => {
151
+ this.#accessTokenTimer = null;
152
+ void this.#startAccessTokenRefresh().catch(() => undefined);
153
+ }, delay);
154
+ }
155
+ async #refreshAccessToken() {
156
+ const appId = this.config.get('app_id');
157
+ const secret = this.config.get('secret');
158
+ if (!appId || !secret) {
159
+ throw new Error('QQ Bot app_id or secret is missing');
160
+ }
161
+ try {
35
162
  const data = await this.getAuthentication();
36
- config.set('access_token', data.access_token);
37
- console.info('refresh', data.expires_in, 's');
38
- setTimeout(() => void accessToken(), data.expires_in * 1000);
39
- };
40
- await accessToken();
163
+ if (!data?.access_token) {
164
+ throw new Error('QQ Bot access token is empty');
165
+ }
166
+ this.config.set('access_token', data.access_token);
167
+ const expiresIn = Number(data.expires_in);
168
+ const refreshIn = Math.max(60000, (Number.isFinite(expiresIn) ? expiresIn * 1000 : 3600000) - 60000);
169
+ this.#scheduleAccessTokenRefresh(refreshIn);
170
+ console.info(`[ws-qqbot] access token refreshed; next refresh in ${refreshIn}ms`);
171
+ }
172
+ catch (err) {
173
+ this.#scheduleAccessTokenRefresh(30000);
174
+ console.error('[ws-qqbot] access token refresh failed; retrying in 30000ms', err);
175
+ throw err;
176
+ }
177
+ }
178
+ #startAccessTokenRefresh() {
179
+ if (this.#accessTokenTask === null) {
180
+ this.#accessTokenTask = this.#refreshAccessToken().finally(() => {
181
+ this.#accessTokenTask = null;
182
+ });
183
+ }
184
+ return this.#accessTokenTask;
185
+ }
186
+ async #ensureAccessToken() {
187
+ if (this.#accessTokenTimer) {
188
+ return;
189
+ }
190
+ await this.#startAccessTokenRefresh();
41
191
  }
42
192
  #aut() {
43
- const token = config.get('access_token');
44
- const intents = config.get('intents');
45
- const shard = config.get('shard');
193
+ const token = this.config.get('access_token');
194
+ const intents = this.config.get('intents');
195
+ const shard = this.config.get('shard');
46
196
  return {
47
197
  op: 2,
48
198
  d: {
49
199
  token: `QQBot ${token}`,
50
200
  intents: getIntentsMask(intents),
51
- shard: shard,
201
+ shard,
52
202
  properties: {
53
203
  $os: process.platform,
54
204
  $browser: 'alemonjs',
@@ -57,8 +207,16 @@ class QQBotClients extends QQBotAPI {
57
207
  }
58
208
  };
59
209
  }
60
- #ws = null;
61
- #events = {};
210
+ #resume() {
211
+ return {
212
+ op: 6,
213
+ d: {
214
+ token: `QQBot ${this.config.get('access_token')}`,
215
+ session_id: this.#sessionId,
216
+ seq: this.#sequence
217
+ }
218
+ };
219
+ }
62
220
  on(key, val) {
63
221
  if (!this.#events[key]) {
64
222
  this.#events[key] = [];
@@ -66,119 +224,172 @@ class QQBotClients extends QQBotAPI {
66
224
  this.#events[key].push(val);
67
225
  return this;
68
226
  }
227
+ #emitError(err) {
228
+ for (const event of this.#events.ERROR || []) {
229
+ try {
230
+ event(err);
231
+ }
232
+ catch (error) {
233
+ console.error('[ws-qqbot] error handler failed', error);
234
+ }
235
+ }
236
+ }
237
+ #handleDispatch(t, d) {
238
+ for (const event of this.#events[t] || []) {
239
+ try {
240
+ event(d);
241
+ }
242
+ catch (err) {
243
+ this.#emitError(err);
244
+ }
245
+ }
246
+ }
69
247
  async connect(gatewayURL) {
70
- await this.#setTimeoutBotConfig();
248
+ this.#stopped = false;
249
+ if (gatewayURL) {
250
+ this.#gatewayUrl = gatewayURL;
251
+ }
252
+ if (this.#ws && this.#ws.readyState !== WebSocket.CLOSED) {
253
+ return;
254
+ }
255
+ await this.#loadSession();
256
+ try {
257
+ await this.#ensureAccessToken();
258
+ }
259
+ catch {
260
+ this.#scheduleReconnect('access token unavailable');
261
+ return;
262
+ }
71
263
  if (!this.#gatewayUrl) {
72
- this.#gatewayUrl = gatewayURL ?? (await this.gateway().then(res => res?.url));
264
+ try {
265
+ this.#gatewayUrl = await this.gateway().then(res => res?.url);
266
+ }
267
+ catch (err) {
268
+ this.#emitError(err);
269
+ this.#scheduleReconnect('gateway request failed');
270
+ return;
271
+ }
73
272
  }
74
273
  if (!this.#gatewayUrl) {
274
+ this.#scheduleReconnect('gateway URL is empty');
75
275
  return;
76
276
  }
77
- const reconnect = () => {
78
- if (this.#counter.value >= 5) {
79
- console.info('The maximum number of reconnections has been reached, cancel reconnection');
277
+ let ws;
278
+ try {
279
+ ws = new WebSocket(this.#gatewayUrl);
280
+ }
281
+ catch (err) {
282
+ this.#emitError(err);
283
+ this.#scheduleReconnect('gateway connection creation failed');
284
+ return;
285
+ }
286
+ this.#ws = ws;
287
+ this.updateConnectionStatus({ state: 'connecting', transport: 'websocket', lastError: undefined });
288
+ ws.on('open', () => {
289
+ if (this.#ws === ws) {
290
+ console.info('[ws-qqbot] open');
291
+ }
292
+ });
293
+ ws.on('message', msg => {
294
+ if (this.#ws !== ws) {
80
295
  return;
81
296
  }
82
- setTimeout(() => {
83
- console.info('[ws-qqbot] reconnecting...');
84
- start();
85
- this.#counter.next();
86
- }, 5000);
87
- };
88
- const start = () => {
89
- if (this.#gatewayUrl) {
297
+ try {
298
+ const message = normalizeGatewayMessage(JSON.parse(msg.toString('utf8')));
299
+ if (process.env.NTQQ_WS === 'dev') {
300
+ console.info('message', message);
301
+ }
90
302
  const map = {
91
- 0: ({ t, d }) => {
92
- if (this.#events[t]) {
93
- try {
94
- for (const event of this.#events[t]) {
95
- if (typeof event !== 'function') {
96
- continue;
97
- }
98
- event(d);
99
- }
100
- }
101
- catch (err) {
102
- if (this.#events['ERROR']) {
103
- for (const event of this.#events['ERROR']) {
104
- if (typeof event !== 'function') {
105
- continue;
106
- }
107
- event(err);
108
- }
109
- }
110
- }
303
+ 0: ({ t, d, s }) => {
304
+ if (typeof s === 'number') {
305
+ this.#sequence = s;
111
306
  }
112
- if (t === 'READY') {
113
- if (this.#IntervalId) {
114
- clearInterval(this.#IntervalId);
115
- }
116
- this.#IntervalId = setInterval(() => {
117
- if (this.#isConnected && this.#ws) {
118
- this.#ws.send(JSON.stringify({
119
- op: 1,
120
- d: null
121
- }));
122
- }
123
- }, this.#heartbeat_interval);
307
+ if (t === 'READY' && d?.session_id) {
308
+ this.#sessionId = String(d.session_id);
124
309
  }
125
- if (t === 'RESUMED') {
126
- console.info('[ws-qqbot] restore connection');
127
- this.#counter.reStart();
310
+ this.#persistSession();
311
+ this.#handleDispatch(t, d);
312
+ if (t === 'READY' || t === 'RESUMED') {
313
+ this.#reconnectAttempts = 0;
314
+ this.updateConnectionStatus({
315
+ state: 'ready',
316
+ reconnectAttempts: 0,
317
+ heartbeatAcknowledged: this.#heartbeatAcknowledged,
318
+ sessionId: this.#sessionId ?? undefined,
319
+ sequence: this.#sequence ?? undefined,
320
+ resumed: t === 'RESUMED'
321
+ });
322
+ console.info(t === 'READY' ? '[ws-qqbot] ready' : '[ws-qqbot] restored connection');
128
323
  }
129
324
  },
130
- 6: ({ d }) => {
131
- console.info('[ws-qqbot] connection attempt', d);
132
- },
133
325
  7: ({ d }) => {
134
- console.info('[ws-qqbot] reconnect', d);
135
- if (this.#IntervalId) {
136
- clearInterval(this.#IntervalId);
137
- }
326
+ console.info('[ws-qqbot] gateway requested reconnect', d);
327
+ this.#requestReconnect('gateway requested reconnect');
138
328
  },
139
329
  9: ({ d }) => {
140
- console.info('[ws-qqbot] parameter error', d);
330
+ console.error('[ws-qqbot] invalid session', d);
331
+ this.#clearSession();
332
+ this.#requestReconnect('invalid session');
141
333
  },
142
334
  10: ({ d }) => {
143
335
  this.#isConnected = true;
144
- this.#heartbeat_interval = d.heartbeat_interval;
145
- if (this.#ws) {
146
- this.#ws.send(JSON.stringify(this.#aut()));
336
+ this.#heartbeatInterval = Number(d?.heartbeat_interval) || 30000;
337
+ this.#startHeartbeat(ws);
338
+ try {
339
+ const resumable = this.#sessionId && this.#sequence !== null;
340
+ ws.send(JSON.stringify(resumable ? this.#resume() : this.#aut()));
341
+ this.updateConnectionStatus({
342
+ state: 'connecting',
343
+ heartbeatAcknowledged: true,
344
+ sessionId: this.#sessionId ?? undefined,
345
+ sequence: this.#sequence ?? undefined,
346
+ resumed: Boolean(resumable)
347
+ });
348
+ }
349
+ catch (err) {
350
+ console.error('[ws-qqbot] identify failed', err);
351
+ this.#emitError(err);
352
+ this.#requestReconnect('identify failed');
147
353
  }
148
354
  },
149
355
  11: () => {
150
- console.info('[ws-qqbot] heartbeat transmission');
151
- this.#counter.reStart();
356
+ this.#heartbeatAcknowledged = true;
357
+ this.updateConnectionStatus({ heartbeatAcknowledged: true });
358
+ console.debug('[ws-qqbot] heartbeat acknowledged');
152
359
  },
153
360
  12: ({ d }) => {
154
361
  console.debug('[ws-qqbot] platform data', d);
155
362
  }
156
363
  };
157
- this.#ws = new WebSocket(this.#gatewayUrl);
158
- this.#ws.on('open', () => {
159
- console.info('[ws-qqbot] open');
160
- });
161
- this.#ws.on('message', msg => {
162
- const message = normalizeGatewayMessage(JSON.parse(msg.toString('utf8')));
163
- if (process.env.NTQQ_WS === 'dev') {
164
- console.info('message', message);
165
- }
166
- if (map[message.op]) {
167
- map[message.op](message);
168
- }
169
- });
170
- this.#ws.on('close', err => {
171
- this.#isConnected = false;
172
- if (this.#IntervalId) {
173
- clearInterval(this.#IntervalId);
174
- this.#IntervalId = null;
175
- }
176
- void reconnect();
177
- console.info('[ws-qqbot] close', err);
178
- });
364
+ if (map[message.op]) {
365
+ map[message.op](message);
366
+ }
179
367
  }
180
- };
181
- start();
368
+ catch (err) {
369
+ console.error('[ws-qqbot] invalid gateway message', err);
370
+ this.#emitError(err);
371
+ }
372
+ });
373
+ ws.on('close', (code, reason) => {
374
+ if (this.#ws !== ws) {
375
+ return;
376
+ }
377
+ this.#ws = null;
378
+ this.#isConnected = false;
379
+ this.#clearHeartbeat();
380
+ this.updateConnectionStatus({ state: 'offline', heartbeatAcknowledged: false });
381
+ console.info(`[ws-qqbot] close ${code}${reason.length ? `: ${reason.toString('utf8')}` : ''}`);
382
+ this.#scheduleReconnect('connection closed');
383
+ });
384
+ ws.on('error', err => {
385
+ if (this.#ws !== ws) {
386
+ return;
387
+ }
388
+ console.error('[ws-qqbot] error', err);
389
+ this.updateConnectionStatus({ state: 'offline', lastError: err.message });
390
+ this.#emitError(err);
391
+ this.#requestReconnect('connection error');
392
+ });
182
393
  }
183
394
  }
184
395
 
@@ -1 +1,3 @@
1
- export declare const config: Map<string, any>;
1
+ export declare class QQBotConfig extends Map<string, any> {
2
+ constructor(value?: Record<string, unknown>);
3
+ }
package/lib/sdk/config.js CHANGED
@@ -1,3 +1,7 @@
1
- const config = new Map();
1
+ class QQBotConfig extends Map {
2
+ constructor(value = {}) {
3
+ super(Object.entries(value));
4
+ }
5
+ }
2
6
 
3
- export { config };
7
+ export { QQBotConfig };
@@ -1,3 +1,5 @@
1
+ import { logger } from 'alemonjs';
2
+
1
3
  const filterHeaders = (headers = {}) => {
2
4
  if (!headers) {
3
5
  return headers;
@@ -1,3 +1,3 @@
1
- export declare const AvailableIntentsEventsEnum: readonly ["GUILDS", "GUILD_MEMBERS", "GUILD_MESSAGES", "GUILD_MESSAGE_REACTIONS", "DIRECT_MESSAGE", "INTERACTION", "MESSAGE_AUDIT", "FORUMS_EVENT", "AUDIO_ACTION", "PUBLIC_GUILD_MESSAGES", "GROUP_AND_C2C_EVENT"];
1
+ export declare const AvailableIntentsEventsEnum: readonly ["GUILDS", "GUILD_MEMBERS", "GUILD_MESSAGES", "GUILD_MESSAGE_REACTIONS", "DIRECT_MESSAGE", "GROUP_MEMBER_EVENT", "INTERACTION", "MESSAGE_AUDIT", "FORUMS_EVENT", "AUDIO_ACTION", "PUBLIC_GUILD_MESSAGES", "GROUP_AND_C2C_EVENT"];
2
2
  export type IntentsEnum = (typeof AvailableIntentsEventsEnum)[number];
3
3
  export declare function getIntentsMask(intents: IntentsEnum[]): number;
@@ -4,6 +4,7 @@ const AvailableIntentsEventsEnum = [
4
4
  'GUILD_MESSAGES',
5
5
  'GUILD_MESSAGE_REACTIONS',
6
6
  'DIRECT_MESSAGE',
7
+ 'GROUP_MEMBER_EVENT',
7
8
  'INTERACTION',
8
9
  'MESSAGE_AUDIT',
9
10
  'FORUMS_EVENT',
@@ -17,6 +18,7 @@ const intentsMap = {
17
18
  GUILD_MESSAGES: 1 << 9,
18
19
  GUILD_MESSAGE_REACTIONS: 1 << 10,
19
20
  DIRECT_MESSAGE: 1 << 12,
21
+ GROUP_MEMBER_EVENT: 1 << 24,
20
22
  INTERACTION: 1 << 26,
21
23
  MESSAGE_AUDIT: 1 << 27,
22
24
  FORUMS_EVENT: 1 << 28,
@@ -14,6 +14,7 @@ import { FRIEND_DEL_TYPE } from '../message/group/FRIEND_DEL';
14
14
  import { ERROR_TYPE } from '../message/ERROR';
15
15
  import { GROUP_MEMBER_REMOVE } from '../message/group/GROUP_MEMBER_REMOVE';
16
16
  import { GROUP_MEMBER_ADD } from '../message/group/GROUP_MEMBER_ADD';
17
+ import { GROUP_JOIN_REQUEST_TYPE } from '../message/group/GROUP_JOIN_REQUEST';
17
18
  export type QQBotGroupEventMap = {
18
19
  C2C_MESSAGE_CREATE: C2C_MESSAGE_CREATE_TYPE;
19
20
  C2C_MSG_REJECT: C2C_MSG_REJECT_TYPE;
@@ -31,4 +32,5 @@ export type QQBotGroupEventMap = {
31
32
  ERROR: ERROR_TYPE;
32
33
  GROUP_MEMBER_ADD: GROUP_MEMBER_ADD;
33
34
  GROUP_MEMBER_REMOVE: GROUP_MEMBER_REMOVE;
35
+ GROUP_JOIN_REQUEST: GROUP_JOIN_REQUEST_TYPE;
34
36
  };