node-karin 0.10.0 → 0.10.2
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 +40 -2
- package/lib/adapter/onebot/11/index.js +1 -1
- package/lib/cli/init.js +1 -1
- package/lib/cli/karin.js +1 -1
- package/lib/core/index.d.ts +9 -9
- package/lib/core/index.js +9 -9
- package/lib/core/init/dir.js +7 -0
- package/lib/core/init/init.js +46 -0
- package/lib/core/{karin.d.ts → karin/karin.d.ts} +1 -1
- package/lib/core/karin/karin.js +194 -0
- package/lib/core/{listener.d.ts → listener/listener.d.ts} +1 -1
- package/lib/core/listener/listener.js +213 -0
- package/lib/core/{plugin.app.d.ts → plugin/app.d.ts} +1 -1
- package/lib/core/plugin/app.js +19 -0
- package/lib/core/{plugin.d.ts → plugin/base.d.ts} +1 -1
- package/lib/core/plugin/base.js +140 -0
- package/lib/core/{plugin.loader.d.ts → plugin/loader.d.ts} +3 -3
- package/lib/core/plugin/loader.js +579 -0
- package/lib/core/process/process.js +100 -0
- package/lib/core/server/server.js +283 -0
- package/lib/db/index.d.ts +2 -2
- package/lib/db/index.js +2 -2
- package/lib/db/level/level.js +36 -0
- package/lib/db/redis/redis.js +135 -0
- package/lib/db/redis/redis_level.js +287 -0
- package/lib/event/{event.handler.d.ts → handler/base.d.ts} +2 -2
- package/lib/event/handler/base.js +173 -0
- package/lib/event/{message.handler.d.ts → handler/message.d.ts} +3 -3
- package/lib/event/handler/message.js +270 -0
- package/lib/event/{notice.handler.d.ts → handler/notice.d.ts} +3 -3
- package/lib/event/handler/notice.js +212 -0
- package/lib/event/{request.handler.d.ts → handler/request.d.ts} +3 -3
- package/lib/event/handler/request.js +118 -0
- package/lib/event/{review.handler.d.ts → handler/review.d.ts} +3 -3
- package/lib/event/handler/review.js +391 -0
- package/lib/event/index.d.ts +5 -5
- package/lib/event/index.js +5 -5
- package/lib/render/base.d.ts +1 -1
- package/lib/render/client.d.ts +1 -1
- package/lib/render/client.js +2 -12
- package/lib/render/client_even.d.ts +1 -1
- package/lib/render/client_even.js +2 -12
- package/lib/render/http.d.ts +1 -1
- package/lib/render/http.js +1 -1
- package/lib/render/server.js +1 -1
- package/lib/types/adapter/{adapter.d.ts → base.d.ts} +2 -2
- package/lib/types/config/config.js +1 -0
- package/lib/types/element/element.js +1 -0
- package/lib/types/event/message.d.ts +1 -1
- package/lib/types/event/reply.d.ts +1 -1
- package/lib/types/index.d.ts +6 -6
- package/lib/types/index.js +6 -6
- package/lib/types/logger/logger.js +1 -0
- package/lib/types/{plugin.d.ts → plugin/plugin.d.ts} +3 -3
- package/lib/types/plugin/plugin.js +1 -0
- package/lib/types/render/render.js +1 -0
- package/lib/utils/{common.d.ts → common/common.d.ts} +1 -1
- package/lib/utils/common/common.js +591 -0
- package/lib/utils/{config.d.ts → config/config.d.ts} +37 -19
- package/lib/utils/config/config.js +328 -0
- package/lib/utils/config/updateVersion.js +145 -0
- package/lib/utils/config/yamlEditor.js +292 -0
- package/lib/utils/{handler.d.ts → core/handler.d.ts} +1 -1
- package/lib/utils/core/handler.js +115 -0
- package/lib/utils/core/init.js +213 -0
- package/lib/utils/core/logger.js +105 -0
- package/lib/utils/{segment.d.ts → core/segment.d.ts} +1 -1
- package/lib/utils/core/segment.js +441 -0
- package/lib/utils/index.d.ts +11 -11
- package/lib/utils/index.js +11 -11
- package/lib/utils/{button.d.ts → tools/button.d.ts} +1 -1
- package/lib/utils/tools/button.js +38 -0
- package/lib/utils/tools/exec.js +37 -0
- package/lib/utils/tools/ffmpeg.js +25 -0
- package/lib/utils/tools/update.js +139 -0
- package/package.json +1 -1
- package/lib/core/dir.js +0 -7
- package/lib/core/init.js +0 -42
- package/lib/core/karin.js +0 -194
- package/lib/core/listener.js +0 -217
- package/lib/core/plugin.app.js +0 -19
- package/lib/core/plugin.js +0 -145
- package/lib/core/plugin.loader.js +0 -561
- package/lib/core/process.js +0 -98
- package/lib/core/server.js +0 -269
- package/lib/db/level.js +0 -37
- package/lib/db/redis.js +0 -134
- package/lib/db/redis_level.js +0 -293
- package/lib/event/event.handler.js +0 -167
- package/lib/event/message.handler.js +0 -254
- package/lib/event/notice.handler.js +0 -204
- package/lib/event/request.handler.js +0 -110
- package/lib/event/review.handler.js +0 -387
- package/lib/types/config.js +0 -1
- package/lib/types/element.js +0 -1
- package/lib/types/logger.js +0 -1
- package/lib/types/plugin.js +0 -1
- package/lib/types/render.js +0 -1
- package/lib/utils/button.js +0 -34
- package/lib/utils/common.js +0 -572
- package/lib/utils/config.js +0 -318
- package/lib/utils/exec.js +0 -36
- package/lib/utils/ffmpeg.js +0 -25
- package/lib/utils/handler.js +0 -109
- package/lib/utils/init.js +0 -208
- package/lib/utils/logger.js +0 -104
- package/lib/utils/segment.js +0 -470
- package/lib/utils/update.js +0 -135
- package/lib/utils/updateVersion.js +0 -145
- package/lib/utils/yamlEditor.js +0 -279
- /package/lib/core/{dir.d.ts → init/dir.d.ts} +0 -0
- /package/lib/core/{init.d.ts → init/init.d.ts} +0 -0
- /package/lib/core/{process.d.ts → process/process.d.ts} +0 -0
- /package/lib/core/{server.d.ts → server/server.d.ts} +0 -0
- /package/lib/db/{level.d.ts → level/level.d.ts} +0 -0
- /package/lib/db/{redis.d.ts → redis/redis.d.ts} +0 -0
- /package/lib/db/{redis_level.d.ts → redis/redis_level.d.ts} +0 -0
- /package/lib/types/adapter/{adapter.js → base.js} +0 -0
- /package/lib/types/{config.d.ts → config/config.d.ts} +0 -0
- /package/lib/types/{element.d.ts → element/element.d.ts} +0 -0
- /package/lib/types/{logger.d.ts → logger/logger.d.ts} +0 -0
- /package/lib/types/{render.d.ts → render/render.d.ts} +0 -0
- /package/lib/utils/{updateVersion.d.ts → config/updateVersion.d.ts} +0 -0
- /package/lib/utils/{yamlEditor.d.ts → config/yamlEditor.d.ts} +0 -0
- /package/lib/utils/{init.d.ts → core/init.d.ts} +0 -0
- /package/lib/utils/{logger.d.ts → core/logger.d.ts} +0 -0
- /package/lib/utils/{exec.d.ts → tools/exec.d.ts} +0 -0
- /package/lib/utils/{ffmpeg.d.ts → tools/ffmpeg.d.ts} +0 -0
- /package/lib/utils/{update.d.ts → tools/update.d.ts} +0 -0
package/lib/core/process.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { listener } from './listener.js'
|
|
2
|
-
import { logger, common, config } from '../utils/index.js'
|
|
3
|
-
/**
|
|
4
|
-
* 处理基本事件
|
|
5
|
-
*/
|
|
6
|
-
export default class Process {
|
|
7
|
-
/**
|
|
8
|
-
* 进程初始化
|
|
9
|
-
*/
|
|
10
|
-
static async process () {
|
|
11
|
-
/**
|
|
12
|
-
* 监听挂起信号 在终端关闭时触发
|
|
13
|
-
*/
|
|
14
|
-
process.once('SIGHUP', async (code) => await this.exit(code))
|
|
15
|
-
/**
|
|
16
|
-
* 监听中断信号 用户按下 Ctrl + C 时触发
|
|
17
|
-
*/
|
|
18
|
-
process.once('SIGINT', async (code) => await this.exit(code))
|
|
19
|
-
/**
|
|
20
|
-
* 监听终止信号 程序正常退出时触发
|
|
21
|
-
*/
|
|
22
|
-
process.once('SIGTERM', async (code) => await this.exit(code))
|
|
23
|
-
/**
|
|
24
|
-
* 监听退出信号 windows下程序正常退出时触发
|
|
25
|
-
*/
|
|
26
|
-
process.once('SIGBREAK', async (code) => await this.exit(code))
|
|
27
|
-
/**
|
|
28
|
-
* 监听退出信号 与 SIGINT 类似,但会生成核心转储
|
|
29
|
-
*/
|
|
30
|
-
process.once('SIGQUIT', async (code) => await this.exit(code))
|
|
31
|
-
/**
|
|
32
|
-
* 监听退出信号 Node.js进程退出时触发
|
|
33
|
-
*/
|
|
34
|
-
process.once('exit', async (code) => await this.exit(code))
|
|
35
|
-
/**
|
|
36
|
-
* 捕获警告
|
|
37
|
-
*/
|
|
38
|
-
process.on('warning', warning => listener.emit('warn', warning))
|
|
39
|
-
/**
|
|
40
|
-
* 捕获错误
|
|
41
|
-
*/
|
|
42
|
-
process.on('uncaughtException', error => listener.emit('error', error))
|
|
43
|
-
/**
|
|
44
|
-
* 捕获未处理的Promise错误
|
|
45
|
-
*/
|
|
46
|
-
process.on('unhandledRejection', error => listener.emit('error', error))
|
|
47
|
-
return this
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* 检查后台进程
|
|
52
|
-
*/
|
|
53
|
-
static async check () {
|
|
54
|
-
const host = `http://127.0.0.1:${config.Server.http.port}/api`
|
|
55
|
-
/**
|
|
56
|
-
* 使用api来检查后台
|
|
57
|
-
*/
|
|
58
|
-
const res = await common.axios(host + '/ping', 'get', { timeout: 100 })
|
|
59
|
-
if (!res) { return this }
|
|
60
|
-
logger.mark(logger.red('检测到后台进程 正在关闭'))
|
|
61
|
-
/** 发退出信号 */
|
|
62
|
-
await common.axios(host + '/exit', 'get', { timeout: 10 })
|
|
63
|
-
for (let i = 0; i < 50; i++) {
|
|
64
|
-
const res = await common.axios(host + '/ping', 'get', { timeout: 100 })
|
|
65
|
-
/** 请求成功继续循环 */
|
|
66
|
-
if (res) { continue }
|
|
67
|
-
/** 请求异常即代表后台进程已关闭 */
|
|
68
|
-
logger.mark(logger.green('后台进程已关闭'))
|
|
69
|
-
return this
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* 走到这里说明后台关闭失败
|
|
73
|
-
* 根据配置文件判断是否继续
|
|
74
|
-
*/
|
|
75
|
-
logger.error(logger.red(`后台进程关闭失败,请检查是否有进程正在占用端口${config.Server.http.port}`))
|
|
76
|
-
if (!config.Config.multi_progress) {
|
|
77
|
-
logger.error(logger.red('当前配置不允许多进程运行,程序即将退出'))
|
|
78
|
-
await this.exit(1)
|
|
79
|
-
}
|
|
80
|
-
logger.error(logger.red('当前配置允许多进程运行,程序继续运行'))
|
|
81
|
-
return this
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* 退出Karin
|
|
86
|
-
* @param code 退出码
|
|
87
|
-
*/
|
|
88
|
-
static async exit (code = 0) {
|
|
89
|
-
try {
|
|
90
|
-
const { redis } = await import('../db/index.js')
|
|
91
|
-
if (redis && redis.save) { await redis.save() }
|
|
92
|
-
logger.mark(`Karin 已停止运行 运行时间:${common.uptime()} 退出码:${code || '未知'}`)
|
|
93
|
-
} finally {
|
|
94
|
-
process.exit()
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
Process.process()
|
package/lib/core/server.js
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import Process from './process.js'
|
|
3
|
-
import { WebSocketServer } from 'ws'
|
|
4
|
-
import { createServer } from 'http'
|
|
5
|
-
import { listener } from './listener.js'
|
|
6
|
-
import express from 'express'
|
|
7
|
-
import { exec, config, logger, common } from '../utils/index.js'
|
|
8
|
-
import { AdapterOneBot11 } from '../adapter/onebot/11/index.js'
|
|
9
|
-
import { render, HttpRenderer, Wormhole, RenderClient } from '../render/index.js'
|
|
10
|
-
export const server = new (class Server {
|
|
11
|
-
reg
|
|
12
|
-
list
|
|
13
|
-
app
|
|
14
|
-
server
|
|
15
|
-
WebSocketServer
|
|
16
|
-
RegExp
|
|
17
|
-
constructor () {
|
|
18
|
-
this.reg = /(?:)/
|
|
19
|
-
this.list = []
|
|
20
|
-
this.app = express()
|
|
21
|
-
this.server = createServer(this.app)
|
|
22
|
-
this.WebSocketServer = new WebSocketServer({ server: this.server })
|
|
23
|
-
this.RegExp = new RegExp(`(${process.cwd()}|${process.cwd().replace(/\\/g, '/')})`, 'g')
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 监听WebSocket连接并初始化http服务器
|
|
28
|
-
*/
|
|
29
|
-
async init () {
|
|
30
|
-
try {
|
|
31
|
-
/** 防止多进程端口冲突 启动失败 */
|
|
32
|
-
await Process.check()
|
|
33
|
-
this.WebSocketServer.on('connection', (socket, request) => {
|
|
34
|
-
const path = request.url
|
|
35
|
-
const headers = request.headers
|
|
36
|
-
logger.debug('[反向WS]', path, JSON.stringify(headers, null, 2))
|
|
37
|
-
try {
|
|
38
|
-
const Adapter = listener.getAdapter(path)
|
|
39
|
-
if (!Adapter) {
|
|
40
|
-
logger.error(`[反向WS] 适配器不存在:${path}`)
|
|
41
|
-
return socket.close()
|
|
42
|
-
}
|
|
43
|
-
const KarinAdapter = new Adapter()
|
|
44
|
-
if (typeof KarinAdapter?.server === 'function') {
|
|
45
|
-
KarinAdapter.server(socket, request)
|
|
46
|
-
}
|
|
47
|
-
} catch (error) {
|
|
48
|
-
logger.error(`[反向WS] 注册适配器发生错误:${path}`, error.stack || error.message || error)
|
|
49
|
-
socket.close()
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
/** GET接口 - 获取当前启动信息 */
|
|
53
|
-
this.app.get('/api/ping', (req, res) => {
|
|
54
|
-
/** 只允许本机ip访问 */
|
|
55
|
-
if (req.hostname === 'localhost' || req.hostname === '127.0.0.1') {
|
|
56
|
-
const data = {
|
|
57
|
-
pm2_id: process.env.pm_id || '',
|
|
58
|
-
uptime: process.uptime(),
|
|
59
|
-
karin_app_mode: process.env.karin_app_mode,
|
|
60
|
-
karin_app_lang: process.env.karin_app_lang,
|
|
61
|
-
karin_app_runner: process.env.karin_app_runner,
|
|
62
|
-
karin_app_start_count: process.env.karin_app_start_count,
|
|
63
|
-
}
|
|
64
|
-
res.json(data)
|
|
65
|
-
} else {
|
|
66
|
-
res.status(403).json({ error: '禁止访问', message: '无效的请求' })
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
/** GET接口 - 退出当前进程 */
|
|
70
|
-
this.app.get('/api/exit', async (req) => {
|
|
71
|
-
/** 只允许本机ip访问 */
|
|
72
|
-
if (req.hostname === 'localhost' || req.hostname === '127.0.0.1') {
|
|
73
|
-
logger.mark('[服务器][HTTP] 收到退出请求,即将退出')
|
|
74
|
-
/** 关闭服务器 */
|
|
75
|
-
listener.emit('exit.grpc')
|
|
76
|
-
this.server.close()
|
|
77
|
-
/** 如果是pm2 获取当前pm2ID 使用 */
|
|
78
|
-
if (process.env.pm_id) { await exec(`pm2 delete ${process.env.pm_id}`) }
|
|
79
|
-
/** 正常启动的进程 */
|
|
80
|
-
process.exit()
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
/** 控制台适配器 */
|
|
84
|
-
this.app.get('/api/input', (req, res) => {
|
|
85
|
-
const name = req.query.name
|
|
86
|
-
const token = req.query.token
|
|
87
|
-
if (!name || !token) {
|
|
88
|
-
logger.error('[HTTP][input] 缺少参数', req.query)
|
|
89
|
-
return res.status(403).json({ error: '禁止访问', message: '缺少参数' })
|
|
90
|
-
}
|
|
91
|
-
// 禁止键入向上级目录
|
|
92
|
-
if (name.includes('/')) {
|
|
93
|
-
logger.error('[HTTP][input] 无效的文件名', name)
|
|
94
|
-
return res.status(403).json({ error: '禁止访问', message: '无效的文件名' })
|
|
95
|
-
}
|
|
96
|
-
const CfgToken = config.Config.AdapterInput.token
|
|
97
|
-
if (CfgToken === 'AdapterInput' || CfgToken !== token) {
|
|
98
|
-
logger.error('[HTTP][input] 无效的令牌', token)
|
|
99
|
-
return res.status(403).json({ error: '禁止访问', message: '无效的令牌' })
|
|
100
|
-
}
|
|
101
|
-
const file = process.cwd() + `/temp/input/${name}`
|
|
102
|
-
if (!fs.existsSync(file)) {
|
|
103
|
-
logger.error('[HTTP][input] 文件不存在', file)
|
|
104
|
-
return res.status(404).json({ error: '文件不存在', message: '找不到指定文件' })
|
|
105
|
-
}
|
|
106
|
-
logger.info(`${logger.yellow('[HTTP][input]')} ${logger.green(token)} file:${file}`)
|
|
107
|
-
res.sendFile(file)
|
|
108
|
-
})
|
|
109
|
-
/** 监听端口 */
|
|
110
|
-
const { host, port } = config.Server.http
|
|
111
|
-
this.server.listen(port, host, () => {
|
|
112
|
-
logger.mark('[服务器][启动成功][HTTP]: ' + logger.green(`http://${host}:${port}`))
|
|
113
|
-
})
|
|
114
|
-
listener.once('restart.http', () => {
|
|
115
|
-
logger.mark('[服务器][重启][HTTP] 正在重启HTTP服务器...')
|
|
116
|
-
this.#restartServer()
|
|
117
|
-
})
|
|
118
|
-
const renderCfg = config.Server.websocket.render
|
|
119
|
-
if (Array.isArray(renderCfg) && renderCfg.length) {
|
|
120
|
-
for (const url of renderCfg) {
|
|
121
|
-
new RenderClient(url).start()
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
const Onebot11 = config.Server.websocket.OneBot11Host
|
|
125
|
-
if (Array.isArray(Onebot11) && Onebot11.length) {
|
|
126
|
-
for (const connect of Onebot11) {
|
|
127
|
-
new AdapterOneBot11().client(connect)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
const { enable, WormholeClient } = config.Server.HttpRender
|
|
131
|
-
if (enable) {
|
|
132
|
-
this.static()
|
|
133
|
-
if (WormholeClient) {
|
|
134
|
-
Wormhole()
|
|
135
|
-
return this
|
|
136
|
-
}
|
|
137
|
-
const { host, post, token } = config.Server.HttpRender
|
|
138
|
-
/** 注册渲染器 */
|
|
139
|
-
const rd = new HttpRenderer(host, post, token)
|
|
140
|
-
render.app({ id: 'puppeteer', type: 'image', render: rd.render.bind(rd) })
|
|
141
|
-
}
|
|
142
|
-
return this
|
|
143
|
-
} catch (error) {
|
|
144
|
-
logger.error('初始化HTTP服务器失败: ', error)
|
|
145
|
-
return false
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* HTTP渲染器
|
|
151
|
-
*/
|
|
152
|
-
static () {
|
|
153
|
-
this.staticPath()
|
|
154
|
-
/** GET接口 - 渲染 */
|
|
155
|
-
this.app.get('/api/renderHtml', (req, res) => {
|
|
156
|
-
try {
|
|
157
|
-
let { html } = req.query
|
|
158
|
-
if (!html) { return res.status(404).send(JSON.stringify({ code: 404, msg: 'Not Found' })) }
|
|
159
|
-
html = decodeURIComponent(html)
|
|
160
|
-
.replace(/\\/g, '/')
|
|
161
|
-
.replace(/^\.\//, '')
|
|
162
|
-
/** 判断是否为html文件且路径存在 */
|
|
163
|
-
if (!html.endsWith('.html') || !fs.existsSync(html)) {
|
|
164
|
-
const not_found = config.Server.HttpRender.not_found
|
|
165
|
-
if (not_found.startsWith('http')) {
|
|
166
|
-
return res.redirect(not_found)
|
|
167
|
-
} else {
|
|
168
|
-
return res.status(404).send(JSON.stringify({ code: 404, msg: not_found || '?' }))
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
let content = fs.readFileSync(html, 'utf-8')
|
|
172
|
-
/** 处理所有绝对路径、相对路径 */
|
|
173
|
-
content = content.replace(this.RegExp, '')
|
|
174
|
-
res.send(content)
|
|
175
|
-
} catch (e) {
|
|
176
|
-
logger.error('[服务器][GET接口 - 渲染]', e)
|
|
177
|
-
res.status(500).send(JSON.stringify({ code: 500, msg: 'Internal Server Error' }))
|
|
178
|
-
}
|
|
179
|
-
})
|
|
180
|
-
/** 拦截静态资源 防止恶意访问 */
|
|
181
|
-
this.app.use((req, res, next) => {
|
|
182
|
-
logger.debug(`[静态资源][${req.headers.host}] ${req.url}`)
|
|
183
|
-
/** 解码 */
|
|
184
|
-
req.url = decodeURIComponent(req.url)
|
|
185
|
-
req.url = req.url
|
|
186
|
-
.replace(/\\/g, '/')
|
|
187
|
-
.replace(/^\.\//, '')
|
|
188
|
-
.replace(/^(\.\.\/)+/, '')
|
|
189
|
-
/** 拦截非资源文件 */
|
|
190
|
-
this.reg.lastIndex = 0
|
|
191
|
-
if (!this.reg.test(req.url)) {
|
|
192
|
-
logger.mark(`[${req.ip}][拦截非资源文件]`, req.url)
|
|
193
|
-
res.status(404).send(JSON.stringify({ code: 404, msg: 'Not Found' }))
|
|
194
|
-
return
|
|
195
|
-
}
|
|
196
|
-
next()
|
|
197
|
-
})
|
|
198
|
-
/** 设置静态文件目录 */
|
|
199
|
-
this.app.use(express.static(process.cwd()))
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* 构建静态资源路径
|
|
204
|
-
*/
|
|
205
|
-
async staticPath () {
|
|
206
|
-
this.list = []
|
|
207
|
-
/** 读取./resources文件夹 */
|
|
208
|
-
const resDir = './resources'
|
|
209
|
-
const resdirs = fs.readdirSync(resDir)
|
|
210
|
-
for (const dir of resdirs) {
|
|
211
|
-
const file = `${resDir}/${dir}`
|
|
212
|
-
if (common.isDir(file)) { this.list.push(file.replace('.', '')) }
|
|
213
|
-
}
|
|
214
|
-
/** 读取./temp/html下所有文件夹 */
|
|
215
|
-
const htmlDir = './temp/html'
|
|
216
|
-
const dirs = fs.readdirSync(htmlDir)
|
|
217
|
-
for (const dir of dirs) {
|
|
218
|
-
const file = `${htmlDir}/${dir}`
|
|
219
|
-
if (common.isDir(file)) { this.list.push(file.replace('.', '')) }
|
|
220
|
-
}
|
|
221
|
-
/** 读取./plugins/xxx/resources下所有文件夹 */
|
|
222
|
-
const pluginsDir = './plugins'
|
|
223
|
-
const plugins = fs.readdirSync(pluginsDir)
|
|
224
|
-
for (const dir of plugins) {
|
|
225
|
-
/** 忽略不是karin-plugin-开头 */
|
|
226
|
-
if (!dir.startsWith('karin-plugin-')) { continue }
|
|
227
|
-
const file = `${pluginsDir}/${dir}`
|
|
228
|
-
const resFile = `${file}/resources`
|
|
229
|
-
/** 包含resources文件夹 */
|
|
230
|
-
if (common.isDir(file) && common.isDir(resFile)) { this.list.push(resFile.replace('.', '')) }
|
|
231
|
-
const componentsFile = `${file}/lib/components`
|
|
232
|
-
/** 包含lib/components文件夹 兼容mys */
|
|
233
|
-
if (common.isDir(file) && common.isDir(componentsFile)) { this.list.push(componentsFile.replace('.', '')) }
|
|
234
|
-
/** 读取package.json 查找是否存在自定义资源文件入口 */
|
|
235
|
-
const pkgFile = `${file}/package.json`
|
|
236
|
-
if (!common.exists(pkgFile)) { continue }
|
|
237
|
-
const pkg = common.readJson(pkgFile)
|
|
238
|
-
if (!pkg?.karin?.static || !Array.isArray(pkg.karin.static)) { continue }
|
|
239
|
-
/** 标准格式为 lib/test/xxxx */
|
|
240
|
-
for (let staticFile of pkg.karin.static) {
|
|
241
|
-
/** 不允许向上级目录 ../开头等 */
|
|
242
|
-
if (staticFile.startsWith('../')) { continue }
|
|
243
|
-
/** ./开头去掉./ */
|
|
244
|
-
if (staticFile.startsWith('./')) { staticFile = staticFile.slice(2) }
|
|
245
|
-
this.list.push(`${file}/${staticFile}`)
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
this.reg = new RegExp(`(${this.list.join('|')})`, 'g')
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/** 重启当前HTTP服务器 */
|
|
252
|
-
async #restartServer () {
|
|
253
|
-
try {
|
|
254
|
-
/** 断开所有 WebSocket 连接 */
|
|
255
|
-
for (const ws of this.WebSocketServer.clients) { ws.terminate() }
|
|
256
|
-
/** 关闭当前HTTP服务器 */
|
|
257
|
-
this.server.close()
|
|
258
|
-
/** 延迟1秒 */
|
|
259
|
-
await common.sleep(1000)
|
|
260
|
-
/** 创建一个新的服务器实例 */
|
|
261
|
-
this.server = createServer(this.app)
|
|
262
|
-
this.WebSocketServer = new WebSocketServer({ server: this.server })
|
|
263
|
-
this.init()
|
|
264
|
-
this.static()
|
|
265
|
-
} catch (err) {
|
|
266
|
-
logger.error('[服务器][重启失败]', err)
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
})()
|
package/lib/db/level.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { Level } from 'level'
|
|
2
|
-
const path = process.cwd() + '/data/db/Level'
|
|
3
|
-
/**
|
|
4
|
-
* @type {Level}
|
|
5
|
-
*/
|
|
6
|
-
export default class LevelDB extends Level {
|
|
7
|
-
id
|
|
8
|
-
constructor () {
|
|
9
|
-
super(path, { valueEncoding: 'json' })
|
|
10
|
-
/**
|
|
11
|
-
* @type {'Level'} 唯一标识符 用于区分不同的数据库
|
|
12
|
-
*/
|
|
13
|
-
this.id = 'Level'
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 对get方法进行重写 找不到数据时返回null
|
|
18
|
-
*/
|
|
19
|
-
async get (key) {
|
|
20
|
-
try {
|
|
21
|
-
const res = await super.get(key)
|
|
22
|
-
return res
|
|
23
|
-
} catch {
|
|
24
|
-
return ''
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* 增加set方法
|
|
30
|
-
* @param {string} key 键
|
|
31
|
-
* @param {object|string} value 值
|
|
32
|
-
*/
|
|
33
|
-
async set (key, value) {
|
|
34
|
-
return await super.put(key, value)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
export const level = new LevelDB()
|
package/lib/db/redis.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { exec } from 'child_process'
|
|
2
|
-
import RedisLevel from './redis_level.js'
|
|
3
|
-
import { logger, config } from '../utils/index.js'
|
|
4
|
-
import { createClient, createCluster } from 'redis'
|
|
5
|
-
class Redis {
|
|
6
|
-
id
|
|
7
|
-
RunCmd
|
|
8
|
-
constructor () {
|
|
9
|
-
this.id = 'redis'
|
|
10
|
-
this.RunCmd = ''
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* redis实例化
|
|
15
|
-
*/
|
|
16
|
-
async start () {
|
|
17
|
-
const { host, port, username, password, db: database, cluster } = config.redis
|
|
18
|
-
/** 集群模式 */
|
|
19
|
-
if (cluster && cluster.enable) {
|
|
20
|
-
const rootNodes = cluster.rootNodes.map((node) => ({ url: node }))
|
|
21
|
-
logger.debug('正在连接 Redis 集群...')
|
|
22
|
-
const { status, data } = await this.connectCluster(rootNodes)
|
|
23
|
-
if (status === 'ok') {
|
|
24
|
-
logger.info('Redis 集群连接成功')
|
|
25
|
-
return data
|
|
26
|
-
}
|
|
27
|
-
logger.error(`Redis 集群建立连接失败:${logger.red(data)}`)
|
|
28
|
-
return false
|
|
29
|
-
}
|
|
30
|
-
logger.debug(`正在连接 ${logger.green(`Redis://${host}:${port}/${database}`)}`)
|
|
31
|
-
const options = { socket: { host, port }, username, password, database }
|
|
32
|
-
/** 第一次连接 */
|
|
33
|
-
const { status, data } = await this.connect(options)
|
|
34
|
-
if (status === 'ok') {
|
|
35
|
-
logger.info('Redis 连接成功')
|
|
36
|
-
return data
|
|
37
|
-
}
|
|
38
|
-
/** 第一次连接失败尝试拉起 windows直接降级 */
|
|
39
|
-
if (process.platform === 'win32') {
|
|
40
|
-
// logger.info(`Redis 建立连接失败:${data}`)
|
|
41
|
-
return await this.LevelDB()
|
|
42
|
-
}
|
|
43
|
-
this.RunCmd = 'redis-server --save 900 1 --save 300 10 --daemonize yes' + (await this.aarch64())
|
|
44
|
-
logger.info('正在尝试启动 Redis...')
|
|
45
|
-
try {
|
|
46
|
-
await this.execSync(this.RunCmd)
|
|
47
|
-
/** 启动成功再次重试 */
|
|
48
|
-
const { status, data } = await this.connect(options)
|
|
49
|
-
if (status === 'ok') {
|
|
50
|
-
logger.info('Redis 连接成功')
|
|
51
|
-
return data
|
|
52
|
-
}
|
|
53
|
-
logger.debug(`Redis 二次建立连接失败:${logger.red(data)}`)
|
|
54
|
-
return false
|
|
55
|
-
} catch (error) {
|
|
56
|
-
logger.debug(`Redis 启动失败:${logger.red(data)}`)
|
|
57
|
-
return await this.LevelDB()
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* 降级为 LevelDB
|
|
63
|
-
*/
|
|
64
|
-
async LevelDB () {
|
|
65
|
-
try {
|
|
66
|
-
logger.debug('使用LevelDB代替Redis实现基础Api')
|
|
67
|
-
const redis = new RedisLevel()
|
|
68
|
-
return redis
|
|
69
|
-
} catch (error) {
|
|
70
|
-
logger.error('降级为 LevelDB 失败')
|
|
71
|
-
logger.error(error)
|
|
72
|
-
return false
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* 连接 Redis 单例
|
|
78
|
-
*/
|
|
79
|
-
async connect (options) {
|
|
80
|
-
const client = createClient(options)
|
|
81
|
-
try {
|
|
82
|
-
await client.connect()
|
|
83
|
-
return { status: 'ok', data: client }
|
|
84
|
-
} catch (error) {
|
|
85
|
-
return { status: 'error', data: error }
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* 连接 Redis 集群
|
|
91
|
-
*/
|
|
92
|
-
async connectCluster (rootNodes) {
|
|
93
|
-
const client = createCluster({ rootNodes })
|
|
94
|
-
try {
|
|
95
|
-
await client.connect()
|
|
96
|
-
return { status: 'ok', data: client }
|
|
97
|
-
} catch (error) {
|
|
98
|
-
return { status: 'error', data: error }
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* 判断是否为 ARM64 并返回参数
|
|
104
|
-
*/
|
|
105
|
-
async aarch64 () {
|
|
106
|
-
try {
|
|
107
|
-
/** 判断arch */
|
|
108
|
-
const arch = await this.execSync('uname -m')
|
|
109
|
-
if (arch && arch.includes('aarch64')) {
|
|
110
|
-
/** 提取 Redis 版本 */
|
|
111
|
-
const version = await this.execSync('redis-server -v')
|
|
112
|
-
if (version) {
|
|
113
|
-
/** 提取版本号 */
|
|
114
|
-
const RedisVersion = version.match(/v=(\d)./)
|
|
115
|
-
/** 如果>=6版本则忽略警告 */
|
|
116
|
-
if (RedisVersion && Number(RedisVersion[1]) >= 6) { return ' --ignore-warnings ARM64-COW-BUG' }
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return ''
|
|
120
|
-
} catch {
|
|
121
|
-
return ''
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
execSync (cmd) {
|
|
126
|
-
return new Promise((resolve, reject) => {
|
|
127
|
-
exec(cmd, (error, stdout) => {
|
|
128
|
-
if (error) { return reject(error) }
|
|
129
|
-
resolve(stdout)
|
|
130
|
-
})
|
|
131
|
-
})
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
export const redis = await new Redis().start()
|