node-karin 0.12.2 → 0.12.5

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 (40) hide show
  1. package/config/defSet/group.yaml +2 -2
  2. package/lib/adapter/onebot/11/convert.js +3 -0
  3. package/lib/adapter/onebot/11/event.js +28 -3
  4. package/lib/api/git.d.ts +6 -0
  5. package/lib/api/git.js +16 -0
  6. package/lib/api/npm.d.ts +7 -0
  7. package/lib/api/npm.js +63 -0
  8. package/lib/api/readJson.d.ts +5 -0
  9. package/lib/api/readJson.js +8 -0
  10. package/lib/cli/index.d.ts +0 -4
  11. package/lib/cli/index.js +6 -33
  12. package/lib/cli/start.js +3 -0
  13. package/lib/core/init/dir.d.ts +3 -3
  14. package/lib/core/init/dir.js +4 -4
  15. package/lib/core/init/init.js +1 -1
  16. package/lib/core/karin/karin.d.ts +2 -0
  17. package/lib/core/karin/karin.js +3 -0
  18. package/lib/core/listener/listener.js +26 -0
  19. package/lib/core/plugin/base.d.ts +10 -3
  20. package/lib/core/plugin/base.js +10 -3
  21. package/lib/core/plugin/loader.d.ts +10 -0
  22. package/lib/core/plugin/loader.js +16 -0
  23. package/lib/event/handler/message.d.ts +24 -0
  24. package/lib/event/handler/message.js +62 -16
  25. package/lib/event/handler/notice.js +1 -0
  26. package/lib/event/handler/request.js +1 -0
  27. package/lib/modules/commander.d.ts +0 -1
  28. package/lib/modules/commander.js +0 -1
  29. package/lib/types/element/element.d.ts +9 -2
  30. package/lib/types/event/event.d.ts +1 -1
  31. package/lib/types/onebot11/event.d.ts +36 -2
  32. package/lib/types/onebot11/event.js +0 -1
  33. package/lib/types/plugin/plugin.d.ts +37 -1
  34. package/lib/utils/common/common.js +7 -64
  35. package/lib/utils/config/config.d.ts +12 -26
  36. package/lib/utils/config/config.js +31 -29
  37. package/lib/utils/core/logger.js +2 -2
  38. package/lib/utils/core/segment.d.ts +6 -1
  39. package/lib/utils/core/segment.js +10 -0
  40. package/package.json +1 -1
@@ -18,7 +18,7 @@ default:
18
18
  disable: []
19
19
 
20
20
  # 单个Bot默认配置
21
- Bot.self_id:
21
+ Bot:self_id:
22
22
  # 群聊中所有消息冷却时间,单位秒,0则无限制
23
23
  GroupCD: 0
24
24
  # 群聊中 每个人的消息冷却时间,单位秒,0则无限制。注意,开启后所有消息都会进CD,无论是否触发插件。
@@ -37,7 +37,7 @@ Bot.self_id:
37
37
  disable: []
38
38
 
39
39
  # 单个Bot单个群配置
40
- Bot.self_id.group_id:
40
+ Bot:self_id:group_id:
41
41
  # 群聊中所有消息冷却时间,单位秒,0则无限制
42
42
  GroupCD: 0
43
43
  # 群聊中 每个人的消息冷却时间,单位秒,0则无限制。注意,开启后所有消息都会进CD,无论是否触发插件。
@@ -154,6 +154,9 @@ export function KarinConvertAdapter(data, bot) {
154
154
  elements.push({ type: 'weather', data: { city: i.city, type: i.type } });
155
155
  break;
156
156
  }
157
+ case 'raw':
158
+ elements.push(i.data);
159
+ break;
157
160
  case 'button':
158
161
  case 'markdown':
159
162
  case 'keyboard':
@@ -90,11 +90,12 @@ export class OB11Event {
90
90
  const time = data.time;
91
91
  const self_id = data.self_id + '';
92
92
  let notice = {};
93
- const user_id = data.user_id + '';
93
+ /** 别问为啥any... 我是any糕手~ */
94
+ const user_id = (data.user_id || data.operator_id) + '';
94
95
  const event_id = `notice.${time}`;
95
96
  const sender = {
96
- uid: data.user_id + '',
97
- uin: data.user_id + '',
97
+ uid: user_id,
98
+ uin: user_id,
98
99
  nick: '',
99
100
  role: "unknown" /* Role.Unknown */,
100
101
  };
@@ -351,6 +352,30 @@ export class OB11Event {
351
352
  notice = new KarinNotice(options);
352
353
  break;
353
354
  }
355
+ // Language表情动态上报
356
+ case 'reaction': {
357
+ const group_id = data.group_id + '';
358
+ const content = {
359
+ group_id,
360
+ message_id: data.message_id,
361
+ face_id: Number(data.code),
362
+ is_set: data.sub_type === 'add',
363
+ };
364
+ const options = {
365
+ raw_event: data,
366
+ time,
367
+ self_id,
368
+ user_id,
369
+ event_id,
370
+ sender,
371
+ contact,
372
+ content,
373
+ group_id,
374
+ sub_event: "group_message_reaction" /* NoticeSubType.GroupMessageReaction */,
375
+ };
376
+ notice = new KarinNotice(options);
377
+ break;
378
+ }
354
379
  default: {
355
380
  return this.adapter.logger('error', '未知通知事件:', JSON.stringify(data));
356
381
  }
@@ -0,0 +1,6 @@
1
+ import { dirName } from '../types/index.js';
2
+ /**
3
+ * 获取git插件列表
4
+ * @param isPack - 是否屏蔽不带package.json的插件,默认为false
5
+ */
6
+ export declare function getGitPlugins(isPack?: boolean): Array<dirName>;
package/lib/api/git.js ADDED
@@ -0,0 +1,16 @@
1
+ import fs from 'fs';
2
+ /**
3
+ * 获取git插件列表
4
+ * @param isPack - 是否屏蔽不带package.json的插件,默认为false
5
+ */
6
+ export function getGitPlugins(isPack = false) {
7
+ const dir = './plugins';
8
+ let list = fs.readdirSync(dir, { withFileTypes: true });
9
+ /** 忽略非文件夹、非 karin-plugin-开头的文件夹 */
10
+ list = list.filter(v => v.isDirectory() && v.name.startsWith('karin-plugin-'));
11
+ if (isPack)
12
+ list = list.filter(v => fs.existsSync(`${dir}/${v.name}/package.json`));
13
+ const arr = [];
14
+ list.map(v => arr.push(v.name));
15
+ return arr;
16
+ }
@@ -0,0 +1,7 @@
1
+ import { NpmInfo } from '../utils/index.js';
2
+ /**
3
+ * 获取npm插件列表
4
+ * @param showDetails - 是否返回详细信息
5
+ * 默认只返回插件npm包名,为true时返回详细的{dir, name}[]
6
+ */
7
+ export declare function getNpmPlugins<T extends boolean>(showDetails: T): Promise<T extends true ? NpmInfo[] : string[]>;
package/lib/api/npm.js ADDED
@@ -0,0 +1,63 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { readJson } from './readJson.js';
4
+ /**
5
+ * 获取npm插件列表
6
+ * @param showDetails - 是否返回详细信息
7
+ * 默认只返回插件npm包名,为true时返回详细的{dir, name}[]
8
+ */
9
+ export async function getNpmPlugins(showDetails) {
10
+ /** 屏蔽的依赖包列表 */
11
+ const exclude = ['art-template', 'axios', 'chalk', 'chokidar', 'commander', 'express', 'level', 'lodash', 'log4js', 'moment', 'node-karin', 'node-schedule', 'redis', 'ws', 'yaml'];
12
+ const pkg = readJson('./package.json');
13
+ const dependencies = Object.keys(pkg.dependencies).filter((name) => !exclude.includes(name));
14
+ if (!showDetails) {
15
+ const list = [];
16
+ const readPackageJson = async (name) => {
17
+ try {
18
+ const pkgPath = path.join(process.cwd(), 'node_modules', name, 'package.json');
19
+ const pkg = readJson(pkgPath);
20
+ if (pkg?.karin)
21
+ list.push(name);
22
+ }
23
+ catch (error) {
24
+ logger.error(`[common] 解析 package.json 时出错:${error.stack || error.message || JSON.stringify(error)}`);
25
+ }
26
+ };
27
+ await Promise.all(dependencies.map(readPackageJson));
28
+ return list;
29
+ }
30
+ const list = [];
31
+ /** 获取详细的npm信息 */
32
+ const readPackageJson = async (files) => {
33
+ try {
34
+ const root = path.join(process.cwd(), 'node_modules', files);
35
+ const pkgPath = path.join(root, 'package.json');
36
+ const pkg = readJson(pkgPath);
37
+ if (!pkg?.karin)
38
+ return;
39
+ if (pkg?.main) {
40
+ list.push({ plugin: files, path: path.dirname(pkg.main), file: path.basename(pkg.main), isMain: true });
41
+ }
42
+ if (pkg?.karin?.apps?.length) {
43
+ pkg.karin.apps.forEach((app) => {
44
+ if (!fs.existsSync(path.join(root, app))) {
45
+ logger.error(`[common] npm插件${files}的app目录${app}不存在 已跳过`);
46
+ return;
47
+ }
48
+ fs.readdirSync(path.join(root, app)).forEach((filename) => {
49
+ /** 忽略非js文件 npm包不考虑ts */
50
+ if (!filename.endsWith('.js'))
51
+ return;
52
+ list.push({ plugin: files, path: app, file: filename, isMain: false });
53
+ });
54
+ });
55
+ }
56
+ }
57
+ catch (error) {
58
+ logger.error(`[common] 获取npm插件列表时出错:${error.stack || error.message || JSON.stringify(error)}`);
59
+ }
60
+ };
61
+ await Promise.all(dependencies.map(readPackageJson));
62
+ return list;
63
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * - 解析json文件
3
+ * @param file - 文件路径
4
+ */
5
+ export declare function readJson(file: string): any;
@@ -0,0 +1,8 @@
1
+ import fs from 'fs';
2
+ /**
3
+ * - 解析json文件
4
+ * @param file - 文件路径
5
+ */
6
+ export function readJson(file) {
7
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
8
+ }
@@ -73,10 +73,6 @@ export declare class KarinCli {
73
73
  * @param pkg - 包管理器
74
74
  */
75
75
  getRemoteVersion(name: string, pkg: 'pnpm' | 'cnpm' | 'yarn' | 'npm'): Promise<string>;
76
- /**
77
- * 获取git插件列表
78
- */
79
- getGitPlugins(): Array<string>;
80
76
  /**
81
77
  * 封装exec
82
78
  * @param cmd - 命令
package/lib/cli/index.js CHANGED
@@ -5,6 +5,8 @@ import axios from 'axios';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { getRegistry } from './pkg.js';
7
7
  import { exec as execCmd, spawn } from 'child_process';
8
+ import { getNpmPlugins } from '../api/npm.js';
9
+ import { getGitPlugins } from '../api/git.js';
8
10
  export class KarinCli {
9
11
  child;
10
12
  filename;
@@ -123,7 +125,7 @@ export class KarinCli {
123
125
  const data = this.getConfigData('pm2');
124
126
  /** 修正入口文件路径 兼容0.6.28以前的版本 */
125
127
  if (!fs.existsSync('./src') && filePath === './config/config/pm2.yaml') {
126
- const script = './node_modules/node-karin/lib/index.js';
128
+ const script = './node_modules/node-karin/lib/cli/start.js';
127
129
  if (data.apps[0].script !== script) {
128
130
  data.apps[0].script = script;
129
131
  fs.writeFileSync(filePath, yaml.stringify(data));
@@ -169,24 +171,8 @@ export class KarinCli {
169
171
  * 更新依赖
170
172
  */
171
173
  async update() {
172
- /** 屏蔽的依赖包列表 */
173
- const pkgdependencies = [
174
- 'art-template',
175
- 'axios',
176
- 'chalk',
177
- 'chokidar',
178
- 'commander',
179
- 'express',
180
- 'level',
181
- 'lodash',
182
- 'log4js',
183
- 'moment',
184
- 'node-schedule',
185
- 'redis',
186
- 'ws',
187
- 'yaml',
188
- ];
189
- const list = Object.keys(this.pkg(false).dependencies).filter(key => !pkgdependencies.includes(key));
174
+ const list = await getNpmPlugins(false);
175
+ list.push('node-karin');
190
176
  /** 获取包管理器 */
191
177
  const pkg = getRegistry();
192
178
  const cmd = pkg === 'yarn' ? 'yarn upgrade' : `${pkg} update`;
@@ -210,7 +196,7 @@ export class KarinCli {
210
196
  }));
211
197
  console.log('[依赖更新] 所有npm依赖已更新完成~');
212
198
  console.log('[依赖更新] 开始更新git插件...');
213
- const gitList = this.getGitPlugins();
199
+ const gitList = getGitPlugins();
214
200
  if (!gitList.length)
215
201
  return console.log('[依赖更新] 没有git插件需要更新~');
216
202
  await Promise.all(gitList.map(async (item) => {
@@ -264,19 +250,6 @@ export class KarinCli {
264
250
  }
265
251
  return text.trim();
266
252
  }
267
- /**
268
- * 获取git插件列表
269
- */
270
- getGitPlugins() {
271
- const dir = path.resolve(process.cwd(), 'plugins');
272
- let list = fs.readdirSync(dir, { withFileTypes: true });
273
- /** 忽略非文件夹、非 karin-plugin-开头的文件夹 */
274
- list = list.filter(v => v.isDirectory() && v.name.startsWith('karin-plugin-'));
275
- list = list.filter(v => fs.existsSync(`${dir}/${v.name}/package.json`));
276
- const arr = [];
277
- list.map(v => arr.push(v.name));
278
- return arr;
279
- }
280
253
  /**
281
254
  * 封装exec
282
255
  * @param cmd - 命令
package/lib/cli/start.js CHANGED
@@ -1,5 +1,8 @@
1
1
  import { program } from 'commander';
2
2
  import { KarinCli } from './index.js';
3
+ /** 兼容node .启动方式 */
4
+ if (process.argv.length === 2)
5
+ process.argv.push('.');
3
6
  const karin = new KarinCli();
4
7
  program.version(karin.pkg(true).version, '-v, --version', '显示版本号');
5
8
  program.command('.').description('启动karin').action(() => karin.start("prod" /* Mode.Prod */, "js" /* Lang.Js */, "node" /* Runner.Node */));
@@ -1,4 +1,4 @@
1
- /**
2
- * - 获取当前npm包的根目录
3
- */
1
+ /** 获取当前npm包的根目录 */
4
2
  export declare const karinDir: string;
3
+ /** 当前是否处于npm包环境 否则代表处于开发环境 */
4
+ export declare const isPkg: boolean;
@@ -1,7 +1,7 @@
1
1
  import path from 'path';
2
2
  import { fileURLToPath } from 'url';
3
3
  const filename = fileURLToPath(import.meta.url);
4
- /**
5
- * - 获取当前npm包的根目录
6
- */
7
- export const karinDir = path.resolve(filename, '../../../../').replace(/\\/g, '/').replace(/\/$/, '');
4
+ /** 获取当前npm包的根目录 */
5
+ export const karinDir = path.resolve(filename, '../../../..').replace(/\/$/, '');
6
+ /** 当前是否处于npm包环境 否则代表处于开发环境 */
7
+ export const isPkg = karinDir.includes('node_modules');
@@ -1,4 +1,4 @@
1
- import { logger } from '../../utils/index.js';
1
+ import { logger } from '../../utils/core/logger.js';
2
2
  /**
3
3
  * 启动日志
4
4
  */
@@ -71,6 +71,8 @@ export interface OptionsElement extends OptionsCommand {
71
71
  }
72
72
  export declare class Karin extends Listeners {
73
73
  #private;
74
+ /** 存储器 由开发者自行调用 */
75
+ store: Map<any, any>;
74
76
  constructor();
75
77
  /**
76
78
  * @param reg - 正则表达式
@@ -9,9 +9,12 @@ import { Listeners } from '../listener/listener.js';
9
9
  export class Karin extends Listeners {
10
10
  /** 是否启动 */
11
11
  #start;
12
+ /** 存储器 由开发者自行调用 */
13
+ store;
12
14
  constructor() {
13
15
  super();
14
16
  this.#start = false;
17
+ this.store = new Map();
15
18
  this.run();
16
19
  }
17
20
  /**
@@ -49,6 +49,32 @@ export class Listeners extends EventEmitter {
49
49
  this.list.push({ index, type: data.type, bot: data.bot });
50
50
  logger.info(`[机器人][注册][${data.type}] ` + logger.green(`[account:${data.bot.account.uid || data.bot.account.uin}(${data.bot.account.name})]`));
51
51
  this.#online(data.bot.account.uid || data.bot.account.uin);
52
+ /** 对sendForwardMessage方法进行修改 添加中间键 */
53
+ const sendForwardMessage = data.bot.sendForwardMessage;
54
+ data.bot.sendForwardMessage = async (contact, elements) => {
55
+ for (const info of pluginLoader.use.forwardMsg) {
56
+ try {
57
+ let next = false;
58
+ let exit = false;
59
+ const nextFn = () => { next = true; };
60
+ const exitFn = () => { exit = true; };
61
+ await info.fn(contact, elements, nextFn, exitFn);
62
+ if (exit) {
63
+ const plugin = pluginLoader.plugin.get(info.key);
64
+ logger.debug(`[消息中间件][${plugin.plugin}][${plugin.file}] 主动操作退出`);
65
+ return { message_id: '' };
66
+ }
67
+ if (!next)
68
+ break;
69
+ }
70
+ catch (e) {
71
+ logger.error('[消息中间件] 调用失败,已跳过');
72
+ logger.error(e);
73
+ }
74
+ }
75
+ const result = await sendForwardMessage(contact, elements);
76
+ return result;
77
+ };
52
78
  logger.debug('注册', this.list);
53
79
  return index;
54
80
  }
@@ -110,11 +110,15 @@ export declare class Plugin implements PluginType {
110
110
  message_id: string;
111
111
  }>;
112
112
  /**
113
+ * - 已废弃 请使用karin.ctx
113
114
  * - 构建上下文键
115
+ * @deprecated
114
116
  */
115
117
  conKey(): string;
116
118
  /**
117
- * 设置上下文状态
119
+ * - 已废弃 请使用karin.ctx
120
+ * - 设置上下文状态
121
+ * @deprecated
118
122
  */
119
123
  setContext(
120
124
  /**
@@ -130,11 +134,14 @@ export declare class Plugin implements PluginType {
130
134
  */
131
135
  time?: number): void;
132
136
  /**
133
- * 获取上下文状态
137
+ * - 已废弃 请使用karin.ctx
138
+ * - 获取上下文状态
134
139
  */
135
140
  getContext(): stateArrType[string];
136
141
  /**
137
- * 清除上下文状态
142
+ * - 已废弃 请使用karin.ctx
143
+ * - 清除上下文状态
144
+ * @deprecated
138
145
  */
139
146
  finish(): void;
140
147
  e: EType<this>;
@@ -63,13 +63,17 @@ export class Plugin {
63
63
  return result;
64
64
  }
65
65
  /**
66
+ * - 已废弃 请使用karin.ctx
66
67
  * - 构建上下文键
68
+ * @deprecated
67
69
  */
68
70
  conKey() {
69
71
  return `${this.e.isGroup ? `${this.e.group_id}.` : ''}` + (this.userId || this.e.user_id);
70
72
  }
71
73
  /**
72
- * 设置上下文状态
74
+ * - 已废弃 请使用karin.ctx
75
+ * - 设置上下文状态
76
+ * @deprecated
73
77
  */
74
78
  setContext(
75
79
  /**
@@ -101,14 +105,17 @@ export class Plugin {
101
105
  }, time * 1000);
102
106
  }
103
107
  /**
104
- * 获取上下文状态
108
+ * - 已废弃 请使用karin.ctx
109
+ * - 获取上下文状态
105
110
  */
106
111
  getContext() {
107
112
  const key = this.conKey();
108
113
  return stateArr[key];
109
114
  }
110
115
  /**
111
- * 清除上下文状态
116
+ * - 已废弃 请使用karin.ctx
117
+ * - 清除上下文状态
118
+ * @deprecated
112
119
  */
113
120
  finish() {
114
121
  const key = this.conKey();
@@ -119,6 +119,10 @@ declare class PluginLoader {
119
119
  /**
120
120
  * 缓存插件
121
121
  * @param index - 插件索引
122
+ * @param plugin - 插件名称
123
+ * @param file - 插件文件
124
+ * @param info - 插件信息
125
+ * @param App - 插件类
122
126
  */
123
127
  cachePlugin(index: number, plugin: string, file: string, info: AppType, App?: any): Promise<boolean>;
124
128
  /**
@@ -127,10 +131,16 @@ declare class PluginLoader {
127
131
  printDependErr(): void;
128
132
  /**
129
133
  * 卸载插件
134
+ * @param plugin - 插件名称
135
+ * @param _path - 插件apps相对路径
136
+ * @param file - 插件文件名称
130
137
  */
131
138
  uninstallApp(plugin: string, _path: string, file: string): void;
132
139
  /**
133
140
  * 监听文件夹更新
141
+ * @param plugin - 插件名称
142
+ * @param _path - 插件apps相对路径
143
+ * @returns 是否成功
134
144
  */
135
145
  watchDir(plugin: string, _path: string): Promise<boolean>;
136
146
  }
@@ -55,6 +55,8 @@ class PluginLoader {
55
55
  recvMsg: [],
56
56
  replyMsg: [],
57
57
  sendMsg: [],
58
+ forwardMsg: [],
59
+ notFound: [],
58
60
  };
59
61
  this.ext = process.env.karin_app_lang === 'ts' ? ['.js', '.ts'] : ['.js'];
60
62
  this.index = 0;
@@ -289,6 +291,8 @@ class PluginLoader {
289
291
  this.use.recvMsg = lodash.orderBy(this.use.recvMsg, ['rank'], ['asc']);
290
292
  this.use.replyMsg = lodash.orderBy(this.use.replyMsg, ['rank'], ['asc']);
291
293
  this.use.sendMsg = lodash.orderBy(this.use.sendMsg, ['rank'], ['asc']);
294
+ this.use.forwardMsg = lodash.orderBy(this.use.forwardMsg, ['rank'], ['asc']);
295
+ this.use.notFound = lodash.orderBy(this.use.notFound, ['rank'], ['asc']);
292
296
  const handler = Object.keys(this.handler);
293
297
  handler.forEach(key => {
294
298
  this.handler[key] = lodash.orderBy(this.handler[key], ['rank'], ['asc']);
@@ -414,6 +418,10 @@ class PluginLoader {
414
418
  /**
415
419
  * 缓存插件
416
420
  * @param index - 插件索引
421
+ * @param plugin - 插件名称
422
+ * @param file - 插件文件
423
+ * @param info - 插件信息
424
+ * @param App - 插件类
417
425
  */
418
426
  async cachePlugin(index, plugin, file, info, App) {
419
427
  if (!info?.name) {
@@ -532,6 +540,9 @@ class PluginLoader {
532
540
  }
533
541
  /**
534
542
  * 卸载插件
543
+ * @param plugin - 插件名称
544
+ * @param _path - 插件apps相对路径
545
+ * @param file - 插件文件名称
535
546
  */
536
547
  uninstallApp(plugin, _path, file) {
537
548
  this.plugin.forEach((info, key) => {
@@ -544,6 +555,8 @@ class PluginLoader {
544
555
  this.use.recvMsg = this.use.recvMsg.filter(val => val.key !== key);
545
556
  this.use.replyMsg = this.use.replyMsg.filter(val => val.key !== key);
546
557
  this.use.sendMsg = this.use.sendMsg.filter(val => val.key !== key);
558
+ this.use.forwardMsg = this.use.forwardMsg.filter(val => val.key !== key);
559
+ this.use.notFound = this.use.notFound.filter(val => val.key !== key);
547
560
  /** 定时任务需要先停止 */
548
561
  this.task = this.task.filter(val => {
549
562
  if (val.key === key) {
@@ -570,6 +583,9 @@ class PluginLoader {
570
583
  }
571
584
  /**
572
585
  * 监听文件夹更新
586
+ * @param plugin - 插件名称
587
+ * @param _path - 插件apps相对路径
588
+ * @returns 是否成功
573
589
  */
574
590
  async watchDir(plugin, _path) {
575
591
  const root = path.join(this.dir, plugin, _path);
@@ -5,11 +5,22 @@ import { KarinMessageType } from '../../types/index.js';
5
5
  */
6
6
  export declare class MessageHandler extends EventBaseHandler {
7
7
  e: KarinMessageType;
8
+ /** 当前事件是否是上下文事件 */
9
+ isContext: boolean;
8
10
  constructor(e: KarinMessageType);
11
+ start(): Promise<void>;
9
12
  /**
10
13
  * 先对消息事件进行初始化
11
14
  */
12
15
  init(): void;
16
+ /**
17
+ * 开始中间件
18
+ */
19
+ startUse(): Promise<void>;
20
+ /**
21
+ * 结束中间件
22
+ */
23
+ endUse(): Promise<void>;
13
24
  /**
14
25
  * 响应模式检查 返回false表示未通过
15
26
  */
@@ -18,6 +29,19 @@ export declare class MessageHandler extends EventBaseHandler {
18
29
  * 处理消息
19
30
  */
20
31
  deal(): Promise<void>;
32
+ /**
33
+ * 获取下文
34
+ */
35
+ getContext(): {
36
+ type: "fnc";
37
+ fnc: Function;
38
+ } | {
39
+ type: "class";
40
+ fnc: import("../../core/index.js").Plugin;
41
+ name: string;
42
+ } | {
43
+ type: "ctx";
44
+ };
21
45
  /**
22
46
  * 处理上下文
23
47
  */
@@ -8,14 +8,22 @@ import { karin, stateArr, pluginLoader } from '../../core/index.js';
8
8
  */
9
9
  export class MessageHandler extends EventBaseHandler {
10
10
  e;
11
+ /** 当前事件是否是上下文事件 */
12
+ isContext;
11
13
  constructor(e) {
12
14
  super(e);
13
15
  this.e = e;
16
+ this.start();
17
+ this.isContext = !!this.getContext();
18
+ }
19
+ async start() {
14
20
  this.init();
15
- if (this.e.group_id) {
21
+ await this.startUse();
22
+ if (this.e.sub_event === "group_message" /* MessageSubType.GroupMessage */) {
16
23
  if (!this.getCd())
17
24
  return;
18
- if (!this.getMode())
25
+ /** 下文不走响应模式 */
26
+ if (!this.isContext && !this.getMode())
19
27
  return;
20
28
  if (!this.getGroupEnable())
21
29
  return;
@@ -26,6 +34,9 @@ export class MessageHandler extends EventBaseHandler {
26
34
  if (!this.private())
27
35
  return;
28
36
  }
37
+ /** 上下文 */
38
+ if (await this.context())
39
+ return;
29
40
  /** 处理消息 */
30
41
  this.deal();
31
42
  }
@@ -33,7 +44,7 @@ export class MessageHandler extends EventBaseHandler {
33
44
  * 先对消息事件进行初始化
34
45
  */
35
46
  init() {
36
- karin.emit('karin:count:recv', 1);
47
+ karin.emit('karin:count:recv', this.e);
37
48
  const logs = [];
38
49
  for (const val of this.e.elements) {
39
50
  switch (val.type) {
@@ -178,20 +189,35 @@ export class MessageHandler extends EventBaseHandler {
178
189
  karin.emit('message', this.e);
179
190
  }
180
191
  /**
181
- * 响应模式检查 返回false表示未通过
192
+ * 开始中间件
182
193
  */
183
- getMode() {
184
- if (review.mode(this.e, this.config))
185
- return true;
186
- logger.debug(`[消息拦截][${this.e.group_id}][${this.e.user_id}] 响应模式不匹配`);
187
- return false;
194
+ async startUse() {
195
+ for (const info of pluginLoader.use.recvMsg) {
196
+ try {
197
+ let next = false;
198
+ let exit = false;
199
+ const nextFn = () => { next = true; };
200
+ const exitFn = () => { exit = true; };
201
+ await info.fn(this.e, nextFn, exitFn);
202
+ if (exit) {
203
+ const plugin = pluginLoader.plugin.get(info.key);
204
+ logger.debug(`[消息中间件][${plugin.plugin}][${plugin.file}] 主动操作退出`);
205
+ return;
206
+ }
207
+ if (!next)
208
+ break;
209
+ }
210
+ catch (e) {
211
+ logger.error('[消息中间件] 调用失败,已跳过');
212
+ logger.error(e);
213
+ }
214
+ }
188
215
  }
189
216
  /**
190
- * 处理消息
217
+ * 结束中间件
191
218
  */
192
- async deal() {
193
- /** 先调用中间件 */
194
- for (const info of pluginLoader.use.recvMsg) {
219
+ async endUse() {
220
+ for (const info of pluginLoader.use.notFound) {
195
221
  try {
196
222
  let next = false;
197
223
  let exit = false;
@@ -211,9 +237,20 @@ export class MessageHandler extends EventBaseHandler {
211
237
  logger.error(e);
212
238
  }
213
239
  }
214
- /** 上下文 */
215
- if (await this.context())
216
- return;
240
+ }
241
+ /**
242
+ * 响应模式检查 返回false表示未通过
243
+ */
244
+ getMode() {
245
+ if (review.mode(this.e, this.config))
246
+ return true;
247
+ logger.debug(`[消息拦截][${this.e.group_id}][${this.e.user_id}] 响应模式不匹配`);
248
+ return false;
249
+ }
250
+ /**
251
+ * 处理消息
252
+ */
253
+ async deal() {
217
254
  const app = this.e.group_id
218
255
  ? (info) => review.PluginEnable(info, this.config)
219
256
  : () => true;
@@ -261,6 +298,15 @@ export class MessageHandler extends EventBaseHandler {
261
298
  }
262
299
  }
263
300
  }
301
+ logger.debug(`[事件处理][${this.e.self_id}][${this.e.user_id}][${this.e.event_id}] 未匹配到任何插件`);
302
+ await this.endUse();
303
+ }
304
+ /**
305
+ * 获取下文
306
+ */
307
+ getContext() {
308
+ const key = this.e.isGroup ? `${this.e.group_id}.${this.e.user_id}` : this.e.user_id;
309
+ return stateArr[key];
264
310
  }
265
311
  /**
266
312
  * 处理上下文
@@ -88,6 +88,7 @@ export class NoticeHandler extends EventBaseHandler {
88
88
  break;
89
89
  }
90
90
  }
91
+ logger.debug(`[事件处理][${this.e.self_id}][${this.e.user_id}][${this.e.event_id}] 未匹配到任何插件`);
91
92
  }
92
93
  /**
93
94
  * 构建原始消息
@@ -83,6 +83,7 @@ export class RequestHandler extends EventBaseHandler {
83
83
  break;
84
84
  }
85
85
  }
86
+ logger.debug(`[事件处理][${this.e.self_id}][${this.e.user_id}][${this.e.event_id}] 未匹配到任何插件`);
86
87
  }
87
88
  /**
88
89
  * 构建原始消息
@@ -1,2 +1 @@
1
1
  export * from 'commander';
2
- export { default } from 'commander';
@@ -1,2 +1 @@
1
1
  export * from 'commander';
2
- export { default } from 'commander';
@@ -1,4 +1,4 @@
1
- export type ElementType = 'text' | 'at' | 'face' | 'bubble_face' | 'reply' | 'image' | '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';
1
+ export type ElementType = 'text' | 'at' | 'face' | 'bubble_face' | 'reply' | 'image' | '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' | 'raw';
2
2
  export interface Element {
3
3
  /**
4
4
  * - 元素类型
@@ -552,7 +552,14 @@ export interface LongMsgElement extends Element {
552
552
  */
553
553
  id: string;
554
554
  }
555
- export type KarinElement = TextElement | AtElement | FaceElement | BubbleFaceElement | ReplyElement | ImageElement | VideoElement | BasketballElement | DiceElement | RpsElement | PokeElement | MusicElement | WeatherElement | LocationElement | ShareElement | GiftElement | MarketFaceElement | ForwardElement | ContactElement | JsonElement | XmlElement | FileElement | ButtonElement | KeyBoardElement | RecordElement | LongMsgElement | TplMarkdownElement | RawMarkdownElement;
555
+ /**
556
+ * 原生元素
557
+ */
558
+ export interface RawElement extends Element {
559
+ type: 'raw';
560
+ data: any;
561
+ }
562
+ export type KarinElement = TextElement | AtElement | FaceElement | BubbleFaceElement | ReplyElement | ImageElement | VideoElement | BasketballElement | DiceElement | RpsElement | PokeElement | MusicElement | WeatherElement | LocationElement | ShareElement | GiftElement | MarketFaceElement | ForwardElement | ContactElement | JsonElement | XmlElement | FileElement | ButtonElement | KeyBoardElement | RecordElement | LongMsgElement | TplMarkdownElement | RawMarkdownElement | RawElement;
556
563
  /**
557
564
  * - 构建自定义转发节点 此元素仅可通过专用接口发送 不支持混合发送
558
565
  */
@@ -240,7 +240,7 @@ export interface KarinEventType {
240
240
  /**
241
241
  * - 存储器 由开发者自行调用
242
242
  */
243
- store: Map<string, any>;
243
+ store: Map<any, any>;
244
244
  /**
245
245
  * - 原始消息
246
246
  */
@@ -162,7 +162,8 @@ export declare const enum OB11NoticeType {
162
162
  GroupRecall = "group_recall",
163
163
  FriendRecall = "friend_recall",
164
164
  Notify = "notify",
165
- GroupMsgEmojiLike = "group_msg_emoji_like"
165
+ GroupMsgEmojiLike = "group_msg_emoji_like",
166
+ GroupMsgEmojiLikeLagrange = "reaction"
166
167
  }
167
168
  /**
168
169
  * - 通知事件基类
@@ -476,6 +477,39 @@ export interface OneBot11GroupMessageReaction extends OneBot11Notice {
476
477
  emoji_id: number;
477
478
  }>;
478
479
  }
480
+ /**
481
+ * 群表情回应事件 Lagrange
482
+ */
483
+ export interface OneBot11GroupMessageReactionLagrange extends OneBot11Notice {
484
+ /**
485
+ * - 消息类型
486
+ */
487
+ notice_type: OB11NoticeType.GroupMsgEmojiLikeLagrange;
488
+ /**
489
+ * - 提示类型
490
+ */
491
+ sub_type: 'remove' | 'add';
492
+ /**
493
+ * - 群号
494
+ */
495
+ group_id: string;
496
+ /**
497
+ * - 发送者 QQ 号
498
+ */
499
+ operator_id: string;
500
+ /**
501
+ * - 消息 ID
502
+ */
503
+ message_id: string;
504
+ /**
505
+ * - 表情ID
506
+ */
507
+ code: string;
508
+ /**
509
+ * - 表情数量
510
+ */
511
+ count: number;
512
+ }
479
513
  /**
480
514
  * 请求事件类型
481
515
  */
@@ -593,7 +627,7 @@ export type OB11MessageEvent = OB11PrivateMessage | OB11GroupMessage;
593
627
  /**
594
628
  * 所有通知事件类型
595
629
  */
596
- export type OB11NoticeEvent = OneBot11GroupUpload | OneBot11GroupAdmin | OneBot11GroupDecrease | OneBot11GroupIncrease | OneBot11GroupBan | OneBot11FriendAdd | OneBot11GroupRecall | OneBot11FriendRecall | OneBot11Poke | OneBot11LuckyKing | OneBot11Honor | OneBot11GroupMessageReaction;
630
+ export type OB11NoticeEvent = OneBot11GroupUpload | OneBot11GroupAdmin | OneBot11GroupDecrease | OneBot11GroupIncrease | OneBot11GroupBan | OneBot11FriendAdd | OneBot11GroupRecall | OneBot11FriendRecall | OneBot11Poke | OneBot11LuckyKing | OneBot11Honor | OneBot11GroupMessageReaction | OneBot11GroupMessageReactionLagrange;
597
631
  /**
598
632
  * 所有请求事件类型
599
633
  */
@@ -1,2 +1 @@
1
- /* eslint-disable no-unused-vars */
2
1
  export {};
@@ -2,7 +2,7 @@ import schedule from 'node-schedule';
2
2
  import { Plugin } from '../../core/index.js';
3
3
  import { Reply, replyCallback, replyForward } from '../event/reply.js';
4
4
  import { KarinNoticeType, KarinRequestType, AllListenEvent, KarinMessageType, PermissionType, AllMessageSubType, Contact, AllNoticeSubType, AllRequestSubType } from '../event/index.js';
5
- import { KarinElement } from '../element/element.js';
5
+ import { KarinElement, NodeElement } from '../element/element.js';
6
6
  /**
7
7
  * - 插件根目录名称
8
8
  * - 例如: karin-plugin-example
@@ -203,6 +203,42 @@ export interface PluginMiddlewareInfoType {
203
203
  /** 优先级 */
204
204
  rank: number;
205
205
  }>;
206
+ /** 发送合并转发前 */
207
+ forwardMsg: Array<{
208
+ /** 插件基本信息的映射key */
209
+ key: number;
210
+ /** 插件包名称 */
211
+ name: string;
212
+ /** 插件执行方法 */
213
+ fn: (
214
+ /** 发送的目标信息 */
215
+ contact: Contact,
216
+ /** 发送的消息体 */
217
+ elements: Array<NodeElement>,
218
+ /** 是否继续执行下一个中间件 */
219
+ next: Function,
220
+ /** 是否不发送此条消息 */
221
+ exit: Function) => Promise<boolean>;
222
+ /** 优先级 */
223
+ rank: number;
224
+ }>;
225
+ /** 消息事件没有找到任何匹配的插件触发 */
226
+ notFound: Array<{
227
+ /** 插件基本信息的映射key */
228
+ key: number;
229
+ /** 插件包名称 */
230
+ name: string;
231
+ /** 插件执行方法 */
232
+ fn: (
233
+ /** 消息事件方法 */
234
+ e: KarinMessageType,
235
+ /** 是否继续执行下一个中间件 */
236
+ next: Function,
237
+ /** 是否退出此条消息 不再执行匹配插件 */
238
+ exit: Function) => Promise<boolean>;
239
+ /** 优先级 */
240
+ rank: number;
241
+ }>;
206
242
  }
207
243
  /**
208
244
  * 上下文状态
@@ -8,6 +8,9 @@ import { fileURLToPath } from 'url';
8
8
  import { createRequire } from 'module';
9
9
  import { pipeline, Readable } from 'stream';
10
10
  import { logger, segment, YamlEditor } from '../../utils/index.js';
11
+ import { readJson } from '../../api/readJson.js';
12
+ import { getNpmPlugins } from '../../api/npm.js';
13
+ import { getGitPlugins } from '../../api/git.js';
11
14
  /**
12
15
  * 常用方法
13
16
  */
@@ -153,7 +156,7 @@ export class Common {
153
156
  */
154
157
  readJson(file, isThrow = false) {
155
158
  try {
156
- return JSON.parse(fs.readFileSync(file, 'utf8'));
159
+ return readJson(file);
157
160
  }
158
161
  catch (error) {
159
162
  logger.debug(`[common][error] 读取json文件错误: ${file} ` + error);
@@ -414,22 +417,14 @@ export class Common {
414
417
  * @param isPack - 是否屏蔽不带package.json的插件,默认为false
415
418
  */
416
419
  getPlugins(isPack = false) {
417
- const dir = this.absPath('./plugins', false);
418
- let list = fs.readdirSync(dir, { withFileTypes: true });
419
- /** 忽略非文件夹、非 karin-plugin-开头的文件夹 */
420
- list = list.filter(v => v.isDirectory() && v.name.startsWith('karin-plugin-'));
421
- if (isPack)
422
- list = list.filter(v => fs.existsSync(`${dir}/${v.name}/package.json`));
423
- const arr = [];
424
- list.map(v => arr.push(v.name));
425
- return arr;
420
+ return this.getGitPlugins(isPack);
426
421
  }
427
422
  /**
428
423
  * 获取git插件列表
429
424
  * @param isPack - 是否屏蔽不带package.json的插件,默认为false
430
425
  */
431
426
  getGitPlugins(isPack = false) {
432
- return this.getPlugins(isPack);
427
+ return getGitPlugins(isPack);
433
428
  }
434
429
  /**
435
430
  * 获取npm插件列表
@@ -437,59 +432,7 @@ export class Common {
437
432
  * 默认只返回插件npm包名,为true时返回详细的{dir, name}[]
438
433
  */
439
434
  async getNpmPlugins(showDetails) {
440
- /** 屏蔽的依赖包列表 */
441
- const exclude = ['art-template', 'axios', 'chalk', 'chokidar', 'commander', 'express', 'level', 'lodash', 'log4js', 'moment', 'node-karin', 'node-schedule', 'redis', 'ws', 'yaml'];
442
- const pkg = this.readJson('./package.json');
443
- const dependencies = Object.keys(pkg.dependencies).filter((name) => !exclude.includes(name));
444
- if (!showDetails) {
445
- const list = [];
446
- const readPackageJson = async (name) => {
447
- try {
448
- const pkgPath = path.join(process.cwd(), 'node_modules', name, 'package.json');
449
- const pkg = this.readJson(pkgPath);
450
- if (pkg?.karin)
451
- list.push(name);
452
- }
453
- catch (error) {
454
- logger.error(`[common] 解析 package.json 时出错:${error.stack || error.message || JSON.stringify(error)}`);
455
- }
456
- };
457
- await Promise.all(dependencies.map(readPackageJson));
458
- return list;
459
- }
460
- const list = [];
461
- /** 获取详细的npm信息 */
462
- const readPackageJson = async (files) => {
463
- try {
464
- const root = path.join(process.cwd(), 'node_modules', files);
465
- const pkgPath = path.join(root, 'package.json');
466
- const pkg = this.readJson(pkgPath);
467
- if (!pkg?.karin)
468
- return;
469
- if (pkg?.main) {
470
- list.push({ plugin: files, path: path.dirname(pkg.main), file: path.basename(pkg.main), isMain: true });
471
- }
472
- if (pkg?.karin?.apps?.length) {
473
- pkg.karin.apps.forEach((app) => {
474
- if (!fs.existsSync(path.join(root, app))) {
475
- logger.error(`[common] npm插件${files}的app目录${app}不存在 已跳过`);
476
- return;
477
- }
478
- fs.readdirSync(path.join(root, app)).forEach((filename) => {
479
- /** 忽略非js文件 npm包不考虑ts */
480
- if (!filename.endsWith('.js'))
481
- return;
482
- list.push({ plugin: files, path: app, file: filename, isMain: false });
483
- });
484
- });
485
- }
486
- }
487
- catch (error) {
488
- logger.error(`[common] 获取npm插件列表时出错:${error.stack || error.message || JSON.stringify(error)}`);
489
- }
490
- };
491
- await Promise.all(dependencies.map(readPackageJson));
492
- return list;
435
+ return getNpmPlugins(showDetails);
493
436
  }
494
437
  /**
495
438
  * 获取运行时间
@@ -4,24 +4,17 @@ import { Redis, App, Config, Server, Package, GroupCfg, KarinEventTypes } from '
4
4
  * 配置文件
5
5
  */
6
6
  export declare const config: {
7
- /**
8
- * 运行目录绝对路径
9
- */
7
+ /** karin运行目录绝对路径 */
10
8
  dir: string;
11
- /**
12
- * 运行目录配置文件夹路径
13
- */
9
+ /** 用户生成配置目录 */
14
10
  cfgDir: string;
15
- /**
16
- * node-karin npm包路径
17
- */
18
- pkgDir: string;
19
- /**
20
- * node-karin 包配置文件夹路径
21
- */
11
+ /** 默认配置目录 */
22
12
  pkgCfgDir: string;
13
+ /** 缓存 */
23
14
  change: Map<string, any>;
15
+ /** 监听 */
24
16
  watcher: Map<string, any>;
17
+ /** 拦截器状态 */
25
18
  review: boolean;
26
19
  logger: Logger;
27
20
  /**
@@ -98,24 +91,17 @@ export declare const config: {
98
91
  "__#2@#review"(): Promise<void>;
99
92
  };
100
93
  export declare const Cfg: {
101
- /**
102
- * 运行目录绝对路径
103
- */
94
+ /** karin运行目录绝对路径 */
104
95
  dir: string;
105
- /**
106
- * 运行目录配置文件夹路径
107
- */
96
+ /** 用户生成配置目录 */
108
97
  cfgDir: string;
109
- /**
110
- * node-karin npm包路径
111
- */
112
- pkgDir: string;
113
- /**
114
- * node-karin 包配置文件夹路径
115
- */
98
+ /** 默认配置目录 */
116
99
  pkgCfgDir: string;
100
+ /** 缓存 */
117
101
  change: Map<string, any>;
102
+ /** 监听 */
118
103
  watcher: Map<string, any>;
104
+ /** 拦截器状态 */
119
105
  review: boolean;
120
106
  logger: Logger;
121
107
  /**
@@ -2,37 +2,29 @@ import fs from 'fs';
2
2
  import Yaml from 'yaml';
3
3
  import path from 'path';
4
4
  import chokidar from 'chokidar';
5
- import { karinDir } from '../../core/init/dir.js';
5
+ import { karinDir, isPkg } from '../../core/init/dir.js';
6
6
  import { common } from '../../utils/common/common.js';
7
7
  /**
8
8
  * 配置文件
9
9
  */
10
10
  export const config = new (class Cfg {
11
- /**
12
- * 运行目录绝对路径
13
- */
11
+ /** karin运行目录绝对路径 */
14
12
  dir;
15
- /**
16
- * 运行目录配置文件夹路径
17
- */
13
+ /** 用户生成配置目录 */
18
14
  cfgDir;
19
- /**
20
- * node-karin npm包路径
21
- */
22
- pkgDir;
23
- /**
24
- * node-karin 包配置文件夹路径
25
- */
15
+ /** 默认配置目录 */
26
16
  pkgCfgDir;
17
+ /** 缓存 */
27
18
  change;
19
+ /** 监听 */
28
20
  watcher;
21
+ /** 拦截器状态 */
29
22
  review;
30
23
  logger;
31
24
  constructor() {
32
25
  this.dir = process.cwd();
33
- this.pkgDir = karinDir;
34
26
  this.cfgDir = this.dir + '/config';
35
- this.pkgCfgDir = this.pkgDir + '/config/defSet';
27
+ this.pkgCfgDir = karinDir + '/config/defSet';
36
28
  /** 缓存 */
37
29
  this.change = new Map();
38
30
  /** 监听文件 */
@@ -52,7 +44,8 @@ export const config = new (class Cfg {
52
44
  this.cfgDir + '/plugin',
53
45
  ];
54
46
  list.forEach(path => this.mkdir(path));
55
- if (this.pkgCfgDir !== (this.cfgDir + '/defSet').replace(/\\/g, '/')) {
47
+ /** 拷贝默认配置文件 */
48
+ if (isPkg) {
56
49
  const files = fs.readdirSync(this.pkgCfgDir).filter(file => file.endsWith('.yaml'));
57
50
  files.forEach(file => {
58
51
  const path = `${this.cfgDir}/config/${file}`;
@@ -61,6 +54,15 @@ export const config = new (class Cfg {
61
54
  fs.copyFileSync(pathDef, path);
62
55
  });
63
56
  }
57
+ else {
58
+ const files = fs.readdirSync(this.cfgDir + '/defSet').filter(file => file.endsWith('.yaml'));
59
+ files.forEach(file => {
60
+ const path = `${this.cfgDir}/config/${file}`;
61
+ const pathDef = `${this.cfgDir}/defSet/${file}`;
62
+ if (!fs.existsSync(path))
63
+ fs.copyFileSync(pathDef, path);
64
+ });
65
+ }
64
66
  /** 为每个插件包创建统一存储的文件夹 */
65
67
  const plugins = await this.getPlugins();
66
68
  const DataList = [
@@ -172,20 +174,20 @@ export const config = new (class Cfg {
172
174
  const Config = {
173
175
  ...data,
174
176
  WhiteList: {
175
- users: data.WhiteList.users.map((i) => String(i)),
176
- groups: data.WhiteList.groups.map((i) => String(i)),
177
- GroupMsgLog: data.WhiteList.GroupMsgLog.map((i) => String(i)),
177
+ users: data?.WhiteList?.users?.map((i) => String(i)) || [],
178
+ groups: data?.WhiteList?.groups?.map((i) => String(i)) || [],
179
+ GroupMsgLog: data?.WhiteList?.GroupMsgLog?.map((i) => String(i)) || [],
178
180
  },
179
181
  BlackList: {
180
- users: data.BlackList.users.map((i) => String(i)),
181
- groups: data.BlackList.groups.map((i) => String(i)),
182
- GroupMsgLog: data.BlackList.GroupMsgLog.map((i) => String(i)),
182
+ users: data?.BlackList?.users?.map((i) => String(i)) || [],
183
+ groups: data?.BlackList?.groups?.map((i) => String(i)) || [],
184
+ GroupMsgLog: data?.BlackList?.GroupMsgLog?.map((i) => String(i)) || [],
183
185
  },
184
- master: data.master.map((i) => String(i)),
185
- admin: data.admin.map((i) => String(i)),
186
+ master: data?.master?.map((i) => String(i)) || [],
187
+ admin: data?.admin?.map((i) => String(i)) || [],
186
188
  private: {
187
- white_list: data.private.white_list.map((i) => String(i)),
188
- tips: data.private.tips,
189
+ white_list: data?.private?.white_list?.map((i) => String(i)) || [],
190
+ tips: data?.private?.tips || '',
189
191
  },
190
192
  };
191
193
  /** 缓存 */
@@ -214,7 +216,7 @@ export const config = new (class Cfg {
214
216
  * 实时获取packageon文件
215
217
  */
216
218
  get package() {
217
- const data = fs.readFileSync(this.pkgDir + '/package.json', 'utf8');
219
+ const data = fs.readFileSync(karinDir + '/package.json', 'utf8');
218
220
  const pack = JSON.parse(data);
219
221
  return pack;
220
222
  }
@@ -320,7 +322,7 @@ export const config = new (class Cfg {
320
322
  if (this.review)
321
323
  return;
322
324
  this.review = true;
323
- const { review } = await import('../../event/index.js');
325
+ const { review } = await import('../../event/handler/review.js');
324
326
  review.main();
325
327
  this.review = false;
326
328
  }
@@ -9,14 +9,14 @@ const { log_level, log_days_Keep, log4jsCfg } = config.Config;
9
9
  const level = log_level || log4jsCfg.level || 'info';
10
10
  const daysToKeep = log_days_Keep || log4jsCfg.daysToKeep || 7;
11
11
  const { overall, fragments, maxLogSize } = log4jsCfg;
12
- const defaultOptions = { appenders: ['console'], level, enableCallStack: process.env.KarinMode === 'dev' };
12
+ const defaultOptions = { appenders: ['console'], level, enableCallStack: process.env.karin_app_mode === 'dev' };
13
13
  const options = {
14
14
  appenders: {
15
15
  console: {
16
16
  type: 'console',
17
17
  layout: {
18
18
  type: 'pattern',
19
- pattern: `%[[Karin][%d{hh:mm:ss.SSS}][%4.4p]%] ${process.env.KarinMode === 'dev' ? '[%f{3}:%l] ' : ''}%m`,
19
+ pattern: `%[[Karin][%d{hh:mm:ss.SSS}][%4.4p]%] ${process.env.karin_app_mode === 'dev' ? '[%f{3}:%l] ' : ''}%m`,
20
20
  },
21
21
  },
22
22
  },
@@ -1,4 +1,4 @@
1
- import { TextElement, AtElement, ImageElement, FaceElement, BubbleFaceElement, ReplyElement, VideoElement, BasketballElement, DiceElement, RpsElement, PokeElement, MusicElement, WeatherElement, LocationElement, ShareElement, GiftElement, MarketFaceElement, ForwardElement, ContactElement, JsonElement, XmlElement, FileElement, ButtonElement, CustomMusicElemen, TplMarkdownElement, RawMarkdownElement, NodeElement, KarinElement, LongMsgElement, RecordElement, KeyBoardElement, Button } from '../../types/index.js';
1
+ import { TextElement, AtElement, ImageElement, FaceElement, BubbleFaceElement, ReplyElement, VideoElement, BasketballElement, DiceElement, RpsElement, PokeElement, MusicElement, WeatherElement, LocationElement, ShareElement, GiftElement, MarketFaceElement, ForwardElement, ContactElement, JsonElement, XmlElement, FileElement, ButtonElement, CustomMusicElemen, TplMarkdownElement, RawMarkdownElement, NodeElement, KarinElement, LongMsgElement, RecordElement, KeyBoardElement, Button, RawElement } from '../../types/index.js';
2
2
  export declare const segment: {
3
3
  /**
4
4
  * 纯文本
@@ -276,4 +276,9 @@ export declare const segment: {
276
276
  * @param content - 节点内容
277
277
  */
278
278
  node(user_id: string, nickname: string, content: KarinElement | Array<KarinElement>): NodeElement;
279
+ /**
280
+ * 发送原生格式给予适配器处理
281
+ * @param data - 原生数据
282
+ */
283
+ raw(data: any): RawElement;
279
284
  };
@@ -448,4 +448,14 @@ export const segment = new (class Segment {
448
448
  content,
449
449
  };
450
450
  }
451
+ /**
452
+ * 发送原生格式给予适配器处理
453
+ * @param data - 原生数据
454
+ */
455
+ raw(data) {
456
+ return {
457
+ type: 'raw',
458
+ data,
459
+ };
460
+ }
451
461
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-karin",
3
- "version": "0.12.2",
3
+ "version": "0.12.5",
4
4
  "private": false,
5
5
  "description": "基于 Kritor 进行开发的nodejs机器人框架",
6
6
  "homepage": "https://github.com/KarinJS/Karin",