1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2024-09-29 13:48:53 +00:00

discord: Modal interaction support (#310)

* Support modal interactions along with the TextInput component

* Replace ModalInteraction with Modal to prevent confusion

* Fix the required field from not being used correctly

* PR Fixes
This commit is contained in:
ItsLychee 2022-02-13 21:15:28 -06:00 committed by GitHub
parent 7727d140a0
commit d6bc738e50
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 91 additions and 0 deletions

View file

@ -25,6 +25,7 @@ const (
DeferredMessageUpdate
UpdateMessage
AutocompleteResult
ModalResponse
)
// InteractionResponseFlags implements flags for an
@ -78,6 +79,11 @@ type InteractionResponseData struct {
//
// During all other events, this should not be provided.
Choices *[]AutocompleteChoice `json:"choices"`
// CustomID used with the modal
CustomID option.NullableString `json:"custom_id,omitempty"`
// Title is the heading of the modal window
Title option.NullableString `json:"title,omitempty"`
}
// NeedsMultipart returns true if the InteractionResponseData has files.

View file

@ -4,6 +4,7 @@ import (
"fmt"
"github.com/diamondburned/arikawa/v3/utils/json"
"github.com/diamondburned/arikawa/v3/utils/json/option"
"github.com/pkg/errors"
)
@ -15,6 +16,7 @@ const (
ActionRowComponentType
ButtonComponentType
SelectComponentType
TextInputComponentType
)
// String formats Type's name as a string.
@ -26,6 +28,8 @@ func (t ComponentType) String() string {
return "Button"
case SelectComponentType:
return "Select"
case TextInputComponentType:
return "TextInput"
default:
return fmt.Sprintf("ComponentType(%d)", int(t))
}
@ -126,6 +130,8 @@ func ParseComponent(b []byte) (Component, error) {
c = &ButtonComponent{}
case SelectComponentType:
c = &SelectComponent{}
case TextInputComponentType:
c = &TextInputComponent{}
default:
c = &UnknownComponent{typ: t.Type}
}
@ -448,6 +454,69 @@ func (s *SelectComponent) MarshalJSON() ([]byte, error) {
return json.Marshal(msg)
}
type TextInputStyle uint8
const (
_ TextInputStyle = iota
TextInputShortStyle
TextInputParagraphStyle
)
// TextInputComponents provide a user-facing text box to be filled out. They can only
// be used with modals.
type TextInputComponent struct {
// CustomID provides a developer-defined ID for the input (max 100 chars)
CustomID ComponentID `json:"custom_id"`
// Style determines if the component should use the short or paragraph style
Style TextInputStyle `json:"style"`
// Label is the title of this component, describing its use
Label string `json:"label"`
// ValueLimits is the minimum and maximum length for the input
ValueLimits [2]int `json:"-"`
// Required dictates whether or not the user must fill out the component
Required bool `json:"required"`
// Value is the pre-filled value of this component (max 4000 chars)
Value option.NullableString `json:"value,omitempty"`
// Placeholder is the text that appears when the input is empty (max 100 chars)
Placeholder option.NullableString `json:"placeholder,omitempty"`
}
func (s *TextInputComponent) _cmp() {}
func (s *TextInputComponent) _icp() {}
func (i *TextInputComponent) ID() ComponentID {
return i.CustomID
}
func (i *TextInputComponent) Type() ComponentType {
return TextInputComponentType
}
func (i *TextInputComponent) MarshalJSON() ([]byte, error) {
type text TextInputComponent
type Msg struct {
Type ComponentType `json:"type"`
*text
MinValues *int `json:"max_values,omitempty"`
MaxValues *int `json:"min_values,omitempty"`
}
m := Msg{
Type: i.Type(),
text: (*text)(i),
}
if i.ValueLimits != [2]int{0, 0} {
m.MinValues = new(int)
m.MaxValues = new(int)
*m.MinValues = i.ValueLimits[0]
*m.MaxValues = i.ValueLimits[1]
}
return json.Marshal(m)
}
// Unknown is reserved for components with unknown or not yet implemented
// components types. It can also be used in place of a ComponentInteraction.
type UnknownComponent struct {

View file

@ -86,6 +86,8 @@ func (e *InteractionEvent) UnmarshalJSON(b []byte) error {
return nil
case AutocompleteInteractionType:
e.Data = &AutocompleteInteraction{}
case ModalInteractionType:
e.Data = &ModalInteraction{}
default:
e.Data = &UnknownInteractionData{
Raw: target.Data,
@ -131,6 +133,7 @@ const (
CommandInteractionType
ComponentInteractionType
AutocompleteInteractionType
ModalInteractionType
)
// InteractionData holds the respose data of an interaction, or more
@ -365,6 +368,19 @@ func (o CommandInteractionOption) FloatValue() (float64, error) {
return f, err
}
// ModalInteraction is the submitted modal form
type ModalInteraction struct {
CustomID ComponentID `json:"custom_id"`
Components ContainerComponents `json:"components"`
}
// InteractionType implements InteractionData.
func (m *ModalInteraction) InteractionType() InteractionDataType {
return ModalInteractionType
}
func (m *ModalInteraction) data() {}
// UnknownInteractionData describes an Interaction response with an unknown
// type.
type UnknownInteractionData struct {