ed75a66982f75d783c647e1ad1c3800d72f45eed
协议端不在本机,而 NoneBot 的 f2s() 会把 Path 转成 file:///D:/...(file:// 的
语义是「协议端那台机器上的路径」),必然 ENOENT。受影响的不止本仓调用点,还有
装不了改不动的 pip 社区插件(本次报错来自 nonebot_plugin_doroending),只能全局拦截。
- 新增 hexi/core/outbound_media.py:挂 Bot.on_calling_api(公开钩子、适配器不覆盖),
在真正调用适配器前原地改写发送类 API 的 data:默认改写成
http://<本机可达IP>:<端口>/media/<token> 由协议端主动回拉(地址与 /hub 首页
「协议端配对」同源,零新配置),拿不到可达地址时回退 base64://
- 文件上传类(upload_group_file / upload_private_file)单独处理:file 在顶层且
只做 URL 不做 base64(几十上百 MB 不适合内联),覆盖 video_analysis 群文件
「本地直传」兜底与 alconna 的 $onebot11:file
- 媒体路由 get_app().mount("/media", sub) 复用现有端口不新开服务;免鉴权是必须的
(协议端登录不了 hub),安全模型改为「路径由 bot 改写那一刻自己登记、请求方只能
出示不可猜 token」,配短 TTL;_mounted 为 False 时绝不发 URL
- 钩子内每个段独立 try/except,任何异常只告警不抛,绝不反过来把发送搞挂
- message_utils.common_proc_reply 占位图不再自己转 base64,改传 path= 交给钩子,
避免两处各有一套策略
- tests/test_outbound_media.py:用 tmp_path 造真实文件而非 mock 文件系统,重点覆盖
file:// 解析(空格/中文编码、手工未转义的字面 %XX)与 walker 各消息形态
Co-Authored-By: Claude Code <noreply@anthropic.com>
禾汐 (HeXi)
基于 NoneBot2 的个人娱乐 QQ 机器人,使用 OneBot V11 协议接入。集成了游戏战绩查询、群聊学习、每日打卡、人设卡、表情包等大量功能,以插件化方式组织,方便增删。
功能特性
游戏相关
| 插件 | 功能 | 主要命令 |
|---|---|---|
nonebot_plugin_bf_bot |
战地系列 (BF3/BF4/BF1/BFV/BF2042/BF6) 战绩查询,PIL 生成统计卡片 | /bft /bfbind /unbind /update_bind |
nonebot_plugin_deadlock |
Deadlock 战绩、段位、近期比赛查询 | /nekoscore /nekobind /nekounbind /nekorank /nekomatch |
nonebot_plugin_steam_info |
Steam 玩家信息、库存、游戏时长查询 | /steamhelp /steambind /steaminfo /steamplaytime 等 |
nonebot_plugin_helldivers_tools |
绝地潜兵 2 前线战况简报、星球详报、随机战备推荐 | /简报 /详报 /随机战备 |
nonebot_plugin_mc_server_status |
Minecraft 服务器状态查询 | /信息 /信息数据 |
nonebot_plugin_ncm_saying |
网易云音乐热评(网抑云) | /网抑云 |
nonebot-bison |
Bilibili / 微博等订阅推送 | — |
聊天娱乐
| 插件 | 功能 | 主要命令 |
|---|---|---|
nonebot_plugin_learning_chat |
马尔可夫链群聊学习:被动学习群消息并模仿回复,定时主动发言;附 Vue 3 Web 管理后台 | — |
nonebot_plugin_galgame_card |
群友"人设卡"生成与展示,带 Web 管理后台 | — |
nonebot_plugin_group_tools |
群工具集(头像、表情、签到素材、游戏素材图等) | — |
nonebot_plugin_dailywife |
每日随机抽取群友当"老婆" | /今日老婆 |
nonebot_plugin_deer_pipe |
每日打卡(鹿)与打卡记录,日历可视化 | /打卡记鹿 /查询记录 |
nonebot_plugin_makeaquote |
生成"名言"引用图片 | — |
memes_ops |
表情包运营/管理 | — |
nonebot_plugin_random_jm_code |
随机 JM 本子代码 | /jm |
nonebot_plugin_dice |
骰子掷点 | — |
实用工具
| 插件 | 功能 | 主要命令 |
|---|---|---|
hexi/core(核心模块) |
核心库:消息解析、权限分级、限流器 (token bucket)、命令冷却、热插件管理(非插件) | — |
nonebot_plugin_video_analysis |
视频链接解析 | — |
nonebot_plugin_regif |
GIF 注册与处理 | — |
nonebot_plugin_picfinder_take |
识图(Playwright 驱动) | — |
nonebot_plugin_picstatus |
头像状态图生成 | — |
nonebot_plugin_group_daily_analysis |
群聊行为分析报告 | /群分析 |
hexi/web_hub(核心模块) |
统一 Web 管理入口 /hub(非插件) |
— |
快速开始
环境要求
安装与启动
# 安装依赖
poetry install
# 配置环境变量(见下节),然后启动
poetry run python bot.py
- 开发:使用
.env.dev(监听127.0.0.1:11011,昵称 Elika) - 生产:复制为根目录
.env后启动(监听0.0.0.0:39697,超级用户2931589710,昵称 爱丽丝)
.env / .env.dev 均已被 .gitignore 排除,包含凭据的文件不会进入仓库。
配置
启动时 NoneBot 自动加载根目录 .env 文件,主要变量:
| 变量 | 说明 |
|---|---|
HOST / PORT |
监听地址与端口 |
SUPERUSERS |
超级用户 QQ 号 |
NICKNAME |
机器人昵称 |
COMMAND_START / COMMAND_SEP |
命令前缀与分隔符 |
DRIVER |
NoneBot 驱动器(httpx + fastapi + websockets) |
ONEBOT_ACCESS_TOKEN |
OneBot 接入鉴权 token |
DATASTORE_* |
数据目录(localstore 统一指向 hexi/data/ 等) |
SENTRY_DSN / SENTRY_ENVIRONMENT |
Sentry 错误上报(可选) |
BISON_* |
Bison 订阅推送配置 |
各插件专属配置(Steam API key、网易云 cookie、识图等)按需在 .env 中补充,详见各插件文档。
目录结构
HeXi/
├── bot.py pyproject.toml README.md
├── hexi/
│ ├── plugins/ # 全部插件(pyproject [tool.nonebot] plugin_dirs 加载)
│ ├── core/ # 机器人核心模块(非插件):工具库/插件控制面/热拔插管理
│ ├── web_hub/ # 机器人核心模块:统一 Web 管理台 + 鉴权/插件注册/配置标准
│ ├── data/ # 运行数据(不入库)
│ ├── config/ # 业务配置(不入库)
│ ├── resource/ # 全局静态资源(fonts/ 字体、menu_config 等)
│ ├── web/ # 统一 Web 前端(React + Vite,构建产物 dist/ 供 /hub 挂载)
│ ├── logs/ # 日志(不入库)
│ └── web_hub/ # 见上:统一 Web 管理台/鉴权/插件注册/配置标准
├── docs/ # 插件开发标准文档
├── tests/ # pytest 测试
└── plugin_template/ # 新插件脚手架模板
- 数据库:
hexi/data/data.db(datastore)、hexi/data/nonebot_plugin_orm/db.sqlite3(orm,各插件表) - 群聊学习数据:
hexi/data/record.json+inverted_index.json(马尔可夫链) - 本地插件数据通过 localstore 统一收进
hexi/data/,避免散落根目录
测试与开发
poetry run pytest # 运行测试(tests/,asyncio auto 模式)
poetry run black . # 格式化
poetry run isort . # import 排序
poetry run ruff check . # lint
poetry run pyright # 类型检查
注意:测试文件必须放在
tests/,不要放进test/——pyproject.toml中test是插件目录,NoneBot 启动时会把其中所有文件当插件加载。
新增插件请参考:
许可
无
Languages
Python
66.4%
HTML
26.7%
TypeScript
6.1%
CSS
0.5%
Jinja
0.2%