Siren

Siren

A D&D-focused Discord bot written in Rust

--- ## Features - Music playback from YouTube via slash commands - Dice rolling with D&D notation (e.g. `/roll 2d6+3`) - Session scheduling - REST API with OAuth2 authentication --- ## Prerequisites ### Running with Docker (recommended) | Tool | Notes | |-----------------------------------|---------------------------------------------| | [Docker](https://www.docker.com/) | Required | | [Task](https://taskfile.dev/) | Optional — used to run convenience commands | ### Running locally (development) | Tool | Notes | |---------------------------------------------------|---------------------------------------------| | [Rust](https://www.rust-lang.org/tools/install) | Stable toolchain | | [yt-dlp](https://github.com/yt-dlp/yt-dlp) | Audio source extraction | | [ffmpeg](https://github.com/yt-dlp/FFmpeg-Builds) | Audio transcoding | | [Docker](https://www.docker.com/) | Used to run PostgreSQL and Valkey | | [Task](https://taskfile.dev/) | Optional — used to run convenience commands | > **yt-dlp note:** Keep yt-dlp up to date. YouTube frequently rotates its player, > and an outdated yt-dlp will fail to resolve stream URLs. --- ## Configuration Copy `.env.example` to `.env` and fill in the required values: ```bash cp .env.example .env # or using Task: task setup ``` ### Environment variables | Variable | Required | Description | |--------------------------|----------|---------------------------------------------------------------------------| | `DISCORD_BOT_TOKEN` | Yes | Bot token from the Discord Developer Portal | | `DISCORD_CLIENT_SECRET` | Yes | OAuth2 client secret | | `JWT_SECRET` | Yes | Secret used to sign JWT tokens — change from default | | `POSTGRES_USER` | Yes | PostgreSQL username | | `POSTGRES_PASSWORD` | Yes | PostgreSQL password — change from default | | `POSTGRES_DB` | Yes | PostgreSQL database name | | `POSTGRES_HOST` | Yes | PostgreSQL host (`localhost` for local dev, `siren-postgres` in Docker) | | `POSTGRES_PORT` | | PostgreSQL port (default `5432`) | | `VALKEY_HOST` | | Valkey host (`localhost` for local dev, `siren-valkey` in Docker) | | `VALKEY_PORT` | | Valkey port (default `6379`) | | `API_BASE_URL` | Yes | Base URL of the API (e.g. `http://localhost:3000`) | | `API_PORT` | | Port the REST API listens on (default `3000`) | | `API_SESSION_TTL` | | OAuth2 session TTL in seconds (default `86400`) | | `CORS_ORIGIN` | | Allowed CORS origin (`*` for dev, specific URL for production) | | `UI_PORT` | | Port the UI dev server listens on (default `5173`) | | `RUST_LOG` | | Log filter (e.g. `warn,siren=info`) | | `FORCE_COMMAND_REGISTER` | | Re-register slash commands with Discord on every startup (`true`/`false`) | | `DATA_DIR_PATH` | | Path to optional local data directory | | `DEFAULT_API_KEY` | | Seed API key created on startup | | `DEFAULT_GUILD_ID` | | Seed Discord guild (server) ID | | `DEFAULT_USER_ID` | | Seed Discord user ID | --- ## Discord Application Setup 1. Visit the [Discord Developer Portal](https://discord.com/developers/applications) and create a new application. 2. Go to the **Bot** tab: - Click **Reset Token** to generate your bot token — this is your `DISCORD_BOT_TOKEN`. - Enable **Message Content Intent** under Privileged Gateway Intents. ![Token location](docs/discord_token_example.png) 3. Go to the **OAuth2** tab to find your **Client Secret** (`DISCORD_CLIENT_SECRET`). ### Invite the bot to your server **Required scopes:** `bot`, `applications.commands` **Required permissions:** | Category | Permissions | |----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | General | Manage Roles, Change Nickname, View Channels, Manage Events, Create Events | | Text | Send Messages, Create Public/Private Threads, Send Messages in Threads, Manage Messages, Manage Threads, Embed Links, Attach Files, Read Message History, Mention Everyone, Use External Emojis/Stickers, Add Reactions, Create Polls | | Voice | Connect, Speak | Use this invite URL (replace `` with your Application ID from the General Information tab): ``` https://discord.com/oauth2/authorize?client_id=&permissions=581083641408576&integration_type=0&scope=bot+applications.commands ``` --- ## Running ### Docker (recommended) Build and start all containers: ```bash # Build the Docker image task docker:build # or: docker build -f Dockerfile -t siren:latest . # Start all services (postgres, valkey, and the app) task docker:up:all # or: docker compose --profile app up -d ``` To stop everything: ```bash task docker:down # or: docker compose --profile app down ``` ### Local development Start the backing services (PostgreSQL and Valkey) in Docker, then run the bot natively: ```bash # Start only the infrastructure containers task docker:up # or: docker compose up -d # Run the bot locally with trace-level logging task run # or: cargo run ``` --- ## Commands Siren uses Discord slash commands. ### Music | Command | Description | Status | |-------------------|-------------------------------------|---------| | `/play ` | Play a track from YouTube | Done | | `/pause` | Pause the current track | Done | | `/resume` | Resume the current track | Done | | `/skip` | Skip to the next track | Done | | `/stop` | Stop playback and clear the queue | Done | | `/mute` | Mute/unmute the bot | Done | | `/volume <0–100>` | Set the playback volume | Done | | `/queue` | Display the current queue | Planned | | `/nowplaying` | Display the currently playing track | Planned | | `/shuffle` | Shuffle the queue | Planned | | `/loop` | Toggle looping the current track | Planned | | `/clear` | Clear the queue | Planned | ### Events | Command | Description | Status | |-------------|------------------------------|---------| | `/schedule` | Schedule a new event | Planned | | `/events` | Display all scheduled events | Planned | ### Fun | Command | Description | Status | |------------------------------|---------------------------------------|--------| | `/roll ` | Roll dice (e.g. `2d6+3`) | Done | | `/requestroll ` | Request a dice roll from another user | Done | ### Utility | Command | Description | Status | |---------|----------------------------|---------| | `/ping` | Check the bot's latency | Done | | `/help` | Display available commands | Planned | --- ## Development | Task | Command | |------------------------|----------------| | Type-check (fast) | `task check` | | Debug build | `task build` | | Release build | `task release` | | Run with trace logging | `task run` | | Format code | `task format` | | Lint (Clippy) | `task lint` | | Clean build artifacts | `task clean` | | Connect to database | `task psql` | Run `task` with no arguments to list all available tasks.