node-karin 0.12.2 → 0.12.6
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/config/defSet/group.yaml +2 -2
- package/lib/adapter/onebot/11/convert.js +3 -0
- package/lib/adapter/onebot/11/event.js +28 -3
- package/lib/api/git.d.ts +6 -0
- package/lib/api/git.js +16 -0
- package/lib/api/npm.d.ts +7 -0
- package/lib/api/npm.js +63 -0
- package/lib/api/readJson.d.ts +5 -0
- package/lib/api/readJson.js +8 -0
- package/lib/cli/index.d.ts +0 -4
- package/lib/cli/index.js +6 -33
- package/lib/cli/start.js +3 -0
- package/lib/core/init/dir.d.ts +3 -3
- package/lib/core/init/dir.js +4 -4
- package/lib/core/init/init.js +1 -1
- package/lib/core/karin/karin.d.ts +2 -0
- package/lib/core/karin/karin.js +3 -0
- package/lib/core/listener/listener.js +26 -0
- package/lib/core/plugin/base.d.ts +10 -3
- package/lib/core/plugin/base.js +10 -3
- package/lib/core/plugin/loader.d.ts +10 -0
- package/lib/core/plugin/loader.js +16 -0
- package/lib/event/handler/message.d.ts +24 -0
- package/lib/event/handler/message.js +62 -16
- package/lib/event/handler/notice.js +1 -0
- package/lib/event/handler/request.js +1 -0
- package/lib/modules/commander.d.ts +0 -1
- package/lib/modules/commander.js +0 -1
- package/lib/types/element/element.d.ts +9 -2
- package/lib/types/event/event.d.ts +1 -1
- package/lib/types/onebot11/event.d.ts +36 -2
- package/lib/types/onebot11/event.js +0 -1
- package/lib/types/plugin/plugin.d.ts +37 -1
- package/lib/utils/common/common.js +7 -64
- package/lib/utils/config/config.d.ts +12 -26
- package/lib/utils/config/config.js +32 -30
- package/lib/utils/core/logger.js +2 -2
- package/lib/utils/core/segment.d.ts +6 -1
- package/lib/utils/core/segment.js +10 -0
- package/package.json +1 -1
package/config/defSet/group.yaml
CHANGED
|
@@ -18,7 +18,7 @@ default:
|
|
|
18
18
|
disable: []
|
|
19
19
|
|
|
20
20
|
# 单个Bot默认配置
|
|
21
|
-
Bot
|
|
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
|
|
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
|
-
|
|
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:
|
|
97
|
-
uin:
|
|
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
|
}
|
package/lib/api/git.d.ts
ADDED
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
|
+
}
|
package/lib/api/npm.d.ts
ADDED
|
@@ -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
|
+
}
|
package/lib/cli/index.d.ts
CHANGED
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/
|
|
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
|
-
|
|
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 =
|
|
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 */));
|
package/lib/core/init/dir.d.ts
CHANGED
package/lib/core/init/dir.js
CHANGED
|
@@ -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
|
-
|
|
6
|
-
*/
|
|
7
|
-
export const
|
|
4
|
+
/** 获取当前npm包的根目录 */
|
|
5
|
+
export const karinDir = path.resolve(filename, '../../../..').replace(/\/$/, '');
|
|
6
|
+
/** 当前是否处于npm包环境 否则代表处于开发环境 */
|
|
7
|
+
export const isPkg = karinDir.includes('node_modules');
|
package/lib/core/init/init.js
CHANGED
package/lib/core/karin/karin.js
CHANGED
|
@@ -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>;
|
package/lib/core/plugin/base.js
CHANGED
|
@@ -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
|
-
|
|
21
|
+
await this.startUse();
|
|
22
|
+
if (this.e.sub_event === "group_message" /* MessageSubType.GroupMessage */) {
|
|
16
23
|
if (!this.getCd())
|
|
17
24
|
return;
|
|
18
|
-
|
|
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',
|
|
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
|
-
*
|
|
192
|
+
* 开始中间件
|
|
182
193
|
*/
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
|
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
|
-
|
|
216
|
-
|
|
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
|
* 处理上下文
|
package/lib/modules/commander.js
CHANGED
|
@@ -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
|
-
|
|
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
|
*/
|
|
@@ -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
|
*/
|
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
|
176
|
-
groups: data
|
|
177
|
-
GroupMsgLog: data
|
|
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
|
|
181
|
-
groups: data
|
|
182
|
-
GroupMsgLog: data
|
|
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
|
|
185
|
-
admin: data
|
|
186
|
+
master: data?.master?.map((i) => String(i)) || [],
|
|
187
|
+
admin: data?.admin?.map((i) => String(i)) || [],
|
|
186
188
|
private: {
|
|
187
|
-
white_list: data
|
|
188
|
-
tips: data
|
|
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(
|
|
219
|
+
const data = fs.readFileSync(karinDir + '/package.json', 'utf8');
|
|
218
220
|
const pack = JSON.parse(data);
|
|
219
221
|
return pack;
|
|
220
222
|
}
|
|
@@ -227,7 +229,7 @@ export const config = new (class Cfg {
|
|
|
227
229
|
const key = 'change.group';
|
|
228
230
|
/** 取缓存 */
|
|
229
231
|
const res = this.change.get(key);
|
|
230
|
-
const keys = e?.self_id ? [`Bot
|
|
232
|
+
const keys = e?.self_id ? [`Bot:${e.self_id}:${group_id}`, `Bot:${e.self_id}`, group_id] : [group_id];
|
|
231
233
|
if (res) {
|
|
232
234
|
const cfg = { ...res.defCfg.default, ...res.Config.default };
|
|
233
235
|
for (const k of keys) {
|
|
@@ -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/
|
|
325
|
+
const { review } = await import('../../event/handler/review.js');
|
|
324
326
|
review.main();
|
|
325
327
|
this.review = false;
|
|
326
328
|
}
|
package/lib/utils/core/logger.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
};
|