koishi-plugin-best-cave 2.7.25 → 2.7.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/AIManager.d.ts +9 -0
- package/lib/index.js +128 -89
- package/package.json +1 -1
package/lib/AIManager.d.ts
CHANGED
|
@@ -40,6 +40,15 @@ export declare class AIManager {
|
|
|
40
40
|
* @param {any} cave - 主命令的实例,用于挂载子命令。
|
|
41
41
|
*/
|
|
42
42
|
registerCommands(cave: any): void;
|
|
43
|
+
/**
|
|
44
|
+
* @description 递归处理和分析回声洞批次,失败时按 1/5 拆分以定位问题。
|
|
45
|
+
* @param {CaveObject[]} caves - 当前要处理的回声洞对象数组。
|
|
46
|
+
* @param {number} totalCaves - 要分析的回声洞总数。
|
|
47
|
+
* @param {{ count: number }} progress - 用于跟踪总体进度的计数器对象。
|
|
48
|
+
* @returns {Promise<number>} 成功分析的回声洞数量。
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
private processCaveBatch;
|
|
43
52
|
/**
|
|
44
53
|
* @description 对新提交的内容执行 AI 驱动的查重检查。
|
|
45
54
|
* @param {StoredElement[]} newElements - 新提交的内容元素数组。
|
package/lib/index.js
CHANGED
|
@@ -103,9 +103,9 @@ var FileManager = class {
|
|
|
103
103
|
});
|
|
104
104
|
await this.s3Client.send(command);
|
|
105
105
|
} else {
|
|
106
|
-
await fs.mkdir(this.resourceDir, { recursive: true }).catch((
|
|
107
|
-
this.logger.error(`创建资源目录失败 ${this.resourceDir}:`,
|
|
108
|
-
throw
|
|
106
|
+
await fs.mkdir(this.resourceDir, { recursive: true }).catch((error) => {
|
|
107
|
+
this.logger.error(`创建资源目录失败 ${this.resourceDir}:`, error);
|
|
108
|
+
throw error;
|
|
109
109
|
});
|
|
110
110
|
const filePath = path.join(this.resourceDir, fileName);
|
|
111
111
|
await this.withLock(filePath, () => fs.writeFile(filePath, data));
|
|
@@ -139,9 +139,9 @@ var FileManager = class {
|
|
|
139
139
|
const filePath = path.join(this.resourceDir, fileIdentifier);
|
|
140
140
|
await this.withLock(filePath, () => fs.unlink(filePath));
|
|
141
141
|
}
|
|
142
|
-
} catch (
|
|
143
|
-
if (
|
|
144
|
-
this.logger.warn(`删除文件 ${fileIdentifier} 失败:`,
|
|
142
|
+
} catch (error) {
|
|
143
|
+
if (error.code !== "ENOENT" && error.name !== "NoSuchKey") {
|
|
144
|
+
this.logger.warn(`删除文件 ${fileIdentifier} 失败:`, error);
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
}
|
|
@@ -238,8 +238,8 @@ async function buildCaveMessage(cave, config, fileManager, logger2, platform, pr
|
|
|
238
238
|
return resultNodes;
|
|
239
239
|
}));
|
|
240
240
|
return (0, import_koishi.h)("message", { forward: true }, messageNodes.flat());
|
|
241
|
-
} catch (
|
|
242
|
-
logger2.warn(`解析回声洞(${cave.id})合并转发内容失败:`,
|
|
241
|
+
} catch (error) {
|
|
242
|
+
logger2.warn(`解析回声洞(${cave.id})合并转发内容失败:`, error);
|
|
243
243
|
return import_koishi.h.text("[合并转发]");
|
|
244
244
|
}
|
|
245
245
|
}
|
|
@@ -252,8 +252,8 @@ async function buildCaveMessage(cave, config, fileManager, logger2, platform, pr
|
|
|
252
252
|
const data2 = await fileManager.readFile(fileName);
|
|
253
253
|
const mimeType = mimeTypeMap[path2.extname(fileName).toLowerCase()] || "application/octet-stream";
|
|
254
254
|
return (0, import_koishi.h)(el.type, { ...el, src: `data:${mimeType};base64,${data2.toString("base64")}` });
|
|
255
|
-
} catch (
|
|
256
|
-
logger2.warn(`转换文件 ${fileName} 为 Base64 失败:`,
|
|
255
|
+
} catch (error) {
|
|
256
|
+
logger2.warn(`转换文件 ${fileName} 为 Base64 失败:`, error);
|
|
257
257
|
return (0, import_koishi.h)("p", {}, `[${el.type}]`);
|
|
258
258
|
}
|
|
259
259
|
}
|
|
@@ -332,8 +332,8 @@ async function cleanupPendingDeletions(ctx, config, fileManager, logger2, reusab
|
|
|
332
332
|
await ctx.database.remove("cave", { id: { $in: idsToDelete } });
|
|
333
333
|
await ctx.database.remove("cave_hash", { cave: { $in: idsToDelete } });
|
|
334
334
|
if (config.enableAI) await ctx.database.remove("cave_meta", { cave: { $in: idsToDelete } });
|
|
335
|
-
} catch (
|
|
336
|
-
logger2.error("清理回声洞时发生错误:",
|
|
335
|
+
} catch (error) {
|
|
336
|
+
logger2.error("清理回声洞时发生错误:", error);
|
|
337
337
|
}
|
|
338
338
|
}
|
|
339
339
|
__name(cleanupPendingDeletions, "cleanupPendingDeletions");
|
|
@@ -481,8 +481,8 @@ async function performSimilarityChecks(ctx, config, hashManager, logger2, finalE
|
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
483
|
return { duplicate: false, textHashesToStore, imageHashesToStore };
|
|
484
|
-
} catch (
|
|
485
|
-
logger2.warn("相似度比较失败:",
|
|
484
|
+
} catch (error) {
|
|
485
|
+
logger2.warn("相似度比较失败:", error);
|
|
486
486
|
return { duplicate: false, textHashesToStore: [], imageHashesToStore: [] };
|
|
487
487
|
}
|
|
488
488
|
}
|
|
@@ -578,9 +578,9 @@ var DataManager = class {
|
|
|
578
578
|
try {
|
|
579
579
|
await session.send("正在处理,请稍候...");
|
|
580
580
|
return await action();
|
|
581
|
-
} catch (
|
|
582
|
-
this.logger.error("数据操作时发生错误:",
|
|
583
|
-
return `操作失败: ${
|
|
581
|
+
} catch (error) {
|
|
582
|
+
this.logger.error("数据操作时发生错误:", error);
|
|
583
|
+
return `操作失败: ${error.message}`;
|
|
584
584
|
}
|
|
585
585
|
}, "commandAction");
|
|
586
586
|
cave.subcommand(".export", "导出回声洞数据", { hidden: true, authority: 4 }).usage("将所有回声洞数据导出到 cave.json 中。").action(commandAction(() => this.exportData()));
|
|
@@ -607,8 +607,8 @@ var DataManager = class {
|
|
|
607
607
|
const fileContent = await this.fileManager.readFile(fileName);
|
|
608
608
|
importedCaves = JSON.parse(fileContent.toString("utf-8"));
|
|
609
609
|
if (!Array.isArray(importedCaves) || !importedCaves.length) throw new Error("导入文件格式无效或为空");
|
|
610
|
-
} catch (
|
|
611
|
-
throw new Error(`读取导入文件失败: ${
|
|
610
|
+
} catch (error) {
|
|
611
|
+
throw new Error(`读取导入文件失败: ${error.message}`);
|
|
612
612
|
}
|
|
613
613
|
const allDbCaves = await this.ctx.database.get("cave", {}, { fields: ["id"] });
|
|
614
614
|
const existingIds = new Set(allDbCaves.map((c) => c.id));
|
|
@@ -703,9 +703,9 @@ ${pendingCaves.map((c) => c.id).join("|")}`;
|
|
|
703
703
|
await this.ctx.database.upsert("cave", processedIds.map((id) => ({ id, status: targetStatus })));
|
|
704
704
|
if (targetStatus === "delete") cleanupPendingDeletions(this.ctx, this.config, this.fileManager, this.logger, this.reusableIds);
|
|
705
705
|
return `已${actionText}回声洞(${processedIds.join("|")})`;
|
|
706
|
-
} catch (
|
|
707
|
-
this.logger.error(`审核操作失败:`,
|
|
708
|
-
return `操作失败: ${
|
|
706
|
+
} catch (error) {
|
|
707
|
+
this.logger.error(`审核操作失败:`, error);
|
|
708
|
+
return `操作失败: ${error.message}`;
|
|
709
709
|
}
|
|
710
710
|
}, "createPendAction");
|
|
711
711
|
pend.subcommand(".Y [...ids:posint]", "通过审核").usage("通过一个或多个指定 ID 的回声洞审核。若不指定 ID,则通过所有待审核的回声洞。").action(createPendAction("approve"));
|
|
@@ -725,8 +725,8 @@ ${pendingCaves.map((c) => c.id).join("|")}`;
|
|
|
725
725
|
const [platform] = this.config.adminChannel.split(":", 1);
|
|
726
726
|
const caveMessages = await buildCaveMessage(cave, this.config, this.fileManager, this.logger, platform, "待审核");
|
|
727
727
|
for (const message of caveMessages) if (message.length > 0) await this.ctx.broadcast([this.config.adminChannel], import_koishi2.h.normalize(message));
|
|
728
|
-
} catch (
|
|
729
|
-
this.logger.error(`发送回声洞(${cave.id})审核消息失败:`,
|
|
728
|
+
} catch (error) {
|
|
729
|
+
this.logger.error(`发送回声洞(${cave.id})审核消息失败:`, error);
|
|
730
730
|
}
|
|
731
731
|
}
|
|
732
732
|
};
|
|
@@ -809,17 +809,17 @@ var HashManager = class {
|
|
|
809
809
|
const newHashesForCave = tempHashes;
|
|
810
810
|
if (newHashesForCave.length > 0) hashesToInsert.push(...newHashesForCave);
|
|
811
811
|
if (hashesToInsert.length >= 100) await flushBatch();
|
|
812
|
-
} catch (
|
|
812
|
+
} catch (error) {
|
|
813
813
|
errorCount++;
|
|
814
|
-
this.logger.warn(`补全回声洞(${cave2.id})哈希时出错: ${
|
|
814
|
+
this.logger.warn(`补全回声洞(${cave2.id})哈希时出错: ${error.message}`);
|
|
815
815
|
}
|
|
816
816
|
}
|
|
817
817
|
await flushBatch();
|
|
818
818
|
const successCount = processedCaveCount - errorCount;
|
|
819
819
|
return `已补全 ${successCount} 个回声洞的 ${totalHashesGenerated} 条哈希(失败 ${errorCount} 条)`;
|
|
820
|
-
} catch (
|
|
821
|
-
this.logger.error("补全哈希失败:",
|
|
822
|
-
return `操作失败: ${
|
|
820
|
+
} catch (error) {
|
|
821
|
+
this.logger.error("补全哈希失败:", error);
|
|
822
|
+
return `操作失败: ${error.message}`;
|
|
823
823
|
}
|
|
824
824
|
});
|
|
825
825
|
cave.subcommand(".check", "检查相似度", { hidden: true }).usage("检查所有回声洞,找出相似度过高的内容。").option("textThreshold", "-t <threshold:number> 文本相似度阈值 (%)").option("imageThreshold", "-i <threshold:number> 图片相似度阈值 (%)").action(async ({ session, options }) => {
|
|
@@ -903,9 +903,9 @@ ${textResult.reportLines.join("\n")}`;
|
|
|
903
903
|
${imageResult.reportLines.join("\n")}`;
|
|
904
904
|
}
|
|
905
905
|
return report.trim();
|
|
906
|
-
} catch (
|
|
907
|
-
this.logger.error("检查相似度失败:",
|
|
908
|
-
return `检查失败: ${
|
|
906
|
+
} catch (error) {
|
|
907
|
+
this.logger.error("检查相似度失败:", error);
|
|
908
|
+
return `检查失败: ${error.message}`;
|
|
909
909
|
}
|
|
910
910
|
});
|
|
911
911
|
cave.subcommand(".fix [...ids:posint]", "修复回声洞", { hidden: true, authority: 3 }).usage("扫描并修复回声洞中的图片,可指定一个或多个 ID。").action(async ({ session }, ...ids) => {
|
|
@@ -931,18 +931,18 @@ ${imageResult.reportLines.join("\n")}`;
|
|
|
931
931
|
await this.fileManager.saveFile(element.file, sanitizedBuffer);
|
|
932
932
|
fixedFiles++;
|
|
933
933
|
}
|
|
934
|
-
} catch (
|
|
935
|
-
if (
|
|
936
|
-
this.logger.warn(`无法修复回声洞(${cave2.id})的图片(${element.file}):`,
|
|
934
|
+
} catch (error) {
|
|
935
|
+
if (error.code !== "ENOENT" && error.name !== "NoSuchKey") {
|
|
936
|
+
this.logger.warn(`无法修复回声洞(${cave2.id})的图片(${element.file}):`, error);
|
|
937
937
|
errorCount++;
|
|
938
938
|
}
|
|
939
939
|
}
|
|
940
940
|
}
|
|
941
941
|
}
|
|
942
942
|
return `已修复 ${cavesToProcess.length} 个回声洞的 ${fixedFiles} 张图片(失败 ${errorCount} 条)`;
|
|
943
|
-
} catch (
|
|
944
|
-
this.logger.error("修复图像文件时发生严重错误:",
|
|
945
|
-
return `操作失败: ${
|
|
943
|
+
} catch (error) {
|
|
944
|
+
this.logger.error("修复图像文件时发生严重错误:", error);
|
|
945
|
+
return `操作失败: ${error.message}`;
|
|
946
946
|
}
|
|
947
947
|
});
|
|
948
948
|
}
|
|
@@ -1083,7 +1083,6 @@ ${imageResult.reportLines.join("\n")}`;
|
|
|
1083
1083
|
|
|
1084
1084
|
// src/AIManager.ts
|
|
1085
1085
|
var path3 = __toESM(require("path"));
|
|
1086
|
-
var import_console = require("console");
|
|
1087
1086
|
var AIManager = class {
|
|
1088
1087
|
/**
|
|
1089
1088
|
* @constructor
|
|
@@ -1155,20 +1154,19 @@ var AIManager = class {
|
|
|
1155
1154
|
if (cavesToAnalyze.length === 0) return "无需分析回声洞";
|
|
1156
1155
|
await session.send(`开始分析 ${cavesToAnalyze.length} 个回声洞...`);
|
|
1157
1156
|
let successCount = 0;
|
|
1158
|
-
const
|
|
1157
|
+
const totalToAnalyze = cavesToAnalyze.length;
|
|
1158
|
+
const progress = { count: 0 };
|
|
1159
|
+
const batchSize = 25;
|
|
1159
1160
|
for (let i = 0; i < cavesToAnalyze.length; i += batchSize) {
|
|
1160
1161
|
const batch = cavesToAnalyze.slice(i, i + batchSize);
|
|
1161
|
-
this.logger.info(`[${i + 1}/${cavesToAnalyze.length}] 正在分析 ${batch.length}
|
|
1162
|
-
|
|
1163
|
-
if (analyses.length > 0) {
|
|
1164
|
-
await this.ctx.database.upsert("cave_meta", analyses);
|
|
1165
|
-
successCount += analyses.length;
|
|
1166
|
-
}
|
|
1162
|
+
this.logger.info(`[${i + 1}/${cavesToAnalyze.length}] 正在分析 ${batch.length} 个回声洞...`);
|
|
1163
|
+
successCount += await this.processCaveBatch(batch, totalToAnalyze, progress);
|
|
1167
1164
|
}
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1165
|
+
const failedCount = totalToAnalyze - successCount;
|
|
1166
|
+
if (failedCount > 0) return `已分析 ${successCount} 个回声洞(失败 ${failedCount} 个)`;
|
|
1167
|
+
} catch (error) {
|
|
1168
|
+
this.logger.error("分析回声洞失败:", error);
|
|
1169
|
+
return `操作失败: ${error.message}`;
|
|
1172
1170
|
}
|
|
1173
1171
|
});
|
|
1174
1172
|
cave.subcommand(".compare", "比较重复性", { hidden: true }).usage("检查回声洞,找出可能重复的内容。").action(async ({ session }) => {
|
|
@@ -1213,12 +1211,44 @@ var AIManager = class {
|
|
|
1213
1211
|
- ${sortedCluster.join("|")}`;
|
|
1214
1212
|
});
|
|
1215
1213
|
return report;
|
|
1216
|
-
} catch (
|
|
1217
|
-
this.logger.error("检查重复性失败:",
|
|
1218
|
-
return `检查失败: ${
|
|
1214
|
+
} catch (error) {
|
|
1215
|
+
this.logger.error("检查重复性失败:", error);
|
|
1216
|
+
return `检查失败: ${error.message}`;
|
|
1219
1217
|
}
|
|
1220
1218
|
});
|
|
1221
1219
|
}
|
|
1220
|
+
/**
|
|
1221
|
+
* @description 递归处理和分析回声洞批次,失败时按 1/5 拆分以定位问题。
|
|
1222
|
+
* @param {CaveObject[]} caves - 当前要处理的回声洞对象数组。
|
|
1223
|
+
* @param {number} totalCaves - 要分析的回声洞总数。
|
|
1224
|
+
* @param {{ count: number }} progress - 用于跟踪总体进度的计数器对象。
|
|
1225
|
+
* @returns {Promise<number>} 成功分析的回声洞数量。
|
|
1226
|
+
* @private
|
|
1227
|
+
*/
|
|
1228
|
+
async processCaveBatch(caves, totalCaves, progress) {
|
|
1229
|
+
if (caves.length === 0) return 0;
|
|
1230
|
+
this.logger.info(`[${progress.count + 1}/${totalCaves}] 正在分析回声洞(${caves.map((c) => c.id).join("|")})...`);
|
|
1231
|
+
try {
|
|
1232
|
+
const analyses = await this.analyze(caves);
|
|
1233
|
+
if (analyses.length > 0) await this.ctx.database.upsert("cave_meta", analyses);
|
|
1234
|
+
progress.count += caves.length;
|
|
1235
|
+
return analyses.length;
|
|
1236
|
+
} catch (error) {
|
|
1237
|
+
if (caves.length > 1) {
|
|
1238
|
+
const subBatches = [];
|
|
1239
|
+
const subBatchSize = Math.ceil(caves.length / 5);
|
|
1240
|
+
for (let i = 0; i < caves.length; i += subBatchSize) subBatches.push(caves.slice(i, i + subBatchSize));
|
|
1241
|
+
const processingPromises = subBatches.map((subBatch) => this.processCaveBatch(subBatch, totalCaves, progress));
|
|
1242
|
+
const results = await Promise.all(processingPromises);
|
|
1243
|
+
return results.reduce((sum, count) => sum + count, 0);
|
|
1244
|
+
} else {
|
|
1245
|
+
const failedCave = caves[0];
|
|
1246
|
+
progress.count++;
|
|
1247
|
+
this.logger.error(`[${progress.count}/${totalCaves}] 分析回声洞(${failedCave.id})失败:`, error);
|
|
1248
|
+
return 0;
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1222
1252
|
/**
|
|
1223
1253
|
* @description 对新提交的内容执行 AI 驱动的查重检查。
|
|
1224
1254
|
* @param {StoredElement[]} newElements - 新提交的内容元素数组。
|
|
@@ -1241,8 +1271,8 @@ var AIManager = class {
|
|
|
1241
1271
|
});
|
|
1242
1272
|
const duplicateIds = (await Promise.all(comparisonPromises)).filter((id) => id !== null);
|
|
1243
1273
|
return { duplicate: duplicateIds.length > 0, ids: duplicateIds };
|
|
1244
|
-
} catch (
|
|
1245
|
-
this.logger.error("查重回声洞出错:",
|
|
1274
|
+
} catch (error) {
|
|
1275
|
+
this.logger.error("查重回声洞出错:", error);
|
|
1246
1276
|
return { duplicate: false };
|
|
1247
1277
|
}
|
|
1248
1278
|
}
|
|
@@ -1265,16 +1295,19 @@ var AIManager = class {
|
|
|
1265
1295
|
type: "image_url",
|
|
1266
1296
|
image_url: { url: `data:${mimeType};base64,${buffer.toString("base64")}` }
|
|
1267
1297
|
};
|
|
1268
|
-
} catch (
|
|
1269
|
-
this.logger.warn(`读取文件(${el.file})失败:`,
|
|
1298
|
+
} catch (error) {
|
|
1299
|
+
this.logger.warn(`读取文件(${el.file})失败:`, error);
|
|
1300
|
+
return null;
|
|
1270
1301
|
}
|
|
1271
1302
|
})
|
|
1272
1303
|
);
|
|
1273
1304
|
const images = imageElements.filter(Boolean);
|
|
1274
1305
|
if (!combinedText.trim() && images.length === 0) return null;
|
|
1275
|
-
const contentForAI = [
|
|
1306
|
+
const contentForAI = [];
|
|
1307
|
+
if (combinedText.trim()) contentForAI.push({ type: "text", text: `请分析以下内容:
|
|
1276
1308
|
|
|
1277
|
-
${combinedText}` }
|
|
1309
|
+
${combinedText}` });
|
|
1310
|
+
contentForAI.push(...images);
|
|
1278
1311
|
const userMessage = { role: "user", content: contentForAI };
|
|
1279
1312
|
const response = await this.requestAI([userMessage], this.ANALYSIS_SYSTEM_PROMPT);
|
|
1280
1313
|
if (response) return {
|
|
@@ -1306,8 +1339,8 @@ ${combinedText}` }, ...images];
|
|
|
1306
1339
|
const userMessage = { role: "user", content: JSON.stringify(userMessageContent) };
|
|
1307
1340
|
const response = await this.requestAI([userMessage], this.DUPLICATE_CHECK_SYSTEM_PROMPT);
|
|
1308
1341
|
return response?.duplicate || false;
|
|
1309
|
-
} catch (
|
|
1310
|
-
this.logger.error(`比较回声洞(${caveA.id})与(${caveB.id})失败:`,
|
|
1342
|
+
} catch (error) {
|
|
1343
|
+
this.logger.error(`比较回声洞(${caveA.id})与(${caveB.id})失败:`, error);
|
|
1311
1344
|
return false;
|
|
1312
1345
|
}
|
|
1313
1346
|
}
|
|
@@ -1346,22 +1379,28 @@ ${combinedText}` }, ...images];
|
|
|
1346
1379
|
"Content-Type": "application/json",
|
|
1347
1380
|
"Authorization": `Bearer ${this.config.aiApiKey}`
|
|
1348
1381
|
};
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1382
|
+
try {
|
|
1383
|
+
const response = await this.http.post(fullUrl, payload, { headers, timeout: 6e5 });
|
|
1384
|
+
const content = response?.choices?.[0]?.message?.content;
|
|
1385
|
+
if (!content?.trim()) throw new Error();
|
|
1386
|
+
const candidates = [];
|
|
1387
|
+
const jsonBlockMatch = content.match(/```json\s*([\s\S]*?)\s*```/i);
|
|
1388
|
+
if (jsonBlockMatch && jsonBlockMatch[1]) candidates.push(jsonBlockMatch[1]);
|
|
1389
|
+
candidates.push(content);
|
|
1390
|
+
const firstBrace = content.indexOf("{");
|
|
1391
|
+
const lastBrace = content.lastIndexOf("}");
|
|
1392
|
+
if (firstBrace !== -1 && lastBrace > firstBrace) candidates.push(content.substring(firstBrace, lastBrace + 1));
|
|
1393
|
+
for (const candidate of [...new Set(candidates)]) {
|
|
1394
|
+
try {
|
|
1395
|
+
return JSON.parse(candidate);
|
|
1396
|
+
} catch (parseError) {
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
this.logger.error("解析失败", "原始响应:", JSON.stringify(response, null, 2));
|
|
1400
|
+
throw new Error();
|
|
1401
|
+
} catch (e) {
|
|
1402
|
+
throw e;
|
|
1362
1403
|
}
|
|
1363
|
-
this.logger.error("解析失败:", import_console.error, "原始响应:", JSON.stringify(response, null, 2));
|
|
1364
|
-
throw import_console.error;
|
|
1365
1404
|
}
|
|
1366
1405
|
};
|
|
1367
1406
|
|
|
@@ -1440,8 +1479,8 @@ function apply(ctx, config) {
|
|
|
1440
1479
|
await ctx.database.upsert("cave", idsToMark);
|
|
1441
1480
|
await cleanupPendingDeletions(ctx, config, fileManager, logger, reusableIds);
|
|
1442
1481
|
}
|
|
1443
|
-
} catch (
|
|
1444
|
-
logger.error("清理残留回声洞时发生错误:",
|
|
1482
|
+
} catch (error) {
|
|
1483
|
+
logger.error("清理残留回声洞时发生错误:", error);
|
|
1445
1484
|
}
|
|
1446
1485
|
});
|
|
1447
1486
|
const cave = ctx.command("cave", "回声洞").option("add", "-a <content:text> 添加回声洞").option("view", "-g <id:posint> 查看指定回声洞").option("delete", "-r <id:posint> 删除指定回声洞").option("list", "-l 查询投稿统计").usage("随机抽取一条已添加的回声洞。").action(async ({ session, options }) => {
|
|
@@ -1457,8 +1496,8 @@ function apply(ctx, config) {
|
|
|
1457
1496
|
const [randomCave] = await ctx.database.get("cave", { ...query, id: randomId });
|
|
1458
1497
|
const messages = await buildCaveMessage(randomCave, config, fileManager, logger, session.platform);
|
|
1459
1498
|
for (const message of messages) if (message.length > 0) await session.send(import_koishi3.h.normalize(message));
|
|
1460
|
-
} catch (
|
|
1461
|
-
logger.error("随机获取回声洞失败:",
|
|
1499
|
+
} catch (error) {
|
|
1500
|
+
logger.error("随机获取回声洞失败:", error);
|
|
1462
1501
|
return "随机获取回声洞失败";
|
|
1463
1502
|
}
|
|
1464
1503
|
});
|
|
@@ -1534,11 +1573,11 @@ function apply(ctx, config) {
|
|
|
1534
1573
|
if (allHashesToInsert.length > 0) await ctx.database.upsert("cave_hash", allHashesToInsert);
|
|
1535
1574
|
}
|
|
1536
1575
|
if (finalStatus === "pending" && reviewManager) reviewManager.sendForPend(newCave);
|
|
1537
|
-
} catch (
|
|
1538
|
-
logger.error(`回声洞(${newId})处理失败:`,
|
|
1576
|
+
} catch (error) {
|
|
1577
|
+
logger.error(`回声洞(${newId})处理失败:`, error);
|
|
1539
1578
|
await ctx.database.upsert("cave", [{ id: newId, status: "delete" }]);
|
|
1540
1579
|
await cleanupPendingDeletions(ctx, config, fileManager, logger, reusableIds);
|
|
1541
|
-
await session.send(`回声洞(${newId})处理失败: ${
|
|
1580
|
+
await session.send(`回声洞(${newId})处理失败: ${error.message}`);
|
|
1542
1581
|
}
|
|
1543
1582
|
})();
|
|
1544
1583
|
});
|
|
@@ -1549,8 +1588,8 @@ function apply(ctx, config) {
|
|
|
1549
1588
|
if (!targetCave) return `回声洞(${id})不存在`;
|
|
1550
1589
|
const messages = await buildCaveMessage(targetCave, config, fileManager, logger, session.platform);
|
|
1551
1590
|
for (const message of messages) if (message.length > 0) await session.send(import_koishi3.h.normalize(message));
|
|
1552
|
-
} catch (
|
|
1553
|
-
logger.error(`查看回声洞(${id})失败:`,
|
|
1591
|
+
} catch (error) {
|
|
1592
|
+
logger.error(`查看回声洞(${id})失败:`, error);
|
|
1554
1593
|
return "查看失败,请稍后再试";
|
|
1555
1594
|
}
|
|
1556
1595
|
});
|
|
@@ -1566,8 +1605,8 @@ function apply(ctx, config) {
|
|
|
1566
1605
|
const caveMessages = await buildCaveMessage(targetCave, config, fileManager, logger, session.platform, "已删除");
|
|
1567
1606
|
for (const message of caveMessages) if (message.length > 0) await session.send(import_koishi3.h.normalize(message));
|
|
1568
1607
|
cleanupPendingDeletions(ctx, config, fileManager, logger, reusableIds);
|
|
1569
|
-
} catch (
|
|
1570
|
-
logger.error(`标记回声洞(${id})失败:`,
|
|
1608
|
+
} catch (error) {
|
|
1609
|
+
logger.error(`标记回声洞(${id})失败:`, error);
|
|
1571
1610
|
return "删除失败,请稍后再试";
|
|
1572
1611
|
}
|
|
1573
1612
|
});
|
|
@@ -1596,8 +1635,8 @@ function apply(ctx, config) {
|
|
|
1596
1635
|
`;
|
|
1597
1636
|
});
|
|
1598
1637
|
return report.trim();
|
|
1599
|
-
} catch (
|
|
1600
|
-
logger.error("查询排行失败:",
|
|
1638
|
+
} catch (error) {
|
|
1639
|
+
logger.error("查询排行失败:", error);
|
|
1601
1640
|
return "查询失败,请稍后再试";
|
|
1602
1641
|
}
|
|
1603
1642
|
}
|