@alemonjs/qq-bot 2.1.0-alpha.14 → 2.1.0-alpha.17

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/lib/index.js CHANGED
@@ -1,8 +1,6 @@
1
1
  import { getConfigValue } from 'alemonjs';
2
- import { start } from './index.group.js';
3
- import { start as start$1 } from './index.guild.js';
4
- import { start as start$2 } from './index.webhook.js';
5
- import { start as start$3 } from './index.websoket.js';
2
+ import { start } from './index.webhook.js';
3
+ import { start as start$1 } from './index.websoket.js';
6
4
  import { platform } from './config.js';
7
5
  export { useClient, useMode, useValue } from './hook.js';
8
6
  export { QQBotAPI as API } from './sdk/api.js';
@@ -13,20 +11,12 @@ var index = () => {
13
11
  if (!value)
14
12
  value = {};
15
13
  const config = value[platform];
16
- if (config?.mode == 'guild') {
14
+ if (config?.route || config?.port || config?.ws) {
17
15
  start();
18
16
  return;
19
17
  }
20
- else if (config?.mode == 'group') {
21
- start$1();
22
- return;
23
- }
24
- else if (config?.route || config?.port || config?.ws) {
25
- start$2();
26
- return;
27
- }
28
18
  else {
29
- start$3();
19
+ start$1();
30
20
  }
31
21
  };
32
22
 
@@ -1,11 +1,12 @@
1
- import { QQBotClient } from './sdk/client.js';
1
+ import { QQBotClient } from './sdk/client.webhook.js';
2
2
  import { register } from './register.js';
3
3
  import { getQQBotConfig } from './config.js';
4
4
 
5
5
  const start = () => {
6
6
  const config = getQQBotConfig();
7
+ const { master_id, master_key, ...cfgConfig } = config;
7
8
  const client = new QQBotClient({
8
- ...config
9
+ ...cfgConfig
9
10
  });
10
11
  // 连接
11
12
  client.connect();
@@ -4,27 +4,46 @@ import { getQQBotConfig } from './config.js';
4
4
 
5
5
  const start = () => {
6
6
  const config = getQQBotConfig();
7
+ const notPrivateIntents = [
8
+ 'GUILDS', // base
9
+ 'GUILD_MEMBERS', // base
10
+ 'GUILD_MESSAGE_REACTIONS',
11
+ 'DIRECT_MESSAGE',
12
+ 'PUBLIC_GUILD_MESSAGES'
13
+ ];
14
+ const isPrivateIntents = [
15
+ 'GUILDS', // base
16
+ 'GUILD_MEMBERS', // base
17
+ 'GUILD_MESSAGES',
18
+ 'GUILD_MESSAGE_REACTIONS',
19
+ 'DIRECT_MESSAGE',
20
+ 'FORUMS_EVENT'
21
+ ];
22
+ const isGroupIntents = ['GROUP_AND_C2C_EVENT'];
23
+ const pubIntents = ['INTERACTION'];
24
+ const intents = [];
25
+ if (config?.mode == 'guild') {
26
+ if (config?.is_private) {
27
+ intents.push(...isPrivateIntents, ...pubIntents);
28
+ }
29
+ else {
30
+ intents.push(...notPrivateIntents, ...pubIntents);
31
+ }
32
+ }
33
+ else if (config?.mode == 'group') {
34
+ intents.push(...isGroupIntents, ...pubIntents);
35
+ }
36
+ else {
37
+ if (config?.is_private) {
38
+ intents.push(...isPrivateIntents, ...pubIntents);
39
+ }
40
+ else {
41
+ intents.push(...notPrivateIntents, ...isGroupIntents, ...pubIntents);
42
+ }
43
+ }
7
44
  const client = new QQBotClients({
8
45
  ...config,
9
- intents: config?.intents ?? config?.is_private
10
- ? [
11
- 'GUILDS', // base
12
- 'GUILD_MEMBERS', // base
13
- 'GUILD_MESSAGES',
14
- 'GUILD_MESSAGE_REACTIONS',
15
- 'DIRECT_MESSAGE',
16
- 'INTERACTION',
17
- 'FORUMS_EVENT'
18
- ]
19
- : [
20
- 'GUILDS', // base
21
- 'GUILD_MEMBERS', // base
22
- 'GUILD_MESSAGE_REACTIONS',
23
- 'DIRECT_MESSAGE',
24
- 'INTERACTION',
25
- 'PUBLIC_GUILD_MESSAGES',
26
- 'GROUP_AND_C2C_EVENT'
27
- ],
46
+ intents: config?.intents || intents,
28
47
  is_private: config?.is_private ?? false,
29
48
  sandbox: config?.sandbox ?? false,
30
49
  shard: config?.shard ?? [0, 1],
package/lib/register.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { cbpPlatform, ResultCode, createResult } from 'alemonjs';
2
2
  import { GROUP_AT_MESSAGE_CREATE, C2C_MESSAGE_CREATE, DIRECT_MESSAGE_CREATE, AT_MESSAGE_CREATE, MESSAGE_CREATE } from './sends.js';
3
- import { getQQBotConfig, getMaster, platform } from './config.js';
3
+ import { getQQBotConfig, platform, getMaster } from './config.js';
4
4
 
5
5
  const register = (client) => {
6
6
  const config = getQQBotConfig();
@@ -20,6 +20,48 @@ const register = (client) => {
20
20
  const createUserAvatarURL = (author_id) => {
21
21
  return `https://q.qlogo.cn/qqapp/${config.app_id}/${author_id}/640`;
22
22
  };
23
+ client.on('GROUP_ADD_ROBOT', async (event) => {
24
+ // 机器人加入群组
25
+ const e = {
26
+ name: 'guild.join',
27
+ Platform: platform,
28
+ GuildId: event.group_openid,
29
+ ChannelId: event.group_openid,
30
+ SpaceId: `GROUP:${event.group_openid}`,
31
+ UserId: event.op_member_openid,
32
+ UserKey: event.op_member_openid,
33
+ UserAvatar: createUserAvatarURL(event.op_member_openid),
34
+ IsMaster: false,
35
+ IsBot: false,
36
+ OpenId: `C2C:${event.op_member_openid}`,
37
+ MessageId: '',
38
+ CreateAt: Date.now(),
39
+ tag: 'GROUP_DEL_ROBOT',
40
+ value: event
41
+ };
42
+ cbp.send(e);
43
+ });
44
+ client.on('GROUP_DEL_ROBOT', async (event) => {
45
+ // 机器人离开群组
46
+ const e = {
47
+ name: 'guild.exit',
48
+ Platform: platform,
49
+ GuildId: event.group_openid,
50
+ ChannelId: event.group_openid,
51
+ SpaceId: `GROUP:${event.group_openid}`,
52
+ UserId: event.op_member_openid,
53
+ UserKey: event.op_member_openid,
54
+ UserAvatar: createUserAvatarURL(event.op_member_openid),
55
+ IsMaster: false,
56
+ IsBot: false,
57
+ OpenId: `C2C:${event.op_member_openid}`,
58
+ MessageId: '',
59
+ CreateAt: Date.now(),
60
+ tag: 'GROUP_DEL_ROBOT',
61
+ value: event
62
+ };
63
+ cbp.send(e);
64
+ });
23
65
  // 监听消息
24
66
  client.on('GROUP_AT_MESSAGE_CREATE', async (event) => {
25
67
  const UserId = event.author.id;
package/lib/sdk/api.d.ts CHANGED
@@ -63,7 +63,7 @@ declare class QQBotAPI {
63
63
  * 1 图文 2 视频 3 语言 4 文件
64
64
  * 图片:png/jpg,视频:mp4,语音:silk
65
65
  */
66
- postRichMediaByUsers(openid: string, data: {
66
+ postRichMediaByUser(openid: string, data: {
67
67
  srv_send_msg?: boolean;
68
68
  file_type: FileType;
69
69
  url?: string;
@@ -73,49 +73,15 @@ declare class QQBotAPI {
73
73
  file_info: string;
74
74
  ttl: number;
75
75
  }>;
76
- /**
77
- * 发送私聊富媒体文件
78
- * @param openid
79
- * @param data
80
- * @returns
81
- * 1 图文 2 视频 3 语言 4 文件
82
- * 图片:png/jpg,视频:mp4,语音:silk
83
- */
84
- userFiles(openid: string, data: {
85
- srv_send_msg: boolean;
86
- file_type: FileType;
87
- url: string;
88
- file_data?: any;
89
- }): Promise<{
90
- file_uuid: string;
91
- file_info: string;
92
- ttl: number;
93
- }>;
94
76
  /**
95
77
  * 发送群里文件
96
- * @param openid GuildID / UserId
78
+ * @param openid
97
79
  * @param data
98
80
  * @returns
99
81
  * 1 图文 2 视频 3 语言 4 文件
100
82
  * 图片:png/jpg,视频:mp4,语音:silk
101
83
  */
102
- postRichMediaById(openid: string, data: {
103
- srv_send_msg?: boolean;
104
- file_type: FileType;
105
- url?: string;
106
- file_data?: any;
107
- }): Promise<{
108
- file_uuid: string;
109
- file_info: string;
110
- ttl: number;
111
- }>;
112
- /**
113
- *
114
- * @param openid
115
- * @param data
116
- * @returns
117
- */
118
- groupsFiles(openid: string, data: {
84
+ postRichMediaByGroup(openid: string, data: {
119
85
  srv_send_msg?: boolean;
120
86
  file_type: FileType;
121
87
  url?: string;
package/lib/sdk/api.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import axios from 'axios';
2
2
  import { config } from './config.js';
3
3
  import FormData from 'form-data';
4
- import { createPicFrom } from './from.js';
4
+ import { createPicFrom } from 'alemonjs/utils';
5
5
 
6
6
  const BOTS_API_RUL = 'https://bots.qq.com';
7
7
  const API_URL_SANDBOX = 'https://sandbox.api.sgroup.qq.com';
@@ -150,22 +150,7 @@ class QQBotAPI {
150
150
  * 1 图文 2 视频 3 语言 4 文件
151
151
  * 图片:png/jpg,视频:mp4,语音:silk
152
152
  */
153
- async postRichMediaByUsers(openid, data) {
154
- return this.groupService({
155
- url: `/v2/users/${openid}/files`,
156
- method: 'post',
157
- data: data
158
- }).then(res => res?.data);
159
- }
160
- /**
161
- * 发送私聊富媒体文件
162
- * @param openid
163
- * @param data
164
- * @returns
165
- * 1 图文 2 视频 3 语言 4 文件
166
- * 图片:png/jpg,视频:mp4,语音:silk
167
- */
168
- async userFiles(openid, data) {
153
+ async postRichMediaByUser(openid, data) {
169
154
  return this.groupService({
170
155
  url: `/v2/users/${openid}/files`,
171
156
  method: 'post',
@@ -174,29 +159,13 @@ class QQBotAPI {
174
159
  }
175
160
  /**
176
161
  * 发送群里文件
177
- * @param openid GuildID / UserId
162
+ * @param openid
178
163
  * @param data
179
164
  * @returns
180
165
  * 1 图文 2 视频 3 语言 4 文件
181
166
  * 图片:png/jpg,视频:mp4,语音:silk
182
167
  */
183
- async postRichMediaById(openid, data) {
184
- return this.groupService({
185
- url: `/v2/groups/${openid}/files`,
186
- method: 'post',
187
- data: {
188
- srv_send_msg: false,
189
- ...data
190
- }
191
- }).then(res => res?.data);
192
- }
193
- /**
194
- *
195
- * @param openid
196
- * @param data
197
- * @returns
198
- */
199
- async groupsFiles(openid, data) {
168
+ async postRichMediaByGroup(openid, data) {
200
169
  return this.groupService({
201
170
  url: `/v2/groups/${openid}/files`,
202
171
  method: 'post',
@@ -250,7 +219,7 @@ class QQBotAPI {
250
219
  }
251
220
  }
252
221
  if (image) {
253
- const from = await createPicFrom(image);
222
+ const from = await createPicFrom({ image });
254
223
  if (from) {
255
224
  const { picData, name } = from;
256
225
  formdata.append('file_image', picData, name);
@@ -280,7 +249,7 @@ class QQBotAPI {
280
249
  }
281
250
  }
282
251
  if (image) {
283
- const from = await createPicFrom(image);
252
+ const from = await createPicFrom({ image });
284
253
  if (from) {
285
254
  const { picData, name } = from;
286
255
  formdata.append('file_image', picData, name);
@@ -2,7 +2,7 @@ import WebSocket from 'ws';
2
2
  import { QQBotAPI } from './api.js';
3
3
  import { config } from './config.js';
4
4
  import { getIntentsMask } from './intents.js';
5
- import { Counter } from './counter.js';
5
+ import { Counter } from 'alemonjs/utils';
6
6
 
7
7
  /**
8
8
  * 连接
@@ -99,7 +99,7 @@ class QQBotClients extends QQBotAPI {
99
99
  return;
100
100
  // 重新连接的逻辑
101
101
  const reconnect = async () => {
102
- if (this.#counter.get() >= 5) {
102
+ if (this.#counter.value >= 5) {
103
103
  console.info('The maximum number of reconnections has been reached, cancel reconnection');
104
104
  return;
105
105
  }
@@ -108,7 +108,7 @@ class QQBotClients extends QQBotAPI {
108
108
  // 重新starrt
109
109
  start();
110
110
  // 记录
111
- this.#counter.getNextId();
111
+ this.#counter.next();
112
112
  }, 5000);
113
113
  };
114
114
  const start = () => {
package/lib/sends.js CHANGED
@@ -216,7 +216,14 @@ const createMarkdownText = (data) => {
216
216
  });
217
217
  return `${listStr}\n`;
218
218
  }
219
- return;
219
+ else if (mdItem.type === 'MD.code') {
220
+ const language = mdItem?.options?.language || '';
221
+ return `\`\`\`${language}\n${mdItem.value}\n\`\`\`\n`;
222
+ }
223
+ else {
224
+ const value = mdItem['value'] || '';
225
+ return String(value);
226
+ }
220
227
  })
221
228
  .join('');
222
229
  return content;
@@ -275,7 +282,7 @@ const GROUP_AT_MESSAGE_CREATE = async (client, event, val) => {
275
282
  const getFileBase64 = () => readFileSync(item.value, 'base64');
276
283
  const file_data = item.type == 'ImageFile' ? getFileBase64() : item.value;
277
284
  const file_info = await client
278
- .postRichMediaById(event.ChannelId, {
285
+ .postRichMediaByGroup(event.ChannelId, {
279
286
  file_type: 1,
280
287
  file_data: file_data
281
288
  })
@@ -435,7 +442,7 @@ const C2C_MESSAGE_CREATE = async (client, event, val) => {
435
442
  const getFileBase64 = () => readFileSync(item.value, 'base64');
436
443
  const file_data = item.type == 'ImageFile' ? getFileBase64() : item.value;
437
444
  const file_info = await client
438
- .postRichMediaById(event.UserId, {
445
+ .postRichMediaByUser(event.UserId, {
439
446
  file_type: 1,
440
447
  file_data: file_data
441
448
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alemonjs/qq-bot",
3
- "version": "2.1.0-alpha.14",
3
+ "version": "2.1.0-alpha.17",
4
4
  "description": "阿柠檬qqbot平台连接",
5
5
  "author": "lemonade",
6
6
  "license": "MIT",
@@ -1,20 +0,0 @@
1
- import { QQBotGroupClient } from './sdk/client.websoket.group.js';
2
- import { register } from './register.js';
3
- import { getQQBotConfig } from './config.js';
4
-
5
- const start = () => {
6
- const config = getQQBotConfig();
7
- // intents 需要默认值
8
- const client = new QQBotGroupClient({
9
- ...config,
10
- intents: config?.intents ?? ['GROUP_AND_C2C_EVENT'],
11
- is_private: config?.is_private ?? false,
12
- sandbox: config?.sandbox ?? false,
13
- shard: config?.shard ?? [0, 1]
14
- });
15
- // 连接
16
- client.connect(config?.gatewayURL);
17
- register(client);
18
- };
19
-
20
- export { start };
@@ -1,37 +0,0 @@
1
- import { getQQBotConfig } from './config.js';
2
- import { register } from './register.js';
3
- import { QQBotGuildClient } from './sdk/client.websoket.guild.js';
4
-
5
- const start = () => {
6
- const config = getQQBotConfig();
7
- // intents 需要默认值
8
- const client = new QQBotGuildClient({
9
- ...config,
10
- intents: config?.intents ?? config?.is_private
11
- ? [
12
- 'GUILDS', // base
13
- 'GUILD_MEMBERS', // base
14
- 'GUILD_MESSAGES',
15
- 'GUILD_MESSAGE_REACTIONS',
16
- 'DIRECT_MESSAGE',
17
- 'INTERACTION',
18
- 'FORUMS_EVENT'
19
- ]
20
- : [
21
- 'GUILDS', // base
22
- 'GUILD_MEMBERS', // base
23
- 'GUILD_MESSAGE_REACTIONS',
24
- 'DIRECT_MESSAGE',
25
- 'INTERACTION',
26
- 'PUBLIC_GUILD_MESSAGES'
27
- ],
28
- is_private: config?.is_private ?? false,
29
- sandbox: config?.sandbox ?? false,
30
- shard: config?.shard ?? [0, 1]
31
- });
32
- // 连接
33
- client.connect(config?.gatewayURL);
34
- register(client);
35
- };
36
-
37
- export { start };
package/lib/register.d.ts DELETED
@@ -1,3 +0,0 @@
1
- declare const platform = "qq-bot";
2
-
3
- export { platform };
@@ -1,221 +0,0 @@
1
- import WebSocket from 'ws';
2
- import { QQBotAPI } from './api.js';
3
- import { config } from './config.js';
4
- import { getIntentsMask } from './intents.js';
5
- import { Counter } from './counter.js';
6
-
7
- /**
8
- * 连接
9
- */
10
- class QQBotGroupClient extends QQBotAPI {
11
- //
12
- #counter = new Counter(1); // 初始值为1
13
- // 标记是否已连接
14
- #isConnected = false;
15
- // 存储最新的消息序号
16
- #heartbeat_interval = 30000;
17
- // 鉴权
18
- #IntervalId = null;
19
- // url
20
- #gatewayUrl = null;
21
- /**
22
- * 设置配置
23
- * @param opstion
24
- */
25
- constructor(opstion) {
26
- super();
27
- for (const key in opstion) {
28
- config.set(key, opstion[key]);
29
- }
30
- }
31
- /**
32
- * 定时鉴权
33
- * @param cfg
34
- * @returns
35
- */
36
- async #setTimeoutBotConfig() {
37
- const accessToken = async () => {
38
- const app_id = config.get('app_id');
39
- const secret = config.get('secret');
40
- if (!app_id || !secret)
41
- return;
42
- // 发送请求
43
- const data = await this.getAuthentication(app_id, secret).then(res => res.data);
44
- config.set('access_token', data.access_token);
45
- console.info('refresh', data.expires_in, 's');
46
- setTimeout(accessToken, data.expires_in * 1000);
47
- };
48
- await accessToken();
49
- return;
50
- }
51
- /**
52
- * 鉴权数据
53
- * @returns
54
- */
55
- #aut() {
56
- const token = config.get('access_token');
57
- const intents = config.get('intents');
58
- const shard = config.get('shard');
59
- return {
60
- op: 2, // op = 2
61
- d: {
62
- token: `QQBot ${token}`,
63
- intents: getIntentsMask(intents),
64
- shard: shard,
65
- properties: {
66
- $os: process.platform,
67
- $browser: 'alemonjs',
68
- $device: 'alemonjs'
69
- }
70
- }
71
- };
72
- }
73
- #ws = null;
74
- #events = {};
75
- /**
76
- * 注册事件处理程序
77
- * @param key 事件名称
78
- * @param val 事件处理函数
79
- */
80
- on(key, val) {
81
- if (!this.#events[key])
82
- this.#events[key] = [];
83
- this.#events[key].push(val);
84
- return this;
85
- }
86
- /**
87
- *
88
- * @param cfg
89
- * @param conversation
90
- */
91
- async connect(gatewayURL) {
92
- // 定时模式
93
- await this.#setTimeoutBotConfig();
94
- // 请求url
95
- if (!this.#gatewayUrl) {
96
- this.#gatewayUrl = gatewayURL ?? (await this.gateway().then(res => res?.url));
97
- }
98
- if (!this.#gatewayUrl)
99
- return;
100
- // 重新连接的逻辑
101
- const reconnect = async () => {
102
- if (this.#counter.get() >= 5) {
103
- console.info('The maximum number of reconnections has been reached, cancel reconnection');
104
- return;
105
- }
106
- setTimeout(() => {
107
- console.info('[ws] reconnecting...');
108
- // 重新starrt
109
- start();
110
- // 记录
111
- this.#counter.getNextId();
112
- }, 5000);
113
- };
114
- const start = () => {
115
- if (this.#gatewayUrl) {
116
- const map = {
117
- 0: async ({ t, d }) => {
118
- if (this.#events[t]) {
119
- try {
120
- for (const event of this.#events[t]) {
121
- // 是否是函数
122
- if (typeof event != 'function')
123
- continue;
124
- event(d);
125
- }
126
- }
127
- catch (err) {
128
- if (this.#events['ERROR']) {
129
- for (const event of this.#events['ERROR']) {
130
- // 是否是函数
131
- if (typeof event != 'function')
132
- continue;
133
- event(err);
134
- }
135
- }
136
- }
137
- }
138
- // Ready Event,鉴权成功
139
- if (t === 'READY') {
140
- this.#IntervalId = setInterval(() => {
141
- if (this.#isConnected) {
142
- this.#ws &&
143
- this.#ws.send(JSON.stringify({
144
- op: 1, // op = 1
145
- d: null // 如果是第一次连接,传null
146
- }));
147
- }
148
- }, this.#heartbeat_interval);
149
- }
150
- // Resumed Event,恢复连接成功
151
- if (t === 'RESUMED') {
152
- console.info('[ws] restore connection');
153
- // 重制次数
154
- this.#counter.reStart();
155
- }
156
- return;
157
- },
158
- 6: ({ d }) => {
159
- console.info('[ws] connection attempt', d);
160
- return;
161
- },
162
- 7: async ({ d }) => {
163
- // 执行重新连接
164
- console.info('[ws] reconnect', d);
165
- // 取消鉴权发送
166
- if (this.#IntervalId)
167
- clearInterval(this.#IntervalId);
168
- return;
169
- },
170
- 9: ({ d }) => {
171
- console.info('[ws] parameter error', d);
172
- return;
173
- },
174
- 10: ({ d }) => {
175
- // 重制次数
176
- this.#isConnected = true;
177
- // 记录新循环
178
- this.#heartbeat_interval = d.heartbeat_interval;
179
- // 发送鉴权
180
- this.#ws && this.#ws.send(JSON.stringify(this.#aut()));
181
- return;
182
- },
183
- 11: () => {
184
- // OpCode 11 Heartbeat ACK 消息,心跳发送成功
185
- console.info('[ws] heartbeat transmission');
186
- // 重制次数
187
- this.#counter.reStart();
188
- return;
189
- },
190
- 12: ({ d }) => {
191
- console.info('[ws] platform data', d);
192
- return;
193
- }
194
- };
195
- // 连接
196
- this.#ws = new WebSocket(this.#gatewayUrl);
197
- this.#ws.on('open', () => {
198
- console.info('[ws] open');
199
- });
200
- // 监听消息
201
- this.#ws.on('message', async (msg) => {
202
- const message = JSON.parse(msg.toString('utf8'));
203
- if (process.env.NTQQ_WS == 'dev')
204
- console.info('message', message);
205
- // 根据 opcode 进行处理
206
- if (map[message.op]) {
207
- map[message.op](message);
208
- }
209
- });
210
- // 关闭
211
- this.#ws.on('close', async (err) => {
212
- await reconnect();
213
- console.info('[ws] close', err);
214
- });
215
- }
216
- };
217
- start();
218
- }
219
- }
220
-
221
- export { QQBotGroupClient };
@@ -1,205 +0,0 @@
1
- import WebSocket from 'ws';
2
- import { config } from './config.js';
3
- import { getIntentsMask } from './intents.js';
4
- import { QQBotAPI } from './api.js';
5
- import { Counter } from './counter.js';
6
-
7
- /**
8
- * 连接
9
- */
10
- class QQBotGuildClient extends QQBotAPI {
11
- //
12
- #counter = new Counter(1); // 初始值为1
13
- // 标记是否已连接
14
- #isConnected = false;
15
- // 存储最新的消息序号
16
- #heartbeat_interval = 30000;
17
- // 鉴权
18
- #IntervalId = null;
19
- // url
20
- #gatewayUrl = null;
21
- #ws;
22
- /**
23
- *
24
- * @param opstion
25
- */
26
- constructor(opstion) {
27
- super();
28
- for (const key in opstion) {
29
- config.set(key, opstion[key]);
30
- }
31
- }
32
- /**
33
- * 鉴权数据
34
- * @returns
35
- */
36
- #aut() {
37
- const app_id = config.get('app_id');
38
- const token = config.get('token');
39
- const intents = config.get('intents');
40
- const shard = config.get('shard');
41
- return {
42
- op: 2, // op = 2
43
- d: {
44
- token: `Bot ${app_id}.${token}`,
45
- intents: getIntentsMask(intents),
46
- shard,
47
- properties: {
48
- $os: process.platform,
49
- $browser: 'alemonjs',
50
- $device: 'alemonjs'
51
- }
52
- }
53
- };
54
- }
55
- #events = {};
56
- /**
57
- * 注册事件处理程序
58
- * @param key 事件名称
59
- * @param val 事件处理函数
60
- */
61
- on(key, val) {
62
- if (!this.#events[key])
63
- this.#events[key] = [];
64
- this.#events[key].push(val);
65
- return this;
66
- }
67
- /**
68
- *
69
- * @param cfg
70
- */
71
- async connect(gatewayURL) {
72
- //
73
- this.#gatewayUrl =
74
- gatewayURL ??
75
- (await this.gateway()
76
- .then(res => res.url)
77
- .catch(err => {
78
- if (this.#events['ERROR']) {
79
- for (const item of this.#events['ERROR']) {
80
- item(err);
81
- }
82
- }
83
- }));
84
- // 请求url
85
- if (!this.#gatewayUrl)
86
- return this;
87
- // 重新连接的逻辑
88
- const reconnect = async () => {
89
- if (this.#counter.get() >= 5) {
90
- console.info('The maximum number of reconnections has been reached, cancel reconnection');
91
- return;
92
- }
93
- setTimeout(() => {
94
- console.info('[ws] reconnecting...');
95
- // 重新starrt
96
- start();
97
- // 记录
98
- this.#counter.getNextId();
99
- }, 5000);
100
- };
101
- const start = () => {
102
- if (this.#gatewayUrl) {
103
- const map = {
104
- 0: async ({ t, d }) => {
105
- // 执行
106
- if (this.#events[t]) {
107
- try {
108
- for (const event of this.#events[t]) {
109
- // 是否是函数
110
- if (typeof event != 'function')
111
- continue;
112
- event(d);
113
- }
114
- }
115
- catch (err) {
116
- if (this.#events['ERROR']) {
117
- for (const item of this.#events['ERROR']) {
118
- item(err);
119
- }
120
- }
121
- }
122
- }
123
- // Ready Event,鉴权成功
124
- if (t === 'READY') {
125
- this.#IntervalId = setInterval(() => {
126
- if (this.#isConnected) {
127
- this.#ws.send(JSON.stringify({
128
- op: 1, // op = 1
129
- d: null // 如果是第一次连接,传null
130
- }));
131
- }
132
- }, this.#heartbeat_interval);
133
- }
134
- // Resumed Event,恢复连接成功
135
- if (t === 'RESUMED') {
136
- console.info('[ws] restore connection');
137
- // 重制次数
138
- this.#counter.reStart();
139
- }
140
- return;
141
- },
142
- 6: ({ d }) => {
143
- console.info('[ws] connection attempt', d);
144
- return;
145
- },
146
- 7: async ({ d }) => {
147
- // 执行重新连接
148
- console.info('[ws] reconnect', d);
149
- // 取消鉴权发送
150
- if (this.#IntervalId)
151
- clearInterval(this.#IntervalId);
152
- return;
153
- },
154
- 9: ({ d }) => {
155
- console.info('[ws] parameter error', d);
156
- return;
157
- },
158
- 10: ({ d }) => {
159
- // 重制次数
160
- this.#isConnected = true;
161
- // 记录新循环
162
- this.#heartbeat_interval = d.heartbeat_interval;
163
- // 发送鉴权
164
- this.#ws.send(JSON.stringify(this.#aut()));
165
- return;
166
- },
167
- 11: () => {
168
- // OpCode 11 Heartbeat ACK 消息,心跳发送成功
169
- console.info('[ws] heartbeat transmission');
170
- // 重制次数
171
- this.#counter.reStart();
172
- return;
173
- },
174
- 12: ({ d }) => {
175
- console.info('[ws] platform data', d);
176
- return;
177
- }
178
- };
179
- // 连接
180
- this.#ws = new WebSocket(this.#gatewayUrl);
181
- this.#ws.on('open', () => {
182
- console.info('[ws] open');
183
- });
184
- // 监听消息
185
- this.#ws.on('message', async (msg) => {
186
- const message = JSON.parse(msg.toString('utf8'));
187
- if (process.env.QQ_WS == 'dev')
188
- console.info('message', message);
189
- if (map[message.op]) {
190
- map[message.op](message);
191
- }
192
- });
193
- // 关闭
194
- this.#ws.on('close', async (err) => {
195
- await reconnect();
196
- console.info('[ws] close', err);
197
- });
198
- }
199
- };
200
- start();
201
- return this;
202
- }
203
- }
204
-
205
- export { QQBotGuildClient };
@@ -1,19 +0,0 @@
1
- class Counter {
2
- #counter = 1;
3
- #val = 0;
4
- constructor(initialValue) {
5
- this.#counter = initialValue;
6
- this.#val = initialValue;
7
- }
8
- getNextId() {
9
- return ++this.#counter;
10
- }
11
- get() {
12
- return this.#counter;
13
- }
14
- reStart() {
15
- this.#counter = this.#val;
16
- }
17
- }
18
-
19
- export { Counter };
package/lib/sdk/from.js DELETED
@@ -1,44 +0,0 @@
1
- import { existsSync, createReadStream } from 'fs';
2
- import { Readable, isReadable } from 'stream';
3
- import { basename } from 'path';
4
- import { fileTypeFromBuffer, fileTypeFromStream } from 'file-type';
5
-
6
- /**
7
- * 创建form
8
- * @param image
9
- * @param name
10
- * @returns
11
- */
12
- async function createPicFrom(image, name = 'image.jpg') {
13
- let picData;
14
- // 是 string
15
- if (typeof image === 'string') {
16
- if (!existsSync(image))
17
- return false;
18
- if (!name)
19
- name = basename(image);
20
- picData = createReadStream(image);
21
- // 是 buffer
22
- }
23
- else if (Buffer.isBuffer(image)) {
24
- const file = await fileTypeFromBuffer(image);
25
- if (!name)
26
- name = 'file.' + file?.ext;
27
- picData = new Readable();
28
- picData.push(image);
29
- picData.push(null);
30
- // 是 文件流
31
- }
32
- else if (isReadable(image)) {
33
- const file = await fileTypeFromStream(image);
34
- if (!name)
35
- name = 'file.' + file?.ext;
36
- picData = image;
37
- }
38
- else {
39
- return false;
40
- }
41
- return { picData, image, name };
42
- }
43
-
44
- export { createPicFrom };
File without changes