265 lines
7.2 KiB
Markdown
265 lines
7.2 KiB
Markdown
# 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`.
|