- /help is sent as a few messages (Discord caps an embed at 6000 characters), with a test for the limits
- command reference, features, self-hosting, beta and getting-started pages describe the commands; the SQL section is gone
- development and contributing: every setting needs a command
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
- /tickets settings (on or off, panel title and text, open tickets per member), /tickets category edit, /tickets list
- schema.sql now creates the NOTIFY triggers, so the integration tests run on a database built from it, and two stale expectations (tickets start off) are fixed
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
- /security settings, joingate check|account-age, words add|remove|list, raid, antinuke set|limit, heat, alert-dms
- Same rule as the rest of the configuration: owner or trusted, validated in the engine
- schema.sql was missing security_settings.alert_dm, so the bot couldn't read security settings on a database built from it. Fixed, with an ALTER for existing installs
- A test checks every command against Discord's limits
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
- README, license section and architecture no longer point to the dashboard repositories
- schema.sql is the schema for contributors; database changes only need schema.sql and a note in the PR
- self-hosting: settings without a dashboard (SQL for security thresholds, beta settings, opted-in servers)
- beta features, deployment and troubleshooting reworded for people who don't have the dashboard
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
- LICENSE (Apache-2.0), NOTICE, CONTRIBUTING.md
- docs/self-hosting.md and README sections for hosting and contributing
- Close() no longer crashes: it only disconnects and leaves the slash commands registered, so they keep their IDs across restarts
- Tests use a neutral server ID
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The bot remembers where it registered beta commands (beta_registered) and
removes them from servers that are no longer in the beta at the next start.
Failed cleanups are retried; a server the bot has left is forgotten.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
- beta.Configure takes the opted-in servers; testers are looked up in the beta server
- beta commands registered per opted-in server and removed when it opts out
- beta.ServerEnabled for behaviour that no person triggers
- docs updated
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The owner sets them on the admin page; the bot polls the shared beta_settings
row (30s) and moves the beta commands if the server changes. BETA_* env vars
are gone.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
- /meeting add-lobby, remove-lobby, lobbies: up to 10 lobbies per server, capped in the database
- Deleted voice channels are dropped from the lobbies
- Beta features: registered only in the beta server and usable only with the Beta Tester role (BETA_GUILD_ID, BETA_ROLE_ID); fails closed
- /beta (bot owner only) shows how beta access is set up
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Every module that can be switched on or off now starts off. A server
with no settings yet reads as off; setting the Twitch alert channel or
running /tickets setup for the first time turns that module on, and
existing settings are left as they are. schema.sql mirrors the API's
migration 000019.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The panel is now one category dropdown and a Create ticket button
instead of a button per category. Discord doesn't send the dropdown's
value with a button click, so each member's pick is remembered in
memory for 15 minutes (per guild and member, capped). Panels posted
before keep working until they're reposted. Every ticket embed is
orange, closed tickets included.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Join Gate (account age, avatar, advertising and username filters, bot
checks), raid detection with invite pausing, anti-nuke quarantine of
admins who mass delete, manual and automatic lockdowns, a decaying heat
score against spam, role and channel snapshots with restore, and alert
DMs to the owner and trusted users. Everything that weakens protection
is limited to the owner and the trusted list.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Members open a ticket from a panel in the ticket channel: one button per
category (a dropdown past five), then a short form. Each ticket is a private
thread named after the category, number and opener, with a first message
that mentions the category's staff role so its members join, and Claim and
Close buttons.
- Claim: staff (the category's role, or Manage Threads / Manage Server)
take a ticket; the first message shows who has it.
- Close: the opener or staff close it, with an optional reason. The thread
is locked and archived, and the log channel gets a summary and a .txt
transcript of the whole thread.
- /ticket add|remove|claim|close inside a ticket; /tickets setup,
/tickets category add|remove|list and /tickets panel for admins.
- Per-member limit on open tickets (default 1), per-server ticket numbers
handed out atomically, a deleted thread closes its ticket.
- The dashboard asks the bot to post or refresh the panel through
ticket_commands (LISTEN/NOTIFY, like music); the listener reconnects if
the database connection drops.
- Setup warns about missing bot permissions in the ticket and log channels.
The flows live in internal/tickets behind small Discord and store
interfaces, with unit tests on fakes; the repo and the listener have
integration tests (-tags integration, TICKETS_TEST_DB).
Needs the ticket tables (velox-dashboard-api migration 000016_tickets).
.gitignore gains the /tldr benchmark rules so private chat exports and
benchmark results on disk can't be committed from this branch.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
New AddToQueue appends to an already-active session without touching
voice (the dashboard can't join a channel on its own), and add_song's
dispatch case now branches: a voice_channel_id in the payload means
"start fresh", so it goes through EnqueueAndPlay (join + play) instead.
Query normalization (plain text -> YouTube search, stripping
autoplay/radio params off pasted YouTube URLs) moves out of /play's
handler into a shared NormalizeQuery, both entry points need it, not
just one.
Starting playback from the dashboard also posts the now-playing embed
into the voice channel's own built-in text chat, matching what /play
already does, instead of leaving it with nowhere to show up.
The dashboard has been writing skip/pause/volume/etc. requests into
music_commands with nothing on this end reading them. Adds a
dedicated LISTEN connection (can't use the pooled *sql.DB for this,
LISTEN has to stay bound to one specific connection) that wakes on
NOTIFY, drains unprocessed rows, and dispatches each to the matching
Manager function. A command's error is logged, not fatal, and every
row gets marked processed regardless of outcome so a permanently
broken command doesn't retry forever.
TrackEntry gets a QueueID generated once when a track is queued and
kept for its whole life there, and musicrepo.ReplaceQueue now upserts
by that ID instead of deleting and reinserting the whole queue on
every sync (which churned every track's database id constantly, even
ones that hadn't moved, and would've made remove/reorder commands
target the wrong track). RemoveFromQueue and Reorder are new Manager
functions built on top of that stable identity. Also adds repeat_song/
repeat_queue to the persisted now-playing state, and makes the two
existing toggle functions actually sync it, they never did before.
The queue and now-playing state only ever lived in the bot's memory,
so the dashboard had nothing real to show and a restart silently
wiped whatever was queued. Adds a musicrepo package and a syncState
call after every queue-changing action (play, skip, pause, volume,
stop, track end) that mirrors the current track and queue into
music_now_playing and music_queue.
No user-visible change yet, this is groundwork for the dashboard
queue/now-playing view.
Music could be started and controlled with no way to turn it off for
a server. Adds a music_settings table (mirrors the same one
velox-dashboard-api's dashboard toggle reads/writes), a /music toggle
command gated to Manage Server, and checks in /play, /queue, and
/volume so they refuse to run when a server has music turned off.
- Added PostgreSQL service to docker-compose.yml with health checks and persistent storage.
- Updated bot service to use environment variable substitution for database connection string.
- Upgraded Go version in Dockerfile to 1.26.1-alpine.
- Modified config loading to ignore missing .env file for better compatibility with Docker.
- Introduced Dockerfile for building the bot application using Go.
- Added .dockerignore to exclude unnecessary files from the Docker context.
- Updated docker-compose.yml to define the bot service and its dependencies, including environment variables for database and Lavalink configuration.
- Modified internal configuration to streamline environment variable handling.
- Added a logging service to manage server event logs including message edits, deletions, member joins/leaves, and moderation actions.
- Introduced commands to configure logging settings, including setting the log channel and enabling/disabling logging.
- Updated the README to document the new logging features and commands.
- Enhanced moderation commands to log actions taken on members.
- Introduced a new set of moderation commands including `/moderation purge`, `/moderation timeout`, `/moderation kick`, `/moderation ban`, `/moderation unban`, `/moderation untimeout`, and `/moderation slowmode`.
- Updated README to include details about the new moderation features and commands.
- Enhanced help command to display moderation tools and their usage.