这是一个从零搭的 Discord Bot + FastAPI 项目,目标是做成偏娱乐向的 DC 机器人,同时带一个简单可视化控制台。
AI 对话- Discord 命令:
/ai chat(支持可选图片) - FastAPI 路由:
POST /api/ai/chat
- Discord 命令:
AI 总结对话- Discord 命令:
/ai summary - FastAPI 路由:
POST /api/ai/summary
- Discord 命令:
AI 绘图- Discord 命令:
/ai draw - FastAPI 路由:
POST /api/ai/draw、POST /api/ai/draw/result
- Discord 命令:
Danbooru 随机找图- Discord 命令:
/fun danbooru - Danbooru 登录信息从环境变量读取
- NSFW 频道默认
rating:e,非 NSFW 频道强制rating:s
- Discord 命令:
图站档案与用户偏好- 支持
danbooru/rule34 - 支持为美图和涩图分别设置默认图站与默认 tag
- 支持
@机器人 来张美图/@机器人 来张色图
- 支持
搬屎交税- 别人给带图消息点到配置的
shitemoji 时,触发警告 - 管理员回复某条带图消息
税/交税/补税也可手动触发 - 被点名的人需要去税务频道补发 3 张图
- 超时未交税自动禁言 1 小时
- 别人给带图消息点到配置的
其他娱乐功能/fun fortune今日运势/fun coin抛硬币/fun eightball是非题/fun waifu今日老婆/老公(safe 二次元角色图)- 欢迎消息
- 答题自助身份组
/fun leaderboard榜单
可视化面板GET /dashboard- 查看状态、改全局设置、改服务器设置、测试 AI、看挂起税单
app/
api/routes/ FastAPI 路由
bot/ Discord Bot 逻辑
core/ 环境变量与配置目录
models/ 状态模型
services/ OpenRouter / Danbooru / 状态存储 / 娱乐逻辑
web/ Dashboard 模板和静态资源
复制 .env.example 为 .env 后填写:
DISCORD_TOKEN=你的机器人 token
DISCORD_TEST_GUILD_ID=测试服务器 ID,可选
AI_PROVIDER_FILE=data/providers.json
PERSONA_FILE=data/personas.json
GRSAI_BASE_URL=https://grsaiapi.com/v1
GRSAI_DRAW_BASE_URL=https://grsaiapi.com/v1
GRSAI_API_KEY=你的 grsai 聊天 key
GRSAI_DRAW_API_KEY=你的 grsai 绘图 key
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
OPENROUTER_API_KEY=你的 OpenRouter key
OPENROUTER_SITE_URL=
OPENROUTER_SITE_NAME=
CUSTOM_BASE_URL=
CUSTOM_DRAW_BASE_URL=
CUSTOM_CHAT_API_KEY=可选的自定义聊天 key
CUSTOM_DRAW_API_KEY=可选的自定义绘图 key
DANBOORU_USERNAME=你的 danbooru 用户名
DANBOORU_API_KEY=你的 danbooru api key
RULE34_API_BASE_URL=https://api.rule34.xxx
RULE34_POST_BASE_URL=https://rule34.xxx
RULE34_USER_ID=你的 rule34 用户 id
RULE34_API_KEY=你的 rule34 api key
SAUCENAO_BASE_URL=https://saucenao.com/search.php
SAUCENAO_API_KEY=你的 SauceNAO key说明:
.env现在只建议存放 URL、token、api key 这类环境信息。data/providers.json负责声明“渠道”和“模型档案”,每个档案会绑定type / provider / adapter / model。data/personas.json负责声明“机器人人设档案”,包括 system prompt、summary prompt 和 fun 文案。- 聊天目前统一按
OpenAI 兼容 /chat/completions走;绘图目前支持grsai_draw_completions和grsai_draw_nano_banana两种适配器。 state.json只负责记录当前选中的chat_model_profile / draw_model_profile和群设置。- 老配置仍然兼容,默认会自动映射到
legacy-chat / legacy-draw。 STATE_FILE默认是data/state.json,机器人运行后的设置和统计会持久化到这里。
pixi install
pixi run check
pixi run dev如果 pixi 默认缓存目录权限有问题,可以改用项目内缓存:
set PIXI_CACHE_DIR=%CD%\.pixi-cache
pixi install
pixi run check
pixi run dev常用命令:
pixi run check:检查项目能否正常导入pixi run dev:开发模式启动 FastAPI,读取.env里的HOST/PORTpixi run start:普通启动,读取.env里的HOST/PORT
docker compose pull
docker compose up -d默认使用 Docker Hub 镜像 moeary/discord_bot:0.1.0。Docker 容器会读取 .env,并把 ./data 挂载到 /app/data。对外部署时建议设置:
HOST=0.0.0.0
PORT=8000
MINECRAFT_TOKEN=强随机 token
MINECRAFT_ALLOW_NO_TOKEN=false
MINECRAFT_ALLOWED_CLIENTS=Paper服务器IP或CIDR如果在 Windows 上通过 WSL2 编译/推送镜像,可以在仓库根目录执行:
wsl docker build -t moeary/discord_bot:0.1.0 .
wsl docker login
wsl docker push moeary/discord_bot:0.1.0python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
uvicorn app.main:app --reload启动后:
- 面板地址:
http://127.0.0.1:8000/dashboard - 健康检查:
http://127.0.0.1:8000/api/health
GET /dashboardGET /docsGET /api/healthGET /api/dashboardGET /api/docs
POST /api/ai/chat(支持image_urls)POST /api/ai/summary(默认不读图片提示)POST /api/ai/drawPOST /api/ai/draw/result
GET /api/settings/globalPATCH /api/settings/globalGET /api/settings/guild/{guild_id}PATCH /api/settings/guild/{guild_id}
GET /api/tax/pendingGET /api/stats/{guild_id}
/ai chat prompt:<内容> image:<可选图片> profile:<可选档案>/ai summary limit:<消息数>/ai draw prompt:<可留空> image:<可选图片> profile:<可选档案> model:<可选覆盖> size:<可选> variants:<1|2>
/fun image style:<safe|explicit> tags:<可选> profile:<可选图站档案>/fun danbooru tags:<标签>/fun rule34 tags:<标签>/fun pretty tags:<可选> profile:<可选图站档案>/fun lewd tags:<可选> profile:<可选图站档案>/fun image_prefs/fun image_source style:<safe|explicit> profile:<档案>/fun image_tags style:<safe|explicit> tags:<标签>/fun image_sites/fun sauce image:<可选图片> url:<可选图片链接>/fun fortune/fun coin/fun eightball/fun waifu/fun ship/fun duel/fun leaderboard
/minecraft bind username:<Minecraft 用户名>/minecraft unbind/minecraft status
/config view/config set key:<配置项> value:<值>
chat_model_profilechat_fallback_profilesdraw_model_profiledraw_fallback_profilespersona_profilemax_chat_history
ai_enabledfun_enabledtax_enabledminecraft_bridge_enabledminecraft_server_idminecraft_server_addressminecraft_channel_idminecraft_tokenminecraft_allow_no_tokenminecraft_max_message_lengthwelcome_channel_idwelcome_textverification_channel_idverification_role_idverification_questionverification_answerverification_success_texttax_channel_idlog_channel_idshit_emojitax_required_imagestax_payment_window_minutesmute_hourssummary_limitdanbooru_default_tagssafe_image_site_profileexplicit_image_site_profilesafe_image_default_tagsexplicit_image_default_tagswarn_text
{user_mention}{tax_channel}{minutes}{required_images}{mute_hours}
FastAPI 侧新增了 /api/minecraft/... 接口,Paper 插件工程在 paper-bridge/。插件默认是关闭的,只有 plugins/DcBotPaperBridge/config.yml 里 enabled: true 时才会轮询 FastAPI。插件只保留很薄的配置:enabled、api-base-url、server-id、token、轮询间隔和消息格式;Discord guild、频道、token、绑定关系都在 FastAPI/机器人状态里配置。
构建插件:
cd paper-bridge
./gradlew buildWindows PowerShell 下用 .\gradlew.bat build。
生成的 jar 在 paper-bridge/build/libs/。GitHub Actions 里的 Paper Bridge Jar workflow 只支持手动触发:进仓库网页的 Actions 页面,选择这个 workflow,点 Run workflow 并填版本号。它会上传 Actions artifact,并默认发布到 GitHub Release,release tag 使用 paper-bridge-v<版本号>,和主项目 v* tag 分开。
最小配置:
- 在
.env里设置:MINECRAFT_BRIDGE_ENABLED=trueMINECRAFT_GUILD_ID=<Discord 服务器 ID>MINECRAFT_SERVER_ID=defaultMINECRAFT_SERVER_ADDRESS=127.0.0.1:30001MINECRAFT_CHANNEL_ID=<要同步的 Discord 文本频道 ID,不是服务器 ID>MINECRAFT_TOKEN=<可选,和插件一致>MINECRAFT_ALLOWED_CLIENTS=<可选,Paper 来源 IP/CIDR 白名单>
- 在 Paper 插件配置
plugins/DcBotPaperBridge/config.yml里设置:enabled: trueapi-base-url: "http://127.0.0.1:8000"server-id: "default"token: "<和 FastAPI 一致,可空>"
- 用户用
/minecraft bind <username>绑定身份;Discord 同步到游戏时会显示为<username> 消息。
MINECRAFT_GUILD_ID 可以不填:没填时会优先复用 DISCORD_TEST_GUILD_ID,或者按 MINECRAFT_CHANNEL_ID 对应的 Discord 频道自动判断。
如果 minecraft_token 留空,FastAPI 只允许本机、内网或链路本地地址直连,并且仍会做 server_id 校验、消息长度限制和短窗口限速。跨公网时建议同时设置 MINECRAFT_TOKEN、MINECRAFT_ALLOW_NO_TOKEN=false 和 MINECRAFT_ALLOWED_CLIENTS,例如 203.0.113.10 或 203.0.113.0/24。
Rule34 现在的 API 访问需要 user_id + api_key。代码已经按这个格式接好了,你只要把它们填进 .env 里的 RULE34_USER_ID 和 RULE34_API_KEY。
建议流程:
- 注册并登录 rule34.xxx。
- 打开账号设置页:https://rule34.xxx/index.php?page=account&s=options
- 找到
API Access Credentials。 - 如果还没看到 key,就勾
Generate New Key?然后保存。 - 长字符串是
api_key,短数字是user_id。 - 分别填进项目
.env。
我参考了这些资料来核对当前流程:
- AI 的系统提示词和总结提示词现在完全来自
data/personas.json里的当前persona_profile。 - 你后面如果要切 RP,只要新增 persona,然后把
persona_profile切过去就行。 /config set现在会按 key 自动判断写入 guild 还是 global,不用再手填scope。- 回复机器人消息会自动触发 AI 对话,并携带上一条 AI 回复与当前用户回复作为上下文。
- 直接
@机器人说话也会触发 AI,对回复某条消息的场景会优先理解那条被回复的消息。 /ai chat和@机器人对话支持读图;/ai summary默认只总结文字,不猜图片内容。/ai draw现在支持“只带参考图不写 prompt”的改图模式;右键消息GLaDOS 改图也能直接对某条图片消息起手。- 不用 slash 的情况下,也可以直接
@机器人或回复机器人来聊天、绘图、改图、搜图、来张美图/色图、看运势、抛硬币、问 8ball、抽老婆。 - 当主 AI 渠道失败时,会自动尝试 fallback 渠道,并直接把失败原因显示出来。
- 浏览器里的命令文档在
/docs;FastAPI 的 Swagger 被挪到了/api/docs。 搬屎交税支持“发图消息 + 点指定 emoji”触发,也支持管理员回复关键字手动触发。- 补税逻辑默认只认税务频道里的图片附件和常见图片链接。
- 如果没有配置
tax_channel_id,机器人仍会警告,但你最好尽快配置税务频道。