* Interactions: the Buttons (#933) * Interactions: buttons * Doc fix * Gofmt fix * Fix typo * Remaking interaction data into interface * Godoc fix * Gofmt fix * Godoc fix * InteractionData helper functions and some fixes in slash commands example * Fix components example * Yet another fix of components example * Fix interaction unmarshaling * Gofmt fix * Godoc fix * Gofmt fix * Corrected naming and docs * Rolled back API version * Requested fixes * Added support of components to webhook and regular messages * Fix components unmarshaling * Godoc fix * Requested fixes * Fixed unmarshaling issues * Components example: cleanup * Added components tracking to state * Requested fixes * Renaming fix * Remove more named returns * Minor English fixes Co-authored-by: Carson Hoffman <c@rsonhoffman.com> * Doc fix * Gofmt fix * Fix typo * Remaking interaction data into interface * Godoc fix * Gofmt fix * Godoc fix * InteractionData helper functions and some fixes in slash commands example * Fix components example * Yet another fix of components example * Fix interaction unmarshaling * Godoc fix * Gofmt fix * Corrected naming and docs * Rolled back API version * Requested fixes * Added support of components to webhook and regular messages * Interactions: select menus * Example fix * Merge fix * Some fixes * Added missing documentation * Fix components unmarshaling * Godoc fix * Requested fixes * Fixed unmarshaling issues * Components example: cleanup * Gofmt fix * Godoc fix * URL field renaming fix * Added flags to followups * Updated components example * Fixed typo in components example * Merge fix * Improve handling of invalid interaction situations * support allowing webhook edits with files, and responding to interactions with files (#931) * allow files in webhook message edits * add Files to WebhookEdit struct * move the construction of the multipart body for files into a shared function * allow interaction responses to have files * go fmt * fix err shadowing * document MakeFilesBody * rename MakeFilesBody -> EncodeWithFiles. fix InteractionRespond responding twice * use resp in InteractionRespond files, add basic-command-with-files example command * import strings and go fmt * EncodeWithFiles -> MultiPartBodyWithJSON * go fmt * fix example for slash_commands * move files to responsedata * Merge fixes * Fixed rebase consequences Co-authored-by: Carson Hoffman <c@rsonhoffman.com> Co-authored-by: plally <pierce@vulpes.dev>
192 lines
5 KiB
Go
192 lines
5 KiB
Go
package discordgo
|
|
|
|
import (
|
|
"encoding/json"
|
|
)
|
|
|
|
// ComponentType is type of component.
|
|
type ComponentType uint
|
|
|
|
// MessageComponent types.
|
|
const (
|
|
ActionsRowComponent ComponentType = 1
|
|
ButtonComponent ComponentType = 2
|
|
SelectMenuComponent ComponentType = 3
|
|
)
|
|
|
|
// MessageComponent is a base interface for all message components.
|
|
type MessageComponent interface {
|
|
json.Marshaler
|
|
Type() ComponentType
|
|
}
|
|
|
|
type unmarshalableMessageComponent struct {
|
|
MessageComponent
|
|
}
|
|
|
|
// UnmarshalJSON is a helper function to unmarshal MessageComponent object.
|
|
func (umc *unmarshalableMessageComponent) UnmarshalJSON(src []byte) error {
|
|
var v struct {
|
|
Type ComponentType `json:"type"`
|
|
}
|
|
err := json.Unmarshal(src, &v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var data MessageComponent
|
|
switch v.Type {
|
|
case ActionsRowComponent:
|
|
v := ActionsRow{}
|
|
err = json.Unmarshal(src, &v)
|
|
data = v
|
|
case ButtonComponent:
|
|
v := Button{}
|
|
err = json.Unmarshal(src, &v)
|
|
data = v
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
umc.MessageComponent = data
|
|
return err
|
|
}
|
|
|
|
// ActionsRow is a container for components within one row.
|
|
type ActionsRow struct {
|
|
Components []MessageComponent `json:"components"`
|
|
}
|
|
|
|
// MarshalJSON is a method for marshaling ActionsRow to a JSON object.
|
|
func (r ActionsRow) MarshalJSON() ([]byte, error) {
|
|
type actionsRow ActionsRow
|
|
|
|
return json.Marshal(struct {
|
|
actionsRow
|
|
Type ComponentType `json:"type"`
|
|
}{
|
|
actionsRow: actionsRow(r),
|
|
Type: r.Type(),
|
|
})
|
|
}
|
|
|
|
// UnmarshalJSON is a helper function to unmarshal Actions Row.
|
|
func (r *ActionsRow) UnmarshalJSON(data []byte) error {
|
|
var v struct {
|
|
RawComponents []unmarshalableMessageComponent `json:"components"`
|
|
}
|
|
err := json.Unmarshal(data, &v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.Components = make([]MessageComponent, len(v.RawComponents))
|
|
for i, v := range v.RawComponents {
|
|
r.Components[i] = v.MessageComponent
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// Type is a method to get the type of a component.
|
|
func (r ActionsRow) Type() ComponentType {
|
|
return ActionsRowComponent
|
|
}
|
|
|
|
// ButtonStyle is style of button.
|
|
type ButtonStyle uint
|
|
|
|
// Button styles.
|
|
const (
|
|
// PrimaryButton is a button with blurple color.
|
|
PrimaryButton ButtonStyle = 1
|
|
// SecondaryButton is a button with grey color.
|
|
SecondaryButton ButtonStyle = 2
|
|
// SuccessButton is a button with green color.
|
|
SuccessButton ButtonStyle = 3
|
|
// DangerButton is a button with red color.
|
|
DangerButton ButtonStyle = 4
|
|
// LinkButton is a special type of button which navigates to a URL. Has grey color.
|
|
LinkButton ButtonStyle = 5
|
|
)
|
|
|
|
// ComponentEmoji represents button emoji, if it does have one.
|
|
type ComponentEmoji struct {
|
|
Name string `json:"name,omitempty"`
|
|
ID string `json:"id,omitempty"`
|
|
Animated bool `json:"animated,omitempty"`
|
|
}
|
|
|
|
// Button represents button component.
|
|
type Button struct {
|
|
Label string `json:"label"`
|
|
Style ButtonStyle `json:"style"`
|
|
Disabled bool `json:"disabled"`
|
|
Emoji ComponentEmoji `json:"emoji"`
|
|
|
|
// NOTE: Only button with LinkButton style can have link. Also, URL is mutually exclusive with CustomID.
|
|
URL string `json:"url,omitempty"`
|
|
CustomID string `json:"custom_id,omitempty"`
|
|
}
|
|
|
|
// MarshalJSON is a method for marshaling Button to a JSON object.
|
|
func (b Button) MarshalJSON() ([]byte, error) {
|
|
type button Button
|
|
|
|
if b.Style == 0 {
|
|
b.Style = PrimaryButton
|
|
}
|
|
|
|
return json.Marshal(struct {
|
|
button
|
|
Type ComponentType `json:"type"`
|
|
}{
|
|
button: button(b),
|
|
Type: b.Type(),
|
|
})
|
|
}
|
|
|
|
// Type is a method to get the type of a component.
|
|
func (Button) Type() ComponentType {
|
|
return ButtonComponent
|
|
}
|
|
|
|
// SelectMenuOption represents an option for a select menu.
|
|
type SelectMenuOption struct {
|
|
Label string `json:"label,omitempty"`
|
|
Value string `json:"value"`
|
|
Description string `json:"description"`
|
|
Emoji ComponentEmoji `json:"emoji"`
|
|
// Determines whenever option is selected by default or not.
|
|
Default bool `json:"default"`
|
|
}
|
|
|
|
// SelectMenu represents select menu component.
|
|
type SelectMenu struct {
|
|
CustomID string `json:"custom_id,omitempty"`
|
|
// The text which will be shown in the menu if there's no default options or all options was deselected and component was closed.
|
|
Placeholder string `json:"placeholder"`
|
|
// This value determines the minimal amount of selected items in the menu.
|
|
MinValues int `json:"min_values,omitempty"`
|
|
// This value determines the maximal amount of selected items in the menu.
|
|
// If MaxValues or MinValues are greater than one then the user can select multiple items in the component.
|
|
MaxValues int `json:"max_values,omitempty"`
|
|
Options []SelectMenuOption `json:"options"`
|
|
}
|
|
|
|
// Type is a method to get the type of a component.
|
|
func (SelectMenu) Type() ComponentType {
|
|
return SelectMenuComponent
|
|
}
|
|
|
|
// MarshalJSON is a method for marshaling SelectMenu to a JSON object.
|
|
func (m SelectMenu) MarshalJSON() ([]byte, error) {
|
|
type selectMenu SelectMenu
|
|
|
|
return json.Marshal(struct {
|
|
selectMenu
|
|
Type ComponentType `json:"type"`
|
|
}{
|
|
selectMenu: selectMenu(m),
|
|
Type: m.Type(),
|
|
})
|
|
}
|