fraq-plugin-drift-bottle
v0.4.0
Published
Fraq 漂流瓶插件
Readme
fraq-plugin-drift-bottle
加载方式与公开 API
Fraq CLI 会生成独立的 ESM 应用,通过
ctx.install((await import('fraq-plugin-drift-bottle')).default, options) 安装本插件。因此默认导出只负责装配,
可复用的漂流瓶操作由命名导出的 DriftBottleApi 提供。
其他 Fraq 插件可以声明并注入该服务:
import { definePlugin } from '@fraqjs/fraq';
import { DriftBottleApi } from 'fraq-plugin-drift-bottle';
export default definePlugin({
name: 'drift-bottle-consumer',
requires: [DriftBottleApi],
inject: { driftBottle: DriftBottleApi },
async apply(ctx) {
const count = await ctx.driftBottle.count();
ctx.logger.info(`当前有 ${count} 个可捡取的漂流瓶`);
},
});DriftBottleApi 提供投递、捡取、评论、署名、删除、权限、重复捡取偏好和审核记录等操作;命令层只负责参数解析和回复构建。源码按职责分为:
src/api/:供命令和其他插件复用的业务 API。src/persistence/:基于 Kysely 的 SQLite 持久化。src/models/:公开数据模型。src/processing/:消息转换、署名解析和 AI 审核处理。src/commands/:Fraq 命令构建与用户交互。
Fraq 漂流瓶插件,支持投递、随机捡取、匿名、原名或别名署名,并可选择 AI 或人工审核投瓶内容。
需要 Node.js 22.13.0 或更高版本。
兼容 Fraq 0.14 与 Fraq CLI 0.7。
使用 Fraq CLI
在 fraq.yml 中先配置 fraqjs/hono、fraqjs/ai 和 fraqjs/kysely,再添加 drift-bottle:
configVersion: 1
fraqVersion: 0.14.0
milky:
url: http://localhost:30001/
plugins:
fraqjs/hono:
host: 127.0.0.1
port: 4649
fraqjs/ai:
providers:
deepseek:
sdk: "@ai-sdk/deepseek"
options:
apiKey: ${{ env:DEEPSEEK_API_KEY }}
models: [deepseek-chat]
defaultModel: deepseek/deepseek-chat
fraqjs/kysely:
sqliteUrl: file:./data/drift-bottles.db
drift-bottle:
moderationMode: ai
moderationModel: deepseek/deepseek-chat
ownerIds: [123456789]
additionalDependencies:
"@ai-sdk/deepseek": ^3
ai: ^7
zod: ^4然后同步插件版本并启动:
fraq lock
fraq startFraq CLI 会把 drift-bottle 解析为 npm 包 fraq-plugin-drift-bottle,并检查其依赖的 fraqjs/hono、fraqjs/ai 和 fraqjs/kysely 插件是否已经配置。
WebUI 由 Fraq 宿主统一网关(@fraqjs/plugin-webui-gateway)挂载并提供登录入口,默认地址为 http://127.0.0.1:4649/webui/drift-bottle/。登录使用宿主级统一访问令牌(fraqjs/webui-gateway.accessToken),不再使用 QQ 账号、密码哈希或主人审批注册;登录后的宿主管理员可以管理全部瓶子、人工审核和插件配置。
登录后可以在“设置”页面修改投瓶审核方式、AI 审核模型和主人 QQ 号列表,保存后立即生效。数据库位置由 fraqjs/kysely.sqliteUrl 统一管理。
代码安装
pnpm add fraq-plugin-drift-bottle @fraqjs/plugin-hono @fraqjs/plugin-ai @fraqjs/plugin-kysely ai kysely zod使用前需按照 Fraq AI 插件文档 安装并配置 @fraqjs/plugin-ai。
import HonoPlugin from '@fraqjs/plugin-hono';
import KyselyPlugin from '@fraqjs/plugin-kysely';
import WebuiGatewayPlugin from '@fraqjs/plugin-webui-gateway';
import DriftBottlePlugin from 'fraq-plugin-drift-bottle';
ctx.install(HonoPlugin, { host: '127.0.0.1', port: 4649 });
ctx.install(KyselyPlugin, { sqliteUrl: 'file:./data/drift-bottles.db' });
ctx.install(WebuiGatewayPlugin, { accessToken: '请替换为宿主统一访问令牌' });
ctx.install(DriftBottlePlugin, {
moderationMode: 'ai',
moderationModel: 'fast',
ownerIds: [123456789],
});配置
所有配置项均为可选。
| 字段 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| moderationMode | 'ai' \| 'manual' | 'ai' | 投瓶审核方式;人工模式会先进入待审核列表,通过后才公开。 |
| moderationModel | string | AI 插件默认模型 | AI 模型别名或 提供商/模型;需支持所投递的图片或视频。 |
| ownerIds | number[] | [] | 插件主人 QQ 号,用于机器人侧的删除、审核和管理权限。 |
WebUI 挂载路径固定为
/webui/drift-bottle,旧版webuiPath配置已不再生效;宿主必须安装@fraqjs/plugin-webui-gateway并配置非空accessToken。
从旧版数据库升级
0.3.17 及更早版本通过本插件的 storagePath 直接打开 SQLite。升级后,请删除 drift-bottle.storagePath,并把同一文件配置为 Kysely 数据库:
plugins:
fraqjs/kysely:
sqliteUrl: file:./data/drift-bottles.db
drift-bottle:
moderationMode: ai首次启动时,Kysely 会在原文件中登记并执行漂流瓶 schema 迁移;现有表名和数据保持不变。插件不会自动复制或删除旧数据库文件。相对路径仍以 Fraq 进程的工作目录为基准,因此升级前应确认 sqliteUrl 指向原 storagePath 文件。
审核记录
审核记录保存在 SQLite 的 bottle_moderation_records 表中。
| 字段 | 说明 |
| --- | --- |
| id | 审核记录 ID。 |
| created_at | 记录时间,Unix 毫秒时间戳。 |
| content | 投稿消息段的 JSON 快照。 |
| process | AI 返回的审核结果、错误信息,或等待人工审核状态。 |
| input_tokens | 输入 Token,无法获得时为 NULL。 |
| output_tokens | 输出 Token,无法获得时为 NULL。 |
| total_tokens | 总 Token,无法获得时为 NULL。 |
| success | AI 调用成功或成功进入人工队列为 1,AI 调用失败为 0。 |
| approved | 内容通过为 1,被 AI 拒绝或等待人工审核为 0,调用失败为 NULL。 |
命令
| 命令 | 说明 |
| --- | --- |
| 扔瓶子 <内容> | 投递漂流瓶,支持文字、图片、视频、表情、动态表情和合并转发;非文字内容可通过回复投递。 |
| 捡瓶子 | 随机捡取一个漂流瓶。 |
| 评论漂流瓶 <ID> <内容> | 评论指定漂流瓶;评论仅支持文字,最多 500 个字符,并经过 AI 审核。 |
| 评论漂流瓶 <ID> | 查看指定漂流瓶的评论,最多显示最新 20 条;也可使用 漂流瓶评论。 |
| 回复后发送 评论漂流瓶 <内容> | 从被回复的投递确认或捡取消息读取瓶子 ID 并评论;省略内容可查看评论。 |
| 漂流瓶重复捡 开启 | 个人捡取后保留瓶子,允许再次被捡取。 |
| 漂流瓶重复捡 关闭 | 个人捡取后删除瓶子。 |
| 漂流瓶重复捡 默认 | 清除个人设置,恢复默认的捡取后删除行为。 |
| 漂流瓶署名 匿名 | 后续投递保持匿名。 |
| 漂流瓶署名 原名 | 后续投递使用当前群昵称或 QQ 昵称。 |
| 漂流瓶署名 <别名> | 后续投递使用别名,最多 20 个字符。 |
| 删除漂流瓶 <ID> | 普通用户只能删除自己投递的瓶子;插件主人、群管和授权列表成员可删除任意瓶子。 |
| 漂流瓶审核 通过 <审核记录ID> | 通过待审核投瓶并公开;仅插件主人和漂流瓶管理员可执行。 |
| 漂流瓶审核 拒绝 <审核记录ID> <理由> | 拒绝待审核投瓶并归档,拒绝理由必填;仅插件主人和漂流瓶管理员可执行。 |
| 漂流瓶权限 添加 <QQ号或@用户...> | 将一个或多个用户加入管理权限列表,使其可以删除和审核漂流瓶;支持 QQ 号、提及或混合输入,仅插件主人可执行。 |
| 漂流瓶权限 删除 <QQ号或@用户...> | 将一个或多个用户移出管理权限列表,支持 QQ 号、提及或混合输入;仅插件主人可执行。 |
| 漂流瓶权限 列表 | 查看数据库中的漂流瓶管理权限列表,仅插件主人可执行。 |
| 漂流瓶帮助 | 以合并转发查看帮助,每条消息使用“指令”和“说明”展示一个命令。 |
行为
- 默认匿名;署名模式按 QQ 用户保存。原名会在投递时读取当前群昵称或 QQ 昵称,旧瓶子不受后续改名影响。
- AI 模式下,投瓶内容和署名通过 AI 审核后才会公开;人工模式下,新投瓶会保存完整草稿并进入待审核列表,通过后才会公开。
- 人工模式只改变投瓶流程;评论、别名和原名署名仍使用 AI 审核。
- 每次 AI 审核完成后,插件日志会记录输入、输出和总 Token 数量。
- 每次 AI 审核都会写入 SQLite 的
bottle_moderation_records表,包括时间、投稿内容 JSON、审核结果或错误、Token 用量、调用是否成功及内容是否通过。 - R18 审核包含性暗示倾向、敏感部位聚焦或触摸等内容,卡通、动物和表情包采用相同标准。
- AI 审核失败或服务不可用时不会绕过审核,相关投瓶记录会进入待审核列表供人工处理。
- 数据存储在 SQLite 中,旧版数据库会自动迁移。
- 漂流瓶管理权限列表存储在同一个 SQLite 数据库中;群主和群管理员无需加入列表即可删除瓶子,但人工审核仍需主人或列表授权。
- 重复捡取设置按 QQ 用户存储在 SQLite 中,只影响该用户执行
捡瓶子时的行为。 - 捡取后删除只移除瓶子内容,评论索引会保留;使用管理删除命令会同时删除评论。
- 包含图片、视频、表情、动态表情或合并转发的瓶子会先单独发送来源和 ID,再发送瓶子内容。
