aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/bwmarrin/discordgo/interactions.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/bwmarrin/discordgo/interactions.go')
-rw-r--r--vendor/github.com/bwmarrin/discordgo/interactions.go516
1 files changed, 515 insertions, 1 deletions
diff --git a/vendor/github.com/bwmarrin/discordgo/interactions.go b/vendor/github.com/bwmarrin/discordgo/interactions.go
index 6fc2f55..0e5ae3c 100644
--- a/vendor/github.com/bwmarrin/discordgo/interactions.go
+++ b/vendor/github.com/bwmarrin/discordgo/interactions.go
@@ -4,14 +4,528 @@ import (
"bytes"
"crypto/ed25519"
"encoding/hex"
+ "encoding/json"
+ "fmt"
"io"
"io/ioutil"
"net/http"
+ "time"
)
+// InteractionDeadline is the time allowed to respond to an interaction.
+const InteractionDeadline = time.Second * 3
+
+// ApplicationCommandType represents the type of application command.
+type ApplicationCommandType uint8
+
+// Application command types
+const (
+ // ChatApplicationCommand is default command type. They are slash commands (i.e. called directly from the chat).
+ ChatApplicationCommand ApplicationCommandType = 1
+ // UserApplicationCommand adds command to user context menu.
+ UserApplicationCommand ApplicationCommandType = 2
+ // MessageApplicationCommand adds command to message context menu.
+ MessageApplicationCommand ApplicationCommandType = 3
+)
+
+// ApplicationCommand represents an application's slash command.
+type ApplicationCommand struct {
+ ID string `json:"id,omitempty"`
+ ApplicationID string `json:"application_id,omitempty"`
+ Version string `json:"version,omitempty"`
+ Type ApplicationCommandType `json:"type,omitempty"`
+ Name string `json:"name"`
+ DefaultPermission *bool `json:"default_permission,omitempty"`
+
+ // NOTE: Chat commands only. Otherwise it mustn't be set.
+
+ Description string `json:"description,omitempty"`
+ Options []*ApplicationCommandOption `json:"options"`
+}
+
+// ApplicationCommandOptionType indicates the type of a slash command's option.
+type ApplicationCommandOptionType uint8
+
+// Application command option types.
+const (
+ ApplicationCommandOptionSubCommand ApplicationCommandOptionType = 1
+ ApplicationCommandOptionSubCommandGroup ApplicationCommandOptionType = 2
+ ApplicationCommandOptionString ApplicationCommandOptionType = 3
+ ApplicationCommandOptionInteger ApplicationCommandOptionType = 4
+ ApplicationCommandOptionBoolean ApplicationCommandOptionType = 5
+ ApplicationCommandOptionUser ApplicationCommandOptionType = 6
+ ApplicationCommandOptionChannel ApplicationCommandOptionType = 7
+ ApplicationCommandOptionRole ApplicationCommandOptionType = 8
+ ApplicationCommandOptionMentionable ApplicationCommandOptionType = 9
+ ApplicationCommandOptionNumber ApplicationCommandOptionType = 10
+ ApplicationCommandOptionAttachment ApplicationCommandOptionType = 11
+)
+
+func (t ApplicationCommandOptionType) String() string {
+ switch t {
+ case ApplicationCommandOptionSubCommand:
+ return "SubCommand"
+ case ApplicationCommandOptionSubCommandGroup:
+ return "SubCommandGroup"
+ case ApplicationCommandOptionString:
+ return "String"
+ case ApplicationCommandOptionInteger:
+ return "Integer"
+ case ApplicationCommandOptionBoolean:
+ return "Boolean"
+ case ApplicationCommandOptionUser:
+ return "User"
+ case ApplicationCommandOptionChannel:
+ return "Channel"
+ case ApplicationCommandOptionRole:
+ return "Role"
+ case ApplicationCommandOptionMentionable:
+ return "Mentionable"
+ case ApplicationCommandOptionNumber:
+ return "Number"
+ case ApplicationCommandOptionAttachment:
+ return "Attachment"
+ }
+ return fmt.Sprintf("ApplicationCommandOptionType(%d)", t)
+}
+
+// ApplicationCommandOption represents an option/subcommand/subcommands group.
+type ApplicationCommandOption struct {
+ Type ApplicationCommandOptionType `json:"type"`
+ Name string `json:"name"`
+ Description string `json:"description,omitempty"`
+ // NOTE: This feature was on the API, but at some point developers decided to remove it.
+ // So I commented it, until it will be officially on the docs.
+ // Default bool `json:"default"`
+
+ ChannelTypes []ChannelType `json:"channel_types"`
+ Required bool `json:"required"`
+ Options []*ApplicationCommandOption `json:"options"`
+
+ // NOTE: mutually exclusive with Choices.
+ Autocomplete bool `json:"autocomplete"`
+ Choices []*ApplicationCommandOptionChoice `json:"choices"`
+ // Minimal value of number/integer option.
+ MinValue *float64 `json:"min_value,omitempty"`
+ // Maximum value of number/integer option.
+ MaxValue float64 `json:"max_value,omitempty"`
+}
+
+// ApplicationCommandOptionChoice represents a slash command option choice.
+type ApplicationCommandOptionChoice struct {
+ Name string `json:"name"`
+ Value interface{} `json:"value"`
+}
+
+// ApplicationCommandPermissions represents a single user or role permission for a command.
+type ApplicationCommandPermissions struct {
+ ID string `json:"id"`
+ Type ApplicationCommandPermissionType `json:"type"`
+ Permission bool `json:"permission"`
+}
+
+// ApplicationCommandPermissionsList represents a list of ApplicationCommandPermissions, needed for serializing to JSON.
+type ApplicationCommandPermissionsList struct {
+ Permissions []*ApplicationCommandPermissions `json:"permissions"`
+}
+
+// GuildApplicationCommandPermissions represents all permissions for a single guild command.
+type GuildApplicationCommandPermissions struct {
+ ID string `json:"id"`
+ ApplicationID string `json:"application_id"`
+ GuildID string `json:"guild_id"`
+ Permissions []*ApplicationCommandPermissions `json:"permissions"`
+}
+
+// ApplicationCommandPermissionType indicates whether a permission is user or role based.
+type ApplicationCommandPermissionType uint8
+
+// Application command permission types.
+const (
+ ApplicationCommandPermissionTypeRole ApplicationCommandPermissionType = 1
+ ApplicationCommandPermissionTypeUser ApplicationCommandPermissionType = 2
+)
+
+// InteractionType indicates the type of an interaction event.
+type InteractionType uint8
+
+// Interaction types
+const (
+ InteractionPing InteractionType = 1
+ InteractionApplicationCommand InteractionType = 2
+ InteractionMessageComponent InteractionType = 3
+ InteractionApplicationCommandAutocomplete InteractionType = 4
+ InteractionModalSubmit InteractionType = 5
+)
+
+func (t InteractionType) String() string {
+ switch t {
+ case InteractionPing:
+ return "Ping"
+ case InteractionApplicationCommand:
+ return "ApplicationCommand"
+ case InteractionMessageComponent:
+ return "MessageComponent"
+ case InteractionModalSubmit:
+ return "ModalSubmit"
+ }
+ return fmt.Sprintf("InteractionType(%d)", t)
+}
+
+// Interaction represents data of an interaction.
+type Interaction struct {
+ ID string `json:"id"`
+ Type InteractionType `json:"type"`
+ Data InteractionData `json:"data"`
+ GuildID string `json:"guild_id"`
+ ChannelID string `json:"channel_id"`
+
+ // The message on which interaction was used.
+ // NOTE: this field is only filled when a button click triggered the interaction. Otherwise it will be nil.
+ Message *Message `json:"message"`
+
+ // The member who invoked this interaction.
+ // NOTE: this field is only filled when the slash command was invoked in a guild;
+ // if it was invoked in a DM, the `User` field will be filled instead.
+ // Make sure to check for `nil` before using this field.
+ Member *Member `json:"member"`
+ // The user who invoked this interaction.
+ // NOTE: this field is only filled when the slash command was invoked in a DM;
+ // if it was invoked in a guild, the `Member` field will be filled instead.
+ // Make sure to check for `nil` before using this field.
+ User *User `json:"user"`
+
+ // The user's discord client locale.
+ Locale Locale `json:"locale"`
+ // The guild's locale. This defaults to EnglishUS
+ // NOTE: this field is only filled when the interaction was invoked in a guild.
+ GuildLocale *Locale `json:"guild_locale"`
+
+ Token string `json:"token"`
+ Version int `json:"version"`
+}
+
+type interaction Interaction
+
+type rawInteraction struct {
+ interaction
+ Data json.RawMessage `json:"data"`
+}
+
+// UnmarshalJSON is a method for unmarshalling JSON object to Interaction.
+func (i *Interaction) UnmarshalJSON(raw []byte) error {
+ var tmp rawInteraction
+ err := json.Unmarshal(raw, &tmp)
+ if err != nil {
+ return err
+ }
+
+ *i = Interaction(tmp.interaction)
+
+ switch tmp.Type {
+ case InteractionApplicationCommand, InteractionApplicationCommandAutocomplete:
+ v := ApplicationCommandInteractionData{}
+ err = json.Unmarshal(tmp.Data, &v)
+ if err != nil {
+ return err
+ }
+ i.Data = v
+ case InteractionMessageComponent:
+ v := MessageComponentInteractionData{}
+ err = json.Unmarshal(tmp.Data, &v)
+ if err != nil {
+ return err
+ }
+ i.Data = v
+ case InteractionModalSubmit:
+ v := ModalSubmitInteractionData{}
+ err = json.Unmarshal(tmp.Data, &v)
+ if err != nil {
+ return err
+ }
+ i.Data = v
+ }
+ return nil
+}
+
+// MessageComponentData is helper function to assert the inner InteractionData to MessageComponentInteractionData.
+// Make sure to check that the Type of the interaction is InteractionMessageComponent before calling.
+func (i Interaction) MessageComponentData() (data MessageComponentInteractionData) {
+ if i.Type != InteractionMessageComponent {
+ panic("MessageComponentData called on interaction of type " + i.Type.String())
+ }
+ return i.Data.(MessageComponentInteractionData)
+}
+
+// ApplicationCommandData is helper function to assert the inner InteractionData to ApplicationCommandInteractionData.
+// Make sure to check that the Type of the interaction is InteractionApplicationCommand before calling.
+func (i Interaction) ApplicationCommandData() (data ApplicationCommandInteractionData) {
+ if i.Type != InteractionApplicationCommand && i.Type != InteractionApplicationCommandAutocomplete {
+ panic("ApplicationCommandData called on interaction of type " + i.Type.String())
+ }
+ return i.Data.(ApplicationCommandInteractionData)
+}
+
+// ModalSubmitData is helper function to assert the inner InteractionData to ModalSubmitInteractionData.
+// Make sure to check that the Type of the interaction is InteractionModalSubmit before calling.
+func (i Interaction) ModalSubmitData() (data ModalSubmitInteractionData) {
+ if i.Type != InteractionModalSubmit {
+ panic("ModalSubmitData called on interaction of type " + i.Type.String())
+ }
+ return i.Data.(ModalSubmitInteractionData)
+}
+
+// InteractionData is a common interface for all types of interaction data.
+type InteractionData interface {
+ Type() InteractionType
+}
+
+// ApplicationCommandInteractionData contains the data of application command interaction.
+type ApplicationCommandInteractionData struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Resolved *ApplicationCommandInteractionDataResolved `json:"resolved"`
+
+ // Slash command options
+ Options []*ApplicationCommandInteractionDataOption `json:"options"`
+ // Target (user/message) id on which context menu command was called.
+ // The details are stored in Resolved according to command type.
+ TargetID string `json:"target_id"`
+}
+
+// ApplicationCommandInteractionDataResolved contains resolved data of command execution.
+// Partial Member objects are missing user, deaf and mute fields.
+// Partial Channel objects only have id, name, type and permissions fields.
+type ApplicationCommandInteractionDataResolved struct {
+ Users map[string]*User `json:"users"`
+ Members map[string]*Member `json:"members"`
+ Roles map[string]*Role `json:"roles"`
+ Channels map[string]*Channel `json:"channels"`
+ Messages map[string]*Message `json:"messages"`
+ Attachments map[string]*MessageAttachment `json:"attachments"`
+}
+
+// Type returns the type of interaction data.
+func (ApplicationCommandInteractionData) Type() InteractionType {
+ return InteractionApplicationCommand
+}
+
+// MessageComponentInteractionData contains the data of message component interaction.
+type MessageComponentInteractionData struct {
+ CustomID string `json:"custom_id"`
+ ComponentType ComponentType `json:"component_type"`
+
+ // NOTE: Only filled when ComponentType is SelectMenuComponent (3). Otherwise is nil.
+ Values []string `json:"values"`
+}
+
+// Type returns the type of interaction data.
+func (MessageComponentInteractionData) Type() InteractionType {
+ return InteractionMessageComponent
+}
+
+// ModalSubmitInteractionData contains the data of modal submit interaction.
+type ModalSubmitInteractionData struct {
+ CustomID string `json:"custom_id"`
+ Components []MessageComponent `json:"-"`
+}
+
+// Type returns the type of interaction data.
+func (ModalSubmitInteractionData) Type() InteractionType {
+ return InteractionModalSubmit
+}
+
+// UnmarshalJSON is a helper function to correctly unmarshal Components.
+func (d *ModalSubmitInteractionData) UnmarshalJSON(data []byte) error {
+ type modalSubmitInteractionData ModalSubmitInteractionData
+ var v struct {
+ modalSubmitInteractionData
+ RawComponents []unmarshalableMessageComponent `json:"components"`
+ }
+ err := json.Unmarshal(data, &v)
+ if err != nil {
+ return err
+ }
+ *d = ModalSubmitInteractionData(v.modalSubmitInteractionData)
+ d.Components = make([]MessageComponent, len(v.RawComponents))
+ for i, v := range v.RawComponents {
+ d.Components[i] = v.MessageComponent
+ }
+ return err
+}
+
+// ApplicationCommandInteractionDataOption represents an option of a slash command.
+type ApplicationCommandInteractionDataOption struct {
+ Name string `json:"name"`
+ Type ApplicationCommandOptionType `json:"type"`
+ // NOTE: Contains the value specified by Type.
+ Value interface{} `json:"value,omitempty"`
+ Options []*ApplicationCommandInteractionDataOption `json:"options,omitempty"`
+
+ // NOTE: autocomplete interaction only.
+ Focused bool `json:"focused,omitempty"`
+}
+
+// IntValue is a utility function for casting option value to integer
+func (o ApplicationCommandInteractionDataOption) IntValue() int64 {
+ if o.Type != ApplicationCommandOptionInteger {
+ panic("IntValue called on data option of type " + o.Type.String())
+ }
+ return int64(o.Value.(float64))
+}
+
+// UintValue is a utility function for casting option value to unsigned integer
+func (o ApplicationCommandInteractionDataOption) UintValue() uint64 {
+ if o.Type != ApplicationCommandOptionInteger {
+ panic("UintValue called on data option of type " + o.Type.String())
+ }
+ return uint64(o.Value.(float64))
+}
+
+// FloatValue is a utility function for casting option value to float
+func (o ApplicationCommandInteractionDataOption) FloatValue() float64 {
+ if o.Type != ApplicationCommandOptionNumber {
+ panic("FloatValue called on data option of type " + o.Type.String())
+ }
+ return o.Value.(float64)
+}
+
+// StringValue is a utility function for casting option value to string
+func (o ApplicationCommandInteractionDataOption) StringValue() string {
+ if o.Type != ApplicationCommandOptionString {
+ panic("StringValue called on data option of type " + o.Type.String())
+ }
+ return o.Value.(string)
+}
+
+// BoolValue is a utility function for casting option value to bool
+func (o ApplicationCommandInteractionDataOption) BoolValue() bool {
+ if o.Type != ApplicationCommandOptionBoolean {
+ panic("BoolValue called on data option of type " + o.Type.String())
+ }
+ return o.Value.(bool)
+}
+
+// ChannelValue is a utility function for casting option value to channel object.
+// s : Session object, if not nil, function additionally fetches all channel's data
+func (o ApplicationCommandInteractionDataOption) ChannelValue(s *Session) *Channel {
+ if o.Type != ApplicationCommandOptionChannel {
+ panic("ChannelValue called on data option of type " + o.Type.String())
+ }
+ chanID := o.Value.(string)
+
+ if s == nil {
+ return &Channel{ID: chanID}
+ }
+
+ ch, err := s.State.Channel(chanID)
+ if err != nil {
+ ch, err = s.Channel(chanID)
+ if err != nil {
+ return &Channel{ID: chanID}
+ }
+ }
+
+ return ch
+}
+
+// RoleValue is a utility function for casting option value to role object.
+// s : Session object, if not nil, function additionally fetches all role's data
+func (o ApplicationCommandInteractionDataOption) RoleValue(s *Session, gID string) *Role {
+ if o.Type != ApplicationCommandOptionRole && o.Type != ApplicationCommandOptionMentionable {
+ panic("RoleValue called on data option of type " + o.Type.String())
+ }
+ roleID := o.Value.(string)
+
+ if s == nil || gID == "" {
+ return &Role{ID: roleID}
+ }
+
+ r, err := s.State.Role(roleID, gID)
+ if err != nil {
+ roles, err := s.GuildRoles(gID)
+ if err == nil {
+ for _, r = range roles {
+ if r.ID == roleID {
+ return r
+ }
+ }
+ }
+ return &Role{ID: roleID}
+ }
+
+ return r
+}
+
+// UserValue is a utility function for casting option value to user object.
+// s : Session object, if not nil, function additionally fetches all user's data
+func (o ApplicationCommandInteractionDataOption) UserValue(s *Session) *User {
+ if o.Type != ApplicationCommandOptionUser && o.Type != ApplicationCommandOptionMentionable {
+ panic("UserValue called on data option of type " + o.Type.String())
+ }
+ userID := o.Value.(string)
+
+ if s == nil {
+ return &User{ID: userID}
+ }
+
+ u, err := s.User(userID)
+ if err != nil {
+ return &User{ID: userID}
+ }
+
+ return u
+}
+
+// InteractionResponseType is type of interaction response.
+type InteractionResponseType uint8
+
+// Interaction response types.
+const (
+ // InteractionResponsePong is for ACK ping event.
+ InteractionResponsePong InteractionResponseType = 1
+ // InteractionResponseChannelMessageWithSource is for responding with a message, showing the user's input.
+ InteractionResponseChannelMessageWithSource InteractionResponseType = 4
+ // InteractionResponseDeferredChannelMessageWithSource acknowledges that the event was received, and that a follow-up will come later.
+ InteractionResponseDeferredChannelMessageWithSource InteractionResponseType = 5
+ // InteractionResponseDeferredMessageUpdate acknowledges that the message component interaction event was received, and message will be updated later.
+ InteractionResponseDeferredMessageUpdate InteractionResponseType = 6
+ // InteractionResponseUpdateMessage is for updating the message to which message component was attached.
+ InteractionResponseUpdateMessage InteractionResponseType = 7
+ // InteractionApplicationCommandAutocompleteResult shows autocompletion results. Autocomplete interaction only.
+ InteractionApplicationCommandAutocompleteResult InteractionResponseType = 8
+ // InteractionResponseModal is for responding to an interaction with a modal window.
+ InteractionResponseModal InteractionResponseType = 9
+)
+
+// InteractionResponse represents a response for an interaction event.
+type InteractionResponse struct {
+ Type InteractionResponseType `json:"type,omitempty"`
+ Data *InteractionResponseData `json:"data,omitempty"`
+}
+
+// InteractionResponseData is response data for an interaction.
+type InteractionResponseData struct {
+ TTS bool `json:"tts"`
+ Content string `json:"content"`
+ Components []MessageComponent `json:"components"`
+ Embeds []*MessageEmbed `json:"embeds,omitempty"`
+ AllowedMentions *MessageAllowedMentions `json:"allowed_mentions,omitempty"`
+ Flags uint64 `json:"flags,omitempty"`
+ Files []*File `json:"-"`
+
+ // NOTE: autocomplete interaction only.
+ Choices []*ApplicationCommandOptionChoice `json:"choices,omitempty"`
+
+ // NOTE: modal interaction only.
+
+ CustomID string `json:"custom_id,omitempty"`
+ Title string `json:"title,omitempty"`
+}
+
// VerifyInteraction implements message verification of the discord interactions api
// signing algorithm, as documented here:
-// https://discord.com/developers/docs/interactions/slash-commands#security-and-authorization
+// https://discord.com/developers/docs/interactions/receiving-and-responding#security-and-authorization
func VerifyInteraction(r *http.Request, key ed25519.PublicKey) bool {
var msg bytes.Buffer