Files
omo-bot/README.md
T
zwitschi 8041a39dfd
CI-CD / Bot Lint Test Build (push) Failing after 2m10s
CI-CD / Dashboard Lint Build (push) Successful in 17s
CI-CD / Deploy to Coolify (push) Has been skipped
feat: Implement Tour Schedule Engine with queue management and announcement features
- Added TourScheduleEngine class for managing user queues in a guild.
- Implemented methods for joining, leaving, listing, and clearing queues.
- Added functionality to promote users to speaker in a stage channel and send announcements.
- Created integration tests for the TourScheduleEngine to verify FIFO behavior and announcement dispatch.

test: Add unit tests for ping and sign-up commands

- Created tests for ping command to ensure it replies with "Pong!".
- Implemented tests for sign-up command to verify queue joining, listing, and permission checks.

test: Add integration tests for mileage engine flow

- Developed tests to validate mileage awarding, event persistence, and role upgrades based on mileage thresholds.

chore: Update TypeScript configuration for ESLint

- Added tsconfig.eslint.json for ESLint integration.
- Modified tsconfig.json to exclude test files from the main compilation.
2026-05-17 17:02:23 +02:00

218 lines
5.6 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
### 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`.
### 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`: 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.
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`
Flow:
- bot checks: `npm ci -> npm run lint -> npm run build -> npm run test`
- dashboard checks: `admin-dashboard/npm ci -> npm run lint -> npm run build`
- deploy: on push to `main`, trigger Coolify deploy webhook
Required Gitea secrets:
- `COOLIFY_DEPLOY_HOOK_URL` (required)
- `COOLIFY_DEPLOY_TOKEN` (optional bearer token)
## Contributing
Internal development only. See `CONTRIBUTING.md`.