# koishi-plugin-best-cave

[![npm](https://img.shields.io/npm/v/koishi-plugin-best-cave?style=flat-square)](https://www.npmjs.com/package/koishi-plugin-best-cave)

功能强大、高度可定制的回声洞插件。支持丰富的媒体类型、内容查重、AI分析、人工审核、用户昵称、数据迁移以及本地/S3 双重文件存储后端。

## 🧩 前置依赖

- **数据库 (`koishi-plugin-database`)**: 本插件强依赖数据库来存储数据，请确保您已至少配置了一个数据库插件（如 `koishi-plugin-database-sqlite` 或 `koishi-plugin-database-mysql`）。
- **图片处理 (`sharp`)**: 如果您启用了 `enableSimilarity` (内容查重) 功能，插件需要使用 `sharp` 库来处理图片。通常情况下它会自动安装，如遇安装问题，请参考 `sharp` 的官方文档解决。
- **AI 服务**: 如果您启用了 `enableAI` (AI 功能)，则需要一个兼容 OpenAI API 的服务提供商，并获取相应的 **Endpoint** 和 **API Key**。

## ✨ 功能亮点

- **丰富的内容形式**：不止于文本，轻松发布包含图片、视频、音频、文件、合并转发的混合内容。插件能自动解析回复或引用的消息，并将其完整存入回声洞。
- **灵活的存储后端**：媒体文件可存储在 **本地服务器** (`data/cave` 目录)，或配置使用任何 **S3 兼容** 的云端对象存储（如 AWS S3, MinIO, 阿里云 OSS, 腾讯云 COS 等）。支持通过公共URL、本地文件路径或Base64三种方式发送媒体。
- **AI 智能分析**：(可选) 启用后，插件能调用大语言模型对投稿内容进行智能分析，自动进行**趣味性评分**、对内容进行**分类**并提取**关键词**，为未来的内容检索、排行和管理提供支持。
- **高级内容查重**：(可选) 插件提供两种查重模式：
  - **哈希查重**：在添加时自动计算文本 (Simhash) 和图片 (pHash) 的哈希值。对于相似度过高的投稿将直接拒绝，有效防止重复。
  - **AI 语义查重**：在添加时利用 AI 模型判断新内容与现有内容在**语义或“梗”的本质上**是否重复，能识别各类变体和转述。
- **完善的审核机制**：(可选) 启用后，所有新投稿都将进入待审核状态，并通知管理群组。只有管理员审核通过后，内容才会对用户可见，确保内容质量。
- **精细的作用域**：通过 `perChannel` 配置，可设定回声洞是在所有群聊中共享（全局模式），还是在每个群聊中独立（分群模式）。
- **专属用户昵称**：(可选) 用户可以为自己在回声洞中的发言设置一个专属昵称，增加趣味性。
- **便捷的数据管理**：(可选) 管理员可通过指令轻松地将所有回声洞数据导出为 `JSON` 文件备份，或从文件中恢复数据，迁移无忧。
- **强大的维护工具**：管理员可以通过一系列指令为历史数据批量生成哈希值 (`cave.hash`)、补全 AI 分析 (`cave.ai`)、获取相似度报告 (`cave.check`) 或 AI 重复性报告 (`cave.compare`)。
- **高效的ID管理**：优先复用已删除的ID，并在无可用ID时采用高效的“最大ID+1”策略，确保回声洞序号紧凑，并能高效处理大量数据。

## 📖 指令说明

### 用户指令

| 指令 | 别名/选项 | 说明 |
| :--- | :--- | :--- |
| `cave` | | 随机查看一条回声洞。 |
| `cave.add [内容]` | `cave -a [内容]` | 添加新的回声洞。可以直接跟文字，也可以**回复一条消息后发送 `cave.add`**，或等待机器人提示后发送。 |
| `cave.view <序号>` | `cave -g <序号>` | 查看指定序号的回声洞。 |
| `cave.del <序号>` | `cave -r <序号>` | 删除指定序号的回声洞。仅投稿人或在管理群组内的管理员可操作。 |
| `cave.list` | `cave -l` | 查询并列出自己投稿过的所有回声洞序号及总数。 |
| | `-u <用户>` | 查询指定用户（需@或使用ID）投稿的所有回声洞。 |
| | `-a` | **(仅限管理群组)** 查看所有用户的投稿数量排行榜。 |

### 模块化管理指令

这些指令只有在配置中启用了相应功能后才可用，且大部分仅限在**管理群组**中使用。

| 指令 | 所需配置 | 说明 |
| :--- | :--- | :--- |
| `cave.name [昵称]` | `enableName: true` | **(用户指令)** 设置你在回声洞中显示的昵称。若不提供昵称，则清除现有设置。 |
| `cave.pend` | `enablePend: true` | **(管理)** 列出所有待审核的回声洞ID。 |
| `cave.pend <序号>` | `enablePend: true` | **(管理)** 查看指定待审核内容的详情。 |
| `cave.pend.Y [...序号]` | `enablePend: true` | **(管理)** 通过审核。若不提供序号，则通过所有待审核内容。 |
| `cave.pend.N [...序号]` | `enablePend: true` | **(管理)** 拒绝审核。若不提供序号，则拒绝所有待审核内容。 |
| `cave.pend.A <阈值>` | `enablePend: true`, `enableAI: true` | **(管理)** 根据 AI 评分自动通过审核，通过所有评分不低于指定阈值的内容。 |
| `cave.export` | `enableIO: true` | **(管理)** 将所有`active`状态的回声洞导出到 `data/cave/cave.json`。 |
| `cave.import` | `enableIO: true` | **(管理)** 从 `data/cave/cave.json` 文件中导入数据。 |
| `cave.hash` | `enableSimilarity: true` | **(管理)** 校验所有历史数据，为缺失哈希的回声洞补全记录。 |
| `cave.check` | `enableSimilarity: true` | **(管理)** 检查所有回声洞的哈希，生成一份关于文本和图片相似度的报告。 |
| `cave.fix [...序号]` | `enableSimilarity: true`| **(管理)** 扫描并修复回声洞中的图片（移除多余数据）。可指定ID或扫描全部。 |
| `cave.ai` | `enableAI: true` | **(管理)** 分析所有历史数据，为缺失AI元数据的回声洞补全记录。 |
| `cave.compare` | `enableAI: true` | **(管理)** 检查所有回声洞的AI关键词，生成一份关于内容重复性的报告。 |
| `cave.rank` | `enableAI: true` | **(管理)** 查询 AI 评分排行，支持 `-n` (数量), `-g` (下限), `-l` (上限), `-p` (查询待审核) 选项。 |

## ⚙️ 配置说明

### 基础配置

| 配置项 | 类型 | 默认值 | 说明 |
| :--- | :--- | :--- | :--- |
| `perChannel` | `boolean` | `false` | 是否启用分群模式。`true` 表示各群的回声洞独立。 |
| `enableName` | `boolean` | `false` | 是否启用自定义昵称功能 (`cave.name` 指令)。 |
| `enableIO` | `boolean` | `false` | 是否启用数据导入/导出功能 (`cave.export` / `.import` 指令)。 |
| `adminChannel` | `string` | `'onebot:'` | **管理群组ID**。格式为 `平台名:群号`，如 `onebot:12345678`。管理指令仅在此群组生效。若配置无效，审核将自动通过。 |
| `caveFormat` | `string` | `'回声洞 ——（{id}）\|—— {name}'` | 回声洞消息的显示格式。`\|`为页眉页脚分隔符。支持强大的占位符语法：• **基本**: `{id}`, `{name}`, `{time}`, `{user}`, `{channel}`• **自动打码**: `{*user}` (在占位符前加 `*`)• **审核可见**: `{name/}` (在 `/` 后留空，表示常规模式下不显示)• **审核替换**: `{user/name}` (常规模式显示 `user`，审核模式显示 `name`)• **组合**: `{*user/user}` (常规模式下打码显示 `user`，审核时完整显示 `user`) |

### 复核配置 (审核与查重)

| 配置项 | 类型 | 默认值 | 说明 |
| :--- | :--- | :--- | :--- |
| `enablePend` | `boolean` | `false` | 是否启用审核机制。启用后，新投稿将进入`pending`状态。 |
| `enableSimilarity` | `boolean` | `false` | 是否启用基于哈希的内容相似度检查（查重）。 |
| `textThreshold` | `number` | `95` | **文本**相似度阈值 (0-100)。基于Simhash汉明距离计算，超过此值将被拒绝。 |
| `imageThreshold` | `number` | `95` | **图片**相似度阈值 (0-100)。基于pHash汉明距离计算，超过此值将被拒绝。 |

### 模型配置 (AI)

| 配置项 | 类型 | 默认值 | 说明 |
| :--- | :--- | :--- | :--- |
| `enableAI` | `boolean` | `false` | 是否启用 AI 分析与查重功能。 |
| `endpoints` | `array` | | **(AI 必填)** AI 服务端点列表。插件会轮流使用列表中的端点，实现负载均衡或故障转移。 |
| `enableApprove` | `boolean` | `false` | 是否启用 AI 自动审核。启用后，AI评分高于阈值的内容将自动通过。 |
| `approveThreshold` | `number` | `60` | AI 自动审核的评分阈值 (0-100)。 |
| `onAIReviewFail` | `boolean` | `true` | 当 AI 自动审核判定为拒绝时，是否转为人工审核。若为 `false`，则直接拒绝。 |
| `systemPrompt` | `string` | `(见代码)` | 用于指导 AI 分析的系统提示词，包含详细的评分、分类和关键词提取标准。 |

`endpoints` 列表中每一项的配置如下：

| 键 | 类型 | 是否必须 | 说明 |
| :--- | :--- | :--- | :--- |
| `url` | `string` | 是 | 兼容 OpenAI 的 API 端点 (Endpoint)，例如 `https://api.openai.com/v1`。 |
| `key` | `string` | 是 | API 密钥 (API Key)。 |
| `model` | `string` | 是 | 使用的语言模型名称 (Model)，需为支持图片理解的多模态模型。 |

### 存储配置

| 配置项 | 类型 | 默认值 | 说明 |
| :--- | :--- | :--- | :--- |
| `localPath` | `string` | | 为本地文件提供一个可访问的绝对路径。配置后，将以 `file:///` 协议发送本地媒体。 |
| `enableS3` | `boolean` | `false` | 是否启用 S3 兼容对象存储。若为 `false`，所有媒体文件将保存在本地 `data/cave` 目录下。 |
| `publicUrl` | `string` | | **(S3 可选)** S3 存储桶的公共访问 URL。如果提供，插件将直接用此 URL 发送媒体链接，性能最佳。 |
| `endpoint` | `string` | | **(S3 必填)** S3 兼容存储的 Endpoint URL。 |
| `bucket` | `string` | | **(S3 必填)** S3 存储桶 (Bucket) 名称。 |
| `region` | `string` | `'auto'` | **(S3 可选)** S3 区域 (Region)。 |
| `accessKeyId` | `string` | | **(S3 必填)** S3 访问密钥 ID。 |
| `secretAccessKey` | `string` | | **(S3 必填)** S3 秘密访问密钥。 |

## ⚠️ 注意事项

1. **媒体发送方式**：插件会按以下优先级决定如何发送图片、视频等媒体文件：
    1. **S3 公共URL**：如果 `enableS3` 和 `publicUrl` 已配置。**(推荐)**
    2. **本地文件路径**：如果 `localPath` 已配置。
    3. **Base64 编码**：如果以上两项均未配置，将文件转为 Base64 发送（可能受平台大小限制或支持问题）。
2. **文件存储权限**：若使用本地存储，请确保 Koishi 拥有对 `data/cave` 目录的读写权限。若使用 S3，请确保 Access Key 权限和存储桶策略（如ACL设为`public-read`）配置正确。
3. **异步处理**：投稿、删除等操作涉及文件下载、哈希计算、AI 分析和文件清理，这些耗时操作均在后台异步执行，以避免阻塞当前指令。您可能会先收到“添加成功”的消息，稍后才会收到查重失败或处理失败的提示。
4. **数据迁移**：导入/导出功能均使用插件数据目录下的 `cave.json` 文件。导入时，若遇到与数据库中现有 ID 冲突的条目，该条目会被分配一个新的、当前最大的 ID 加一的序号，不会覆盖或修改老数据。
5. **查重机制**：投稿时的查重是实时进行的，若相似度超过阈值会直接拒绝。而 `.check` 和 `.compare` 指令则用于对整个数据库进行批量扫描，生成全面的相似度/重复性报告，帮助管理员发现更复杂或历史遗留的重复内容。
