# Velox Bot A Discord bot written in Go with a PostgreSQL backing store. It currently includes: - Fun commands (`/ping`, `/joke`, `/dice`, `/rps`, …) - Leveling system (opt-in per server via `/slvl toggle`) - Meeting rooms (voice lobby → auto-created temporary voice channels) - Scheduling (1:1 sessions with DM invites + reaction-based accept/decline/reschedule) - Projects (list/create projects + helpers) - Support tickets (a panel with categories, a private thread per ticket, claim/close, transcripts to a log channel) - Anti-raid and anti-nuke (Join Gate, raid mode, quarantine of anyone who mass-deletes or mass-bans, lockdowns), modelled on Wick - Music (Lavalink-powered `/play`, `/queue`, `/volume`) - Twitch live notifications (per-guild `/config` setup) - Welcome messages, DMs, and default role assignment (per-guild `/config` setup) - Focused moderation tools (`/moderation purge|timeout|untimeout|kick|ban|unban|slowmode`) - Server logging system (edits/deletes/joins/leaves/roles/ban/kick/mod actions) When the bot is added to a new server for the first time, toggleable systems are defaulted to **disabled** and a setup DM is sent to the inviter (or server owner fallback) with enable instructions. ## Requirements - Go (see `go.mod`) - PostgreSQL 16+ (or use the provided `docker-compose.yml`) - (Optional) [Air](https://github.com/air-verse/air) for live reload during development - (Optional) Lavalink if you want music commands ## Configuration The app loads environment variables from `.env` (see `internal/config/config.go`). Required: - `BOT_TOKEN`: Discord bot token - `APP_ID`: Discord application ID - `GUILD_ID`: Target guild/server ID (commands are registered per-guild) - `BETA_GUILD_ID`: Server where beta features exist (defaults to the Velox server) - `BETA_ROLE_ID`: ID of the "Beta Tester" role. Beta features work only for members of the beta server who have this role; if unset, they stay locked for everyone - `DB_HOST`: Postgres connection string (pgx), e.g. `postgres://velox:velox_pwd@localhost:5432/velox?sslmode=disable` Optional (music): - `LAVALINK_HOST`: Lavalink WebSocket/HTTP host (depends on your Lavalink setup) - `LAVALINK_PASSWORD`: Lavalink password Optional (Twitch live notifications): - `TWITCH_CLIENT_ID`: Twitch Client ID used to query live status ## Database setup If you use the compose file: ```bash docker compose up -d ``` Then apply the schema: ```bash psql "postgres://velox:velox_pwd@localhost:5432/velox?sslmode=disable" -f schema.sql ``` ## Run Plain Go: ```bash go run . ``` With live reload (Air): ```bash air ``` If you use `just`, a small workflow is included: ```bash just up # start postgres just start # start postgres + run air just down # stop postgres ``` ## Commands (high-level) - **Fun** - `/ping`, `/joke [type]`, `/coinflip`, `/dice ` - `/rps `, `/rpsstats`, `/rpsleaderboard` (server only) - **Help** - `/help` (sends a DM with command reference) - **Leveling** - `/slvl ...` admin/config - `/rank`, `/leaderboard`, `/rewards` - **Meetings** (**Manage Server**) - `/meeting add-lobby`, `/meeting remove-lobby`, `/meeting lobbies` (up to 10 lobby channels per server), `/meeting lock`, `/meeting lock-private`, `/meeting unlock`, `/meeting invite`, `/meeting uninvite` - **Timezone** - `/timezone set`, `/timezone show` - **Scheduling** - `/schedule create`, `/schedule list`, `/schedule reschedule` - **Projects** - `/projects list`, `/projects create`, `/projects add-helper` - **Tickets** - `/tickets setup channel:#tickets [log-channel] [staff-role]` — Where tickets open and closed ones are logged (**Manage Server**) - `/tickets category add|remove|list` — One entry in the panel's dropdown per category, each with its own staff role (**Manage Server**) - `/tickets panel` — Post or refresh the panel (**Manage Server**) - `/ticket add`, `/ticket close [reason]` — Opener or staff; `/ticket claim`, `/ticket remove` — staff - The bot needs View Channel, Send Messages, Embed Links, Create Private Threads, Send Messages in Threads and Manage Threads in the ticket channel, and Attach Files in the log channel. Give the staff role Manage Threads there too, so staff see every ticket. - **Security** (anti-raid and anti-nuke; everything is off until turned on) - `/security status`, `/security toggle feature on`, `/security alerts channel [role]` - `/security trust add|remove user|role` — owner only; trusted members are exempt from anti-nuke and may change security settings - `/security release user`, `/security quarantined`, `/security end-raid`, `/security quarantine-role` - `/lockdown channel|server|joins`, `/unlock channel|server|joins` — unlocking needs the owner or a trusted member - `/security snapshot`, `/security restore` — snapshots of roles and channels are also taken every 6 hours while anti-nuke is on (last three kept); restore recreates deleted roles and channels and reverts dangerous permission changes, and can run automatically after a stopped nuke - Heat (anti-spam): messages build a per-member score that cools over time; spam, repeats, mass mentions and invite links max it, which deletes the message and times the member out (doubling for repeat offences). A wave of spammers turns on heat panic (newcomers timed out on sight for 10 minutes); a mention flood can lock the server. Moderators (Manage Messages) and trusted members are exempt. - Raid mode survives a bot restart. - Critical alerts (raids, stopped nukes, restores, spam waves, removed bots) are also DMed to the owner and trusted users (up to 10; trusted roles aren't expanded), since the alert channel may be the first thing a nuker deletes. One setting turns this off. - Join Gate filters, raid thresholds, anti-nuke limits and heat settings are set on the dashboard. - The bot needs View Audit Log, Manage Roles, Manage Channels, Manage Server (to pause invites), Moderate Members, Kick Members and Ban Members, and its role must be above the roles it protects against: it can only quarantine members whose highest role is below its own. - Turning things off, unlocking and releasing always need the owner or someone on the trusted list, whatever Discord's command permissions say. - **Music** (requires **DJ** role) - `/play`, `/queue`, `/volume` - **Moderation** (focused + practical) - `/moderation purge amount:<1-100>` — Fast recent message cleanup (**Manage Messages**) - `/moderation timeout user:@someone duration:<10m|1h|...> [reason]` — Temporary member timeout (**Moderate Members**) - `/moderation kick user:@someone [reason]` — Kick member (**Kick Members**) - `/moderation ban user:@someone [delete_days] [reason]` — Ban member (**Ban Members**) - `/moderation unban user_id: [reason]` — Unban by user ID (**Ban Members**) - `/moderation untimeout user:@someone [reason]` — Remove timeout (**Moderate Members**) - `/moderation slowmode channel:#channel seconds:<0-21600>` — Control channel flood (**Manage Channels**) - **Twitch live notifications** (**Manage Server**) - `/config addstreamer username:` — Add a streamer for notifications - `/config removestreamer username:` — Remove a streamer - `/config settwitchnotificationchannel channel:#channel` — Channel for live pings - **Welcome / onboarding** (**Manage Server**) - `/config setwelcomechannel channel:#channel` — Channel for welcome messages - `/config setwelcomemessage message:"..."` — Server welcome template (supports `{user}`, `{server}`) - `/config setwelcomedm message:"..."` — DM welcome template (supports `{user}`, `{server}`) - `/config setwelcomegif url:` — GIF/image used in welcome embed - `/config setdefaultrole role:@role` — Role automatically granted on join - **Logging** (**Manage Server**) - `/config setlogchannel channel:#channel` — Set where logs are sent - `/config enablelogging` — Enable event/moderation logs - `/config disablelogging` — Disable event/moderation logs ## Notes - Slash commands are registered to the configured `GUILD_ID` on startup. - Beta features: add the command with `commands.RegisterBeta(cmd, handler)` instead of `AllCommands`. It is registered only in `BETA_GUILD_ID` and the handler runs only for members with `BETA_ROLE_ID`. `/beta` (bot owner only) shows how access is set up. To release a feature, move it into `AllCommands` and the handler map. - Some features require server permissions (e.g. **Manage Server**) or roles (e.g. **DJ** for music).