Improve handling of invalid interaction situations

This commit is contained in:
Carson Hoffman 2021-07-25 13:39:31 -04:00
parent 421e149650
commit 083bf5c1d9
No known key found for this signature in database
GPG key ID: 05B660CB452C657F

View file

@ -5,6 +5,7 @@ import (
"crypto/ed25519"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
@ -40,6 +41,30 @@ const (
ApplicationCommandOptionMentionable ApplicationCommandOptionType = 9
)
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"
}
return fmt.Sprintf("ApplicationCommandOptionType(%d)", t)
}
// ApplicationCommandOption represents an option/subcommand/subcommands group.
type ApplicationCommandOption struct {
Type ApplicationCommandOptionType `json:"type"`
@ -69,6 +94,18 @@ const (
InteractionMessageComponent InteractionType = 3
)
func (t InteractionType) String() string {
switch t {
case InteractionPing:
return "Ping"
case InteractionApplicationCommand:
return "ApplicationCommand"
case InteractionMessageComponent:
return "MessageComponent"
}
return fmt.Sprintf("InteractionType(%d)", t)
}
// Interaction represents data of an interaction.
type Interaction struct {
ID string `json:"id"`
@ -135,12 +172,18 @@ func (i *Interaction) UnmarshalJSON(raw []byte) error {
// 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 {
panic("ApplicationCommandData called on interaction of type " + i.Type.String())
}
return i.Data.(ApplicationCommandInteractionData)
}
@ -185,32 +228,32 @@ func (MessageComponentInteractionData) Type() InteractionType {
// ApplicationCommandInteractionDataOption represents an option of a slash command.
type ApplicationCommandInteractionDataOption struct {
Name string `json:"name"`
// NOTE: Contains the value specified by InteractionType.
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"`
}
// IntValue is a utility function for casting option value to integer
func (o ApplicationCommandInteractionDataOption) IntValue() int64 {
if v, ok := o.Value.(float64); ok {
return int64(v)
if o.Type != ApplicationCommandOptionInteger {
panic("IntValue called on data option of type " + o.Type.String())
}
return 0
return int64(o.Value.(float64))
}
// UintValue is a utility function for casting option value to unsigned integer
func (o ApplicationCommandInteractionDataOption) UintValue() uint64 {
if v, ok := o.Value.(float64); ok {
return uint64(v)
if o.Type != ApplicationCommandOptionInteger {
panic("UintValue called on data option of type " + o.Type.String())
}
return 0
return uint64(o.Value.(float64))
}
// FloatValue is a utility function for casting option value to float
func (o ApplicationCommandInteractionDataOption) FloatValue() float64 {
// TODO: limit calls to Number type once it is released
if v, ok := o.Value.(float64); ok {
return v
}
@ -220,29 +263,27 @@ func (o ApplicationCommandInteractionDataOption) FloatValue() float64 {
// StringValue is a utility function for casting option value to string
func (o ApplicationCommandInteractionDataOption) StringValue() string {
if v, ok := o.Value.(string); ok {
return v
if o.Type != ApplicationCommandOptionString {
panic("StringValue called on data option of type " + o.Type.String())
}
return ""
return o.Value.(string)
}
// BoolValue is a utility function for casting option value to bool
func (o ApplicationCommandInteractionDataOption) BoolValue() bool {
if v, ok := o.Value.(bool); ok {
return v
if o.Type != ApplicationCommandOptionBoolean {
panic("BoolValue called on data option of type " + o.Type.String())
}
return false
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 {
chanID := o.StringValue()
if chanID == "" {
return nil
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}
@ -262,10 +303,10 @@ func (o ApplicationCommandInteractionDataOption) ChannelValue(s *Session) *Chann
// 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 {
roleID := o.StringValue()
if roleID == "" {
return nil
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}
@ -290,10 +331,10 @@ func (o ApplicationCommandInteractionDataOption) RoleValue(s *Session, gID strin
// 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 {
userID := o.StringValue()
if userID == "" {
return nil
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}