node-karin 0.2.1 → 0.3.0
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/core/listener.js +4 -4
- package/lib/core/plugin.d.ts +5 -5
- package/lib/core/plugin.js +3 -2
- package/lib/core/plugin.loader.d.ts +46 -84
- package/lib/core/plugin.loader.js +220 -244
- package/lib/core/server.js +1 -1
- package/lib/db/level.d.ts +1 -1
- package/lib/event/message.handler.js +3 -3
- package/lib/event/review.handler.d.ts +5 -5
- package/lib/index.d.ts +1 -7
- package/lib/index.js +5 -5
- package/lib/tools/init.js +1 -1
- package/lib/types/event.d.ts +13 -2
- package/lib/types/plugin.d.ts +7 -10
- package/lib/utils/button.d.ts +1 -47
- package/lib/utils/button.js +29 -73
- package/lib/utils/config.js +10 -10
- package/lib/utils/handler.d.ts +14 -51
- package/lib/utils/handler.js +60 -55
- package/package.json +4 -6
- /package/lib/{renderer → render}/app.d.ts +0 -0
- /package/lib/{renderer → render}/app.js +0 -0
- /package/lib/{renderer → render}/base.d.ts +0 -0
- /package/lib/{renderer → render}/base.js +0 -0
- /package/lib/{renderer → render}/client.d.ts +0 -0
- /package/lib/{renderer → render}/client.js +0 -0
- /package/lib/{renderer → render}/http.d.ts +0 -0
- /package/lib/{renderer → render}/http.js +0 -0
- /package/lib/{renderer → render}/index.d.ts +0 -0
- /package/lib/{renderer → render}/index.js +0 -0
- /package/lib/{renderer → render}/server.d.ts +0 -0
- /package/lib/{renderer → render}/server.js +0 -0
- /package/lib/{renderer → render}/wormhole.d.ts +0 -0
- /package/lib/{renderer → render}/wormhole.js +0 -0
|
@@ -1,21 +1,43 @@
|
|
|
1
1
|
import fs from 'fs'
|
|
2
2
|
import path from 'path'
|
|
3
3
|
import lodash from 'lodash'
|
|
4
|
+
import chokidar from 'chokidar'
|
|
4
5
|
import schedule from 'node-schedule'
|
|
5
6
|
import { listener } from './listener.js'
|
|
6
7
|
import PluginApp from './plugin.app.js'
|
|
7
|
-
import { render } from '../
|
|
8
|
-
import {
|
|
8
|
+
import { render } from '../render/index.js'
|
|
9
|
+
import { common, handler, logger } from '../utils/index.js'
|
|
9
10
|
/**
|
|
10
11
|
* 加载插件
|
|
11
12
|
*/
|
|
12
|
-
export const
|
|
13
|
+
export const pluginLoader = new (class PluginLoader {
|
|
13
14
|
dir
|
|
14
15
|
dirPath
|
|
16
|
+
/**
|
|
17
|
+
* - 插件索引ID
|
|
18
|
+
*/
|
|
19
|
+
index
|
|
20
|
+
/**
|
|
21
|
+
* - 命令插件索引列表
|
|
22
|
+
*/
|
|
23
|
+
ruleIds
|
|
24
|
+
buttonIds
|
|
25
|
+
/**
|
|
26
|
+
* - handler
|
|
27
|
+
*/
|
|
28
|
+
handlerIds
|
|
15
29
|
/**
|
|
16
30
|
* - 插件列表
|
|
17
31
|
*/
|
|
18
|
-
|
|
32
|
+
FileList
|
|
33
|
+
/**
|
|
34
|
+
* - 是否ts环境
|
|
35
|
+
*/
|
|
36
|
+
isTs
|
|
37
|
+
/**
|
|
38
|
+
* - 最终缓存的插件列表 通过index索引
|
|
39
|
+
*/
|
|
40
|
+
PluginList
|
|
19
41
|
/**
|
|
20
42
|
* - 定时任务
|
|
21
43
|
*/
|
|
@@ -28,59 +50,40 @@ export const PluginLoader = new (class PluginLoader {
|
|
|
28
50
|
* - 热更新列表
|
|
29
51
|
*/
|
|
30
52
|
watchList
|
|
31
|
-
/**
|
|
32
|
-
* - 插件索引ID
|
|
33
|
-
*/
|
|
34
|
-
index
|
|
35
|
-
/**
|
|
36
|
-
* - 命令插件索引列表
|
|
37
|
-
*/
|
|
38
|
-
rule
|
|
39
|
-
PluginList
|
|
40
53
|
constructor () {
|
|
54
|
+
this.index = 0
|
|
41
55
|
this.dir = './plugins'
|
|
42
56
|
this.dirPath = common.urlToPath(import.meta.url)
|
|
43
|
-
this.
|
|
44
|
-
this.task = []
|
|
57
|
+
this.isTs = process.env.karin_app_lang === 'ts'
|
|
45
58
|
this.watcher = new Map()
|
|
46
|
-
/** 热更新收集 */
|
|
47
59
|
this.watchList = []
|
|
48
|
-
this.
|
|
49
|
-
this.index = 0
|
|
60
|
+
this.FileList = []
|
|
50
61
|
this.PluginList = {}
|
|
62
|
+
this.task = []
|
|
63
|
+
this.ruleIds = []
|
|
64
|
+
this.buttonIds = []
|
|
65
|
+
this.handlerIds = {}
|
|
51
66
|
}
|
|
52
67
|
|
|
53
68
|
/**
|
|
54
69
|
* 插件初始化
|
|
55
70
|
*/
|
|
56
71
|
async load () {
|
|
57
|
-
|
|
58
|
-
listener.once('plugin.
|
|
59
|
-
for (const v of this.watchList) {
|
|
60
|
-
v.name ? this.watch(v.dir, v.name) : this.watchDir(v.dir)
|
|
61
|
-
}
|
|
72
|
+
this.getPlugins()
|
|
73
|
+
listener.once('plugin.watch', () => {
|
|
74
|
+
for (const v of this.watchList) { v.name ? this.watch(v.dir, v.name) : this.watchDir(v.dir) }
|
|
62
75
|
})
|
|
63
76
|
logger.info(logger.green('-----------'))
|
|
64
77
|
logger.info('加载插件中..')
|
|
65
78
|
/** 载入插件 */
|
|
66
|
-
const promises =
|
|
79
|
+
const promises = this.FileList.map(async ({ dir, name }) => await this.createdApp(dir, name, false))
|
|
67
80
|
/** 等待所有插件加载完成 */
|
|
68
81
|
await Promise.all(promises)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
logger.info(`[按钮][${button.Apps.length}个] 加载完成`)
|
|
75
|
-
logger.info(`[插件][${this.Apps.length}个] 加载完成`)
|
|
76
|
-
logger.info(`[渲染器][${render.Apps.length}个] 加载完成`)
|
|
77
|
-
logger.info(`[定时任务][${this.task.length}个] 加载完成`)
|
|
78
|
-
logger.info(`[Handler][Key:${handlerKeys.length}个][fnc:${handlerCount}个] 加载完成`)
|
|
79
|
-
logger.info(logger.green('-----------'))
|
|
80
|
-
logger.info(`Karin启动完成:耗时 ${logger.green(process.uptime().toFixed(2))} 秒...`)
|
|
81
|
-
/** 优先级排序 */
|
|
82
|
-
this.orderBy()
|
|
83
|
-
listener.emit('plugin.loader')
|
|
82
|
+
/** 释放缓存 */
|
|
83
|
+
this.FileList = []
|
|
84
|
+
/** 优先级排序并打印插件信息 */
|
|
85
|
+
this.orderBy(true)
|
|
86
|
+
listener.emit('plugin.watch')
|
|
84
87
|
return this
|
|
85
88
|
}
|
|
86
89
|
|
|
@@ -88,51 +91,69 @@ export const PluginLoader = new (class PluginLoader {
|
|
|
88
91
|
* 获取所有插件
|
|
89
92
|
*/
|
|
90
93
|
getPlugins () {
|
|
91
|
-
const Apps = []
|
|
92
94
|
/** 获取所有插件包 */
|
|
93
95
|
const plugins = common.getPlugins()
|
|
94
|
-
const isTs = process.env.karin_app_lang === 'ts'
|
|
95
96
|
for (const dir of plugins) {
|
|
96
97
|
/**
|
|
97
98
|
* - 插件包路径
|
|
98
99
|
* - 例如: ./plugins/karin-plugin-example
|
|
99
100
|
*/
|
|
100
101
|
const PluginPath = `${this.dir}/${dir}`
|
|
101
|
-
|
|
102
|
+
/**
|
|
103
|
+
* 一共3种模式
|
|
104
|
+
* 1. npm run dev 开发模式 直接加载ts,js文件,对于同时存在编译产物、源代码的情况,优先加载编译产物而不加载源代码
|
|
105
|
+
* 2. node . 生产模式 只加载js文件
|
|
106
|
+
* 3. npm run debug 调试模式 在2的基础上,对apps进行热更新
|
|
107
|
+
*/
|
|
108
|
+
/** 非插件包 加载该文件夹下全部js 视语言环境加载ts */
|
|
102
109
|
if (!common.isPlugin(PluginPath)) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
})
|
|
110
|
+
this.watchList.push({ dir })
|
|
111
|
+
const list = fs.readdirSync(`${this.dir}/${dir}`, { withFileTypes: true })
|
|
106
112
|
for (const file of list) {
|
|
107
113
|
/** 忽略不符合规则的文件 */
|
|
108
|
-
const ext = isTs ? ['.js', '.ts'] : ['.js']
|
|
114
|
+
const ext = this.isTs ? ['.js', '.ts'] : ['.js']
|
|
109
115
|
if (!ext.includes(path.extname(file.name))) { continue }
|
|
110
|
-
|
|
116
|
+
this.FileList.push({ dir, name: file.name })
|
|
111
117
|
}
|
|
118
|
+
continue
|
|
112
119
|
}
|
|
113
|
-
/**
|
|
114
|
-
|
|
115
|
-
|
|
120
|
+
/** 入口文件 */
|
|
121
|
+
const index = this.getIndex(PluginPath, process.env.karin_app_lang)
|
|
122
|
+
if (index) {
|
|
123
|
+
this.watchList.push({ dir, name: index })
|
|
124
|
+
this.FileList.push({ dir, name: index })
|
|
116
125
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
})
|
|
124
|
-
/** ts环境 */
|
|
125
|
-
if (isTs) {
|
|
126
|
-
if (common.exists(`${PluginPath}/index.ts`)) {
|
|
127
|
-
Apps.push({ dir, name: 'index.ts' })
|
|
126
|
+
/** ts环境 全部加载 如果存在编译产物 则不加载ts */
|
|
127
|
+
if (this.isTs) {
|
|
128
|
+
/** 编译产物 存在不加载ts */
|
|
129
|
+
if (common.exists(`${PluginPath}/dist/apps`)) {
|
|
130
|
+
this.getApps((`${dir}/dist/apps`), false)
|
|
131
|
+
continue
|
|
128
132
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
133
|
+
/** ts */
|
|
134
|
+
if (common.exists(`${PluginPath}/src/apps`)) {
|
|
135
|
+
this.getApps((`${dir}/src/apps`), true)
|
|
136
|
+
continue
|
|
132
137
|
}
|
|
133
138
|
}
|
|
139
|
+
/** js环境 */
|
|
140
|
+
if (common.isDir(`${PluginPath}/apps`)) { this.getApps(`${dir}/apps`, false) }
|
|
141
|
+
/** 这里需要判断下 不然ts环境下会重复加载 */
|
|
142
|
+
if (!this.isTs && common.isDir(`${PluginPath}/dist/apps`)) { this.getApps(`${dir}/dist/apps`, false) }
|
|
134
143
|
}
|
|
135
|
-
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* 传入路径 语言环境 返回加载index.ts 还是 index.js
|
|
148
|
+
* @param path - 插件路径
|
|
149
|
+
* @param lang - 语言环境
|
|
150
|
+
*/
|
|
151
|
+
getIndex (path, lang) {
|
|
152
|
+
const isJS = common.exists(`${path}/index.js`)
|
|
153
|
+
if (isJS && lang === 'js') { return 'index.js' }
|
|
154
|
+
const isTS = common.exists(`${path}/index.ts`)
|
|
155
|
+
if (isTS && lang === 'ts') { return 'index.ts' }
|
|
156
|
+
return false
|
|
136
157
|
}
|
|
137
158
|
|
|
138
159
|
/**
|
|
@@ -140,66 +161,49 @@ export const PluginLoader = new (class PluginLoader {
|
|
|
140
161
|
* @param dir - 插件包名称
|
|
141
162
|
* @param isTs - 是否获取ts插件
|
|
142
163
|
*/
|
|
143
|
-
getApps (dir, isTs
|
|
144
|
-
|
|
164
|
+
getApps (dir, isTs) {
|
|
165
|
+
this.watchList.push({ dir })
|
|
145
166
|
const ext = isTs ? ['.js', '.ts'] : ['.js']
|
|
146
167
|
const list = fs.readdirSync(`${this.dir}/${dir}`, { withFileTypes: true })
|
|
147
168
|
for (const file of list) {
|
|
148
|
-
// 获取后缀
|
|
149
169
|
const extname = path.extname(file.name)
|
|
150
170
|
if (!ext.includes(extname)) { continue }
|
|
151
|
-
|
|
171
|
+
this.FileList.push({ dir, name: file.name })
|
|
152
172
|
}
|
|
153
|
-
return info
|
|
154
173
|
}
|
|
155
174
|
|
|
156
175
|
/**
|
|
157
|
-
*
|
|
158
|
-
|
|
159
|
-
App (
|
|
160
|
-
/**
|
|
161
|
-
* - 插件Class 未实例化
|
|
162
|
-
*/
|
|
163
|
-
App,
|
|
164
|
-
/**
|
|
165
|
-
* - 插件实例化后的Class
|
|
166
|
-
*/
|
|
167
|
-
Class,
|
|
168
|
-
/**
|
|
169
|
-
* - 插件文件信息
|
|
176
|
+
* 排序并打印插件加兹安信息
|
|
177
|
+
* @param isPrint - 是否打印
|
|
170
178
|
*/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
name: Class.name,
|
|
177
|
-
desc: Class.dsc || Class.desc || Class.name,
|
|
178
|
-
event: Class.event || 'message',
|
|
179
|
-
priority: Class.priority ?? 5000,
|
|
180
|
-
accept: typeof Class.accept === 'function',
|
|
181
|
-
rule: Class.rule || [],
|
|
182
|
-
type: typeof App === 'function' ? 'function' : 'class',
|
|
183
|
-
task: Class.task || [],
|
|
184
|
-
handler: Class.handler || [],
|
|
185
|
-
button: Class.button || [],
|
|
186
|
-
}
|
|
187
|
-
/** 进一步处理rule */
|
|
188
|
-
info.rule.forEach((val, index) => {
|
|
189
|
-
info.rule[index].reg = new RegExp(val.reg)
|
|
190
|
-
info.rule[index].log = val.log === false ? (id, log) => logger.debug('mark', id, log) : (id, log) => logger.bot('mark', id, log)
|
|
191
|
-
})
|
|
192
|
-
return info
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/** 排序 */
|
|
196
|
-
orderBy () {
|
|
197
|
-
const list = []
|
|
179
|
+
orderBy (isPrint = false) {
|
|
180
|
+
let taskCount = 0
|
|
181
|
+
let handlerCount = 0
|
|
182
|
+
const rule = []
|
|
183
|
+
const button = []
|
|
198
184
|
Object.keys(this.PluginList).forEach(key => {
|
|
199
|
-
|
|
185
|
+
taskCount += this.PluginList[key].task.length
|
|
186
|
+
if (this.PluginList[key].rule.length) { rule.push({ key, val: this.PluginList[key].priority }) }
|
|
187
|
+
if (this.PluginList[key].button.length) { button.push({ key, val: this.PluginList[key].priority }) }
|
|
200
188
|
})
|
|
201
|
-
this.
|
|
189
|
+
this.ruleIds = lodash.orderBy(rule, ['val'], ['asc']).map((v) => Number(v.key))
|
|
202
190
|
logger.debug('rule排序完成...')
|
|
191
|
+
this.buttonIds = lodash.orderBy(button, ['val'], ['asc']).map((v) => Number(v.key))
|
|
192
|
+
logger.debug('button排序完成...')
|
|
193
|
+
if (!isPrint) { return }
|
|
194
|
+
const PluginListKeys = Object.keys(this.PluginList)
|
|
195
|
+
const handlerKeys = Object.keys(this.handlerIds)
|
|
196
|
+
handlerKeys.forEach((key) => {
|
|
197
|
+
handlerCount += this.handlerIds[key].length
|
|
198
|
+
})
|
|
199
|
+
logger.info(`[插件][${PluginListKeys.length}个] 加载完成`)
|
|
200
|
+
logger.info(`[渲染器][${render.Apps.length}个] 加载完成`)
|
|
201
|
+
logger.info(`[rule][${this.ruleIds.length}个] 加载完成`)
|
|
202
|
+
logger.info(`[button][${this.buttonIds.length}个] 加载完成`)
|
|
203
|
+
logger.info(`[定时任务][${taskCount}个] 加载完成`)
|
|
204
|
+
logger.info(`[Handler][Key:${handlerKeys.length}个][fnc:${handlerCount}个] 加载完成`)
|
|
205
|
+
logger.info(logger.green('-----------'))
|
|
206
|
+
logger.info(`Karin启动完成:耗时 ${logger.green(process.uptime().toFixed(2))} 秒...`)
|
|
203
207
|
}
|
|
204
208
|
|
|
205
209
|
/**
|
|
@@ -240,7 +244,7 @@ export const PluginLoader = new (class PluginLoader {
|
|
|
240
244
|
accept: Class.accept && typeof Class.accept === 'function',
|
|
241
245
|
})
|
|
242
246
|
/** 定时任务 */
|
|
243
|
-
lodash.forEach(Class.task,
|
|
247
|
+
lodash.forEach(Class.task, val => {
|
|
244
248
|
if (!val.name) { return logger.error(`[${dir}][${name}] 定时任务name错误`) }
|
|
245
249
|
if (!val.cron) { return logger.error(`[${dir}][${name}] 定时任务cron错误:${Class.name}`) }
|
|
246
250
|
info.task.push({
|
|
@@ -266,7 +270,7 @@ export const PluginLoader = new (class PluginLoader {
|
|
|
266
270
|
})
|
|
267
271
|
})
|
|
268
272
|
/** rule */
|
|
269
|
-
lodash.forEach(Class.rule,
|
|
273
|
+
lodash.forEach(Class.rule, val => {
|
|
270
274
|
if (!val.fnc) { return logger.error(`[${dir}][${name}] rule.fnc错误:${Class.name}`) }
|
|
271
275
|
info.rule.push({
|
|
272
276
|
reg: val.reg instanceof RegExp ? val.reg : new RegExp(val.reg),
|
|
@@ -276,6 +280,16 @@ export const PluginLoader = new (class PluginLoader {
|
|
|
276
280
|
log: val.log === false ? (id, log) => logger.debug('mark', id, log) : (id, log) => logger.bot('mark', id, log),
|
|
277
281
|
})
|
|
278
282
|
})
|
|
283
|
+
/** button */
|
|
284
|
+
lodash.forEach(Class.button, val => {
|
|
285
|
+
if (!val.fnc) { return logger.error(`[${dir}][${name}] rule.fnc错误:${Class.name}`) }
|
|
286
|
+
info.button.push({
|
|
287
|
+
reg: val.reg instanceof RegExp ? val.reg : new RegExp(val.reg),
|
|
288
|
+
fnc: val.fnc,
|
|
289
|
+
})
|
|
290
|
+
})
|
|
291
|
+
/** handler */
|
|
292
|
+
handler.add(index + '', Class)
|
|
279
293
|
/** 执行初始化 */
|
|
280
294
|
Class.init && Class.init()
|
|
281
295
|
this.PluginList[index] = info
|
|
@@ -284,9 +298,6 @@ export const PluginLoader = new (class PluginLoader {
|
|
|
284
298
|
// if (!lodash.isEmpty(Class.handler)) handler.add({ name, dir, App, Class })
|
|
285
299
|
/** 注册按钮 */
|
|
286
300
|
// if (!lodash.isEmpty(Class.button)) button.add({ name, dir, App, Class })
|
|
287
|
-
/** 收集插件 */
|
|
288
|
-
// const res = this.App(App, Class, { name, dir, path: `${dir}/${name}` })
|
|
289
|
-
// this.Apps.push(res)
|
|
290
301
|
return true
|
|
291
302
|
})
|
|
292
303
|
// rule收集并排序
|
|
@@ -314,45 +325,15 @@ export const PluginLoader = new (class PluginLoader {
|
|
|
314
325
|
* 卸载插件
|
|
315
326
|
*/
|
|
316
327
|
uninstallApp (dir, name) {
|
|
317
|
-
this.Apps = this.Apps.filter((v) => !(v.file.dir === dir && v.file.name === name))
|
|
318
|
-
this.uninstallTask(dir, name)
|
|
319
|
-
button.del(dir, name)
|
|
320
|
-
handler.del({ dir, name, key: '' })
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (val.schedule) { return }
|
|
327
|
-
val.log = val.log === false ? (log) => logger.debug(log) : (log) => logger.mark(log)
|
|
328
|
-
val.schedule = schedule.scheduleJob(val.cron, async () => {
|
|
329
|
-
try {
|
|
330
|
-
typeof val.log === 'function' && val.log(`[定时任务][${val.file.dir}][${val.name}] 开始执行`)
|
|
331
|
-
const App = new val.App()
|
|
332
|
-
await App[val.fnc]()
|
|
333
|
-
typeof val.log === 'function' && val.log(`[定时任务][${val.file.dir}][${val.name}] 执行完毕`)
|
|
334
|
-
} catch (error) {
|
|
335
|
-
logger.error(`[定时任务][${val.file.dir}][${val.name}] 执行报错`)
|
|
336
|
-
logger.error(error)
|
|
337
|
-
}
|
|
338
|
-
})
|
|
339
|
-
this.task[index] = val
|
|
340
|
-
})
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* 卸载定时任务
|
|
345
|
-
*/
|
|
346
|
-
uninstallTask (dir, name) {
|
|
347
|
-
this.task = this.task.filter((task) => {
|
|
348
|
-
if (task.file.dir === dir && task.file.name === name) {
|
|
349
|
-
/** 停止定时任务 */
|
|
350
|
-
task.schedule && task.schedule.cancel()
|
|
351
|
-
/** 移除定时任务 */
|
|
352
|
-
return false
|
|
353
|
-
}
|
|
354
|
-
/** 保留定时任务 */
|
|
355
|
-
return true
|
|
328
|
+
// this.Apps = this.Apps.filter((v) => !(v.file.dir === dir && v.file.name === name))
|
|
329
|
+
// this.uninstallTask(dir, name)
|
|
330
|
+
// button.del(dir, name)
|
|
331
|
+
// handler.del({ dir, name, key: '' })
|
|
332
|
+
Object.keys(this.PluginList).forEach(key => {
|
|
333
|
+
const info = this.PluginList[key]
|
|
334
|
+
/** 停止定时任务 */
|
|
335
|
+
info.task.forEach(val => val.schedule?.cancel())
|
|
336
|
+
info.file.dir === dir && info.file.name === name && delete this.PluginList[key]
|
|
356
337
|
})
|
|
357
338
|
}
|
|
358
339
|
|
|
@@ -360,99 +341,94 @@ export const PluginLoader = new (class PluginLoader {
|
|
|
360
341
|
* 监听单个文件热更新
|
|
361
342
|
*/
|
|
362
343
|
watch (dir, name) {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
344
|
+
if (this.watcher.get(`${dir}.${name}`)) { return }
|
|
345
|
+
const file = `./plugins/${dir}/${name}`
|
|
346
|
+
const watcher = chokidar.watch(file)
|
|
347
|
+
/** 监听修改 */
|
|
348
|
+
watcher.on('change', async () => {
|
|
349
|
+
/** 卸载 */
|
|
350
|
+
this.uninstallApp(dir, name)
|
|
351
|
+
/** 载入插件 */
|
|
352
|
+
const res = await this.createdApp(dir, name, true)
|
|
353
|
+
if (!res) { return }
|
|
354
|
+
logger.mark(`[修改插件][${dir}][${name}]`)
|
|
355
|
+
})
|
|
375
356
|
/** 监听删除 */
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
357
|
+
watcher.on('unlink', async () => {
|
|
358
|
+
/** 卸载 */
|
|
359
|
+
this.uninstallApp(dir, name)
|
|
360
|
+
this.watcher.delete(`${dir}.${name}`)
|
|
361
|
+
logger.mark(`[卸载插件][${dir}][${name}]`)
|
|
362
|
+
})
|
|
363
|
+
this.watcher.set(`${dir}.${name}`, watcher)
|
|
383
364
|
}
|
|
384
365
|
|
|
385
366
|
/**
|
|
386
367
|
* 监听文件夹更新
|
|
387
368
|
*/
|
|
388
|
-
watchDir (dir) {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
// }
|
|
453
|
-
// this.watcher.set(dir, watcher)
|
|
454
|
-
// return true
|
|
455
|
-
// })
|
|
456
|
-
// .catch(() => {})
|
|
369
|
+
async watchDir (dir) {
|
|
370
|
+
if (this.watcher.get(dir)) { return }
|
|
371
|
+
const file = `${this.dir}/${dir}/`
|
|
372
|
+
const watcher = chokidar.watch(file)
|
|
373
|
+
/** 热更新 */
|
|
374
|
+
setTimeout(() => {
|
|
375
|
+
/** 新增文件 */
|
|
376
|
+
watcher.on('add', async (filePath) => {
|
|
377
|
+
logger.debug(`[热更新][新增插件] ${filePath}`)
|
|
378
|
+
const name = path.basename(filePath)
|
|
379
|
+
/** js环境仅接受js ts接受两者 */
|
|
380
|
+
if (!this.isTs && !name.endsWith('.js')) { return }
|
|
381
|
+
if (this.isTs && !name.endsWith('.ts') && !name.endsWith('.js')) { return }
|
|
382
|
+
if (!fs.existsSync(`${file}/${name}`)) { return }
|
|
383
|
+
/** 载入插件 */
|
|
384
|
+
const res = await this.createdApp(dir, name, true)
|
|
385
|
+
if (!res) { return }
|
|
386
|
+
/** 延迟1秒 等待卸载完成 */
|
|
387
|
+
await common.sleep(1000)
|
|
388
|
+
/** 停止整个文件夹监听 */
|
|
389
|
+
watcher.close()
|
|
390
|
+
/** 新增插件之后重新监听文件夹 */
|
|
391
|
+
this.watcher.delete(dir)
|
|
392
|
+
this.watchDir(dir)
|
|
393
|
+
logger.mark(`[新增插件][${dir}][${name}]`)
|
|
394
|
+
return true
|
|
395
|
+
})
|
|
396
|
+
/** 监听修改 */
|
|
397
|
+
watcher.on('change', async (PluPath) => {
|
|
398
|
+
const name = path.basename(PluPath)
|
|
399
|
+
if (!name.endsWith('')) { return }
|
|
400
|
+
if (!fs.existsSync(`${this.dir}/${dir}/${name}`)) { return }
|
|
401
|
+
/** 卸载 */
|
|
402
|
+
this.uninstallApp(dir, name)
|
|
403
|
+
/** 载入插件 */
|
|
404
|
+
const res = await this.createdApp(dir, name, true)
|
|
405
|
+
if (!res) { return }
|
|
406
|
+
logger.mark(`[修改插件][${dir}][${name}]`)
|
|
407
|
+
})
|
|
408
|
+
/** 监听删除 */
|
|
409
|
+
watcher.on('unlink', async (PluPath) => {
|
|
410
|
+
const name = path.basename(PluPath)
|
|
411
|
+
if (!name.endsWith('')) { return }
|
|
412
|
+
/** 卸载 */
|
|
413
|
+
this.uninstallApp(dir, name)
|
|
414
|
+
/** 停止监听 */
|
|
415
|
+
watcher.close()
|
|
416
|
+
/** 重新监听文件夹 */
|
|
417
|
+
this.watcher.delete(dir)
|
|
418
|
+
this.watchDir(dir)
|
|
419
|
+
logger.mark(`[卸载插件][${dir}][${name}]`)
|
|
420
|
+
})
|
|
421
|
+
}, 500)
|
|
422
|
+
/** 生成随机数0.5-2秒 */
|
|
423
|
+
const random = Math.floor(Math.random() * 1000) + 500
|
|
424
|
+
await common.sleep(random)
|
|
425
|
+
const isExist = this.watcher.get(dir)
|
|
426
|
+
/** 这里需要检查一下是否已经存在,已经存在就关掉之前的监听 */
|
|
427
|
+
if (isExist) {
|
|
428
|
+
isExist.close()
|
|
429
|
+
this.watcher.delete(dir)
|
|
430
|
+
}
|
|
431
|
+
this.watcher.set(dir, watcher)
|
|
432
|
+
return true
|
|
457
433
|
}
|
|
458
434
|
})()
|
package/lib/core/server.js
CHANGED
|
@@ -5,7 +5,7 @@ import { WebSocketServer } from 'ws'
|
|
|
5
5
|
import { createServer } from 'http'
|
|
6
6
|
import express from 'express'
|
|
7
7
|
import { exec, config, logger, common } from '../utils/index.js'
|
|
8
|
-
import { render, HttpRenderer, Wormhole } from '../
|
|
8
|
+
import { render, HttpRenderer, Wormhole } from '../render/index.js'
|
|
9
9
|
export const server = new (class Server {
|
|
10
10
|
reg
|
|
11
11
|
list
|
package/lib/db/level.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import lodash from 'lodash'
|
|
|
2
2
|
import { review } from './review.handler.js'
|
|
3
3
|
import EventHandler from './event.handler.js'
|
|
4
4
|
import { logger, config } from '../utils/index.js'
|
|
5
|
-
import { listener, stateArr,
|
|
5
|
+
import { listener, stateArr, pluginLoader } from '../core/index.js'
|
|
6
6
|
/**
|
|
7
7
|
* 消息事件
|
|
8
8
|
*/
|
|
@@ -39,8 +39,8 @@ export class MessageHandler extends EventHandler {
|
|
|
39
39
|
/** 上下文 */
|
|
40
40
|
if (await this.context()) { return }
|
|
41
41
|
/* eslint-disable no-labels */
|
|
42
|
-
a: for (const index of
|
|
43
|
-
const app =
|
|
42
|
+
a: for (const index of pluginLoader.ruleIds) {
|
|
43
|
+
const app = pluginLoader.PluginList[index]
|
|
44
44
|
/** 判断事件 */
|
|
45
45
|
if (app.event && !this.filtEvent(app.event)) { continue }
|
|
46
46
|
/** 正则匹配 */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KarinMessage } from '../event/index.js';
|
|
2
|
-
import {
|
|
2
|
+
import { EType, PluginApps, GroupCfg } from '../types/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* 事件拦截器
|
|
5
5
|
* 利用可执行函数的特性,热更新所有拦截器
|
|
@@ -14,12 +14,12 @@ export declare const review: {
|
|
|
14
14
|
};
|
|
15
15
|
App: import("../types/index.js").App;
|
|
16
16
|
Config: import("../types/index.js").Config;
|
|
17
|
-
CD: (e:
|
|
17
|
+
CD: (e: EType, config: GroupCfg) => boolean;
|
|
18
18
|
mode: (e: KarinMessage, config: GroupCfg) => boolean;
|
|
19
19
|
alias: (e: KarinMessage, config: GroupCfg) => boolean;
|
|
20
|
-
GroupEnable: (e:
|
|
21
|
-
UserEnable: (e:
|
|
22
|
-
GroupMsgPrint: (e:
|
|
20
|
+
GroupEnable: (e: EType) => boolean;
|
|
21
|
+
UserEnable: (e: EType) => boolean;
|
|
22
|
+
GroupMsgPrint: (e: EType) => boolean;
|
|
23
23
|
PluginEnable: (app: PluginApps, config: GroupCfg) => boolean;
|
|
24
24
|
main(): void;
|
|
25
25
|
/**
|