基于 Bun、TypeScript、NapLink 与 NapCat 的插件化 QQ 机器人。
miz 面向群聊协作和内容订阅场景,内置提醒、日程、活动报名、群待办、群问答、B 站主播订阅、财经新闻、每日壁纸、视频搬运、二维码、FF14 市场查询等功能。需要持久化的数据通过 Prisma 保存到 PostgreSQL,定时任务在重复触发时会自动避免并发执行。
| 分类 | 功能 |
|---|---|
| 群聊协作 | 单次或循环提醒、群日程、活动报名、群待办、群问答、全群广播 |
| 内容订阅 | B 站主播开播、下播与动态推送,财经新闻推送,每日 Bing 壁纸 |
| 实用工具 | 视频下载与 QQ 兼容转码、二维码生成与识别、FF14 国服市场查询与低价提醒 |
| 娱乐功能 | 占卜、米哈游笑话图、文字和图片复读 |
| 运行能力 | 插件自动发现、TOML 分层配置、配置热重载、请求限流与缓存、优雅停机 |
- Bun:运行时、包管理与测试。
- TypeScript:机器人、插件和脚本的实现语言。
- NapLink:连接 NapCat OneBot WebSocket 网关。
- PostgreSQL + Prisma:保存订阅状态、提醒、日程、活动、FAQ、待办和消息投递记录。
- yt-dlp + 稳定版 FFmpeg:视频下载、合并和 H.264/AAC 转码。
- Bun
- 已启用 OneBot WebSocket 的 NapCat
- PostgreSQL
- 视频功能需要
yt-dlp和ffmpeg - FFmpeg 请使用稳定发行版;不要使用 Git master/nightly 开发版,后者生成的 MP4 可能被 QQ 富媒体上传拒绝
建议先确认 NapCat WebSocket、访问令牌和 PostgreSQL 均可从 miz 的运行环境访问。
git clone https://github.com/PullAndRun/miz-ai-base.git miz
cd miz
bun install最小可运行配置只需要网关和 PostgreSQL。创建 config/app.toml:
[miz.gateway]
url = "ws://127.0.0.1:3000"
accessToken = "replace-with-your-token"
[miz.postgresql]
url = "http://127.0.0.1:5432"
database = "miz"
username = "postgres"
password = "replace-with-your-password"完整字段可参考 config/example/app.toml。示例中的空字符串和 0 是待填写占位值;复制完整示例后,请填写需要的字段,并删除不使用的可选占位项,否则配置校验可能失败。
FF14 低价提醒和 VTB 群订阅分别参考:
config/example/ff14.toml→config/ff14.tomlconfig/example/vtb.toml→config/vtb.toml
这些本地配置均已加入 .gitignore,不要提交访问令牌、数据库密码、Cookie 等敏感信息。
如果启用视频功能,需要先将 yt-dlp 放到以下默认位置,或在 [miz.video] 中改为实际路径:
| 系统 | yt-dlp | FFmpeg |
|---|---|---|
| Windows | tools/yt-dlp.exe |
tools/ffmpeg.exe |
| Linux / Docker | tools/yt-dlp |
tools/ffmpeg |
FFmpeg 和 yt-dlp 需要先自行安装。执行 bun run start 或 bun run dev 时,应用启动前仍会检查并更新 npm 依赖,同时查询 FFmpeg 和 yt-dlp 的最新版本,但不会下载或更新这两个工具。没有更新时只显示本地版本;发现更新时显示 本地版本 -> 最新版本:
FFmpeg: 8.1.2 -> 8.2
yt-dlp: 2026.07.04 -> 2026.08.01
需要主动检测并更新 npm 依赖、FFmpeg 和 yt-dlp 时,仍使用完整更新命令。它会按当前 CPU 架构查询和准备 Windows 与 Linux 两套工具文件;下载支持 [miz.network].proxyUrl,FFmpeg 会校验 SHA-256:
bun run dependencies:update -- normalLinux 下需要为两个文件添加执行权限:
chmod +x tools/yt-dlp tools/ffmpegbun run start启动脚本会依次生成 Prisma Client、执行已有数据库迁移,然后连接 NapCat 并加载插件与定时任务。
开发时可以使用监听模式:
bun run dev普通模式按以下顺序合并配置,后面的文件覆盖前面的同名字段:
config/app.toml
→ config/ff14.toml
→ config/vtb.toml
→ config/app.local.toml
Docker 模式最后再合并:
→ config/app.docker.toml
对象字段会递归合并,数组会整体替换。ff14.toml、vtb.toml 和 app.local.toml 都是可选文件;app.toml 始终必需。
通用外部 API URL 放在 app.toml。ff14.toml 只保存低价提醒目标,vtb.toml 只保存群订阅;本机网关、数据库和代理等环境相关地址继续放在 app.local.toml,Docker 地址放在 app.docker.toml。
运行期间修改 config 目录中的 TOML 文件,会重新加载插件和定时任务配置。如果修改了网关地址、NapLink 连接参数等连接级配置,建议重启进程以确保完全生效。
| 配置段 | 作用 |
|---|---|
[miz.gateway] |
NapCat OneBot WebSocket 地址和访问令牌。 |
[miz.postgresql] |
PostgreSQL 主机地址、数据库名、用户名和密码。 |
[miz.naplink] |
日志级别、连接超时、心跳、API 超时和 API 重试次数;网关断线后会持续自动重连,直至恢复连接。 |
[miz.plugins] |
命令前缀和插件目录,默认分别为 miz、plugins。 |
[miz.network] |
供视频和 VTB 请求使用的代理地址 proxyUrl。 |
[miz.reminder] |
提醒轮询、批量处理数量和管理白名单。 |
[miz.schedule] |
群日程轮询、提前提醒分钟数和管理白名单。 |
[miz.activity] |
活动提醒、人数上限、批量处理数量和管理白名单。 |
[miz.faq] |
每群词条上限、答案长度上限和管理白名单。 |
[miz.todo] |
群待办提醒、批量处理数量和管理白名单。 |
[miz.broadcast] |
可以向机器人所在全部群发送广播的用户白名单。 |
[miz.recall] |
可以撤回迷子群消息的用户白名单;群主和管理员无需加入白名单。 |
[miz.video] |
视频开关、白名单、B 站域名、下载目录、NapCat 媒体目录、工具路径,以及视频任务并发上限 maxConcurrentJobs(默认 2,最大 8)。 |
[miz.news] |
财经新闻接口、目标群和定时表达式。 |
[miz.wallpaper] |
Bing 官方元数据接口、图片基址、开关和定时表达式。 |
[miz.ff14] |
Universalis 市场接口及其前端使用的物品搜索接口、返回条数、低价提醒开关、定时表达式和管理白名单;每条 priceAlerts 可单独配置提醒成员列表 priceAlertAtUserIds。 |
[miz.vtb] |
B 站数据接口、网页与直播基址、轮询策略、缓存及管理白名单。 |
未填写对应接口地址时,依赖该接口的命令会提示尚未配置,相关定时任务会自动停用并记录原因。示例配置已填写 Bing 官方地址。
每个群使用一个 [[miz.vtb.subscriptions]] 配置块:
[[miz.vtb.subscriptions]]
groupId = "123456789"
streamers = ["主播甲", "主播乙"]
dynamicStreamers = ["主播甲"]
atAllStreamers = ["主播甲"]
dynamicAtAllStreamers = ["主播甲"]streamers中的主播会推送开播和下播。- 只有同时出现在
streamers和dynamicStreamers中的主播才会轮询并推送最新动态。 - 动态轮询直连 Bilibili 接口,复用
miz vtb login保存的凭据;未登录时会跳过动态轮询。 atAllStreamers控制开播通知是否@全体成员;dynamicAtAllStreamers控制动态通知是否@全体成员,两者都必须对应已订阅的主播。- 只有机器人是群主或管理员,且该 QQ 账号在群内仍有可用的
@全体成员次数时,开播或动态通知才会真正@全体;否则发送普通通知。 - 群管理员或 VTB 管理员白名单成员可以通过命令直接维护
config/vtb.toml中的订阅。
项目自带 docker-compose.yml,使用 oven/bun:latest,将项目根目录挂载到容器的 /app,并在容器启动时安装生产依赖、执行数据库迁移和启动机器人。
Compose 使用名为 diana 的外部网络。首次部署时,如果该网络不存在,需要先创建:
docker network create diana
docker compose up -d如使用其他网络名称,请同步修改 Compose。NapCat、PostgreSQL、代理等依赖服务也需要加入同一网络,或者在 config/app.docker.toml 中填写容器能够访问的地址。
首次执行 bun run start:docker 时,会根据 config/example/app.docker.toml 自动创建最小的 config/app.docker.toml:
- NapCat:
ws://napcat-miz:3000 - PostgreSQL:
http://postgresql:5432 - 代理:
http://clash:7890
这些名称只是默认容器名,请按实际环境修改。文件创建后不会被后续启动覆盖。
Docker 模式发送视频时,miz 先通过扫码登录保存的 B 站凭据和 [miz.network].proxyUrl 调用 yt-dlp 下载最佳视频和音频,再统一通过稳定版 FFmpeg 转码为 H.264/AAC MP4,结果写入项目的 temp 目录。
视频发送依次尝试三种方式:先把 napcatMediaDirectory 下的 file:/// 路径作为普通 video 消息交给 NapCat;失败后改用 base64://... 的 video 消息;仍失败时,再把文件 video 消息段作为单节点合并转发发送。三种发送均禁用自动重试,并在任一方式失败(包括超时)后继续下一种。使用文件和转发方式时,NapCat 必须能读取 napcatMediaDirectory,Docker 部署需要把同一个宿主机 temp 目录挂载到该路径。
services:
napcat:
volumes:
- ./temp:/app/media对应配置:
[miz.video]
napcatMediaDirectory = "/app/media"默认命令前缀为 miz,可以通过 [miz.plugins].commandPrefix 修改。发送 miz help 或 miz 帮助 可以查看机器人实际加载的命令。
| 命令 | 说明与权限 |
|---|---|
miz help |
显示已加载插件和命令说明。 |
miz 占卜 [主题] |
抽取今日签,可附带想问的事情;英文命令为 fortune。 |
miz news |
查询当前会话尚未投递的财经快讯。 |
miz wallpaper |
获取并发送当日 Bing 壁纸。 |
miz qrcode <文本> |
将最多 1000 个字符生成二维码。 |
miz qrcode decode |
与二维码图片放在同一条消息中,识别最大 10 MB 的图片。 |
miz video <URL> |
下载并发送视频;普通成员仅可使用 B 站链接,白名单成员可使用其他 yt-dlp 支持的站点。 |
miz remind 30m 内容 |
创建单次提醒;支持 m、h、d,最长 365 天。 |
miz remind every 1d 内容 |
创建循环提醒。使用 @QQ号 或 @全体成员 指定提醒对象,需要群管理或提醒白名单权限。 |
miz remind list/cancel/edit ... |
查看、取消或编辑提醒;普通成员只能管理自己创建的提醒。 |
miz schedule add YYYY-MM-DD HH:mm 内容 |
创建群日程;需要群主、群管理员或日程白名单权限。 |
miz schedule list |
查看本群即将开始的日程。 |
miz schedule cancel <编号> |
取消群日程;需要日程管理权限。 |
miz activity create YYYY-MM-DD HH:mm 内容 |
发起活动报名;需要群管理或活动白名单权限。 |
miz activity list/join/leave ... |
查看、参加或退出活动;参加和退出不需要管理权限。 |
miz activity cancel <编号> |
取消活动;需要活动管理权限。 |
miz faq <关键词> / miz faq list |
查询群问答或查看已收录关键词。 |
miz faq add/edit/delete ... |
添加、修改或删除词条;需要群管理或 FAQ 白名单权限。 |
miz todo add [YYYY-MM-DD HH:mm] [@QQ号] 内容 |
添加群待办;指定其他负责人需要群管理或待办白名单权限。 |
miz todo list/done/cancel ... |
查看、完成或取消待办;创建者、负责人和管理者拥有不同的处理权限。 |
miz vtb live <主播昵称> |
查询主播当前直播状态。 |
miz vtb dynamic <主播昵称> |
查询主播最新动态。 |
miz vtb list/subscribe/unsubscribe ... |
查看或维护本群订阅;list 按主播分组列出已开启的直播、动态推送及 @全体成员 设置,关闭项不显示;需要群管理员或 VTB 管理员白名单权限。 |
miz vtb atall enable/disable <主播昵称> |
开启或关闭该主播开播通知的 @全体成员;需要先订阅该主播,并需要群管理员或 VTB 管理员白名单权限。 |
miz vtb dynamicatall enable/disable <主播昵称> |
开启或关闭该主播动态通知的 @全体成员;需要先订阅该主播,并需要群管理员或 VTB 管理员白名单权限。 |
miz vtb sync |
同步主播昵称、MID 和直播间资料;仅 VTB 管理员白名单可用。 |
miz ff14 <分区> <道具名> |
查询国服市场;分区简写为猫、猪、狗、鸟。 |
miz ff14 list |
用一条合并转发展示当前群的全部商品推送及启用状态;转发内每 10 个商品归为一个节点。 |
miz ff14 add <分区> <最高价> <道具名> [@成员 ...] |
给当前群增加商品推送,可指定触发时要 at 的成员;需要群管理或 FF14 管理白名单权限。 |
miz ff14 remove <道具名> |
删除当前群中该商品的全部推送;需要管理权限。 |
miz ff14 disable/enable <道具名> |
暂时禁用或恢复当前群中该商品的推送,不删除配置;需要管理权限。 |
miz broadcast <内容> |
向机器人所在全部群发送最多 1000 字的广播;仅广播白名单可用。 |
miz recall [数量] / miz 撤回 [数量] |
从群消息历史中查找并撤回迷子账号最近发送的消息(包括同一账号从手机等其他客户端发出的消息),数量默认为 1、单次最多 20;仅 [miz.recall].whitelistUserIds 中的 QQ 号可用。成功后静默,超时或部分失败时会提示结果。 |
miz joke |
随机发送 10 张不重复的米哈游笑话图。 |
多数英文命令同时提供中文别名,具体以 miz help 的输出为准。
复读不是命令:同一群连续第 3 次出现相同文本或图片时,机器人复读一次。可识别的命令消息不会参与复读计数。
| 任务 | 默认计划 |
|---|---|
| 每日壁纸 | 每天 08:00,发送到机器人所在的全部群。 |
| 财经新闻 | 每 5 分钟检查配置群的新内容。 |
| 单次与循环提醒 | 每分钟检查,单批默认处理 20 条。 |
| 群日程 | 每分钟检查,默认提前 30 分钟提醒。 |
| 活动报名 | 每分钟检查,默认提前 30 分钟提醒报名成员。 |
| 群待办 | 每分钟检查,默认提前 30 分钟提醒负责人。 |
| VTB 直播 | 每 3 分钟批量检查直播状态。 |
| VTB 动态 | 分片轮转,默认约 15 分钟覆盖全部订阅主播。 |
| VTB 资料同步 | 默认每周日 00:00。 |
| FF14 低价提醒 | 默认每小时检查,实际目标及每条提醒的 priceAlertAtUserIds 由 config/ff14.toml 配置;已提醒的市场挂单会记录到 PostgreSQL,同一挂单只提醒一次,连续 3 天未再出现的挂单记录会自动清理。 |
同一个定时任务不会重叠执行:前一次还未结束时,下一次会跳过并写入日志。短暂的事件循环或容器调度延迟会被容忍;确实错过 cron 时刻时,任务恢复调度后会自动补跑一次。VTB 上游请求还会合并相同并发查询、限制请求间隔,并在遇到 429、412 或连续故障时暂时熔断,冷却后自动恢复。FF14 道具名称与 ID 会保存在 PostgreSQL,命中后只查询动态市场价格;所有 FF14 外部请求共用保守的请求间隔,并在限流时按 Retry-After 退避重试。
准备为 miz 添加插件时,请先阅读完整的 插件开发指南。其中包含插件接口、命令解析、消息格式、权限、并发、配置、数据库、定时任务和测试约定。
运行时会递归扫描 [miz.plugins].directory,加载 .ts、.js 和 .mjs 文件。模块可以通过 default、plugin 或 plugins 导出一个或多个插件。
最小命令插件:
import type { MizPlugin } from "@/plugins";
const pingPlugin: MizPlugin = {
name: "ping",
commands: ["ping"],
description: "检查机器人是否在线。\n用法:miz ping",
async handle({ reply }) {
await reply("pong");
},
};
export default pingPlugin;插件可以使用 reply、replyForward、网关实例、当前配置、日志器和已加载插件信息。没有命令但需要监听所有消息的插件,可以提供 onMessage,内置复读功能就是这种形式。
config/example/ 配置模板
plugins/ 可自动发现的命令与消息插件
prisma/ Prisma Schema 与数据库迁移
scripts/ 启动和迁移脚本
src/ 网关、配置、任务、仓储和业务实现
tests/ Bun 单元测试
tools/ 本地 yt-dlp 与 FFmpeg(不提交到 Git)
temp/ 临时媒体文件(不提交到 Git)
bun test
bun run typecheck
bun run prisma:generate
bun run prisma:migrate
bun audit常用脚本:
| 脚本 | 作用 |
|---|---|
bun run start |
更新 npm 依赖、检查并显示媒体工具版本后,以普通模式启动、生成 Prisma Client 并执行迁移。 |
bun run start:docker |
更新 npm 依赖、检查并显示媒体工具版本后,以 Docker 模式启动并加载 app.docker.toml。 |
bun run dev |
更新 npm 依赖、检查并显示媒体工具版本后,以普通模式监听源文件变化。 |
bun run dev:docker |
更新 npm 依赖、检查并显示媒体工具版本后,以 Docker 配置监听源文件变化。 |
bun run dependencies:update -- normal |
使用本机 app.local.toml 的代理检测并更新 npm 依赖、FFmpeg 和 yt-dlp。 |
bun run dependencies:update -- docker |
使用 Docker app.docker.toml 的代理检测并更新 npm 依赖、FFmpeg 和 yt-dlp。 |
bun run prisma:migrate |
使用当前配置执行 prisma migrate deploy。 |
bun run prisma:push |
将 Schema 直接推送到数据库,适合本地开发验证。 |
日志默认输出到控制台。外部接口调用失败时,优先检查接口地址、代理、B 站 Cookie、容器网络、PostgreSQL 和 NapCat 网关状态。
检查是否保留了完整示例中的空字符串或不合法的 0 占位值。只保留需要覆盖的可选字段,或者为其填写有效值。
先检查 NapCat 日志中的具体富媒体错误,并确认 miz 的项目 temp 目录与 NapCat 的 napcatMediaDirectory 指向同一份宿主机目录、NapCat 有读取权限;文件路径发送失败后,miz 还会自动尝试 Base64 和单节点合并转发。
这些功能依赖外部接口。补全对应配置段中的 API 地址后保存 TOML;运行时会热重载配置。原生文件事件之外还有内容指纹校验兜底,运行时重建遇到短暂故障会恢复旧配置并自动重试。VTB 订阅和 FF14 低价提醒由命令修改后还会直接刷新对应任务。修改程序代码本身仍需要重启生产进程部署。
确认主播已加入该群订阅的 atAllStreamers,机器人在群内具有群主或管理员身份,并且账号仍有可用的 @全体成员 次数。