koishi-plugin-best-cave 1.3.3 → 1.3.4
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.d.ts +1 -0
- package/lib/index.js +23 -17
- package/package.json +1 -1
- package/readme.md +40 -14
package/lib/index.d.ts
CHANGED
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: "启用审核", imageMaxSize: "图片最大大小(MB)", enableDuplicate: "
|
|
36
|
+
module2.exports = { _config: { manager: "管理员", number: "冷却时间(秒)", enableAudit: "启用审核", imageMaxSize: "图片最大大小(MB)", enableMD5: "启用MD5查重", enableDuplicate: "启用pHash查重", duplicateThreshold: "pHash相似度阈值(0-1)", allowVideo: "允许视频上传", videoMaxSize: "视频最大大小(MB)", enablePagination: "启用统计分页", itemsPerPage: "每页显示数目", blacklist: "黑名单(用户)", whitelist: "审核白名单(用户/群组/频道)" }, commands: { cave: { description: "回声洞", usage: "支持添加、抽取、查看、管理回声洞", examples: "使用 cave 随机抽取回声洞\n使用 -a 直接添加或引用添加\n使用 -g 查看指定回声洞\n使用 -r 删除指定回声洞", options: { a: "添加回声洞", g: "查看回声洞", r: "删除回声洞", p: "通过审核(批量)", d: "拒绝审核(批量)", l: "查询投稿统计" }, 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}% 的" }, 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", imageMaxSize: "Maximum image size (MB)", enableDuplicate: "Enable
|
|
43
|
+
module2.exports = { _config: { manager: "Administrator", number: "Cooldown time (seconds)", enableAudit: "Enable moderation", imageMaxSize: "Maximum image size (MB)", enableMD5: "Enable MD5 duplicate check", enableDuplicate: "Enable pHash duplicate check", duplicateThreshold: "pHash similarity threshold (0-1)", 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", p: "Approve moderation (batch)", d: "Reject moderation (batch)", l: "Query submission statistics" }, 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" }, 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
|
|
|
@@ -908,10 +908,12 @@ var Config = import_koishi4.Schema.object({
|
|
|
908
908
|
// 启用审核
|
|
909
909
|
imageMaxSize: import_koishi4.Schema.number().default(4),
|
|
910
910
|
// 图片大小限制(MB)
|
|
911
|
+
enableMD5: import_koishi4.Schema.boolean().default(true),
|
|
912
|
+
// 启用MD5查重
|
|
911
913
|
enableDuplicate: import_koishi4.Schema.boolean().default(true),
|
|
912
|
-
//
|
|
914
|
+
// 启用相似度查重
|
|
913
915
|
duplicateThreshold: import_koishi4.Schema.number().default(0.8),
|
|
914
|
-
//
|
|
916
|
+
// 相似度查重阈值(0-1)
|
|
915
917
|
allowVideo: import_koishi4.Schema.boolean().default(true),
|
|
916
918
|
// 允许视频
|
|
917
919
|
videoMaxSize: import_koishi4.Schema.number().default(16),
|
|
@@ -1481,23 +1483,27 @@ async function saveMedia(urls, fileNames, resourceDir, caveId, mediaType, config
|
|
|
1481
1483
|
const buffer = Buffer.from(response.data);
|
|
1482
1484
|
if (mediaType === "img") {
|
|
1483
1485
|
const baseName = path4.basename(fileName || "md5", ext).replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, "");
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1486
|
+
if (config.enableMD5) {
|
|
1487
|
+
const files = await fs4.promises.readdir(resourceDir);
|
|
1488
|
+
const duplicateFile = files.find((file) => file.startsWith(baseName + "_"));
|
|
1489
|
+
if (duplicateFile) {
|
|
1490
|
+
const duplicateCaveId = parseInt(duplicateFile.split("_")[1]);
|
|
1491
|
+
if (!isNaN(duplicateCaveId)) {
|
|
1492
|
+
const caveFilePath = path4.join(ctx.baseDir, "data", "cave", "cave.json");
|
|
1493
|
+
const data = await FileHandler.readJsonData(caveFilePath);
|
|
1494
|
+
const originalCave = data.find((item) => item.cave_id === duplicateCaveId);
|
|
1495
|
+
if (originalCave) {
|
|
1496
|
+
const message = session.text("commands.cave.error.exactDuplicateFound");
|
|
1497
|
+
await session.send(message + await buildMessage(originalCave, resourceDir, session));
|
|
1498
|
+
throw new Error("duplicate_found");
|
|
1499
|
+
}
|
|
1496
1500
|
}
|
|
1497
1501
|
}
|
|
1498
1502
|
}
|
|
1499
1503
|
if (config.enableDuplicate) {
|
|
1500
|
-
const
|
|
1504
|
+
const hashStorage2 = new HashStorage(path4.join(ctx.baseDir, "data", "cave"));
|
|
1505
|
+
await hashStorage2.initialize();
|
|
1506
|
+
const result = await hashStorage2.findDuplicates([buffer], config.duplicateThreshold);
|
|
1501
1507
|
if (result.length > 0 && result[0] !== null) {
|
|
1502
1508
|
const duplicate = result[0];
|
|
1503
1509
|
const similarity = duplicate.similarity;
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -8,15 +8,36 @@
|
|
|
8
8
|
|
|
9
9
|
### 核心功能
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
11
|
+
- **内容管理**
|
|
12
|
+
- 支持文字与图片混合保存,自动保持布局顺序
|
|
13
|
+
- 视频内容单独发送,支持多种格式
|
|
14
|
+
- 自动文本格式化与排版
|
|
15
|
+
- 引用消息自动解析和保存
|
|
16
|
+
- 支持引用已有内容的布局
|
|
17
|
+
|
|
18
|
+
- **审核机制**
|
|
19
|
+
- 可配置的审核开关与多级权限
|
|
20
|
+
- 完整的黑白名单系统(支持用户/群组/频道)
|
|
21
|
+
- 白名单用户自动跳过审核
|
|
22
|
+
- 支持单条和批量审核操作
|
|
23
|
+
- 拒绝审核时自动清理媒体文件
|
|
24
|
+
- 审核消息自动通知管理员
|
|
25
|
+
|
|
26
|
+
- **媒体处理**
|
|
27
|
+
- 智能处理多种类型媒体链接
|
|
28
|
+
- 支持本地图片上传和URL引用
|
|
29
|
+
- 自动文件大小检查与限制
|
|
30
|
+
- 基于感知哈希的图片查重
|
|
31
|
+
- 可配置的相似度阈值检测
|
|
32
|
+
- MD5文件名重复检查
|
|
33
|
+
|
|
34
|
+
- **使用体验**
|
|
35
|
+
- 基于群组的调用冷却机制
|
|
36
|
+
- 管理员操作不受冷却限制
|
|
37
|
+
- 支持按页浏览投稿记录
|
|
38
|
+
- 支持按用户ID查询统计
|
|
39
|
+
- 临时消息自动清理
|
|
40
|
+
- 错误提示自动消失
|
|
20
41
|
|
|
21
42
|
### 指令
|
|
22
43
|
|
|
@@ -54,9 +75,14 @@
|
|
|
54
75
|
### 注意事项
|
|
55
76
|
|
|
56
77
|
1. 图片和视频会自动保存到本地,请确保存储空间充足
|
|
57
|
-
2.
|
|
58
|
-
3.
|
|
59
|
-
4.
|
|
60
|
-
5.
|
|
78
|
+
2. 管理员不受群组冷却时间限制且可查看所有用户统计
|
|
79
|
+
3. 开启审核模式后,白名单内的用户/群组/频道可直接投稿
|
|
80
|
+
4. 引用消息添加时会保留原消息的格式与布局顺序
|
|
81
|
+
5. 支持两种重复检测机制:
|
|
82
|
+
- 基于MD5的精确查重
|
|
83
|
+
- 基于感知哈希的相似度查重
|
|
61
84
|
6. 黑名单中的用户无法使用任何功能
|
|
62
|
-
7.
|
|
85
|
+
7. 支持按页码和用户ID查看投稿统计
|
|
86
|
+
8. 临时消息(如错误提示)会在10秒后自动消失
|
|
87
|
+
9. 视频内容会单独发送以保证正常显示
|
|
88
|
+
10. 支持自动清理被拒绝或删除的媒体文件
|