@alemonjs/qq-bot 2.1.0-alpha.0 → 2.1.0-alpha.10

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/sdk/api.js CHANGED
@@ -3,19 +3,12 @@ import { config } from './config.js';
3
3
  import FormData from 'form-data';
4
4
  import { createPicFrom } from './from.js';
5
5
 
6
+ const BOTS_API_RUL = 'https://bots.qq.com';
7
+ const API_URL_SANDBOX = 'https://sandbox.api.sgroup.qq.com';
8
+ const API_URL = 'https://api.sgroup.qq.com';
9
+ const msgMap = new Map();
6
10
  class QQBotAPI {
7
- /**
8
- * qq机器人
9
- */
10
- BOTS_API_RUL = 'https://bots.qq.com';
11
- /**
12
- * qq群 沙河接口
13
- */
14
- API_URL_SANDBOX = 'https://sandbox.api.sgroup.qq.com';
15
- /**
16
- * qq群
17
- */
18
- API_URL = 'https://api.sgroup.qq.com';
11
+ // /\[🔗[^\]]+\]\([^)]+\)|@everyone/.test(content)
19
12
  /**
20
13
  * 得到鉴权
21
14
  * @param app_id
@@ -23,7 +16,7 @@ class QQBotAPI {
23
16
  * @returns
24
17
  */
25
18
  getAuthentication(app_id, clientSecret) {
26
- return axios.post(`${this.BOTS_API_RUL}/app/getAppAccessToken`, {
19
+ return axios.post(`${BOTS_API_RUL}/app/getAppAccessToken`, {
27
20
  appId: app_id,
28
21
  clientSecret: clientSecret
29
22
  });
@@ -33,12 +26,12 @@ class QQBotAPI {
33
26
  * @param config
34
27
  * @returns
35
28
  */
36
- async groupService(options) {
29
+ groupService(options) {
37
30
  const app_id = config.get('app_id');
38
31
  // 群聊是加密token
39
32
  const token = config.get('access_token');
40
- const service = await axios.create({
41
- baseURL: this.API_URL,
33
+ const service = axios.create({
34
+ baseURL: API_URL,
42
35
  timeout: 20000,
43
36
  headers: {
44
37
  'X-Union-Appid': app_id,
@@ -52,12 +45,12 @@ class QQBotAPI {
52
45
  * @param opstion
53
46
  * @returns
54
47
  */
55
- async guildServer(opstion) {
48
+ guildServer(opstion) {
56
49
  const app_id = config.get('app_id');
57
50
  const token = config.get('token');
58
51
  const sandbox = config.get('sandbox');
59
- const service = await axios.create({
60
- baseURL: sandbox ? this.API_URL_SANDBOX : this.API_URL,
52
+ const service = axios.create({
53
+ baseURL: sandbox ? API_URL_SANDBOX : API_URL,
61
54
  timeout: 20000,
62
55
  headers: {
63
56
  Authorization: `Bot ${app_id}.${token}`
@@ -96,29 +89,35 @@ class QQBotAPI {
96
89
  * @returns
97
90
  * 0 文本 1 图文 2 md 3 ark 4 embed
98
91
  */
99
- async usersOpenMessages(openid, data, _msg_id) {
92
+ async usersOpenMessages(openid, data) {
93
+ const db = {
94
+ ...(data.event_id
95
+ ? { event_id: data.event_id }
96
+ : {
97
+ msg_seq: this.getMessageSeq(data.msg_id || '')
98
+ }),
99
+ ...data
100
+ };
100
101
  return this.groupService({
101
102
  url: `/v2/users/${openid}/messages`,
102
103
  method: 'post',
103
- data: data
104
+ data: db
104
105
  }).then(res => res?.data);
105
106
  }
106
- // /\[🔗[^\]]+\]\([^)]+\)|@everyone/.test(content)
107
- #map = new Map();
108
107
  /**
109
108
  * 得到消息序列
110
109
  * @param MessageId
111
110
  * @returns
112
111
  */
113
112
  getMessageSeq(MessageId) {
114
- let seq = this.#map.get(MessageId) || 0;
113
+ let seq = msgMap.get(MessageId) || 0;
115
114
  seq++;
116
- this.#map.set(MessageId, seq);
115
+ msgMap.set(MessageId, seq);
117
116
  // 如果映射表大小超过 100,则删除最早添加的 MessageId
118
- if (this.#map.size > 100) {
119
- const firstKey = this.#map.keys().next().value;
117
+ if (msgMap.size > 100) {
118
+ const firstKey = msgMap.keys().next().value;
120
119
  if (firstKey)
121
- this.#map.delete(firstKey);
120
+ msgMap.delete(firstKey);
122
121
  }
123
122
  return seq;
124
123
  }
@@ -129,10 +128,18 @@ class QQBotAPI {
129
128
  * @returns
130
129
  */
131
130
  async groupOpenMessages(group_openid, data) {
131
+ const db = {
132
+ ...(data.event_id
133
+ ? { event_id: data.event_id }
134
+ : {
135
+ msg_seq: this.getMessageSeq(data.msg_id || '')
136
+ }),
137
+ ...data
138
+ };
132
139
  return this.groupService({
133
140
  url: `/v2/groups/${group_openid}/messages`,
134
141
  method: 'post',
135
- data: data
142
+ data: db
136
143
  }).then(res => res?.data);
137
144
  }
138
145
  /**
@@ -167,13 +174,13 @@ class QQBotAPI {
167
174
  }
168
175
  /**
169
176
  * 发送群里文件
170
- * @param openid
177
+ * @param openid GuildID / UserId
171
178
  * @param data
172
179
  * @returns
173
180
  * 1 图文 2 视频 3 语言 4 文件
174
181
  * 图片:png/jpg,视频:mp4,语音:silk
175
182
  */
176
- async postRichMediaByGroup(openid, data) {
183
+ async postRichMediaById(openid, data) {
177
184
  return this.groupService({
178
185
  url: `/v2/groups/${openid}/files`,
179
186
  method: 'post',
@@ -199,118 +206,13 @@ class QQBotAPI {
199
206
  }
200
207
  }).then(res => res?.data);
201
208
  }
202
- /**
203
- * 创建模板
204
- * *********
205
- * 使用该方法,你需要申请模板Id
206
- * 并设置markdown源码为{{.text_0}}{{.text_1}}
207
- * {{.text_2}}{{.text_3}}{{.text_4}}{{.text_5}}
208
- * {{.text_6}}{{.text_7}}{{.text_8}}{{.text_9}}
209
- * 当前,你也可以传递回调对key和values进行休整
210
- * @param custom_template_id
211
- * @param mac 默认 9
212
- * @param callBack 默认 (key,values)=>({key,values})
213
- * @returns
214
- */
215
- createTemplate(custom_template_id, mac = 10, callBack = (key, values) => ({ key, values })) {
216
- let size = -1;
217
- const params = [];
218
- const Id = custom_template_id;
219
- /**
220
- * 消耗一个参数
221
- * @param value 值
222
- * @param change 是否换行
223
- * @returns
224
- */
225
- const text = (value, change = false) => {
226
- // 仅限push
227
- if (size > mac - 1)
228
- return;
229
- size++;
230
- params.push(callBack(`text_${size}`, [`${value}${change ? '\r' : ''}`]));
231
- };
232
- /**
233
- * 消耗一个参数
234
- * @param start 开始的值
235
- * @param change 是否换行
236
- * @returns
237
- */
238
- const prefix = (start, label) => {
239
- text(`${start}[${label}]`);
240
- };
241
- /**
242
- * 消耗一个参数
243
- * @param param0.value 发送的值
244
- * @param param0.enter 是否自动发送
245
- * @param param0.reply 是否回复
246
- * @param param0.change 是否换行
247
- * @param param0.end 尾部字符串
248
- */
249
- const suffix = ({ value, enter = true, reply = false, change = false, end = '' }) => {
250
- text(`(mqqapi://aio/inlinecmd?command=${value}&enter=${enter}&reply=${reply})${end}${change ? '\r' : ''}`);
251
- };
252
- /**
253
- * 消耗2个参数
254
- * @param param0.label 显示的值
255
- * @param param0.value 发送的值
256
- * @param param0.enter 是否自动发送
257
- * @param param0.reply 是否回复
258
- * @param param0.change 是否换行
259
- * @param param0.start 头部字符串
260
- * @param param0.end 尾部字符串
261
- */
262
- const button = ({ label, value, start = '', end = '', enter = true, reply = false, change = false }) => {
263
- // size 只少留两个
264
- if (size > mac - 1 - 2)
265
- return;
266
- prefix(start, label);
267
- suffix({ value, enter, reply, change, end });
268
- };
269
- /**
270
- * **********
271
- * 代码块
272
- * **********
273
- * 跟在后面
274
- * 前面需要设置换行
275
- * 消耗4个参数
276
- * @param val
277
- * @returns
278
- */
279
- const code = (val) => {
280
- // size 至少留4个
281
- if (size > mac - 1 - 4)
282
- return;
283
- text('``');
284
- text('`javascript\r' + val);
285
- text('\r`');
286
- text('``\r');
287
- };
288
- const getParam = () => {
289
- return {
290
- msg_type: 2,
291
- markdown: {
292
- custom_template_id: Id,
293
- params
294
- }
295
- };
296
- };
297
- return {
298
- size,
299
- text,
300
- prefix,
301
- suffix,
302
- button,
303
- code,
304
- getParam
305
- };
306
- }
307
209
  /**
308
210
  *
309
211
  * @param openid
310
212
  * @param message_id
311
213
  * @returns
312
214
  */
313
- userMessageDelete(openid, message_id) {
215
+ async userMessageDelete(openid, message_id) {
314
216
  return this.groupService({
315
217
  url: `/v2/users/${openid}/messages/${message_id}`,
316
218
  method: 'delete'
@@ -322,47 +224,39 @@ class QQBotAPI {
322
224
  * @param message_id
323
225
  * @returns
324
226
  */
325
- grouMessageDelte(group_openid, message_id) {
227
+ async grouMessageDelte(group_openid, message_id) {
326
228
  return this.groupService({
327
229
  url: `/v2/groups/${group_openid}/messages/${message_id}`,
328
230
  method: 'delete'
329
231
  }).then(res => res?.data);
330
232
  }
331
- /**
332
- * 创建form
333
- * @param image
334
- * @param msg_id
335
- * @param content
336
- * @param name
337
- * @returns
338
- */
339
- async createFrom(image, msg_id, content, Name = 'image.jpg') {
340
- const from = await createPicFrom(image, Name);
341
- if (!from)
342
- return false;
343
- const { picData, name } = from;
344
- const formdata = new FormData();
345
- formdata.append('msg_id', msg_id);
346
- if (typeof content === 'string')
347
- formdata.append('content', content);
348
- formdata.append('file_image', picData, name);
349
- return formdata;
350
- }
351
233
  /**
352
234
  * ************
353
235
  * 消息-图片接口
354
236
  * ***********
355
237
  */
356
238
  /**
357
- * 发送buffer图片
358
- * @param id 私信传频道id,公信传子频道id
359
- * @param message {消息编号,图片,内容}
360
- * @param isGroup 是否是群聊
239
+ *
240
+ * @param channel_id
241
+ * @param message
242
+ * @param image
361
243
  * @returns
362
244
  */
363
- async postImage(channel_id, message) {
364
- const formdata = await this.createFrom(message.image, message.msg_id, message.content, message.name);
365
- const dary = formdata != false ? formdata.getBoundary() : '';
245
+ async channelsMessages(channel_id, message, image) {
246
+ const formdata = new FormData();
247
+ for (const key in message) {
248
+ if (message[key] !== undefined) {
249
+ formdata.append(key, message[key]);
250
+ }
251
+ }
252
+ if (image) {
253
+ const from = await createPicFrom(image);
254
+ if (from) {
255
+ const { picData, name } = from;
256
+ formdata.append('file_image', picData, name);
257
+ }
258
+ }
259
+ const dary = formdata.getBoundary();
366
260
  return this.guildServer({
367
261
  method: 'post',
368
262
  url: `/channels/${channel_id}/messages`,
@@ -373,14 +267,26 @@ class QQBotAPI {
373
267
  }).then(res => res?.data);
374
268
  }
375
269
  /**
376
- * 私聊发送buffer图片
270
+ * 私聊发送
377
271
  * @param id 私信传频道id,公信传子频道id
378
272
  * @param message {消息编号,图片,内容}
379
273
  * @returns
380
274
  */
381
- async postDirectImage(guild_id, message) {
382
- const formdata = await this.createFrom(message.image, message.msg_id, message.content, message.name);
383
- const dary = formdata != false ? formdata.getBoundary() : '';
275
+ async dmsMessages(guild_id, message, image) {
276
+ const formdata = new FormData();
277
+ for (const key in message) {
278
+ if (message[key] !== undefined) {
279
+ formdata.append(key, message[key]);
280
+ }
281
+ }
282
+ if (image) {
283
+ const from = await createPicFrom(image);
284
+ if (from) {
285
+ const { picData, name } = from;
286
+ formdata.append('file_image', picData, name);
287
+ }
288
+ }
289
+ const dary = formdata.getBoundary();
384
290
  return this.guildServer({
385
291
  method: 'post',
386
292
  url: `/dms/${guild_id}/messages`,
@@ -570,26 +476,12 @@ class QQBotAPI {
570
476
  * @param message_id
571
477
  * @returns
572
478
  */
573
- async channelsMessages(channel_id, message_id) {
479
+ async channelsMessagesById(channel_id, message_id) {
574
480
  return this.guildServer({
575
481
  method: 'GET',
576
482
  url: `/channels/${channel_id}/messages/${message_id}`
577
483
  }).then(res => res?.data);
578
484
  }
579
- /**
580
- * 发送消息
581
- * @param channel_id
582
- * @param message_id
583
- * @param data
584
- * @returns
585
- */
586
- async channelsMessagesPost(channel_id, data) {
587
- return this.guildServer({
588
- method: 'POST',
589
- url: `/channels/${channel_id}/messages`,
590
- data
591
- }).then(res => res?.data);
592
- }
593
485
  /**
594
486
  * 撤回消息
595
487
  * @param channel_id
@@ -770,18 +662,6 @@ class QQBotAPI {
770
662
  url: `/users/@me/dms`
771
663
  }).then(res => res?.data);
772
664
  }
773
- /**
774
- * 发送私信
775
- * @param guild_id
776
- * @returns
777
- */
778
- async dmsMessage(guild_id, data) {
779
- return this.guildServer({
780
- method: 'POST',
781
- url: `/dms/${guild_id}/messages`,
782
- data
783
- }).then(res => res?.data);
784
- }
785
665
  /**
786
666
  * 撤回私信
787
667
  * @param guild_id
@@ -1177,6 +1057,32 @@ class QQBotAPI {
1177
1057
  url: `/guilds/${guild_id}/api_permission`
1178
1058
  }).then(res => res?.data);
1179
1059
  }
1060
+ /**
1061
+ * 交互事件回应
1062
+ * @param interaction_id
1063
+ * @param code
1064
+ * @returns
1065
+ */
1066
+ async interactionResponse(mode, interaction_id, code) {
1067
+ if (mode === 'group') {
1068
+ return this.groupService({
1069
+ method: 'PUT',
1070
+ url: `/interactions/${interaction_id}`,
1071
+ data: {
1072
+ code: code || 0
1073
+ }
1074
+ }).then(res => res?.data);
1075
+ }
1076
+ else {
1077
+ return this.guildServer({
1078
+ method: 'PUT',
1079
+ url: `/interactions/${interaction_id}`,
1080
+ data: {
1081
+ code: code || 0
1082
+ }
1083
+ }).then(res => res?.data);
1084
+ }
1085
+ }
1180
1086
  }
1181
1087
 
1182
- export { QQBotAPI };
1088
+ export { API_URL, API_URL_SANDBOX, BOTS_API_RUL, QQBotAPI };
@@ -1,63 +1,61 @@
1
- type MessageType = 0 | 1 | 2 | 3 | 4 | 7
2
- type FileType = 1 | 2 | 3 | 4
1
+ type MessageType = 0 | 1 | 2 | 3 | 4 | 7;
2
+ type FileType = 1 | 2 | 3 | 4;
3
3
  interface ButtonType {
4
- id: string
5
- render_data: {
6
- label: string
7
- visited_label: string
8
- style?: number
9
- }
10
- action: {
11
- type: number
12
- permission: {
13
- type: number
14
- }
15
- reply?: boolean
16
- enter?: boolean
17
- unsupport_tips?: string
18
- data:
19
- | string
20
- | {
21
- click: string
22
- confirm: string
23
- cancel: string
24
- }
25
- at_bot_show_channel_list?: boolean
26
- }
4
+ id: string;
5
+ render_data: {
6
+ label: string;
7
+ visited_label: string;
8
+ style?: number;
9
+ };
10
+ action: {
11
+ type: number;
12
+ permission: {
13
+ type: number;
14
+ };
15
+ reply?: boolean;
16
+ enter?: boolean;
17
+ unsupport_tips?: string;
18
+ data: string | {
19
+ click: string;
20
+ confirm: string;
21
+ cancel: string;
22
+ };
23
+ at_bot_show_channel_list?: boolean;
24
+ };
27
25
  }
28
26
  interface KeyboardType {
29
- id?: string
30
- content?: {
31
- rows: {
32
- buttons: ButtonType[]
33
- }[]
34
- }
27
+ id?: string;
28
+ content?: {
29
+ rows: {
30
+ buttons: ButtonType[];
31
+ }[];
32
+ };
35
33
  }
36
34
  interface MarkdownType {
37
- /** markdown 模版id,申请模版后获得 */
38
- custom_template_id: string
39
- /** 原生 markdown 文本内容(内邀使用) */
40
- content?: string
41
- /** 模版内变量与填充值的kv映射 */
42
- params?: Array<{
43
- key: string
44
- values: string[]
45
- }>
35
+ /** markdown 模版id,申请模版后获得 */
36
+ custom_template_id?: string;
37
+ /** 原生 markdown 文本内容(内邀使用) */
38
+ content?: string;
39
+ /** 模版内变量与填充值的kv映射 */
40
+ params?: Array<{
41
+ key: string;
42
+ values: string[];
43
+ }>;
46
44
  }
47
45
  interface ApiRequestData {
48
- content?: string
49
- msg_type: MessageType
50
- markdown?: MarkdownType
51
- keyboard?: KeyboardType
52
- media?: {
53
- file_info: string
54
- }
55
- ark?: any
56
- image?: any
57
- message_reference?: any
58
- event_id?: any
59
- msg_id?: string
60
- msg_seq?: number
46
+ content?: string;
47
+ msg_type: MessageType;
48
+ markdown?: MarkdownType;
49
+ keyboard?: KeyboardType;
50
+ media?: {
51
+ file_info: string;
52
+ };
53
+ ark?: any;
54
+ image?: any;
55
+ message_reference?: any;
56
+ event_id?: any;
57
+ msg_id?: string;
58
+ msg_seq?: number;
61
59
  }
62
60
 
63
- export type { ApiRequestData, ButtonType, FileType, KeyboardType, MarkdownType, MessageType }
61
+ export type { ApiRequestData, ButtonType, FileType, KeyboardType, MarkdownType, MessageType };