Skip to content

Slash Commands

Jason Tucker edited this page May 8, 2026 · 13 revisions

Slash Commands

SquishyBot has 6 slash commands and 1 right-click context menu. All responses are ephemeral.

Self-service flows that aren't high-frequency (e.g. profile editing) live as buttons inside the /squishy panel rather than as standalone slash commands, to keep the global command list short.

/squishy

Who: Everyone
What: User-facing help panel and menu

Shows bot status (active channels, hubs), an explanation of how voice channels work, and two action buttons: Edit My Profile (opens the profile editor in self mode — display name, birthday, opt-outs) and Request Staff Role. Includes a select menu to explore sections:

  • 🔊 Auto Voice Channels — how hubs and auto channels work
  • 📝 Staff Requests — how to submit a staff role request
  • 🎛️ Voice Control Panel — what each button does
  • 🛡️ Admin Tools — sudo panel overview (only shown to sudo users)

/voice

Who: Anyone currently in an auto voice channel
What: Opens the voice control panel

Use this from any channel to get an ephemeral copy of your voice channel's control panel. Also refreshes the persistent panel in the private text channel.

Errors if you're not in an auto voice channel.

/sudo

Who: Sudo users only — configured via SUDO_ROLE_IDS / SUDO_USER_IDS, plus anyone added at runtime via Settings → Sudo Users What: Admin management panel with a select menu

Select menu options:

  • ⚙️ Settings — runtime config editor (see below)
  • 👤 Manage user — pick a member; opens the same Manage panel as right-click → Manage
  • 🎲 Game Night — schedule a Game Night announcement (modal: game + when + notes)
  • 🔊 Active voice channels — list all current auto channels
  • 🪐 Hub channels — list all registered hubs
  • 🧹 Force cleanup — delete empty or orphaned channels
  • 📥 Pending approvals — view pending staff requests
  • 🔧 Run reconciler — repair channels and rebuild DB state
  • 🔁 Restart instructions — terminal commands for VPS management

Every sub-panel reachable from this menu (and the Settings home) has a 🏠 Back to /sudo button to return to this view in one click — no need to dismiss and rerun.

Game Night flow

  1. Sudo runs /sudo from the channel they want the announcement in, then picks 🎲 Game Night from the select. A modal opens with three fields: game name (resolved against the catalog), when (free text), notes (optional).
  2. On submit, bot posts a Components V2 announcement in that same channel. The post pings the game's ping_role_id if set.
  3. Members RSVP via three buttons (✅ Joining · 🤔 Might join · ❌ Not joining) — clicking the current state again clears it.
  4. Members declare ownership via two buttons (👍 I own it · 🛒 I don't own it). The 🛒 list surfaces who to gift the game to (the server buys copies for non-owners on Game Night).
  5. ✖️ Cancel button visible to the host and any sudo. Deletes the message.
  6. State per announcement is held in-memory (keyed by message ID) with parse-from-message recovery on cache miss, so live announcements survive bot restarts.

Settings sub-panel

A nested panel for editing values that would normally come from .env, without restarting the bot. Each field shows whether the live value is from env or a DB override; Reset on any field clears the override and falls back to env. Persistence: bot_settings (key/value overrides) and sudo_users (members granted sudo at runtime).

Category Fields Notes
🛡️ Sudo Users Add member · Remove additional sudo user Env-listed sudo users (SUDO_USER_IDS) cannot be removed here; only runtime additions can.
📺 Channels Log · Admin · Birthday · Staff approval thread Channel pickers per setting.
🔊 Voice voice.cleanup_delay_ms (modal-edited, 0–600000) · channel.auto_voice_category (ChannelSelectMenu, category-only) The auto-voice category is the parent for hubs and auto channels. Override falls back to AUTO_VOICE_CATEGORY_ID env.
🪐 Hub Channels Add hub (ChannelSelectMenu, voice-only) · Unregister hub (StringSelectMenu) Dynamic list of hub voice channels. Backed by hub_channels (the DB is authoritative; HUB_CHANNEL_IDS env is a one-time seed list).
🧵 Auto Threads Add channel (ChannelSelectMenu) · Remove channel (StringSelectMenu) Dynamic list of channels where every non-bot message gets an auto-thread. Backed by auto_thread_channels.
🎮 Games List → pick a game → field editor (name / aliases / sort / view-role / ping-role / visibility / archive / delete) · Add Game button Manages the game catalog backing /games and /play. Roles use RoleSelectMenu.
👤 User Profiles UserSelectMenu picker → full profile editor Sudo can edit any field on any member's user_profiles row. Opens the same editor as right-click → Manage User → Edit Profile.

Automatic events

Event What happens
Message in an auto-thread channel When a non-bot, non-system message lands in any channel listed in auto_thread_channels, the bot calls message.startThread({ name, autoArchiveDuration }). Default name: {author} — {first line of message} (truncated to 100 chars). Bot messages, system messages, and channels that already have a thread on that message are skipped. Requires the MessageContent privileged intent.
Daily birthday tick Every minute, the birthday scheduler checks the wall clock. When the configured target hour is reached (birthday.target_hour, default 9) AND the date hasn't been seen yet (bot_settings.birthday.last_run_date), it queries user_profiles for members whose birthday is today AND birthday_pings_enabled = true, then posts a celebratory message in getSetting('channel.birthday') ?? env.BIRTHDAY_CHANNEL_ID. Feb 29 birthdays are pinged on Feb 28 in non-leap years with a small note.

/report

Who: Everyone
What: File a bug or feature request that gets reviewed by the bot owner before landing on GitHub

Opens a modal: Title, Type (bug / feature / question), Description, optional Steps to reproduce.

On submit, the bot DMs BOT_OWNER_ID with the full report and four review buttons:

  • Approve + Notify — file issue, DM the reporter the URL
  • Approve, Silent — file issue, no DM to reporter
  • Reject + Notify — drop, DM reporter that it was reviewed and not filed
  • Reject, Silent — drop, no DM

Requires GITHUB_TOKEN (PAT with Issues: Read & Write) and GITHUB_REPO (owner/name) env vars; replies with a friendly "not configured" error if missing.

Edit My Profile (/squishy button)

Who: Everyone What: Self-service editor for your bot profile (no slash command — reachable via the Edit My Profile button on /squishy).

Opens the shared profile editor in self mode, scoped to fields a member should edit on themselves:

  • Display Name (modal)
  • Birthday (modal, month + day)
  • Birthday pings toggle (status-flip) — Birthday pings: Enabled (green) / Birthday pings: Disabled (red). Opt out without deleting the date.
  • Show year toggle (status-flip) — Show year: Enabled / Show year: Disabled. Reserved for future age display.

The boolean toggles use the status-flip convention: the button label and color show the current state, not the action you're about to take. Same convention as the voice panel's Locked / Unlocked and Visible / Hidden buttons, the /games view/pings buttons, and otterbot's portal permission flags.

Staff fields (staff_category, department, tier, leadership_title) and real_name stay sudo-only and are not visible in this view.

Every edit is logged with editor + target + mode + fields touched. Sudo edits the same fields (plus the staff fields) via right-click → Manage User → Edit Profile, which uses the identical editor module.

/games

Who: Everyone What: Pick which games you want View access and LFG pings for

Lists every visible+non-archived game in the catalog. Each row has two buttons: View (assigns the game's view role) and Pings (assigns the game's LFG ping role). Toggling either button immediately adds or removes the matching Discord role.

Self-mode UI; sudo can do this on a member's behalf via right-click → Manage User → Game Prefs (same editor).

/play

Who: Everyone What: Post an LFG message + Join button in the game's channel

Args: game (required, autocompletes by name or alias) and force (sudo only — bypass the cooldown).

Posts a Components V2 message in the game's configured channel, pings the ping_role_id, and includes a 🎮 I want to play! button. Anyone clicking the button toggles their presence in the player list shown in the message body. The host (the user who ran /play) is locked in — to cancel they delete the message themselves.

Per-(user, game) cooldown is 30 minutes (in-memory). allowedMentions whitelists only the host and the ping role, so @everyone/@here are never resolved regardless of user input.

State is held in-memory keyed by message ID. If the bot restarts, the handler re-derives the player list by parsing the <@id> mentions out of the existing message — so existing posts keep working through restarts.

Errors with helpful messages when the game has no channel, the channel is unreachable, or the bot lacks Send Messages.

Right-click → Manage

Who: Sudo users only What: User management panel (renamed from "Manage User" in 0.7.x)

Right-click any Discord member → Apps → Manage

Shows: their roles, voice channel, owned auto channel. Buttons: Edit Profile (opens the same editor as /sudo → Settings → User Profiles, target pre-set), Game Prefs (opens the same editor as /games but in mode='sudo' for the targeted member), View Channel Panel (when in voice), Disconnect from Voice (when in voice), View Staff Request History.

Staff request flow

See the dedicated Staff Roles page for the full picker → role-grant flow, the 7 role registry, and /sudo → Settings → Staff Roles (provisioning + linking the Discord roles into bot_settings).

Quick summary:

  1. User runs /squishy → clicks Request Staff Role.
  2. Ephemeral picker lists the 7 staff roles (Tier 1 / 2 / 3, Help Desk, Onsites, Security, Leadership) — pick one.
  3. Small modal opens: real / preferred name (optional), reason (optional).
  4. Bot posts the request in STAFF_APPROVAL_THREAD_ID with Approve / Deny buttons, pings STAFF_APPROVAL_PING_USER_ID with the role label.
  5. Sudo Approve → bot adds the linked Discord role to the requester via member.roles.add(), edits the card with the grant outcome, and DMs the requester.
  6. Sudo Deny → bot edits the card with the Deny styling and DMs the requester.

Clone this wiki locally