hulichajian

# 🦊 狐狸插件 [![AstrBot](https://img.shields.io/badge/AstrBot-%3E4.16%2C%3C5-blue?style=for-the-badge)](https://github.com/Soulter/astrbot) [![Python](https://img.shields.io/badge/Python-3.12+-green?style=for-the-badge)](https://www.python.org/) [![License](https://img.shields.io/badge/License-AGPL--3.0-blue?style=for-the-badge)](LICENSE) [![Version](https://img.shields.io/badge/Version-2.2.2-orange?style=for-the-badge)](CHANGELOG.md) **全平台聊天消息自动记录 | MySQL 5.7 存储 | Web 管理面板 | 全文搜索 | 插件 API**

为什么选择狐狸插件?

安装即用,零配置起步 — 插件会自动记录经过 AstrBot 的每一条消息,无需任何手动操作。需要更多功能时再按需开启。

狐狸插件 就是为此而生 —— 装上就忘,需要时随时搜索、导出、分析。


✨ 功能特色


📱 支持的平台

插件已适配 AstrBot 注册的全部 18 个平台,按类型分组:

类型 平台
即时通讯 Telegram、LINE、WebChat
QQ aiocqhttp(OneBot)、QQ 官方、QQ 官方 Webhook
企业协作 钉钉、飞书、企业微信、企业微信 AI 助手
频道 / 社区 Discord、Slack、Mattermost、Kook
微信公众号 微信开放平台、微信公众号
联邦宇宙 Misskey、Satori

未列出的平台也不会丢失消息 —— 插件会自动回退到通用适配器,确保所有经过 AstrBot 的消息都能被记录。


🎯 适用场景


📦 安装

方式一:插件市场(推荐)

在 AstrBot WebUI 的 插件市场 中搜索「狐狸插件」并一键安装

方式二:手动安装

将本仓库克隆到 AstrBot 的插件目录:

cd AstrBot/data/plugins/
git clone https://github.com/leafliber/astrbot_plugin_fox_toolbox.git

然后在 AstrBot WebUI 的「插件管理」页面点击「重载插件」

前置要求


🎛️ 配置项

在 AstrBot WebUI 的插件配置页面可调整以下选项:

功能配置

配置项 默认值 说明
enable_commands true 是否启用消息记录指令
max_records 0 最大消息记录数,超过时自动清理最旧记录(0 = 不限制)
retention_days 0 消息保留天数,超过此天数自动清理(0 = 永久保留)
save_message_chain true 是否保存完整消息链(包含图片、表情等)
save_raw_message false 是否保存平台原始消息对象
cleanup_interval_hours 24 自动清理间隔(小时)
save_media_files false 是否保存多媒体文件到本地
image_save_mode original 图片保存模式:original(原图)/ thumbnail(缩略图)

提示:首次使用需先在 MySQL 中创建数据库(如 CREATE DATABASE fox_toolbox CHARACTER SET utf8mb4;),然后在配置页面填写连接信息。

MySQL 数据库配置

配置项 默认值 说明
mysql_host 127.0.0.1 MySQL 服务器地址
mysql_port 3306 MySQL 服务器端口
mysql_user root MySQL 用户名
mysql_password `` MySQL 密码
mysql_database fox_toolbox MySQL 数据库名(需提前创建)

本地 SQLite 兜底存储(自动降级)

MySQL 不可用、故障或连接中断时,插件自动降级到本地 SQLite 文件继续记录消息与爱发电订单,避免消息丢失;MySQL 恢复后自动切回并分批补写降级期间的消息(默认每 30 秒检测一次,单批 500 条幂等写入)。降级期间全部查询、统计、排行、导出功能保持可用,Web 面板状态卡片会标注当前存储后端与未同步消息数。

配置项 默认值 说明
storage_fallback_enabled true 是否启用本地 SQLite 自动兜底存储;关闭后故障行为与旧版一致(消息无法记录)
recovery_check_interval 30 MySQL 恢复检测间隔(秒),最小 5 秒
connection_max_retries 5 MySQL 与 Redis 断连后自动重连的最大连续次数(最小 1);达到上限后停止自动重连,分别进入 SQLite 降级 / 无缓存模式
backfill_batch_size 500 MySQL 恢复后单批补写消息条数,按批推进避免大事务
sqlite_max_retention_days 30 已补写进 MySQL 的消息在本地 SQLite 中的保留天数,超过后自动清理以控制文件增长

存储位置:SQLite 兜底库位于插件数据目录下 astrbot_plugin_fox_toolbox/messages_fallback.db(如 data/plugins/astrbot_plugin_fox_toolbox/messages_fallback.db),无需额外安装依赖。降级与恢复全程自动,无需人工干预。

数据安全:降级期间按保留天数/条数执行的自动清理只针对已补写进 MySQL 的同步数据,未同步(待补写)的消息会完整保留,确保 MySQL 恢复补写时不丢失任何消息。

爱发电打赏对接(可选)

配置项 默认值 说明
afdian_enabled false 是否启用爱发电打赏对接功能
afdian_webhook_host 0.0.0.0 爱发电 Webhook 监听地址
afdian_webhook_port 6500 爱发电 Webhook 监听端口
afdian_webhook_token `` 爱发电 Webhook 回调校验令牌(可选):填写后回调请求需在 URL 携带 ?token=<值> 才会被接受;留空保持向后兼容、不做校验
afdian_use_polling true 是否启用无公网订单轮询检测(无公网机器替代 Webhook 推送)
afdian_poll_interval 5 订单轮询间隔(秒),最小 1 秒
afdian_poll_timeout 300 发电后等待支付的完成时限(秒),默认 5 分钟
afdian_recovery_check_interval 30 MySQL 故障降级后订单存储的恢复检测间隔(秒),恢复后自动切回并回写降级期订单,最小 5 秒
afdian_api_base_url https://afdian.com/api/open 爱发电 API 根地址
afdian_api_user_id `` 爱发电用户 ID(开发者后台获取)
afdian_api_token `` 爱发电 API 密钥(开发者后台获取)
afdian_default_price 5 发起赞助时的默认金额(元)
afdian_default_reply 赞助成功,感谢支持! 赞助成功后的默认回复语
afdian_notice_sessions [] 接收订单通知的会话 ID(可用「开启发电通知」指令添加)
afdian_rate_limit_enabled true 是否启用 /发电 防刷限流
afdian_rate_limit_max_orders 3 1 分钟窗口内允许发起订单的最大次数,达到即触发拉黑
afdian_rate_limit_window 60 限流统计窗口(秒)
afdian_rate_limit_ban_seconds 3600 触发限流后的拉黑时长(秒),默认 1 小时

防刷限流:同一用户在 1 分钟窗口内发起 /发电 达到上限次数(默认 3 次)时,拒绝本次请求并临时拉黑(默认 1 小时),期间该用户再使用 /发电 会被拒绝并提示剩余等待时间,防止批量刷单/骚扰推送。

Webhook 要求:爱发电订单通知需要公网可达的回调地址。请放行 afdian_webhook_port 对应端口,并在爱发电开发者设置中将回调地址指向该端口(如 http://公网IP:6500/);若无公网 IP,可配置反向代理或内网穿透(frp / ngrok / cloudflared)转发到该端口。

无公网替代方案:完全没有公网地址的机器可启用 afdian_use_polling(默认开启)。用户点击发电后,插件每 afdian_poll_interval 秒(默认 5 秒)拉取一次订单,并在 afdian_poll_timeout 秒(默认 300 秒 / 5 分钟)内发现新订单即处理(备注匹配用户并自动回复),无需公网回调;此模式同样可用全部查询指令。

数据存储:爱发电订单会写入主插件 MySQL 数据库的 afdian_orders 表(与消息记录同一实例、同一库);MySQL 不可用时自动回退到插件数据目录下的 SQLite 兜底,保证订单不丢失。

广告助手(可选)

按设定的时间点向所有已记录的群聊定时广播广告,支持按平台、按群单独控制。默认所有平台都参与;插件在收到群聊/频道消息后会自动记录该群作为广播目标(无需手工配置群列表),广告内容与定时时间点通过指令管理。

配置项 默认值 说明
dsgg_enabled true 是否启用广告助手功能
dsgg_platforms [] 参与广播的平台白名单;留空表示所有平台参与,填写平台名(如 aiocqhttptelegram)则仅这些平台参与
dsgg_exclude_platforms [] 不参与广播的平台黑名单;填写平台名则这些平台不参与
disable_gids [] 不接收广告的群聊 ID 列表。支持两种格式:纯群 ID(如 123456)屏蔽所有平台的该群;platform:群ID(如 aiocqhttp:123456)仅屏蔽指定平台该群。可在群内用 /关闭广告 自动添加
dsgg_send_interval 0 群间发送间隔(秒);0 表示随机间隔 1-3 秒,正数则按固定秒数间隔发送,避免触发平台频率限制

广告内容:支持 /添加广告 广告内容 直接添加文字广告,也支持发送 /添加广告 后在 30 秒内发送要广播的内容(支持文字、图片等富媒体),发送「取消」可中止;/广告列表/查看广告 <ID>/删除广告 <ID> 管理已有广告。添加广告别名:/加广告/新增广告定时广播/定时广告 09:00,14:30 设置每天发送时间点(支持多个,英文逗号分隔),/停止广告 停止定时广播。 群级开关:任何群成员都可在群内用 /开启广告 / /关闭广告 控制本群是否接收广告(disable_gids 同步更新)。

宝塔面板管理(可选)

通过宝塔面板官方 API 远程管理面板(复刻自 btpanel-plugin)。需在宝塔「面板设置 → API 接口」中开启接口、放行机器人服务器 IP,并获取接口密钥;面板需部署在可通过网络访问的地址上。

配置项 默认值 说明
btpanel_enabled true 是否启用宝塔面板管理功能
btpanel_url `` 宝塔面板 API 地址,如 https://127.0.0.1:8080(支持自签证书)
btpanel_api_sk `` 宝塔面板「面板设置 → API 接口」中的接口密钥

查询指令(所有人可用):/宝塔 系统状态/宝塔 磁盘信息/宝塔 内存详情/宝塔 CPU详情/宝塔 系统负载/宝塔 网络流量/宝塔 网站列表/宝塔 网站SSL <域名>/宝塔 数据库列表/宝塔 数据库状态/宝塔 MySQL配置/宝塔 计划任务/宝塔 任务日志 <ID>/宝塔 FTP列表/宝塔 后台任务/宝塔 安全扫描/宝塔 安全评分管理指令(仅管理员):/宝塔 释放内存/宝塔 重启面板/宝塔 清理系统/宝塔 服务 <重启|启动|停止|重载> <服务名>/宝塔 网站开启|网站停止|网站备份 <域名>/宝塔 数据库备份 <库名>/宝塔 任务启用|任务暂停 <ID>。 完整清单见 /宝塔 帮助

Redis 缓存(可选)

通过 Redis 缓存消息统计与最近消息,可显著降低 WebUI 首页加载时对数据库的查询压力。未启用、未安装依赖或连接失败时,插件自动以无缓存模式运行,不影响任何功能。运行中若 Redis 断连,插件会按 connection_max_retries(默认 5 次)自动重连,期间自动以无缓存模式运行,恢复后自动切回缓存;达到上限仍未恢复则保持降级,需重启插件后重新建立自动重连。

配置项 默认值 说明
redis_enabled false 是否启用 Redis 缓存
redis_host 127.0.0.1 Redis 服务器地址
redis_port 6379 Redis 服务端口
redis_password `` Redis 认证密码(未设置则留空)
redis_db 0 Redis 数据库编号(建议使用独立编号)
redis_cache_ttl 300 统计缓存有效期(秒);消息落库后会即时更新最近消息缓存,统计缓存按此 TTL 刷新
redis_recent_window_seconds 1800 最近消息缓存时间窗口(秒,默认 1800 即 30 分钟);超出窗口的旧消息会被清除,只保留窗口内的最新消息
redis_cache_refresh_interval 1800 缓存周期刷新间隔(秒,默认 1800 即 30 分钟);每隔该周期从数据库重建最近消息缓存并强制对齐统计缓存,避免长期增量累积导致数据漂移

依赖安装:使用 Redis 缓存需安装 redis 包。在 AstrBot 容器内执行 pip install redis 或在插件依赖中声明;未安装时插件会打印提示并自动降级为无缓存模式。


🌐 Web 管理面板

启用 Web 面板后,可在 AstrBot Dashboard 的插件页面中直接访问管理界面,无需额外安装依赖。

界面设计 — Liquid Glass 液态玻璃

Web 面板采用 Liquid Glass 液态玻璃设计风格,通过现代 CSS 技术实现半透明磨砂玻璃质感:

技术特性 说明
磨砂玻璃 backdrop-filter: blur(20px) saturate(180%) 实现背景模糊与饱和度增强
渐变高光 ::before 伪元素叠加斜向白色渐变,模拟玻璃表面的光线折射
内外阴影 外阴影提供悬浮感,内阴影(inset)模拟玻璃边缘高光
动态背景 多层径向渐变(紫、粉、蓝、黄)作为底衬,增强玻璃透明效果的视觉层次
流动光斑 统计卡片内部 ::after 伪元素配合 drift 动画,营造液态流动感
交互反馈 全卡片浮动动画(统计卡片、图表容器、内容卡片、筛选区)、卡片悬停浮起、按钮高光反射、卡片入场动画(cardAppear
优雅降级 不支持 backdrop-filter 的浏览器自动回退为不透明背景(@supports
无障碍 尊重 prefers-reduced-motion 偏好,自动禁用动画
响应式 三套断点自适应手机(≤480px/≤768px)、平板(769~1024px)、电脑(>1024px),所有页面元素完美适配

浏览器兼容性:液态玻璃效果需要浏览器支持 backdrop-filter 属性(Chrome 76+、Firefox 103+、Safari 9+)。不支持的环境会自动降级为不透明卡片样式,功能不受影响。

仪表盘

仪表盘采用渐进式渲染:各区域独立骨架屏加载,数据到达后即时填充。

消息搜索

数据导出

格式 扩展名 说明
JSON .json 标准 JSON 格式,适合数据交换和程序处理
CSV .csv 表格格式,可用 Excel 等工具打开
ZIP .zip 专用打包格式,包含数据 + 媒体文件,支持导入还原

导出功能特性:

数据导入


💬 指令使用

指令功能可通过配置项 enable_commands 启用或禁用,默认启用。

基础指令

主命令均为中文;旧英文指令(如 /huli_record stats)仍可作为别名使用。

权限说明:清理查询搜索表列表快照 为管理类命令,仅管理员可执行。

指令 说明 示例
/狐狸记录 统计 查看消息统计信息 /狐狸记录 统计
/狐狸记录 清理 手动触发清理 /狐狸记录 清理
/狐狸记录 查询 [发送者ID] [limit] 查询消息记录 /狐狸记录 查询 123456 20
/狐狸记录 搜索 <关键词> [limit] 搜索消息内容 /狐狸记录 搜索 hello 10
/狐狸记录 帮助 查看帮助信息 /狐狸记录 帮助
/狐狸记录 今日 查看今天的消息 /狐狸记录 今日
/狐狸记录 昨日 查看昨天的消息 /狐狸记录 昨日
/狐狸记录 历史 <时间范围> 按时间范围查询 /狐狸记录 历史 last7d
/狐狸记录 快照 生成 WebUI 仪表盘快照图 /狐狸记录 快照
/狐狸记录 表列表 查看数据库中的业务表列表 /狐狸记录 表列表
/狐狸菜单 查看全部可用指令(旧 /hulihelp 仍可用) /狐狸菜单

时间范围格式支持:

格式 说明 示例
自然语言 todayyesterdayweekmonthhour week
天数范围 last7dlast30dlast3d last7d
小时范围 last1hlast3hlast12h last3h
具体日期 YYYY-MM-DD 格式 2024-01-15
日期范围 日期范围,用 ~ 分隔 2024-01-01~2024-01-15
相对时间 -1d(昨天)、-7d(7天前)等 -3d

⚡ 爱发电打赏指令

需在插件配置中启用 afdian_enabled 并填写 afdian_api_user_id / afdian_api_token

指令 说明 权限
/发电 [金额] 生成爱发电支付链接,接受用户打赏(备注记录付款人);别名 /赞助。启用轮询时提示请在设定时间内(默认 5 分钟)完成支付 所有人
/爱发电测试 模拟一笔新订单,走完整「自动检测 → 入库 → 推送到所有已设置的推送群 + 当前聊天群」链路(不请求真实接口),验证通知链路;别名 /发电测试/发电模拟/模拟发电/模拟发电订单/爱发电模拟 管理员
/查询订单 <订单号> 查询指定订单的详情信息 管理员
/同步历史订单 通过爱发电 API 主动分页拉取全部历史订单入库(按交易号去重),随时可手动补拉 管理员
/查询发电 查询默认账号收到的赞助记录;别名 /查询赞助 管理员
/开启发电通知 在当前会话开启爱发电订单通知;别名 /发电通知/爱发电通知 管理员

工作流程:用户在机器人发送 /发电,获得支付链接并付款(链接备注中写入用户ID);有公网时爱发电通过 Webhook 推送订单给插件;无公网时插件触发按需限时轮询,每 afdian_poll_interval 秒(默认 5 秒)拉取一次新订单,最多持续 afdian_poll_timeout 秒(默认 5 分钟),无待确认订单时自动停止。哪种方式下单均保存订单、通知所有订阅会话,并对该付款用户发送赞助成功回复。

历史订单同步:插件启动/重载时会自动分页拉取爱发电平台的全部历史订单并入库(按交易号 out_trade_no 去重,只保存新增订单),保证 Webhook/轮询上线前的订单不丢失;也可随时使用 /同步历史订单 命令手动补拉。

无公网轮询(按需限时):无公网地址的机器可开启 afdian_use_polling(默认开启)。用户点击发电后插件启动限时轮询:每 afdian_poll_interval 秒(默认 5 秒)拉取一次订单,最多持续 afdian_poll_timeout 秒(默认 300 秒 = 5 分钟);发现新订单即按与 Webhook 完全相同的备注匹配逻辑处理,订单只有首次入库(按交易号去重,旧订单不会被覆盖);待确认订单全部处理完或轮询窗口到期后自动停止,无人发电时不会持续请求接口、避免刷屏日志。建议同时关闭 Webhook 端口对外监听。

图片水印/查询订单/查询发电 的查询结果图片顶部显示插件名与插件版本(替代默认的框架名水印)。


📢 广告助手指令

需在插件配置中启用 dsgg_enabled(默认开启)。广播目标为插件记录过的全部群聊/频道会话,可通过平台白名单/黑名单与群级开关控制范围。

指令 说明 权限
/开启广告 [序号] 开启当前群聊的广告接收;管理员可传序号开启指定群(序号见 /广告群列表);别名 /开广告 所有人
/关闭广告 [序号] 关闭当前群聊的广告接收;管理员可传序号关闭指定群;别名 /关广告 所有人
/广告群列表 查看所有已记录的群聊及其广告接收状态(含平台、群 ID、启用/关闭) 管理员
/添加广告 [广告内容] 可直接添加文字广告;不带内容时在 30 秒内发送要添加的广告内容(支持富媒体),发送「取消」中止;别名 /加广告/新增广告 管理员
/广告列表 列出所有广告的 ID 与创建时间 管理员
/查看广告 <ID> 查看指定广告的内容摘要并在当前会话预览发送 管理员
/删除广告 <ID> 删除指定广告 管理员
/定时广告 <HH:MM[,HH:MM...]> 设置定时广告发送时间点(支持多个,英文逗号分隔);不带参数时查询当前设置 管理员
/停止广告 停止定时广告发送 管理员

平台过滤dsgg_platforms(白名单)与 dsgg_exclude_platforms(黑名单)决定哪些平台参与广播,默认全部平台参与。 群级过滤disable_gids 支持纯群 ID 与 platform:群ID 两种格式,可精确到平台下的单个群。 致谢:广告助手复刻自 astrbot_plugin_furry_dsgg(作者 furryHM-mrz,AGPL-3.0),在原 QQ 平台实现基础上改造为全平台通用(通过 unified_msg_origin 记录会话并经 context.send_message 广播,不依赖 QQ 群列表 API)。

🗄 宝塔面板指令

需在插件配置中填写 btpanel_urlbtpanel_api_sk(宝塔「面板设置 → API 接口」开启接口后获取)。查询指令所有人可用,管理指令仅管理员。

指令 说明 权限
/宝塔 帮助 查看宝塔面板全部指令 所有人
/宝塔 系统状态 查看服务器完整状态(系统/内存/CPU 汇总) 所有人
/宝塔 磁盘信息 查看磁盘分区信息 所有人
/宝塔 内存详情 查看内存详细信息 所有人
/宝塔 CPU详情 查看 CPU 详细信息 所有人
/宝塔 系统负载 查看系统负载(1/5/15 分钟) 所有人
/宝塔 网络流量 查看网络流量与各网卡速率 所有人
/宝塔 释放内存 释放系统内存缓存 管理员
/宝塔 重启面板 重启宝塔面板服务 管理员
/宝塔 清理系统 清理系统垃圾文件 管理员
/宝塔 服务 <重启\|启动\|停止\|重载> <服务名> 管理服务启停,如 /宝塔 服务 重启 nginx(支持 nginx/mysqld/redis 等) 管理员
/宝塔 网站列表 查看所有网站 所有人
/宝塔 网站开启 <域名> 启用指定网站 管理员
/宝塔 网站停止 <域名> 停止指定网站 管理员
/宝塔 网站备份 <域名> 备份指定网站 管理员
/宝塔 网站SSL <域名> 查看网站 SSL 证书信息 所有人
/宝塔 数据库列表 查看所有数据库 所有人
/宝塔 数据库状态 查看 MySQL 运行状态 所有人
/宝塔 MySQL配置 查看 MySQL 配置信息 所有人
/宝塔 数据库备份 <库名> 备份指定数据库 管理员
/宝塔 计划任务 查看所有计划任务 所有人
/宝塔 任务启用 <ID> 启用指定计划任务 管理员
/宝塔 任务暂停 <ID> 暂停指定计划任务 管理员
/宝塔 任务日志 <ID> 查看指定计划任务日志 所有人
/宝塔 FTP列表 查看 FTP 用户列表 所有人
/宝塔 后台任务 查看面板后台任务队列 所有人
/宝塔 安全扫描 查看安全扫描结果 所有人
/宝塔 安全评分 查看安全扫描评分 所有人

致谢:宝塔面板管理功能复刻自 btpanel-plugin(作者 桉南/yll14,MIT License),由 Yunzai-Bot 插件改为 AstrBot 命令组,命令前缀统一为 /宝塔


🔌 其他插件调用

本插件提供了完整的 API 接口,其他插件可以通过以下方式调用:

获取 API 实例

from astrbot.api.star import Context

async def get_fox_toolbox_api(context: Context):
    """获取狐狸插件 API"""
    recorder = context.get_registered_star("astrbot_plugin_fox_toolbox")
    if recorder:
        plugin_instance = getattr(recorder, "star_cls", None)
        if plugin_instance and hasattr(plugin_instance, "get_api"):
            return plugin_instance.get_api()
    return None

核心查询:query() 和 count()

mr_api = await get_fox_toolbox_api(context)

# 基础查询
messages = await mr_api.query(limit=10)

# 多条件组合查询
messages = await mr_api.query(
    platform="telegram",
    group_id="123456",
    sender_id="user1",
    time="today",
    keyword="关键词",
    limit=20,
    order="desc"
)

# 多 ID 查询
messages = await mr_api.query(
    sender_ids=["user1", "user2", "user3"],
    time="last7d"
)

# 频道查询
messages = await mr_api.query(
    channel_id="987654",
    time="week"
)

# 回复查询
replies = await mr_api.query(
    reply_to_id="12345678",
    platform="discord"
)

# 分页查询
messages = await mr_api.query(
    group_id="123456",
    limit=20,
    offset=40
)

# 统计数量
count = await mr_api.count(platform="telegram", time="month")

快捷方法

# 时间相关
messages = await mr_api.get_today(limit=20)
messages = await mr_api.get_yesterday(limit=20)
messages = await mr_api.get_recent(hours=6, limit=50)
messages = await mr_api.get_recent_days(days=30, limit=100)

# 搜索
messages = await mr_api.search("关键词", limit=20)
messages = await mr_api.search("关键词", group_id="123456", time="week")

# 单条查询
message = await mr_api.get_by_id(123)
message = await mr_api.get_by_platform_message_id("12345678", platform="telegram")

# 上下文
context_messages = await mr_api.get_context(message_id=123, before=5, after=5)

# 回复
replies = await mr_api.get_replies("12345678", platform="telegram")

# 频道
messages = await mr_api.get_by_channel("987654", time="week")

# 统计
stats = await mr_api.get_stats()

query() 参数详解

参数 类型 说明
platform str 单个平台名称
platforms List[str] 多个平台列表
sender_id str 单个发送者 ID
sender_ids List[str] 多个发送者 ID 列表
group_id str 单个群组 ID
group_ids List[str] 多个群组 ID 列表
session_id str 单个会话 ID
session_ids List[str] 多个会话 ID 列表
channel_id str 频道 ID(Discord 等)
message_type str 消息类型:groupprivatechannel
time str 时间字符串(见时间格式表)
start_time int 开始时间戳(毫秒),与 time 互斥
end_time int 结束时间戳(毫秒),与 time 互斥
keyword str 消息内容关键词
reply_to_id str 回复的目标消息 ID
limit int 返回数量限制
offset int 偏移量(分页)
order str desc 倒序,asc 正序

MessageRecord 数据结构

@dataclass
class MessageRecord:
    id: Optional[int]           # 数据库自增ID
    platform: str               # 平台名称
    message_id: str             # 平台消息ID
    session_id: str             # 会话ID
    group_id: Optional[str]     # 群组ID (私聊为 None)
    channel_id: Optional[str]   # 频道ID (Discord等)
    sender_id: str              # 发送者ID
    sender_name: Optional[str]  # 发送者昵称
    message_type: str           # 消息类型 (group/private/channel)
    message_str: Optional[str]  # 纯文本消息内容
    message_chain: Optional[str] # 消息链JSON (包含图片、表情等)
    raw_message: Optional[str]  # 原始消息JSON
    reply_to_id: Optional[str]  # 回复的目标消息ID
    content_hash: Optional[str] # 内容哈希 (用于去重)
    timestamp: int              # 消息时间戳 (毫秒)
    created_at: int             # 记录创建时间 (毫秒)

# 辅助方法
message.to_dict()                        # 转为字典
message.get_message_chain_list()         # 解析消息链为列表
message.get_raw_message_dict()           # 解析原始消息为字典

🖼️ 媒体文件 API

其他插件获取媒体文件

mr_api = await get_fox_toolbox_api(context)

messages = await mr_api.query(limit=10)

for msg in messages:
    media_paths = mr_api.extract_media_paths(msg)

    for rel_path in media_paths:
        # 获取绝对路径(文件不存在返回 None)
        abs_path = mr_api.get_media_absolute_path(rel_path)
        if abs_path:
            with open(abs_path, "rb") as f:
                image_data = f.read()

        # 获取 Web 访问 URL
        web_url = mr_api.get_media_url(rel_path)

媒体相关 API 方法

方法 说明
get_media_base_path() 获取媒体文件存储根目录的绝对路径
get_media_absolute_path(rel_path) 获取媒体文件的绝对路径(不存在返回 None)
get_media_url(rel_path) 获取媒体文件的 Web 访问 URL
extract_media_paths(message) 从消息记录中提取所有媒体文件的相对路径

📊 数据存储

数据库

消息存储在 MySQL 5.7 数据库中,需提前创建数据库:

CREATE DATABASE fox_toolbox CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

表结构(Schema Version 2):

字段 类型 说明
id INT AUTO_INCREMENT 自增主键
platform VARCHAR(64) NOT NULL 平台标识
message_id VARCHAR(128) 平台消息 ID
session_id VARCHAR(128) 会话 ID
group_id VARCHAR(128) 群组 ID
channel_id VARCHAR(128) 频道 ID
sender_id VARCHAR(128) NOT NULL 发送者 ID
sender_name VARCHAR(256) 发送者昵称
message_type VARCHAR(32) NOT NULL 消息类型
message_str MEDIUMTEXT 纯文本内容
message_chain LONGTEXT 消息链 JSON
raw_message LONGTEXT 原始消息 JSON
reply_to_id VARCHAR(128) 回复目标消息 ID
content_hash VARCHAR(64) 内容哈希(去重)
timestamp BIGINT NOT NULL 消息时间戳
created_at BIGINT NOT NULL 记录创建时间

索引:

多媒体文件

启用多媒体保存后,文件存储路径为:

data/plugin_data/astrbot_plugin_fox_toolbox/media/
├── images/       # 图片
│   ├── a1/       # 按内容哈希前2位分目录
│   ├── b2/
│   └── ...
├── records/      # 语音
├── videos/       # 视频
└── files/        # 其他文件

存储策略:


🔗 Web API 列表

插件注册了以下 Web API 端点(前缀 /astrbot_plugin_fox_toolbox/):

端点 方法 说明
stats GET 获取统计概览
stats/timeline GET 获取时间趋势数据
stats/senders GET 获取发送者排行
stats/groups GET 获取群组排行
messages GET 查询消息列表
message/detail GET 获取消息详情
message/context GET 获取消息上下文
search GET 搜索消息
export POST 创建导出任务
export/status GET 查询导出状态
export/download GET 下载导出文件(大文件)
export/download_data GET 获取导出文件数据(base64,小文件)
import/upload POST 简单文件导入
import/init POST 初始化分片导入
import/chunk/<session_id>/<index> POST 上传分片
import/complete POST 完成分片导入
import/status GET 查询导入状态
platforms GET 获取平台列表
senders GET 获取发送者列表
groups GET 获取群组列表
media GET 获取媒体文件
schema_version GET 获取数据库 Schema 版本

🏗️ 项目结构

astrbot_plugin_fox_toolbox/
├── main.py                  # 插件主入口
├── fox_toolbox/             # 核心源码
│   ├── __init__.py
│   ├── api.py               # 对外 API 接口
│   ├── database.py          # MySQL 5.7 数据库操作
│   ├── media_downloader.py  # 多媒体文件下载
│   ├── models.py            # 数据模型定义
│   ├── platform_adapter.py  # 平台适配器(18 个平台)
│   ├── serializer.py        # 消息链序列化
│   ├── time_utils.py        # 时间工具
│   └── web_api.py           # Web API 注册
├── pages/                   # Web 前端页面
│   └── recorder/
├── tests/                   # 测试用例
├── _conf_schema.json        # 配置项定义
├── metadata.yaml            # 插件元数据
└── requirements.txt         # 依赖列表

🛠️ 开发

本地调试

  1. 克隆 AstrBot 本体和本插件仓库
  2. 将插件目录放入 AstrBot/data/plugins/
  3. 启动 AstrBot,在 WebUI 重载插件
  4. 修改代码后点击「重载」即可热更新

运行测试

# 运行单元测试(不需要 MySQL)
python3 -m pytest tests/ -v -k "not mysql"

# 运行全部测试(包括 MySQL 集成测试,需启动 MySQL)
MYSQL_TEST_HOST=127.0.0.1 MYSQL_TEST_PORT=3306 \
MYSQL_TEST_USER=root MYSQL_TEST_PASSWORD=your_password \
python3 -m pytest tests/ -v

代码格式化

ruff format .

📝 更新日志

v2.4.3(2026-08-07)

v2.4.2(2026-08-07)

v2.4.1(2026-08-07)

v2.4.0(2026-08-07)

v2.3.2(2026-08-07)

v2.3.1(2026-08-07)

v0.4.0(2026-08-06)

v0.3.2(2026-08-07)

v0.3.1(2026-08-07)

v0.3.0(2026-08-06)

v0.2.10(2026-08-06)

v0.2.9(2026-08-06)

v0.2.8(2026-08-06)

v0.2.7(2026-08-06)

v0.2.6(2026-08-06)

v0.2.5(2026-08-06)

v0.2.4(2026-08-06)

v0.2.3(2026-08-06)

v0.2.2(2026-08-05)

v0.2.1(2026-08-05)

v0.2.0(2026-08-05)

v0.1.12(2026-08-05)

v0.1.11(2026-08-05)

v0.1.10(2026-08-05)

v0.1.9(2026-08-05)

v0.1.8(2026-08-05)

v0.1.7(2026-08-05)

v0.1.6(2026-08-05)

v0.1.5(2026-08-05)

v0.1.4(2026-08-05)

v0.1.3(2026-08-05)

v0.1.2(2026-08-05)

v0.1.1(2026-08-05)

v0.1.0(2026-08-05)

v0.0.11(2026-08-05)

v0.0.10(2026-08-05)

v0.0.9(2026-08-05)

v0.0.8(2026-08-05)

v0.0.7(2026-08-05)

v0.0.6(2026-08-05)

v0.0.1(2026-08-04)

首个正式版本,基于 astrbot_plugin_message_recorder 重构。

完整变更记录见 CHANGELOG.md


📄 许可证

GNU Affero General Public License v3.0


🙏 致谢


**如果这个插件对你有帮助,请给个 Star 支持!**