Skip to content

feat: custom command aliases per guild (#166)#203

Merged
BillChirico merged 8 commits intomainfrom
feat/issue-166
Mar 2, 2026
Merged

feat: custom command aliases per guild (#166)#203
BillChirico merged 8 commits intomainfrom
feat/issue-166

Conversation

@BillChirico
Copy link
Collaborator

Summary

Closes #166

Allows guild admins to create custom aliases for bot commands (e.g. /w/warn).

How it works

  1. Discord registration — When an alias is created, it's registered as a guild-specific slash command with Discord so it appears in the command picker with auto-complete.
  2. Persistent storage — Aliases are stored in the guild_command_aliases database table, scoped per guild.
  3. In-memory cache — Loaded from DB on startup into a Map<guildId, Map<alias, target>>, giving O(1) resolution on every interaction.
  4. Transparent routing — The interactionCreate handler resolves the alias to its target command before permission checks and execution. Permissions are evaluated against the target command, not the alias name.
  5. Clean removal — Removing an alias deregisters the guild command from Discord and clears it from DB + cache.

Files changed

File Purpose
migrations/004_command_aliases.cjs New guild_command_aliases table with UNIQUE(guild_id, alias)
src/modules/commandAliases.js Module: addAlias, removeAlias, listAliases, resolveAlias, loadAliasesFromDb
src/commands/alias.js /alias add, /alias remove, /alias list slash command
src/index.js Load aliases on startup; resolve in interactionCreate
tests/modules/commandAliases.test.js 13 tests for the module
tests/commands/alias.test.js 13 tests for the command

Usage

/alias add w warn          → Creates /w as an alias for /warn
/alias add b ban           → Creates /b as an alias for /ban
/alias list                → Shows all aliases for this server
/alias remove w            → Removes the /w alias

Test results

  • ✅ 26 new tests passing (13 module + 13 command)
  • ✅ Lint clean (biome, 2 pre-existing warnings unrelated to this PR)
  • ✅ No regressions (3 pre-existing failures in redis/triage/ai-feedback on main, unchanged)

Copilot AI review requested due to automatic review settings March 2, 2026 04:12
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 2, 2026

Warning

Rate limit exceeded

@BillChirico has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 4 minutes and 26 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between c6633d1 and e10cad3.

📒 Files selected for processing (6)
  • migrations/004_command_aliases.cjs
  • src/commands/alias.js
  • src/index.js
  • src/modules/commandAliases.js
  • tests/commands/alias.test.js
  • tests/modules/commandAliases.test.js
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/issue-166

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds per-guild custom slash-command aliases so server admins can define shortcuts (e.g. /w/warn) that show up in Discord’s command picker and route transparently to the target command at runtime.

Changes:

  • Introduces guild_command_aliases persistence (migration) and an in-memory alias cache loaded at startup.
  • Adds a new /alias admin command to add/remove/list aliases.
  • Updates the interaction handler to resolve aliases before permission checks and command execution; adds module + command tests.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
migrations/004_command_aliases.cjs Creates guild_command_aliases table and supporting index.
src/modules/commandAliases.js Implements alias CRUD, Discord guild-command registration/deregistration, and cache loading/resolution.
src/commands/alias.js Adds `/alias add
src/index.js Loads aliases on startup; resolves aliases for slash-command execution.
tests/modules/commandAliases.test.js Unit tests covering cache load/resolve/list and add/remove flows with mocked Discord REST + DB.
tests/commands/alias.test.js Command-level tests for /alias subcommands and error handling paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@greptile-apps
Copy link

greptile-apps bot commented Mar 2, 2026

Greptile Summary

Implemented per-guild command aliases with Discord slash command registration, PostgreSQL persistence, and in-memory caching for O(1) resolution. The architecture is sound with proper separation of concerns between the module, command, and integration layers.

Key implementation details:

  • Aliases are registered as guild-specific Discord commands for autocomplete support
  • Transparent routing resolves aliases before permission checks and command execution
  • Permissions are correctly evaluated against target commands, not alias names
  • Database uses parameterized queries throughout (no SQL injection risk)
  • Comprehensive error handling with rollback mechanisms for failed operations
  • 26 passing tests covering happy paths, validation, and error scenarios

Validation safeguards:

  • Prevents shadowing built-in commands
  • Blocks circular references (aliasing the /alias command)
  • Prevents alias chaining (can't alias an alias)
  • Discord command name format validation (1-32 chars, lowercase, alphanumeric + hyphens/underscores)

Minor observation:

  • The ON CONFLICT DO UPDATE clause in addAlias may leave orphaned Discord commands in edge cases, though normal usage prevents this since Discord rejects duplicate command names

Confidence Score: 4/5

  • Safe to merge with minimal risk - well-tested feature with proper security measures
  • Score of 4 reflects solid implementation with comprehensive tests (26 new passing tests), proper security practices (parameterized queries, admin-only access, input validation), and thoughtful error handling. Minor deduction for edge case in ON CONFLICT handling that could theoretically leave orphaned Discord commands, though unlikely in practice.
  • Pay attention to src/modules/commandAliases.js regarding the ON CONFLICT update behavior

Important Files Changed

Filename Overview
src/modules/commandAliases.js Core alias functionality with good error handling and rollback logic; ON CONFLICT clause may leave orphaned Discord commands if alias update is attempted
src/commands/alias.js Well-implemented command with comprehensive validation, prevents shadowing built-in commands and circular alias references
src/index.js Clean integration of alias resolution before permission checks, ensures permissions are evaluated against target command

Sequence Diagram

sequenceDiagram
    participant Admin
    participant Discord
    participant AliasCmd as /alias Command
    participant Module as commandAliases Module
    participant DB as PostgreSQL
    participant Cache as In-Memory Cache

    Note over Admin,Cache: Creating an Alias
    Admin->>Discord: /alias add w warn
    Discord->>AliasCmd: interaction
    AliasCmd->>AliasCmd: Validate alias name
    AliasCmd->>AliasCmd: Check no built-in conflict
    AliasCmd->>Module: addAlias(w → warn)
    Module->>Discord: POST guild command /w
    Discord-->>Module: command ID
    Module->>DB: INSERT with discord_command_id
    DB-->>Module: success
    Module->>Cache: Update cache
    Module-->>AliasCmd: {alias: w, target: warn}
    AliasCmd-->>Admin: ✅ Created alias

    Note over Admin,Cache: Using an Alias
    Admin->>Discord: /w @user reason
    Discord->>AliasCmd: interaction (commandName: w)
    AliasCmd->>Cache: resolveAlias(w)
    Cache-->>AliasCmd: warn
    AliasCmd->>AliasCmd: Check permissions for warn
    AliasCmd->>AliasCmd: Execute warn command
    AliasCmd-->>Admin: Warning issued
Loading

Last reviewed commit: e10cad3

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 2, 2026
Copilot AI review requested due to automatic review settings March 2, 2026 11:44
@BillChirico BillChirico merged commit 966d51f into main Mar 2, 2026
9 of 14 checks passed
@BillChirico BillChirico deleted the feat/issue-166 branch March 2, 2026 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

enhancement: refactor events.js into single InteractionCreate dispatcher

2 participants