安装即用,零配置起步 — 插件会自动记录经过 AstrBot 的每一条消息,无需任何手动操作。需要更多功能时再按需开启。
狐狸插件 就是为此而生 —— 装上就忘,需要时随时搜索、导出、分析。
query() / count() / search() 等完整查询接口,其他插件一行代码即可调用(platform, message_id) 和 (platform, content_hash) 双唯一索引,同一消息不会重复入库插件已适配 AstrBot 注册的全部 18 个平台,按类型分组:
| 类型 | 平台 |
|---|---|
| 即时通讯 | Telegram、LINE、WebChat |
| 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_host |
127.0.0.1 |
MySQL 服务器地址 |
mysql_port |
3306 |
MySQL 服务器端口 |
mysql_user |
root |
MySQL 用户名 |
mysql_password |
`` | MySQL 密码 |
mysql_database |
fox_toolbox |
MySQL 数据库名(需提前创建) |
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 |
[] |
参与广播的平台白名单;留空表示所有平台参与,填写平台名(如 aiocqhttp、telegram)则仅这些平台参与 |
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 缓存消息统计与最近消息,可显著降低 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 面板后,可在 AstrBot Dashboard 的插件页面中直接访问管理界面,无需额外安装依赖。
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 仍可用) |
/狐狸菜单 |
时间范围格式支持:
| 格式 | 说明 | 示例 |
|---|---|---|
| 自然语言 | today、yesterday、week、month、hour |
week |
| 天数范围 | last7d、last30d、last3d 等 |
last7d |
| 小时范围 | last1h、last3h、last12h 等 |
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_url与btpanel_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 接口,其他插件可以通过以下方式调用:
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
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()
| 参数 | 类型 | 说明 |
|---|---|---|
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 | 消息类型:group、private、channel |
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 正序 |
@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() # 解析原始消息为字典
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)
| 方法 | 说明 |
|---|---|
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 | 记录创建时间 |
索引:
(platform, message_id) 唯一索引 — 防止同平台同消息重复入库(platform, content_hash) 唯一索引 — 内容级别去重timestamp、sender_id、group_id、channel_id、session_id、reply_to_id 常规索引FULLTEXT 全文搜索索引(ngram 分词器) — 支持中文消息内容关键词搜索启用多媒体保存后,文件存储路径为:
data/plugin_data/astrbot_plugin_fox_toolbox/media/
├── images/ # 图片
│ ├── a1/ # 按内容哈希前2位分目录
│ ├── b2/
│ └── ...
├── records/ # 语音
├── videos/ # 视频
└── files/ # 其他文件
存储策略:
a1b2c3d4e5f6g7h8.jpg插件注册了以下 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 # 依赖列表
AstrBot/data/plugins/# 运行单元测试(不需要 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 .
/hulihelp / /狐狸菜单 命令:输入即可查看全部可用指令other / forum / 脏 message_type 会结合 group_id、channel_id 自动归类,顶部统计卡、时间趋势、平台消息详情、群组排行恢复正常消息内容类型分布 缺失:content_types 兼容逗号串、JSON 数组和空值文本回退,旧数据也能统计出内容类型metadata.yaml、Plugin Page BUILD_VERSION、index.html 资源参数和快照水印/huli_record snapshot 快照图大面积变黑:旧版圆环图用全不透明掩码镂空内圆,导致整幅图被黑色覆盖,改为透明色重绘镂空彻底修复消息内容类型分布 从旧版独立饼图重构为与平台分布一致的玻璃态圆环图,全图视觉风格统一ImportError: cannot import name '_to_int':main.py 全部导入改为相对导入 from .fox_toolbox.xxx import,符合 AstrBot 官方规范,根治热重载时顶层包模块缓存残留导致的问题(更新文件后无需完全重启 AstrBot)scripts/fix_deploy.sh:合并覆盖语法确保旧目录文件被更新,新增同步校验输出scripts/fix_deploy.sh 一键同步脚本:在 AstrBot 部署服务器上执行 bash scripts/fix_deploy.sh,将插件代码完整对齐到远程最新版本,避免 main.py 与 fox_toolbox/ 文件版本混用导致的导入错误/huli_record snapshot 报错 'dict' object cannot be interpreted as an integer:新增 _to_int 安全类型转换函数,对所有统计数值做防御性转换,兼容 MySQL 驱动的 Decimal、None、dict 等异常类型,杜绝渲染崩溃_draw_content_types 饼图中 math 未导入、_TEXT_DARK/_GLASS_BG 常量不存在导致的 NameError/huli_record snapshot 增加渲染兜底:渲染异常时返回友好提示并记录完整日志,不再让 astrbot 弹出崩溃异常_draw_header 最新消息时间戳与 /huli_record stats 最早/最新消息时间戳,异常类型(dict 等)不再导致 TypeErrorhuli_record(原 msg_record),所有子命令同步更新load() 像素赋值在 resize 时丢失数据,改用 paste)/huli_record snapshot 指令:将数据库统计渲染成与 WebUI 风格一致的 PNG 快照图发到聊天,包含统计卡片、时间趋势、发送者/群组排行、内容类型分布fox_toolbox/snapshot_renderer.py,基于 Pillow 渲染 Liquid Glass 风格仪表盘,无新增重依赖/huli_record help 补充 snapshot 指令说明web_api.py 与新版 main.py 混用时 register_all_web_apis 参数不匹配崩溃,页面/API 不再因版本不同步而全部未注册status/stats 接口的 db_status 携带具体 MySQL 连接错误,前端状态卡片与顶部横幅直接展示失败原因0.2.2status/stats 接口新增 db_status.error 透出具体连接错误,前端状态卡片与顶部横幅直接展示失败原因0.2.1db_status 缺失时显示 -- 并清除加载骨架,并自动用 status 接口兜底,不再停留骨架态list_tables() 兼容 tuple 与 dict 两种游标行SHOW / DESCRIBE / DESC 不再追加 LIMIT,已有超大 LIMIT 自动钳制0.2.0SELECT / SHOW / DESCRIBE / DESC,拦截 DROP/TRUNCATE/GRANT/注释注入等危险操作,自动附加 LIMIT 防止大表全量拉取,查询超时上限 15 秒/huli_record tables 聊天命令,查看数据库业务表列表(自动跳过 _schema_meta 系统表)LIKE '%grant%')不再被误判为危险操作0.1.12-1,不再依赖额外的 ping() 前置判断--stats 响应数据,仅在 stats 失败时用 status 接口兜底0.1.11,刷新后会加载最新页面资源12 张),连接失败时显示“未连接”status 接口兜底,stats 接口失败也能正常展示0.1.10,刷新后会加载最新页面资源stats 接口移除未使用的旧状态计算,减轻页面首屏加载负担stats 接口新增 db_status 字段,数据库状态卡片直接复用统计接口返回数据0.1.8,刷新后会加载最新页面资源CHANGELOG.md 中重复空版本标题,补齐版本记录可读性app.js 和 style.css 增加版本查询参数,强制 AstrBot 页面刷新后加载最新前端资源stats 接口即使统计失败也会返回 plugin_status,状态卡片不再跟着统计接口一起失效stats 接口返回的 plugin_status,不再依赖独立的状态接口路由stats 与 status 共用同一份状态构造逻辑,插件状态、健康度、内存/CPU 数值来源统一Plugin Pages 文档修正状态接口路径,状态卡片前端请求改为插件内相对路径 statusstatus 主路由,并保留旧的 plugin/status 兼容路由,降低 AstrBot 页面桥接下的接口匹配风险- 的问题,前端现在会稳定显示明确状态和数值plugin/status 接口改为分项容错采集,数据库或资源指标局部异常时仍返回可展示结果astrbot_plugin_fox_toolbox 兼容包路径,恢复本地测试按项目包名导入176 passed, 63 skipped,主入口 main.py 可正常导入plugin/status 接口失败时显示 - 和骨架屏残留的问题console.log 诊断日志,便于定位 plugin/status 接口失败原因clearStatusSkeletons() 兜底清理逻辑,确保状态卡片最终能退出加载态280px 调整到 340px,响应式断点同步更新_build_query_filter_from_dict 新增 order 白名单校验,导入相关接口补充文件大小和分片边界校验0.0.11 升级到 0.1.0Database.ping() 探测数据库连通性,正常显示绿色「健康」,异常显示红色「异常」GET /fox_toolbox/plugin/status 接口与 fox_toolbox/sys_util.py(标准库采集进程资源,无新增依赖)channel_message_count 字段此前已支持,本次补齐前端展示)downloadExportFile 缺少 extractData(),导致 base64 下载必定失败)test_schema_version 测试断言过时(SCHEMA_VERSION 已升级至 3,断言仍为 2).card 浮动动画不生效(contain: layout paint 与 translate 冲突)get_timeline_stats 补充 channel_count 字段)safeUrl() 函数,仅允许 http/https 协议)首个正式版本,基于 astrbot_plugin_message_recorder 重构。
FROM_UNIXTIME + GROUP BY 别名兼容性)_conf_schema.json 中 JSON 语法错误(未转义双引号导致插件安装失败)__init__.py(干扰 AstrBot 插件加载)完整变更记录见 CHANGELOG.md。
GNU Affero General Public License v3.0
redis.asyncio 接口实现scripts/fix_deploy.sh)的实现语言,用于一键同步插件代码到 AstrBot 服务器