# Discord Bot for Open Mic Odyssey A modular Discord bot + admin platform that syncs community engagement between Discord and [openmicodyssey.com](https://openmicodyssey.com). The system includes onboarding roles, stage queue management, mileage progression, content syndication, an admin API, and a React admin dashboard. ## Core Features ### The Call Sheet (Onboarding + Roles) - Reaction-role onboarding message with emoji-to-role bindings - Role hierarchy safety checks before assignment/removal - Optional onboarding completion role and welcome-channel message ### The Tour Schedule (Stage Queue) - `/sign-up` subcommands: `join`, `leave`, `list`, `next`, `clear` - FIFO queue per guild - Optional stage-speaker promotion and queue announcement dispatch ### The Dailies (Content Syndication) - Adapter-based polling pipeline - YouTube RSS adapter implemented - Discord webhook dispatch with duplicate suppression ### Mileage Engine - PostgreSQL-backed mileage event/user persistence - Configurable event scoring - Role-tier upgrades on threshold milestones - Retry behavior for transient write failures ### Admin API + Dashboard - Express Admin API for config, queue, stats, OAuth bridge, configuration DB - React/Vite dashboard for OAuth login + analytics views ### OAuth2 Bridge - Discord OAuth2 code exchange to user profile - Ephemeral session issuance - Optional sync callback to openmicodyssey.com backend ### Configuration Database - `bot_settings`, `content_schedules`, `engagement_stats` tables - Admin CRUD endpoints for settings/schedules - Engagement snapshot persistence from runtime events ## Implemented Modules - `src/bot.ts`: gateway client lifecycle, command dispatch, service wiring - `src/call-sheet.ts`: reaction role onboarding and role hierarchy guards - `src/tour-schedule.ts`: FIFO queue, stage speaker promotion, announcements - `src/mileage.ts`: mileage persistence, scoring, role-upgrade triggers - `src/dailies/*`: adapter/poller/webhook syndication pipeline - `src/admin-api.ts`: operational and configuration endpoints - `src/oauth-bridge.ts`: Discord code exchange + openmic session sync - `src/configuration-database.ts`: bot settings, schedules, engagement snapshots - `admin-dashboard/src/*`: admin SPA, OAuth callback flow, analytics views ## Architecture Documentation (arc42) This project uses the arc42 template. Chapters are in `docs/`. ## Architecture & Tech Stack | Layer | Choice | | --------------- | -------------------- | | Runtime | Node.js + TypeScript | | Discord SDK | discord.js | | Database | PostgreSQL | | Admin API | Express | | Admin Dashboard | React + Vite | | Auth | Discord OAuth2 | | Hosting | Coolify + Nixpacks | ## Getting Started ### Prerequisites - Node.js 22+ - npm 10+ - Discord Developer Application (bot token + OAuth2 app) - PostgreSQL instance - Discord server where you can install bots with role/channel permissions ### Discord Bot Setup (Portal) 1. Open Discord Developer Portal and create a new application. 2. In `Bot` tab, click `Add Bot`. 3. Copy these values for runtime config (`bot_settings`): - `DISCORD_TOKEN` from Bot tab (Reset Token if needed) - `DISCORD_CLIENT_ID` from OAuth2 > General - `OAUTH_BRIDGE_REDIRECT_URI` as exact callback URL, recommended: `https://admin.openmicodyssey.com/oauth/discord/callback` 4. In `Bot` > `Privileged Gateway Intents`, enable only: - `Server Members Intent` (required by current code) 5. Keep these disabled unless code changes require them: - `Message Content Intent` - `Presence Intent` Current gateway intents used by this project (`src/bot.ts`): - `Guilds` - `GuildMembers` (privileged) - `GuildMessageReactions` ### Discord Bot Install (OAuth2 URL) 1. Open `OAuth2` > `URL Generator`. 2. Select scopes: - `bot` - `applications.commands` 3. Select bot permissions (minimum recommended for current features): - `View Channels` - `Send Messages` - `Read Message History` - `Add Reactions` - `Manage Roles` (call-sheet role assignment) - `Manage Channels` (queue moderation paths) 4. Use generated URL to add bot to your server. ### Installation 1. Clone repository: ```bash git clone https://git.allucanget.biz/allucanget/omo-bot.git cd omo-bot ``` 2. Install root dependencies: ```bash npm install ``` 3. Configure bootstrap environment variables (`.env` from `.env.example`): ```env DATABASE_URL=postgres://... CONFIG_DB_ENABLED=true DISCORD_GUILD_ID=... # optional seed scope ``` 4. Register slash commands: ```bash npm run register:commands ``` 5. Run bot in development: ```bash npm run dev ``` 6. Build and run production bundle: ```bash npm run build npm start ``` ### Admin Dashboard ```bash cd admin-dashboard npm install npm run dev ``` Dashboard environment template: `admin-dashboard/.env.example`. Recommended production OAuth callback URL: - `https://admin.openmicodyssey.com/oauth/discord/callback` This same URL must match: - Discord OAuth2 redirect whitelist - `VITE_DISCORD_REDIRECT_URI` - `OAUTH_BRIDGE_REDIRECT_URI` ### Validation Commands ```bash npm run lint npm run build npm run test ``` ### Database Setup Commands `DATABASE_URL` is required for each command. ```bash npm run db:migrate npm run db:seed npm run db:setup ``` - `db:migrate`: applies schema migrations tracked in `schema_migrations` - `db:seed`: ensures migrations are applied, then inserts initial config values from environment into `bot_settings` when missing - `db:setup`: runs migrate then seed ### Runtime Config Source Runtime reads configuration keys from `bot_settings` table first, then falls back to environment values. - Global scope: `guild_id = __global__` - Guild override scope: `guild_id = DISCORD_GUILD_ID` - Key names match previous env variable names (examples: `DISCORD_TOKEN`, `DISCORD_CLIENT_ID`, `ADMIN_API_TOKEN`) Recommended flow: 1. Set bootstrap env (`DATABASE_URL`, optional `DISCORD_GUILD_ID`). 2. Run `npm run db:migrate`. 3. Run `npm run db:seed` once while legacy env vars are still present. 4. Remove legacy runtime vars from `.env` after confirming `bot_settings` contains required keys. ### Deployment Deployment setup and domain configuration moved to `DEPLOYMENT.md`. - Coolify project/resource setup - Real domain DNS/TLS and routing patterns - Discord OAuth production redirect alignment - Gitea Actions secret configuration for deploy hooks - Two-resource deploy flow (`omo-bot-backend` + `omo-bot-dashboard`) Dashboard quality check: ```bash cd admin-dashboard npm run lint npm run build ``` ## Admin API Endpoints - `GET /health` - `GET /admin/config` - `GET /admin/stats?guildId=...` - `GET /admin/schedule?guildId=...` - `POST /admin/schedule/clear` - `POST /admin/oauth/discord/exchange` - `GET /admin/oauth/session/:sessionId` - `GET /admin/db/settings?guildId=...` - `PUT /admin/db/settings` - `GET /admin/db/schedules?guildId=...` - `PUT /admin/db/schedules` - `DELETE /admin/db/schedules/:guildId/:scheduleKey` - `GET /admin/db/engagement/latest?guildId=...` ## CI/CD (Gitea Actions) Pipeline file: `.gitea/workflows/ci-cd.yml` For full deployment flow, webhook secret strategy, and two-resource Coolify deployment, see `DEPLOYMENT.md`. ## Contributing Internal development only. See `CONTRIBUTING.md`.