Discord bot for the unorouter community. A slim derivative of the coding.global bot that reuses its AI-chat and moderation engines, plus a ticket system, a bug-report forum, and a balance-grant integration with new-api.
- AI chat - mention the bot (or reply to it, or start a message with its name) and it answers via Google Gemini, with key rotation + model fallback. Optional meme-GIF tool.
- Moderation - AI first-message spam detection, duplicate + cross-channel spam detection, jail role + message cleanup.
- Leveling - message-count based level roles (
LEVEL_ROLES), with self-assign protection onguildMemberUpdate. - Tickets -
/ticket-panelposts a panel with "Open Ticket" / "Report a Bug" buttons. Tickets are private threads, transcripted toTICKET_LOG_CHANNELon close. Staff controls: Claim, Approve & Reward, Close. - Bug reports - both a ticket category and a public forum (
BUG_REPORT_FORUM_CHANNEL). New forum threads get staff "Approve & Reward" / "Reject" buttons. - Balance grants - staff reward users who linked their Discord on unorouter. Repeatable.
Triggers:
/grant, ticket/bug "Approve & Reward" buttons, and automatic on server boost (BOOST_GRANT_QUOTA). Every grant is recorded inGrantLog.
Cloned from the coding.global bot:
- discordx
Client+ decorator registry (@Discord/@On/@Slash/@ButtonComponent/@ModalComponent). - Every
src/bot/**file is imported insrc/bot/index.ts;tsup.config.tsfails the build if any decorated file is missing or stale. - Layering:
bot/(thin) ->core/handlers->core/services->core/embeds. lib/db.tsis a postgres-js + drizzle singleton; schema insrc/lib/db-schema.
- User clicks a staff "Approve & Reward" button (or staff runs
/grant, or a boost fires). - The bot POSTs
${NEW_API_URL}/api/user/discord_grantwithAuthorization: Bearer ${NEW_API_ADMIN_TOKEN}(a new-api admin user's access token) and body{ discord_id, quota }. - new-api resolves the user by Discord ID (
FillUserByDiscordId) and, if linked, adds quota (IncreaseUserQuota). It returns{ linked, user_id }. - On
linked: truethe bot writes aGrantLogrow and announces inGRANT_LOG_CHANNEL. Onlinked: falsethe user is told to link their Discord on unorouter first.
NEW_API_URL should be the internal service URL on the proxy network
(e.g. http://unorouter-new-api:3000) so grants never leave the host.
bun install
cp .env.example .env # fill in TOKEN, DATABASE_URL, etc.
bun run db:push # sync schema to your Postgres
bun run devbun run build # tsup -> dist/main.js (also runs the bot-imports check)Deployed on the don host via GitHub Actions (.github/workflows/docker.yml), self-hosted
runner: it writes .env from repo secrets and runs docker compose up -d --force-recreate --build.
Never ship images manually. The new-api endpoint ships through new-api's own CI.