node-karin 0.6.12 → 0.6.13
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/adapter/input/index.js +1 -1
- package/lib/adapter/onebot/onebot11.d.ts +3 -11
- package/lib/adapter/onebot/onebot11.js +36 -28
- package/lib/core/listener.js +1 -1
- package/lib/core/plugin.loader.js +17 -5
- package/lib/event/event.handler.js +1 -1
- package/lib/event/message.handler.js +12 -10
- package/lib/event/request.d.ts +2 -2
- package/lib/event/request.js +0 -1
- package/lib/render/client.js +2 -2
- package/lib/types/adapter.d.ts +9 -7
- package/lib/types/element.d.ts +9 -27
- package/lib/utils/common.d.ts +26 -3
- package/lib/utils/common.js +72 -18
- package/lib/utils/segment.d.ts +15 -13
- package/lib/utils/segment.js +34 -16
- package/package.json +1 -2
|
@@ -2,7 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import { randomUUID } from 'crypto';
|
|
3
3
|
import { listener } from '../../core/index.js';
|
|
4
4
|
import { KarinMessage } from '../../event/index.js';
|
|
5
|
-
import { config, common, YamlEditor } from '../../utils/index.js';
|
|
5
|
+
import { config, common, YamlEditor, logger } from '../../utils/index.js';
|
|
6
6
|
const { enable, msgToFile, token: oldToken, ip } = config.Config.AdapterInput;
|
|
7
7
|
/**
|
|
8
8
|
* - 标准输入输出适配器
|
|
@@ -153,17 +153,9 @@ export declare class AdapterOneBot11 implements KarinAdapter {
|
|
|
153
153
|
SetGroupWholeBan(group_id: string, is_ban?: boolean): Promise<void>;
|
|
154
154
|
/**
|
|
155
155
|
* 设置群管理员
|
|
156
|
-
* @param
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* target_uin?:string,
|
|
160
|
-
* is_admin:boolean
|
|
161
|
-
* }} options - 设置管理员选项
|
|
162
|
-
* @param options.group_id - 群组ID
|
|
163
|
-
* @param options.target_uid - 要设置为管理员的用户uid
|
|
164
|
-
* @param options.target_uin - 要设置为管理员的用户uin
|
|
165
|
-
* @param options.is_admin - 是否设置为管理员
|
|
166
|
-
* @returns {Promise<SetGroupAdminResponse>} - 设置群管理员操作的响应
|
|
156
|
+
* @param group_id - 群号
|
|
157
|
+
* @param target_uid_or_uin - 目标用户ID
|
|
158
|
+
* @param is_admin - 是否设置为管理员
|
|
167
159
|
*/
|
|
168
160
|
SetGroupAdmin(group_id: string, target_uid_or_uin: string, is_admin: boolean): Promise<void>;
|
|
169
161
|
/**
|
|
@@ -213,7 +213,7 @@ export class AdapterOneBot11 {
|
|
|
213
213
|
uid: data.user_id + '',
|
|
214
214
|
uin: data.user_id + '',
|
|
215
215
|
nick: '',
|
|
216
|
-
role: '',
|
|
216
|
+
role: 'unknown',
|
|
217
217
|
};
|
|
218
218
|
const contact = {
|
|
219
219
|
scene: ('group_id' in data ? 'group' : 'friend'),
|
|
@@ -223,8 +223,9 @@ export class AdapterOneBot11 {
|
|
|
223
223
|
switch (data.notice_type) {
|
|
224
224
|
// 群文件上传
|
|
225
225
|
case 'group_upload': {
|
|
226
|
+
const group_id = data.group_id + '';
|
|
226
227
|
const content = {
|
|
227
|
-
group_id
|
|
228
|
+
group_id,
|
|
228
229
|
operator_uid: data.user_id + '',
|
|
229
230
|
operator_uin: data.user_id + '',
|
|
230
231
|
file_id: data.file.id,
|
|
@@ -242,6 +243,7 @@ export class AdapterOneBot11 {
|
|
|
242
243
|
content,
|
|
243
244
|
sender,
|
|
244
245
|
contact,
|
|
246
|
+
group_id,
|
|
245
247
|
sub_event: 'group_file_uploaded',
|
|
246
248
|
};
|
|
247
249
|
notice = new KarinNotice(options);
|
|
@@ -249,8 +251,9 @@ export class AdapterOneBot11 {
|
|
|
249
251
|
}
|
|
250
252
|
// 群管理员变动
|
|
251
253
|
case 'group_admin': {
|
|
254
|
+
const group_id = data.group_id + '';
|
|
252
255
|
const content = {
|
|
253
|
-
group_id
|
|
256
|
+
group_id,
|
|
254
257
|
target_uid: data.user_id + '',
|
|
255
258
|
target_uin: data.user_id + '',
|
|
256
259
|
is_admin: data.sub_type === 'set',
|
|
@@ -263,6 +266,7 @@ export class AdapterOneBot11 {
|
|
|
263
266
|
sender,
|
|
264
267
|
contact,
|
|
265
268
|
content,
|
|
269
|
+
group_id,
|
|
266
270
|
sub_event: 'group_admin_changed',
|
|
267
271
|
};
|
|
268
272
|
notice = new KarinNotice(options);
|
|
@@ -270,10 +274,11 @@ export class AdapterOneBot11 {
|
|
|
270
274
|
}
|
|
271
275
|
// 群成员减少
|
|
272
276
|
case 'group_decrease': {
|
|
277
|
+
const group_id = data.group_id + '';
|
|
273
278
|
const content = {
|
|
274
|
-
group_id
|
|
275
|
-
operator_uid: data.operator_id || '',
|
|
276
|
-
operator_uin: data.operator_id || '',
|
|
279
|
+
group_id,
|
|
280
|
+
operator_uid: (data.operator_id + '') || '',
|
|
281
|
+
operator_uin: (data.operator_id + '') || '',
|
|
277
282
|
target_uid: data.user_id || '',
|
|
278
283
|
target_uin: data.user_id || '',
|
|
279
284
|
type: data.sub_type,
|
|
@@ -286,6 +291,7 @@ export class AdapterOneBot11 {
|
|
|
286
291
|
sender,
|
|
287
292
|
contact,
|
|
288
293
|
content,
|
|
294
|
+
group_id,
|
|
289
295
|
sub_event: 'group_member_decrease',
|
|
290
296
|
};
|
|
291
297
|
notice = new KarinNotice(options);
|
|
@@ -293,8 +299,9 @@ export class AdapterOneBot11 {
|
|
|
293
299
|
}
|
|
294
300
|
// 群成员增加
|
|
295
301
|
case 'group_increase': {
|
|
302
|
+
const group_id = data.group_id + '';
|
|
296
303
|
const content = {
|
|
297
|
-
group_id
|
|
304
|
+
group_id,
|
|
298
305
|
operator_uid: (data.operator_id || '') + '',
|
|
299
306
|
operator_uin: (data.operator_id || '') + '',
|
|
300
307
|
target_uid: (data.user_id || '') + '',
|
|
@@ -309,6 +316,7 @@ export class AdapterOneBot11 {
|
|
|
309
316
|
sender,
|
|
310
317
|
contact,
|
|
311
318
|
content,
|
|
319
|
+
group_id,
|
|
312
320
|
sub_event: 'group_member_increase',
|
|
313
321
|
};
|
|
314
322
|
notice = new KarinNotice(options);
|
|
@@ -316,10 +324,11 @@ export class AdapterOneBot11 {
|
|
|
316
324
|
}
|
|
317
325
|
// 群禁言事件
|
|
318
326
|
case 'group_ban': {
|
|
327
|
+
const group_id = data.group_id + '';
|
|
319
328
|
const content = {
|
|
320
|
-
group_id
|
|
321
|
-
operator_uid: data.operator_id || '',
|
|
322
|
-
operator_uin: data.operator_id || '',
|
|
329
|
+
group_id,
|
|
330
|
+
operator_uid: (data.operator_id + '') || '',
|
|
331
|
+
operator_uin: (data.operator_id + '') || '',
|
|
323
332
|
target_uid: data.user_id || '',
|
|
324
333
|
target_uin: data.user_id || '',
|
|
325
334
|
duration: data.duration,
|
|
@@ -333,6 +342,7 @@ export class AdapterOneBot11 {
|
|
|
333
342
|
sender,
|
|
334
343
|
contact,
|
|
335
344
|
content,
|
|
345
|
+
group_id,
|
|
336
346
|
sub_event: 'group_member_ban',
|
|
337
347
|
};
|
|
338
348
|
notice = new KarinNotice(options);
|
|
@@ -343,10 +353,11 @@ export class AdapterOneBot11 {
|
|
|
343
353
|
this.logger('info', `[好友添加]:${JSON.stringify(data)}`);
|
|
344
354
|
break;
|
|
345
355
|
case 'group_recall': {
|
|
356
|
+
const group_id = data.group_id + '';
|
|
346
357
|
const content = {
|
|
347
|
-
group_id
|
|
348
|
-
operator_uid: data.operator_id || '',
|
|
349
|
-
operator_uin: data.operator_id || '',
|
|
358
|
+
group_id,
|
|
359
|
+
operator_uid: (data.operator_id + '') || '',
|
|
360
|
+
operator_uin: (data.operator_id + '') || '',
|
|
350
361
|
target_uid: data.user_id || '',
|
|
351
362
|
target_uin: data.user_id || '',
|
|
352
363
|
message_id: data.message_id,
|
|
@@ -360,6 +371,7 @@ export class AdapterOneBot11 {
|
|
|
360
371
|
sender,
|
|
361
372
|
contact,
|
|
362
373
|
content,
|
|
374
|
+
group_id,
|
|
363
375
|
sub_event: 'group_recall',
|
|
364
376
|
};
|
|
365
377
|
notice = new KarinNotice(options);
|
|
@@ -388,8 +400,9 @@ export class AdapterOneBot11 {
|
|
|
388
400
|
case 'notify':
|
|
389
401
|
switch (data.sub_type) {
|
|
390
402
|
case 'poke': {
|
|
403
|
+
const group_id = 'group_id' in data ? data.group_id + '' : '';
|
|
391
404
|
const content = {
|
|
392
|
-
group_id
|
|
405
|
+
group_id,
|
|
393
406
|
operator_uid: data.user_id + '',
|
|
394
407
|
operator_uin: data.user_id + '',
|
|
395
408
|
target_uid: data.target_id + '',
|
|
@@ -406,6 +419,7 @@ export class AdapterOneBot11 {
|
|
|
406
419
|
sender,
|
|
407
420
|
contact,
|
|
408
421
|
content,
|
|
422
|
+
group_id,
|
|
409
423
|
sub_event: data.group_id ? 'group_poke' : 'private_poke',
|
|
410
424
|
};
|
|
411
425
|
notice = new KarinNotice(options);
|
|
@@ -422,8 +436,9 @@ export class AdapterOneBot11 {
|
|
|
422
436
|
}
|
|
423
437
|
break;
|
|
424
438
|
case 'group_msg_emoji_like': {
|
|
439
|
+
const group_id = data.group_id + '';
|
|
425
440
|
const content = {
|
|
426
|
-
group_id
|
|
441
|
+
group_id,
|
|
427
442
|
message_id: data.message_id,
|
|
428
443
|
face_id: data.likes[0].emoji_id,
|
|
429
444
|
is_set: true,
|
|
@@ -436,6 +451,7 @@ export class AdapterOneBot11 {
|
|
|
436
451
|
sender,
|
|
437
452
|
contact,
|
|
438
453
|
content,
|
|
454
|
+
group_id,
|
|
439
455
|
sub_event: 'group_message_reaction',
|
|
440
456
|
};
|
|
441
457
|
notice = new KarinNotice(options);
|
|
@@ -465,7 +481,7 @@ export class AdapterOneBot11 {
|
|
|
465
481
|
uid: data.user_id + '',
|
|
466
482
|
uin: data.user_id + '',
|
|
467
483
|
nick: '',
|
|
468
|
-
role: '',
|
|
484
|
+
role: 'unknown',
|
|
469
485
|
},
|
|
470
486
|
sub_event: 'private_apply',
|
|
471
487
|
content: {
|
|
@@ -492,7 +508,7 @@ export class AdapterOneBot11 {
|
|
|
492
508
|
uid: data.user_id + '',
|
|
493
509
|
uin: data.user_id + '',
|
|
494
510
|
nick: '',
|
|
495
|
-
role: '',
|
|
511
|
+
role: 'unknown',
|
|
496
512
|
},
|
|
497
513
|
sub_event: data.sub_type === 'add' ? 'group_apply' : 'invited_group',
|
|
498
514
|
content: {
|
|
@@ -871,17 +887,9 @@ export class AdapterOneBot11 {
|
|
|
871
887
|
}
|
|
872
888
|
/**
|
|
873
889
|
* 设置群管理员
|
|
874
|
-
* @param
|
|
875
|
-
*
|
|
876
|
-
*
|
|
877
|
-
* target_uin?:string,
|
|
878
|
-
* is_admin:boolean
|
|
879
|
-
* }} options - 设置管理员选项
|
|
880
|
-
* @param options.group_id - 群组ID
|
|
881
|
-
* @param options.target_uid - 要设置为管理员的用户uid
|
|
882
|
-
* @param options.target_uin - 要设置为管理员的用户uin
|
|
883
|
-
* @param options.is_admin - 是否设置为管理员
|
|
884
|
-
* @returns {Promise<SetGroupAdminResponse>} - 设置群管理员操作的响应
|
|
890
|
+
* @param group_id - 群号
|
|
891
|
+
* @param target_uid_or_uin - 目标用户ID
|
|
892
|
+
* @param is_admin - 是否设置为管理员
|
|
885
893
|
*/
|
|
886
894
|
async SetGroupAdmin(group_id, target_uid_or_uin, is_admin) {
|
|
887
895
|
const user_id = Number(target_uid_or_uin);
|
package/lib/core/listener.js
CHANGED
|
@@ -163,7 +163,7 @@ class Listeners extends EventEmitter {
|
|
|
163
163
|
/** 标准化 */
|
|
164
164
|
const NewElements = common.makeMessage(elements)
|
|
165
165
|
/** 结果 */
|
|
166
|
-
let result = {
|
|
166
|
+
let result = {}
|
|
167
167
|
const reply_log = common.makeMessageLog(NewElements)
|
|
168
168
|
const self_id = bot.account.uid || bot.account.uin
|
|
169
169
|
if (contact.scene === 'group') {
|
|
@@ -123,14 +123,23 @@ class PluginLoader {
|
|
|
123
123
|
this.getApps(dir, this.isTs, true)
|
|
124
124
|
continue
|
|
125
125
|
}
|
|
126
|
-
/**
|
|
126
|
+
/** package */
|
|
127
|
+
const pack = common.readJson(`${PluginPath}/package.json`)
|
|
128
|
+
/** 旧版本入口文件 */
|
|
127
129
|
const index = this.getIndex(PluginPath, process.env.karin_app_lang)
|
|
128
130
|
if (index) {
|
|
129
131
|
this.FileList.push({ dir, name: index })
|
|
130
132
|
this.isDev && this.watchList.push({ dir, name: index })
|
|
131
133
|
}
|
|
134
|
+
/** 新版本入口 */
|
|
135
|
+
if (pack.main) {
|
|
136
|
+
const { dir: dirName, pop } = common.splitPath(pack.main)
|
|
137
|
+
const dirPath = `${dir}/${dirName}`
|
|
138
|
+
this.FileList.push({ dir: dirPath, name: pop })
|
|
139
|
+
this.isDev && this.watchList.push({ dir: dirPath, name: pop })
|
|
140
|
+
}
|
|
132
141
|
/** 检查是否存在karin.apps */
|
|
133
|
-
const
|
|
142
|
+
const outDir = (pack?.karin?.outDir || 'dist')
|
|
134
143
|
if (pack && pack?.karin?.apps) {
|
|
135
144
|
const cfg = pack.karin.apps
|
|
136
145
|
if (Array.isArray(cfg)) {
|
|
@@ -144,8 +153,8 @@ class PluginLoader {
|
|
|
144
153
|
/** ts环境 全部加载 如果存在编译产物 则不加载ts */
|
|
145
154
|
if (this.isTs) {
|
|
146
155
|
/** 编译产物 存在不加载ts */
|
|
147
|
-
if (common.exists(`${PluginPath}/
|
|
148
|
-
this.getApps((`${dir}/
|
|
156
|
+
if (common.exists(`${PluginPath}/${outDir}/apps`)) {
|
|
157
|
+
this.getApps((`${dir}/${outDir}/apps`), false)
|
|
149
158
|
continue
|
|
150
159
|
}
|
|
151
160
|
/** ts */
|
|
@@ -157,7 +166,7 @@ class PluginLoader {
|
|
|
157
166
|
/** js环境 */
|
|
158
167
|
if (common.isDir(`${PluginPath}/apps`)) { this.getApps(`${dir}/apps`, false) }
|
|
159
168
|
/** 这里需要判断下 不然ts环境下会重复加载 */
|
|
160
|
-
if (!this.isTs && common.isDir(`${PluginPath}/
|
|
169
|
+
if (!this.isTs && common.isDir(`${PluginPath}/${outDir}/apps`)) { this.getApps(`${dir}/${outDir}/apps`, false) }
|
|
161
170
|
}
|
|
162
171
|
}
|
|
163
172
|
|
|
@@ -247,6 +256,9 @@ class PluginLoader {
|
|
|
247
256
|
if (!App?.name) { return logger.error(`[${dir}][${name}] 插件名称错误`) }
|
|
248
257
|
App.file.dir = dir
|
|
249
258
|
App.file.name = name
|
|
259
|
+
App.rule.forEach((v, index) => {
|
|
260
|
+
App.rule[index].log = v.log === false ? (id, log) => logger.bot('debug', id, log) : (id, log) => logger.bot('mark', id, log)
|
|
261
|
+
})
|
|
250
262
|
/** handler */
|
|
251
263
|
App.task = this.addTaskFnc(dir, App)
|
|
252
264
|
this.PluginList[index] = App
|
|
@@ -16,7 +16,7 @@ export default class EventHandler {
|
|
|
16
16
|
this.config = {}
|
|
17
17
|
this.GroupMsgPrint = false
|
|
18
18
|
/** 加入e.bot */
|
|
19
|
-
Object.defineProperty(this.e, 'bot', { value: listener.getBot(this.e.self_id) })
|
|
19
|
+
!this.e.bot && Object.defineProperty(this.e, 'bot', { value: listener.getBot(this.e.self_id) })
|
|
20
20
|
if (this.e.group_id) { this.config = config.group(this.e.group_id) }
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -25,7 +25,6 @@ export class MessageHandler extends EventHandler {
|
|
|
25
25
|
logger.debug('[消息拦截] 响应模式不匹配')
|
|
26
26
|
return
|
|
27
27
|
}
|
|
28
|
-
this.GroupMsgPrint = false
|
|
29
28
|
/** 处理回复 */
|
|
30
29
|
this.reply()
|
|
31
30
|
/** 处理消息 */
|
|
@@ -51,8 +50,9 @@ export class MessageHandler extends EventHandler {
|
|
|
51
50
|
if ('GroupCD' in this.config && !review.PluginEnable(app, this.config)) { continue }
|
|
52
51
|
/** 判断子事件 */
|
|
53
52
|
if (v.event && !this.filtEvent(v.event)) { continue }
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
const fncName = app.file.type === 'function' ? 'default' : v.fnc
|
|
54
|
+
this.e.logFnc = `[${app.file.dir}][${app.name}][${fncName}]`
|
|
55
|
+
const logFnc = logger.fnc(`[${app.name}][${fncName}]`)
|
|
56
56
|
this.GroupMsgPrint && typeof v.log === 'function' && v.log(this.e.self_id, `${logFnc}${this.e.logText} ${lodash.truncate(this.e.msg, { length: 80 })}`)
|
|
57
57
|
/** 判断权限 */
|
|
58
58
|
if (!this.filterPermission(v.permission)) { break a }
|
|
@@ -165,13 +165,15 @@ export class MessageHandler extends EventHandler {
|
|
|
165
165
|
logs.push(`[json:${JSON.stringify(val.data)}]`)
|
|
166
166
|
break
|
|
167
167
|
case 'markdown': {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
168
|
+
logs.push(`[markdown:${val.content}]`)
|
|
169
|
+
break
|
|
170
|
+
}
|
|
171
|
+
case 'markdown_tpl': {
|
|
172
|
+
const params = val.params
|
|
173
|
+
if (!params) { break }
|
|
174
|
+
const content = { id: val.custom_template_id }
|
|
175
|
+
for (const v of params) { content[v.key] = v.values[0] }
|
|
176
|
+
logs.push(`[markdown_tpl:${JSON.stringify(content)}]`)
|
|
175
177
|
break
|
|
176
178
|
}
|
|
177
179
|
case 'rows': {
|
package/lib/event/request.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KarinEvent } from './event.js';
|
|
2
|
-
import { contact, Sender, EventToSubEvent, RequestType
|
|
2
|
+
import { contact, Sender, EventToSubEvent, RequestType } from '../types/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* - 请求事件基类
|
|
5
5
|
*/
|
|
@@ -45,5 +45,5 @@ export declare class KarinRequest extends KarinEvent {
|
|
|
45
45
|
/**
|
|
46
46
|
* - 事件对应的内容参数
|
|
47
47
|
*/
|
|
48
|
-
content:
|
|
48
|
+
content: RequestType[EventToSubEvent['request']];
|
|
49
49
|
}
|
package/lib/event/request.js
CHANGED
|
@@ -5,7 +5,6 @@ import { KarinEvent } from './event.js'
|
|
|
5
5
|
export class KarinRequest extends KarinEvent {
|
|
6
6
|
constructor ({ self_id, event_id, user_id, time, contact, sender, sub_event, content, group_id = '' }) {
|
|
7
7
|
super({ event: 'request', event_id, self_id, user_id, group_id, time, contact, sender, sub_event })
|
|
8
|
-
// ...
|
|
9
8
|
this.content = content
|
|
10
9
|
}
|
|
11
10
|
|
package/lib/render/client.js
CHANGED
|
@@ -21,14 +21,14 @@ export class RenderClient extends RenderBase {
|
|
|
21
21
|
this.index = 0
|
|
22
22
|
this.retry = 0
|
|
23
23
|
this.reg = new RegExp(`(${process.cwd().replace(/\\/g, '\\\\')}|${process.cwd().replace(/\\/g, '/')})`, 'g')
|
|
24
|
-
/** 连接ws */
|
|
25
|
-
this.ws = new WebSocket(this.url)
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
/**
|
|
29
27
|
* 初始化
|
|
30
28
|
*/
|
|
31
29
|
async start () {
|
|
30
|
+
/** 连接ws */
|
|
31
|
+
this.ws = new WebSocket(this.url)
|
|
32
32
|
/** 建立连接 */
|
|
33
33
|
this.ws.on('open', () => {
|
|
34
34
|
logger.mark(`[渲染器:${this.id}][WebSocket] 建立连接:${logger.green(this.url)}`)
|
package/lib/types/adapter.d.ts
CHANGED
|
@@ -105,9 +105,10 @@ export interface KarinAdapter {
|
|
|
105
105
|
/**
|
|
106
106
|
* - 头像大小,默认需要为`0`,请开发者注意
|
|
107
107
|
*/
|
|
108
|
-
size?:
|
|
108
|
+
size?: 0 | 40 | 100 | 140): string;
|
|
109
109
|
/**
|
|
110
|
-
*
|
|
110
|
+
* 获取群头像url
|
|
111
|
+
* @returns 头像的url地址
|
|
111
112
|
*/
|
|
112
113
|
getGroupAvatar(
|
|
113
114
|
/**
|
|
@@ -117,7 +118,7 @@ export interface KarinAdapter {
|
|
|
117
118
|
/**
|
|
118
119
|
* - 头像大小,默认`0`
|
|
119
120
|
*/
|
|
120
|
-
size?:
|
|
121
|
+
size?: 0 | 40 | 100 | 140,
|
|
121
122
|
/**
|
|
122
123
|
* - 历史头像记录,默认`0`,若要获取历史群头像则填写1,2,3...
|
|
123
124
|
*/
|
|
@@ -141,7 +142,8 @@ export interface KarinAdapter {
|
|
|
141
142
|
/**
|
|
142
143
|
* - 消息ID
|
|
143
144
|
*/
|
|
144
|
-
message_id
|
|
145
|
+
message_id?: string;
|
|
146
|
+
[key: string]: any;
|
|
145
147
|
}>;
|
|
146
148
|
/**
|
|
147
149
|
* - 上传合并转发消息返回一个资源ID
|
|
@@ -193,7 +195,7 @@ export interface KarinAdapter {
|
|
|
193
195
|
/**
|
|
194
196
|
* - 消息ID
|
|
195
197
|
*/
|
|
196
|
-
message_id: string): Promise<void>;
|
|
198
|
+
message_id: string): Promise<void | boolean>;
|
|
197
199
|
/**
|
|
198
200
|
* - 获取消息
|
|
199
201
|
*/
|
|
@@ -281,7 +283,7 @@ export interface KarinAdapter {
|
|
|
281
283
|
/**
|
|
282
284
|
* - 赞的次数,默认为10
|
|
283
285
|
*/
|
|
284
|
-
vote_count: number): Promise<void>;
|
|
286
|
+
vote_count: number): Promise<void | boolean>;
|
|
285
287
|
/**
|
|
286
288
|
* - 群踢人
|
|
287
289
|
*/
|
|
@@ -554,7 +556,7 @@ export interface KarinAdapter {
|
|
|
554
556
|
message_id?: string;
|
|
555
557
|
}>;
|
|
556
558
|
/**
|
|
557
|
-
* 对消息进行表情回应
|
|
559
|
+
* 对消息进行表情回应 icqq需要传递seq
|
|
558
560
|
* @param Contact - 联系人信息
|
|
559
561
|
* @param message_id - 消息ID
|
|
560
562
|
* @param face_id - 表情ID
|
package/lib/types/element.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ElementType = 'text' | 'at' | 'face' | 'bubble_face' | 'reply' | 'image' | 'voice' | 'video' | 'basketball' | 'dice' | 'rps' | 'poke' | 'music' | 'weather' | 'location' | 'share' | 'gift' | 'market_face' | 'forward' | 'contact' | 'json' | 'xml' | 'file' | 'markdown' | 'keyboard' | 'node' | 'rows' | 'record' | 'long_msg';
|
|
1
|
+
export type ElementType = 'text' | 'at' | 'face' | 'bubble_face' | 'reply' | 'image' | 'voice' | 'video' | 'basketball' | 'dice' | 'rps' | 'poke' | 'music' | 'weather' | 'location' | 'share' | 'gift' | 'market_face' | 'forward' | 'contact' | 'json' | 'xml' | 'file' | 'markdown' | 'markdown_tpl' | 'keyboard' | 'node' | 'rows' | 'record' | 'long_msg';
|
|
2
2
|
export interface Element {
|
|
3
3
|
/**
|
|
4
4
|
* - 元素类型
|
|
@@ -444,36 +444,18 @@ export interface ContentElement extends Element {
|
|
|
444
444
|
* - 原生markdown内容
|
|
445
445
|
*/
|
|
446
446
|
content: string;
|
|
447
|
+
config?: {
|
|
448
|
+
/** 未知的参数 */
|
|
449
|
+
unknown?: number;
|
|
450
|
+
time: number;
|
|
451
|
+
token: string;
|
|
452
|
+
};
|
|
447
453
|
}
|
|
448
454
|
/**
|
|
449
455
|
* - 模板 Markdown 元素
|
|
450
456
|
*/
|
|
451
457
|
export interface TemplateElement extends Element {
|
|
452
|
-
type: '
|
|
453
|
-
/**
|
|
454
|
-
* - 模板ID
|
|
455
|
-
*/
|
|
456
|
-
custom_template_id: string;
|
|
457
|
-
/**
|
|
458
|
-
* - 模板参数
|
|
459
|
-
*/
|
|
460
|
-
params: Array<{
|
|
461
|
-
/**
|
|
462
|
-
* - 模板参数键名称
|
|
463
|
-
*/
|
|
464
|
-
key: string;
|
|
465
|
-
/**
|
|
466
|
-
* - 模板参数值
|
|
467
|
-
*/
|
|
468
|
-
values: Array<string>;
|
|
469
|
-
}>;
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
* - Markdown元素
|
|
473
|
-
*/
|
|
474
|
-
export interface MarkdownElement extends Element {
|
|
475
|
-
type: 'markdown';
|
|
476
|
-
content: string;
|
|
458
|
+
type: 'markdown_tpl';
|
|
477
459
|
/**
|
|
478
460
|
* - 模板ID
|
|
479
461
|
*/
|
|
@@ -566,7 +548,7 @@ export interface LongMsgElement extends Element {
|
|
|
566
548
|
*/
|
|
567
549
|
id: string;
|
|
568
550
|
}
|
|
569
|
-
export type KarinElement = TextElement | AtElement | FaceElement | BubbleFaceElement | ReplyElement | ImageElement | VoiceElement | VideoElement | BasketballElement | DiceElement | RpsElement | PokeElement | MusicElement | WeatherElement | LocationElement | ShareElement | GiftElement | MarketFaceElement | ForwardElement | ContactElement | JsonElement | XmlElement | FileElement |
|
|
551
|
+
export type KarinElement = TextElement | AtElement | FaceElement | BubbleFaceElement | ReplyElement | ImageElement | VoiceElement | VideoElement | BasketballElement | DiceElement | RpsElement | PokeElement | MusicElement | WeatherElement | LocationElement | ShareElement | GiftElement | MarketFaceElement | ForwardElement | ContactElement | JsonElement | XmlElement | FileElement | ButtonElement | RowElement | RecordElement | LongMsgElement | TemplateElement | ContentElement;
|
|
570
552
|
/**
|
|
571
553
|
* - 构建自定义转发节点 此元素仅可通过专用接口发送 不支持混合发送
|
|
572
554
|
*/
|
package/lib/utils/common.d.ts
CHANGED
|
@@ -61,6 +61,18 @@ export declare const common: {
|
|
|
61
61
|
* - 解析json文件
|
|
62
62
|
*/
|
|
63
63
|
readJson(file: string): any;
|
|
64
|
+
/**
|
|
65
|
+
* - 写入json文件
|
|
66
|
+
*/
|
|
67
|
+
writeJson(file: string, data: any): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* - 解析yaml文件
|
|
70
|
+
*/
|
|
71
|
+
readYaml(file: string): any;
|
|
72
|
+
/**
|
|
73
|
+
* - 写入yaml文件
|
|
74
|
+
*/
|
|
75
|
+
writeYaml(file: string, data: any): boolean;
|
|
64
76
|
/**
|
|
65
77
|
* 根据文件后缀名从指定路径下读取符合要求的文件
|
|
66
78
|
* @param path - 路径
|
|
@@ -70,10 +82,22 @@ export declare const common: {
|
|
|
70
82
|
*/
|
|
71
83
|
readDir(_path: string, ext: string | string[]): string[] | null;
|
|
72
84
|
/**
|
|
73
|
-
*
|
|
85
|
+
* 根据传入的 import.meta.url 计算相对于项目根目录的路径,返回需要的 '../' 层级。
|
|
74
86
|
* @param url - import.meta.url
|
|
87
|
+
* @returns 相对路径的层级数量,用 '../' 表示
|
|
88
|
+
* @example
|
|
89
|
+
* // 在 plugins/karin-plugin-example/index.ts 中使用
|
|
90
|
+
* common.urlToPath(import.meta.url) // 返回 '../../'
|
|
75
91
|
*/
|
|
76
92
|
urlToPath(url: string): string;
|
|
93
|
+
/**
|
|
94
|
+
* 传入相对路径 分割为两部分 1为文件夹路径 2为文件名 文件夹路径无前缀开头
|
|
95
|
+
* @param _path - 路径
|
|
96
|
+
*/
|
|
97
|
+
splitPath(_path: string): {
|
|
98
|
+
dir: string;
|
|
99
|
+
pop: string;
|
|
100
|
+
};
|
|
77
101
|
/**
|
|
78
102
|
* 将文件转换为不带前缀的base64字符串
|
|
79
103
|
* @param file - 文件路径或Buffer对象、可读流对象、http地址、base64://字符串
|
|
@@ -106,10 +130,9 @@ export declare const common: {
|
|
|
106
130
|
makeMessage(elements: string | KarinElement | (string | KarinElement)[]): Array<KarinElement>;
|
|
107
131
|
/**
|
|
108
132
|
* 制作简单转发,返回segment.node[]。仅简单包装node,也可以自己组装
|
|
109
|
-
* @param
|
|
133
|
+
* @param elements
|
|
110
134
|
* @param fakeUin 用户id
|
|
111
135
|
* @param fakeNick 用户昵称
|
|
112
|
-
* @return {Array<KarinNodeElement>}
|
|
113
136
|
*/
|
|
114
137
|
makeForward(elements: KarinElement | KarinElement[], fakeUin: string, fakeNick: string): Array<KarinNodeElement>;
|
|
115
138
|
/**
|
package/lib/utils/common.js
CHANGED
|
@@ -2,7 +2,7 @@ import { promisify } from 'util'
|
|
|
2
2
|
import { fileURLToPath } from 'url'
|
|
3
3
|
import { pipeline, Readable } from 'stream'
|
|
4
4
|
import { logger, segment } from '../utils/index.js'
|
|
5
|
-
import { fs, path, axios, lodash } from '../modules.js'
|
|
5
|
+
import { fs, path, axios, lodash, yaml as Yaml } from '../modules.js'
|
|
6
6
|
/**
|
|
7
7
|
* 常用方法
|
|
8
8
|
*/
|
|
@@ -136,11 +136,49 @@ export const common = new (class Common {
|
|
|
136
136
|
try {
|
|
137
137
|
return JSON.parse(fs.readFileSync(file, 'utf8'))
|
|
138
138
|
} catch (error) {
|
|
139
|
-
logger.error('读取json文件错误:' + error)
|
|
139
|
+
logger.error('[common] 读取json文件错误:' + error)
|
|
140
140
|
return null
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
/**
|
|
145
|
+
* - 写入json文件
|
|
146
|
+
*/
|
|
147
|
+
writeJson (file, data) {
|
|
148
|
+
try {
|
|
149
|
+
fs.writeFileSync(file, JSON.stringify(data, null, 2))
|
|
150
|
+
return true
|
|
151
|
+
} catch (error) {
|
|
152
|
+
logger.error('[common] 写入json文件错误:' + error)
|
|
153
|
+
return false
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* - 解析yaml文件
|
|
159
|
+
*/
|
|
160
|
+
readYaml (file) {
|
|
161
|
+
try {
|
|
162
|
+
return Yaml.parse(fs.readFileSync(file, 'utf8'))
|
|
163
|
+
} catch (error) {
|
|
164
|
+
logger.error('[common] 读取yaml文件错误:' + error)
|
|
165
|
+
return null
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* - 写入yaml文件
|
|
171
|
+
*/
|
|
172
|
+
writeYaml (file, data) {
|
|
173
|
+
try {
|
|
174
|
+
fs.writeFileSync(file, Yaml.stringify(data))
|
|
175
|
+
return true
|
|
176
|
+
} catch (error) {
|
|
177
|
+
logger.error('[common] 写入yaml文件错误:' + error)
|
|
178
|
+
return false
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
144
182
|
/**
|
|
145
183
|
* 根据文件后缀名从指定路径下读取符合要求的文件
|
|
146
184
|
* @param path - 路径
|
|
@@ -162,25 +200,40 @@ export const common = new (class Common {
|
|
|
162
200
|
}
|
|
163
201
|
|
|
164
202
|
/**
|
|
165
|
-
*
|
|
203
|
+
* 根据传入的 import.meta.url 计算相对于项目根目录的路径,返回需要的 '../' 层级。
|
|
166
204
|
* @param url - import.meta.url
|
|
205
|
+
* @returns 相对路径的层级数量,用 '../' 表示
|
|
206
|
+
* @example
|
|
207
|
+
* // 在 plugins/karin-plugin-example/index.ts 中使用
|
|
208
|
+
* common.urlToPath(import.meta.url) // 返回 '../../'
|
|
167
209
|
*/
|
|
168
210
|
urlToPath (url) {
|
|
169
|
-
|
|
211
|
+
/** 当前文件的绝对路径 */
|
|
170
212
|
const filePath = fileURLToPath(url)
|
|
171
|
-
|
|
213
|
+
/** 当前文件所在目录的绝对路径 */
|
|
172
214
|
const dirPath = path.dirname(filePath)
|
|
173
|
-
|
|
215
|
+
/** 项目根目录 */
|
|
174
216
|
const rootPath = process.cwd()
|
|
175
|
-
|
|
217
|
+
/** 当前文件到项目根目录的相对路径 */
|
|
176
218
|
const relativePath = path.relative(dirPath, rootPath)
|
|
177
|
-
|
|
219
|
+
/** 相对路径的层级数量 */
|
|
178
220
|
const upLevelsCount = relativePath.split(path.sep).length
|
|
179
|
-
|
|
221
|
+
/** 返回构建的路径 */
|
|
180
222
|
const upPath = lodash.repeat('../', upLevelsCount)
|
|
181
223
|
return upPath
|
|
182
224
|
}
|
|
183
225
|
|
|
226
|
+
/**
|
|
227
|
+
* 传入相对路径 分割为两部分 1为文件夹路径 2为文件名 文件夹路径无前缀开头
|
|
228
|
+
* @param _path - 路径
|
|
229
|
+
*/
|
|
230
|
+
splitPath (_path) {
|
|
231
|
+
const list = _path.replace(/\\/g, '/').split('/')
|
|
232
|
+
const pop = list.pop() || ''
|
|
233
|
+
const dir = path.join(...list)
|
|
234
|
+
return { dir, pop }
|
|
235
|
+
}
|
|
236
|
+
|
|
184
237
|
/**
|
|
185
238
|
* 将文件转换为不带前缀的base64字符串
|
|
186
239
|
* @param file - 文件路径或Buffer对象、可读流对象、http地址、base64://字符串
|
|
@@ -297,10 +350,9 @@ export const common = new (class Common {
|
|
|
297
350
|
|
|
298
351
|
/**
|
|
299
352
|
* 制作简单转发,返回segment.node[]。仅简单包装node,也可以自己组装
|
|
300
|
-
* @param
|
|
353
|
+
* @param elements
|
|
301
354
|
* @param fakeUin 用户id
|
|
302
355
|
* @param fakeNick 用户昵称
|
|
303
|
-
* @return {Array<KarinNodeElement>}
|
|
304
356
|
*/
|
|
305
357
|
makeForward (elements, fakeUin, fakeNick) {
|
|
306
358
|
if (!Array.isArray(elements)) { elements = [elements] }
|
|
@@ -406,13 +458,15 @@ export const common = new (class Common {
|
|
|
406
458
|
logs.push(`[json:${val.data}]`)
|
|
407
459
|
break
|
|
408
460
|
case 'markdown': {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
461
|
+
logs.push(`[markdown:${val.content}]`)
|
|
462
|
+
break
|
|
463
|
+
}
|
|
464
|
+
case 'markdown_tpl': {
|
|
465
|
+
const params = val.params
|
|
466
|
+
if (!params) { break }
|
|
467
|
+
const content = { id: val.custom_template_id }
|
|
468
|
+
for (const v of params) { content[v.key] = v.values[0] }
|
|
469
|
+
logs.push(`[markdown_tpl:${JSON.stringify(content)}]`)
|
|
416
470
|
break
|
|
417
471
|
}
|
|
418
472
|
case 'rows': {
|
package/lib/utils/segment.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TextElement, AtElement, ImageElement, FaceElement, BubbleFaceElement, ReplyElement, VoiceElement, VideoElement, BasketballElement, DiceElement, RpsElement, PokeElement, MusicElement, WeatherElement, LocationElement, ShareElement, GiftElement, MarketFaceElement, ForwardElement, ContactElement, JsonElement, XmlElement, FileElement, ButtonElement, CustomMusicElemen, TemplateElement, ContentElement, KarinNodeElement, KarinElement } from '../types/index.js';
|
|
1
|
+
import { TextElement, AtElement, ImageElement, FaceElement, BubbleFaceElement, ReplyElement, VoiceElement, VideoElement, BasketballElement, DiceElement, RpsElement, PokeElement, MusicElement, WeatherElement, LocationElement, ShareElement, GiftElement, MarketFaceElement, ForwardElement, ContactElement, JsonElement, XmlElement, FileElement, ButtonElement, CustomMusicElemen, TemplateElement, ContentElement, KarinNodeElement, KarinElement, LongMsgElement } from '../types/index.js';
|
|
2
2
|
export declare const segment: {
|
|
3
3
|
/**
|
|
4
4
|
* 纯文本
|
|
@@ -78,7 +78,7 @@ export declare const segment: {
|
|
|
78
78
|
*/
|
|
79
79
|
record(file: string, magic?: boolean, md5?: string, name?: string): VoiceElement;
|
|
80
80
|
/**
|
|
81
|
-
* 语音
|
|
81
|
+
* 语音 即将废弃 请使用segment.record
|
|
82
82
|
* @param file - 语音URL或路径、Base64
|
|
83
83
|
* @param magic - 是否魔法语音,默认为 false
|
|
84
84
|
* @param md5 - 语音md5
|
|
@@ -241,21 +241,23 @@ export declare const segment: {
|
|
|
241
241
|
*/
|
|
242
242
|
md5?: string;
|
|
243
243
|
}): FileElement;
|
|
244
|
+
/**
|
|
245
|
+
* 长消息
|
|
246
|
+
* @param id - ID
|
|
247
|
+
*/
|
|
248
|
+
long_msg(id: string): LongMsgElement;
|
|
244
249
|
/**
|
|
245
250
|
* Markdown
|
|
246
251
|
* @param content - 原生markdown内容
|
|
247
|
-
* @
|
|
252
|
+
* @param config - 未知的参数
|
|
248
253
|
*/
|
|
249
|
-
markdown(content:
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
*/
|
|
257
|
-
values: Array<string>;
|
|
258
|
-
}>): ContentElement | TemplateElement;
|
|
254
|
+
markdown(content: ContentElement["content"], config?: ContentElement["config"]): ContentElement;
|
|
255
|
+
/**
|
|
256
|
+
* 构建模板Markdown
|
|
257
|
+
* @param custom_template_id - 模板ID
|
|
258
|
+
* @param params - 模板markdown参数
|
|
259
|
+
*/
|
|
260
|
+
markdown_tpl(custom_template_id: TemplateElement["custom_template_id"], params: TemplateElement["params"]): TemplateElement;
|
|
259
261
|
/**
|
|
260
262
|
* 按钮
|
|
261
263
|
* @param data - 按钮数据
|
package/lib/utils/segment.js
CHANGED
|
@@ -112,7 +112,7 @@ export const segment = new (class Segment {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
|
-
* 语音
|
|
115
|
+
* 语音 即将废弃 请使用segment.record
|
|
116
116
|
* @param file - 语音URL或路径、Base64
|
|
117
117
|
* @param magic - 是否魔法语音,默认为 false
|
|
118
118
|
* @param md5 - 语音md5
|
|
@@ -384,29 +384,47 @@ export const segment = new (class Segment {
|
|
|
384
384
|
}
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
+
/**
|
|
388
|
+
* 长消息
|
|
389
|
+
* @param id - ID
|
|
390
|
+
*/
|
|
391
|
+
long_msg (id) {
|
|
392
|
+
return {
|
|
393
|
+
type: 'long_msg',
|
|
394
|
+
id,
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
387
398
|
/**
|
|
388
399
|
* Markdown
|
|
389
400
|
* @param content - 原生markdown内容
|
|
390
|
-
* @
|
|
401
|
+
* @param config - 未知的参数
|
|
391
402
|
*/
|
|
392
|
-
markdown (
|
|
403
|
+
markdown (content, config) {
|
|
404
|
+
return {
|
|
405
|
+
type: 'markdown',
|
|
406
|
+
content,
|
|
407
|
+
config,
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* 构建模板Markdown
|
|
413
|
+
* @param custom_template_id - 模板ID
|
|
414
|
+
* @param params - 模板markdown参数
|
|
415
|
+
*/
|
|
416
|
+
markdown_tpl (
|
|
393
417
|
/**
|
|
394
|
-
* -
|
|
418
|
+
* - 模板ID
|
|
395
419
|
*/
|
|
396
|
-
|
|
420
|
+
custom_template_id,
|
|
397
421
|
/**
|
|
398
|
-
* - 模板markdown参数
|
|
399
|
-
*/
|
|
400
|
-
params
|
|
401
|
-
if (typeof content === 'string') {
|
|
402
|
-
return {
|
|
403
|
-
type: 'markdown',
|
|
404
|
-
content,
|
|
405
|
-
}
|
|
406
|
-
}
|
|
422
|
+
* - 模板markdown参数
|
|
423
|
+
*/
|
|
424
|
+
params) {
|
|
407
425
|
return {
|
|
408
|
-
type: '
|
|
409
|
-
custom_template_id
|
|
426
|
+
type: 'markdown_tpl',
|
|
427
|
+
custom_template_id,
|
|
410
428
|
params,
|
|
411
429
|
}
|
|
412
430
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-karin",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.13",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "基于 Kritor 进行开发的nodejs机器人框架",
|
|
6
6
|
"homepage": "https://github.com/KarinJS/Karin",
|
|
@@ -58,7 +58,6 @@
|
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@grpc/grpc-js": "1.10.10",
|
|
60
60
|
"@grpc/proto-loader": "0.7.13",
|
|
61
|
-
"@inquirer/prompts": "^5.0.7",
|
|
62
61
|
"art-template": "4.13.2",
|
|
63
62
|
"axios": "1.7.2",
|
|
64
63
|
"chalk": "5.3.0",
|