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.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BiucMVzj.mjs";
|
|
2
|
-
import { t as version } from "./package-
|
|
2
|
+
import { t as version } from "./package-B4h-fhCq.mjs";
|
|
3
3
|
import fs, { default as fs$1 } from "node:fs";
|
|
4
4
|
import util from "node:util";
|
|
5
5
|
import path, { default as path$1 } from "node:path";
|
|
@@ -779,12 +779,20 @@ var config_exports = /* @__PURE__ */ __exportAll({
|
|
|
779
779
|
isInPm2: () => isInPm2,
|
|
780
780
|
isOwner: () => isOwner,
|
|
781
781
|
isOwnerOrAdmin: () => isOwnerOrAdmin,
|
|
782
|
+
normalizeNapCatConfig: () => normalizeNapCatConfig,
|
|
782
783
|
readMiokiConfig: () => readMiokiConfig,
|
|
783
784
|
readPackageJson: () => readPackageJson,
|
|
784
785
|
updateBotCWD: () => updateBotCWD,
|
|
785
786
|
updateBotConfig: () => updateBotConfig,
|
|
786
787
|
writePackageJson: () => writePackageJson
|
|
787
788
|
});
|
|
789
|
+
function isSingleNapCatConfig(config) {
|
|
790
|
+
return !Array.isArray(config);
|
|
791
|
+
}
|
|
792
|
+
function normalizeNapCatConfig(config) {
|
|
793
|
+
if (isSingleNapCatConfig(config)) return [config];
|
|
794
|
+
return config;
|
|
795
|
+
}
|
|
788
796
|
/**
|
|
789
797
|
* 机器人根目录
|
|
790
798
|
*/
|
|
@@ -800,7 +808,10 @@ function readMiokiConfig() {
|
|
|
800
808
|
const config = readPackageJson().mioki;
|
|
801
809
|
if (!config) throw new Error(`无法在 package.json 中找到 mioki 配置,请确认 package.json 文件中是否包含 mioki 字段`);
|
|
802
810
|
if (!config.napcat) throw new Error(`mioki 配置中缺少 napcat 字段,请补全后重试`);
|
|
803
|
-
return
|
|
811
|
+
return {
|
|
812
|
+
...config,
|
|
813
|
+
napcat: normalizeNapCatConfig(config.napcat)
|
|
814
|
+
};
|
|
804
815
|
}
|
|
805
816
|
/**
|
|
806
817
|
* `mioki` 框架相关配置
|
|
@@ -1201,9 +1212,132 @@ function addService(name, service, cover = true) {
|
|
|
1201
1212
|
function bindBot(bot, func) {
|
|
1202
1213
|
return (...args) => func(bot, ...args);
|
|
1203
1214
|
}
|
|
1215
|
+
/**
|
|
1216
|
+
* 去重器
|
|
1217
|
+
* 处理多个 bot 在相同场景下,同一事件只处理一次
|
|
1218
|
+
*/
|
|
1219
|
+
var Deduplicator = class {
|
|
1220
|
+
processedEvents = /* @__PURE__ */ new Set();
|
|
1221
|
+
maxSize = 1e3;
|
|
1222
|
+
/**
|
|
1223
|
+
* 获取事件类型键
|
|
1224
|
+
*/
|
|
1225
|
+
getEventTypeKey(e) {
|
|
1226
|
+
const { post_type } = e;
|
|
1227
|
+
if (post_type === "message") return `msg:${e.message_type}`;
|
|
1228
|
+
if (post_type === "request") {
|
|
1229
|
+
if (e.request_type === "friend") return "req:friend";
|
|
1230
|
+
return `req:group:${e.sub_type ?? "unknown"}`;
|
|
1231
|
+
}
|
|
1232
|
+
if (post_type === "notice") {
|
|
1233
|
+
if (e.notice_type === "group") return `notice:group:${e.sub_type}`;
|
|
1234
|
+
return `notice:${e.notice_type}:${e.sub_type}`;
|
|
1235
|
+
}
|
|
1236
|
+
return "unknown";
|
|
1237
|
+
}
|
|
1238
|
+
getGroupMessageKey(e) {
|
|
1239
|
+
const groupId = e.group_id ?? "_";
|
|
1240
|
+
const userId = e.user_id ?? "_";
|
|
1241
|
+
const time = e.time ?? "_";
|
|
1242
|
+
const raw = e.raw_message ?? "_";
|
|
1243
|
+
return `msg:group:${groupId}:${userId}:${time}:${crypto.createHash("md5").update(raw).digest("hex")}`;
|
|
1244
|
+
}
|
|
1245
|
+
getNoticeGroupKey(e) {
|
|
1246
|
+
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 ?? "_"}`;
|
|
1247
|
+
}
|
|
1248
|
+
getRequestKey(e) {
|
|
1249
|
+
const typeKey = this.getEventTypeKey(e);
|
|
1250
|
+
const userId = e.user_id ?? "_";
|
|
1251
|
+
const groupId = "group_id" in e ? e.group_id ?? "_" : "_";
|
|
1252
|
+
const time = e.time ?? "_";
|
|
1253
|
+
const comment = e.comment ?? "_";
|
|
1254
|
+
return `${typeKey}:${userId}:${groupId}:${time}:${comment ? crypto.createHash("md5").update(comment).digest("hex") : "_"}`;
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* 生成事件唯一键
|
|
1258
|
+
*/
|
|
1259
|
+
getKey(e) {
|
|
1260
|
+
const typeKey = this.getEventTypeKey(e);
|
|
1261
|
+
if (typeKey === "msg:group") return this.getGroupMessageKey(e);
|
|
1262
|
+
if (typeKey.startsWith("notice:group:")) return this.getNoticeGroupKey(e);
|
|
1263
|
+
if (typeKey.startsWith("req:")) return this.getRequestKey(e);
|
|
1264
|
+
return "";
|
|
1265
|
+
}
|
|
1266
|
+
/**
|
|
1267
|
+
* 检查事件是否已处理过
|
|
1268
|
+
* @param event
|
|
1269
|
+
* @param scope
|
|
1270
|
+
*/
|
|
1271
|
+
isProcessed(event, scope) {
|
|
1272
|
+
const key = scope ? `${this.getKey(event)}:${scope}` : this.getKey(event);
|
|
1273
|
+
return this.processedEvents.has(key);
|
|
1274
|
+
}
|
|
1275
|
+
/**
|
|
1276
|
+
* 标记事件为已处理
|
|
1277
|
+
* @param event
|
|
1278
|
+
* @param scope 需与 isProcessed 一致
|
|
1279
|
+
*/
|
|
1280
|
+
markProcessed(event, scope) {
|
|
1281
|
+
const key = scope ? `${this.getKey(event)}:${scope}` : this.getKey(event);
|
|
1282
|
+
if (this.processedEvents.size >= this.maxSize) {
|
|
1283
|
+
const first = this.processedEvents.values().next();
|
|
1284
|
+
if (!first.done) this.processedEvents.delete(first.value);
|
|
1285
|
+
}
|
|
1286
|
+
this.processedEvents.add(key);
|
|
1287
|
+
}
|
|
1288
|
+
};
|
|
1289
|
+
/**
|
|
1290
|
+
* 消息去重器
|
|
1291
|
+
* @deprecated 请使用 Deduplicator,它支持更多事件类型
|
|
1292
|
+
*/
|
|
1293
|
+
var MessageDeduplicator = class extends Deduplicator {
|
|
1294
|
+
isProcessed(event) {
|
|
1295
|
+
return super.isProcessed(event);
|
|
1296
|
+
}
|
|
1297
|
+
markProcessed(event) {
|
|
1298
|
+
super.markProcessed(event);
|
|
1299
|
+
}
|
|
1300
|
+
};
|
|
1301
|
+
const deduplicator = new Deduplicator();
|
|
1204
1302
|
const runtimePlugins = /* @__PURE__ */ new Map();
|
|
1205
1303
|
const buildRemovedActions = (bot) => Object.fromEntries(Object.entries(actions_exports).map(([k, v]) => [k, bindBot(bot, v)]));
|
|
1206
1304
|
/**
|
|
1305
|
+
* 检查事件是否是群消息事件
|
|
1306
|
+
*/
|
|
1307
|
+
function isGroupMessageEvent(event) {
|
|
1308
|
+
return event?.post_type === "message" && event?.message_type === "group";
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* 检查事件是否是私聊消息事件
|
|
1312
|
+
*/
|
|
1313
|
+
function isPrivateMessageEvent(event) {
|
|
1314
|
+
return event?.post_type === "message" && event?.message_type === "private";
|
|
1315
|
+
}
|
|
1316
|
+
/**
|
|
1317
|
+
* 检查事件是否是消息事件
|
|
1318
|
+
*/
|
|
1319
|
+
function isMessageEvent(event) {
|
|
1320
|
+
return isGroupMessageEvent(event) || isPrivateMessageEvent(event);
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
* 检查事件是否是请求事件
|
|
1324
|
+
*/
|
|
1325
|
+
function isRequestEvent(event) {
|
|
1326
|
+
return event?.post_type === "request";
|
|
1327
|
+
}
|
|
1328
|
+
/**
|
|
1329
|
+
* 检查事件是否是群通知事件
|
|
1330
|
+
*/
|
|
1331
|
+
function isGroupNoticeEvent(event) {
|
|
1332
|
+
return event?.post_type === "notice" && event?.notice_type === "group";
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* 检查事件是否需要去重
|
|
1336
|
+
*/
|
|
1337
|
+
function isDeduplicableEvent(event) {
|
|
1338
|
+
return isMessageEvent(event) || isRequestEvent(event) || isGroupNoticeEvent(event);
|
|
1339
|
+
}
|
|
1340
|
+
/**
|
|
1207
1341
|
* 定义一个 Mioki 插件
|
|
1208
1342
|
* @param plugin Mioki 插件对象
|
|
1209
1343
|
* @returns Mioki 插件对象
|
|
@@ -1225,55 +1359,83 @@ function getAbsPluginDir(defaultDir = "plugins") {
|
|
|
1225
1359
|
const cwd = BOT_CWD.value;
|
|
1226
1360
|
return path$1.join(cwd, botConfig.plugins_dir || defaultDir);
|
|
1227
1361
|
}
|
|
1228
|
-
async function enablePlugin(
|
|
1362
|
+
async function enablePlugin(bots, plugin, type = "external") {
|
|
1229
1363
|
const typeDesc = type === "builtin" ? "内置" : "用户";
|
|
1230
1364
|
const pluginName = plugin.name || "null";
|
|
1231
1365
|
const { name = pluginName, version: version$1 = "null", description = "-", setup = () => {} } = plugin;
|
|
1366
|
+
if (!bots[0]) throw new Error("没有可用的 bot 实例");
|
|
1232
1367
|
try {
|
|
1233
1368
|
const start$1 = hrtime.bigint();
|
|
1234
1369
|
const clears = /* @__PURE__ */ new Set();
|
|
1235
1370
|
const userClears = /* @__PURE__ */ new Set();
|
|
1236
|
-
const logger$1 =
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
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
|
-
|
|
1371
|
+
const logger$1 = logger.withDefaults({ tag: `plugin:${name}` });
|
|
1372
|
+
const createContext = (bot) => {
|
|
1373
|
+
return {
|
|
1374
|
+
bot,
|
|
1375
|
+
bots,
|
|
1376
|
+
self_id: bot.bot_id,
|
|
1377
|
+
segment: bot.segment,
|
|
1378
|
+
getCookie: bot.getCookie.bind(bot),
|
|
1379
|
+
...utils_exports,
|
|
1380
|
+
...config_exports,
|
|
1381
|
+
...buildRemovedActions(bot),
|
|
1382
|
+
logger: logger$1,
|
|
1383
|
+
services,
|
|
1384
|
+
clears: userClears,
|
|
1385
|
+
deduplicator,
|
|
1386
|
+
addService: (name$1, service, cover) => {
|
|
1387
|
+
const remove = addService(name$1, service, cover);
|
|
1388
|
+
clears.add(remove);
|
|
1389
|
+
return remove;
|
|
1390
|
+
},
|
|
1391
|
+
handle: (eventName, handler, options = {}) => {
|
|
1392
|
+
logger$1.debug(`Registering event handler for event: ${String(eventName)}`);
|
|
1393
|
+
const { deduplicate = true } = options;
|
|
1394
|
+
const dedupeScope = `${name}:${String(eventName)}:${crypto.randomUUID()}`;
|
|
1395
|
+
const unsubscribes = [];
|
|
1396
|
+
for (const bot$1 of bots) {
|
|
1397
|
+
const wrappedHandler = (e) => {
|
|
1398
|
+
if (isPrivateMessageEvent(e)) {
|
|
1399
|
+
if (e.self_id !== bot$1.bot_id) return;
|
|
1400
|
+
}
|
|
1401
|
+
const senderUserId = e.user_id;
|
|
1402
|
+
const senderOperatorId = e.operator_id;
|
|
1403
|
+
const isFromConnectedBot = senderUserId && bots.some((b) => b.bot_id === senderUserId);
|
|
1404
|
+
const isFromConnectedBotOperator = senderOperatorId && bots.some((b) => b.bot_id === senderOperatorId);
|
|
1405
|
+
if (isFromConnectedBot || isFromConnectedBotOperator) return;
|
|
1406
|
+
if (deduplicate && isDeduplicableEvent(e)) {
|
|
1407
|
+
if (deduplicator.isProcessed(e, dedupeScope)) return;
|
|
1408
|
+
deduplicator.markProcessed(e, dedupeScope);
|
|
1409
|
+
}
|
|
1410
|
+
handler(e);
|
|
1411
|
+
};
|
|
1412
|
+
bot$1.on(eventName, wrappedHandler);
|
|
1413
|
+
const unsubscribe = () => {
|
|
1414
|
+
logger$1.debug(`Unregistering event handler for event: ${String(eventName)}`);
|
|
1415
|
+
bot$1.off(eventName, wrappedHandler);
|
|
1416
|
+
};
|
|
1417
|
+
unsubscribes.push(unsubscribe);
|
|
1418
|
+
}
|
|
1419
|
+
const clearAll = () => {
|
|
1420
|
+
unsubscribes.forEach((fn) => fn());
|
|
1421
|
+
};
|
|
1422
|
+
clears.add(clearAll);
|
|
1423
|
+
return clearAll;
|
|
1424
|
+
},
|
|
1425
|
+
cron: (cronExpression, handler) => {
|
|
1426
|
+
logger$1.debug(`Scheduling cron job: ${cronExpression}`);
|
|
1427
|
+
const job = nodeCron.schedule(cronExpression, (now) => handler(createContext(bot), now));
|
|
1428
|
+
const clear = () => {
|
|
1429
|
+
logger$1.debug(`Stopping cron job: ${cronExpression}`);
|
|
1430
|
+
job.stop();
|
|
1431
|
+
};
|
|
1432
|
+
clears.add(clear);
|
|
1433
|
+
return job;
|
|
1434
|
+
}
|
|
1435
|
+
};
|
|
1275
1436
|
};
|
|
1276
|
-
|
|
1437
|
+
const mainContext = createContext(bots[0]);
|
|
1438
|
+
clears.add(await setup(mainContext) || (() => {}));
|
|
1277
1439
|
runtimePlugins.set(name, {
|
|
1278
1440
|
name,
|
|
1279
1441
|
type,
|
|
@@ -1292,7 +1454,7 @@ async function enablePlugin(bot, plugin, type = "external") {
|
|
|
1292
1454
|
});
|
|
1293
1455
|
const end = hrtime.bigint();
|
|
1294
1456
|
const time = Math.round(Number(end - start$1)) / 1e6;
|
|
1295
|
-
|
|
1457
|
+
logger$1.info(`- 启用插件 ${colors$1.yellow(`[${typeDesc}]`)} ${colors$1.yellow(`${name}@${version$1}`)} => 耗时 ${colors$1.green(time.toFixed(2))} 毫秒`);
|
|
1296
1458
|
} catch (e) {
|
|
1297
1459
|
throw new Error(`启用插件 ${colors$1.yellow(`[${typeDesc}]`)} ${colors$1.yellow(`${name}@${version$1}`)} 失败: ${e?.message}`);
|
|
1298
1460
|
}
|
|
@@ -1318,18 +1480,12 @@ const ArchMap = {
|
|
|
1318
1480
|
arm64: "arm64",
|
|
1319
1481
|
x64: "x64"
|
|
1320
1482
|
};
|
|
1321
|
-
async function getMiokiStatus(
|
|
1483
|
+
async function getMiokiStatus(bots) {
|
|
1322
1484
|
const osType = os.type();
|
|
1323
1485
|
const osArch = os.arch();
|
|
1324
1486
|
const isInUnix = ["Linux", "Darwin"].includes(osType);
|
|
1325
1487
|
const arch = ArchMap[osArch] || osArch;
|
|
1326
|
-
const [osInfo, localPlugins
|
|
1327
|
-
systemInfo.osInfo(),
|
|
1328
|
-
findLocalPlugins(),
|
|
1329
|
-
bot.getVersionInfo(),
|
|
1330
|
-
bot.getFriendList(),
|
|
1331
|
-
bot.getGroupList()
|
|
1332
|
-
]);
|
|
1488
|
+
const [osInfo, localPlugins] = await Promise.all([systemInfo.osInfo(), findLocalPlugins()]);
|
|
1333
1489
|
const pluginCount = localPlugins.length + BUILTIN_PLUGINS.length;
|
|
1334
1490
|
const system = isInUnix ? {
|
|
1335
1491
|
name: osInfo.distro,
|
|
@@ -1343,27 +1499,58 @@ async function getMiokiStatus(bot) {
|
|
|
1343
1499
|
const rssMem = process.memoryUsage.rss();
|
|
1344
1500
|
const nodeVersion = process.versions.node;
|
|
1345
1501
|
const cpu = getCpuInfo();
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1502
|
+
const botStatuses = [];
|
|
1503
|
+
let totalSend = 0;
|
|
1504
|
+
let totalReceive = 0;
|
|
1505
|
+
let mainVersionInfo = {
|
|
1506
|
+
app_version: "unknown",
|
|
1507
|
+
protocol_version: "unknown"
|
|
1508
|
+
};
|
|
1509
|
+
for (const bot of bots) try {
|
|
1510
|
+
const [versionInfo, friendList, groupList] = await Promise.all([
|
|
1511
|
+
bot.getVersionInfo(),
|
|
1512
|
+
bot.getFriendList(),
|
|
1513
|
+
bot.getGroupList()
|
|
1514
|
+
]);
|
|
1515
|
+
mainVersionInfo = versionInfo;
|
|
1516
|
+
botStatuses.push({
|
|
1517
|
+
uin: bot.bot_id,
|
|
1349
1518
|
nickname: bot.nickname,
|
|
1519
|
+
name: bot.name,
|
|
1350
1520
|
friends: friendList.length,
|
|
1351
|
-
groups: groupList.length
|
|
1352
|
-
|
|
1521
|
+
groups: groupList.length,
|
|
1522
|
+
send: bot.stat.send.group + bot.stat.send.private,
|
|
1523
|
+
receive: bot.stat.recv.group + bot.stat.recv.private
|
|
1524
|
+
});
|
|
1525
|
+
totalSend += bot.stat.send.group + bot.stat.send.private;
|
|
1526
|
+
totalReceive += bot.stat.recv.group + bot.stat.recv.private;
|
|
1527
|
+
} catch (err) {
|
|
1528
|
+
botStatuses.push({
|
|
1529
|
+
uin: bot.bot_id,
|
|
1530
|
+
nickname: bot.nickname,
|
|
1531
|
+
name: bot.name,
|
|
1532
|
+
friends: 0,
|
|
1533
|
+
groups: 0,
|
|
1534
|
+
send: 0,
|
|
1535
|
+
receive: 0
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
return {
|
|
1539
|
+
bots: botStatuses,
|
|
1353
1540
|
plugins: {
|
|
1354
1541
|
enabled: runtimePlugins.size,
|
|
1355
1542
|
total: pluginCount
|
|
1356
1543
|
},
|
|
1357
1544
|
stats: {
|
|
1358
1545
|
uptime: process.uptime() * 1e3,
|
|
1359
|
-
send:
|
|
1360
|
-
receive:
|
|
1546
|
+
send: totalSend,
|
|
1547
|
+
receive: totalReceive
|
|
1361
1548
|
},
|
|
1362
1549
|
versions: {
|
|
1363
1550
|
node: nodeVersion,
|
|
1364
1551
|
mioki: version,
|
|
1365
|
-
napcat:
|
|
1366
|
-
protocol:
|
|
1552
|
+
napcat: mainVersionInfo.app_version,
|
|
1553
|
+
protocol: mainVersionInfo.protocol_version
|
|
1367
1554
|
},
|
|
1368
1555
|
system: {
|
|
1369
1556
|
name: system.name || "N/A",
|
|
@@ -1393,16 +1580,16 @@ async function getMiokiStatus(bot) {
|
|
|
1393
1580
|
};
|
|
1394
1581
|
}
|
|
1395
1582
|
async function formatMiokiStatus(status) {
|
|
1396
|
-
const {
|
|
1583
|
+
const { bots, plugins, stats, system, disk, cpu, memory, versions } = status;
|
|
1397
1584
|
const diskValid = disk.total > 0 && disk.free >= 0;
|
|
1398
1585
|
const diskDesc = `${disk.percent}%-${filesize(disk.used, { round: 1 })}/${filesize(disk.total, { round: 1 })}`;
|
|
1399
1586
|
return `
|
|
1400
1587
|
〓 🟢 mioki 状态 〓
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1588
|
+
${bots.map((bot, index) => {
|
|
1589
|
+
return `👤 ${bot.name ? `[${bot.name}] ` : ""}${bot.nickname} (${bot.uin})\n 📋 ${localNum(bot.friends)} 好友 / ${localNum(bot.groups)} 群 / 📮 收 ${localNum(bot.receive)} 发 ${localNum(bot.send)}`;
|
|
1590
|
+
}).join("\n")}
|
|
1404
1591
|
🧩 启用了 ${localNum(plugins.enabled)} 个插件,共 ${localNum(plugins.total)} 个
|
|
1405
|
-
📮 收 ${localNum(stats.receive)} 条,发 ${localNum(stats.send)} 条
|
|
1592
|
+
📮 总计: 收 ${localNum(stats.receive)} 条,发 ${localNum(stats.send)} 条
|
|
1406
1593
|
🚀 ${filesize(memory.rss.used, { round: 1 })}/${memory.percent}%
|
|
1407
1594
|
⏳ 已运行 ${prettyMs(stats.uptime, {
|
|
1408
1595
|
hideYear: true,
|
|
@@ -1486,7 +1673,7 @@ const core = definePlugin({
|
|
|
1486
1673
|
const displayPrefix = prefix.replace(/\\\\/g, "\\");
|
|
1487
1674
|
const statusAdminOnly = ctx.botConfig.status_permission === "admin-only";
|
|
1488
1675
|
let statusFormatter = (status) => formatMiokiStatus(status);
|
|
1489
|
-
ctx.addService("getMiokiStatus", () => getMiokiStatus(ctx.
|
|
1676
|
+
ctx.addService("getMiokiStatus", () => getMiokiStatus(ctx.bots));
|
|
1490
1677
|
ctx.addService("formatMiokiStatus", (status) => formatMiokiStatus(status));
|
|
1491
1678
|
ctx.addService("customFormatMiokiStatus", (formatter) => statusFormatter = formatter);
|
|
1492
1679
|
ctx.handle("message", (e) => ctx.runWithErrorHandler(async () => {
|
|
@@ -1494,7 +1681,7 @@ const core = definePlugin({
|
|
|
1494
1681
|
if (!cmdPrefix.test(text$1)) return;
|
|
1495
1682
|
if (statusAdminOnly && !ctx.hasRight(e)) return;
|
|
1496
1683
|
if (text$1.replace(cmdPrefix, "") === "状态") {
|
|
1497
|
-
const status = await statusFormatter(await getMiokiStatus(ctx.
|
|
1684
|
+
const status = await statusFormatter(await getMiokiStatus(ctx.bots));
|
|
1498
1685
|
await e.reply(status);
|
|
1499
1686
|
return;
|
|
1500
1687
|
}
|
|
@@ -1559,10 +1746,10 @@ const core = definePlugin({
|
|
|
1559
1746
|
const plugin = await ctx.jiti.import(pluginPath, { default: true });
|
|
1560
1747
|
if (plugin.name !== target) {
|
|
1561
1748
|
const tip = `[插件目录名称: ${target}] 和插件代码中设置的 [name: ${plugin.name}] 不一致,可能导致重载异常,请修改后重启。`;
|
|
1562
|
-
ctx.
|
|
1749
|
+
ctx.logger.warn(tip);
|
|
1563
1750
|
ctx.noticeMainOwner(tip);
|
|
1564
1751
|
}
|
|
1565
|
-
await enablePlugin(ctx.
|
|
1752
|
+
await enablePlugin(ctx.bots, plugin);
|
|
1566
1753
|
} catch (err) {
|
|
1567
1754
|
await e.reply(`插件 ${target} 启用失败:${err?.message || "未知错误"}`, true);
|
|
1568
1755
|
return;
|
|
@@ -1588,7 +1775,7 @@ const core = definePlugin({
|
|
|
1588
1775
|
break;
|
|
1589
1776
|
}
|
|
1590
1777
|
await ctx.updateBotConfig((c) => c.plugins = ctx.botConfig.plugins.filter((name) => name !== target));
|
|
1591
|
-
ctx.
|
|
1778
|
+
ctx.logger.info(`禁用插件 => ${target}`);
|
|
1592
1779
|
await e.reply(`插件 ${target} 已禁用`, true);
|
|
1593
1780
|
break;
|
|
1594
1781
|
}
|
|
@@ -1610,10 +1797,10 @@ const core = definePlugin({
|
|
|
1610
1797
|
const importedPlugin = await ctx.jiti.import(pluginPath, { default: true });
|
|
1611
1798
|
if (importedPlugin.name !== target) {
|
|
1612
1799
|
const tip = `插件目录名称: ${target} 和插件代码中设置的 name: ${importedPlugin.name} 不一致,可能导致重载异常,请修改后重启。`;
|
|
1613
|
-
ctx.
|
|
1800
|
+
ctx.logger.warn(tip);
|
|
1614
1801
|
ctx.noticeMainOwner(tip);
|
|
1615
1802
|
}
|
|
1616
|
-
await enablePlugin(ctx.
|
|
1803
|
+
await enablePlugin(ctx.bots, importedPlugin);
|
|
1617
1804
|
} catch (err) {
|
|
1618
1805
|
await e.reply(err?.message, true);
|
|
1619
1806
|
await ctx.updateBotConfig((c) => c.plugins = c.plugins.filter((name) => name !== target));
|
|
@@ -1726,7 +1913,7 @@ const core = definePlugin({
|
|
|
1726
1913
|
break;
|
|
1727
1914
|
case "退出":
|
|
1728
1915
|
await e.reply("またね~", true);
|
|
1729
|
-
ctx.
|
|
1916
|
+
ctx.logger.info("接收到退出指令,即将退出... 如需自动重启,请使用 pm2 部署。");
|
|
1730
1917
|
process.exit(0);
|
|
1731
1918
|
}
|
|
1732
1919
|
}, e));
|
|
@@ -1740,6 +1927,120 @@ const BUILTIN_PLUGINS = [core_default];
|
|
|
1740
1927
|
|
|
1741
1928
|
//#endregion
|
|
1742
1929
|
//#region src/start.ts
|
|
1930
|
+
const connectedBots = /* @__PURE__ */ new Map();
|
|
1931
|
+
async function connectBot(config, index) {
|
|
1932
|
+
const { protocol = "ws", port = 3001, host = "localhost", token = "", name } = config;
|
|
1933
|
+
const botName = name || `Bot${index + 1}`;
|
|
1934
|
+
const wsUrl = colors$1.green(`${protocol}://${host}:${port}${token ? "?access_token=***" : ""}`);
|
|
1935
|
+
logger.info(`>>> 正在连接 ${colors$1.cyan(botName)}: ${wsUrl}`);
|
|
1936
|
+
const napcat = new NapCat({
|
|
1937
|
+
token,
|
|
1938
|
+
protocol,
|
|
1939
|
+
host,
|
|
1940
|
+
port,
|
|
1941
|
+
logger
|
|
1942
|
+
});
|
|
1943
|
+
return new Promise((resolve) => {
|
|
1944
|
+
napcat.on("ws.close", () => {
|
|
1945
|
+
logger.warn(`${colors$1.yellow(botName)} WS 连接已关闭`);
|
|
1946
|
+
});
|
|
1947
|
+
napcat.on("ws.error", (err) => {
|
|
1948
|
+
logger.error(`${colors$1.red(botName)} WS 连接错误: ${err}`);
|
|
1949
|
+
});
|
|
1950
|
+
napcat.once("napcat.connected", ({ user_id, nickname, app_name, app_version }) => {
|
|
1951
|
+
logger.info(`已连接到 ${colors$1.cyan(botName)}: ${colors$1.green(`${app_name}-v${app_version} ${nickname}(${user_id})`)}`);
|
|
1952
|
+
if (connectedBots.has(user_id)) {
|
|
1953
|
+
const existingBot = connectedBots.get(user_id);
|
|
1954
|
+
if (existingBot.name) logger.warn(`${colors$1.yellow(botName)} (${user_id}) 与 ${colors$1.yellow(existingBot.name)} (${user_id}) QQ 号重复,将跳过`);
|
|
1955
|
+
napcat.close();
|
|
1956
|
+
resolve(null);
|
|
1957
|
+
return;
|
|
1958
|
+
}
|
|
1959
|
+
const extendedNapCat = napcat;
|
|
1960
|
+
extendedNapCat.bot_id = user_id;
|
|
1961
|
+
extendedNapCat.app_name = app_name;
|
|
1962
|
+
extendedNapCat.app_version = app_version;
|
|
1963
|
+
extendedNapCat.name = botName;
|
|
1964
|
+
resolve(extendedNapCat);
|
|
1965
|
+
});
|
|
1966
|
+
napcat.run().catch((err) => {
|
|
1967
|
+
logger.error(`${colors$1.red(botName)} 连接失败: ${err.message}`);
|
|
1968
|
+
resolve(null);
|
|
1969
|
+
});
|
|
1970
|
+
});
|
|
1971
|
+
}
|
|
1972
|
+
async function setupPlugins(napcat, bots) {
|
|
1973
|
+
const plugin_dir = getAbsPluginDir();
|
|
1974
|
+
const mainBot = napcat;
|
|
1975
|
+
ensurePluginDir();
|
|
1976
|
+
const plugins = botConfig.plugins.map((p) => ({
|
|
1977
|
+
dirName: p,
|
|
1978
|
+
absPath: path$1.resolve(plugin_dir, p)
|
|
1979
|
+
})).filter((p) => {
|
|
1980
|
+
if (!fs$1.existsSync(p.absPath)) {
|
|
1981
|
+
mainBot.logger.warn(`插件 ${colors$1.red(p.dirName)} 不存在,已忽略`);
|
|
1982
|
+
return false;
|
|
1983
|
+
}
|
|
1984
|
+
return true;
|
|
1985
|
+
});
|
|
1986
|
+
const failedImportPlugins = [];
|
|
1987
|
+
const promises = plugins.map(async ({ absPath, dirName }) => {
|
|
1988
|
+
try {
|
|
1989
|
+
const plugin = await jiti.import(absPath, { default: true });
|
|
1990
|
+
if (plugin.name !== dirName) {
|
|
1991
|
+
const tip = `插件目录名 [${colors$1.yellow(dirName)}] 和插件声明的 name [${colors$1.yellow(plugin.name)}] 不一致,可能导致重载异常,请修改一致后重启。`;
|
|
1992
|
+
mainBot.logger.warn(tip);
|
|
1993
|
+
noticeMainOwner(mainBot, tip);
|
|
1994
|
+
}
|
|
1995
|
+
return plugin;
|
|
1996
|
+
} catch (e) {
|
|
1997
|
+
const err = stringifyError(e);
|
|
1998
|
+
failedImportPlugins.push([dirName, err]);
|
|
1999
|
+
return null;
|
|
2000
|
+
}
|
|
2001
|
+
});
|
|
2002
|
+
const start$1 = hrtime.bigint();
|
|
2003
|
+
const sortedUserPlugins = (await Promise.all(promises)).filter(Boolean).toSorted((prev, next) => (prev.priority ?? 100) - (next.priority ?? 100));
|
|
2004
|
+
if (failedImportPlugins.length) {
|
|
2005
|
+
const tip = `${colors$1.red(failedImportPlugins.length)} 个插件加载失败: \n\n${failedImportPlugins.map(([dirName, err]) => `${dirName}: ${err}`).join("\n\n")}`;
|
|
2006
|
+
mainBot.logger.warn(tip);
|
|
2007
|
+
noticeMainOwner(mainBot, tip);
|
|
2008
|
+
}
|
|
2009
|
+
const pluginGroups = /* @__PURE__ */ new Map();
|
|
2010
|
+
for (const plugin of sortedUserPlugins) {
|
|
2011
|
+
const priority = plugin.priority ?? 100;
|
|
2012
|
+
if (!pluginGroups.has(priority)) pluginGroups.set(priority, []);
|
|
2013
|
+
pluginGroups.get(priority).push(plugin);
|
|
2014
|
+
}
|
|
2015
|
+
const sortedGroups = Array.from(pluginGroups.entries()).toSorted(([a], [b]) => a - b);
|
|
2016
|
+
const failedEnablePlugins = [];
|
|
2017
|
+
try {
|
|
2018
|
+
mainBot.logger.info(`>>> 加载内置插件: ${BUILTIN_PLUGINS.map((p) => colors$1.cyan(p.name)).join(", ")}`);
|
|
2019
|
+
await Promise.all(BUILTIN_PLUGINS.map((p) => enablePlugin(bots, p, "builtin")));
|
|
2020
|
+
mainBot.logger.info(`>>> 加载用户插件: ${sortedGroups.map(([priority, plugins$1]) => `优先级 ${colors$1.yellow(priority)} (${plugins$1.map((p) => colors$1.cyan(p.name)).join(", ")})`).join(",")}`);
|
|
2021
|
+
for (const [_, plugins$1] of sortedGroups) await Promise.all(plugins$1.map(async (p) => {
|
|
2022
|
+
try {
|
|
2023
|
+
await enablePlugin(bots, p, "external");
|
|
2024
|
+
} catch (e) {
|
|
2025
|
+
failedEnablePlugins.push([p.name, stringifyError(e)]);
|
|
2026
|
+
}
|
|
2027
|
+
}));
|
|
2028
|
+
} catch (e) {
|
|
2029
|
+
mainBot.logger.error(e?.message);
|
|
2030
|
+
await noticeMainOwner(mainBot, e?.message).catch(() => {
|
|
2031
|
+
mainBot.logger.error("发送插件启用失败通知失败");
|
|
2032
|
+
});
|
|
2033
|
+
}
|
|
2034
|
+
const end = hrtime.bigint();
|
|
2035
|
+
const costTime = Math.round(Number(end - start$1)) / 1e6;
|
|
2036
|
+
const failedCount = failedImportPlugins.length + failedEnablePlugins.length;
|
|
2037
|
+
const failedInfo = failedCount > 0 ? `${colors$1.red(failedCount)} 个失败 (导入 ${colors$1.red(failedImportPlugins.length)},启用 ${colors$1.red(failedEnablePlugins.length)})` : "";
|
|
2038
|
+
mainBot.logger.info(`成功加载了 ${colors$1.green(runtimePlugins.size)} 个插件,${failedInfo ? failedInfo : ""}总耗时 ${colors$1.green(costTime.toFixed(2))} 毫秒`);
|
|
2039
|
+
mainBot.logger.info(colors$1.green(`mioki v${version} 启动完成,向机器人发送「${colors$1.magentaBright(`${botConfig.prefix}帮助`)}」查看消息指令`));
|
|
2040
|
+
if (botConfig.online_push) await noticeMainOwner(mainBot, `✅ mioki v${version} 已就绪`).catch((err) => {
|
|
2041
|
+
mainBot.logger.error(`发送就绪通知失败: ${stringifyError(err)}`);
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
1743
2044
|
async function start(options = {}) {
|
|
1744
2045
|
const { cwd = process.cwd() } = options;
|
|
1745
2046
|
if (cwd !== BOT_CWD.value) updateBotCWD(path$1.resolve(cwd));
|
|
@@ -1758,119 +2059,69 @@ async function start(options = {}) {
|
|
|
1758
2059
|
logger.info(`${colors$1.dim("插件目录: ")}${colors$1.blue(plugin_dir)}`);
|
|
1759
2060
|
logger.info(`${colors$1.dim("配置文件: ")}${colors$1.blue(`${BOT_CWD.value}/package.json`)}`);
|
|
1760
2061
|
logger.info(colors$1.dim("=".repeat(40)));
|
|
1761
|
-
const
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
2062
|
+
const napcatConfigs = botConfig.napcat;
|
|
2063
|
+
if (napcatConfigs.length === 0) {
|
|
2064
|
+
logger.warn("未配置任何 NapCat 实例,框架将以无实例模式启动");
|
|
2065
|
+
logger.info(colors$1.green(`mioki v${version} 启动完成,向机器人发送「${colors$1.magentaBright(`${botConfig.prefix}帮助`)}」查看消息指令`));
|
|
2066
|
+
return;
|
|
2067
|
+
}
|
|
2068
|
+
const seenEndpoints = /* @__PURE__ */ new Set();
|
|
2069
|
+
const duplicateConfigs = [];
|
|
2070
|
+
for (const config of napcatConfigs) {
|
|
2071
|
+
const { protocol = "ws", host = "localhost", port = 3001 } = config;
|
|
2072
|
+
const endpoint = `${protocol}://${host}:${port}`;
|
|
2073
|
+
if (seenEndpoints.has(endpoint)) duplicateConfigs.push(`${config.name || "未命名"} (${endpoint})`);
|
|
2074
|
+
else seenEndpoints.add(endpoint);
|
|
2075
|
+
}
|
|
2076
|
+
if (duplicateConfigs.length > 0) {
|
|
2077
|
+
logger.error(`检测到重复的 NapCat 实例配置:`);
|
|
2078
|
+
duplicateConfigs.forEach((dup) => logger.error(` - ${dup}`));
|
|
2079
|
+
logger.error("请检查配置文件,确保每个实例的 host:port 组合唯一");
|
|
1773
2080
|
process.exit(1);
|
|
1774
|
-
}
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
2081
|
+
}
|
|
2082
|
+
logger.info(colors$1.dim("=".repeat(40)));
|
|
2083
|
+
logger.info(`>>> 正在连接 ${napcatConfigs.length} 个 NapCat 实例...`);
|
|
2084
|
+
const bots = (await Promise.all(napcatConfigs.map((config, index) => connectBot(config, index)))).filter((b) => b !== null);
|
|
2085
|
+
if (bots.length === 0) {
|
|
2086
|
+
logger.error("所有 NapCat 实例连接失败,框架无法启动");
|
|
2087
|
+
process.exit(1);
|
|
2088
|
+
}
|
|
2089
|
+
for (const bot of bots) connectedBots.set(bot.bot_id, bot);
|
|
2090
|
+
if (bots.length < napcatConfigs.length) logger.warn(`${colors$1.yellow(napcatConfigs.length - bots.length)} 个 NapCat 实例连接失败`);
|
|
2091
|
+
const botNames = bots.map((b) => `${b.name}(${b.bot_id})`).join(", ");
|
|
2092
|
+
logger.info(colors$1.green(`成功连接 ${bots.length} 个实例: ${botNames}`));
|
|
2093
|
+
logger.info(colors$1.dim("=".repeat(40)));
|
|
2094
|
+
const mainBot = bots[0];
|
|
2095
|
+
process.title = `mioki v${version} ${bots.map((b) => `${b.bot_id}`).join(", ")}`;
|
|
2096
|
+
let lastNoticeTime = 0;
|
|
2097
|
+
for (const bot of bots) {
|
|
1779
2098
|
process.on("uncaughtException", async (err) => {
|
|
1780
2099
|
const msg = stringifyError(err);
|
|
1781
|
-
|
|
2100
|
+
bot.logger.error(`uncaughtException, 出错了: ${msg}`);
|
|
1782
2101
|
if (botConfig.error_push) {
|
|
1783
2102
|
if (Date.now() - lastNoticeTime < 1e3) return;
|
|
1784
2103
|
lastNoticeTime = Date.now();
|
|
1785
|
-
await noticeMainOwner(
|
|
1786
|
-
|
|
2104
|
+
await noticeMainOwner(mainBot, `mioki 发生未捕获异常:\n\n${msg}`).catch(() => {
|
|
2105
|
+
mainBot.logger.error("发送未捕获异常通知失败");
|
|
1787
2106
|
});
|
|
1788
2107
|
}
|
|
1789
2108
|
});
|
|
1790
2109
|
process.on("unhandledRejection", async (err) => {
|
|
1791
2110
|
const msg = stringifyError(err);
|
|
1792
|
-
|
|
2111
|
+
bot.logger.error(`unhandledRejection, 出错了: ${msg}`);
|
|
1793
2112
|
if (botConfig.error_push) {
|
|
1794
2113
|
if (Date.now() - lastNoticeTime < 1e3) return;
|
|
1795
2114
|
lastNoticeTime = Date.now();
|
|
1796
2115
|
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
1797
|
-
await noticeMainOwner(
|
|
1798
|
-
|
|
2116
|
+
await noticeMainOwner(mainBot, `【${date}】\n\nmioki 发生未处理异常:\n\n${msg}`).catch(() => {
|
|
2117
|
+
mainBot.logger.error("发送未处理异常通知失败");
|
|
1799
2118
|
});
|
|
1800
2119
|
}
|
|
1801
2120
|
});
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
dirName: p,
|
|
1805
|
-
absPath: path$1.resolve(plugin_dir, p)
|
|
1806
|
-
})).filter((p) => {
|
|
1807
|
-
if (!fs$1.existsSync(p.absPath)) {
|
|
1808
|
-
napcat.logger.warn(`插件 ${colors$1.red(p.dirName)} 不存在,已忽略`);
|
|
1809
|
-
return false;
|
|
1810
|
-
}
|
|
1811
|
-
return true;
|
|
1812
|
-
});
|
|
1813
|
-
const failedImportPlugins = [];
|
|
1814
|
-
const promises = plugins.map(async ({ absPath, dirName }) => {
|
|
1815
|
-
try {
|
|
1816
|
-
const plugin = await jiti.import(absPath, { default: true });
|
|
1817
|
-
if (plugin.name !== dirName) {
|
|
1818
|
-
const tip = `插件目录名 [${colors$1.yellow(dirName)}] 和插件声明的 name [${colors$1.yellow(plugin.name)}] 不一致,可能导致重载异常,请修改一致后重启。`;
|
|
1819
|
-
napcat.logger.warn(tip);
|
|
1820
|
-
noticeMainOwner(napcat, tip);
|
|
1821
|
-
}
|
|
1822
|
-
return plugin;
|
|
1823
|
-
} catch (e) {
|
|
1824
|
-
const err = stringifyError(e);
|
|
1825
|
-
failedImportPlugins.push([dirName, err]);
|
|
1826
|
-
return null;
|
|
1827
|
-
}
|
|
1828
|
-
});
|
|
1829
|
-
const start$1 = hrtime.bigint();
|
|
1830
|
-
const sortedUserPlugins = (await Promise.all(promises)).filter(Boolean).toSorted((prev, next) => (prev.priority ?? 100) - (next.priority ?? 100));
|
|
1831
|
-
if (failedImportPlugins.length) {
|
|
1832
|
-
const tip = `${colors$1.red(failedImportPlugins.length)} 个插件加载失败: \n\n${failedImportPlugins.map(([dirName, err]) => `${dirName}: ${err}`).join("\n\n")}`;
|
|
1833
|
-
napcat.logger.warn(tip);
|
|
1834
|
-
noticeMainOwner(napcat, tip);
|
|
1835
|
-
}
|
|
1836
|
-
const pluginGroups = /* @__PURE__ */ new Map();
|
|
1837
|
-
for (const plugin of sortedUserPlugins) {
|
|
1838
|
-
const priority = plugin.priority ?? 100;
|
|
1839
|
-
if (!pluginGroups.has(priority)) pluginGroups.set(priority, []);
|
|
1840
|
-
pluginGroups.get(priority).push(plugin);
|
|
1841
|
-
}
|
|
1842
|
-
const sortedGroups = Array.from(pluginGroups.entries()).toSorted(([a], [b]) => a - b);
|
|
1843
|
-
const failedEnablePlugins = [];
|
|
1844
|
-
try {
|
|
1845
|
-
napcat.logger.info(`>>> 加载内置插件: ${BUILTIN_PLUGINS.map((p) => colors$1.cyan(p.name)).join(", ")}`);
|
|
1846
|
-
await Promise.all(BUILTIN_PLUGINS.map((p) => enablePlugin(napcat, p, "builtin")));
|
|
1847
|
-
napcat.logger.info(`>>> 加载用户插件: ${sortedGroups.map(([priority, plugins$1]) => `优先级 ${colors$1.yellow(priority)} (${plugins$1.map((p) => colors$1.cyan(p.name)).join(", ")})`).join(",")}`);
|
|
1848
|
-
for (const [_, plugins$1] of sortedGroups) await Promise.all(plugins$1.map(async (p) => {
|
|
1849
|
-
try {
|
|
1850
|
-
await enablePlugin(napcat, p, "external");
|
|
1851
|
-
} catch (e) {
|
|
1852
|
-
failedEnablePlugins.push([p.name, stringifyError(e)]);
|
|
1853
|
-
}
|
|
1854
|
-
}));
|
|
1855
|
-
} catch (e) {
|
|
1856
|
-
napcat.logger.error(e?.message);
|
|
1857
|
-
await noticeMainOwner(napcat, e?.message).catch(() => {
|
|
1858
|
-
napcat.logger.error("发送插件启用失败通知失败");
|
|
1859
|
-
});
|
|
1860
|
-
}
|
|
1861
|
-
const end = hrtime.bigint();
|
|
1862
|
-
const costTime = Math.round(Number(end - start$1)) / 1e6;
|
|
1863
|
-
const failedCount = failedImportPlugins.length + failedEnablePlugins.length;
|
|
1864
|
-
const failedInfo = failedCount > 0 ? `${colors$1.red(failedCount)} 个失败 (导入 ${colors$1.red(failedImportPlugins.length)},启用 ${colors$1.red(failedEnablePlugins.length)})` : "";
|
|
1865
|
-
napcat.logger.info(`成功加载了 ${colors$1.green(runtimePlugins.size)} 个插件,${failedInfo ? failedInfo : ""}总耗时 ${colors$1.green(costTime.toFixed(2))} 毫秒`);
|
|
1866
|
-
napcat.logger.info(colors$1.green(`mioki v${version} 启动完成,向机器人发送「${colors$1.magentaBright(`${botConfig.prefix}帮助`)}」查看消息指令`));
|
|
1867
|
-
if (botConfig.online_push) await noticeMainOwner(napcat, `✅ mioki v${version} 已就绪`).catch((err) => {
|
|
1868
|
-
napcat.logger.error(`发送就绪通知失败: ${stringifyError(err)}`);
|
|
1869
|
-
});
|
|
1870
|
-
});
|
|
1871
|
-
await napcat.run();
|
|
2121
|
+
}
|
|
2122
|
+
await setupPlugins(mainBot, bots);
|
|
1872
2123
|
}
|
|
1873
2124
|
|
|
1874
2125
|
//#endregion
|
|
1875
|
-
export { ArchMap, BOT_CWD, BUILTIN_PLUGINS, CORE_PLUGINS, ChromeUA, START_TIME, SystemMap, addService, base64Decode, base64Encode, bindBot, botConfig, box, clamp, colorize, colors, createCmd, createDB, createForwardMsg, createStore, dayjs, dedent, definePlugin, enablePlugin, ensureBuffer, ensurePluginDir, filesize, filter, find, findLocalPlugins, formatDuration, formatMiokiStatus, formatQQLevel, fs, getAbsPluginDir, getAuthCodeViaTicket, getBfaceUrl, getGTk, getGroupAvatarLink, getImage, getImageUrl, getLogFilePath, getMentionedImage, getMentionedImageUrl, getMentionedUserId, getMinicoTokenViaAuthCode, getMiokiLogger, getMiokiStatus, getQQAvatarLink, getQuoteImage, getQuoteImageUrl, getQuoteMsg, getQuoteText, getTerminalInput, getViolationRecords, hasRight, isAdmin, isBoolean, isDefined, isFunction, isGroupMsg, isInPm2, isNumber, isObject, isOwner, isOwnerOrAdmin, isPrivateMsg, isString, jiti, localNum, localeDate, localeTime, logger, match, md5, mri, noNullish, noticeAdmins, noticeFriends, noticeGroups, noticeMainOwner, noticeOwners, path, prettyMs, qs, queryDevToolsLoginStatus, randomId, randomInt, randomItem, randomItems, readMiokiConfig, readPackageJson, requestLoginViaDevTools, runWithErrorHandler, runWithReaction, runtimePlugins, services, signArk, start, string2argv, stringifyError, stripAnsi, systemInfo, text, toArray, toMsgId, unique, updateBotCWD, updateBotConfig, uploadImageToCollection, uploadImageToGroupHomework, uploadImageToGroupNotice, uuid, wait, writePackageJson };
|
|
2126
|
+
export { ArchMap, BOT_CWD, BUILTIN_PLUGINS, CORE_PLUGINS, ChromeUA, Deduplicator, MessageDeduplicator, START_TIME, SystemMap, addService, base64Decode, base64Encode, bindBot, botConfig, box, clamp, colorize, colors, connectedBots, createCmd, createDB, createForwardMsg, createStore, dayjs, dedent, deduplicator, definePlugin, enablePlugin, ensureBuffer, ensurePluginDir, filesize, filter, find, findLocalPlugins, formatDuration, formatMiokiStatus, formatQQLevel, fs, getAbsPluginDir, getAuthCodeViaTicket, getBfaceUrl, getGTk, getGroupAvatarLink, getImage, getImageUrl, getLogFilePath, getMentionedImage, getMentionedImageUrl, getMentionedUserId, getMinicoTokenViaAuthCode, getMiokiLogger, getMiokiStatus, getQQAvatarLink, getQuoteImage, getQuoteImageUrl, getQuoteMsg, getQuoteText, getTerminalInput, getViolationRecords, hasRight, isAdmin, isBoolean, isDefined, isFunction, isGroupMsg, isInPm2, isNumber, isObject, isOwner, isOwnerOrAdmin, isPrivateMsg, isString, jiti, localNum, localeDate, localeTime, logger, match, md5, mri, noNullish, normalizeNapCatConfig, noticeAdmins, noticeFriends, noticeGroups, noticeMainOwner, noticeOwners, path, prettyMs, qs, queryDevToolsLoginStatus, randomId, randomInt, randomItem, randomItems, readMiokiConfig, readPackageJson, requestLoginViaDevTools, runWithErrorHandler, runWithReaction, runtimePlugins, services, signArk, start, string2argv, stringifyError, stripAnsi, systemInfo, text, toArray, toMsgId, unique, updateBotCWD, updateBotConfig, uploadImageToCollection, uploadImageToGroupHomework, uploadImageToGroupNotice, uuid, wait, writePackageJson };
|
|
1876
2127
|
//# sourceMappingURL=index.mjs.map
|