Skip to content

Commit 7bd477a

Browse files
committed
feat: enhance modal interaction data with resolved values
1 parent f391b60 commit 7bd477a

File tree

6 files changed

+180
-6
lines changed

6 files changed

+180
-6
lines changed

discord/component.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,8 @@ type FileUploadComponent struct {
14301430
MaxValues int `json:"max_values,omitempty"`
14311431
// Required specifies whether the file upload is required. (default: false)
14321432
Required bool `json:"required"`
1433+
// Values is only set when the FileUploadComponent is received from an InteractionTypeModalSubmit
1434+
Values []snowflake.ID `json:"values,omitempty"`
14331435
}
14341436

14351437
func (f FileUploadComponent) component() {}

discord/interaction.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ type ResolvedMember struct {
151151
Permissions Permissions `json:"permissions,omitempty"`
152152
}
153153

154+
func (ResolvedMember) isMentionableValue() {}
155+
154156
type ResolvedChannel struct {
155157
ID snowflake.ID `json:"id"`
156158
Name string `json:"name"`
@@ -160,6 +162,8 @@ type ResolvedChannel struct {
160162
ParentID snowflake.ID `json:"parent_id"`
161163
}
162164

165+
func (ResolvedChannel) isMentionableValue() {}
166+
163167
type InteractionChannel struct {
164168
MessageChannel
165169
Permissions Permissions `json:"permissions"`

discord/interaction_modal_submit.go

Lines changed: 162 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ type ModalSubmitInteraction struct {
2020
func (i *ModalSubmitInteraction) UnmarshalJSON(data []byte) error {
2121
var interaction struct {
2222
rawInteraction
23-
Data ModalSubmitInteractionData `json:"data"`
24-
Message *Message `json:"message,omitempty"`
23+
Data ModalSubmitInteractionData `json:"data"`
24+
Message *Message `json:"message,omitempty"`
25+
Resolved ResolvedData
2526
}
2627
if err := json.Unmarshal(data, &interaction); err != nil {
2728
return err
@@ -96,6 +97,7 @@ func (ModalSubmitInteraction) interaction() {}
9697
type ModalSubmitInteractionData struct {
9798
CustomID string `json:"custom_id"`
9899
Components []LayoutComponent `json:"components"`
100+
Resolved ResolvedData `json:"resolved"`
99101
}
100102

101103
func (d *ModalSubmitInteractionData) UnmarshalJSON(data []byte) error {
@@ -131,7 +133,7 @@ func (d ModalSubmitInteractionData) Component(customID string) (InteractiveCompo
131133
return nil, false
132134
}
133135

134-
func (d ModalSubmitInteractionData) TextInputComponent(customID string) (TextInputComponent, bool) {
136+
func (d ModalSubmitInteractionData) TextInput(customID string) (TextInputComponent, bool) {
135137
if component, ok := d.Component(customID); ok {
136138
textInputComponent, ok := component.(TextInputComponent)
137139
return textInputComponent, ok
@@ -140,7 +142,7 @@ func (d ModalSubmitInteractionData) TextInputComponent(customID string) (TextInp
140142
}
141143

142144
func (d ModalSubmitInteractionData) OptText(customID string) (string, bool) {
143-
if textInputComponent, ok := d.TextInputComponent(customID); ok {
145+
if textInputComponent, ok := d.TextInput(customID); ok {
144146
return textInputComponent.Value, true
145147
}
146148
return "", false
@@ -153,7 +155,7 @@ func (d ModalSubmitInteractionData) Text(customID string) string {
153155
return ""
154156
}
155157

156-
func (d ModalSubmitInteractionData) StringSelectMenuComponent(customID string) (StringSelectMenuComponent, bool) {
158+
func (d ModalSubmitInteractionData) StringSelectMenu(customID string) (StringSelectMenuComponent, bool) {
157159
if component, ok := d.Component(customID); ok {
158160
selectMenuComponent, ok := component.(StringSelectMenuComponent)
159161
return selectMenuComponent, ok
@@ -162,7 +164,7 @@ func (d ModalSubmitInteractionData) StringSelectMenuComponent(customID string) (
162164
}
163165

164166
func (d ModalSubmitInteractionData) OptStringValues(customID string) ([]string, bool) {
165-
if selectMenuComponent, ok := d.StringSelectMenuComponent(customID); ok {
167+
if selectMenuComponent, ok := d.StringSelectMenu(customID); ok {
166168
return selectMenuComponent.Values, true
167169
}
168170
return nil, false
@@ -174,3 +176,157 @@ func (d ModalSubmitInteractionData) StringValues(customID string) []string {
174176
}
175177
return nil
176178
}
179+
180+
func (d ModalSubmitInteractionData) UserSelectMenu(customID string) (UserSelectMenuComponent, bool) {
181+
if component, ok := d.Component(customID); ok {
182+
selectMenuComponent, ok := component.(UserSelectMenuComponent)
183+
return selectMenuComponent, ok
184+
}
185+
return UserSelectMenuComponent{}, false
186+
}
187+
188+
func (d ModalSubmitInteractionData) OptUsers(customID string) ([]User, bool) {
189+
if selectMenuComponent, ok := d.UserSelectMenu(customID); ok {
190+
users := make([]User, 0, len(selectMenuComponent.Values))
191+
for _, userID := range selectMenuComponent.Values {
192+
if user, ok := d.Resolved.Users[userID]; ok {
193+
users = append(users, user)
194+
}
195+
}
196+
return users, true
197+
}
198+
return nil, false
199+
}
200+
201+
func (d ModalSubmitInteractionData) Users(customID string) []User {
202+
if users, ok := d.OptUsers(customID); ok {
203+
return users
204+
}
205+
return nil
206+
}
207+
208+
func (d ModalSubmitInteractionData) RoleSelectMenu(customID string) (RoleSelectMenuComponent, bool) {
209+
if component, ok := d.Component(customID); ok {
210+
selectMenuComponent, ok := component.(RoleSelectMenuComponent)
211+
return selectMenuComponent, ok
212+
}
213+
return RoleSelectMenuComponent{}, false
214+
}
215+
216+
func (d ModalSubmitInteractionData) OptRoles(customID string) ([]Role, bool) {
217+
if selectMenuComponent, ok := d.RoleSelectMenu(customID); ok {
218+
roles := make([]Role, 0, len(selectMenuComponent.Values))
219+
for _, roleID := range selectMenuComponent.Values {
220+
if role, ok := d.Resolved.Roles[roleID]; ok {
221+
roles = append(roles, role)
222+
}
223+
}
224+
return roles, true
225+
}
226+
return nil, false
227+
}
228+
229+
func (d ModalSubmitInteractionData) Roles(customID string) []Role {
230+
if roles, ok := d.OptRoles(customID); ok {
231+
return roles
232+
}
233+
return nil
234+
}
235+
236+
// MentionableValue is an interface for all values a [MentionableSelectMenuComponent] can return.
237+
// [User]
238+
// [ResolvedMember]
239+
// [Role]
240+
// [ResolvedChannel]
241+
type MentionableValue interface {
242+
isMentionableValue()
243+
}
244+
245+
func (d ModalSubmitInteractionData) MentionableSelectMenu(customID string) (MentionableSelectMenuComponent, bool) {
246+
if component, ok := d.Component(customID); ok {
247+
selectMenuComponent, ok := component.(MentionableSelectMenuComponent)
248+
return selectMenuComponent, ok
249+
}
250+
return MentionableSelectMenuComponent{}, false
251+
}
252+
253+
func (d ModalSubmitInteractionData) OptMentionables(customID string) ([]Mentionable, bool) {
254+
if selectMenuComponent, ok := d.MentionableSelectMenu(customID); ok {
255+
mentionables := make([]Mentionable, 0, len(selectMenuComponent.Values))
256+
for _, id := range selectMenuComponent.Values {
257+
if user, ok := d.Resolved.Users[id]; ok {
258+
mentionables = append(mentionables, user)
259+
continue
260+
}
261+
if role, ok := d.Resolved.Roles[id]; ok {
262+
mentionables = append(mentionables, role)
263+
continue
264+
}
265+
}
266+
return mentionables, true
267+
}
268+
return nil, false
269+
}
270+
271+
func (d ModalSubmitInteractionData) Mentionables(customID string) []Mentionable {
272+
if mentionables, ok := d.OptMentionables(customID); ok {
273+
return mentionables
274+
}
275+
return nil
276+
}
277+
278+
func (d ModalSubmitInteractionData) ChannelSelectMenu(customID string) (ChannelSelectMenuComponent, bool) {
279+
if component, ok := d.Component(customID); ok {
280+
selectMenuComponent, ok := component.(ChannelSelectMenuComponent)
281+
return selectMenuComponent, ok
282+
}
283+
return ChannelSelectMenuComponent{}, false
284+
}
285+
286+
func (d ModalSubmitInteractionData) OptChannels(customID string) ([]ResolvedChannel, bool) {
287+
if selectMenuComponent, ok := d.ChannelSelectMenu(customID); ok {
288+
channels := make([]ResolvedChannel, 0, len(selectMenuComponent.Values))
289+
for _, channelID := range selectMenuComponent.Values {
290+
if channel, ok := d.Resolved.Channels[channelID]; ok {
291+
channels = append(channels, channel)
292+
}
293+
}
294+
return channels, true
295+
}
296+
return nil, false
297+
}
298+
299+
func (d ModalSubmitInteractionData) Channels(customID string) []ResolvedChannel {
300+
if channels, ok := d.OptChannels(customID); ok {
301+
return channels
302+
}
303+
return nil
304+
}
305+
306+
func (d ModalSubmitInteractionData) FileUpload(customID string) (FileUploadComponent, bool) {
307+
if component, ok := d.Component(customID); ok {
308+
fileUploadComponent, ok := component.(FileUploadComponent)
309+
return fileUploadComponent, ok
310+
}
311+
return FileUploadComponent{}, false
312+
}
313+
314+
func (d ModalSubmitInteractionData) OptAttachments(customID string) ([]Attachment, bool) {
315+
if fileUploadComponent, ok := d.FileUpload(customID); ok {
316+
attachments := make([]Attachment, 0, len(fileUploadComponent.Values))
317+
for _, attachmentID := range fileUploadComponent.Values {
318+
if attachment, ok := d.Resolved.Attachments[attachmentID]; ok {
319+
attachments = append(attachments, attachment)
320+
}
321+
}
322+
return attachments, true
323+
}
324+
return nil, false
325+
}
326+
327+
func (d ModalSubmitInteractionData) Attachments(customID string) []Attachment {
328+
if attachments, ok := d.OptAttachments(customID); ok {
329+
return attachments
330+
}
331+
return nil
332+
}

discord/role.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ type Role struct {
2828
Flags RoleFlags `json:"flags"`
2929
}
3030

31+
func (Role) isMentionableValue() {}
32+
3133
func (r Role) String() string {
3234
return RoleMention(r.ID)
3335
}

discord/select_menu.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ type UserSelectMenuComponent struct {
240240
Required bool `json:"required"`
241241
// Disabled whether the select menu is disabled (only supported in messages)
242242
Disabled bool `json:"disabled"`
243+
// Values is only set when the UserSelectMenuComponent is received from an InteractionTypeModalSubmit
244+
Values []snowflake.ID `json:"values,omitempty"`
243245
}
244246

245247
func (c UserSelectMenuComponent) MarshalJSON() ([]byte, error) {
@@ -374,6 +376,8 @@ type RoleSelectMenuComponent struct {
374376
Required bool `json:"required"`
375377
// Disabled whether the select menu is disabled (only supported in messages)
376378
Disabled bool `json:"disabled"`
379+
// Values is only set when the RoleSelectMenuComponent is received from an InteractionTypeModalSubmit
380+
Values []snowflake.ID `json:"values,omitempty"`
377381
}
378382

379383
func (c RoleSelectMenuComponent) MarshalJSON() ([]byte, error) {
@@ -508,6 +512,8 @@ type MentionableSelectMenuComponent struct {
508512
Required bool `json:"required"`
509513
// Disabled whether the select menu is disabled (only supported in messages)
510514
Disabled bool `json:"disabled"`
515+
// Values is only set when the MentionableSelectMenuComponent is received from an InteractionTypeModalSubmit
516+
Values []snowflake.ID `json:"values,omitempty"`
511517
}
512518

513519
func (c MentionableSelectMenuComponent) MarshalJSON() ([]byte, error) {
@@ -640,6 +646,8 @@ type ChannelSelectMenuComponent struct {
640646
Required bool `json:"required"`
641647
// Disabled whether the select menu is disabled (only supported in messages)
642648
Disabled bool `json:"disabled"`
649+
// Values is only set when the ChannelSelectMenuComponent is received from an InteractionTypeModalSubmit
650+
Values []snowflake.ID `json:"values,omitempty"`
643651
}
644652

645653
func (c ChannelSelectMenuComponent) MarshalJSON() ([]byte, error) {

discord/user.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ type User struct {
8080
PrimaryGuild *PrimaryGuild `json:"primary_guild"`
8181
}
8282

83+
func (User) isMentionableValue() {}
84+
8385
// String returns a mention of the user
8486
func (u User) String() string {
8587
return UserMention(u.ID)

0 commit comments

Comments
 (0)