Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/disgoorg/disgo/llms.txt

Use this file to discover all available pages before exploring further.

The handler package provides a powerful routing system for handling Discord interactions (slash commands, buttons, select menus, modals) with a simple, HTTP router-inspired interface.

Overview

The handler routes interactions based on paths:
  • Commands: Use the command name as path (e.g., /test, /test/subcommand)
  • Components: Use the custom ID as path
  • Modals: Use the custom ID as path
Supports path variables using curly braces: /command/{id}/subcommand

Core types

Router

The main interface for registering handlers and middleware.
type Router interface {
    bot.EventListener
    
    Use(middlewares ...Middleware)
    With(middlewares ...Middleware) Router
    Group(fn func(r Router))
    Route(pattern string, fn func(r Router)) Router
    Mount(pattern string, r Router)
    
    Interaction(pattern string, h InteractionHandler)
    SlashCommand(pattern string, h SlashCommandHandler)
    UserCommand(pattern string, h UserCommandHandler)
    MessageCommand(pattern string, h MessageCommandHandler)
    Autocomplete(pattern string, h AutocompleteHandler)
    Component(pattern string, h ComponentHandler)
    ButtonComponent(pattern string, h ButtonComponentHandler)
    SelectMenuComponent(pattern string, h SelectMenuComponentHandler)
    Modal(pattern string, h ModalHandler)
}

Mux

The default Router implementation.
func New() *Mux
New()
*Mux
Creates a new router instance

Handler types

Different handler function types for various interaction types.

InteractionHandler

Handles all types of interactions.
type InteractionHandler func(e *InteractionEvent) error

SlashCommandHandler

Handles slash command interactions with parsed data.
type SlashCommandHandler func(
    data discord.SlashCommandInteractionData,
    e *CommandEvent,
) error

UserCommandHandler

Handles user context menu commands.
type UserCommandHandler func(
    data discord.UserCommandInteractionData,
    e *CommandEvent,
) error

MessageCommandHandler

Handles message context menu commands.
type MessageCommandHandler func(
    data discord.MessageCommandInteractionData,
    e *CommandEvent,
) error

ComponentHandler

Handles all component interactions (buttons, select menus).
type ComponentHandler func(e *ComponentEvent) error

ButtonComponentHandler

Handles button interactions specifically.
type ButtonComponentHandler func(
    data discord.ButtonInteractionData,
    e *ComponentEvent,
) error

SelectMenuComponentHandler

Handles select menu interactions.
type SelectMenuComponentHandler func(
    data discord.SelectMenuInteractionData,
    e *ComponentEvent,
) error

AutocompleteHandler

Handles autocomplete requests.
type AutocompleteHandler func(e *AutocompleteEvent) error

ModalHandler

Handles modal submissions.
type ModalHandler func(e *ModalEvent) error

Event types

InteractionEvent

Base event for all interactions.
type InteractionEvent struct {
    *events.InteractionCreate
    Vars map[string]string
    Ctx  context.Context
}
Vars
map[string]string
Path variables extracted from the route pattern
Ctx
context.Context
Request context for cancellation and values

Response methods

CreateMessage(messageCreate, opts)
error
Responds with a new message
DeferCreateMessage(ephemeral, opts)
error
Shows a loading state that should be edited later
UpdateMessage(messageUpdate, opts)
error
Updates the original message (for components)
DeferUpdateMessage(opts)
error
Acknowledges without showing a loading state
Modal(modalCreate, opts)
error
Responds with a modal
AutocompleteResult(choices, opts)
error
Responds with autocomplete choices
LaunchActivity(opts)
error
Launches an activity associated with the app

CommandEvent

Event for application command interactions.
type CommandEvent struct {
    *events.ApplicationCommandInteractionCreate
    Vars map[string]string
    Ctx  context.Context
}

Followup methods

GetInteractionResponse(opts)
(*discord.Message, error)
Gets the original interaction response
UpdateInteractionResponse(messageUpdate, opts)
(*discord.Message, error)
Updates the original interaction response
DeleteInteractionResponse(opts)
error
Deletes the original interaction response
CreateFollowupMessage(messageCreate, opts)
(*discord.Message, error)
Creates a followup message
UpdateFollowupMessage(messageID, messageUpdate, opts)
(*discord.Message, error)
Updates a specific followup message
DeleteFollowupMessage(messageID, opts)
error
Deletes a specific followup message

ComponentEvent

Event for component interactions (buttons, select menus).
type ComponentEvent struct {
    *events.ComponentInteractionCreate
    Vars map[string]string
    Ctx  context.Context
}
Has the same followup methods as CommandEvent.

AutocompleteEvent

Event for autocomplete interactions.
type AutocompleteEvent struct {
    *events.AutocompleteInteractionCreate
    Vars map[string]string
    Ctx  context.Context
}

ModalEvent

Event for modal submission interactions.
type ModalEvent struct {
    *events.ModalSubmitInteractionCreate
    Vars map[string]string
    Ctx  context.Context
}

Middleware

Middleware wraps handlers to add pre/post processing.
type Middleware func(next Handler) Handler
type Handler func(e *InteractionEvent) error

Usage example

// Logging middleware
func loggingMiddleware(next handler.Handler) handler.Handler {
    return func(e *handler.InteractionEvent) error {
        log.Printf("Handling interaction: %s", e.ID())
        return next(e)
    }
}

// Permission check middleware
func requireAdmin(next handler.Handler) handler.Handler {
    return func(e *handler.InteractionEvent) error {
        member, _ := e.Member()
        perms := e.Client().Caches.MemberPermissions(member)
        
        if !perms.Has(discord.PermissionAdministrator) {
            return e.CreateMessage(discord.MessageCreate{
                Content: "You need administrator permission!",
                Flags:   discord.MessageFlagEphemeral,
            })
        }
        
        return next(e)
    }
}

Router methods

Use

Adds middleware to the current router.
func (r *Mux) Use(middlewares ...Middleware)

With

Returns a new router with the given middleware.
func (r *Mux) With(middlewares ...Middleware) Router

Group

Creates a sub-router for grouping routes.
func (r *Mux) Group(fn func(r Router))

Route

Creates a sub-router with a path prefix.
func (r *Mux) Route(pattern string, fn func(r Router)) Router

Mount

Mounts another router at a specific path.
func (r *Mux) Mount(pattern string, router Router)

NotFound

Sets a handler for when no route matches.
func (r *Mux) NotFound(h NotFoundHandler)

Error

Sets a global error handler.
func (r *Mux) Error(h ErrorHandler)

DefaultContext

Sets the default context function.
func (r *Mux) DefaultContext(ctx func() context.Context)

Utility functions

SyncCommands

Synchronizes application commands with Discord.
func SyncCommands(
    client *bot.Client,
    commands []discord.ApplicationCommandCreate,
    guildIDs []snowflake.ID,
    opts ...rest.RequestOpt,
) error
client
*bot.Client
The bot client
commands
[]discord.ApplicationCommandCreate
The commands to register
guildIDs
[]snowflake.ID
Guild IDs to register commands in, or empty for global commands

Complete usage example

package main

import (
    "fmt"
    "github.com/disgoorg/disgo"
    "github.com/disgoorg/disgo/discord"
    "github.com/disgoorg/disgo/handler"
)

func main() {
    // Create router
    r := handler.New()
    
    // Global middleware
    r.Use(loggingMiddleware)
    
    // Slash commands
    r.SlashCommand("/ping", func(data discord.SlashCommandInteractionData, e *handler.CommandEvent) error {
        return e.CreateMessage(discord.MessageCreate{
            Content: "Pong!",
        })
    })
    
    // Command with subcommands and variables
    r.Route("/user", func(r handler.Router) {
        r.SlashCommand("/info/{userID}", func(data discord.SlashCommandInteractionData, e *handler.CommandEvent) error {
            userID := e.Vars["userID"]
            return e.CreateMessage(discord.MessageCreate{
                Content: fmt.Sprintf("User ID: %s", userID),
            })
        })
    })
    
    // Admin-only commands with middleware
    r.Route("/admin", func(r handler.Router) {
        r.Use(requireAdmin)
        
        r.SlashCommand("/ban", func(data discord.SlashCommandInteractionData, e *handler.CommandEvent) error {
            // Handle ban command
            return nil
        })
    })
    
    // Component handlers
    r.ButtonComponent("/button/{action}", func(data discord.ButtonInteractionData, e *handler.ComponentEvent) error {
        action := e.Vars["action"]
        return e.UpdateMessage(discord.MessageUpdate{
            Content: discord.Ptr(fmt.Sprintf("Action: %s", action)),
        })
    })
    
    // Select menu handler
    r.SelectMenuComponent("/select/role", func(data discord.SelectMenuInteractionData, e *handler.ComponentEvent) error {
        selectedRoles := data.Values
        return e.CreateMessage(discord.MessageCreate{
            Content: fmt.Sprintf("Selected %d roles", len(selectedRoles)),
            Flags:   discord.MessageFlagEphemeral,
        })
    })
    
    // Modal handler
    r.Modal("/feedback", func(e *handler.ModalEvent) error {
        feedback := e.Data.Text("feedback")
        return e.CreateMessage(discord.MessageCreate{
            Content: "Thanks for your feedback!",
            Flags:   discord.MessageFlagEphemeral,
        })
    })
    
    // Autocomplete
    r.Autocomplete("/search", func(e *handler.AutocompleteEvent) error {
        return e.AutocompleteResult([]discord.AutocompleteChoice{
            discord.AutocompleteChoiceString{Name: "Option 1", Value: "1"},
            discord.AutocompleteChoiceString{Name: "Option 2", Value: "2"},
        })
    })
    
    // Error handler
    r.Error(func(e *handler.InteractionEvent, err error) {
        fmt.Printf("Error: %v\n", err)
    })
    
    // Not found handler
    r.NotFound(func(e *handler.InteractionEvent) error {
        return e.CreateMessage(discord.MessageCreate{
            Content: "Command not found!",
            Flags:   discord.MessageFlagEphemeral,
        })
    })
    
    // Create bot with router
    client, _ := disgo.New(token,
        bot.WithEventListeners(r),
    )
    
    // Sync commands
    commands := []discord.ApplicationCommandCreate{
        discord.SlashCommandCreate{
            Name:        "ping",
            Description: "Ping the bot",
        },
    }
    handler.SyncCommands(client, commands, nil)
}

Build docs developers (and LLMs) love