koishi-plugin-best-cave 1.5.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +43 -11
- package/lib/utils/mediaUtils.d.ts +0 -0
- package/package.json +3 -3
- package/lib/utils/HashStorage.d.ts +0 -92
- package/lib/utils/ImageHasher.d.ts +0 -81
- package/lib/utils/fileHandler.d.ts +0 -63
- package/lib/utils/idManager.d.ts +0 -69
package/lib/index.js
CHANGED
|
@@ -33,14 +33,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
33
33
|
// src/locales/zh-CN.yml
|
|
34
34
|
var require_zh_CN = __commonJS({
|
|
35
35
|
"src/locales/zh-CN.yml"(exports2, module2) {
|
|
36
|
-
module2.exports = { _config: { manager: "管理员", number: "冷却时间(秒)", enableAudit: "启用审核", enableTextDuplicate: "启用文本查重", textDuplicateThreshold: "文本相似度阈值(0-1)", enableImageDuplicate: "启用图片查重", imageDuplicateThreshold: "图片相似度阈值(0-1)", imageMaxSize: "图片最大大小(MB)", allowVideo: "允许视频上传", videoMaxSize: "视频最大大小(MB)", enablePagination: "启用统计分页", itemsPerPage: "每页显示数目", blacklist: "黑名单(用户)", whitelist: "审核白名单(用户/群组/频道)" }, commands: { cave: { description: "回声洞", usage: "支持添加、抽取、查看、管理回声洞", examples: "使用 cave 随机抽取回声洞\n使用 -a 直接添加或引用添加\n使用 -g 查看指定回声洞\n使用 -r 删除指定回声洞", options: { a: "添加回声洞", g: "查看回声洞", r: "删除回声洞",
|
|
36
|
+
module2.exports = { _config: { manager: "管理员", number: "冷却时间(秒)", enableAudit: "启用审核", enableTextDuplicate: "启用文本查重", textDuplicateThreshold: "文本相似度阈值(0-1)", enableImageDuplicate: "启用图片查重", imageDuplicateThreshold: "图片相似度阈值(0-1)", imageMaxSize: "图片最大大小(MB)", allowVideo: "允许视频上传", videoMaxSize: "视频最大大小(MB)", enablePagination: "启用统计分页", itemsPerPage: "每页显示数目", blacklist: "黑名单(用户)", whitelist: "审核白名单(用户/群组/频道)" }, commands: { cave: { description: "回声洞", usage: "支持添加、抽取、查看、管理回声洞", examples: "使用 cave 随机抽取回声洞\n使用 -a 直接添加或引用添加\n使用 -g 查看指定回声洞\n使用 -r 删除指定回声洞", options: { a: "添加回声洞", g: "查看回声洞", r: "删除回声洞", l: "查询投稿统计" }, pass: { description: "通过回声洞审核", usage: "通过指定ID的回声洞审核\ncave.pass <ID> - 通过审核\ncave.pass all - 通过所有待审核内容\n" }, reject: { description: "拒绝回声洞审核", usage: "拒绝指定ID的回声洞审核\ncave.reject <ID> - 拒绝审核\ncave.reject all - 拒绝所有待审核内容\n" }, add: { noContent: "请在一分钟内发送内容", operationTimeout: "操作超时,添加取消", videoDisabled: "不允许上传视频", submitPending: "提交成功,序号为({0})", addSuccess: "添加成功,序号为({0})", mediaSizeExceeded: "{0}文件大小超过限制", localFileNotAllowed: "检测到本地文件路径,无法保存" }, remove: { noPermission: "你无权删除他人添加的回声洞", deletePending: "删除(待审核)", deleted: "已删除" }, list: { pageInfo: "第 {0} / {1} 页", header: "当前共有 {0} 项回声洞:", totalItems: "用户 {0} 共计投稿 {1} 项:", idsLine: "{0}" }, audit: { noPending: "暂无待审核回声洞", pendingNotFound: "未找到待审核回声洞", pendingResult: "{0},剩余 {1} 个待审核回声洞:[{2}]", auditPassed: "已通过", auditRejected: "已拒绝", batchAuditResult: "已{0} {1}/{2} 项回声洞", title: "待审核回声洞:", from: "投稿人:", sendFailed: "发送审核消息失败,无法联系管理员 {0}" }, error: { noContent: "回声洞内容为空", getCave: "获取回声洞失败", noCave: "没有回声洞", invalidId: "请输入有效的回声洞ID", notFound: "未找到该回声洞", exactDuplicateFound: "发现完全相同的", similarDuplicateFound: "发现相似度为 {0}% 的", addFailed: "添加失败,请稍后重试。" }, message: { blacklisted: "你已被列入黑名单", managerOnly: "此操作仅限管理员可用", cooldown: "群聊冷却中...请在 {0} 秒后重试", caveTitle: "回声洞 —— ({0})", contributorSuffix: "—— {0}", mediaSizeExceeded: "{0}文件大小超过限制" } } } };
|
|
37
37
|
}
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
// src/locales/en-US.yml
|
|
41
41
|
var require_en_US = __commonJS({
|
|
42
42
|
"src/locales/en-US.yml"(exports2, module2) {
|
|
43
|
-
module2.exports = { _config: { manager: "Administrator", number: "Cooldown time (seconds)", enableAudit: "Enable moderation", enableTextDuplicate: "Enable text duplicate check", textDuplicateThreshold: "Text similarity threshold (0-1)", enableImageDuplicate: "Enable image duplicate check", imageDuplicateThreshold: "Image similarity threshold (0-1)", imageMaxSize: "Maximum image size (MB)", allowVideo: "Allow video upload", videoMaxSize: "Maximum video size (MB)", enablePagination: "Enable statistics pagination", itemsPerPage: "Items per page", blacklist: "Blacklist (users)", whitelist: "Moderation whitelist (users/groups/channels)" }, commands: { cave: { description: "Echo Cave", usage: "Support adding, drawing, viewing, and managing echo caves", examples: "Use cave to randomly draw an echo\nUse -a to add directly or add by reference\nUse -g to view specific echo\nUse -r to delete specific echo", options: { a: "Add echo", g: "View echo", r: "Delete echo",
|
|
43
|
+
module2.exports = { _config: { manager: "Administrator", number: "Cooldown time (seconds)", enableAudit: "Enable moderation", enableTextDuplicate: "Enable text duplicate check", textDuplicateThreshold: "Text similarity threshold (0-1)", enableImageDuplicate: "Enable image duplicate check", imageDuplicateThreshold: "Image similarity threshold (0-1)", imageMaxSize: "Maximum image size (MB)", allowVideo: "Allow video upload", videoMaxSize: "Maximum video size (MB)", enablePagination: "Enable statistics pagination", itemsPerPage: "Items per page", blacklist: "Blacklist (users)", whitelist: "Moderation whitelist (users/groups/channels)" }, commands: { cave: { description: "Echo Cave", usage: "Support adding, drawing, viewing, and managing echo caves", examples: "Use cave to randomly draw an echo\nUse -a to add directly or add by reference\nUse -g to view specific echo\nUse -r to delete specific echo", options: { a: "Add echo", g: "View echo", r: "Delete echo", l: "Query submission statistics" }, pass: { description: "Approve cave submission", usage: "Approve cave submission with specific ID\ncave.pass <ID> - Approve submission\ncave.pass all - Approve all pending submissions\n" }, reject: { description: "Reject cave submission", usage: "Reject cave submission with specific ID\ncave.reject <ID> - Reject submission\ncave.reject all - Reject all pending submissions\n" }, add: { noContent: "Please send content within one minute", operationTimeout: "Operation timeout, addition cancelled", videoDisabled: "Video upload not allowed", submitPending: "Submission successful, ID is ({0})", addSuccess: "Added successfully, ID is ({0})", mediaSizeExceeded: "{0} file size exceeds limit", localFileNotAllowed: "Local file path detected, cannot save" }, remove: { noPermission: "You don't have permission to delete others' echos", deletePending: "Delete (pending review)", deleted: "Deleted" }, list: { pageInfo: "Page {0} / {1}", header: "Currently there are {0} echos:", totalItems: "User {0} has submitted {1} items:", idsLine: "{0}" }, audit: { noPending: "No pending echos for review", pendingNotFound: "Pending echo not found", pendingResult: "{0}, {1} pending echos remaining: [{2}]", auditPassed: "Approved", auditRejected: "Rejected", batchAuditResult: "{0} {1}/{2} echos", title: "Pending echos:", from: "Submitted by:", sendFailed: "Failed to send moderation message, cannot contact administrator {0}" }, error: { noContent: "Echo content is empty", getCave: "Failed to get echo", noCave: "No echos available", invalidId: "Please enter a valid echo ID", notFound: "Echo not found", exactDuplicateFound: "Found exactly identical", similarDuplicateFound: "Found {0}% similar", addFailed: "Add failed, please try again later." }, message: { blacklisted: "You have been blacklisted", managerOnly: "This operation is limited to administrators only", cooldown: "Group chat cooling down... Please try again in {0} seconds", caveTitle: "Echo Cave —— ({0})", contributorSuffix: "—— {0}", mediaSizeExceeded: "{0} file size exceeds limit" } } } };
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
46
|
|
|
@@ -1343,7 +1343,7 @@ async function apply(ctx, config) {
|
|
|
1343
1343
|
let caveId;
|
|
1344
1344
|
try {
|
|
1345
1345
|
const inputContent = content.length > 0 ? content.join("\n") : await (async () => {
|
|
1346
|
-
await sendMessage(session, "commands.cave.add.noContent", [], true);
|
|
1346
|
+
await sendMessage(session, "commands.cave.add.noContent", [], true, 6e4);
|
|
1347
1347
|
const reply = await session.prompt({ timeout: 6e4 });
|
|
1348
1348
|
if (!reply) throw new Error(session.text("commands.cave.add.operationTimeout"));
|
|
1349
1349
|
return reply;
|
|
@@ -1481,20 +1481,17 @@ async function apply(ctx, config) {
|
|
|
1481
1481
|
}
|
|
1482
1482
|
}
|
|
1483
1483
|
__name(processAdd, "processAdd");
|
|
1484
|
-
ctx.command("cave [message]").option("a", "添加回声洞").option("g", "查看回声洞", { type: "string" }).option("r", "删除回声洞", { type: "string" }).option("
|
|
1484
|
+
const caveCommand = ctx.command("cave [message]").option("a", "添加回声洞").option("g", "查看回声洞", { type: "string" }).option("r", "删除回声洞", { type: "string" }).option("l", "查询投稿统计", { type: "string" }).before(async ({ session, options }) => {
|
|
1485
1485
|
if (config.blacklist.includes(session.userId)) {
|
|
1486
1486
|
return sendMessage(session, "commands.cave.message.blacklisted", [], true);
|
|
1487
1487
|
}
|
|
1488
|
-
if ((options.p || options.d) && !config.manager.includes(session.userId)) {
|
|
1489
|
-
return sendMessage(session, "commands.cave.message.managerOnly", [], true);
|
|
1490
|
-
}
|
|
1491
1488
|
}).action(async ({ session, options }, ...content) => {
|
|
1492
1489
|
const dataDir2 = path5.join(ctx.baseDir, "data");
|
|
1493
1490
|
const caveDir2 = path5.join(dataDir2, "cave");
|
|
1494
1491
|
const caveFilePath = path5.join(caveDir2, "cave.json");
|
|
1495
1492
|
const resourceDir = path5.join(caveDir2, "resources");
|
|
1496
1493
|
const pendingFilePath = path5.join(caveDir2, "pending.json");
|
|
1497
|
-
const needsCooldown = !options.l && !options.a
|
|
1494
|
+
const needsCooldown = !options.l && !options.a;
|
|
1498
1495
|
if (needsCooldown) {
|
|
1499
1496
|
const guildId = session.guildId;
|
|
1500
1497
|
const now = Date.now();
|
|
@@ -1524,9 +1521,6 @@ async function apply(ctx, config) {
|
|
|
1524
1521
|
return await processList(session, config, session.userId);
|
|
1525
1522
|
}
|
|
1526
1523
|
}
|
|
1527
|
-
if (options.p || options.d) {
|
|
1528
|
-
return await processAudit(pendingFilePath, caveFilePath, resourceDir, session, options, content);
|
|
1529
|
-
}
|
|
1530
1524
|
if (options.g) {
|
|
1531
1525
|
return await processView(caveFilePath, resourceDir, session, options, content);
|
|
1532
1526
|
}
|
|
@@ -1538,6 +1532,44 @@ async function apply(ctx, config) {
|
|
|
1538
1532
|
}
|
|
1539
1533
|
return await processRandom(caveFilePath, resourceDir, session);
|
|
1540
1534
|
});
|
|
1535
|
+
caveCommand.subcommand(".pass <id:text>", "通过回声洞审核").before(async ({ session }) => {
|
|
1536
|
+
if (!config.manager.includes(session.userId)) {
|
|
1537
|
+
return sendMessage(session, "commands.cave.message.managerOnly", [], true);
|
|
1538
|
+
}
|
|
1539
|
+
}).action(async ({ session }, id) => {
|
|
1540
|
+
const dataDir2 = path5.join(ctx.baseDir, "data");
|
|
1541
|
+
const caveDir2 = path5.join(dataDir2, "cave");
|
|
1542
|
+
const caveFilePath = path5.join(caveDir2, "cave.json");
|
|
1543
|
+
const resourceDir = path5.join(caveDir2, "resources");
|
|
1544
|
+
const pendingFilePath = path5.join(caveDir2, "pending.json");
|
|
1545
|
+
return await processAudit(
|
|
1546
|
+
pendingFilePath,
|
|
1547
|
+
caveFilePath,
|
|
1548
|
+
resourceDir,
|
|
1549
|
+
session,
|
|
1550
|
+
{ p: true },
|
|
1551
|
+
[id]
|
|
1552
|
+
);
|
|
1553
|
+
});
|
|
1554
|
+
caveCommand.subcommand(".reject <id:text>", "拒绝回声洞审核").before(async ({ session }) => {
|
|
1555
|
+
if (!config.manager.includes(session.userId)) {
|
|
1556
|
+
return sendMessage(session, "commands.cave.message.managerOnly", [], true);
|
|
1557
|
+
}
|
|
1558
|
+
}).action(async ({ session }, id) => {
|
|
1559
|
+
const dataDir2 = path5.join(ctx.baseDir, "data");
|
|
1560
|
+
const caveDir2 = path5.join(dataDir2, "cave");
|
|
1561
|
+
const caveFilePath = path5.join(caveDir2, "cave.json");
|
|
1562
|
+
const resourceDir = path5.join(caveDir2, "resources");
|
|
1563
|
+
const pendingFilePath = path5.join(caveDir2, "pending.json");
|
|
1564
|
+
return await processAudit(
|
|
1565
|
+
pendingFilePath,
|
|
1566
|
+
caveFilePath,
|
|
1567
|
+
resourceDir,
|
|
1568
|
+
session,
|
|
1569
|
+
{ d: true },
|
|
1570
|
+
[id]
|
|
1571
|
+
);
|
|
1572
|
+
});
|
|
1541
1573
|
}
|
|
1542
1574
|
__name(apply, "apply");
|
|
1543
1575
|
var logger4 = new import_koishi5.Logger("cave");
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-best-cave",
|
|
3
3
|
"description": "最好的 cave 插件,可开关的审核系统,可引用添加,支持图文混合内容,可查阅投稿列表,完美复刻你的 .cave 体验!",
|
|
4
|
-
"version": "1.5.
|
|
4
|
+
"version": "1.5.1",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Yis_Rime <yis_rime@outlook.com>"
|
|
7
7
|
],
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"devDependencies": {},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"koishi": "^4.18.3",
|
|
29
|
-
"sharp": "^0.
|
|
29
|
+
"sharp": "^0.33.5",
|
|
30
30
|
"koishi-plugin-adapter-onebot": "^6.1.3"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"sharp": "^0.
|
|
33
|
+
"sharp": "^0.33.5",
|
|
34
34
|
"koishi-plugin-adapter-onebot": "^6.1.3"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 哈希存储管理类
|
|
3
|
-
* @class HashStorage
|
|
4
|
-
*/
|
|
5
|
-
export declare class HashStorage {
|
|
6
|
-
private readonly caveDir;
|
|
7
|
-
private readonly filePath;
|
|
8
|
-
private readonly resourceDir;
|
|
9
|
-
private readonly caveFilePath;
|
|
10
|
-
private imageHashes;
|
|
11
|
-
private textHashes;
|
|
12
|
-
private initialized;
|
|
13
|
-
/**
|
|
14
|
-
* 创建哈希存储实例
|
|
15
|
-
* @param caveDir - 回声洞数据目录路径
|
|
16
|
-
*/
|
|
17
|
-
constructor(caveDir: string);
|
|
18
|
-
/**
|
|
19
|
-
* 初始化哈希存储
|
|
20
|
-
* @throws 初始化失败时抛出错误
|
|
21
|
-
*/
|
|
22
|
-
initialize(): Promise<void>;
|
|
23
|
-
/**
|
|
24
|
-
* 加载哈希数据
|
|
25
|
-
* @param data - 要加载的哈希数据
|
|
26
|
-
* @private
|
|
27
|
-
*/
|
|
28
|
-
private loadHashData;
|
|
29
|
-
/**
|
|
30
|
-
* 更新指定回声洞的哈希值
|
|
31
|
-
* @param caveId - 回声洞ID
|
|
32
|
-
* @param type - 哈希类型(图像或文本)
|
|
33
|
-
* @param content - 要计算哈希的内容
|
|
34
|
-
*/
|
|
35
|
-
updateHash(caveId: number, type: 'image' | 'text', content: Buffer | string): Promise<void>;
|
|
36
|
-
/**
|
|
37
|
-
* 查找重复项
|
|
38
|
-
* @param type - 查找类型(图像或文本)
|
|
39
|
-
* @param hashes - 要查找的哈希值数组
|
|
40
|
-
* @param threshold - 相似度阈值,默认为1
|
|
41
|
-
* @returns 匹配结果数组
|
|
42
|
-
*/
|
|
43
|
-
findDuplicates(type: 'image' | 'text', hashes: string[], threshold?: number): Promise<Array<{
|
|
44
|
-
index: number;
|
|
45
|
-
caveId: number;
|
|
46
|
-
similarity: number;
|
|
47
|
-
} | null>>;
|
|
48
|
-
/**
|
|
49
|
-
* 清除指定回声洞的所有哈希值
|
|
50
|
-
* @param caveId - 回声洞ID
|
|
51
|
-
*/
|
|
52
|
-
clearHashes(caveId: number): Promise<void>;
|
|
53
|
-
/**
|
|
54
|
-
* 构建初始哈希值
|
|
55
|
-
* @private
|
|
56
|
-
*/
|
|
57
|
-
private buildInitialHashes;
|
|
58
|
-
/**
|
|
59
|
-
* 更新缺失的哈希值
|
|
60
|
-
* @private
|
|
61
|
-
*/
|
|
62
|
-
private updateMissingHashes;
|
|
63
|
-
/**
|
|
64
|
-
* 处理单个回声洞的哈希值
|
|
65
|
-
* @param cave - 回声洞数据
|
|
66
|
-
* @private
|
|
67
|
-
*/
|
|
68
|
-
private processCaveHashes;
|
|
69
|
-
private processCaveTextHashes;
|
|
70
|
-
/**
|
|
71
|
-
* 保存哈希数据到文件
|
|
72
|
-
* @private
|
|
73
|
-
*/
|
|
74
|
-
private saveHashes;
|
|
75
|
-
/**
|
|
76
|
-
* 加载回声洞数据
|
|
77
|
-
* @returns 回声洞数据数组
|
|
78
|
-
* @private
|
|
79
|
-
*/
|
|
80
|
-
private loadCaveData;
|
|
81
|
-
/**
|
|
82
|
-
* 计算文本的哈希值
|
|
83
|
-
* @param text - 要计算哈希的文本
|
|
84
|
-
* @returns MD5哈希值
|
|
85
|
-
*/
|
|
86
|
-
static hashText(text: string): string;
|
|
87
|
-
/**
|
|
88
|
-
* 获取存储统计数据
|
|
89
|
-
* @private
|
|
90
|
-
*/
|
|
91
|
-
private getStorageStats;
|
|
92
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { Buffer } from 'buffer';
|
|
2
|
-
/**
|
|
3
|
-
* 图片哈希计算工具类
|
|
4
|
-
* 使用 DCT(离散余弦变换)方法计算图片的感知哈希值,可用于图片相似度比较
|
|
5
|
-
*/
|
|
6
|
-
export declare class ImageHasher {
|
|
7
|
-
/**
|
|
8
|
-
* 计算图片的感知哈希值
|
|
9
|
-
* @param imageBuffer - 图片的二进制数据
|
|
10
|
-
* @returns 返回64位的十六进制哈希字符串
|
|
11
|
-
* @throws 当图片处理失败时可能抛出错误
|
|
12
|
-
*/
|
|
13
|
-
static calculateHash(imageBuffer: Buffer): Promise<string>;
|
|
14
|
-
/**
|
|
15
|
-
* 将二进制字符串转换为十六进制
|
|
16
|
-
* @param binary - 二进制字符串
|
|
17
|
-
* @returns 十六进制字符串
|
|
18
|
-
* @private
|
|
19
|
-
*/
|
|
20
|
-
private static binaryToHex;
|
|
21
|
-
/**
|
|
22
|
-
* 将十六进制字符串转换为二进制
|
|
23
|
-
* @param hex - 十六进制字符串
|
|
24
|
-
* @returns 二进制字符串
|
|
25
|
-
* @private
|
|
26
|
-
*/
|
|
27
|
-
private static hexToBinary;
|
|
28
|
-
/**
|
|
29
|
-
* 计算图像的DCT(离散余弦变换)
|
|
30
|
-
* @param data - 图像数据
|
|
31
|
-
* @param size - 图像尺寸
|
|
32
|
-
* @returns DCT变换后的矩阵
|
|
33
|
-
* @private
|
|
34
|
-
*/
|
|
35
|
-
private static computeDCT;
|
|
36
|
-
/**
|
|
37
|
-
* 获取DCT系数
|
|
38
|
-
* @param index - 索引值
|
|
39
|
-
* @param size - 矩阵大小
|
|
40
|
-
* @returns DCT系数
|
|
41
|
-
* @private
|
|
42
|
-
*/
|
|
43
|
-
private static getDCTCoefficient;
|
|
44
|
-
/**
|
|
45
|
-
* 计算数组的中位数
|
|
46
|
-
* @param arr - 输入数组
|
|
47
|
-
* @returns 中位数
|
|
48
|
-
* @private
|
|
49
|
-
*/
|
|
50
|
-
private static calculateMedian;
|
|
51
|
-
/**
|
|
52
|
-
* 从DCT矩阵中提取特征值
|
|
53
|
-
* @param matrix - DCT矩阵
|
|
54
|
-
* @param size - 矩阵大小
|
|
55
|
-
* @returns 特征值数组
|
|
56
|
-
* @private
|
|
57
|
-
*/
|
|
58
|
-
private static extractFeatures;
|
|
59
|
-
/**
|
|
60
|
-
* 计算两个哈希值之间的汉明距离
|
|
61
|
-
* @param hash1 - 第一个哈希值
|
|
62
|
-
* @param hash2 - 第二个哈希值
|
|
63
|
-
* @returns 汉明距离
|
|
64
|
-
* @throws 当两个哈希值长度不等时抛出错误
|
|
65
|
-
*/
|
|
66
|
-
static calculateDistance(hash1: string, hash2: string): number;
|
|
67
|
-
/**
|
|
68
|
-
* 计算两个图片哈希值的相似度
|
|
69
|
-
* @param hash1 - 第一个哈希值
|
|
70
|
-
* @param hash2 - 第二个哈希值
|
|
71
|
-
* @returns 返回0-1之间的相似度值,1表示完全相同,0表示完全不同
|
|
72
|
-
*/
|
|
73
|
-
static calculateSimilarity(hash1: string, hash2: string): number;
|
|
74
|
-
/**
|
|
75
|
-
* 批量比较一个新哈希值与多个已存在哈希值的相似度
|
|
76
|
-
* @param newHash - 新的哈希值
|
|
77
|
-
* @param existingHashes - 已存在的哈希值数组
|
|
78
|
-
* @returns 相似度数组,每个元素对应一个已存在哈希值的相似度
|
|
79
|
-
*/
|
|
80
|
-
static batchCompareSimilarity(newHash: string, existingHashes: string[]): number[];
|
|
81
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
export declare class FileHandler {
|
|
2
|
-
private static locks;
|
|
3
|
-
private static readonly RETRY_COUNT;
|
|
4
|
-
private static readonly RETRY_DELAY;
|
|
5
|
-
private static readonly CONCURRENCY_LIMIT;
|
|
6
|
-
/**
|
|
7
|
-
* 并发控制
|
|
8
|
-
* @param operation 要执行的操作
|
|
9
|
-
* @param limit 并发限制
|
|
10
|
-
* @returns 操作结果
|
|
11
|
-
*/
|
|
12
|
-
private static withConcurrencyLimit;
|
|
13
|
-
/**
|
|
14
|
-
* 文件操作包装器
|
|
15
|
-
* @param filePath 文件路径
|
|
16
|
-
* @param operation 要执行的操作
|
|
17
|
-
* @returns 操作结果
|
|
18
|
-
*/
|
|
19
|
-
private static withFileOp;
|
|
20
|
-
/**
|
|
21
|
-
* 事务处理
|
|
22
|
-
* @param operations 要执行的操作数组
|
|
23
|
-
* @returns 操作结果数组
|
|
24
|
-
*/
|
|
25
|
-
static withTransaction<T>(operations: Array<{
|
|
26
|
-
filePath: string;
|
|
27
|
-
operation: () => Promise<T>;
|
|
28
|
-
rollback?: () => Promise<void>;
|
|
29
|
-
}>): Promise<T[]>;
|
|
30
|
-
/**
|
|
31
|
-
* 读取 JSON 数据
|
|
32
|
-
* @param filePath 文件路径
|
|
33
|
-
* @returns JSON 数据
|
|
34
|
-
*/
|
|
35
|
-
static readJsonData<T>(filePath: string): Promise<T[]>;
|
|
36
|
-
/**
|
|
37
|
-
* 写入 JSON 数据
|
|
38
|
-
* @param filePath 文件路径
|
|
39
|
-
* @param data 要写入的数据
|
|
40
|
-
*/
|
|
41
|
-
static writeJsonData<T>(filePath: string, data: T[]): Promise<void>;
|
|
42
|
-
/**
|
|
43
|
-
* 确保目录存在
|
|
44
|
-
* @param dir 目录路径
|
|
45
|
-
*/
|
|
46
|
-
static ensureDirectory(dir: string): Promise<void>;
|
|
47
|
-
/**
|
|
48
|
-
* 确保 JSON 文件存在
|
|
49
|
-
* @param filePath 文件路径
|
|
50
|
-
*/
|
|
51
|
-
static ensureJsonFile(filePath: string): Promise<void>;
|
|
52
|
-
/**
|
|
53
|
-
* 保存媒体文件
|
|
54
|
-
* @param filePath 文件路径
|
|
55
|
-
* @param data 文件数据
|
|
56
|
-
*/
|
|
57
|
-
static saveMediaFile(filePath: string, data: Buffer | string): Promise<void>;
|
|
58
|
-
/**
|
|
59
|
-
* 删除媒体文件
|
|
60
|
-
* @param filePath 文件路径
|
|
61
|
-
*/
|
|
62
|
-
static deleteMediaFile(filePath: string): Promise<void>;
|
|
63
|
-
}
|
package/lib/utils/idManager.d.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ID管理器类
|
|
3
|
-
* 负责管理回声洞ID的分配、删除和统计信息
|
|
4
|
-
*/
|
|
5
|
-
export declare class IdManager {
|
|
6
|
-
private deletedIds;
|
|
7
|
-
private maxId;
|
|
8
|
-
private initialized;
|
|
9
|
-
private readonly statusFilePath;
|
|
10
|
-
private stats;
|
|
11
|
-
private usedIds;
|
|
12
|
-
/**
|
|
13
|
-
* 初始化ID管理器
|
|
14
|
-
* @param baseDir - 基础目录路径
|
|
15
|
-
*/
|
|
16
|
-
constructor(baseDir: string);
|
|
17
|
-
/**
|
|
18
|
-
* 初始化ID管理系统
|
|
19
|
-
* @param caveFilePath - 正式回声洞数据文件路径
|
|
20
|
-
* @param pendingFilePath - 待处理回声洞数据文件路径
|
|
21
|
-
* @throws 当初始化失败时抛出错误
|
|
22
|
-
*/
|
|
23
|
-
initialize(caveFilePath: string, pendingFilePath: string): Promise<void>;
|
|
24
|
-
/**
|
|
25
|
-
* 处理ID冲突
|
|
26
|
-
* @param conflicts - ID冲突映射表
|
|
27
|
-
* @param caveFilePath - 正式回声洞数据文件路径
|
|
28
|
-
* @param pendingFilePath - 待处理回声洞数据文件路径
|
|
29
|
-
* @param caveData - 正式回声洞数据
|
|
30
|
-
* @param pendingData - 待处理回声洞数据
|
|
31
|
-
* @private
|
|
32
|
-
*/
|
|
33
|
-
private handleConflicts;
|
|
34
|
-
/**
|
|
35
|
-
* 获取下一个可用的ID
|
|
36
|
-
* @returns 下一个可用的ID
|
|
37
|
-
* @throws 当ID管理器未初始化时抛出错误
|
|
38
|
-
*/
|
|
39
|
-
getNextId(): number;
|
|
40
|
-
/**
|
|
41
|
-
* 标记ID为已删除状态
|
|
42
|
-
* @param id - 要标记为删除的ID
|
|
43
|
-
* @throws 当ID管理器未初始化时抛出错误
|
|
44
|
-
*/
|
|
45
|
-
markDeleted(id: number): Promise<void>;
|
|
46
|
-
/**
|
|
47
|
-
* 添加贡献统计
|
|
48
|
-
* @param contributorNumber - 贡献者编号
|
|
49
|
-
* @param caveId - 回声洞ID
|
|
50
|
-
*/
|
|
51
|
-
addStat(contributorNumber: string, caveId: number): Promise<void>;
|
|
52
|
-
/**
|
|
53
|
-
* 移除贡献统计
|
|
54
|
-
* @param contributorNumber - 贡献者编号
|
|
55
|
-
* @param caveId - 回声洞ID
|
|
56
|
-
*/
|
|
57
|
-
removeStat(contributorNumber: string, caveId: number): Promise<void>;
|
|
58
|
-
/**
|
|
59
|
-
* 获取所有贡献统计信息
|
|
60
|
-
* @returns 贡献者编号到回声洞ID列表的映射
|
|
61
|
-
*/
|
|
62
|
-
getStats(): Record<string, number[]>;
|
|
63
|
-
/**
|
|
64
|
-
* 保存当前状态到文件
|
|
65
|
-
* @private
|
|
66
|
-
* @throws 当保存失败时抛出错误
|
|
67
|
-
*/
|
|
68
|
-
private saveStatus;
|
|
69
|
-
}
|