node-karin 1.15.5 → 1.16.1
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/CHANGELOG.md +31 -0
- package/dist/adapter-BqlH3u3X.mjs +218 -0
- package/dist/app-DdMQbBEY.mjs +4109 -0
- package/dist/cache-CPcPeo6N.mjs +163 -0
- package/dist/chunk-NzVPYdc1.mjs +21 -0
- package/dist/cli/index.cjs +10900 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.mjs +10770 -10224
- package/dist/file-ZGuqNDd-.mjs +15987 -0
- package/dist/file-dGy9of8-.mjs +268 -0
- package/dist/fsSync-Cf5MWILk.mjs +65 -0
- package/dist/index.d.ts +12235 -12738
- package/dist/index.mjs +2054 -25247
- package/dist/internal-DupfycKE.mjs +597 -0
- package/dist/kv-DZp4UIxg.mjs +192 -0
- package/dist/module/art-template.d.ts +2 -13
- package/dist/module/art-template.mjs +3 -1
- package/dist/module/axios.d.ts +3 -2
- package/dist/module/axios.mjs +5 -2
- package/dist/module/chalk.d.ts +3 -2
- package/dist/module/chalk.mjs +5 -2
- package/dist/module/chokidar.d.ts +3 -2
- package/dist/module/chokidar.mjs +5 -2
- package/dist/module/express.d.ts +2 -1
- package/dist/module/express.mjs +3 -1
- package/dist/module/lodash.d.ts +2 -1
- package/dist/module/lodash.mjs +3 -1
- package/dist/module/log4js.d.ts +3 -2
- package/dist/module/log4js.mjs +5 -2
- package/dist/module/moment.d.ts +2 -1
- package/dist/module/moment.mjs +3 -1
- package/dist/module/node-schedule.d.ts +3 -2
- package/dist/module/node-schedule.mjs +5 -2
- package/dist/module/redis.d.ts +3 -2
- package/dist/module/redis.mjs +5 -2
- package/dist/module/sqlite3.d.ts +3 -2
- package/dist/module/sqlite3.mjs +5 -2
- package/dist/module/ws.d.ts +3 -2
- package/dist/module/ws.mjs +5 -2
- package/dist/module/yaml.d.ts +3 -2
- package/dist/module/yaml.mjs +5 -2
- package/dist/queue-CnKedaZA.mjs +70 -0
- package/dist/redis-aLJ7wbJH.mjs +1556 -0
- package/dist/render-DPqueDZr.mjs +170 -0
- package/dist/root.d.ts +46 -46
- package/dist/root.mjs +136 -93
- package/dist/router-zPSN9-tY.mjs +124 -0
- package/dist/server-DT64D-m-.mjs +38 -0
- package/dist/snapka-BTlnZOyI.mjs +450 -0
- package/dist/sqlite-Dcj9jlW9.mjs +307 -0
- package/dist/start/app.d.ts +1 -1
- package/dist/start/app.mjs +14 -7
- package/dist/start/index.d.ts +1 -1
- package/dist/start/index.mjs +325 -656
- package/dist/template-Djk6y0uC.mjs +133 -0
- package/dist/terminalManager-Lxa8Sm06.mjs +783 -0
- package/dist/uptime-C121X_rq.mjs +210 -0
- package/dist/web/{CompressaPRO-GX.woff2.br → CompressaPRO-GX.woff2} +0 -0
- package/dist/web/assets/css/style-CBB8wM_W.css +14880 -0
- package/dist/web/assets/js/entry-Blf4Trpx.js +258540 -0
- package/dist/web/{googleapis.woff2.br → googleapis.woff2} +0 -0
- package/dist/web/index.html +2 -15
- package/dist/web/karin.png +0 -0
- package/dist/web/sha256.min.js +9 -0
- package/dist/ws-BLDoC2gV.mjs +80 -0
- package/dist/ws-CcoWd3Ar.mjs +106 -0
- package/package.json +7 -7
- package/dist/global.d.d.ts +0 -68
- package/dist/types-hAhbXJDZ.d.ts +0 -109
- package/dist/web/assets/css/components-ep7vm38G.css +0 -1
- package/dist/web/assets/css/index-Dadvd9mn.css.br +0 -0
- package/dist/web/assets/css/vendor-editor-CFbL2ovg.css.br +0 -0
- package/dist/web/assets/css/vendor-others-ZgkIHsf0.css +0 -1
- package/dist/web/assets/js/components-CU2xw4lY.js.br +0 -0
- package/dist/web/assets/js/entry-Dvb7eYLE.js.br +0 -0
- package/dist/web/assets/js/hooks-CRfhs4ON.js.br +0 -0
- package/dist/web/assets/js/page-404.tsx-DYMd_RI_.js +0 -1
- package/dist/web/assets/js/page-dashboard-CG60V_Z-.js.br +0 -0
- package/dist/web/assets/js/page-loading.tsx-wY8a9me3.js.br +0 -0
- package/dist/web/assets/js/page-login.tsx-B54ZOEZB.js.br +0 -0
- package/dist/web/assets/js/utils-C9nWTSuo.js +0 -2
- package/dist/web/assets/js/vendor-editor-BmqYP7lh.js.br +0 -0
- package/dist/web/assets/js/vendor-heroui-ClBCy2zk.js.br +0 -0
- package/dist/web/assets/js/vendor-others-6GiMrjd4.js.br +0 -0
- package/dist/web/assets/js/vendor-react-Dc9jdQiK.js.br +0 -0
- package/dist/web/assets/js/vendor-ui-utils-D0xkboLL.js.br +0 -0
- package/dist/web/assets/js/vendor-visual-saF8KLH_.js.br +0 -0
- package/dist/web/karin.png.br +0 -0
- package/dist/web/sha256.min.js.br +0 -0
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
import { t as __exportAll } from "./chunk-NzVPYdc1.mjs";
|
|
2
|
+
import { f as sep } from "./file-dGy9of8-.mjs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import lodash from "lodash";
|
|
7
|
+
import { EventEmitter } from "node:events";
|
|
8
|
+
import os from "node:os";
|
|
9
|
+
|
|
10
|
+
//#region src/utils/fs/path.ts
|
|
11
|
+
/**
|
|
12
|
+
* @description 根据文件后缀名从指定路径下读取符合要求的文件
|
|
13
|
+
* @param path - 路径
|
|
14
|
+
* @param ext - 后缀名、或后缀名列表
|
|
15
|
+
* @param returnType - 返回类型 `name:文件名` `rel:相对路径` `abs:绝对路径`
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* filesByExt('./plugins/karin-plugin-test', '.js')
|
|
19
|
+
* // -> ['1.js', '2.js']
|
|
20
|
+
* filesByExt('./plugins', ['.js', '.ts'], 'name')
|
|
21
|
+
* // -> ['1.js', '2.js', '3.ts']
|
|
22
|
+
* filesByExt('./plugins', '.js', 'rel')
|
|
23
|
+
* // -> ['plugins/1.js', 'plugins/2.js']
|
|
24
|
+
* filesByExt('./plugins', '.js', 'abs')
|
|
25
|
+
* // -> ['C:/Users/karin/plugins/1.js', 'C:/Users/karin/plugins/2.js']
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
const filesByExt = (filePath, ext, returnType = "name") => {
|
|
29
|
+
if (!fs.existsSync(filePath) || !fs.statSync(filePath).isDirectory()) return [];
|
|
30
|
+
const files = fs.readdirSync(filePath, { withFileTypes: true });
|
|
31
|
+
const list = [];
|
|
32
|
+
if (!Array.isArray(ext)) ext = [ext];
|
|
33
|
+
const allFiles = (dir, entry) => {
|
|
34
|
+
/** 如果是目录则递归查找 */
|
|
35
|
+
if (entry.isDirectory()) {
|
|
36
|
+
const subFiles = filesByExt(path.join(dir, entry.name), ext, returnType);
|
|
37
|
+
list.push(...subFiles);
|
|
38
|
+
} else if (ext.includes(path.extname(entry.name))) {
|
|
39
|
+
/** 如果是文件则添加到列表 */
|
|
40
|
+
if (returnType === "name") list.push(entry.name);
|
|
41
|
+
else if (returnType === "rel") {
|
|
42
|
+
const file = path.resolve(dir, entry.name);
|
|
43
|
+
list.push(path.relative(process.cwd(), file));
|
|
44
|
+
} else if (returnType === "abs") list.push(formatPath(path.resolve(dir, entry.name)));
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
files.forEach((entry) => allFiles(filePath, entry));
|
|
48
|
+
return list;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* @description 分割路径为文件夹路径和文件名
|
|
52
|
+
* @param filePath - 路径
|
|
53
|
+
* @returns - 文件夹路径和文件名
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* splitPath('C:/Users/admin/1.txt')
|
|
57
|
+
* // -> { dirname: 'C:/Users/admin', basename: '1.txt' }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
const splitPath = (filePath) => {
|
|
61
|
+
return {
|
|
62
|
+
dirname: path.dirname(filePath).replace(sep, ""),
|
|
63
|
+
basename: path.basename(filePath)
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* @description 去掉相对路径的前缀和后缀
|
|
68
|
+
* @param filePath - 相对路径路径
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* getRelPath('./plugins/karin-plugin-example/index.ts')
|
|
72
|
+
* // -> 'plugins/karin-plugin-example/index.ts'
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
const getRelPath = (filePath) => filePath.replace(/\\+/g, "/").replace(/\.+\/+|\/+$/g, "");
|
|
76
|
+
/**
|
|
77
|
+
* 根据传入的 import.meta.url 计算相对于项目根目录的路径,返回需要的 '../' 层级。
|
|
78
|
+
* @param url - import.meta.url
|
|
79
|
+
* @returns 相对路径的层级数量,用 '../' 表示
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* // 在 plugins/karin-plugin-example/index.ts 中使用
|
|
83
|
+
* urlToPath(import.meta.url)
|
|
84
|
+
* // -> '../../'
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
const urlToPath = (url) => {
|
|
88
|
+
const filePath = fileURLToPath(url);
|
|
89
|
+
/** 相对路径的层级数量 */
|
|
90
|
+
const upLevelsCount = path.relative(path.dirname(filePath), process.cwd()).split(path.sep).length;
|
|
91
|
+
return lodash.repeat("../", upLevelsCount);
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* @description 检查目标路径是否处于根路径下
|
|
95
|
+
* @param root 根路径
|
|
96
|
+
* @param target 目标路径
|
|
97
|
+
* @param isAbs 是否将传入的路径转为绝对路径
|
|
98
|
+
* @returns 返回布尔值
|
|
99
|
+
*/
|
|
100
|
+
const isSubPath = (root, target, isAbs = true) => {
|
|
101
|
+
if (isAbs) {
|
|
102
|
+
root = path.resolve(root);
|
|
103
|
+
target = path.resolve(target);
|
|
104
|
+
}
|
|
105
|
+
/** 相对路径 */
|
|
106
|
+
const relative = path.relative(root, target);
|
|
107
|
+
/** 检查是否以 `..` 开头或是否为空路径 如果是则代表目标路径不处于根路径下 */
|
|
108
|
+
return relative && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* @description 将路径统一格式
|
|
112
|
+
* - 绝对路径
|
|
113
|
+
* - 统一分隔符`/`
|
|
114
|
+
* @param filePath - 路径
|
|
115
|
+
* @returns 统一格式后的路径
|
|
116
|
+
*/
|
|
117
|
+
const formatPath = (filePath) => {
|
|
118
|
+
return path.resolve(filePath).replace(/\\/g, "/");
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* @description 比较两个路径是否相同
|
|
122
|
+
* @param path1 - 第一个路径
|
|
123
|
+
* @param path2 - 第二个路径
|
|
124
|
+
* @returns 是否相同
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* isPathEqual('C:\\Users\\admin', 'C:/Users/admin')
|
|
128
|
+
* // -> true
|
|
129
|
+
* isPathEqual('./folder', 'folder')
|
|
130
|
+
* // -> true
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
const isPathEqual = (path1, path2) => {
|
|
134
|
+
/** 先直接判断 */
|
|
135
|
+
if (path1 === path2) return true;
|
|
136
|
+
/** 格式化后第二次比较 */
|
|
137
|
+
path1 = formatPath(path1);
|
|
138
|
+
path2 = formatPath(path2);
|
|
139
|
+
if (path1 === path2) return true;
|
|
140
|
+
/** 判断是否为windows */
|
|
141
|
+
if (process.platform === "win32") return path1.toLowerCase() === path2.toLowerCase();
|
|
142
|
+
return false;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/plugin/system/cache.ts
|
|
147
|
+
/** 缓存 */
|
|
148
|
+
const cache = {
|
|
149
|
+
index: {},
|
|
150
|
+
accept: [],
|
|
151
|
+
command: [],
|
|
152
|
+
task: [],
|
|
153
|
+
button: [],
|
|
154
|
+
handler: {},
|
|
155
|
+
missing: /* @__PURE__ */ new Map(),
|
|
156
|
+
watcher: /* @__PURE__ */ new Map(),
|
|
157
|
+
count: {
|
|
158
|
+
accept: 0,
|
|
159
|
+
command: 0,
|
|
160
|
+
task: 0,
|
|
161
|
+
button: 0,
|
|
162
|
+
handler: {
|
|
163
|
+
key: 0,
|
|
164
|
+
fnc: 0
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
static: []
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
//#endregion
|
|
171
|
+
//#region src/utils/fs/static.ts
|
|
172
|
+
/**
|
|
173
|
+
* @description 传入一个文件路径,检查是否是静态资源中的文件
|
|
174
|
+
* @param filePath 文件路径
|
|
175
|
+
* @returns 是否是静态资源中的文件
|
|
176
|
+
*/
|
|
177
|
+
const isPublic = (filePath) => {
|
|
178
|
+
try {
|
|
179
|
+
for (const item of cache.static) if (isSubPath(item, filePath)) return true;
|
|
180
|
+
return false;
|
|
181
|
+
} catch (error) {
|
|
182
|
+
logger.error(error);
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region src/utils/fs/key.ts
|
|
189
|
+
var key_exports = /* @__PURE__ */ __exportAll({
|
|
190
|
+
BOT_CONNECT: () => BOT_CONNECT,
|
|
191
|
+
BOT_DISCONNECT: () => BOT_DISCONNECT,
|
|
192
|
+
EVENT_COUNT: () => EVENT_COUNT,
|
|
193
|
+
FILE_CHANGE: () => FILE_CHANGE,
|
|
194
|
+
RECV_MSG: () => RECV_MSG,
|
|
195
|
+
SEND_MSG: () => SEND_MSG,
|
|
196
|
+
WS_CLOSE: () => WS_CLOSE,
|
|
197
|
+
WS_CLOSE_ONEBOT: () => WS_CLOSE_ONEBOT,
|
|
198
|
+
WS_CLOSE_PUPPETEER: () => WS_CLOSE_PUPPETEER,
|
|
199
|
+
WS_CLOSE_SANDBOX: () => WS_CLOSE_SANDBOX,
|
|
200
|
+
WS_CONNECTION: () => WS_CONNECTION,
|
|
201
|
+
WS_CONNECTION_ONEBOT: () => WS_CONNECTION_ONEBOT,
|
|
202
|
+
WS_CONNECTION_PUPPETEER: () => WS_CONNECTION_PUPPETEER,
|
|
203
|
+
WS_CONNECTION_SANDBOX: () => WS_CONNECTION_SANDBOX,
|
|
204
|
+
WS_CONNECTION_TERMINAL: () => WS_CONNECTION_TERMINAL,
|
|
205
|
+
WS_SNAPKA: () => WS_SNAPKA
|
|
206
|
+
});
|
|
207
|
+
/** 收到消息 */
|
|
208
|
+
const RECV_MSG = "karin:count:recv";
|
|
209
|
+
/** 发送消息 */
|
|
210
|
+
const SEND_MSG = "karin:count:send";
|
|
211
|
+
/** 事件调用 */
|
|
212
|
+
const EVENT_COUNT = "karin:count:fnc";
|
|
213
|
+
/** 文件变动 */
|
|
214
|
+
const FILE_CHANGE = "karin:file:change";
|
|
215
|
+
/** 传递ws连接 */
|
|
216
|
+
const WS_CONNECTION = "ws:connection";
|
|
217
|
+
/** 传递onebot ws连接 */
|
|
218
|
+
const WS_CONNECTION_ONEBOT = "ws:connection:onebot";
|
|
219
|
+
/** 传递puppeteer ws连接 */
|
|
220
|
+
const WS_CONNECTION_PUPPETEER = "ws:connection:puppeteer";
|
|
221
|
+
/** 传递sandbox ws连接 */
|
|
222
|
+
const WS_CONNECTION_SANDBOX = "ws:connection:sandbox";
|
|
223
|
+
/** 传递虚拟终端 ws连接 */
|
|
224
|
+
const WS_CONNECTION_TERMINAL = "ws:connection:terminal";
|
|
225
|
+
/** 传递ws关闭 */
|
|
226
|
+
const WS_CLOSE = "ws:close";
|
|
227
|
+
/** 传递onebot ws关闭 */
|
|
228
|
+
const WS_CLOSE_ONEBOT = "ws:close:onebot";
|
|
229
|
+
/** 传递puppeteer ws关闭 */
|
|
230
|
+
const WS_CLOSE_PUPPETEER = "ws:close:puppeteer";
|
|
231
|
+
/** 传递sandbox ws关闭 */
|
|
232
|
+
const WS_CLOSE_SANDBOX = "ws:close:sandbox";
|
|
233
|
+
/** 传递 snapka ws连接 */
|
|
234
|
+
const WS_SNAPKA = "ws:connection:snapka";
|
|
235
|
+
/** Bot连接成功 */
|
|
236
|
+
const BOT_CONNECT = "bot.connect";
|
|
237
|
+
/** Bot连接断开 */
|
|
238
|
+
const BOT_DISCONNECT = "bot.disconnect";
|
|
239
|
+
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region src/core/internal/listeners.ts
|
|
242
|
+
/** 类型化事件监听器 */
|
|
243
|
+
var TypedListeners = class extends EventEmitter {
|
|
244
|
+
/**
|
|
245
|
+
* 注册事件监听器
|
|
246
|
+
* @param event 事件名称
|
|
247
|
+
* @param listener 监听器函数
|
|
248
|
+
*/
|
|
249
|
+
on(event, listener) {
|
|
250
|
+
return super.on(event, listener);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* 注册一次性事件监听器
|
|
254
|
+
* @param event 事件名称
|
|
255
|
+
* @param listener 监听器函数
|
|
256
|
+
*/
|
|
257
|
+
once(event, listener) {
|
|
258
|
+
return super.once(event, listener);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* 移除事件监听器
|
|
262
|
+
* @param event 事件名称
|
|
263
|
+
* @param listener 监听器函数
|
|
264
|
+
*/
|
|
265
|
+
off(event, listener) {
|
|
266
|
+
return super.off(event, listener);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* 触发事件
|
|
270
|
+
* @param event 事件名称
|
|
271
|
+
* @param args 事件参数
|
|
272
|
+
*/
|
|
273
|
+
emit(event, ...args) {
|
|
274
|
+
return super.emit(event, ...args);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* 获取事件监听器列表
|
|
278
|
+
* @param event 事件名称
|
|
279
|
+
*/
|
|
280
|
+
listeners(event) {
|
|
281
|
+
return super.listeners(event);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* 移除所有事件监听器
|
|
285
|
+
* @param event 事件名称
|
|
286
|
+
* @returns this
|
|
287
|
+
*/
|
|
288
|
+
removeAllListeners(event) {
|
|
289
|
+
super.removeAllListeners(event);
|
|
290
|
+
return this;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* 设置最大监听器数量
|
|
294
|
+
* @param n 最大监听器数量
|
|
295
|
+
* @returns this
|
|
296
|
+
*/
|
|
297
|
+
setMaxListeners(n) {
|
|
298
|
+
super.setMaxListeners(n);
|
|
299
|
+
return this;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* 获取最大监听器数量
|
|
303
|
+
* @returns 最大监听器数量
|
|
304
|
+
*/
|
|
305
|
+
getMaxListeners() {
|
|
306
|
+
return super.getMaxListeners();
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* 添加事件监听器
|
|
310
|
+
* @param event 事件名称
|
|
311
|
+
* @param listener 监听器函数
|
|
312
|
+
*/
|
|
313
|
+
addListener(event, listener) {
|
|
314
|
+
return super.addListener(event, listener);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* 获取事件监听器数量
|
|
318
|
+
* @param event 事件名称
|
|
319
|
+
* @returns 监听器数量
|
|
320
|
+
*/
|
|
321
|
+
listenerCount(event) {
|
|
322
|
+
return super.listenerCount(event);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* 返回已注册的事件名称数组
|
|
326
|
+
* @param event 事件名称
|
|
327
|
+
* @returns 监听器数量
|
|
328
|
+
*/
|
|
329
|
+
eventNames() {
|
|
330
|
+
return super.eventNames();
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* 返回指定事件的原始监听器数组(包括一次性监听器)
|
|
334
|
+
* @param event 事件名称
|
|
335
|
+
* @returns 监听器数量
|
|
336
|
+
*/
|
|
337
|
+
rawListeners(event) {
|
|
338
|
+
return super.rawListeners(event);
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* 为指定事件添加监听器,但将其添加到监听器数组的开头
|
|
342
|
+
* @param event 事件名称
|
|
343
|
+
* @returns 监听器数量
|
|
344
|
+
*/
|
|
345
|
+
prependListener(event, listener) {
|
|
346
|
+
return super.prependListener(event, listener);
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* 为指定事件添加一次性监听器,并将其添加到监听器数组的开头
|
|
350
|
+
* @param event 事件名称
|
|
351
|
+
* @returns 监听器数量
|
|
352
|
+
*/
|
|
353
|
+
prependOnceListener(event, listener) {
|
|
354
|
+
return super.prependOnceListener(event, listener);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* 移除事件监听器
|
|
358
|
+
* @param event 事件名称
|
|
359
|
+
* @param listener 监听器函数
|
|
360
|
+
*/
|
|
361
|
+
removeListener(event, listener) {
|
|
362
|
+
return super.removeListener(event, listener);
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
/**
|
|
366
|
+
* @internal
|
|
367
|
+
* @description 内部事件监听器
|
|
368
|
+
*/
|
|
369
|
+
const listeners = new TypedListeners();
|
|
370
|
+
|
|
371
|
+
//#endregion
|
|
372
|
+
//#region src/core/internal/error.ts
|
|
373
|
+
/** 插件名称:缺失的依赖 */
|
|
374
|
+
const missing = /* @__PURE__ */ new Map();
|
|
375
|
+
/**
|
|
376
|
+
* @description 插件载入错误
|
|
377
|
+
* @param name 插件包名
|
|
378
|
+
* @param file 报错的文件名称
|
|
379
|
+
* @param error 错误信息
|
|
380
|
+
*/
|
|
381
|
+
const loaderPlugin = (name, file, error) => {
|
|
382
|
+
const pkg = /Cannot find package '(.+?)'/.exec(error)?.[1];
|
|
383
|
+
if (pkg) {
|
|
384
|
+
const key = `${name}.${pkg}`;
|
|
385
|
+
if (missing.has(key)) return;
|
|
386
|
+
missing.set(key, {
|
|
387
|
+
name,
|
|
388
|
+
file,
|
|
389
|
+
depend: pkg
|
|
390
|
+
});
|
|
391
|
+
} else {
|
|
392
|
+
logger.error(`载入插件错误:${logger.red(`${name}/${path.basename(file)}`)}`);
|
|
393
|
+
listeners.emit("error", error);
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
/**
|
|
397
|
+
* @description 定时任务执行错误
|
|
398
|
+
* @param name 插件包名
|
|
399
|
+
* @param task 任务名称
|
|
400
|
+
* @param error 错误信息
|
|
401
|
+
*/
|
|
402
|
+
const taskStart = (name, task, error) => {
|
|
403
|
+
logger.error(`[定时任务][${name}][${task}] 执行错误`);
|
|
404
|
+
listeners.emit("error", error);
|
|
405
|
+
};
|
|
406
|
+
/**
|
|
407
|
+
* @description 打印插件载入错误
|
|
408
|
+
*/
|
|
409
|
+
const printMissing = () => {
|
|
410
|
+
try {
|
|
411
|
+
if (!missing.size) return;
|
|
412
|
+
const msg = ["\n-----依赖缺失----"];
|
|
413
|
+
for (const [, { name, file, depend }] of missing) msg.push(`[${name}][${path.basename(file)}] 缺少依赖:${logger.red(depend)}`);
|
|
414
|
+
msg.push("-------------------");
|
|
415
|
+
const one = missing.values().next().value;
|
|
416
|
+
msg.push(...[
|
|
417
|
+
"温馨提示:",
|
|
418
|
+
`1. 如果是新安装的插件,请尝试执行 ${logger.red("pnpm install -P")} 自动安装依赖`,
|
|
419
|
+
`2. 如果执行第一步无效,请尝试执行 ${logger.red("pnpm imstall 依赖名称 -w")} 手动安装依赖`,
|
|
420
|
+
`举例: ${logger.red(`pnpm add ${one.depend} -w`)}`,
|
|
421
|
+
logger.yellow("对于手动安装的依赖,如果对应插件未在使用,请进行及时卸载: pnpm rm 依赖名称")
|
|
422
|
+
]);
|
|
423
|
+
msg.push("-------------------");
|
|
424
|
+
logger.error(msg.join("\n"));
|
|
425
|
+
} finally {
|
|
426
|
+
missing.clear();
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
const errorHandler = {
|
|
430
|
+
/** 插件载入错误 */
|
|
431
|
+
loaderPlugin,
|
|
432
|
+
/** 定时任务执行错误 */
|
|
433
|
+
taskStart,
|
|
434
|
+
/** 打印插件载入错误 */
|
|
435
|
+
printMissing
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
//#endregion
|
|
439
|
+
//#region src/core/internal/status_listener.ts
|
|
440
|
+
var StatusHelper = class {
|
|
441
|
+
psCpuUsage = process.cpuUsage();
|
|
442
|
+
psCurrentTime = process.hrtime();
|
|
443
|
+
cpuTimes = os.cpus().map((cpu) => cpu.times);
|
|
444
|
+
replaceNaN(value) {
|
|
445
|
+
return isNaN(value) ? 0 : value;
|
|
446
|
+
}
|
|
447
|
+
sysCpuInfo() {
|
|
448
|
+
const currentTimes = os.cpus().map((cpu) => cpu.times);
|
|
449
|
+
const { total, active } = currentTimes.map((times, index) => {
|
|
450
|
+
const prevTimes = this.cpuTimes[index];
|
|
451
|
+
const totalCurrent = times.user + times.nice + times.sys + times.idle + times.irq;
|
|
452
|
+
const totalPrev = prevTimes.user + prevTimes.nice + prevTimes.sys + prevTimes.idle + prevTimes.irq;
|
|
453
|
+
const activeCurrent = totalCurrent - times.idle;
|
|
454
|
+
const activePrev = totalPrev - prevTimes.idle;
|
|
455
|
+
return {
|
|
456
|
+
total: totalCurrent - totalPrev,
|
|
457
|
+
active: activeCurrent - activePrev
|
|
458
|
+
};
|
|
459
|
+
}).reduce((acc, cur) => ({
|
|
460
|
+
total: acc.total + cur.total,
|
|
461
|
+
active: acc.active + cur.active
|
|
462
|
+
}), {
|
|
463
|
+
total: 0,
|
|
464
|
+
active: 0
|
|
465
|
+
});
|
|
466
|
+
this.cpuTimes = currentTimes;
|
|
467
|
+
return {
|
|
468
|
+
usage: this.replaceNaN(active / total * 100).toFixed(2),
|
|
469
|
+
model: os.cpus()[0].model,
|
|
470
|
+
speed: os.cpus()[0].speed,
|
|
471
|
+
core: os.cpus().length
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
sysMemoryUsage() {
|
|
475
|
+
const { total, free } = {
|
|
476
|
+
total: os.totalmem(),
|
|
477
|
+
free: os.freemem()
|
|
478
|
+
};
|
|
479
|
+
return ((total - free) / 1024 / 1024).toFixed(2);
|
|
480
|
+
}
|
|
481
|
+
karinUsage() {
|
|
482
|
+
const mem = process.memoryUsage();
|
|
483
|
+
const numCpus = os.cpus().length;
|
|
484
|
+
const usageDiff = process.cpuUsage(this.psCpuUsage);
|
|
485
|
+
const endTime = process.hrtime(this.psCurrentTime);
|
|
486
|
+
this.psCpuUsage = process.cpuUsage();
|
|
487
|
+
this.psCurrentTime = process.hrtime();
|
|
488
|
+
const normPercent = (usageDiff.user + usageDiff.system) / 1e3 / (endTime[0] * 1e3 + endTime[1] / 1e6) / numCpus * 100;
|
|
489
|
+
return {
|
|
490
|
+
cpu: this.replaceNaN(normPercent).toFixed(2),
|
|
491
|
+
memory: ((mem.heapTotal + mem.external + mem.arrayBuffers) / 1024 / 1024).toFixed(2)
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* 获取系统状态信息
|
|
496
|
+
*/
|
|
497
|
+
systemStatus() {
|
|
498
|
+
const karinUsage = this.karinUsage();
|
|
499
|
+
const sysCpuInfo = this.sysCpuInfo();
|
|
500
|
+
const memUsage = process.memoryUsage();
|
|
501
|
+
let userInfo;
|
|
502
|
+
try {
|
|
503
|
+
userInfo = os.userInfo();
|
|
504
|
+
} catch (e) {
|
|
505
|
+
userInfo = void 0;
|
|
506
|
+
}
|
|
507
|
+
let loadavg;
|
|
508
|
+
try {
|
|
509
|
+
loadavg = os.loadavg();
|
|
510
|
+
} catch (e) {
|
|
511
|
+
loadavg = void 0;
|
|
512
|
+
}
|
|
513
|
+
return {
|
|
514
|
+
cpu: {
|
|
515
|
+
core: sysCpuInfo.core,
|
|
516
|
+
model: sysCpuInfo.model,
|
|
517
|
+
speed: (sysCpuInfo.speed / 1e3).toFixed(2),
|
|
518
|
+
usage: {
|
|
519
|
+
system: sysCpuInfo.usage,
|
|
520
|
+
karin: karinUsage.cpu
|
|
521
|
+
}
|
|
522
|
+
},
|
|
523
|
+
memory: {
|
|
524
|
+
total: (os.totalmem() / 1024 / 1024).toFixed(2),
|
|
525
|
+
usage: {
|
|
526
|
+
system: this.sysMemoryUsage(),
|
|
527
|
+
karin: karinUsage.memory
|
|
528
|
+
},
|
|
529
|
+
details: {
|
|
530
|
+
rss: (memUsage.rss / 1024 / 1024).toFixed(2),
|
|
531
|
+
heapTotal: (memUsage.heapTotal / 1024 / 1024).toFixed(2),
|
|
532
|
+
heapUsed: (memUsage.heapUsed / 1024 / 1024).toFixed(2),
|
|
533
|
+
external: (memUsage.external / 1024 / 1024).toFixed(2),
|
|
534
|
+
arrayBuffers: (memUsage.arrayBuffers / 1024 / 1024).toFixed(2)
|
|
535
|
+
}
|
|
536
|
+
},
|
|
537
|
+
system: {
|
|
538
|
+
arch: `${os.platform()} ${os.arch()}`,
|
|
539
|
+
hostname: os.hostname(),
|
|
540
|
+
osName: os.type(),
|
|
541
|
+
osVersion: os.release(),
|
|
542
|
+
platform: os.platform(),
|
|
543
|
+
uptime: os.uptime(),
|
|
544
|
+
loadavg,
|
|
545
|
+
tmpdir: os.tmpdir(),
|
|
546
|
+
homedir: os.homedir()
|
|
547
|
+
},
|
|
548
|
+
process: {
|
|
549
|
+
nodeVersion: process.version,
|
|
550
|
+
pid: process.pid,
|
|
551
|
+
uptime: process.uptime(),
|
|
552
|
+
execPath: process.execPath,
|
|
553
|
+
argv: process.argv,
|
|
554
|
+
env: {
|
|
555
|
+
nodeEnv: process.env.NODE_ENV,
|
|
556
|
+
timezone: process.env.TZ
|
|
557
|
+
},
|
|
558
|
+
user: userInfo ? {
|
|
559
|
+
username: userInfo.username,
|
|
560
|
+
homedir: userInfo.homedir,
|
|
561
|
+
shell: userInfo.shell
|
|
562
|
+
} : void 0
|
|
563
|
+
},
|
|
564
|
+
network: { interfaces: os.networkInterfaces() }
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
var StatusHelperSubscription = class extends EventEmitter {
|
|
569
|
+
statusHelper;
|
|
570
|
+
interval = null;
|
|
571
|
+
constructor(time = 3e3) {
|
|
572
|
+
super();
|
|
573
|
+
this.statusHelper = new StatusHelper();
|
|
574
|
+
this.on("newListener", (event) => {
|
|
575
|
+
if (event === "statusUpdate" && this.listenerCount("statusUpdate") === 0) this.startInterval(time);
|
|
576
|
+
});
|
|
577
|
+
this.on("removeListener", (event) => {
|
|
578
|
+
if (event === "statusUpdate" && this.listenerCount("statusUpdate") === 0) this.stopInterval();
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
startInterval(time) {
|
|
582
|
+
this.interval ??= setInterval(() => {
|
|
583
|
+
const status = this.statusHelper.systemStatus();
|
|
584
|
+
this.emit("statusUpdate", status);
|
|
585
|
+
}, time);
|
|
586
|
+
}
|
|
587
|
+
stopInterval() {
|
|
588
|
+
if (this.interval) {
|
|
589
|
+
clearInterval(this.interval);
|
|
590
|
+
this.interval = null;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
const statusListener = new StatusHelperSubscription();
|
|
595
|
+
|
|
596
|
+
//#endregion
|
|
597
|
+
export { filesByExt as C, isSubPath as D, isPathEqual as E, splitPath as O, cache as S, getRelPath as T, WS_CONNECTION_SANDBOX as _, BOT_DISCONNECT as a, key_exports as b, RECV_MSG as c, WS_CLOSE_ONEBOT as d, WS_CLOSE_PUPPETEER as f, WS_CONNECTION_PUPPETEER as g, WS_CONNECTION_ONEBOT as h, BOT_CONNECT as i, urlToPath as k, SEND_MSG as l, WS_CONNECTION as m, errorHandler as n, EVENT_COUNT as o, WS_CLOSE_SANDBOX as p, listeners as r, FILE_CHANGE as s, statusListener as t, WS_CLOSE as u, WS_CONNECTION_TERMINAL as v, formatPath as w, isPublic as x, WS_SNAPKA as y };
|