node-karin 0.0.3

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 (107) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +57 -0
  3. package/config/defSet/App.yaml +37 -0
  4. package/config/defSet/config.yaml +43 -0
  5. package/config/defSet/group.yaml +18 -0
  6. package/config/defSet/pm2.yaml +21 -0
  7. package/config/defSet/redis.yaml +18 -0
  8. package/config/defSet/server.yaml +42 -0
  9. package/config/view/App.yaml +74 -0
  10. package/config/view/config.yaml +100 -0
  11. package/config/view/group.yaml +62 -0
  12. package/config/view/pm2.yaml +41 -0
  13. package/config/view/redis.yaml +25 -0
  14. package/config/view/server.yaml +93 -0
  15. package/lib/adapter/onebot/onebot11.d.ts +430 -0
  16. package/lib/adapter/onebot/onebot11.js +1302 -0
  17. package/lib/core/init.d.ts +0 -0
  18. package/lib/core/init.js +4 -0
  19. package/lib/core/karin.d.ts +72 -0
  20. package/lib/core/karin.js +51 -0
  21. package/lib/core/listener.d.ts +121 -0
  22. package/lib/core/listener.js +188 -0
  23. package/lib/core/plugin.app.d.ts +15 -0
  24. package/lib/core/plugin.app.js +18 -0
  25. package/lib/core/plugin.d.ts +182 -0
  26. package/lib/core/plugin.js +138 -0
  27. package/lib/core/plugin.loader.d.ts +149 -0
  28. package/lib/core/plugin.loader.js +462 -0
  29. package/lib/core/server.d.ts +26 -0
  30. package/lib/core/server.js +213 -0
  31. package/lib/db/level.d.ts +20 -0
  32. package/lib/db/level.js +38 -0
  33. package/lib/db/redis.d.ts +41 -0
  34. package/lib/db/redis.js +137 -0
  35. package/lib/db/redis_level.d.ts +113 -0
  36. package/lib/db/redis_level.js +290 -0
  37. package/lib/event/event.d.ts +138 -0
  38. package/lib/event/event.handler.d.ts +29 -0
  39. package/lib/event/event.handler.js +142 -0
  40. package/lib/event/event.js +120 -0
  41. package/lib/event/message.d.ts +102 -0
  42. package/lib/event/message.handler.d.ts +25 -0
  43. package/lib/event/message.handler.js +240 -0
  44. package/lib/event/message.js +70 -0
  45. package/lib/event/notice.d.ts +49 -0
  46. package/lib/event/notice.js +15 -0
  47. package/lib/event/request.d.ts +49 -0
  48. package/lib/event/request.js +15 -0
  49. package/lib/event/review.handler.d.ts +54 -0
  50. package/lib/event/review.handler.js +382 -0
  51. package/lib/index.d.ts +23 -0
  52. package/lib/index.js +40 -0
  53. package/lib/renderer/app.d.ts +53 -0
  54. package/lib/renderer/app.js +93 -0
  55. package/lib/renderer/base.d.ts +30 -0
  56. package/lib/renderer/base.js +71 -0
  57. package/lib/renderer/client.d.ts +30 -0
  58. package/lib/renderer/client.js +159 -0
  59. package/lib/renderer/http.d.ts +19 -0
  60. package/lib/renderer/http.js +51 -0
  61. package/lib/renderer/server.d.ts +42 -0
  62. package/lib/renderer/server.js +112 -0
  63. package/lib/renderer/wormhole.d.ts +1 -0
  64. package/lib/renderer/wormhole.js +154 -0
  65. package/lib/types/adapter.d.ts +575 -0
  66. package/lib/types/adapter.js +1 -0
  67. package/lib/types/config.d.ts +327 -0
  68. package/lib/types/config.js +1 -0
  69. package/lib/types/element.d.ts +576 -0
  70. package/lib/types/element.js +1 -0
  71. package/lib/types/index.d.ts +8 -0
  72. package/lib/types/index.js +8 -0
  73. package/lib/types/logger.d.ts +109 -0
  74. package/lib/types/logger.js +1 -0
  75. package/lib/types/onebots11.d.ts +1371 -0
  76. package/lib/types/onebots11.js +1 -0
  77. package/lib/types/plugin.d.ts +282 -0
  78. package/lib/types/plugin.js +1 -0
  79. package/lib/types/render.d.ts +111 -0
  80. package/lib/types/render.js +1 -0
  81. package/lib/types/reply.d.ts +40 -0
  82. package/lib/types/reply.js +1 -0
  83. package/lib/types/types.d.ts +898 -0
  84. package/lib/types/types.js +1 -0
  85. package/lib/utils/YamlEditor.d.ts +62 -0
  86. package/lib/utils/YamlEditor.js +208 -0
  87. package/lib/utils/button.d.ts +49 -0
  88. package/lib/utils/button.js +79 -0
  89. package/lib/utils/common.d.ts +123 -0
  90. package/lib/utils/common.js +413 -0
  91. package/lib/utils/config.d.ts +72 -0
  92. package/lib/utils/config.js +254 -0
  93. package/lib/utils/exec.d.ts +22 -0
  94. package/lib/utils/exec.js +36 -0
  95. package/lib/utils/ffmpeg.d.ts +12 -0
  96. package/lib/utils/ffmpeg.js +25 -0
  97. package/lib/utils/handler.d.ts +76 -0
  98. package/lib/utils/handler.js +102 -0
  99. package/lib/utils/logger.d.ts +3 -0
  100. package/lib/utils/logger.js +104 -0
  101. package/lib/utils/segment.d.ts +276 -0
  102. package/lib/utils/segment.js +448 -0
  103. package/lib/utils/update.d.ts +69 -0
  104. package/lib/utils/update.js +151 -0
  105. package/lib/utils/updateVersion.d.ts +33 -0
  106. package/lib/utils/updateVersion.js +145 -0
  107. package/package.json +92 -0
@@ -0,0 +1,1302 @@
1
+ import { KarinMessage } from '../../event/message.js'
2
+ import { KarinNotice } from '../../event/notice.js'
3
+ import { KarinRequest } from '../../event/request.js'
4
+ import WebSocket from 'ws'
5
+ import { randomUUID } from 'crypto'
6
+ import logger from '../../utils/logger.js'
7
+ import common from '../../utils/common.js'
8
+ import listener from '../../core/listener.js'
9
+ import config from '../../utils/config.js'
10
+ import segment from '../../utils/segment.js'
11
+ /**
12
+ * @class OneBot11
13
+ * @extends KarinAdapter
14
+ */
15
+ export class OneBot11 {
16
+ /**
17
+ * 是否初始化
18
+ */
19
+ #init = false
20
+ /**
21
+ * 机器人QQ号
22
+ */
23
+ self_id
24
+ /**
25
+ * - 重连次数 仅正向ws使用
26
+ */
27
+ index
28
+ socket
29
+ account
30
+ adapter
31
+ version
32
+ constructor () {
33
+ this.self_id = ''
34
+ this.index = 0
35
+ this.account = { uid: '', uin: '', name: '' }
36
+ this.adapter = { id: 'QQ', name: 'OneBot11', type: 'ws', sub_type: 'internal', start_time: Date.now(), connect: '' }
37
+ this.version = { name: '', app_name: '', version: '' }
38
+ }
39
+
40
+ /**
41
+ * 反向ws初始化
42
+ */
43
+ async server (socket, request) {
44
+ this.socket = socket
45
+ const self_id = String(request.headers['x-self-id'])
46
+ const connect = 'ws://' + request.headers.host + request.url
47
+ this.account.uin = self_id
48
+ this.account.uid = self_id
49
+ this.adapter.connect = connect
50
+ this.adapter.sub_type = 'server'
51
+ this.logger('info', `[反向WS][onebot11-${request.headers.upgrade}][${self_id}] ` + logger.green(connect))
52
+ await this.#initListener(connect)
53
+ }
54
+
55
+ /**
56
+ * 正向ws初始化
57
+ * @param connect - WebSocket连接地址
58
+ */
59
+ async client (connect) {
60
+ /** 创建连接 */
61
+ this.socket = new WebSocket(connect)
62
+ this.socket.on('open', async () => {
63
+ this.adapter.sub_type = 'client'
64
+ this.adapter.connect = connect
65
+ logger.info('[正向WS][连接成功][onebot11] ' + logger.green(connect))
66
+ this.index = 0
67
+ this.#initListener(connect)
68
+ })
69
+ /** 监听断开 */
70
+ this.socket.on('close', async () => {
71
+ this.index++
72
+ logger.warn(`[正向WS][重连次数:${this.index}] 连接断开,将在5秒后重连:${connect}`)
73
+ /** 停止全部监听 */
74
+ this.socket.removeAllListeners()
75
+ await common.sleep(5000)
76
+ this.client(connect)
77
+ })
78
+ }
79
+
80
+ /**
81
+ * 初始化监听事件
82
+ * @param connect - WebSocket连接地址
83
+ */
84
+ async #initListener (connect) {
85
+ /** 监听事件 */
86
+ this.socket.on('message', data => {
87
+ this.logger('debug', `[收到事件]:${data}`)
88
+ const event = data.toString().trim() || '{"post_type":"error","error":"空事件"}'
89
+ const json = JSON.parse(event)
90
+ if (json.echo) {
91
+ return this.socket.emit(json.echo, json)
92
+ } else {
93
+ /** 未初始化 */
94
+ this.#init && this.#event(json)
95
+ }
96
+ })
97
+ /** 监听错误 */
98
+ this.socket.on('error', error => {
99
+ this.logger('debug', '[正向WS] 发生错误', error)
100
+ })
101
+ /** 监听断开 */
102
+ this.socket.once('close', async () => {
103
+ const type = this.adapter.sub_type === 'server' ? '反向WS' : '正向WS'
104
+ this.logger('warn', `[${type}] 连接断开:${connect}`)
105
+ /** 停止全部监听 */
106
+ this.socket.removeAllListeners()
107
+ /** 正向ws需要重连 */
108
+ if (this.adapter.sub_type === 'client') {
109
+ this.index++
110
+ this.logger('warn', `[正向WS][重连次数:${this.index}] 连接断开,将在5秒后重连:${connect}`)
111
+ await common.sleep(5000)
112
+ this.client(connect)
113
+ }
114
+ })
115
+ await this.getSelf()
116
+ this.#init = true
117
+ }
118
+
119
+ /**
120
+ * 获取当前登录号信息
121
+ */
122
+ async getSelf () {
123
+ const data = await this.GetCurrentAccount()
124
+ try {
125
+ const { app_name, app_version: version } = await this.GetVersion()
126
+ this.version.name = app_name
127
+ this.version.app_name = app_name
128
+ this.version.version = version
129
+ } catch (e) {
130
+ /** 兼容onebots */
131
+ const { app_name, app_version: version } = await this.SendApi('get_version')
132
+ this.version.name = app_name
133
+ this.version.app_name = app_name
134
+ this.version.version = version
135
+ }
136
+ this.account.uid = data.account_uid
137
+ this.account.uin = data.account_uin
138
+ this.account.name = data.account_name
139
+ this.logger('info', `[加载完成][app_name:${this.version.name}][version:${this.version.version}] ` + logger.green(this.adapter.connect))
140
+ /** 注册bot */
141
+ listener.emit('bot', { type: 'websocket', bot: this })
142
+ }
143
+
144
+ /** 是否初始化 */
145
+ get isInit () {
146
+ return new Promise(resolve => {
147
+ const timer = setInterval(() => {
148
+ if (this.account.name) {
149
+ const { name, version } = this.version
150
+ this.logger('info', `建立连接成功:[${name}(${version})] ${this.adapter.connect}`)
151
+ clearInterval(timer)
152
+ resolve(true)
153
+ }
154
+ }, 100)
155
+ })
156
+ }
157
+
158
+ /** 处理事件 */
159
+ #event (data) {
160
+ switch (data.post_type) {
161
+ case 'meta_event': {
162
+ switch (data.meta_event_type) {
163
+ case 'heartbeat':
164
+ this.logger('trace', `[心跳]:${JSON.stringify(data.status)}`)
165
+ break
166
+ case 'lifecycle': {
167
+ const typeMap = {
168
+ enable: 'OneBot启用',
169
+ disable: 'OneBot停用',
170
+ connect: 'WebSocket连接成功',
171
+ }
172
+ const sub_type = data.sub_type
173
+ this.logger('debug', `[生命周期]:${typeMap[sub_type]}`)
174
+ break
175
+ }
176
+ }
177
+ listener.emit('meta_event', data)
178
+ return
179
+ }
180
+ case 'message':
181
+ case 'message_sent': {
182
+ const message = {
183
+ event: (data.post_type + ''),
184
+ self_id: data.self_id + '',
185
+ user_id: data.sender.user_id + '',
186
+ time: data.time,
187
+ message_id: data.message_id + '',
188
+ message_seq: data.message_id + '',
189
+ sender: {
190
+ ...data.sender,
191
+ uid: data.sender.user_id + '',
192
+ uin: data.sender.user_id + '',
193
+ nick: data.sender.nickname || '',
194
+ role: ('role' in data.sender ? data.sender.role || '' : ''),
195
+ },
196
+ elements: this.AdapterConvertKarin(data.message),
197
+ contact: {
198
+ scene: (data.message_type === 'private' ? 'private' : 'group'),
199
+ peer: data.message_type === 'private' ? data.sender.user_id : data.group_id,
200
+ sub_peer: '',
201
+ },
202
+ group_id: 'group_id' in data ? data.group_id : '',
203
+ raw_message: '',
204
+ }
205
+ const e = new KarinMessage(message)
206
+ e.bot = this
207
+ /**
208
+ * 快速回复 开发者不应该使用这个方法,应该使用由karin封装过后的reply方法
209
+ */
210
+ e.replyCallback = async (elements) => {
211
+ if (data.message_type === 'private') {
212
+ return this.send_private_msg(data.user_id, elements)
213
+ } else {
214
+ return this.send_group_msg(data.group_id, elements)
215
+ }
216
+ }
217
+ listener.emit('message', e)
218
+ return
219
+ }
220
+ case 'notice':
221
+ this.#notice_event(data)
222
+ break
223
+ case 'request':
224
+ this.#request_event(data)
225
+ break
226
+ default:
227
+ this.logger('info', `未知事件:${JSON.stringify(data)}`)
228
+ }
229
+ }
230
+
231
+ /**
232
+ * 通知事件
233
+ */
234
+ #notice_event (data) {
235
+ const time = data.time
236
+ const self_id = data.self_id + ''
237
+ let notice = {}
238
+ const user_id = data.user_id + ''
239
+ const event_id = `notice.${time}`
240
+ const sender = {
241
+ uid: data.user_id + '',
242
+ uin: data.user_id + '',
243
+ nick: '',
244
+ role: '',
245
+ }
246
+ const contact = {
247
+ scene: ('group_id' in data ? 'group' : 'private'),
248
+ peer: 'group_id' in data ? data.group_id : data.user_id,
249
+ sub_peer: '',
250
+ }
251
+ switch (data.notice_type) {
252
+ // 群文件上传
253
+ case 'group_upload': {
254
+ const content = {
255
+ group_id: data.group_id + '',
256
+ operator_uid: data.user_id + '',
257
+ operator_uin: data.user_id + '',
258
+ file_id: data.file.id,
259
+ file_sub_id: '',
260
+ file_name: data.file.name,
261
+ file_size: data.file.size,
262
+ bus_id: 0,
263
+ expire_time: 0,
264
+ url: '',
265
+ }
266
+ const options = {
267
+ time,
268
+ self_id,
269
+ user_id,
270
+ event_id,
271
+ content,
272
+ sender,
273
+ contact,
274
+ sub_event: 'group_file_uploaded',
275
+ }
276
+ notice = new KarinNotice(options)
277
+ break
278
+ }
279
+ // 群管理员变动
280
+ case 'group_admin': {
281
+ const content = {
282
+ group_id: data.group_id + '',
283
+ target_uid: data.user_id + '',
284
+ target_uin: data.user_id + '',
285
+ is_admin: data.sub_type === 'set',
286
+ }
287
+ const options = {
288
+ time,
289
+ self_id,
290
+ user_id,
291
+ event_id,
292
+ sender,
293
+ contact,
294
+ content,
295
+ sub_event: 'group_admin_changed',
296
+ }
297
+ notice = new KarinNotice(options)
298
+ break
299
+ }
300
+ // 群成员减少
301
+ case 'group_decrease': {
302
+ const content = {
303
+ group_id: data.group_id + '',
304
+ operator_uid: data.operator_id || '',
305
+ operator_uin: data.operator_id || '',
306
+ target_uid: data.user_id || '',
307
+ target_uin: data.user_id || '',
308
+ type: data.sub_type,
309
+ }
310
+ const options = {
311
+ time,
312
+ self_id,
313
+ user_id,
314
+ event_id,
315
+ sender,
316
+ contact,
317
+ content,
318
+ sub_event: 'group_member_decrease',
319
+ }
320
+ notice = new KarinNotice(options)
321
+ break
322
+ }
323
+ // 群成员增加
324
+ case 'group_increase': {
325
+ const content = {
326
+ group_id: data.group_id + '',
327
+ operator_uid: (data.operator_id || '') + '',
328
+ operator_uin: (data.operator_id || '') + '',
329
+ target_uid: (data.user_id || '') + '',
330
+ target_uin: (data.user_id || '') + '',
331
+ type: data.sub_type,
332
+ }
333
+ const options = {
334
+ time,
335
+ self_id,
336
+ user_id,
337
+ event_id,
338
+ sender,
339
+ contact,
340
+ content,
341
+ sub_event: 'group_member_increase',
342
+ }
343
+ notice = new KarinNotice(options)
344
+ break
345
+ }
346
+ // 群禁言事件
347
+ case 'group_ban': {
348
+ const content = {
349
+ group_id: data.group_id,
350
+ operator_uid: data.operator_id || '',
351
+ operator_uin: data.operator_id || '',
352
+ target_uid: data.user_id || '',
353
+ target_uin: data.user_id || '',
354
+ duration: data.duration,
355
+ type: data.sub_type,
356
+ }
357
+ const options = {
358
+ time,
359
+ self_id,
360
+ user_id,
361
+ event_id,
362
+ sender,
363
+ contact,
364
+ content,
365
+ sub_event: 'group_member_ban',
366
+ }
367
+ notice = new KarinNotice(options)
368
+ break
369
+ }
370
+ case 'friend_add':
371
+ // todo kritor没有这个事件
372
+ this.logger('info', `[好友添加]:${JSON.stringify(data)}`)
373
+ break
374
+ case 'group_recall': {
375
+ const content = {
376
+ group_id: data.group_id,
377
+ operator_uid: data.operator_id || '',
378
+ operator_uin: data.operator_id || '',
379
+ target_uid: data.user_id || '',
380
+ target_uin: data.user_id || '',
381
+ message_id: data.message_id,
382
+ tip_text: '撤回了一条消息',
383
+ }
384
+ const options = {
385
+ time,
386
+ self_id,
387
+ user_id,
388
+ event_id,
389
+ sender,
390
+ contact,
391
+ content,
392
+ sub_event: 'group_recall',
393
+ }
394
+ notice = new KarinNotice(options)
395
+ break
396
+ }
397
+ case 'friend_recall': {
398
+ const content = {
399
+ operator_uid: data.user_id || '',
400
+ operator_uin: data.user_id || '',
401
+ message_id: data.message_id,
402
+ tip_text: '撤回了一条消息',
403
+ }
404
+ const options = {
405
+ time,
406
+ self_id,
407
+ user_id,
408
+ event_id,
409
+ sender,
410
+ contact,
411
+ content,
412
+ sub_event: 'group_recall',
413
+ }
414
+ notice = new KarinNotice(options)
415
+ break
416
+ }
417
+ case 'notify':
418
+ switch (data.sub_type) {
419
+ case 'poke': {
420
+ const content = {
421
+ group_id: data.group_id + '',
422
+ operator_uid: data.user_id + '',
423
+ operator_uin: data.user_id + '',
424
+ target_uid: data.target_id + '',
425
+ target_uin: data.target_id + '',
426
+ action: '戳了戳',
427
+ suffix: '',
428
+ action_image: '',
429
+ }
430
+ const options = {
431
+ time,
432
+ self_id,
433
+ user_id,
434
+ event_id,
435
+ sender,
436
+ contact,
437
+ content,
438
+ sub_event: 'group_poke',
439
+ }
440
+ notice = new KarinNotice(options)
441
+ break
442
+ }
443
+ case 'lucky_king':
444
+ // todo kritor没有这个事件
445
+ this.logger('info', `[运气王]:${JSON.stringify(data)}`)
446
+ break
447
+ case 'honor':
448
+ // todo kritor没有这个事件
449
+ this.logger('info', `[群荣誉变更]:${JSON.stringify(data)}`)
450
+ break
451
+ }
452
+ break
453
+ case 'group_msg_emoji_like': {
454
+ const content = {
455
+ group_id: data.group_id + '',
456
+ message_id: data.message_id,
457
+ face_id: data.likes[0].emoji_id,
458
+ is_set: true,
459
+ }
460
+ const options = {
461
+ time,
462
+ self_id,
463
+ user_id,
464
+ event_id,
465
+ sender,
466
+ contact,
467
+ content,
468
+ sub_event: 'group_message_reaction',
469
+ }
470
+ notice = new KarinNotice(options)
471
+ break
472
+ }
473
+ default: {
474
+ return this.logger('error', '未知通知事件:', JSON.stringify(data))
475
+ }
476
+ }
477
+ listener.emit('notice', notice)
478
+ }
479
+
480
+ /** 请求事件 */
481
+ #request_event (data) {
482
+ switch (data.request_type) {
483
+ case 'friend': {
484
+ const request = new KarinRequest({
485
+ event_id: `request.${data.time}`,
486
+ self_id: data.self_id + '',
487
+ user_id: data.user_id + '',
488
+ time: data.time,
489
+ contact: {
490
+ scene: 'private',
491
+ peer: data.user_id + '',
492
+ sub_peer: '',
493
+ },
494
+ sender: {
495
+ uid: data.user_id + '',
496
+ uin: data.user_id + '',
497
+ nick: '',
498
+ role: '',
499
+ },
500
+ sub_event: 'friend_apply',
501
+ content: {
502
+ applier_uid: data.user_id + '',
503
+ applier_uin: data.user_id + '',
504
+ message: data.comment,
505
+ },
506
+ })
507
+ listener.emit('request', request)
508
+ return
509
+ }
510
+ case 'group': {
511
+ const request = new KarinRequest({
512
+ event_id: `request.${data.time}`,
513
+ self_id: data.self_id + '',
514
+ user_id: data.user_id + '',
515
+ time: data.time,
516
+ contact: {
517
+ scene: 'group',
518
+ peer: data.group_id + '',
519
+ sub_peer: '',
520
+ },
521
+ sender: {
522
+ uid: data.user_id + '',
523
+ uin: data.user_id + '',
524
+ nick: '',
525
+ role: '',
526
+ },
527
+ sub_event: data.sub_type === 'add' ? 'group_apply' : 'invited_group',
528
+ content: {
529
+ group_id: data.group_id + '',
530
+ applier_uid: data.user_id + '',
531
+ applier_uin: data.user_id + '',
532
+ inviter_uid: data.user_id + '',
533
+ inviter_uin: data.user_id + '',
534
+ message: data.comment,
535
+ },
536
+ })
537
+ listener.emit('request', request)
538
+ return
539
+ }
540
+ default: {
541
+ this.logger('info', `未知请求事件:${JSON.stringify(data)}`)
542
+ }
543
+ }
544
+ }
545
+
546
+ /**
547
+ * onebot11转karin
548
+ * @param {Array<{type: string, data: any}>} data onebot11格式消息
549
+ * @return karin格式消息
550
+ * */
551
+ AdapterConvertKarin (data) {
552
+ const elements = []
553
+ for (const i of data) {
554
+ switch (i.type) {
555
+ case 'text':
556
+ elements.push(segment.text(i.data.text))
557
+ break
558
+ case 'face':
559
+ elements.push(segment.face(Number(i.data.id)))
560
+ break
561
+ case 'image':
562
+ elements.push(segment.image(i.data.url || i.data.file, { file_type: i.data.type }))
563
+ break
564
+ case 'record':
565
+ elements.push(segment.voice(i.data.url || i.data.file, i.data.magic === 1))
566
+ break
567
+ case 'video':
568
+ elements.push(segment.video(i.data.url || i.data.file))
569
+ break
570
+ case 'at':
571
+ elements.push(segment.at(i.data.qq, i.data.qq))
572
+ break
573
+ case 'poke':
574
+ elements.push(segment.poke(Number(i.data.id), Number(i.data.type)))
575
+ break
576
+ case 'contact':
577
+ elements.push(segment.contact(i.data.type === 'qq' ? 'friend' : 'group', i.data.id))
578
+ break
579
+ case 'location':
580
+ elements.push(segment.location(Number(i.data.lat), Number(i.data.lon), i.data.title || '', i.data.content || ''))
581
+ break
582
+ case 'reply':
583
+ elements.push(segment.reply(i.data.id))
584
+ break
585
+ case 'forward':
586
+ elements.push(segment.forward(i.data.id))
587
+ break
588
+ case 'json':
589
+ elements.push(segment.json(i.data.data))
590
+ break
591
+ case 'xml':
592
+ elements.push(segment.xml(i.data.data))
593
+ break
594
+ default: {
595
+ elements.push(segment.text(JSON.stringify(i)))
596
+ }
597
+ }
598
+ }
599
+ return elements
600
+ }
601
+
602
+ /**
603
+ * karin转onebot11
604
+ * @param data karin格式消息
605
+ * @return {Array<{type: string, data: any}>} onebot11格式消息
606
+ * */
607
+ KarinConvertAdapter (data) {
608
+ const elements = []
609
+ // const selfUin = this.account.uin
610
+ // const selfNick = this.account.name
611
+ for (const i of data) {
612
+ switch (i.type) {
613
+ case 'text':
614
+ elements.push({ type: 'text', data: { text: i.text } })
615
+ break
616
+ case 'face':
617
+ elements.push({ type: 'face', data: { id: i.id } })
618
+ break
619
+ case 'at':
620
+ elements.push({ type: 'at', data: { qq: String(i.uid || i.uin) } })
621
+ break
622
+ case 'reply':
623
+ elements.push({ type: 'reply', data: { id: i.message_id } })
624
+ break
625
+ case 'image':
626
+ case 'video':
627
+ case 'file': {
628
+ elements.push({ type: i.type, data: { file: i.file } })
629
+ break
630
+ }
631
+ case 'xml':
632
+ case 'json': {
633
+ elements.push({ type: i.type, data: { data: i.data } })
634
+ break
635
+ }
636
+ // case 'node': {
637
+ // let { type, user_id = selfUin, nickname = selfNick, content } = i
638
+ // content = this.KarinConvertAdapter(content)
639
+ // elements.push({ type, data: { uin: user_id, name: nickname, content } })
640
+ // break
641
+ // }
642
+ case 'forward': {
643
+ elements.push({ type: 'forward', data: { id: i.res_id } })
644
+ break
645
+ }
646
+ case 'voice': {
647
+ elements.push({ type: 'record', data: { file: i.file, magic: i.magic || false } })
648
+ break
649
+ }
650
+ case 'music': {
651
+ // if (i.platform) {
652
+ // elements.push({ type: 'music', data: { type: i.platform, id: i.id } })
653
+ // } else {
654
+ // const { url, audio, title, content, image } = i
655
+ // elements.push({ type: 'music', data: { type: 'custom', url, audio, title, content, image } })
656
+ // }
657
+ break
658
+ }
659
+ case 'button': {
660
+ // todo
661
+ // elements.push({ type: 'button', data: { buttons: i.buttons } })
662
+ break
663
+ }
664
+ case 'markdown': {
665
+ const { type, ...data } = i
666
+ elements.push({ type, data: { ...data } })
667
+ break
668
+ }
669
+ // case 'rows': {
670
+ // for (const val of i.rows) {
671
+ // elements.push({ type: 'button', data: { buttons: val.buttons } })
672
+ // }
673
+ // break
674
+ // }
675
+ case 'poke': {
676
+ elements.push({ type: 'poke', data: { type: i.poke_type, id: i.id } })
677
+ break
678
+ }
679
+ default: {
680
+ elements.push(i)
681
+ logger.info(i)
682
+ }
683
+ }
684
+ }
685
+ return elements
686
+ }
687
+
688
+ /**
689
+ * 专属当前Bot的日志打印方法
690
+ */
691
+ logger (level, ...args) {
692
+ logger.bot(level, this.account.uid || this.account.uin, ...args)
693
+ }
694
+
695
+ /**
696
+ * 获取头像url
697
+ * @param 头像大小,默认`0`
698
+ * @param 用户qq,默认为机器人QQ
699
+ * @returns 头像的url地址
700
+ */
701
+ getAvatarUrl (uid = this.account.uid || this.account.uin, size = 0) {
702
+ return Number(uid) ? `https://q1.qlogo.cn/g?b=qq&s=${size}&nk=${uid}` : `https://q.qlogo.cn/qqapp/${uid}/${uid}/${size}`
703
+ }
704
+
705
+ /**
706
+ * 获取群头像
707
+ * @param group_id - 群号
708
+ * @param size - 头像大小,默认`0`
709
+ * @param history - 历史头像记录,默认`0`,若要获取历史群头像则填写1,2,3...
710
+ * @returns - 群头像的url地址
711
+ */
712
+ getGroupAvatar (group_id, size = 0, history = 0) {
713
+ return `https://p.qlogo.cn/gh/${group_id}/${group_id}${history ? '_' + history : ''}/` + size
714
+ }
715
+
716
+ /**
717
+ * 发送私聊消息
718
+ * @param user_id - 用户ID
719
+ * @param message - 要发送的内容
720
+ * @returns - 消息ID
721
+ */
722
+ async send_private_msg (user_id, message) {
723
+ const obMessage = this.KarinConvertAdapter(message)
724
+ // this.logger(`${logger.green(`Send private ${user_id}: `)}${this.logSend(message)}`))
725
+ return await this.SendApi('send_private_msg', { user_id, message: obMessage })
726
+ }
727
+
728
+ /**
729
+ * 发送群消息
730
+ * @param group_id - 群号
731
+ * @param message - 要发送的内容
732
+ * @returns - 消息ID
733
+ */
734
+ async send_group_msg (group_id, message) {
735
+ const obMessages = this.KarinConvertAdapter(message)
736
+ return await this.SendApi('send_group_msg', { group_id, message: obMessages })
737
+ }
738
+
739
+ /**
740
+ * 发送消息
741
+ *
742
+ * @param contact
743
+ * @param elements
744
+ * @returns - 消息ID
745
+ */
746
+ async SendMessage (contact, elements) {
747
+ const { scene, peer } = contact
748
+ const message_type = scene === 'group' ? 'group' : 'private'
749
+ const key = scene === 'group' ? 'group_id' : 'user_id'
750
+ const message = this.KarinConvertAdapter(elements)
751
+ const params = { [key]: peer, message_type, message }
752
+ return await this.SendApi('send_msg', params)
753
+ }
754
+
755
+ /**
756
+ * 上传合并转发消息
757
+ * @param contact - 联系人信息
758
+ * @param elements - nodes
759
+ * @returns - 资源id
760
+ * */
761
+ async UploadForwardMessage (contact, elements) {
762
+ if (!Array.isArray(elements)) { elements = [elements] }
763
+ if (elements.some((element) => element.type !== 'node')) {
764
+ throw new Error('elements should be all node type')
765
+ }
766
+ const { scene, peer } = contact
767
+ const message_type = scene === 'group' ? 'group_id' : 'user_id'
768
+ const messages = this.KarinConvertAdapter(elements)
769
+ const params = { [message_type]: String(peer), messages }
770
+ return await this.SendApi('send_forward_msg', params)
771
+ }
772
+
773
+ /**
774
+ * 通过资源id发送转发消息
775
+ * @param contact - 联系人信息
776
+ * @param id - 资源id
777
+ * */
778
+ async SendMessageByResId (contact, id) {
779
+ const { scene, peer } = contact
780
+ const message_type = scene === 'group' ? 'group' : 'private'
781
+ const key = scene === 'group' ? 'group_id' : 'user_id'
782
+ const message = [{ type: 'forward', data: { id } }]
783
+ const params = { [key]: peer, message_type, message }
784
+ const res = await this.SendApi('send_msg', params)
785
+ return { message_id: res.message_id, message_time: Date.now() }
786
+ }
787
+
788
+ /**
789
+ * 撤回消息
790
+ * @param {null} [_contact] - ob11无需提供contact参数
791
+ * @param message_id - 消息ID
792
+ * @returns {Promise<null>}
793
+ */
794
+ async RecallMessage (_contact, message_id) {
795
+ return await this.SendApi('delete_msg', { message_id })
796
+ }
797
+
798
+ /**
799
+ * 获取消息
800
+ * @param {null} [_contact] - ob11无需提供contact参数
801
+ * @param message_id - 消息ID
802
+ * @returns {Promise<object>} - 消息内容
803
+ */
804
+ async GetMessage (_contact, message_id) {
805
+ let res = await this.SendApi('get_msg', { message_id })
806
+ res = {
807
+ time: res.time,
808
+ message_id: res.message_id,
809
+ message_seq: res.message_id,
810
+ contact: {
811
+ scene: res.message_type === 'group' ? 'group' : 'private',
812
+ peer: res.sender.user_id, // 拿不到group_id...
813
+ },
814
+ sender: {
815
+ uid: res.sender.user_id,
816
+ uin: res.sender.user_id,
817
+ nick: res.sender.nickname,
818
+ },
819
+ elements: this.AdapterConvertKarin(res.message),
820
+ }
821
+ return res
822
+ }
823
+
824
+ /**
825
+ * 获取msg_id获取历史消息
826
+ * @description 此api各平台实现不同,暂时废弃
827
+ */
828
+ async GetHistoryMessage (contact, start_message_id, count = 1) {
829
+ const type = contact.scene === 'group' ? 'group_id' : 'user_id'
830
+ const param = { [type]: contact.peer, message_id: start_message_id, count }
831
+ const api = contact.scene === 'group' ? 'get_group_msg_history' : 'get_friend_msg_history'
832
+ const res = await this.SendApi(api, param, 120)
833
+ const ret = []
834
+ for (const i of res.messages) {
835
+ let { time = Date.now(), message_id, message_seq = message_id, sender, message } = i
836
+ const { user_id, nickname } = sender
837
+ sender = { uid: user_id, uin: user_id, nick: nickname }
838
+ const elements = this.AdapterConvertKarin(message)
839
+ ret.push({ time, message_id, message_seq, contact, sender, elements })
840
+ }
841
+ return ret
842
+ }
843
+
844
+ /**
845
+ * 获取合并转发消息
846
+ */
847
+ async get_forward_msg (id) {
848
+ return await this.SendApi('get_forward_msg', { id })
849
+ }
850
+
851
+ /**
852
+ * 发送好友赞
853
+ * @param target_uid_or_uin - 用户ID
854
+ * @param vote_count - 赞的次数,默认为`10`
855
+ */
856
+ async VoteUser (target_uid_or_uin, vote_count = 10) {
857
+ const user_id = Number(target_uid_or_uin)
858
+ await this.SendApi('send_like', { user_id, times: vote_count })
859
+ }
860
+
861
+ /**
862
+ * 群组踢人
863
+ */
864
+ async KickMember (group_id, target_uid_or_uin, reject_add_request = false, kick_reason = '') {
865
+ const user_id = Number(target_uid_or_uin)
866
+ await this.SendApi('set_group_kick', { group_id, user_id, reject_add_request })
867
+ }
868
+
869
+ /**
870
+ * 禁言用户
871
+ * @param group_id - 群号
872
+ * @param target_uid_or_uin - 用户ID
873
+ * @param duration - 禁言时长,单位秒,0 表示取消禁言
874
+ */
875
+ async BanMember (group_id, target_uid_or_uin, duration) {
876
+ const user_id = Number(target_uid_or_uin)
877
+ await this.SendApi('set_group_ban', { group_id, user_id, duration })
878
+ }
879
+
880
+ /**
881
+ * 群组全员禁言
882
+ * @param group_id - 群号
883
+ * @param enable - 是否全员禁言
884
+ */
885
+ async SetGroupWholeBan (group_id, enable = true) {
886
+ await this.SendApi('set_group_whole_ban', { group_id, enable })
887
+ }
888
+
889
+ /**
890
+ * 设置群管理员
891
+ * @param {{
892
+ * group_id:string,
893
+ * target_uid?:string,
894
+ * target_uin?:string,
895
+ * is_admin:boolean
896
+ * }} options - 设置管理员选项
897
+ * @param options.group_id - 群组ID
898
+ * @param options.target_uid - 要设置为管理员的用户uid
899
+ * @param options.target_uin - 要设置为管理员的用户uin
900
+ * @param options.is_admin - 是否设置为管理员
901
+ * @returns {Promise<SetGroupAdminResponse>} - 设置群管理员操作的响应
902
+ */
903
+ async SetGroupAdmin (group_id, target_uid_or_uin, is_admin) {
904
+ const user_id = Number(target_uid_or_uin)
905
+ await this.SendApi('set_group_admin', { group_id, user_id, enable: is_admin })
906
+ }
907
+
908
+ /**
909
+ * 群组匿名
910
+ * @param group_id - 群号
911
+ * @param enable - 是否允许匿名聊天
912
+ */
913
+ async set_group_anonymous (group_id, enable = true) {
914
+ await this.SendApi('set_group_anonymous', { group_id, enable })
915
+ }
916
+
917
+ /**
918
+ * 修改群名片
919
+ * @param group_id - 群号
920
+ * @param target_uid_or_uin - 目标用户ID
921
+ * @param card - 新名片
922
+ */
923
+ async ModifyMemberCard (group_id, target_uid_or_uin, card) {
924
+ const user_id = Number(target_uid_or_uin)
925
+ await this.SendApi('set_group_card', { group_id, user_id, card })
926
+ }
927
+
928
+ /**
929
+ * 设置群名
930
+ * @param group_id - 群号
931
+ * @param group_name - 新群名
932
+ */
933
+ async ModifyGroupName (group_id, group_name) {
934
+ await this.SendApi('set_group_name', { group_id, group_name })
935
+ }
936
+
937
+ /**
938
+ * 退出群组
939
+ * @param group_id - 群号
940
+ * @param is_dismiss - 是否解散,如果登录号是群主,则仅在此项为 true 时能够解散
941
+ */
942
+ async LeaveGroup (group_id, is_dismiss = false) {
943
+ await this.SendApi('set_group_leave', { group_id, is_dismiss })
944
+ }
945
+
946
+ /**
947
+ * 设置群专属头衔
948
+ * @param group_id - 群号
949
+ * @param target_uid_or_uin - 目标用户ID
950
+ * @param special_title - 专属头衔
951
+ */
952
+ async SetGroupUniqueTitle (group_id, target_uid_or_uin, unique_title) {
953
+ const user_id = Number(target_uid_or_uin)
954
+ const special_title = unique_title
955
+ const duration = -1
956
+ await this.SendApi('set_group_special_title', { group_id, user_id, special_title, duration })
957
+ }
958
+
959
+ // /**
960
+ // * 处理加好友请求
961
+ // * @param flag - 加好友请求的 flag(需从上报的数据中获得)
962
+ // * @param {boolean} [approve=true] - 是否同意请求
963
+ // * @param [remark=''] - 添加后的好友备注(仅在同意时有效)
964
+ // */
965
+ // async set_friend_add_request(flag: string, approve = true, remark = '') {
966
+ // await this.SendApi('set_friend_add_request', { flag, approve, remark })
967
+ // }
968
+ // /**
969
+ // * 处理加群请求/邀请
970
+ // * @param flag - 加群请求的 flag(需从上报的数据中获得)
971
+ // * @param sub_type - add 或 invite,请求类型(需要和上报消息中的 sub_type 字段相符)
972
+ // * @param {boolean} [approve=true] - 是否同意请求/邀请
973
+ // * @param [reason=''] - 拒绝理由(仅在拒绝时有效)
974
+ // */
975
+ // async set_group_add_request(flag: string, sub_type: string, approve = true, reason = '') {
976
+ // await this.SendApi('set_group_add_request', { flag, sub_type, approve, reason })
977
+ // }
978
+ /**
979
+ * 获取登录号信息
980
+ */
981
+ async GetCurrentAccount () {
982
+ const res = await this.SendApi('get_login_info')
983
+ return {
984
+ account_uid: res.user_id,
985
+ account_uin: res.user_id,
986
+ account_name: res.nickname,
987
+ }
988
+ }
989
+
990
+ /**
991
+ * 获取陌生人信息 不支持批量获取 只支持一个
992
+ * @param target_uid_or_uin - 目标用户ID
993
+ */
994
+ async GetStrangerProfileCard (target_uid_or_uin) {
995
+ const user_id = Number(target_uid_or_uin[0]) || String(target_uid_or_uin[0])
996
+ const res = await this.SendApi('get_stranger_info', { user_id, no_cache: true })
997
+ return [res]
998
+ }
999
+
1000
+ /**
1001
+ * 获取好友列表
1002
+ * @returns {Promise<Array<IFriendInfo>>} - 好友列表
1003
+ */
1004
+ async GetFriendList () {
1005
+ /** @type {{
1006
+ * user_id: number,
1007
+ * user_name: string?,
1008
+ * user_remark: string,
1009
+ * remark: string?,
1010
+ * nickname: string?,
1011
+ }[]} **/
1012
+ const friendList = await this.SendApi('get_friend_list')
1013
+ return friendList.map((friend) => {
1014
+ return {
1015
+ uin: friend.user_id,
1016
+ uid: friend.user_id,
1017
+ qid: '',
1018
+ nick: friend.nickname || friend.user_name,
1019
+ remark: friend.remark || friend.user_remark,
1020
+ }
1021
+ })
1022
+ }
1023
+
1024
+ /**
1025
+ * 获取群信息
1026
+ * @param group_id - 群号
1027
+ * @param no_cache - 是否不使用缓存
1028
+ * @returns {Promise<IGroupInfo>} - 群信息
1029
+ */
1030
+ async GetGroupInfo (group_id, no_cache = false) {
1031
+ /**
1032
+ * @type {{
1033
+ * group_id: number,
1034
+ * group_name: string,
1035
+ * group_memo: string,
1036
+ * group_remark: string,
1037
+ * group_create_time: number,
1038
+ * group_level: number,
1039
+ * member_count: number,
1040
+ * max_member_count: number,
1041
+ * admins: number[]
1042
+ * }}
1043
+ */
1044
+ const groupInfo = await this.SendApi('get_group_info', { group_id, no_cache })
1045
+ return {
1046
+ group_id: groupInfo.group_id,
1047
+ group_name: groupInfo.group_name,
1048
+ group_remark: groupInfo.group_memo || groupInfo.group_remark,
1049
+ max_member_count: groupInfo.max_member_count,
1050
+ member_count: groupInfo.member_count,
1051
+ group_uin: groupInfo.group_id,
1052
+ admins: groupInfo.admins,
1053
+ owner: groupInfo.admins[0],
1054
+ }
1055
+ }
1056
+
1057
+ /**
1058
+ * 获取群列表
1059
+ */
1060
+ async GetGroupList () {
1061
+ const groupList = await this.SendApi('get_group_list')
1062
+ return groupList?.map((groupInfo) => {
1063
+ return {
1064
+ group_id: groupInfo.group_id,
1065
+ group_name: groupInfo.group_name,
1066
+ group_remark: groupInfo.group_memo || groupInfo.group_remark,
1067
+ max_member_count: groupInfo.max_member_count,
1068
+ member_count: groupInfo.member_count,
1069
+ group_uin: groupInfo.group_id,
1070
+ admins: groupInfo.admins,
1071
+ }
1072
+ })
1073
+ }
1074
+
1075
+ /**
1076
+ * 获取群成员信息
1077
+ * @param group_id - 群号
1078
+ * @param target_uid_or_uin - 目标用户ID
1079
+ * @param refresh - 是否刷新缓存,默认为 false
1080
+ */
1081
+ async GetGroupMemberInfo (group_id, target_uid_or_uin, refresh = false) {
1082
+ const user_id = Number(target_uid_or_uin)
1083
+ /**
1084
+ * @type {{
1085
+ * group_id: number,
1086
+ * user_id: number,
1087
+ * nickname: string,
1088
+ * card: string,
1089
+ * sex: string,
1090
+ * age: number,
1091
+ * area: string,
1092
+ * join_time: number,
1093
+ * last_sent_time: number,
1094
+ * level: string,
1095
+ * role: 'owner' | 'admin' | 'member',
1096
+ * unfriendly: boolean,
1097
+ * title: string,
1098
+ * title_expire_time: number,
1099
+ * card_changeable: boolean,
1100
+ * shut_up_timestamp: number
1101
+ * }}
1102
+ */
1103
+ const groupMemberInfo = await this.SendApi('get_group_member_info', { group_id, user_id, no_cache: refresh })
1104
+ let level = 0
1105
+ try {
1106
+ level = parseInt(groupMemberInfo.level)
1107
+ } catch (e) { }
1108
+ return {
1109
+ uid: groupMemberInfo.user_id,
1110
+ uin: groupMemberInfo.user_id,
1111
+ nick: groupMemberInfo.nickname,
1112
+ age: groupMemberInfo.age,
1113
+ unique_title: groupMemberInfo.title,
1114
+ unique_title_expire_time: groupMemberInfo.title_expire_time,
1115
+ card: groupMemberInfo.card,
1116
+ join_time: groupMemberInfo.join_time,
1117
+ last_active_time: groupMemberInfo.last_sent_time,
1118
+ shut_up_time: 0,
1119
+ level,
1120
+ shut_up_timestamp: groupMemberInfo.shut_up_timestamp,
1121
+ unfriendly: groupMemberInfo.unfriendly,
1122
+ card_changeable: groupMemberInfo.card_changeable,
1123
+ }
1124
+ }
1125
+
1126
+ /**
1127
+ * 获取群成员列表
1128
+ * @param group_id - 群号
1129
+ * @param refresh - 是否刷新缓存,默认为 false
1130
+ */
1131
+ async GetGroupMemberList (group_id, refresh = false) {
1132
+ const gl = await this.SendApi('get_group_member_list', { group_id, refresh })
1133
+ return gl.map((groupMemberInfo) => {
1134
+ let level = 0
1135
+ try {
1136
+ level = parseInt(groupMemberInfo.level)
1137
+ } catch (e) { }
1138
+ return {
1139
+ uid: groupMemberInfo.user_id,
1140
+ uin: groupMemberInfo.user_id,
1141
+ nick: groupMemberInfo.nickname,
1142
+ age: groupMemberInfo.age,
1143
+ unique_title: groupMemberInfo.title,
1144
+ unique_title_expire_time: groupMemberInfo.title_expire_time,
1145
+ card: groupMemberInfo.card,
1146
+ join_time: groupMemberInfo.join_time,
1147
+ last_active_time: groupMemberInfo.last_sent_time,
1148
+ level,
1149
+ shut_up_timestamp: groupMemberInfo.shut_up_timestamp,
1150
+ unfriendly: groupMemberInfo.unfriendly,
1151
+ card_changeable: groupMemberInfo.card_changeable,
1152
+ }
1153
+ })
1154
+ }
1155
+
1156
+ /**
1157
+ * 获取群荣誉信息
1158
+ */
1159
+ async GetGroupHonor (group_id, refresh = false) {
1160
+ /**
1161
+ * @typedef {{user_id: number, nickname: string, avatar: string, description: string}} GroupHonor
1162
+ */
1163
+ /**
1164
+ * @type {{
1165
+ * group_id: number,
1166
+ * current_talkative: {user_id: number, nickname: string, avatar: string, day_count: number},
1167
+ * talkative_list: Array<GroupHonor>,
1168
+ * performer_list: Array<GroupHonor>,
1169
+ * legend_list: Array<GroupHonor>,
1170
+ * strong_newbie_list: Array<GroupHonor>,
1171
+ * emotion_list: Array<GroupHonor>,
1172
+ * }}
1173
+ */
1174
+ const groupHonor = await this.SendApi('get_group_honor_info', { group_id, type: 'all' })
1175
+ const result = []
1176
+ groupHonor.talkative_list.forEach((honor) => {
1177
+ result.push({
1178
+ uin: honor.user_id,
1179
+ uid: honor.user_id,
1180
+ nick: honor.nickname,
1181
+ honor_name: '历史龙王',
1182
+ id: 0,
1183
+ avatar: honor.avatar,
1184
+ description: honor.description,
1185
+ })
1186
+ })
1187
+ groupHonor.performer_list.forEach((honor) => {
1188
+ result.push({
1189
+ uin: honor.user_id,
1190
+ uid: honor.user_id,
1191
+ nick: honor.nickname,
1192
+ honor_name: '群聊之火',
1193
+ avatar: honor.avatar,
1194
+ id: 0,
1195
+ description: honor.description,
1196
+ })
1197
+ })
1198
+ groupHonor.legend_list.forEach((honor) => {
1199
+ result.push({
1200
+ uin: honor.user_id,
1201
+ uid: honor.user_id,
1202
+ nick: honor.nickname,
1203
+ honor_name: '群聊炽焰',
1204
+ avatar: honor.avatar,
1205
+ id: 0,
1206
+ description: honor.description,
1207
+ })
1208
+ })
1209
+ groupHonor.strong_newbie_list.forEach((honor) => {
1210
+ result.push({
1211
+ uin: honor.user_id,
1212
+ uid: honor.user_id,
1213
+ nick: honor.nickname,
1214
+ honor_name: '冒尖小春笋',
1215
+ avatar: honor.avatar,
1216
+ id: 0,
1217
+ description: honor.description,
1218
+ })
1219
+ })
1220
+ groupHonor.emotion_list.forEach((honor) => {
1221
+ result.push({
1222
+ uin: honor.user_id,
1223
+ uid: honor.user_id,
1224
+ nick: honor.nickname,
1225
+ honor_name: '快乐之源',
1226
+ avatar: honor.avatar,
1227
+ id: 0,
1228
+ description: honor.description,
1229
+ })
1230
+ })
1231
+ return result
1232
+ }
1233
+
1234
+ // /**
1235
+ // * 对消息进行表情回应
1236
+ // * @param Contact - 联系人信息
1237
+ // * @param message_id - 消息ID
1238
+ // * @param face_id - 表情ID
1239
+ // */
1240
+ // async ReactMessageWithEmojiRequest(Contact: any, message_id: any, face_id: any, is_set = true) {
1241
+ // return await this.SendApi('set_msg_emoji_like', { message_id, emoji_id: face_id, is_set })
1242
+ // }
1243
+ /**
1244
+ * 获取版本信息
1245
+ */
1246
+ async GetVersion () {
1247
+ return await this.SendApi('get_version_info')
1248
+ }
1249
+
1250
+ async DownloadForwardMessage () {
1251
+ throw new Error('Method not implemented.')
1252
+ }
1253
+
1254
+ async GetEssenceMessageList () {
1255
+ throw new Error('Method not implemented.')
1256
+ }
1257
+
1258
+ async SetEssenceMessage () { }
1259
+ async DeleteEssenceMessage () { }
1260
+ async SetFriendApplyResult () { }
1261
+ async SetGroupApplyResultRequest () { }
1262
+ async SetInvitedJoinGroupResult () { }
1263
+ async ReactMessageWithEmojiRequest () { }
1264
+ async UploadPrivateFile () { }
1265
+ async UploadGroupFile () { }
1266
+ async sendForwardMessage () {
1267
+ return {}
1268
+ }
1269
+
1270
+ /**
1271
+ * 发送API请求
1272
+ * @param action - API断点
1273
+ * @param {object} params - API参数
1274
+ * @returns {Promise<any>} - API返回
1275
+ */
1276
+ async SendApi (action, params = {}, time = 0) {
1277
+ if (!time) { time = config.timeout('ws') }
1278
+ const echo = randomUUID()
1279
+ const request = JSON.stringify({ echo, action, params })
1280
+ logger.debug(`[API请求] ${action}: ${request}`)
1281
+ return new Promise((resolve, reject) => {
1282
+ this.socket.send(request)
1283
+ this.socket.once(echo, data => {
1284
+ if (data.status === 'ok') {
1285
+ resolve(data.data)
1286
+ } else {
1287
+ this.logger('error', `[Api请求错误] ${action}: ${JSON.stringify(data, null, 2)}`)
1288
+ reject(data)
1289
+ }
1290
+ })
1291
+ /** 设置一个超时计时器 */
1292
+ setTimeout(() => {
1293
+ reject(new Error('API请求超时'))
1294
+ }, time * 1000)
1295
+ })
1296
+ }
1297
+ }
1298
+ export default {
1299
+ type: 'websocket',
1300
+ path: '/onebot/v11/ws',
1301
+ adapter: OneBot11,
1302
+ }