Files
siren/README.md

208 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div align="center">
<img src="docs/siren.png" alt="Siren" width="200"/>
<h1 align="center">Siren</h1>
<p>A D&D-focused Discord bot written in Rust</p>
</div>
---
## 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 `<CLIENT_ID>` with your Application ID from the General Information tab):
```
https://discord.com/oauth2/authorize?client_id=<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 <track>` | 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 <0100>` | 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 <dice>` | Roll dice (e.g. `2d6+3`) | Done |
| `/requestroll <user> <dice>` | 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.