Documentation
¶
Overview ¶
Package discord - components.go provides reusable interactive component handling for Discord (buttons, select menus) with registration, TTL-based cleanup, AllowedUsers restriction, and Reusable behavior. See ComponentRegistry, ComponentSpec, and BuildButtonRow/BuildSelectRow.
Package discord implements the Discord channel for DevClaw using discordgo.
Features:
- Send/receive text, images, audio, video, documents
- Typing indicators
- Reactions (emoji)
- Thread support (auto-thread mode)
- Embed messages for long responses
- Guild and channel allowlists
- Interactive components (buttons, select menus) with Reusable and AllowedUsers
- Automatic reconnection via discordgo's gateway
Index ¶
- func BuildButtonRow(customID, label string, style discordgo.ButtonStyle) discordgo.MessageComponent
- func BuildSelectRow(customID string, options []discordgo.SelectMenuOption, placeholder string) discordgo.MessageComponent
- type ComponentHandler
- type ComponentKind
- type ComponentRegistry
- type ComponentSpec
- type Config
- type Discord
- func (d *Discord) BaseType() string
- func (d *Discord) ComponentRegistry() *ComponentRegistry
- func (d *Discord) Connect(ctx context.Context) error
- func (d *Discord) Disconnect() error
- func (d *Discord) DownloadMedia(ctx context.Context, msg *channels.IncomingMessage) ([]byte, string, error)
- func (d *Discord) Health() channels.HealthStatus
- func (d *Discord) InstanceID() string
- func (d *Discord) IsConnected() bool
- func (d *Discord) MarkRead(ctx context.Context, chatID string, messageIDs []string) error
- func (d *Discord) Name() string
- func (d *Discord) Receive() <-chan *channels.IncomingMessage
- func (d *Discord) Send(ctx context.Context, to string, message *channels.OutgoingMessage) error
- func (d *Discord) SendMedia(ctx context.Context, to string, media *channels.MediaMessage) error
- func (d *Discord) SendPresence(ctx context.Context, available bool) error
- func (d *Discord) SendReaction(ctx context.Context, chatID, messageID, emoji string) error
- func (d *Discord) SendTyping(ctx context.Context, to string) error
- func (d *Discord) SendWithComponents(ctx context.Context, to string, content string, ...) error
- type InteractionEvent
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BuildButtonRow ¶
func BuildButtonRow(customID, label string, style discordgo.ButtonStyle) discordgo.MessageComponent
BuildButtonRow creates a discordgo ActionsRow containing a single button. Use with Register(customID, spec) before sending the message.
func BuildSelectRow ¶
func BuildSelectRow(customID string, options []discordgo.SelectMenuOption, placeholder string) discordgo.MessageComponent
BuildSelectRow creates a discordgo ActionsRow containing a string select menu. Use with Register(customID, spec) before sending the message.
Types ¶
type ComponentHandler ¶
type ComponentHandler func(ctx context.Context, evt *InteractionEvent) (content string, err error)
ComponentHandler processes a component interaction. It receives the interaction context and returns optional response content and an optional error. For select menus, evt.Values contains the selected option values.
type ComponentKind ¶
type ComponentKind string
ComponentKind identifies the type of component.
const ( ComponentKindButton ComponentKind = "button" ComponentKindSelect ComponentKind = "select" )
type ComponentRegistry ¶
type ComponentRegistry struct {
// contains filtered or unexported fields
}
ComponentRegistry stores component specs by custom_id and handles TTL cleanup.
func NewComponentRegistry ¶
func NewComponentRegistry(logger *slog.Logger) *ComponentRegistry
NewComponentRegistry creates a registry and starts background TTL cleanup.
func (*ComponentRegistry) Copy ¶
func (r *ComponentRegistry) Copy() map[string]ComponentSpec
Copy returns a snapshot of all registered custom IDs (for tests/debug).
func (*ComponentRegistry) Get ¶
func (r *ComponentRegistry) Get(customID string) (*ComponentSpec, bool)
Get retrieves the component spec if it exists and is not expired.
func (*ComponentRegistry) Register ¶
func (r *ComponentRegistry) Register(customID string, spec ComponentSpec)
Register adds or overwrites a component spec for the given custom_id. Call this before sending a message that includes the component.
func (*ComponentRegistry) Stop ¶
func (r *ComponentRegistry) Stop()
Stop halts the cleanup loop. Call when shutting down the Discord channel.
func (*ComponentRegistry) Unregister ¶
func (r *ComponentRegistry) Unregister(customID string)
Unregister removes a component spec.
type ComponentSpec ¶
type ComponentSpec struct {
// Kind is the component type (button or select).
Kind ComponentKind
// Reusable, when true, means clicking does NOT consume/disable the component.
// It can be clicked multiple times. Default is false.
Reusable bool
// AllowedUsers restricts who can interact. If nil or empty, anyone can use it.
AllowedUsers []string
// TTL is how long the component stays registered. After expiry it is removed
// and interactions are ignored. Zero means no expiry.
TTL time.Duration
// Handler is called when an authorized user interacts. The handler may return
// content to display in the interaction response. If the handler returns
// an error, an error message is shown to the user.
Handler ComponentHandler
}
ComponentSpec defines the behavior of a registered interactive component. Register components before sending messages that include them.
func (*ComponentSpec) IsAllowed ¶
func (s *ComponentSpec) IsAllowed(userID string) bool
IsAllowed checks if the user is in AllowedUsers. If AllowedUsers is nil/empty, returns true.
type Config ¶
type Config struct {
// InstanceID identifies this instance ("" for default, e.g. "gaming" for named).
// Set automatically from the config key in discord_instances.
InstanceID string `yaml:"instance_id,omitempty"`
// Token is the Discord bot token.
Token string `yaml:"token"`
// AllowedGuilds restricts which guild (server) IDs the bot responds in.
// Empty means respond in all guilds.
AllowedGuilds []string `yaml:"allowed_guilds"`
// AllowedChannels restricts which channel IDs the bot responds in.
// Empty means respond in all channels.
AllowedChannels []string `yaml:"allowed_channels"`
// RespondToThreads enables responding inside threads.
RespondToThreads bool `yaml:"respond_to_threads"`
// AutoThread creates a new thread per conversation for cleanliness.
AutoThread bool `yaml:"auto_thread"`
// SendTyping sends "typing..." indicators while processing.
SendTyping bool `yaml:"send_typing"`
}
Config holds Discord channel configuration.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns a Config with sensible defaults.
type Discord ¶
type Discord struct {
// contains filtered or unexported fields
}
Discord implements channels.Channel, channels.MediaChannel, channels.PresenceChannel, and channels.ReactionChannel.
func (*Discord) ComponentRegistry ¶
func (d *Discord) ComponentRegistry() *ComponentRegistry
ComponentRegistry returns the component registry for registering buttons and selects.
func (*Discord) Disconnect ¶
Disconnect closes the Discord gateway connection.
func (*Discord) DownloadMedia ¶
func (d *Discord) DownloadMedia(ctx context.Context, msg *channels.IncomingMessage) ([]byte, string, error)
DownloadMedia downloads an attachment from an incoming message.
func (*Discord) Health ¶
func (d *Discord) Health() channels.HealthStatus
Health returns the channel health status.
func (*Discord) InstanceID ¶ added in v1.16.0
InstanceID returns the instance identifier ("" for default).
func (*Discord) IsConnected ¶
IsConnected returns true if the bot is connected.
func (*Discord) Name ¶
Name returns the channel name. For the default instance this is "discord"; for named instances it returns "discord:<instance_id>".
func (*Discord) Receive ¶
func (d *Discord) Receive() <-chan *channels.IncomingMessage
Receive returns the incoming messages channel.
func (*Discord) SendPresence ¶
SendPresence updates the bot's status.
func (*Discord) SendReaction ¶
SendReaction adds a reaction emoji to a message.
func (*Discord) SendTyping ¶
SendTyping sends a typing indicator to the channel.
func (*Discord) SendWithComponents ¶
func (d *Discord) SendWithComponents(ctx context.Context, to string, content string, components []discordgo.MessageComponent) error
SendWithComponents sends a message with interactive components (buttons, selects). Register components with d.ComponentRegistry().Register(customID, spec) before calling.