mioki 0.13.0 → 0.15.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/dist/cli.cjs +10 -7
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +10 -7
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +423 -167
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -19
- package/dist/index.d.mts +97 -19
- package/dist/index.mjs +419 -168
- package/dist/index.mjs.map +1 -1
- package/dist/{package-BHgI99iP.cjs → package-49Rgph2M.cjs} +2 -2
- package/dist/package-49Rgph2M.cjs.map +1 -0
- package/dist/package-B4h-fhCq.mjs +6 -0
- package/dist/package-B4h-fhCq.mjs.map +1 -0
- package/package.json +3 -3
- package/dist/package-BHgI99iP.cjs.map +0 -1
- package/dist/package-D5I4iirh.mjs +0 -6
- package/dist/package-D5I4iirh.mjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_package = require('./package-
|
|
1
|
+
const require_package = require('./package-49Rgph2M.cjs');
|
|
2
2
|
let node_fs = require("node:fs");
|
|
3
3
|
node_fs = require_package.__toESM(node_fs);
|
|
4
4
|
let node_util = require("node:util");
|
|
@@ -790,12 +790,20 @@ var config_exports = /* @__PURE__ */ require_package.__exportAll({
|
|
|
790
790
|
isInPm2: () => isInPm2,
|
|
791
791
|
isOwner: () => isOwner,
|
|
792
792
|
isOwnerOrAdmin: () => isOwnerOrAdmin,
|
|
793
|
+
normalizeNapCatConfig: () => normalizeNapCatConfig,
|
|
793
794
|
readMiokiConfig: () => readMiokiConfig,
|
|
794
795
|
readPackageJson: () => readPackageJson,
|
|
795
796
|
updateBotCWD: () => updateBotCWD,
|
|
796
797
|
updateBotConfig: () => updateBotConfig,
|
|
797
798
|
writePackageJson: () => writePackageJson
|
|
798
799
|
});
|
|
800
|
+
function isSingleNapCatConfig(config) {
|
|
801
|
+
return !Array.isArray(config);
|
|
802
|
+
}
|
|
803
|
+
function normalizeNapCatConfig(config) {
|
|
804
|
+
if (isSingleNapCatConfig(config)) return [config];
|
|
805
|
+
return config;
|
|
806
|
+
}
|
|
799
807
|
/**
|
|
800
808
|
* 机器人根目录
|
|
801
809
|
*/
|
|
@@ -811,7 +819,10 @@ function readMiokiConfig() {
|
|
|
811
819
|
const config = readPackageJson().mioki;
|
|
812
820
|
if (!config) throw new Error(`无法在 package.json 中找到 mioki 配置,请确认 package.json 文件中是否包含 mioki 字段`);
|
|
813
821
|
if (!config.napcat) throw new Error(`mioki 配置中缺少 napcat 字段,请补全后重试`);
|
|
814
|
-
return
|
|
822
|
+
return {
|
|
823
|
+
...config,
|
|
824
|
+
napcat: normalizeNapCatConfig(config.napcat)
|
|
825
|
+
};
|
|
815
826
|
}
|
|
816
827
|
/**
|
|
817
828
|
* `mioki` 框架相关配置
|
|
@@ -1212,9 +1223,132 @@ function addService(name, service, cover = true) {
|
|
|
1212
1223
|
function bindBot(bot, func) {
|
|
1213
1224
|
return (...args) => func(bot, ...args);
|
|
1214
1225
|
}
|
|
1226
|
+
/**
|
|
1227
|
+
* 去重器
|
|
1228
|
+
* 处理多个 bot 在相同场景下,同一事件只处理一次
|
|
1229
|
+
*/
|
|
1230
|
+
var Deduplicator = class {
|
|
1231
|
+
processedEvents = /* @__PURE__ */ new Set();
|
|
1232
|
+
maxSize = 1e3;
|
|
1233
|
+
/**
|
|
1234
|
+
* 获取事件类型键
|
|
1235
|
+
*/
|
|
1236
|
+
getEventTypeKey(e) {
|
|
1237
|
+
const { post_type } = e;
|
|
1238
|
+
if (post_type === "message") return `msg:${e.message_type}`;
|
|
1239
|
+
if (post_type === "request") {
|
|
1240
|
+
if (e.request_type === "friend") return "req:friend";
|
|
1241
|
+
return `req:group:${e.sub_type ?? "unknown"}`;
|
|
1242
|
+
}
|
|
1243
|
+
if (post_type === "notice") {
|
|
1244
|
+
if (e.notice_type === "group") return `notice:group:${e.sub_type}`;
|
|
1245
|
+
return `notice:${e.notice_type}:${e.sub_type}`;
|
|
1246
|
+
}
|
|
1247
|
+
return "unknown";
|
|
1248
|
+
}
|
|
1249
|
+
getGroupMessageKey(e) {
|
|
1250
|
+
const groupId = e.group_id ?? "_";
|
|
1251
|
+
const userId = e.user_id ?? "_";
|
|
1252
|
+
const time = e.time ?? "_";
|
|
1253
|
+
const raw = e.raw_message ?? "_";
|
|
1254
|
+
return `msg:group:${groupId}:${userId}:${time}:${node_crypto.default.createHash("md5").update(raw).digest("hex")}`;
|
|
1255
|
+
}
|
|
1256
|
+
getNoticeGroupKey(e) {
|
|
1257
|
+
return `${this.getEventTypeKey(e)}:${e.group_id ?? "_"}:${e.user_id ?? "_"}:${"operator_id" in e ? e.operator_id ?? "_" : "_"}:${"target_id" in e ? e.target_id ?? "_" : "_"}:${e.sub_type ?? "_"}:${"action_type" in e ? e.action_type ?? "_" : "_"}:${"duration" in e ? e.duration ?? "_" : "_"}:${e.time ?? "_"}`;
|
|
1258
|
+
}
|
|
1259
|
+
getRequestKey(e) {
|
|
1260
|
+
const typeKey = this.getEventTypeKey(e);
|
|
1261
|
+
const userId = e.user_id ?? "_";
|
|
1262
|
+
const groupId = "group_id" in e ? e.group_id ?? "_" : "_";
|
|
1263
|
+
const time = e.time ?? "_";
|
|
1264
|
+
const comment = e.comment ?? "_";
|
|
1265
|
+
return `${typeKey}:${userId}:${groupId}:${time}:${comment ? node_crypto.default.createHash("md5").update(comment).digest("hex") : "_"}`;
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* 生成事件唯一键
|
|
1269
|
+
*/
|
|
1270
|
+
getKey(e) {
|
|
1271
|
+
const typeKey = this.getEventTypeKey(e);
|
|
1272
|
+
if (typeKey === "msg:group") return this.getGroupMessageKey(e);
|
|
1273
|
+
if (typeKey.startsWith("notice:group:")) return this.getNoticeGroupKey(e);
|
|
1274
|
+
if (typeKey.startsWith("req:")) return this.getRequestKey(e);
|
|
1275
|
+
return "";
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* 检查事件是否已处理过
|
|
1279
|
+
* @param event
|
|
1280
|
+
* @param scope
|
|
1281
|
+
*/
|
|
1282
|
+
isProcessed(event, scope) {
|
|
1283
|
+
const key = scope ? `${this.getKey(event)}:${scope}` : this.getKey(event);
|
|
1284
|
+
return this.processedEvents.has(key);
|
|
1285
|
+
}
|
|
1286
|
+
/**
|
|
1287
|
+
* 标记事件为已处理
|
|
1288
|
+
* @param event
|
|
1289
|
+
* @param scope 需与 isProcessed 一致
|
|
1290
|
+
*/
|
|
1291
|
+
markProcessed(event, scope) {
|
|
1292
|
+
const key = scope ? `${this.getKey(event)}:${scope}` : this.getKey(event);
|
|
1293
|
+
if (this.processedEvents.size >= this.maxSize) {
|
|
1294
|
+
const first = this.processedEvents.values().next();
|
|
1295
|
+
if (!first.done) this.processedEvents.delete(first.value);
|
|
1296
|
+
}
|
|
1297
|
+
this.processedEvents.add(key);
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
/**
|
|
1301
|
+
* 消息去重器
|
|
1302
|
+
* @deprecated 请使用 Deduplicator,它支持更多事件类型
|
|
1303
|
+
*/
|
|
1304
|
+
var MessageDeduplicator = class extends Deduplicator {
|
|
1305
|
+
isProcessed(event) {
|
|
1306
|
+
return super.isProcessed(event);
|
|
1307
|
+
}
|
|
1308
|
+
markProcessed(event) {
|
|
1309
|
+
super.markProcessed(event);
|
|
1310
|
+
}
|
|
1311
|
+
};
|
|
1312
|
+
const deduplicator = new Deduplicator();
|
|
1215
1313
|
const runtimePlugins = /* @__PURE__ */ new Map();
|
|
1216
1314
|
const buildRemovedActions = (bot) => Object.fromEntries(Object.entries(actions_exports).map(([k, v]) => [k, bindBot(bot, v)]));
|
|
1217
1315
|
/**
|
|
1316
|
+
* 检查事件是否是群消息事件
|
|
1317
|
+
*/
|
|
1318
|
+
function isGroupMessageEvent(event) {
|
|
1319
|
+
return event?.post_type === "message" && event?.message_type === "group";
|
|
1320
|
+
}
|
|
1321
|
+
/**
|
|
1322
|
+
* 检查事件是否是私聊消息事件
|
|
1323
|
+
*/
|
|
1324
|
+
function isPrivateMessageEvent(event) {
|
|
1325
|
+
return event?.post_type === "message" && event?.message_type === "private";
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* 检查事件是否是消息事件
|
|
1329
|
+
*/
|
|
1330
|
+
function isMessageEvent(event) {
|
|
1331
|
+
return isGroupMessageEvent(event) || isPrivateMessageEvent(event);
|
|
1332
|
+
}
|
|
1333
|
+
/**
|
|
1334
|
+
* 检查事件是否是请求事件
|
|
1335
|
+
*/
|
|
1336
|
+
function isRequestEvent(event) {
|
|
1337
|
+
return event?.post_type === "request";
|
|
1338
|
+
}
|
|
1339
|
+
/**
|
|
1340
|
+
* 检查事件是否是群通知事件
|
|
1341
|
+
*/
|
|
1342
|
+
function isGroupNoticeEvent(event) {
|
|
1343
|
+
return event?.post_type === "notice" && event?.notice_type === "group";
|
|
1344
|
+
}
|
|
1345
|
+
/**
|
|
1346
|
+
* 检查事件是否需要去重
|
|
1347
|
+
*/
|
|
1348
|
+
function isDeduplicableEvent(event) {
|
|
1349
|
+
return isMessageEvent(event) || isRequestEvent(event) || isGroupNoticeEvent(event);
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1218
1352
|
* 定义一个 Mioki 插件
|
|
1219
1353
|
* @param plugin Mioki 插件对象
|
|
1220
1354
|
* @returns Mioki 插件对象
|
|
@@ -1236,55 +1370,83 @@ function getAbsPluginDir(defaultDir = "plugins") {
|
|
|
1236
1370
|
const cwd = BOT_CWD.value;
|
|
1237
1371
|
return node_path.default.join(cwd, botConfig.plugins_dir || defaultDir);
|
|
1238
1372
|
}
|
|
1239
|
-
async function enablePlugin(
|
|
1373
|
+
async function enablePlugin(bots, plugin, type = "external") {
|
|
1240
1374
|
const typeDesc = type === "builtin" ? "内置" : "用户";
|
|
1241
1375
|
const pluginName = plugin.name || "null";
|
|
1242
1376
|
const { name = pluginName, version: version$1 = "null", description = "-", setup = () => {} } = plugin;
|
|
1377
|
+
if (!bots[0]) throw new Error("没有可用的 bot 实例");
|
|
1243
1378
|
try {
|
|
1244
1379
|
const start$1 = node_process.hrtime.bigint();
|
|
1245
1380
|
const clears = /* @__PURE__ */ new Set();
|
|
1246
1381
|
const userClears = /* @__PURE__ */ new Set();
|
|
1247
|
-
const logger$1 =
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1382
|
+
const logger$1 = logger.withDefaults({ tag: `plugin:${name}` });
|
|
1383
|
+
const createContext = (bot) => {
|
|
1384
|
+
return {
|
|
1385
|
+
bot,
|
|
1386
|
+
bots,
|
|
1387
|
+
self_id: bot.bot_id,
|
|
1388
|
+
segment: bot.segment,
|
|
1389
|
+
getCookie: bot.getCookie.bind(bot),
|
|
1390
|
+
...utils_exports,
|
|
1391
|
+
...config_exports,
|
|
1392
|
+
...buildRemovedActions(bot),
|
|
1393
|
+
logger: logger$1,
|
|
1394
|
+
services,
|
|
1395
|
+
clears: userClears,
|
|
1396
|
+
deduplicator,
|
|
1397
|
+
addService: (name$1, service, cover) => {
|
|
1398
|
+
const remove = addService(name$1, service, cover);
|
|
1399
|
+
clears.add(remove);
|
|
1400
|
+
return remove;
|
|
1401
|
+
},
|
|
1402
|
+
handle: (eventName, handler, options = {}) => {
|
|
1403
|
+
logger$1.debug(`Registering event handler for event: ${String(eventName)}`);
|
|
1404
|
+
const { deduplicate = true } = options;
|
|
1405
|
+
const dedupeScope = `${name}:${String(eventName)}:${node_crypto.default.randomUUID()}`;
|
|
1406
|
+
const unsubscribes = [];
|
|
1407
|
+
for (const bot$1 of bots) {
|
|
1408
|
+
const wrappedHandler = (e) => {
|
|
1409
|
+
if (isPrivateMessageEvent(e)) {
|
|
1410
|
+
if (e.self_id !== bot$1.bot_id) return;
|
|
1411
|
+
}
|
|
1412
|
+
const senderUserId = e.user_id;
|
|
1413
|
+
const senderOperatorId = e.operator_id;
|
|
1414
|
+
const isFromConnectedBot = senderUserId && bots.some((b) => b.bot_id === senderUserId);
|
|
1415
|
+
const isFromConnectedBotOperator = senderOperatorId && bots.some((b) => b.bot_id === senderOperatorId);
|
|
1416
|
+
if (isFromConnectedBot || isFromConnectedBotOperator) return;
|
|
1417
|
+
if (deduplicate && isDeduplicableEvent(e)) {
|
|
1418
|
+
if (deduplicator.isProcessed(e, dedupeScope)) return;
|
|
1419
|
+
deduplicator.markProcessed(e, dedupeScope);
|
|
1420
|
+
}
|
|
1421
|
+
handler(e);
|
|
1422
|
+
};
|
|
1423
|
+
bot$1.on(eventName, wrappedHandler);
|
|
1424
|
+
const unsubscribe = () => {
|
|
1425
|
+
logger$1.debug(`Unregistering event handler for event: ${String(eventName)}`);
|
|
1426
|
+
bot$1.off(eventName, wrappedHandler);
|
|
1427
|
+
};
|
|
1428
|
+
unsubscribes.push(unsubscribe);
|
|
1429
|
+
}
|
|
1430
|
+
const clearAll = () => {
|
|
1431
|
+
unsubscribes.forEach((fn) => fn());
|
|
1432
|
+
};
|
|
1433
|
+
clears.add(clearAll);
|
|
1434
|
+
return clearAll;
|
|
1435
|
+
},
|
|
1436
|
+
cron: (cronExpression, handler) => {
|
|
1437
|
+
logger$1.debug(`Scheduling cron job: ${cronExpression}`);
|
|
1438
|
+
const job = node_cron.default.schedule(cronExpression, (now) => handler(createContext(bot), now));
|
|
1439
|
+
const clear = () => {
|
|
1440
|
+
logger$1.debug(`Stopping cron job: ${cronExpression}`);
|
|
1441
|
+
job.stop();
|
|
1442
|
+
};
|
|
1443
|
+
clears.add(clear);
|
|
1444
|
+
return job;
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1286
1447
|
};
|
|
1287
|
-
|
|
1448
|
+
const mainContext = createContext(bots[0]);
|
|
1449
|
+
clears.add(await setup(mainContext) || (() => {}));
|
|
1288
1450
|
runtimePlugins.set(name, {
|
|
1289
1451
|
name,
|
|
1290
1452
|
type,
|
|
@@ -1303,7 +1465,7 @@ async function enablePlugin(bot, plugin, type = "external") {
|
|
|
1303
1465
|
});
|
|
1304
1466
|
const end = node_process.hrtime.bigint();
|
|
1305
1467
|
const time = Math.round(Number(end - start$1)) / 1e6;
|
|
1306
|
-
|
|
1468
|
+
logger$1.info(`- 启用插件 ${consola_utils.colors.yellow(`[${typeDesc}]`)} ${consola_utils.colors.yellow(`${name}@${version$1}`)} => 耗时 ${consola_utils.colors.green(time.toFixed(2))} 毫秒`);
|
|
1307
1469
|
} catch (e) {
|
|
1308
1470
|
throw new Error(`启用插件 ${consola_utils.colors.yellow(`[${typeDesc}]`)} ${consola_utils.colors.yellow(`${name}@${version$1}`)} 失败: ${e?.message}`);
|
|
1309
1471
|
}
|
|
@@ -1329,18 +1491,12 @@ const ArchMap = {
|
|
|
1329
1491
|
arm64: "arm64",
|
|
1330
1492
|
x64: "x64"
|
|
1331
1493
|
};
|
|
1332
|
-
async function getMiokiStatus(
|
|
1494
|
+
async function getMiokiStatus(bots) {
|
|
1333
1495
|
const osType = node_os.default.type();
|
|
1334
1496
|
const osArch = node_os.default.arch();
|
|
1335
1497
|
const isInUnix = ["Linux", "Darwin"].includes(osType);
|
|
1336
1498
|
const arch = ArchMap[osArch] || osArch;
|
|
1337
|
-
const [osInfo, localPlugins
|
|
1338
|
-
systeminformation.default.osInfo(),
|
|
1339
|
-
findLocalPlugins(),
|
|
1340
|
-
bot.getVersionInfo(),
|
|
1341
|
-
bot.getFriendList(),
|
|
1342
|
-
bot.getGroupList()
|
|
1343
|
-
]);
|
|
1499
|
+
const [osInfo, localPlugins] = await Promise.all([systeminformation.default.osInfo(), findLocalPlugins()]);
|
|
1344
1500
|
const pluginCount = localPlugins.length + BUILTIN_PLUGINS.length;
|
|
1345
1501
|
const system = isInUnix ? {
|
|
1346
1502
|
name: osInfo.distro,
|
|
@@ -1354,27 +1510,58 @@ async function getMiokiStatus(bot) {
|
|
|
1354
1510
|
const rssMem = process.memoryUsage.rss();
|
|
1355
1511
|
const nodeVersion = process.versions.node;
|
|
1356
1512
|
const cpu = getCpuInfo();
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1513
|
+
const botStatuses = [];
|
|
1514
|
+
let totalSend = 0;
|
|
1515
|
+
let totalReceive = 0;
|
|
1516
|
+
let mainVersionInfo = {
|
|
1517
|
+
app_version: "unknown",
|
|
1518
|
+
protocol_version: "unknown"
|
|
1519
|
+
};
|
|
1520
|
+
for (const bot of bots) try {
|
|
1521
|
+
const [versionInfo, friendList, groupList] = await Promise.all([
|
|
1522
|
+
bot.getVersionInfo(),
|
|
1523
|
+
bot.getFriendList(),
|
|
1524
|
+
bot.getGroupList()
|
|
1525
|
+
]);
|
|
1526
|
+
mainVersionInfo = versionInfo;
|
|
1527
|
+
botStatuses.push({
|
|
1528
|
+
uin: bot.bot_id,
|
|
1360
1529
|
nickname: bot.nickname,
|
|
1530
|
+
name: bot.name,
|
|
1361
1531
|
friends: friendList.length,
|
|
1362
|
-
groups: groupList.length
|
|
1363
|
-
|
|
1532
|
+
groups: groupList.length,
|
|
1533
|
+
send: bot.stat.send.group + bot.stat.send.private,
|
|
1534
|
+
receive: bot.stat.recv.group + bot.stat.recv.private
|
|
1535
|
+
});
|
|
1536
|
+
totalSend += bot.stat.send.group + bot.stat.send.private;
|
|
1537
|
+
totalReceive += bot.stat.recv.group + bot.stat.recv.private;
|
|
1538
|
+
} catch (err) {
|
|
1539
|
+
botStatuses.push({
|
|
1540
|
+
uin: bot.bot_id,
|
|
1541
|
+
nickname: bot.nickname,
|
|
1542
|
+
name: bot.name,
|
|
1543
|
+
friends: 0,
|
|
1544
|
+
groups: 0,
|
|
1545
|
+
send: 0,
|
|
1546
|
+
receive: 0
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
return {
|
|
1550
|
+
bots: botStatuses,
|
|
1364
1551
|
plugins: {
|
|
1365
1552
|
enabled: runtimePlugins.size,
|
|
1366
1553
|
total: pluginCount
|
|
1367
1554
|
},
|
|
1368
1555
|
stats: {
|
|
1369
1556
|
uptime: process.uptime() * 1e3,
|
|
1370
|
-
send:
|
|
1371
|
-
receive:
|
|
1557
|
+
send: totalSend,
|
|
1558
|
+
receive: totalReceive
|
|
1372
1559
|
},
|
|
1373
1560
|
versions: {
|
|
1374
1561
|
node: nodeVersion,
|
|
1375
1562
|
mioki: require_package.version,
|
|
1376
|
-
napcat:
|
|
1377
|
-
protocol:
|
|
1563
|
+
napcat: mainVersionInfo.app_version,
|
|
1564
|
+
protocol: mainVersionInfo.protocol_version
|
|
1378
1565
|
},
|
|
1379
1566
|
system: {
|
|
1380
1567
|
name: system.name || "N/A",
|
|
@@ -1404,16 +1591,16 @@ async function getMiokiStatus(bot) {
|
|
|
1404
1591
|
};
|
|
1405
1592
|
}
|
|
1406
1593
|
async function formatMiokiStatus(status) {
|
|
1407
|
-
const {
|
|
1594
|
+
const { bots, plugins, stats, system, disk, cpu, memory, versions } = status;
|
|
1408
1595
|
const diskValid = disk.total > 0 && disk.free >= 0;
|
|
1409
1596
|
const diskDesc = `${disk.percent}%-${(0, filesize.filesize)(disk.used, { round: 1 })}/${(0, filesize.filesize)(disk.total, { round: 1 })}`;
|
|
1410
1597
|
return `
|
|
1411
1598
|
〓 🟢 mioki 状态 〓
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1599
|
+
${bots.map((bot, index) => {
|
|
1600
|
+
return `👤 ${bot.name ? `[${bot.name}] ` : ""}${bot.nickname} (${bot.uin})\n 📋 ${localNum(bot.friends)} 好友 / ${localNum(bot.groups)} 群 / 📮 收 ${localNum(bot.receive)} 发 ${localNum(bot.send)}`;
|
|
1601
|
+
}).join("\n")}
|
|
1415
1602
|
🧩 启用了 ${localNum(plugins.enabled)} 个插件,共 ${localNum(plugins.total)} 个
|
|
1416
|
-
📮 收 ${localNum(stats.receive)} 条,发 ${localNum(stats.send)} 条
|
|
1603
|
+
📮 总计: 收 ${localNum(stats.receive)} 条,发 ${localNum(stats.send)} 条
|
|
1417
1604
|
🚀 ${(0, filesize.filesize)(memory.rss.used, { round: 1 })}/${memory.percent}%
|
|
1418
1605
|
⏳ 已运行 ${(0, pretty_ms.default)(stats.uptime, {
|
|
1419
1606
|
hideYear: true,
|
|
@@ -1497,7 +1684,7 @@ const core = definePlugin({
|
|
|
1497
1684
|
const displayPrefix = prefix.replace(/\\\\/g, "\\");
|
|
1498
1685
|
const statusAdminOnly = ctx.botConfig.status_permission === "admin-only";
|
|
1499
1686
|
let statusFormatter = (status) => formatMiokiStatus(status);
|
|
1500
|
-
ctx.addService("getMiokiStatus", () => getMiokiStatus(ctx.
|
|
1687
|
+
ctx.addService("getMiokiStatus", () => getMiokiStatus(ctx.bots));
|
|
1501
1688
|
ctx.addService("formatMiokiStatus", (status) => formatMiokiStatus(status));
|
|
1502
1689
|
ctx.addService("customFormatMiokiStatus", (formatter) => statusFormatter = formatter);
|
|
1503
1690
|
ctx.handle("message", (e) => ctx.runWithErrorHandler(async () => {
|
|
@@ -1505,7 +1692,7 @@ const core = definePlugin({
|
|
|
1505
1692
|
if (!cmdPrefix.test(text$1)) return;
|
|
1506
1693
|
if (statusAdminOnly && !ctx.hasRight(e)) return;
|
|
1507
1694
|
if (text$1.replace(cmdPrefix, "") === "状态") {
|
|
1508
|
-
const status = await statusFormatter(await getMiokiStatus(ctx.
|
|
1695
|
+
const status = await statusFormatter(await getMiokiStatus(ctx.bots));
|
|
1509
1696
|
await e.reply(status);
|
|
1510
1697
|
return;
|
|
1511
1698
|
}
|
|
@@ -1570,10 +1757,10 @@ const core = definePlugin({
|
|
|
1570
1757
|
const plugin = await ctx.jiti.import(pluginPath, { default: true });
|
|
1571
1758
|
if (plugin.name !== target) {
|
|
1572
1759
|
const tip = `[插件目录名称: ${target}] 和插件代码中设置的 [name: ${plugin.name}] 不一致,可能导致重载异常,请修改后重启。`;
|
|
1573
|
-
ctx.
|
|
1760
|
+
ctx.logger.warn(tip);
|
|
1574
1761
|
ctx.noticeMainOwner(tip);
|
|
1575
1762
|
}
|
|
1576
|
-
await enablePlugin(ctx.
|
|
1763
|
+
await enablePlugin(ctx.bots, plugin);
|
|
1577
1764
|
} catch (err) {
|
|
1578
1765
|
await e.reply(`插件 ${target} 启用失败:${err?.message || "未知错误"}`, true);
|
|
1579
1766
|
return;
|
|
@@ -1599,7 +1786,7 @@ const core = definePlugin({
|
|
|
1599
1786
|
break;
|
|
1600
1787
|
}
|
|
1601
1788
|
await ctx.updateBotConfig((c) => c.plugins = ctx.botConfig.plugins.filter((name) => name !== target));
|
|
1602
|
-
ctx.
|
|
1789
|
+
ctx.logger.info(`禁用插件 => ${target}`);
|
|
1603
1790
|
await e.reply(`插件 ${target} 已禁用`, true);
|
|
1604
1791
|
break;
|
|
1605
1792
|
}
|
|
@@ -1621,10 +1808,10 @@ const core = definePlugin({
|
|
|
1621
1808
|
const importedPlugin = await ctx.jiti.import(pluginPath, { default: true });
|
|
1622
1809
|
if (importedPlugin.name !== target) {
|
|
1623
1810
|
const tip = `插件目录名称: ${target} 和插件代码中设置的 name: ${importedPlugin.name} 不一致,可能导致重载异常,请修改后重启。`;
|
|
1624
|
-
ctx.
|
|
1811
|
+
ctx.logger.warn(tip);
|
|
1625
1812
|
ctx.noticeMainOwner(tip);
|
|
1626
1813
|
}
|
|
1627
|
-
await enablePlugin(ctx.
|
|
1814
|
+
await enablePlugin(ctx.bots, importedPlugin);
|
|
1628
1815
|
} catch (err) {
|
|
1629
1816
|
await e.reply(err?.message, true);
|
|
1630
1817
|
await ctx.updateBotConfig((c) => c.plugins = c.plugins.filter((name) => name !== target));
|
|
@@ -1737,7 +1924,7 @@ const core = definePlugin({
|
|
|
1737
1924
|
break;
|
|
1738
1925
|
case "退出":
|
|
1739
1926
|
await e.reply("またね~", true);
|
|
1740
|
-
ctx.
|
|
1927
|
+
ctx.logger.info("接收到退出指令,即将退出... 如需自动重启,请使用 pm2 部署。");
|
|
1741
1928
|
process.exit(0);
|
|
1742
1929
|
}
|
|
1743
1930
|
}, e));
|
|
@@ -1751,6 +1938,120 @@ const BUILTIN_PLUGINS = [core_default];
|
|
|
1751
1938
|
|
|
1752
1939
|
//#endregion
|
|
1753
1940
|
//#region src/start.ts
|
|
1941
|
+
const connectedBots = /* @__PURE__ */ new Map();
|
|
1942
|
+
async function connectBot(config, index) {
|
|
1943
|
+
const { protocol = "ws", port = 3001, host = "localhost", token = "", name } = config;
|
|
1944
|
+
const botName = name || `Bot${index + 1}`;
|
|
1945
|
+
const wsUrl = consola_utils.colors.green(`${protocol}://${host}:${port}${token ? "?access_token=***" : ""}`);
|
|
1946
|
+
logger.info(`>>> 正在连接 ${consola_utils.colors.cyan(botName)}: ${wsUrl}`);
|
|
1947
|
+
const napcat = new napcat_sdk.NapCat({
|
|
1948
|
+
token,
|
|
1949
|
+
protocol,
|
|
1950
|
+
host,
|
|
1951
|
+
port,
|
|
1952
|
+
logger
|
|
1953
|
+
});
|
|
1954
|
+
return new Promise((resolve) => {
|
|
1955
|
+
napcat.on("ws.close", () => {
|
|
1956
|
+
logger.warn(`${consola_utils.colors.yellow(botName)} WS 连接已关闭`);
|
|
1957
|
+
});
|
|
1958
|
+
napcat.on("ws.error", (err) => {
|
|
1959
|
+
logger.error(`${consola_utils.colors.red(botName)} WS 连接错误: ${err}`);
|
|
1960
|
+
});
|
|
1961
|
+
napcat.once("napcat.connected", ({ user_id, nickname, app_name, app_version }) => {
|
|
1962
|
+
logger.info(`已连接到 ${consola_utils.colors.cyan(botName)}: ${consola_utils.colors.green(`${app_name}-v${app_version} ${nickname}(${user_id})`)}`);
|
|
1963
|
+
if (connectedBots.has(user_id)) {
|
|
1964
|
+
const existingBot = connectedBots.get(user_id);
|
|
1965
|
+
if (existingBot.name) logger.warn(`${consola_utils.colors.yellow(botName)} (${user_id}) 与 ${consola_utils.colors.yellow(existingBot.name)} (${user_id}) QQ 号重复,将跳过`);
|
|
1966
|
+
napcat.close();
|
|
1967
|
+
resolve(null);
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
const extendedNapCat = napcat;
|
|
1971
|
+
extendedNapCat.bot_id = user_id;
|
|
1972
|
+
extendedNapCat.app_name = app_name;
|
|
1973
|
+
extendedNapCat.app_version = app_version;
|
|
1974
|
+
extendedNapCat.name = botName;
|
|
1975
|
+
resolve(extendedNapCat);
|
|
1976
|
+
});
|
|
1977
|
+
napcat.run().catch((err) => {
|
|
1978
|
+
logger.error(`${consola_utils.colors.red(botName)} 连接失败: ${err.message}`);
|
|
1979
|
+
resolve(null);
|
|
1980
|
+
});
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1983
|
+
async function setupPlugins(napcat, bots) {
|
|
1984
|
+
const plugin_dir = getAbsPluginDir();
|
|
1985
|
+
const mainBot = napcat;
|
|
1986
|
+
ensurePluginDir();
|
|
1987
|
+
const plugins = botConfig.plugins.map((p) => ({
|
|
1988
|
+
dirName: p,
|
|
1989
|
+
absPath: node_path.default.resolve(plugin_dir, p)
|
|
1990
|
+
})).filter((p) => {
|
|
1991
|
+
if (!node_fs.default.existsSync(p.absPath)) {
|
|
1992
|
+
mainBot.logger.warn(`插件 ${consola_utils.colors.red(p.dirName)} 不存在,已忽略`);
|
|
1993
|
+
return false;
|
|
1994
|
+
}
|
|
1995
|
+
return true;
|
|
1996
|
+
});
|
|
1997
|
+
const failedImportPlugins = [];
|
|
1998
|
+
const promises = plugins.map(async ({ absPath, dirName }) => {
|
|
1999
|
+
try {
|
|
2000
|
+
const plugin = await jiti$1.import(absPath, { default: true });
|
|
2001
|
+
if (plugin.name !== dirName) {
|
|
2002
|
+
const tip = `插件目录名 [${consola_utils.colors.yellow(dirName)}] 和插件声明的 name [${consola_utils.colors.yellow(plugin.name)}] 不一致,可能导致重载异常,请修改一致后重启。`;
|
|
2003
|
+
mainBot.logger.warn(tip);
|
|
2004
|
+
noticeMainOwner(mainBot, tip);
|
|
2005
|
+
}
|
|
2006
|
+
return plugin;
|
|
2007
|
+
} catch (e) {
|
|
2008
|
+
const err = stringifyError(e);
|
|
2009
|
+
failedImportPlugins.push([dirName, err]);
|
|
2010
|
+
return null;
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
const start$1 = node_process.hrtime.bigint();
|
|
2014
|
+
const sortedUserPlugins = (await Promise.all(promises)).filter(Boolean).toSorted((prev, next) => (prev.priority ?? 100) - (next.priority ?? 100));
|
|
2015
|
+
if (failedImportPlugins.length) {
|
|
2016
|
+
const tip = `${consola_utils.colors.red(failedImportPlugins.length)} 个插件加载失败: \n\n${failedImportPlugins.map(([dirName, err]) => `${dirName}: ${err}`).join("\n\n")}`;
|
|
2017
|
+
mainBot.logger.warn(tip);
|
|
2018
|
+
noticeMainOwner(mainBot, tip);
|
|
2019
|
+
}
|
|
2020
|
+
const pluginGroups = /* @__PURE__ */ new Map();
|
|
2021
|
+
for (const plugin of sortedUserPlugins) {
|
|
2022
|
+
const priority = plugin.priority ?? 100;
|
|
2023
|
+
if (!pluginGroups.has(priority)) pluginGroups.set(priority, []);
|
|
2024
|
+
pluginGroups.get(priority).push(plugin);
|
|
2025
|
+
}
|
|
2026
|
+
const sortedGroups = Array.from(pluginGroups.entries()).toSorted(([a], [b]) => a - b);
|
|
2027
|
+
const failedEnablePlugins = [];
|
|
2028
|
+
try {
|
|
2029
|
+
mainBot.logger.info(`>>> 加载内置插件: ${BUILTIN_PLUGINS.map((p) => consola_utils.colors.cyan(p.name)).join(", ")}`);
|
|
2030
|
+
await Promise.all(BUILTIN_PLUGINS.map((p) => enablePlugin(bots, p, "builtin")));
|
|
2031
|
+
mainBot.logger.info(`>>> 加载用户插件: ${sortedGroups.map(([priority, plugins$1]) => `优先级 ${consola_utils.colors.yellow(priority)} (${plugins$1.map((p) => consola_utils.colors.cyan(p.name)).join(", ")})`).join(",")}`);
|
|
2032
|
+
for (const [_, plugins$1] of sortedGroups) await Promise.all(plugins$1.map(async (p) => {
|
|
2033
|
+
try {
|
|
2034
|
+
await enablePlugin(bots, p, "external");
|
|
2035
|
+
} catch (e) {
|
|
2036
|
+
failedEnablePlugins.push([p.name, stringifyError(e)]);
|
|
2037
|
+
}
|
|
2038
|
+
}));
|
|
2039
|
+
} catch (e) {
|
|
2040
|
+
mainBot.logger.error(e?.message);
|
|
2041
|
+
await noticeMainOwner(mainBot, e?.message).catch(() => {
|
|
2042
|
+
mainBot.logger.error("发送插件启用失败通知失败");
|
|
2043
|
+
});
|
|
2044
|
+
}
|
|
2045
|
+
const end = node_process.hrtime.bigint();
|
|
2046
|
+
const costTime = Math.round(Number(end - start$1)) / 1e6;
|
|
2047
|
+
const failedCount = failedImportPlugins.length + failedEnablePlugins.length;
|
|
2048
|
+
const failedInfo = failedCount > 0 ? `${consola_utils.colors.red(failedCount)} 个失败 (导入 ${consola_utils.colors.red(failedImportPlugins.length)},启用 ${consola_utils.colors.red(failedEnablePlugins.length)})` : "";
|
|
2049
|
+
mainBot.logger.info(`成功加载了 ${consola_utils.colors.green(runtimePlugins.size)} 个插件,${failedInfo ? failedInfo : ""}总耗时 ${consola_utils.colors.green(costTime.toFixed(2))} 毫秒`);
|
|
2050
|
+
mainBot.logger.info(consola_utils.colors.green(`mioki v${require_package.version} 启动完成,向机器人发送「${consola_utils.colors.magentaBright(`${botConfig.prefix}帮助`)}」查看消息指令`));
|
|
2051
|
+
if (botConfig.online_push) await noticeMainOwner(mainBot, `✅ mioki v${require_package.version} 已就绪`).catch((err) => {
|
|
2052
|
+
mainBot.logger.error(`发送就绪通知失败: ${stringifyError(err)}`);
|
|
2053
|
+
});
|
|
2054
|
+
}
|
|
1754
2055
|
async function start(options = {}) {
|
|
1755
2056
|
const { cwd = process.cwd() } = options;
|
|
1756
2057
|
if (cwd !== BOT_CWD.value) updateBotCWD(node_path.default.resolve(cwd));
|
|
@@ -1769,117 +2070,67 @@ async function start(options = {}) {
|
|
|
1769
2070
|
logger.info(`${consola_utils.colors.dim("插件目录: ")}${consola_utils.colors.blue(plugin_dir)}`);
|
|
1770
2071
|
logger.info(`${consola_utils.colors.dim("配置文件: ")}${consola_utils.colors.blue(`${BOT_CWD.value}/package.json`)}`);
|
|
1771
2072
|
logger.info(consola_utils.colors.dim("=".repeat(40)));
|
|
1772
|
-
const
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
2073
|
+
const napcatConfigs = botConfig.napcat;
|
|
2074
|
+
if (napcatConfigs.length === 0) {
|
|
2075
|
+
logger.warn("未配置任何 NapCat 实例,框架将以无实例模式启动");
|
|
2076
|
+
logger.info(consola_utils.colors.green(`mioki v${require_package.version} 启动完成,向机器人发送「${consola_utils.colors.magentaBright(`${botConfig.prefix}帮助`)}」查看消息指令`));
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
const seenEndpoints = /* @__PURE__ */ new Set();
|
|
2080
|
+
const duplicateConfigs = [];
|
|
2081
|
+
for (const config of napcatConfigs) {
|
|
2082
|
+
const { protocol = "ws", host = "localhost", port = 3001 } = config;
|
|
2083
|
+
const endpoint = `${protocol}://${host}:${port}`;
|
|
2084
|
+
if (seenEndpoints.has(endpoint)) duplicateConfigs.push(`${config.name || "未命名"} (${endpoint})`);
|
|
2085
|
+
else seenEndpoints.add(endpoint);
|
|
2086
|
+
}
|
|
2087
|
+
if (duplicateConfigs.length > 0) {
|
|
2088
|
+
logger.error(`检测到重复的 NapCat 实例配置:`);
|
|
2089
|
+
duplicateConfigs.forEach((dup) => logger.error(` - ${dup}`));
|
|
2090
|
+
logger.error("请检查配置文件,确保每个实例的 host:port 组合唯一");
|
|
1784
2091
|
process.exit(1);
|
|
1785
|
-
}
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
2092
|
+
}
|
|
2093
|
+
logger.info(consola_utils.colors.dim("=".repeat(40)));
|
|
2094
|
+
logger.info(`>>> 正在连接 ${napcatConfigs.length} 个 NapCat 实例...`);
|
|
2095
|
+
const bots = (await Promise.all(napcatConfigs.map((config, index) => connectBot(config, index)))).filter((b) => b !== null);
|
|
2096
|
+
if (bots.length === 0) {
|
|
2097
|
+
logger.error("所有 NapCat 实例连接失败,框架无法启动");
|
|
2098
|
+
process.exit(1);
|
|
2099
|
+
}
|
|
2100
|
+
for (const bot of bots) connectedBots.set(bot.bot_id, bot);
|
|
2101
|
+
if (bots.length < napcatConfigs.length) logger.warn(`${consola_utils.colors.yellow(napcatConfigs.length - bots.length)} 个 NapCat 实例连接失败`);
|
|
2102
|
+
const botNames = bots.map((b) => `${b.name}(${b.bot_id})`).join(", ");
|
|
2103
|
+
logger.info(consola_utils.colors.green(`成功连接 ${bots.length} 个实例: ${botNames}`));
|
|
2104
|
+
logger.info(consola_utils.colors.dim("=".repeat(40)));
|
|
2105
|
+
const mainBot = bots[0];
|
|
2106
|
+
process.title = `mioki v${require_package.version} ${bots.map((b) => `${b.bot_id}`).join(", ")}`;
|
|
2107
|
+
let lastNoticeTime = 0;
|
|
2108
|
+
for (const bot of bots) {
|
|
1790
2109
|
process.on("uncaughtException", async (err) => {
|
|
1791
2110
|
const msg = stringifyError(err);
|
|
1792
|
-
|
|
2111
|
+
bot.logger.error(`uncaughtException, 出错了: ${msg}`);
|
|
1793
2112
|
if (botConfig.error_push) {
|
|
1794
2113
|
if (Date.now() - lastNoticeTime < 1e3) return;
|
|
1795
2114
|
lastNoticeTime = Date.now();
|
|
1796
|
-
await noticeMainOwner(
|
|
1797
|
-
|
|
2115
|
+
await noticeMainOwner(mainBot, `mioki 发生未捕获异常:\n\n${msg}`).catch(() => {
|
|
2116
|
+
mainBot.logger.error("发送未捕获异常通知失败");
|
|
1798
2117
|
});
|
|
1799
2118
|
}
|
|
1800
2119
|
});
|
|
1801
2120
|
process.on("unhandledRejection", async (err) => {
|
|
1802
2121
|
const msg = stringifyError(err);
|
|
1803
|
-
|
|
2122
|
+
bot.logger.error(`unhandledRejection, 出错了: ${msg}`);
|
|
1804
2123
|
if (botConfig.error_push) {
|
|
1805
2124
|
if (Date.now() - lastNoticeTime < 1e3) return;
|
|
1806
2125
|
lastNoticeTime = Date.now();
|
|
1807
2126
|
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
1808
|
-
await noticeMainOwner(
|
|
1809
|
-
|
|
2127
|
+
await noticeMainOwner(mainBot, `【${date}】\n\nmioki 发生未处理异常:\n\n${msg}`).catch(() => {
|
|
2128
|
+
mainBot.logger.error("发送未处理异常通知失败");
|
|
1810
2129
|
});
|
|
1811
2130
|
}
|
|
1812
2131
|
});
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
dirName: p,
|
|
1816
|
-
absPath: node_path.default.resolve(plugin_dir, p)
|
|
1817
|
-
})).filter((p) => {
|
|
1818
|
-
if (!node_fs.default.existsSync(p.absPath)) {
|
|
1819
|
-
napcat.logger.warn(`插件 ${consola_utils.colors.red(p.dirName)} 不存在,已忽略`);
|
|
1820
|
-
return false;
|
|
1821
|
-
}
|
|
1822
|
-
return true;
|
|
1823
|
-
});
|
|
1824
|
-
const failedImportPlugins = [];
|
|
1825
|
-
const promises = plugins.map(async ({ absPath, dirName }) => {
|
|
1826
|
-
try {
|
|
1827
|
-
const plugin = await jiti$1.import(absPath, { default: true });
|
|
1828
|
-
if (plugin.name !== dirName) {
|
|
1829
|
-
const tip = `插件目录名 [${consola_utils.colors.yellow(dirName)}] 和插件声明的 name [${consola_utils.colors.yellow(plugin.name)}] 不一致,可能导致重载异常,请修改一致后重启。`;
|
|
1830
|
-
napcat.logger.warn(tip);
|
|
1831
|
-
noticeMainOwner(napcat, tip);
|
|
1832
|
-
}
|
|
1833
|
-
return plugin;
|
|
1834
|
-
} catch (e) {
|
|
1835
|
-
const err = stringifyError(e);
|
|
1836
|
-
failedImportPlugins.push([dirName, err]);
|
|
1837
|
-
return null;
|
|
1838
|
-
}
|
|
1839
|
-
});
|
|
1840
|
-
const start$1 = node_process.hrtime.bigint();
|
|
1841
|
-
const sortedUserPlugins = (await Promise.all(promises)).filter(Boolean).toSorted((prev, next) => (prev.priority ?? 100) - (next.priority ?? 100));
|
|
1842
|
-
if (failedImportPlugins.length) {
|
|
1843
|
-
const tip = `${consola_utils.colors.red(failedImportPlugins.length)} 个插件加载失败: \n\n${failedImportPlugins.map(([dirName, err]) => `${dirName}: ${err}`).join("\n\n")}`;
|
|
1844
|
-
napcat.logger.warn(tip);
|
|
1845
|
-
noticeMainOwner(napcat, tip);
|
|
1846
|
-
}
|
|
1847
|
-
const pluginGroups = /* @__PURE__ */ new Map();
|
|
1848
|
-
for (const plugin of sortedUserPlugins) {
|
|
1849
|
-
const priority = plugin.priority ?? 100;
|
|
1850
|
-
if (!pluginGroups.has(priority)) pluginGroups.set(priority, []);
|
|
1851
|
-
pluginGroups.get(priority).push(plugin);
|
|
1852
|
-
}
|
|
1853
|
-
const sortedGroups = Array.from(pluginGroups.entries()).toSorted(([a], [b]) => a - b);
|
|
1854
|
-
const failedEnablePlugins = [];
|
|
1855
|
-
try {
|
|
1856
|
-
napcat.logger.info(`>>> 加载内置插件: ${BUILTIN_PLUGINS.map((p) => consola_utils.colors.cyan(p.name)).join(", ")}`);
|
|
1857
|
-
await Promise.all(BUILTIN_PLUGINS.map((p) => enablePlugin(napcat, p, "builtin")));
|
|
1858
|
-
napcat.logger.info(`>>> 加载用户插件: ${sortedGroups.map(([priority, plugins$1]) => `优先级 ${consola_utils.colors.yellow(priority)} (${plugins$1.map((p) => consola_utils.colors.cyan(p.name)).join(", ")})`).join(",")}`);
|
|
1859
|
-
for (const [_, plugins$1] of sortedGroups) await Promise.all(plugins$1.map(async (p) => {
|
|
1860
|
-
try {
|
|
1861
|
-
await enablePlugin(napcat, p, "external");
|
|
1862
|
-
} catch (e) {
|
|
1863
|
-
failedEnablePlugins.push([p.name, stringifyError(e)]);
|
|
1864
|
-
}
|
|
1865
|
-
}));
|
|
1866
|
-
} catch (e) {
|
|
1867
|
-
napcat.logger.error(e?.message);
|
|
1868
|
-
await noticeMainOwner(napcat, e?.message).catch(() => {
|
|
1869
|
-
napcat.logger.error("发送插件启用失败通知失败");
|
|
1870
|
-
});
|
|
1871
|
-
}
|
|
1872
|
-
const end = node_process.hrtime.bigint();
|
|
1873
|
-
const costTime = Math.round(Number(end - start$1)) / 1e6;
|
|
1874
|
-
const failedCount = failedImportPlugins.length + failedEnablePlugins.length;
|
|
1875
|
-
const failedInfo = failedCount > 0 ? `${consola_utils.colors.red(failedCount)} 个失败 (导入 ${consola_utils.colors.red(failedImportPlugins.length)},启用 ${consola_utils.colors.red(failedEnablePlugins.length)})` : "";
|
|
1876
|
-
napcat.logger.info(`成功加载了 ${consola_utils.colors.green(runtimePlugins.size)} 个插件,${failedInfo ? failedInfo : ""}总耗时 ${consola_utils.colors.green(costTime.toFixed(2))} 毫秒`);
|
|
1877
|
-
napcat.logger.info(consola_utils.colors.green(`mioki v${require_package.version} 启动完成,向机器人发送「${consola_utils.colors.magentaBright(`${botConfig.prefix}帮助`)}」查看消息指令`));
|
|
1878
|
-
if (botConfig.online_push) await noticeMainOwner(napcat, `✅ mioki v${require_package.version} 已就绪`).catch((err) => {
|
|
1879
|
-
napcat.logger.error(`发送就绪通知失败: ${stringifyError(err)}`);
|
|
1880
|
-
});
|
|
1881
|
-
});
|
|
1882
|
-
await napcat.run();
|
|
2132
|
+
}
|
|
2133
|
+
await setupPlugins(mainBot, bots);
|
|
1883
2134
|
}
|
|
1884
2135
|
|
|
1885
2136
|
//#endregion
|
|
@@ -1888,6 +2139,8 @@ exports.BOT_CWD = BOT_CWD;
|
|
|
1888
2139
|
exports.BUILTIN_PLUGINS = BUILTIN_PLUGINS;
|
|
1889
2140
|
exports.CORE_PLUGINS = CORE_PLUGINS;
|
|
1890
2141
|
exports.ChromeUA = ChromeUA;
|
|
2142
|
+
exports.Deduplicator = Deduplicator;
|
|
2143
|
+
exports.MessageDeduplicator = MessageDeduplicator;
|
|
1891
2144
|
exports.START_TIME = START_TIME;
|
|
1892
2145
|
exports.SystemMap = SystemMap;
|
|
1893
2146
|
exports.addService = addService;
|
|
@@ -1914,6 +2167,7 @@ Object.defineProperty(exports, 'colors', {
|
|
|
1914
2167
|
return consola_utils.colors;
|
|
1915
2168
|
}
|
|
1916
2169
|
});
|
|
2170
|
+
exports.connectedBots = connectedBots;
|
|
1917
2171
|
exports.createCmd = createCmd;
|
|
1918
2172
|
exports.createDB = createDB;
|
|
1919
2173
|
exports.createForwardMsg = createForwardMsg;
|
|
@@ -1930,6 +2184,7 @@ Object.defineProperty(exports, 'dedent', {
|
|
|
1930
2184
|
return dedent.default;
|
|
1931
2185
|
}
|
|
1932
2186
|
});
|
|
2187
|
+
exports.deduplicator = deduplicator;
|
|
1933
2188
|
exports.definePlugin = definePlugin;
|
|
1934
2189
|
exports.enablePlugin = enablePlugin;
|
|
1935
2190
|
exports.ensureBuffer = ensureBuffer;
|
|
@@ -2000,6 +2255,7 @@ Object.defineProperty(exports, 'mri', {
|
|
|
2000
2255
|
}
|
|
2001
2256
|
});
|
|
2002
2257
|
exports.noNullish = noNullish;
|
|
2258
|
+
exports.normalizeNapCatConfig = normalizeNapCatConfig;
|
|
2003
2259
|
exports.noticeAdmins = noticeAdmins;
|
|
2004
2260
|
exports.noticeFriends = noticeFriends;
|
|
2005
2261
|
exports.noticeGroups = noticeGroups;
|