* feat(SelectMenu): default values * fix: remove unncessary pointer Since SelectMenu is used as a nested structure, it is not possible to partially edit it. Thus, an empty slice does not need to be accounted for, and the pointer, which would only be omitted if the value is nil, can be converted to a regular slice. * fix: correct grammar in the comment to SelectMenuDefaultValueType
289 lines
8.5 KiB
Go
289 lines
8.5 KiB
Go
package discordgo
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
// ComponentType is type of component.
|
|
type ComponentType uint
|
|
|
|
// MessageComponent types.
|
|
const (
|
|
ActionsRowComponent ComponentType = 1
|
|
ButtonComponent ComponentType = 2
|
|
SelectMenuComponent ComponentType = 3
|
|
TextInputComponent ComponentType = 4
|
|
UserSelectMenuComponent ComponentType = 5
|
|
RoleSelectMenuComponent ComponentType = 6
|
|
MentionableSelectMenuComponent ComponentType = 7
|
|
ChannelSelectMenuComponent ComponentType = 8
|
|
)
|
|
|
|
// 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
|
|
}
|
|
|
|
switch v.Type {
|
|
case ActionsRowComponent:
|
|
umc.MessageComponent = &ActionsRow{}
|
|
case ButtonComponent:
|
|
umc.MessageComponent = &Button{}
|
|
case SelectMenuComponent, ChannelSelectMenuComponent, UserSelectMenuComponent,
|
|
RoleSelectMenuComponent, MentionableSelectMenuComponent:
|
|
umc.MessageComponent = &SelectMenu{}
|
|
case TextInputComponent:
|
|
umc.MessageComponent = &TextInput{}
|
|
default:
|
|
return fmt.Errorf("unknown component type: %d", v.Type)
|
|
}
|
|
return json.Unmarshal(src, umc.MessageComponent)
|
|
}
|
|
|
|
// MessageComponentFromJSON is a helper function for unmarshaling message components
|
|
func MessageComponentFromJSON(b []byte) (MessageComponent, error) {
|
|
var u unmarshalableMessageComponent
|
|
err := u.UnmarshalJSON(b)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal into MessageComponent: %w", err)
|
|
}
|
|
return u.MessageComponent, nil
|
|
}
|
|
|
|
// 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 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 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"`
|
|
}
|
|
|
|
// SelectMenuDefaultValueType represents the type of an entity selected by default in auto-populated select menus.
|
|
type SelectMenuDefaultValueType string
|
|
|
|
// SelectMenuDefaultValue types.
|
|
const (
|
|
SelectMenuDefaultValueUser SelectMenuDefaultValueType = "user"
|
|
SelectMenuDefaultValueRole SelectMenuDefaultValueType = "role"
|
|
SelectMenuDefaultValueChannel SelectMenuDefaultValueType = "channel"
|
|
)
|
|
|
|
// SelectMenuDefaultValue represents an entity selected by default in auto-populated select menus.
|
|
type SelectMenuDefaultValue struct {
|
|
// ID of the entity.
|
|
ID string `json:"id"`
|
|
// Type of the entity.
|
|
Type SelectMenuDefaultValueType `json:"type"`
|
|
}
|
|
|
|
// SelectMenuType represents select menu type.
|
|
type SelectMenuType ComponentType
|
|
|
|
// SelectMenu types.
|
|
const (
|
|
StringSelectMenu = SelectMenuType(SelectMenuComponent)
|
|
UserSelectMenu = SelectMenuType(UserSelectMenuComponent)
|
|
RoleSelectMenu = SelectMenuType(RoleSelectMenuComponent)
|
|
MentionableSelectMenu = SelectMenuType(MentionableSelectMenuComponent)
|
|
ChannelSelectMenu = SelectMenuType(ChannelSelectMenuComponent)
|
|
)
|
|
|
|
// SelectMenu represents select menu component.
|
|
type SelectMenu struct {
|
|
// Type of the select menu.
|
|
MenuType SelectMenuType `json:"type,omitempty"`
|
|
// CustomID is a developer-defined identifier for the select menu.
|
|
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"`
|
|
// List of default values for auto-populated select menu.
|
|
// NOTE: Number of entries should be in the range defined by MinValues and MaxValues.
|
|
DefaultValues []SelectMenuDefaultValue `json:"default_values,omitempty"`
|
|
|
|
Options []SelectMenuOption `json:"options,omitempty"`
|
|
Disabled bool `json:"disabled"`
|
|
|
|
// NOTE: Can only be used in SelectMenu with Channel menu type.
|
|
ChannelTypes []ChannelType `json:"channel_types,omitempty"`
|
|
}
|
|
|
|
// Type is a method to get the type of a component.
|
|
func (s SelectMenu) Type() ComponentType {
|
|
if s.MenuType != 0 {
|
|
return ComponentType(s.MenuType)
|
|
}
|
|
return SelectMenuComponent
|
|
}
|
|
|
|
// MarshalJSON is a method for marshaling SelectMenu to a JSON object.
|
|
func (s SelectMenu) MarshalJSON() ([]byte, error) {
|
|
type selectMenu SelectMenu
|
|
|
|
return Marshal(struct {
|
|
selectMenu
|
|
Type ComponentType `json:"type"`
|
|
}{
|
|
selectMenu: selectMenu(s),
|
|
Type: s.Type(),
|
|
})
|
|
}
|
|
|
|
// TextInput represents text input component.
|
|
type TextInput struct {
|
|
CustomID string `json:"custom_id"`
|
|
Label string `json:"label"`
|
|
Style TextInputStyle `json:"style"`
|
|
Placeholder string `json:"placeholder,omitempty"`
|
|
Value string `json:"value,omitempty"`
|
|
Required bool `json:"required"`
|
|
MinLength int `json:"min_length,omitempty"`
|
|
MaxLength int `json:"max_length,omitempty"`
|
|
}
|
|
|
|
// Type is a method to get the type of a component.
|
|
func (TextInput) Type() ComponentType {
|
|
return TextInputComponent
|
|
}
|
|
|
|
// MarshalJSON is a method for marshaling TextInput to a JSON object.
|
|
func (m TextInput) MarshalJSON() ([]byte, error) {
|
|
type inputText TextInput
|
|
|
|
return Marshal(struct {
|
|
inputText
|
|
Type ComponentType `json:"type"`
|
|
}{
|
|
inputText: inputText(m),
|
|
Type: m.Type(),
|
|
})
|
|
}
|
|
|
|
// TextInputStyle is style of text in TextInput component.
|
|
type TextInputStyle uint
|
|
|
|
// Text styles
|
|
const (
|
|
TextInputShort TextInputStyle = 1
|
|
TextInputParagraph TextInputStyle = 2
|
|
)
|