koishi-plugin-best-cave 1.7.3 → 2.0.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/LICENSE +70 -83
- package/lib/index.js +647 -1664
- package/package.json +4 -4
- package/readme.md +55 -78
- package/lib/index.d.ts +0 -86
- package/lib/utils/AuditHandler.d.ts +0 -89
- package/lib/utils/ContentHasher.d.ts +0 -80
- package/lib/utils/FileHandler.d.ts +0 -63
- package/lib/utils/HashManager.d.ts +0 -108
- package/lib/utils/IdManager.d.ts +0 -69
- package/lib/utils/MediaHandler.d.ts +0 -72
- package/lib/utils/ProcessHandle.d.ts +0 -45
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-best-cave",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "
|
|
3
|
+
"description": "最强大的回声洞现已重构完成啦!注意数据格式需要使用脚本转换哦~",
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Yis_Rime <yis_rime@outlook.com>"
|
|
7
7
|
],
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"lib",
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
|
-
"license": "
|
|
19
|
+
"license": "AGPL-3.0-only",
|
|
20
20
|
"keywords": [
|
|
21
21
|
"chatbot",
|
|
22
22
|
"koishi",
|
|
@@ -28,6 +28,6 @@
|
|
|
28
28
|
"koishi": "^4.18.3"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"
|
|
31
|
+
"@aws-sdk/client-s3": "^3.300.0"
|
|
32
32
|
}
|
|
33
33
|
}
|
package/readme.md
CHANGED
|
@@ -2,101 +2,78 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/koishi-plugin-best-cave)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
一款功能强大且灵活的回声洞插件,支持丰富的媒体类型、可插拔的功能模块和双重存储后端(本地或 S3)。
|
|
6
6
|
|
|
7
|
-
## 功能亮点
|
|
7
|
+
## ✨ 功能亮点
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
9
|
+
- **丰富的媒体支持**:不止于文本,轻松发布包含图片、视频、音频甚至文件的混合内容。插件会自动处理消息引用,解析并保存其内容。
|
|
10
|
+
- **双重存储后端**:可根据需求选择将媒体文件存储在 **本地服务器** (`data/cave` 目录) 或 **AWS S3** 兼容的云端对象存储中,便于扩展和管理。
|
|
11
|
+
- **可选的审核机制**:可开启审核模式 (`enableReview`)。开启后,所有新提交的内容都需要管理员审核通过才会进入公共池,确保内容质量。
|
|
12
|
+
- **作用域隔离**:通过 `perChannel` 配置,可设定回声洞是在所有群聊中共享(全局模式),还是在每个群聊中独立(分群模式)。
|
|
13
|
+
- **用户身份定制**:当 `enableProfile` 开启时,用户可以为自己在回声洞中的发言设置一个专属昵称。
|
|
14
|
+
- **便捷的数据管理**:管理员可以通过指令轻松地将所有回声洞数据导出为 `JSON` 文件备份,或从文件中恢复数据,迁移无忧 (`enableDataIO`)。
|
|
15
|
+
- **完善的权限控制**:通过 `adminUsers` 列表指定管理员,只有管理员才能执行审核、数据迁移和删除任意投稿等高级操作。
|
|
13
16
|
|
|
14
|
-
##
|
|
17
|
+
## 📖 指令说明
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
- 文字与图片混合保存,自动保持布局顺序
|
|
18
|
-
- 视频内容单独发送,支持多种格式
|
|
19
|
-
- 自动文本格式化与排版
|
|
20
|
-
- 引用消息自动解析和保存
|
|
19
|
+
### 核心指令
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
| 指令 | 别名/选项 | 说明 |
|
|
22
|
+
| :--- | :--- | :--- |
|
|
23
|
+
| `cave` | | 随机查看一条回声洞。 |
|
|
24
|
+
| `cave.add <内容>` | `cave -a <内容>` | 添加一条新的回声洞。可以直接在指令后跟内容,也可以回复或引用一条消息来添加。 |
|
|
25
|
+
| `cave.view <序号>` | `cave -g <序号>` | 查看指定序号的回声洞。 |
|
|
26
|
+
| `cave.del <序号>` | `cave -r <序号>` | 删除指定序号的回声洞。仅投稿人或管理员可操作。 |
|
|
27
|
+
| `cave.list` | `cave -l` | 查询并列出自己投稿过的所有回声洞序号。 |
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
- 完整的黑白名单系统
|
|
29
|
-
- 白名单用户自动跳过审核
|
|
30
|
-
- 拒绝审核时自动清理媒体文件
|
|
29
|
+
### 模块化指令
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
- 智能处理多种类型媒体链接
|
|
34
|
-
- 支持本地图片上传和URL引用
|
|
35
|
-
- 自动文件大小检查与限制
|
|
31
|
+
这些指令只有在配置中启用了相应功能后才可用。
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
| 指令 | 所需配置 | 说明 |
|
|
34
|
+
| :--- | :--- | :--- |
|
|
35
|
+
| `cave.profile [昵称]` | `enableProfile: true` | 设置你在回声洞中显示的昵称。若不提供昵称,则清除设置。 |
|
|
36
|
+
| `cave.review` | `enableReview: true` | **(仅管理员)** 列出所有待审核的回声洞。 |
|
|
37
|
+
| `cave.review <序号>` | `enableReview: true` | **(仅管理员)** 查看指定待审核内容的详情。 |
|
|
38
|
+
| `cave.review <序号> <Y/N>` | `enableReview: true` | **(仅管理员)** 审核指定内容。`Y` (或 `yes`, `pass`) 表示通过,`N` (或 `no`, `reject`) 表示拒绝。 |
|
|
39
|
+
| `cave.export` | `enableDataIO: true` | **(仅管理员)** 将所有回声洞数据导出到 `cave_export.json` 文件中。 |
|
|
40
|
+
| `cave.import` | `enableDataIO: true` | **(仅管理员)** 从 `cave_import.json` 文件中导入数据。 |
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
## ⚙️ 配置说明
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|------|------|------|
|
|
43
|
-
| `cave` | `cave` | 随机抽取一条回声洞 |
|
|
44
|
-
| `cave -a` | `cave -a 内容` | 添加新回声洞 |
|
|
45
|
-
| `cave -g` | `cave -g 123` | 查看指定编号回声洞 |
|
|
46
|
-
| `cave -r` | `cave -r 123` | 删除指定回声洞 |
|
|
47
|
-
| `cave -l` | `cave -l 2` 或 `cave -l 114514` | 查看统计或指定用户投稿 |
|
|
48
|
-
|
|
49
|
-
### 审核指令 (仅管理员)
|
|
50
|
-
|
|
51
|
-
| 指令 | 示例 | 说明 |
|
|
52
|
-
|------|------|------|
|
|
53
|
-
| `cave.pass` | `cave.pass 123` 或 `cave.pass all` | 通过指定/所有待审核内容 |
|
|
54
|
-
| `cave.reject` | `cave.reject 123` 或 `cave.reject all` | 拒绝指定/所有待审核内容 |
|
|
55
|
-
|
|
56
|
-
## 配置说明
|
|
44
|
+
插件配置分为三个部分:基础配置、审核配置和存储配置。
|
|
57
45
|
|
|
58
46
|
### 基础配置
|
|
59
47
|
|
|
60
48
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
61
|
-
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
67
|
-
### 权限管理
|
|
68
|
-
|
|
69
|
-
| 配置项 | 类型 | 默认值 | 说明 |
|
|
70
|
-
|--------|------|--------|------|
|
|
71
|
-
| enableAudit | boolean | false | 启用审核机制 |
|
|
72
|
-
| blacklist | string[] | [] | 黑名单(用户) |
|
|
73
|
-
| whitelist | string[] | [] | 白名单(用户/群组/频道) |
|
|
49
|
+
| :--- | :--- | :--- | :--- |
|
|
50
|
+
| `cooldown` | `number` | `10` | 指令冷却时间(秒)。管理员不受此限制。 |
|
|
51
|
+
| `perChannel` | `boolean` | `false` | 是否启用分群模式。`true` 表示每个群的回声洞独立,`false` 表示所有群共享一个回声洞池。 |
|
|
52
|
+
| `adminUsers` | `string[]` | `[]` | 管理员的用户 ID 列表。 |
|
|
53
|
+
| `enableProfile` | `boolean` | `false` | 是否启用自定义昵称功能 (`cave.profile` 指令)。 |
|
|
54
|
+
| `enableDataIO` | `boolean` | `false` | 是否启用数据导入/导出功能 (`cave.export` / `.import` 指令)。 |
|
|
74
55
|
|
|
75
|
-
###
|
|
56
|
+
### 审核配置
|
|
76
57
|
|
|
77
58
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
78
|
-
|
|
79
|
-
|
|
|
80
|
-
| textDuplicateThreshold | number | 0.9 | 文本相似度阈值 |
|
|
81
|
-
| enableImageDuplicate | boolean | true | 启用图片查重 |
|
|
82
|
-
| imageDuplicateThreshold | number | 0.8 | 图片相似度阈值 |
|
|
59
|
+
| :--- | :--- | :--- | :--- |
|
|
60
|
+
| `enableReview` | `boolean` | `false` | 是否启用审核机制。启用后,新投稿将进入待审核状态,并由管理员使用 `cave.review` 指令处理。 |
|
|
83
61
|
|
|
84
|
-
###
|
|
62
|
+
### 存储配置
|
|
85
63
|
|
|
86
64
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
87
|
-
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
7. 支持自动清理被拒绝或删除的媒体文件
|
|
65
|
+
| :--- | :--- | :--- | :--- |
|
|
66
|
+
| `enableS3` | `boolean` | `false` | 是否启用 S3 存储。若为 `false`,所有媒体文件将保存在本地 `data/cave` 目录下。 |
|
|
67
|
+
| `endpoint` | `string` | | **(S3 必填)** S3 兼容存储的 Endpoint URL。 |
|
|
68
|
+
| `bucket` | `string` | | **(S3 必填)** S3 存储桶 (Bucket) 名称。 |
|
|
69
|
+
| `region` | `string` | `'auto'` | **(S3 可选)** S3 区域 (Region)。 |
|
|
70
|
+
| `publicUrl` | `string` | | **(S3 可选)** S3 存储桶的公共访问 URL。如果提供,插件将直接用此 URL 拼接文件名来访问资源,否则将尝试使用 Base64 格式发送媒体。 |
|
|
71
|
+
| `accessKeyId` | `string` | | **(S3 必填)** S3 访问密钥 ID。 |
|
|
72
|
+
| `secretAccessKey` | `string` | | **(S3 必填)** S3 秘密访问密钥。 |
|
|
73
|
+
|
|
74
|
+
## ⚠️ 注意事项
|
|
75
|
+
|
|
76
|
+
1. **文件存储**:所有媒体文件(图片、视频等)会根据配置保存在本地 `data/cave` 目录或 S3 存储桶中。请确保 Koishi 拥有对本地目录的读写权限,或 S3 配置正确无误。
|
|
77
|
+
2. **S3 公共访问**:如果启用了 S3 并配置了 `publicUrl`,请确保该 URL 指向的存储桶策略允许公共读取,否则媒体文件将无法正常显示。
|
|
78
|
+
3. **删除机制**:删除操作(`cave.del` 或审核拒绝)并非立即从数据库和文件系统中移除。内容会被标记为 `delete` 状态,并在后台任务中被异步清理,以避免阻塞当前指令的响应。
|
|
79
|
+
4. **数据导入/导出**:导入功能会读取插件工作目录下的 `cave_import.json` 文件。请在执行导入指令前,将数据文件放置在正确位置。导出会生成 `cave_export.json`。
|
package/lib/index.d.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { Context, Schema } from 'koishi';
|
|
2
|
-
export declare const name = "best-cave";
|
|
3
|
-
export declare const inject: string[];
|
|
4
|
-
export declare const usage = "\n<div style=\"border-radius: 10px; border: 1px solid #ddd; padding: 16px; margin-bottom: 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1);\">\n <h2 style=\"margin-top: 0; color: #4a6ee0;\">\uD83D\uDCCC \u63D2\u4EF6\u8BF4\u660E</h2>\n <p>\uD83D\uDCD6 <strong>\u4F7F\u7528\u6587\u6863</strong>\uFF1A\u8BF7\u70B9\u51FB\u5DE6\u4E0A\u89D2\u7684 <strong>\u63D2\u4EF6\u4E3B\u9875</strong> \u67E5\u770B\u63D2\u4EF6\u4F7F\u7528\u6587\u6863</p>\n <p>\uD83D\uDD0D <strong>\u66F4\u591A\u63D2\u4EF6</strong>\uFF1A\u53EF\u8BBF\u95EE <a href=\"https://github.com/YisRime\" style=\"color:#4a6ee0;text-decoration:none;\">\u82E1\u6DDE\u7684 GitHub</a> \u67E5\u770B\u672C\u4EBA\u7684\u6240\u6709\u63D2\u4EF6</p>\n</div>\n\n<div style=\"border-radius: 10px; border: 1px solid #ddd; padding: 16px; margin-bottom: 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1);\">\n <h2 style=\"margin-top: 0; color: #e0574a;\">\u2764\uFE0F \u652F\u6301\u4E0E\u53CD\u9988</h2>\n <p>\uD83C\uDF1F \u559C\u6B22\u8FD9\u4E2A\u63D2\u4EF6\uFF1F\u8BF7\u5728 <a href=\"https://github.com/YisRime\" style=\"color:#e0574a;text-decoration:none;\">GitHub</a> \u4E0A\u7ED9\u6211\u4E00\u4E2A Star\uFF01</p>\n <p>\uD83D\uDC1B \u9047\u5230\u95EE\u9898\uFF1F\u8BF7\u901A\u8FC7 <strong>Issues</strong> \u63D0\u4EA4\u53CD\u9988\uFF0C\u6216\u52A0\u5165 QQ \u7FA4 <a href=\"https://qm.qq.com/q/PdLMx9Jowq\" style=\"color:#e0574a;text-decoration:none;\"><strong>855571375</strong></a> \u8FDB\u884C\u4EA4\u6D41</p>\n</div>\n";
|
|
5
|
-
/**
|
|
6
|
-
* 基础元素类型
|
|
7
|
-
* @interface BaseElement
|
|
8
|
-
* @property {('text'|'img'|'video')} type - 元素类型
|
|
9
|
-
* @property {number} index - 排序索引
|
|
10
|
-
*/
|
|
11
|
-
export interface BaseElement {
|
|
12
|
-
type: 'text' | 'img' | 'video';
|
|
13
|
-
index: number;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* 文本元素类型
|
|
17
|
-
* @interface TextElement
|
|
18
|
-
* @extends {BaseElement}
|
|
19
|
-
* @property {'text'} type - 文本类型
|
|
20
|
-
* @property {string} content - 文本内容
|
|
21
|
-
*/
|
|
22
|
-
export interface TextElement extends BaseElement {
|
|
23
|
-
type: 'text';
|
|
24
|
-
content: string;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* 媒体元素类型
|
|
28
|
-
* @interface MediaElement
|
|
29
|
-
* @extends {BaseElement}
|
|
30
|
-
* @property {('img'|'video')} type - 媒体类型
|
|
31
|
-
* @property {string} [file] - 文件名
|
|
32
|
-
* @property {string} [fileName] - 原始文件名
|
|
33
|
-
* @property {string} [fileSize] - 文件大小
|
|
34
|
-
* @property {string} [filePath] - 文件路径
|
|
35
|
-
*/
|
|
36
|
-
export interface MediaElement extends BaseElement {
|
|
37
|
-
type: 'img' | 'video';
|
|
38
|
-
file?: string;
|
|
39
|
-
fileName?: string;
|
|
40
|
-
fileSize?: string;
|
|
41
|
-
filePath?: string;
|
|
42
|
-
}
|
|
43
|
-
export type Element = TextElement | MediaElement;
|
|
44
|
-
/**
|
|
45
|
-
* 回声洞对象
|
|
46
|
-
* @interface CaveObject
|
|
47
|
-
* @property {number} cave_id - 回声洞ID
|
|
48
|
-
* @property {Element[]} elements - 元素列表
|
|
49
|
-
* @property {string} contributor_number - 投稿者ID
|
|
50
|
-
* @property {string} contributor_name - 投稿者名称
|
|
51
|
-
*/
|
|
52
|
-
export interface CaveObject {
|
|
53
|
-
cave_id: number;
|
|
54
|
-
elements: Element[];
|
|
55
|
-
contributor_number: string;
|
|
56
|
-
contributor_name: string;
|
|
57
|
-
}
|
|
58
|
-
export interface PendingCave extends CaveObject {
|
|
59
|
-
}
|
|
60
|
-
export interface Config {
|
|
61
|
-
manager: string[];
|
|
62
|
-
number: number;
|
|
63
|
-
enableAudit: boolean;
|
|
64
|
-
allowVideo: boolean;
|
|
65
|
-
videoMaxSize: number;
|
|
66
|
-
imageMaxSize: number;
|
|
67
|
-
blacklist: string[];
|
|
68
|
-
whitelist: string[];
|
|
69
|
-
enablePagination: boolean;
|
|
70
|
-
itemsPerPage: number;
|
|
71
|
-
enableImageDuplicate: boolean;
|
|
72
|
-
imageDuplicateThreshold: number;
|
|
73
|
-
textDuplicateThreshold: number;
|
|
74
|
-
enableTextDuplicate: boolean;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* 插件配置项
|
|
78
|
-
* @type {Schema}
|
|
79
|
-
*/
|
|
80
|
-
export declare const Config: Schema<Config>;
|
|
81
|
-
/**
|
|
82
|
-
* 插件主入口
|
|
83
|
-
* @param {Context} ctx - Koishi上下文
|
|
84
|
-
* @param {Config} config - 插件配置
|
|
85
|
-
*/
|
|
86
|
-
export declare function apply(ctx: Context, config: Config): Promise<void>;
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { Context } from 'koishi';
|
|
2
|
-
import { Config, PendingCave } from '..';
|
|
3
|
-
import { IdManager } from './IdManager';
|
|
4
|
-
/**
|
|
5
|
-
* 管理洞审核相关操作的类
|
|
6
|
-
*/
|
|
7
|
-
export declare class AuditManager {
|
|
8
|
-
private ctx;
|
|
9
|
-
private config;
|
|
10
|
-
private idManager;
|
|
11
|
-
private logger;
|
|
12
|
-
/**
|
|
13
|
-
* 创建审核管理器实例
|
|
14
|
-
* @param ctx - Koishi 上下文
|
|
15
|
-
* @param config - 配置对象
|
|
16
|
-
* @param idManager - ID 管理器实例
|
|
17
|
-
*/
|
|
18
|
-
constructor(ctx: Context, config: Config, idManager: IdManager);
|
|
19
|
-
/**
|
|
20
|
-
* 处理审核操作
|
|
21
|
-
* @param pendingData - 待审核的洞数据数组
|
|
22
|
-
* @param isApprove - 是否通过审核
|
|
23
|
-
* @param caveFilePath - 洞数据文件路径
|
|
24
|
-
* @param resourceDir - 资源目录路径
|
|
25
|
-
* @param pendingFilePath - 待审核数据文件路径
|
|
26
|
-
* @param session - 会话对象
|
|
27
|
-
* @param targetId - 目标洞ID(可选)
|
|
28
|
-
* @returns 处理结果消息
|
|
29
|
-
*/
|
|
30
|
-
processAudit(pendingData: PendingCave[], isApprove: boolean, caveFilePath: string, resourceDir: string, pendingFilePath: string, session: any, targetId?: number): Promise<string>;
|
|
31
|
-
/**
|
|
32
|
-
* 处理单条审核
|
|
33
|
-
* @param pendingData - 待审核的洞数据数组
|
|
34
|
-
* @param isApprove - 是否通过审核
|
|
35
|
-
* @param caveFilePath - 洞数据文件路径
|
|
36
|
-
* @param resourceDir - 资源目录路径
|
|
37
|
-
* @param pendingFilePath - 待审核数据文件路径
|
|
38
|
-
* @param targetId - 目标洞ID
|
|
39
|
-
* @param session - 会话对象
|
|
40
|
-
* @returns 处理结果消息
|
|
41
|
-
* @private
|
|
42
|
-
*/
|
|
43
|
-
private handleSingleAudit;
|
|
44
|
-
/**
|
|
45
|
-
* 处理批量审核
|
|
46
|
-
* @param pendingData - 待审核的洞数据数组
|
|
47
|
-
* @param isApprove - 是否通过审核
|
|
48
|
-
* @param caveFilePath - 洞数据文件路径
|
|
49
|
-
* @param resourceDir - 资源目录路径
|
|
50
|
-
* @param pendingFilePath - 待审核数据文件路径
|
|
51
|
-
* @param session - 会话对象
|
|
52
|
-
* @returns 处理结果消息
|
|
53
|
-
* @private
|
|
54
|
-
*/
|
|
55
|
-
private handleBatchAudit;
|
|
56
|
-
/**
|
|
57
|
-
* 发送审核消息给管理员
|
|
58
|
-
* @param cave - 待审核的洞数据
|
|
59
|
-
* @param content - 消息内容
|
|
60
|
-
* @param session - 会话对象
|
|
61
|
-
*/
|
|
62
|
-
sendAuditMessage(cave: PendingCave, content: string, session: any): Promise<void>;
|
|
63
|
-
/**
|
|
64
|
-
* 删除媒体文件
|
|
65
|
-
* @param cave - 洞数据
|
|
66
|
-
* @param resourceDir - 资源目录路径
|
|
67
|
-
* @private
|
|
68
|
-
*/
|
|
69
|
-
private deleteMediaFiles;
|
|
70
|
-
/**
|
|
71
|
-
* 清理元素数据用于保存
|
|
72
|
-
* @param elements - 元素数组
|
|
73
|
-
* @param keepIndex - 是否保留索引
|
|
74
|
-
* @returns 清理后的元素数组
|
|
75
|
-
* @private
|
|
76
|
-
*/
|
|
77
|
-
private cleanElementsForSave;
|
|
78
|
-
/**
|
|
79
|
-
* 发送消息
|
|
80
|
-
* @param session - 会话对象
|
|
81
|
-
* @param key - 消息key
|
|
82
|
-
* @param params - 消息参数
|
|
83
|
-
* @param isTemp - 是否为临时消息
|
|
84
|
-
* @param timeout - 临时消息超时时间
|
|
85
|
-
* @returns 空字符串
|
|
86
|
-
* @private
|
|
87
|
-
*/
|
|
88
|
-
private sendMessage;
|
|
89
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { Buffer } from 'buffer';
|
|
2
|
-
/**
|
|
3
|
-
* 图片哈希计算工具类
|
|
4
|
-
* 使用 DCT(离散余弦变换)方法计算图片的感知哈希值,可用于图片相似度比较
|
|
5
|
-
*/
|
|
6
|
-
export declare class ContentHasher {
|
|
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 text - 输入文本
|
|
77
|
-
* @returns 文本的哈希值(36进制字符串)
|
|
78
|
-
*/
|
|
79
|
-
static calculateTextHash(text: string): string;
|
|
80
|
-
}
|
|
@@ -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
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 哈希存储状态类型
|
|
3
|
-
*/
|
|
4
|
-
interface HashStorageStatus {
|
|
5
|
-
lastUpdated: string;
|
|
6
|
-
entries: Array<{
|
|
7
|
-
caveId: number;
|
|
8
|
-
imageHashes: string[];
|
|
9
|
-
textHashes: string[];
|
|
10
|
-
}>;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* 图片哈希值存储管理类
|
|
14
|
-
* 负责管理和维护回声洞图片的哈希值
|
|
15
|
-
*/
|
|
16
|
-
export declare class HashManager {
|
|
17
|
-
private readonly caveDir;
|
|
18
|
-
private static readonly HASH_FILE;
|
|
19
|
-
private static readonly CAVE_FILE;
|
|
20
|
-
private static readonly BATCH_SIZE;
|
|
21
|
-
private imageHashes;
|
|
22
|
-
private textHashes;
|
|
23
|
-
private initialized;
|
|
24
|
-
/**
|
|
25
|
-
* 初始化HashManager实例
|
|
26
|
-
* @param caveDir 回声洞数据目录路径
|
|
27
|
-
*/
|
|
28
|
-
constructor(caveDir: string);
|
|
29
|
-
private get filePath();
|
|
30
|
-
private get resourceDir();
|
|
31
|
-
private get caveFilePath();
|
|
32
|
-
/**
|
|
33
|
-
* 初始化哈希存储
|
|
34
|
-
* 读取现有哈希数据或重新构建哈希值
|
|
35
|
-
* @throws 初始化失败时抛出错误
|
|
36
|
-
*/
|
|
37
|
-
initialize(): Promise<void>;
|
|
38
|
-
/**
|
|
39
|
-
* 获取当前哈希存储状态
|
|
40
|
-
* @returns 包含最后更新时间和所有条目的状态对象
|
|
41
|
-
*/
|
|
42
|
-
getStatus(): Promise<HashStorageStatus>;
|
|
43
|
-
/**
|
|
44
|
-
* 更新指定回声洞的图片哈希值
|
|
45
|
-
* @param caveId 回声洞ID
|
|
46
|
-
* @param content 图片buffer数组
|
|
47
|
-
*/
|
|
48
|
-
updateCaveContent(caveId: number, content: {
|
|
49
|
-
images?: Buffer[];
|
|
50
|
-
texts?: string[];
|
|
51
|
-
}): Promise<void>;
|
|
52
|
-
/**
|
|
53
|
-
* 更新所有回声洞的哈希值
|
|
54
|
-
* @param isInitialBuild 是否为初始构建
|
|
55
|
-
*/
|
|
56
|
-
updateAllCaves(isInitialBuild?: boolean): Promise<void>;
|
|
57
|
-
/**
|
|
58
|
-
* 查找重复的图片
|
|
59
|
-
* @param content 待查找的图片buffer数组
|
|
60
|
-
* @param thresholds 相似度阈值
|
|
61
|
-
* @returns 匹配结果数组,包含索引、回声洞ID和相似度
|
|
62
|
-
*/
|
|
63
|
-
findDuplicates(content: {
|
|
64
|
-
images?: Buffer[];
|
|
65
|
-
texts?: string[];
|
|
66
|
-
}, thresholds: {
|
|
67
|
-
image: number;
|
|
68
|
-
text: number;
|
|
69
|
-
}): Promise<Array<{
|
|
70
|
-
type: 'image' | 'text';
|
|
71
|
-
index: number;
|
|
72
|
-
caveId: number;
|
|
73
|
-
similarity: number;
|
|
74
|
-
} | null>>;
|
|
75
|
-
private findTextDuplicates;
|
|
76
|
-
private calculateTextSimilarity;
|
|
77
|
-
private findImageDuplicates;
|
|
78
|
-
/**
|
|
79
|
-
* 加载回声洞数据
|
|
80
|
-
* @returns 回声洞数据数组
|
|
81
|
-
* @private
|
|
82
|
-
*/
|
|
83
|
-
private loadCaveData;
|
|
84
|
-
/**
|
|
85
|
-
* 保存哈希数据到文件
|
|
86
|
-
* @private
|
|
87
|
-
*/
|
|
88
|
-
private saveContentHashes;
|
|
89
|
-
/**
|
|
90
|
-
* 构建初始哈希数据
|
|
91
|
-
* @private
|
|
92
|
-
*/
|
|
93
|
-
private buildInitialHashes;
|
|
94
|
-
/**
|
|
95
|
-
* 更新缺失的哈希值
|
|
96
|
-
* @private
|
|
97
|
-
*/
|
|
98
|
-
private updateMissingHashes;
|
|
99
|
-
/**
|
|
100
|
-
* 批量处理数组项
|
|
101
|
-
* @param items 待处理项数组
|
|
102
|
-
* @param processor 处理函数
|
|
103
|
-
* @param batchSize 批处理大小
|
|
104
|
-
* @private
|
|
105
|
-
*/
|
|
106
|
-
private processBatch;
|
|
107
|
-
}
|
|
108
|
-
export {};
|
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
|
-
}
|