Files
broccolini-bot/docs/architecture/COMMANDS_ANALYSIS.md
2026-02-17 21:49:58 -06:00

84 lines
5.8 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.
# Broccolini Bot Commands Analysis
Analysis of slash commands and context menus: who can see/use them today, and how to restrict usage to the support role (@broccolini / `ROLE_ID_TO_PING`) only so customers cannot use them.
---
## Current permission model
Commands use **Discord permission bits** via `setDefaultMemberPermissions(...)`. Only users who have that permission (or Administrator) see the command in the slash menu. There is **no role-ID check** at registration time (Discord API does not support “visible only to role X”).
| Command | Registration permission | Handler: staff only? | Who can use today |
|--------|-------------------------|----------------------|--------------------|
| **Slash commands** | | | |
| `/escalate` | ManageMessages | Yes | Broccolini (staff role) only |
| `/deescalate` | ManageMessages | Yes | Broccolini only |
| `/add` | ManageMessages | Yes | Broccolini only |
| `/remove` | ManageMessages | Yes | Broccolini only |
| `/transfer` | ManageMessages | Yes (caller + target staff) | Broccolini only |
| `/move` | ManageChannels | Yes | Broccolini only |
| `/force-close` | ManageChannels | Yes | Broccolini only |
| `/topic` | ManageMessages | Yes | Broccolini only |
| `/tag` | ManageMessages | Yes | Broccolini only |
| `/response` | ManageMessages | Yes | Broccolini only |
| `/help` | **None** | **No** | **Everyone** |
| `/setup` | ManageChannels | Yes | Broccolini only |
| `/panel` | ManageChannels | Yes | Broccolini only |
| `/email-routing` | ManageGuild | Yes | Broccolini only |
| `/backup` | Administrator | Yes | Broccolini only |
| `/export` | Administrator | Yes | Broccolini only |
| `/priority` | ManageMessages | Yes | Broccolini only |
| `/search` | ManageMessages | Yes | Broccolini only |
| `/stats` | Administrator | Yes | Broccolini only |
| `/accountinfo` | ManageMessages | Yes | Broccolini only |
| **Context menus** | | | |
| Create Ticket From Message | ManageMessages | Yes | Broccolini only |
| View User Tickets | ManageMessages | Yes | Broccolini only |
---
## Role used for pinging
- **`ROLE_ID_TO_PING`** (env: `ROLE_ID_TO_PING`) The “@broccolini” role ID used to ping support on new tickets, escalations, etc. Same as `ROLE_TO_PING_ID` in config (alias).
- **`ADDITIONAL_STAFF_ROLES`** Optional comma-separated role IDs; members with any of these roles can also use staff-only commands (same as having `ROLE_ID_TO_PING`). `/transfer` also validates that the *target* user has the main staff role.
---
## Goal: “Support @broccolini @role to ping id only I dont want customers using them”
You want **all** bot commands to be usable **only** by users who have the support role (the one you ping, i.e. `ROLE_ID_TO_PING`), so customers cannot use them.
- **Ping role** = same role as today: `ROLE_ID_TO_PING` (e.g. @broccolini). No change to who gets pinged.
- **Who can run commands** = only members who have that role (and optionally `ADDITIONAL_STAFF_ROLES`). No permission-bit-only access.
Discord does **not** let you restrict slash commands by role ID in the registration. So the way to get “only this role can use” is:
1. **In the handler**: For every guild interaction, before running any command logic, check that the member has `ROLE_ID_TO_PING` (or one of `ADDITIONAL_STAFF_ROLES`). If not, reply ephemeral e.g. “This command is only available to the support team.” and do not run the command.
2. **Registration**: Leave as-is (or tighten for consistency). The role check in the handler is the real gate; permission bits only control who *sees* the command. If you want only staff to see commands, youd give the support role a permission (e.g. Manage Messages) and set that on commands; the handler check still ensures only that role (and optional additional staff roles) can actually run them.
---
## Who can use what (current behavior)
- **Only `/help`** Usable by everyone (no staff role required). Visible in guild and in DMs; in DMs there is no role check.
- **All other commands** (including `/topic` and `/priority`) Broccolini-only. The handler requires the support role (`ROLE_ID_TO_PING` or `ADDITIONAL_STAFF_ROLES`) in guild; customers get an ephemeral “This command is only available to the support team.” and the command does not run.
Note: `/topic` and `/priority` use `ManageMessages` in registration, so they appear in the slash menu only for users with that permission (typically staff). The handler also enforces the staff role. Only `/help` has no default permission and is visible to everyone.
---
## Implementation (done)
- **`handlers/commands.js`**
- **`hasStaffRole(member)`** Returns true if the member has `ROLE_ID_TO_PING` or any `ADDITIONAL_STAFF_ROLES`.
- **`requireStaffRole(interaction)`** If the interaction is in a guild and the user is not staff, replies ephemeral with “This command is only available to the support team (@role).” and returns `true` (so the handler returns without running the command). If not in a guild (e.g. `/help` in DMs), or if no staff roles are configured, no block is applied.
- **`handleCommand`** Calls `requireStaffRole(interaction)` at the top **except for `/help`**; if it returns true, the handler returns immediately.
- **`handleContextMenu`** Same check at the top for “Create Ticket From Message” and “View User Tickets”.
- **Behavior**
- **`/help`** Can be used by everyone (no staff role required).
- **All other slash commands** In a guild, only users with the staff role (ROLE_ID_TO_PING or ADDITIONAL_STAFF_ROLES) can use them; others get an ephemeral message and the command does not run.
- **Context menus** Staff role required in guild.
- In **DM** (e.g. `/help` in BotDM): No role check, so help and any other DM commands still work.
- If **`ROLE_ID_TO_PING`** and **`ADDITIONAL_STAFF_ROLES`** are both unset, the check is skipped (backward compatible).