From 8f4bb6c8bbe22a7039bc051b3bf5cbe5b7f3597d Mon Sep 17 00:00:00 2001 From: TopiSenpai Date: Sat, 8 Jan 2022 19:53:43 +0100 Subject: [PATCH 1/4] refactor discord interactions --- discord/interaction.go | 320 ++++++++++++++++++++--------------------- 1 file changed, 158 insertions(+), 162 deletions(-) diff --git a/discord/interaction.go b/discord/interaction.go index 91913257..4babd2a4 100644 --- a/discord/interaction.go +++ b/discord/interaction.go @@ -19,7 +19,7 @@ const ( // Interaction is used for easier unmarshalling of different Interaction(s) type Interaction interface { - InteractionType() InteractionType + Type() InteractionType interaction() } @@ -52,41 +52,14 @@ func (i *UnmarshalInteraction) UnmarshalJSON(data []byte) error { interaction = v case InteractionTypeApplicationCommand: - switch iType.Data.ApplicationCommandType { - case ApplicationCommandTypeSlash: - v := SlashCommandInteraction{} - err = json.Unmarshal(data, &v) - interaction = v - - case ApplicationCommandTypeUser: - v := UserCommandInteraction{} - err = json.Unmarshal(data, &v) - interaction = v - - case ApplicationCommandTypeMessage: - v := MessageCommandInteraction{} - err = json.Unmarshal(data, &v) - interaction = v - - default: - return fmt.Errorf("unkown application command interaction with type %d received", iType.Data.ApplicationCommandType) - } + v := ApplicationCommandInteraction{} + err = json.Unmarshal(data, &v) + interaction = v case InteractionTypeComponent: - switch iType.Data.ComponentType { - case ComponentTypeButton: - v := ButtonInteraction{} - err = json.Unmarshal(data, &v) - interaction = v - - case ComponentTypeSelectMenu: - v := SelectMenuInteraction{} - err = json.Unmarshal(data, &v) - interaction = v - - default: - return fmt.Errorf("unkown component interaction with type %d received", iType.Data.ComponentType) - } + v := ComponentInteraction{} + err = json.Unmarshal(data, &v) + interaction = v case InteractionTypeAutocomplete: v := AutocompleteInteraction{} @@ -115,35 +88,82 @@ type PingInteraction struct { func (PingInteraction) interaction() {} -func (PingInteraction) InteractionType() InteractionType { +func (PingInteraction) Type() InteractionType { return InteractionTypePing } -type ApplicationCommandInteraction interface { - Interaction - ApplicationCommandType() ApplicationCommandType - applicationCommandInteraction() -} - var ( - _ Interaction = (*SlashCommandInteraction)(nil) - _ ApplicationCommandInteraction = (*SlashCommandInteraction)(nil) + _ Interaction = (*ApplicationCommandInteraction)(nil) ) -type SlashCommandInteraction struct { - ID Snowflake `json:"id"` - ApplicationID Snowflake `json:"application_id"` - Token string `json:"token"` - Version int `json:"version"` - GuildID *Snowflake `json:"guild_id,omitempty"` - ChannelID Snowflake `json:"channel_id"` - Member *Member `json:"member,omitempty"` - User *User `json:"user,omitempty"` - Data SlashCommandInteractionData `json:"data"` +type ApplicationCommandInteraction struct { + ID Snowflake `json:"id"` + ApplicationID Snowflake `json:"application_id"` + Token string `json:"token"` + Version int `json:"version"` + GuildID *Snowflake `json:"guild_id,omitempty"` + ChannelID Snowflake `json:"channel_id"` + Member *Member `json:"member,omitempty"` + User *User `json:"user,omitempty"` + Data ApplicationCommandInteractionData `json:"data"` +} + +func (ApplicationCommandInteraction) interaction() {} +func (ApplicationCommandInteraction) applicationCommandInteraction() {} +func (ApplicationCommandInteraction) Type() InteractionType { + return InteractionTypeApplicationCommand +} + +func (i *ApplicationCommandInteraction) UnmarshalJSON(data []byte) error { + type applicationCommandInteraction ApplicationCommandInteraction + var cType struct { + Data struct { + Type ApplicationCommandType `json:"type"` + } `json:"data"` + applicationCommandInteraction + } + + if err := json.Unmarshal(data, &cType); err != nil { + return err + } + + var ( + interactionData ApplicationCommandInteractionData + err error + ) + switch cType.Type { + case ApplicationCommandTypeSlash: + v := SlashCommandInteractionData{} + err = json.Unmarshal(data, &v) + interactionData = v + + case ApplicationCommandTypeUser: + v := UserCommandInteractionData{} + err = json.Unmarshal(data, &v) + interactionData = v + + case ApplicationCommandTypeMessage: + v := MessageCommandInteractionData{} + err = json.Unmarshal(data, &v) + interactionData = v + + default: + return fmt.Errorf("unkown application interaction data with type %d received", cType.Type) + } + if err != nil { + return err + } + + *i = ApplicationCommandInteraction(cType.applicationCommandInteraction) + + i.Data = interactionData + return nil } -func (SlashCommandInteraction) interaction() {} -func (SlashCommandInteraction) applicationCommandInteraction() {} +type ApplicationCommandInteractionData interface { + applicationCommandInteractionData() + Type() ApplicationCommandType +} type SlashCommandInteractionData struct { CommandID Snowflake `json:"id"` @@ -152,6 +172,11 @@ type SlashCommandInteractionData struct { Options []SlashCommandOption `json:"options"` } +func (SlashCommandInteractionData) applicationCommandInteractionData() {} +func (SlashCommandInteractionData) Type() ApplicationCommandType { + return ApplicationCommandTypeSlash +} + func (d *SlashCommandInteractionData) UnmarshalJSON(data []byte) error { type slashCommandInteractionData SlashCommandInteractionData var iData struct { @@ -182,34 +207,10 @@ type SlashCommandResolved struct { Channels map[Snowflake]Channel `json:"channels,omitempty"` } -func (SlashCommandInteraction) InteractionType() InteractionType { - return InteractionTypeComponent -} - -func (SlashCommandInteraction) ApplicationCommandType() ApplicationCommandType { - return ApplicationCommandTypeSlash -} - var ( - _ Interaction = (*UserCommandInteraction)(nil) - _ ApplicationCommandInteraction = (*UserCommandInteraction)(nil) + _ ApplicationCommandInteractionData = (*UserCommandInteractionData)(nil) ) -func (UserCommandInteraction) interaction() {} -func (UserCommandInteraction) applicationCommandInteraction() {} - -type UserCommandInteraction struct { - ID Snowflake `json:"id"` - ApplicationID Snowflake `json:"application_id"` - Token string `json:"token"` - Version int `json:"version"` - GuildID *Snowflake `json:"guild_id,omitempty"` - ChannelID Snowflake `json:"channel_id"` - Member *Member `json:"member,omitempty"` - User *User `json:"user,omitempty"` - Data UserCommandInteractionData `json:"data"` -} - type UserCommandInteractionData struct { CommandID Snowflake `json:"id"` CommandName string `json:"name"` @@ -217,39 +218,20 @@ type UserCommandInteractionData struct { TargetID Snowflake `json:"target_id"` } +func (UserCommandInteractionData) applicationCommandInteractionData() {} +func (UserCommandInteractionData) Type() ApplicationCommandType { + return ApplicationCommandTypeUser +} + type UserCommandResolved struct { Users map[Snowflake]User `json:"users,omitempty"` Members map[Snowflake]Member `json:"members,omitempty"` } -func (UserCommandInteraction) InteractionType() InteractionType { - return InteractionTypeComponent -} - -func (UserCommandInteraction) ApplicationCommandType() ApplicationCommandType { - return ApplicationCommandTypeUser -} - var ( - _ Interaction = (*MessageCommandInteraction)(nil) - _ ApplicationCommandInteraction = (*MessageCommandInteraction)(nil) + _ ApplicationCommandInteractionData = (*MessageCommandInteractionData)(nil) ) -type MessageCommandInteraction struct { - ID Snowflake `json:"id"` - ApplicationID Snowflake `json:"application_id"` - Token string `json:"token"` - Version int `json:"version"` - GuildID *Snowflake `json:"guild_id,omitempty"` - ChannelID Snowflake `json:"channel_id"` - Member *Member `json:"member,omitempty"` - User *User `json:"user,omitempty"` - Data MessageCommandInteractionData `json:"data"` -} - -func (MessageCommandInteraction) interaction() {} -func (MessageCommandInteraction) applicationCommandInteraction() {} - type MessageCommandInteractionData struct { CommandID Snowflake `json:"id"` CommandName string `json:"name"` @@ -257,88 +239,103 @@ type MessageCommandInteractionData struct { TargetID Snowflake `json:"target_id"` } +func (MessageCommandInteractionData) applicationCommandInteractionData() {} +func (MessageCommandInteractionData) Type() ApplicationCommandType { + return ApplicationCommandTypeMessage +} + type MessageCommandResolved struct { Messages map[Snowflake]Message `json:"messages,omitempty"` } -func (MessageCommandInteraction) InteractionType() InteractionType { +var ( + _ Interaction = (*ComponentInteraction)(nil) +) + +type ComponentInteraction struct { + ID Snowflake `json:"id"` + ApplicationID Snowflake `json:"application_id"` + Token string `json:"token"` + Version int `json:"version"` + GuildID *Snowflake `json:"guild_id,omitempty"` + ChannelID Snowflake `json:"channel_id"` + Member *Member `json:"member,omitempty"` + User *User `json:"user,omitempty"` + Data ComponentInteractionData `json:"data"` + Message Message `json:"message"` +} + +func (ComponentInteraction) interaction() {} +func (ComponentInteraction) Type() InteractionType { return InteractionTypeComponent } -func (MessageCommandInteraction) ApplicationCommandType() ApplicationCommandType { - return ApplicationCommandTypeMessage -} +func (i *ComponentInteraction) UnmarshalJSON(data []byte) error { + type componentInteraction ComponentInteraction + var cType struct { + Data struct { + Type ComponentType `json:"component_type"` + } `json:"data"` + componentInteraction + } -type ComponentInteraction interface { - Interaction - ComponentType() ComponentType - componentInteraction() -} + if err := json.Unmarshal(data, &cType); err != nil { + return err + } -var ( - _ Interaction = (*ButtonInteraction)(nil) - _ ComponentInteraction = (*ButtonInteraction)(nil) -) + var ( + interactionData ComponentInteractionData + err error + ) + switch cType.Data.Type { + case ComponentTypeButton: + v := ButtonInteractionData{} + err = json.Unmarshal(data, &v) + interactionData = v -type ButtonInteraction struct { - ID Snowflake `json:"id"` - ApplicationID Snowflake `json:"application_id"` - Token string `json:"token"` - Version int `json:"version"` - GuildID *Snowflake `json:"guild_id,omitempty"` - ChannelID Snowflake `json:"channel_id"` - Member *Member `json:"member,omitempty"` - User *User `json:"user,omitempty"` - Data ButtonInteractionData `json:"data"` - Message Message `json:"message"` -} + case ComponentTypeSelectMenu: + v := SelectMenuInteractionData{} + err = json.Unmarshal(data, &v) + interactionData = v -type ButtonInteractionData struct { - CustomID CustomID `json:"custom_id"` + default: + return fmt.Errorf("unkown application interaction data with type %d received", cType.Data.Type) + } + if err != nil { + return err + } + + *i = ComponentInteraction(cType.componentInteraction) + + i.Data = interactionData + return nil } -func (ButtonInteraction) interaction() {} -func (ButtonInteraction) componentInteraction() {} +type ComponentInteractionData interface { + componentInteractionData() + Type() ComponentType +} -func (ButtonInteraction) InteractionType() InteractionType { - return InteractionTypeComponent +type ButtonInteractionData struct { + CustomID CustomID `json:"custom_id"` } -func (ButtonInteraction) ComponentType() ComponentType { +func (ButtonInteractionData) componentInteractionData() {} +func (ButtonInteractionData) Type() ComponentType { return ComponentTypeButton } var ( - _ Interaction = (*SelectMenuInteraction)(nil) - _ ComponentInteraction = (*SelectMenuInteraction)(nil) + _ ComponentInteractionData = (*SelectMenuInteractionData)(nil) ) -type SelectMenuInteraction struct { - ID Snowflake `json:"id"` - ApplicationID Snowflake `json:"application_id"` - Token string `json:"token"` - Version int `json:"version"` - GuildID *Snowflake `json:"guild_id,omitempty"` - ChannelID Snowflake `json:"channel_id"` - Member *Member `json:"member,omitempty"` - User *User `json:"user,omitempty"` - Data SelectMenuInteractionData `json:"data"` - Message Message `json:"message"` -} - type SelectMenuInteractionData struct { CustomID CustomID `json:"custom_id"` Values []string `json:"values"` } -func (SelectMenuInteraction) interaction() {} -func (SelectMenuInteraction) componentInteraction() {} - -func (SelectMenuInteraction) InteractionType() InteractionType { - return InteractionTypeComponent -} - -func (SelectMenuInteraction) ComponentType() ComponentType { +func (SelectMenuInteractionData) componentInteractionData() {} +func (SelectMenuInteractionData) Type() ComponentType { return ComponentTypeSelectMenu } @@ -359,8 +356,7 @@ type AutocompleteInteraction struct { } func (AutocompleteInteraction) interaction() {} - -func (AutocompleteInteraction) InteractionType() InteractionType { +func (AutocompleteInteraction) Type() InteractionType { return InteractionTypeAutocomplete } From d98eabea5ca8bbc69fe050ea1d8fbabbf8bdb1e6 Mon Sep 17 00:00:00 2001 From: TopiSenpai Date: Sun, 9 Jan 2022 14:24:08 +0100 Subject: [PATCH 2/4] cleanup of core interactions package --- .../application_commands/gateway/example.go | 12 +- .../application_commands/http/example.go | 22 +- _examples/components/example.go | 4 +- _examples/oauth2/example.go | 2 +- _examples/test/listeners.go | 92 ++--- core/application_command_interaction.go | 87 ++++ core/autocomplete_interaction.go | 84 ++-- core/button_interaction.go | 79 ---- core/collectors.go | 42 +- ...lication_command_interaction_collector.go} | 8 +- ... => autocomplete_interaction_collector.go} | 14 +- core/collectors/button_click_collector.go | 42 -- ....go => component_interaction_collector.go} | 8 +- core/collectors/config.go | 7 +- .../interaction_create_collector.go | 2 +- core/collectors/message_command_collector.go | 42 -- .../select_menu_submit_collector.go | 41 -- core/collectors/slash_command_collector.go | 42 -- core/collectors/user_command_collector.go | 42 -- core/component_interaction.go | 93 +++++ core/entity_builder.go | 375 ++++++++---------- core/events/events_interactions.go | 40 +- core/events/listener_adapter.go | 49 +-- .../gateway_handler_interaction_create.go | 54 +-- .../httpserver_handler_interaction_create.go | 2 +- core/interaction.go | 188 +++------ core/message_command_interaction.go | 79 ---- core/select_menu_interaction.go | 103 ----- core/slash_command_interaction.go | 327 --------------- core/slash_command_option.go | 240 +++++++++++ core/user_command_interaction.go | 84 ---- discord/interaction.go | 63 ++- 32 files changed, 839 insertions(+), 1530 deletions(-) create mode 100644 core/application_command_interaction.go delete mode 100644 core/button_interaction.go rename core/collectors/{application_command_interaction_create_collector.go => application_command_interaction_collector.go} (79%) rename core/collectors/{autocomplete_collector.go => autocomplete_interaction_collector.go} (51%) delete mode 100644 core/collectors/button_click_collector.go rename core/collectors/{component_interaction_create_collector.go => component_interaction_collector.go} (81%) delete mode 100644 core/collectors/message_command_collector.go delete mode 100644 core/collectors/select_menu_submit_collector.go delete mode 100644 core/collectors/slash_command_collector.go delete mode 100644 core/collectors/user_command_collector.go create mode 100644 core/component_interaction.go delete mode 100644 core/message_command_interaction.go delete mode 100644 core/select_menu_interaction.go delete mode 100644 core/slash_command_interaction.go delete mode 100644 core/user_command_interaction.go diff --git a/_examples/application_commands/gateway/example.go b/_examples/application_commands/gateway/example.go index 4f0813e2..0a9b98d8 100644 --- a/_examples/application_commands/gateway/example.go +++ b/_examples/application_commands/gateway/example.go @@ -45,7 +45,7 @@ func main() { bot.WithGatewayOpts(gateway.WithGatewayIntents(discord.GatewayIntentsNone)), bot.WithCacheOpts(core.WithCacheFlags(core.CacheFlagsDefault)), bot.WithEventListeners(&events.ListenerAdapter{ - OnSlashCommand: commandListener, + OnApplicationCommandInteraction: commandListener, }), ) if err != nil { @@ -55,8 +55,7 @@ func main() { defer disgo.Close(context.TODO()) - _, err = disgo.SetGuildCommands(guildID, commands) - if err != nil { + if _, err = disgo.SetGuildCommands(guildID, commands); err != nil { log.Fatal("error while registering commands: ", err) } @@ -70,10 +69,11 @@ func main() { <-s } -func commandListener(event *events.SlashCommandEvent) { - if event.Data.CommandName == "say" { +func commandListener(event *events.ApplicationCommandInteractionEvent) { + data := event.SlashCommandInteractionData() + if data.CommandName == "say" { err := event.Create(discord.NewMessageCreateBuilder(). - SetContent(*event.Data.Options.String("message")). + SetContent(*data.Options.String("message")). Build(), ) if err != nil { diff --git a/_examples/application_commands/http/example.go b/_examples/application_commands/http/example.go index 93707581..742f372d 100644 --- a/_examples/application_commands/http/example.go +++ b/_examples/application_commands/http/example.go @@ -48,7 +48,7 @@ func main() { httpserver.WithPublicKey(publicKey), ), bot.WithEventListeners(&events.ListenerAdapter{ - OnSlashCommand: commandListener, + OnApplicationCommandInteraction: commandListener, }), ) if err != nil { @@ -58,13 +58,11 @@ func main() { defer disgo.Close(context.TODO()) - _, err = disgo.SetGuildCommands(guildID, commands) - if err != nil { + if _, err = disgo.SetGuildCommands(guildID, commands); err != nil { log.Fatal("error while registering commands: ", err) } - err = disgo.StartHTTPServer() - if err != nil { + if err = disgo.StartHTTPServer(); err != nil { log.Fatal("error while starting http server: ", err) } @@ -74,13 +72,15 @@ func main() { <-s } -func commandListener(event *events.SlashCommandEvent) { - if event.Data.CommandName == "say" { - if err := event.Create(discord.NewMessageCreateBuilder(). - SetContent(*event.Data.Options.String("message")). +func commandListener(event *events.ApplicationCommandInteractionEvent) { + data := event.SlashCommandInteractionData() + if data.CommandName == "say" { + err := event.Create(discord.NewMessageCreateBuilder(). + SetContent(*data.Options.String("message")). Build(), - ); err != nil { - log.Error("error sending interaction response: ", err) + ) + if err != nil { + event.Bot().Logger.Error("error on sending response: ", err) } } } diff --git a/_examples/components/example.go b/_examples/components/example.go index 26d6157b..84087597 100644 --- a/_examples/components/example.go +++ b/_examples/components/example.go @@ -38,8 +38,8 @@ func main() { ) } }, - OnButtonClick: func(event *events.ButtonClickEvent) { - if event.Data.CustomID == "danger" { + OnComponentInteraction: func(event *events.ComponentInteractionEvent) { + if event.ButtonInteractionData().CustomID == "danger" { _ = event.Create(discord.NewMessageCreateBuilder().SetEphemeral(true).SetContent("Ey that was danger").Build()) } }, diff --git a/_examples/oauth2/example.go b/_examples/oauth2/example.go index 4e563d22..392065a6 100644 --- a/_examples/oauth2/example.go +++ b/_examples/oauth2/example.go @@ -85,7 +85,7 @@ func handleRoot(w http.ResponseWriter, r *http.Request) { } func handleLogin(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, client.GenerateAuthorizationURL(baseURL+"/trylogin", discord.ApplicationScopeIdentify, discord.ApplicationScopeGuilds, discord.ApplicationScopeEmail, discord.ApplicationScopeConnections, discord.ApplicationScopeWebhookIncoming), http.StatusMovedPermanently) + http.Redirect(w, r, client.GenerateAuthorizationURL(baseURL+"/trylogin", discord.PermissionsNone, "", false, discord.ApplicationScopeIdentify, discord.ApplicationScopeGuilds, discord.ApplicationScopeEmail, discord.ApplicationScopeConnections, discord.ApplicationScopeWebhookIncoming), http.StatusMovedPermanently) } func handleTryLogin(w http.ResponseWriter, r *http.Request) { diff --git a/_examples/test/listeners.go b/_examples/test/listeners.go index 3a0f881a..a8b3ec4d 100644 --- a/_examples/test/listeners.go +++ b/_examples/test/listeners.go @@ -15,53 +15,55 @@ import ( ) var listener = &events.ListenerAdapter{ - OnGuildMessageCreate: messageListener, - OnSlashCommand: slashCommandListener, - OnButtonClick: buttonClickListener, - OnSelectMenuSubmit: selectMenuSubmitListener, + OnGuildMessageCreate: messageListener, + OnApplicationCommandInteraction: applicationCommandListener, + OnComponentInteraction: componentListener, } -func buttonClickListener(event *events.ButtonClickEvent) { - switch event.Data.CustomID { - case "test1": - _ = event.Create(discord.NewMessageCreateBuilder(). - SetContent(event.Data.CustomID.String()). - Build(), - ) +func componentListener(event *events.ComponentInteractionEvent) { + switch data := event.Data.(type) { + case *core.ButtonInteractionData: + switch data.CustomID { + case "test1": + _ = event.Create(discord.NewMessageCreateBuilder(). + SetContent(data.CustomID.String()). + Build(), + ) - case "test2": - _ = event.DeferCreate(false) + case "test2": + _ = event.DeferCreate(false) - case "test3": - _ = event.DeferUpdate() + case "test3": + _ = event.DeferUpdate() - case "test4": - _ = event.Update(discord.NewMessageUpdateBuilder(). - SetContent(event.Data.CustomID.String()). - Build(), - ) - } -} + case "test4": + _ = event.Update(discord.NewMessageUpdateBuilder(). + SetContent(data.CustomID.String()). + Build(), + ) + } -func selectMenuSubmitListener(event *events.SelectMenuSubmitEvent) { - switch event.Data.CustomID { - case "test3": - if err := event.DeferUpdate(); err != nil { - log.Errorf("error sending interaction response: %s", err) + case *core.SelectMenuInteractionData: + switch data.CustomID { + case "test3": + if err := event.DeferUpdate(); err != nil { + log.Errorf("error sending interaction response: %s", err) + } + _, _ = event.CreateFollowupMessage(discord.NewMessageCreateBuilder(). + SetEphemeral(true). + SetContentf("selected options: %s", data.Values). + Build(), + ) } - _, _ = event.CreateFollowup(discord.NewMessageCreateBuilder(). - SetEphemeral(true). - SetContentf("selected options: %s", event.Data.Values). - Build(), - ) } } -func slashCommandListener(event *events.SlashCommandEvent) { - switch event.Data.CommandName { +func applicationCommandListener(event *events.ApplicationCommandInteractionEvent) { + data := event.SlashCommandInteractionData() + switch data.CommandName { case "eval": go func() { - code := *event.Data.Options.String("code") + code := *data.Options.String("code") embed := discord.NewEmbedBuilder(). SetColor(orange). AddField("Status", "...", true). @@ -80,7 +82,7 @@ func slashCommandListener(event *events.SlashCommandEvent) { embed.SetField(1, "Time", strconv.Itoa(int(elapsed.Milliseconds()))+"ms", true) if err != nil { - _, err = event.UpdateOriginal(discord.NewMessageUpdateBuilder(). + _, err = event.UpdateResponse(discord.NewMessageUpdateBuilder(). SetEmbeds(embed. SetColor(red). SetField(0, "Status", "Failed", true). @@ -94,7 +96,7 @@ func slashCommandListener(event *events.SlashCommandEvent) { } return } - _, err = event.UpdateOriginal(discord.NewMessageUpdateBuilder(). + _, err = event.UpdateResponse(discord.NewMessageUpdateBuilder(). SetEmbeds(embed. SetColor(green). SetField(0, "Status", "Success", true). @@ -110,8 +112,8 @@ func slashCommandListener(event *events.SlashCommandEvent) { case "say": _ = event.Create(discord.NewMessageCreateBuilder(). - SetContent(*event.Data.Options.String("message")). - SetEphemeral(*event.Data.Options.Bool("ephemeral")). + SetContent(*data.Options.String("message")). + SetEphemeral(*data.Options.Bool("ephemeral")). ClearAllowedMentions(). Build(), ) @@ -121,18 +123,18 @@ func slashCommandListener(event *events.SlashCommandEvent) { _ = event.DeferCreate(true) members, err := event.Guild().RequestMembersWithQuery("", 0) if err != nil { - _, _ = event.UpdateOriginal(discord.NewMessageUpdateBuilder().SetContentf("failed to load members. error: %s", err).Build()) + _, _ = event.UpdateResponse(discord.NewMessageUpdateBuilder().SetContentf("failed to load members. error: %s", err).Build()) return } - _, _ = event.UpdateOriginal(discord.NewMessageUpdateBuilder(). + _, _ = event.UpdateResponse(discord.NewMessageUpdateBuilder(). SetContentf("loaded %d members", len(members)). Build(), ) }() case "addrole": - user := event.Data.Options.User("member") - role := event.Data.Options.Role("role") + user := data.Options.User("member") + role := data.Options.Role("role") if err := event.Bot().RestServices.GuildService().AddMemberRole(*event.GuildID, user.ID, role.ID); err == nil { _ = event.Create(discord.NewMessageCreateBuilder().AddEmbeds( @@ -145,8 +147,8 @@ func slashCommandListener(event *events.SlashCommandEvent) { } case "removerole": - user := event.Data.Options.User("member") - role := event.Data.Options.Role("role") + user := data.Options.User("member") + role := data.Options.Role("role") if err := event.Bot().RestServices.GuildService().RemoveMemberRole(*event.GuildID, user.ID, role.ID); err == nil { _ = event.Create(discord.NewMessageCreateBuilder().AddEmbeds( diff --git a/core/application_command_interaction.go b/core/application_command_interaction.go new file mode 100644 index 00000000..ecf1e48b --- /dev/null +++ b/core/application_command_interaction.go @@ -0,0 +1,87 @@ +package core + +import "github.com/DisgoOrg/disgo/discord" + +type ApplicationCommandInteractionFilter func(interaction *ApplicationCommandInteraction) bool + +// ApplicationCommandInteraction represents a generic ApplicationCommandInteraction received from discord +type ApplicationCommandInteraction struct { + discord.ApplicationCommandInteraction + *ReplyInteraction + Data ApplicationCommandInteractionData +} + +func (i ApplicationCommandInteraction) SlashCommandInteractionData() *SlashCommandInteractionData { + return i.Data.(*SlashCommandInteractionData) +} + +func (i ApplicationCommandInteraction) UserCommandInteractionData() *UserCommandInteractionData { + return i.Data.(*UserCommandInteractionData) +} + +func (i ApplicationCommandInteraction) MessageCommandInteractionData() *MessageCommandInteractionData { + return i.Data.(*MessageCommandInteractionData) +} + +type ApplicationCommandInteractionData interface { + discord.ApplicationCommandInteractionData +} + +type SlashCommandInteractionData struct { + discord.SlashCommandInteractionData + SubCommandName *string + SubCommandGroupName *string + Resolved *SlashCommandResolved + Options SlashCommandOptionsMap +} + +// CommandPath returns the ApplicationCommand path +func (i SlashCommandInteractionData) CommandPath() string { + path := i.CommandName + if name := i.SubCommandName; name != nil { + path += "/" + *name + } + if name := i.SubCommandGroupName; name != nil { + path += "/" + *name + } + return path +} + +// SlashCommandResolved contains resolved mention data for SlashCommand(s) +type SlashCommandResolved struct { + Users map[discord.Snowflake]*User + Members map[discord.Snowflake]*Member + Roles map[discord.Snowflake]*Role + Channels map[discord.Snowflake]Channel +} + +type UserCommandInteractionData struct { + discord.UserCommandInteractionData + Resolved *UserCommandResolved +} + +func (i *UserCommandInteractionData) TargetUser() *User { + return i.Resolved.Users[i.TargetID] +} + +func (i *UserCommandInteractionData) TargetMember() *Member { + return i.Resolved.Members[i.TargetID] +} + +type UserCommandResolved struct { + Users map[discord.Snowflake]*User + Members map[discord.Snowflake]*Member +} + +type MessageCommandInteractionData struct { + discord.MessageCommandInteractionData + Resolved *MessageCommandResolved +} + +func (i *MessageCommandInteractionData) TargetMessage() *Message { + return i.Resolved.Messages[i.TargetID] +} + +type MessageCommandResolved struct { + Messages map[discord.Snowflake]*Message +} diff --git a/core/autocomplete_interaction.go b/core/autocomplete_interaction.go index 21bbf70a..31340e7f 100644 --- a/core/autocomplete_interaction.go +++ b/core/autocomplete_interaction.go @@ -9,52 +9,70 @@ type AutocompleteInteractionFilter func(autocompleteInteraction *AutocompleteInt type AutocompleteInteraction struct { discord.AutocompleteInteraction - *InteractionFields - User *User - Member *Member - Data AutocompleteInteractionData + *BaseInteraction + Data AutocompleteInteractionData } -type AutocompleteInteractionData struct { - discord.AutocompleteInteractionData - SubCommandName *string - SubCommandGroupName *string - Options AutocompleteOptionsMap -} - -func (i *AutocompleteInteraction) Respond(callbackType discord.InteractionCallbackType, callbackData discord.InteractionCallbackData, opts ...rest.RequestOpt) error { - return respond(i.InteractionFields, i.ID, i.Token, callbackType, callbackData, opts...) +func (i AutocompleteInteraction) Result(choices []discord.AutocompleteChoice, opts ...rest.RequestOpt) error { + return i.Respond(discord.InteractionCallbackTypeAutocompleteResult, discord.AutocompleteResult{Choices: choices}, opts...) } -func (i *AutocompleteInteraction) Result(choices []discord.AutocompleteChoice, opts ...rest.RequestOpt) error { - return result(i.InteractionFields, i.ID, i.Token, choices, opts...) +func (i AutocompleteInteraction) ResultMapString(resultMap map[string]string, opts ...rest.RequestOpt) error { + choices := make([]discord.AutocompleteChoice, len(resultMap)) + ii := 0 + for name, value := range resultMap { + choices[ii] = discord.AutocompleteChoiceString{ + Name: name, + Value: value, + } + ii++ + } + return i.Result(choices, opts...) } -func (i *AutocompleteInteraction) ResultMapString(resultMap map[string]string, opts ...rest.RequestOpt) error { - return resultMapString(i.InteractionFields, i.ID, i.Token, resultMap, opts...) +func (i AutocompleteInteraction) ResultMapInt(resultMap map[string]int, opts ...rest.RequestOpt) error { + choices := make([]discord.AutocompleteChoice, len(resultMap)) + ii := 0 + for name, value := range resultMap { + choices[ii] = discord.AutocompleteChoiceInt{ + Name: name, + Value: value, + } + ii++ + } + return i.Result(choices, opts...) } -func (i *AutocompleteInteraction) ResultMapInt(resultMap map[string]int, opts ...rest.RequestOpt) error { - return resultMapInt(i.InteractionFields, i.ID, i.Token, resultMap, opts...) +func (i AutocompleteInteraction) ResultMapFloat(resultMap map[string]float64, opts ...rest.RequestOpt) error { + choices := make([]discord.AutocompleteChoice, len(resultMap)) + ii := 0 + for name, value := range resultMap { + choices[ii] = discord.AutocompleteChoiceFloat{ + Name: name, + Value: value, + } + ii++ + } + return i.Result(choices, opts...) } -func (i *AutocompleteInteraction) ResultMapFloat(resultMap map[string]float64, opts ...rest.RequestOpt) error { - return resultMapFloat(i.InteractionFields, i.ID, i.Token, resultMap, opts...) +type AutocompleteInteractionData struct { + discord.AutocompleteInteractionData + SubCommandName *string + SubCommandGroupName *string + Options AutocompleteOptionsMap } // CommandPath returns the ApplicationCommand path -func (i *AutocompleteInteraction) CommandPath() string { - return commandPath(i.Data.CommandName, i.Data.SubCommandName, i.Data.SubCommandGroupName) -} - -// Guild returns the Guild from the Caches -func (i *AutocompleteInteraction) Guild() *Guild { - return guild(i.InteractionFields, i.GuildID) -} - -// Channel returns the Channel from the Caches -func (i *AutocompleteInteraction) Channel() MessageChannel { - return channel(i.InteractionFields, i.ChannelID) +func (i *AutocompleteInteractionData) CommandPath() string { + path := i.CommandName + if name := i.SubCommandName; name != nil { + path += "/" + *name + } + if name := i.SubCommandGroupName; name != nil { + path += "/" + *name + } + return path } type AutocompleteOptionsMap map[string]discord.AutocompleteOption diff --git a/core/button_interaction.go b/core/button_interaction.go deleted file mode 100644 index 3207ca28..00000000 --- a/core/button_interaction.go +++ /dev/null @@ -1,79 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -// ButtonInteractionFilter used to filter ButtonInteraction(s) in a collectors.ButtonClickCollector -type ButtonInteractionFilter func(buttonInteraction *ButtonInteraction) bool - -var _ Interaction = (*ButtonInteraction)(nil) -var _ ComponentInteraction = (*ButtonInteraction)(nil) - -type ButtonInteraction struct { - discord.ButtonInteraction - *InteractionFields - User *User - Member *Member - Message *Message -} - -func (i *ButtonInteraction) Respond(callbackType discord.InteractionCallbackType, callbackData discord.InteractionCallbackData, opts ...rest.RequestOpt) error { - return respond(i.InteractionFields, i.ID, i.Token, callbackType, callbackData, opts...) -} - -func (i *ButtonInteraction) Create(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) error { - return create(i.InteractionFields, i.ID, i.Token, messageCreate, opts...) -} - -func (i *ButtonInteraction) DeferCreate(ephemeral bool, opts ...rest.RequestOpt) error { - return deferCreate(i.InteractionFields, i.ID, i.Token, ephemeral, opts...) -} - -func (i *ButtonInteraction) GetOriginal(opts ...rest.RequestOpt) (*Message, error) { - return getOriginal(i.InteractionFields, i.ApplicationID, i.Token, opts...) -} - -func (i *ButtonInteraction) UpdateOriginal(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateOriginal(i.InteractionFields, i.ApplicationID, i.Token, messageUpdate, opts...) -} - -func (i *ButtonInteraction) DeleteOriginal(opts ...rest.RequestOpt) error { - return deleteOriginal(i.InteractionFields, i.ApplicationID, i.Token, opts...) -} - -func (i *ButtonInteraction) GetFollowup(messageID discord.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - return getFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, opts...) -} - -func (i *ButtonInteraction) CreateFollowup(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return createFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageCreate, opts...) -} - -func (i *ButtonInteraction) UpdateFollowup(messageID discord.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, messageUpdate, opts...) -} - -func (i *ButtonInteraction) DeleteFollowup(messageID discord.Snowflake, opts ...rest.RequestOpt) error { - return deleteFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, opts...) -} - -func (i *ButtonInteraction) Update(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) error { - return update(i.InteractionFields, i.ID, i.Token, messageUpdate, opts...) -} - -func (i *ButtonInteraction) DeferUpdate(opts ...rest.RequestOpt) error { - return deferUpdate(i.InteractionFields, i.ID, i.Token, opts...) -} - -// UpdateButton updates the clicked ButtonComponent with a new ButtonComponent -func (i *ButtonInteraction) UpdateButton(button discord.ButtonComponent, opts ...rest.RequestOpt) error { - return updateComponent(i.InteractionFields, i.ID, i.Token, i.Message, i.Data.CustomID, button, opts...) -} - -// ButtonComponent returns the ButtonComponent which issued this ButtonInteraction -func (i *ButtonInteraction) ButtonComponent() discord.ButtonComponent { - // this should never be nil - return *i.Message.ButtonByID(i.Data.CustomID) -} diff --git a/core/collectors.go b/core/collectors.go index a030b3e7..7b5f1aee 100644 --- a/core/collectors.go +++ b/core/collectors.go @@ -7,13 +7,8 @@ type Collectors interface { NewMessageReactionAddCollector(filter MessageReactionAddFilter) (<-chan *MessageReactionAdd, func()) NewMessageReactionRemoveCollector(filter MessageReactionRemoveFilter) (<-chan *MessageReactionRemove, func()) NewInteractionCollector(filter InteractionFilter) (<-chan Interaction, func()) - NewApplicationCommandInteractionCollector(filter ApplicationCommandInteractionFilter) (<-chan ApplicationCommandInteraction, func()) - NewSlashCommandCollector(filter SlashCommandInteractionFilter) (<-chan *SlashCommandInteraction, func()) - NewMessageCommandCollector(filter MessageCommandInteractionFilter) (<-chan *MessageCommandInteraction, func()) - NewUserCommandCollector(filter UserCommandInteractionFilter) (<-chan *UserCommandInteraction, func()) - NewComponentInteractionCollector(filter ComponentInteractionFilter) (<-chan ComponentInteraction, func()) - NewButtonClickCollector(filter ButtonInteractionFilter) (<-chan *ButtonInteraction, func()) - NewSelectMenuSubmitCollector(filter SelectMenuInteractionFilter) (<-chan *SelectMenuInteraction, func()) + NewApplicationCommandInteractionCollector(filter ApplicationCommandInteractionFilter) (<-chan *ApplicationCommandInteraction, func()) + NewComponentInteractionCollector(filter ComponentInteractionFilter) (<-chan *ComponentInteraction, func()) NewAutocompleteCollector(filter AutocompleteInteractionFilter) (<-chan *AutocompleteInteraction, func()) } @@ -26,13 +21,8 @@ type CollectorsConfig struct { NewMessageReactionAddCollectorFunc func(bot *Bot, filter MessageReactionAddFilter) (<-chan *MessageReactionAdd, func()) NewMessageReactionRemoveCollectorFunc func(bot *Bot, filter MessageReactionRemoveFilter) (<-chan *MessageReactionRemove, func()) NewInteractionCollectorFunc func(bot *Bot, filter InteractionFilter) (<-chan Interaction, func()) - NewApplicationCommandInteractionCollectorFunc func(bot *Bot, filter ApplicationCommandInteractionFilter) (<-chan ApplicationCommandInteraction, func()) - NewSlashCommandCollectorFunc func(bot *Bot, filter SlashCommandInteractionFilter) (<-chan *SlashCommandInteraction, func()) - NewMessageCommandCollectorFunc func(bot *Bot, filter MessageCommandInteractionFilter) (<-chan *MessageCommandInteraction, func()) - NewUserCommandCollectorFunc func(bot *Bot, filter UserCommandInteractionFilter) (<-chan *UserCommandInteraction, func()) - NewComponentInteractionCollectorFunc func(bot *Bot, filter ComponentInteractionFilter) (<-chan ComponentInteraction, func()) - NewButtonClickCollectorFunc func(bot *Bot, filter ButtonInteractionFilter) (<-chan *ButtonInteraction, func()) - NewSelectMenuSubmitCollectorFunc func(bot *Bot, filter SelectMenuInteractionFilter) (<-chan *SelectMenuInteraction, func()) + NewApplicationCommandInteractionCollectorFunc func(bot *Bot, filter ApplicationCommandInteractionFilter) (<-chan *ApplicationCommandInteraction, func()) + NewComponentInteractionCollectorFunc func(bot *Bot, filter ComponentInteractionFilter) (<-chan *ComponentInteraction, func()) NewAutocompleteCollectorFunc func(bot *Bot, filter AutocompleteInteractionFilter) (<-chan *AutocompleteInteraction, func()) } @@ -45,10 +35,6 @@ func (c *collectorsImpl) NewMessageCollector(filter MessageFilter) (<-chan *Mess return c.NewMessageCollectorFunc(c.Bot, filter) } -func (c *collectorsImpl) NewMessageCommandCollector(filter MessageCommandInteractionFilter) (<-chan *MessageCommandInteraction, func()) { - return c.NewMessageCommandCollectorFunc(c.Bot, filter) -} - func (c *collectorsImpl) NewMessageReactionAddCollector(filter MessageReactionAddFilter) (<-chan *MessageReactionAdd, func()) { return c.NewMessageReactionAddCollectorFunc(c.Bot, filter) } @@ -61,30 +47,14 @@ func (c *collectorsImpl) NewInteractionCollector(filter InteractionFilter) (<-ch return c.NewInteractionCollectorFunc(c.Bot, filter) } -func (c *collectorsImpl) NewApplicationCommandInteractionCollector(filter ApplicationCommandInteractionFilter) (<-chan ApplicationCommandInteraction, func()) { +func (c *collectorsImpl) NewApplicationCommandInteractionCollector(filter ApplicationCommandInteractionFilter) (<-chan *ApplicationCommandInteraction, func()) { return c.NewApplicationCommandInteractionCollectorFunc(c.Bot, filter) } -func (c *collectorsImpl) NewSlashCommandCollector(filter SlashCommandInteractionFilter) (<-chan *SlashCommandInteraction, func()) { - return c.NewSlashCommandCollectorFunc(c.Bot, filter) -} - -func (c *collectorsImpl) NewUserCommandCollector(filter UserCommandInteractionFilter) (<-chan *UserCommandInteraction, func()) { - return c.NewUserCommandCollectorFunc(c.Bot, filter) -} - -func (c *collectorsImpl) NewComponentInteractionCollector(filter ComponentInteractionFilter) (<-chan ComponentInteraction, func()) { +func (c *collectorsImpl) NewComponentInteractionCollector(filter ComponentInteractionFilter) (<-chan *ComponentInteraction, func()) { return c.NewComponentInteractionCollectorFunc(c.Bot, filter) } -func (c *collectorsImpl) NewButtonClickCollector(filter ButtonInteractionFilter) (<-chan *ButtonInteraction, func()) { - return c.NewButtonClickCollectorFunc(c.Bot, filter) -} - -func (c *collectorsImpl) NewSelectMenuSubmitCollector(filter SelectMenuInteractionFilter) (<-chan *SelectMenuInteraction, func()) { - return c.NewSelectMenuSubmitCollectorFunc(c.Bot, filter) -} - func (c *collectorsImpl) NewAutocompleteCollector(filter AutocompleteInteractionFilter) (<-chan *AutocompleteInteraction, func()) { return c.NewAutocompleteCollectorFunc(c.Bot, filter) } diff --git a/core/collectors/application_command_interaction_create_collector.go b/core/collectors/application_command_interaction_collector.go similarity index 79% rename from core/collectors/application_command_interaction_create_collector.go rename to core/collectors/application_command_interaction_collector.go index 7b937f42..c8ed5c00 100644 --- a/core/collectors/application_command_interaction_create_collector.go +++ b/core/collectors/application_command_interaction_collector.go @@ -7,8 +7,8 @@ import ( // NewApplicationCommandInteractionCollector gives you a channel to receive on and a function to close the collector //goland:noinspection GoUnusedExportedFunction -func NewApplicationCommandInteractionCollector(disgo *core.Bot, filter core.ApplicationCommandInteractionFilter) (<-chan core.ApplicationCommandInteraction, func()) { - ch := make(chan core.ApplicationCommandInteraction) +func NewApplicationCommandInteractionCollector(disgo *core.Bot, filter core.ApplicationCommandInteractionFilter) (<-chan *core.ApplicationCommandInteraction, func()) { + ch := make(chan *core.ApplicationCommandInteraction) col := &ApplicationCommandInteractionCollector{ Filter: filter, @@ -27,13 +27,13 @@ func NewApplicationCommandInteractionCollector(disgo *core.Bot, filter core.Appl // ApplicationCommandInteractionCollector used to collect core.ApplicationCommandInteractionApplicationCommandInteraction(s) from a core.Message using a ButtonFilter function type ApplicationCommandInteractionCollector struct { Filter core.ApplicationCommandInteractionFilter - Chan chan<- core.ApplicationCommandInteraction + Chan chan<- *core.ApplicationCommandInteraction Close func() } // OnEvent used to get events for the ButtonCollector func (c *ApplicationCommandInteractionCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.ApplicationCommandInteractionCreateEvent); ok { + if event, ok := e.(*events.ApplicationCommandInteractionEvent); ok { if !c.Filter(event.ApplicationCommandInteraction) { return } diff --git a/core/collectors/autocomplete_collector.go b/core/collectors/autocomplete_interaction_collector.go similarity index 51% rename from core/collectors/autocomplete_collector.go rename to core/collectors/autocomplete_interaction_collector.go index 9b206b47..5f46cacb 100644 --- a/core/collectors/autocomplete_collector.go +++ b/core/collectors/autocomplete_interaction_collector.go @@ -5,12 +5,12 @@ import ( "github.com/DisgoOrg/disgo/core/events" ) -// NewAutocompleteCollector gives you a channel to receive on and a function to close the collector +// NewAutocompleteInteractionCollector gives you a channel to receive on and a function to close the collector //goland:noinspection GoUnusedExportedFunction -func NewAutocompleteCollector(disgo *core.Bot, filter core.AutocompleteInteractionFilter) (<-chan *core.AutocompleteInteraction, func()) { +func NewAutocompleteInteractionCollector(disgo *core.Bot, filter core.AutocompleteInteractionFilter) (<-chan *core.AutocompleteInteraction, func()) { ch := make(chan *core.AutocompleteInteraction) - col := &AutocompleteCollector{ + col := &AutocompleteInteractionCollector{ Filter: filter, Chan: ch, } @@ -24,16 +24,16 @@ func NewAutocompleteCollector(disgo *core.Bot, filter core.AutocompleteInteracti return ch, cls } -// AutocompleteCollector used to collect core.AutocompleteInteraction(s) from a core.Message using a ButtonFilter function -type AutocompleteCollector struct { +// AutocompleteInteractionCollector used to collect core.AutocompleteInteraction(s) from a core.Message using a ButtonFilter function +type AutocompleteInteractionCollector struct { Filter core.AutocompleteInteractionFilter Chan chan<- *core.AutocompleteInteraction Close func() } // OnEvent used to get events for the ButtonCollector -func (c *AutocompleteCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.AutocompleteEvent); ok { +func (c *AutocompleteInteractionCollector) OnEvent(e core.Event) { + if event, ok := e.(*events.AutocompleteInteractionEvent); ok { if !c.Filter(event.AutocompleteInteraction) { return } diff --git a/core/collectors/button_click_collector.go b/core/collectors/button_click_collector.go deleted file mode 100644 index a83f9702..00000000 --- a/core/collectors/button_click_collector.go +++ /dev/null @@ -1,42 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewButtonClickCollector gives you a channel to receive on and a function to close the collector -//goland:noinspection GoUnusedExportedFunction -func NewButtonClickCollector(disgo *core.Bot, filter core.ButtonInteractionFilter) (<-chan *core.ButtonInteraction, func()) { - ch := make(chan *core.ButtonInteraction) - - col := &ButtonClickCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(col) - } - col.Close = cls - disgo.EventManager.AddEventListeners(col) - - return ch, cls -} - -// ButtonClickCollector used to collect core.ButtonInteraction(s) from a core.Message using a ButtonFilter function -type ButtonClickCollector struct { - Filter core.ButtonInteractionFilter - Chan chan<- *core.ButtonInteraction - Close func() -} - -// OnEvent used to get events for the ButtonCollector -func (c *ButtonClickCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.ButtonClickEvent); ok { - if !c.Filter(event.ButtonInteraction) { - return - } - c.Chan <- event.ButtonInteraction - } -} diff --git a/core/collectors/component_interaction_create_collector.go b/core/collectors/component_interaction_collector.go similarity index 81% rename from core/collectors/component_interaction_create_collector.go rename to core/collectors/component_interaction_collector.go index 3ff818be..e5455895 100644 --- a/core/collectors/component_interaction_create_collector.go +++ b/core/collectors/component_interaction_collector.go @@ -7,8 +7,8 @@ import ( // NewComponentInteractionCollector gives you a channel to receive on and a function to close the collector //goland:noinspection GoUnusedExportedFunction -func NewComponentInteractionCollector(disgo *core.Bot, filter core.ComponentInteractionFilter) (<-chan core.ComponentInteraction, func()) { - ch := make(chan core.ComponentInteraction) +func NewComponentInteractionCollector(disgo *core.Bot, filter core.ComponentInteractionFilter) (<-chan *core.ComponentInteraction, func()) { + ch := make(chan *core.ComponentInteraction) col := &ComponentInteractionCollector{ Filter: filter, @@ -27,13 +27,13 @@ func NewComponentInteractionCollector(disgo *core.Bot, filter core.ComponentInte // ComponentInteractionCollector used to collect core.ComponentInteractionComponentInteraction(s) from a core.Message using a ButtonFilter function type ComponentInteractionCollector struct { Filter core.ComponentInteractionFilter - Chan chan<- core.ComponentInteraction + Chan chan<- *core.ComponentInteraction Close func() } // OnEvent used to get events for the ButtonCollector func (c *ComponentInteractionCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.ComponentInteractionCreateEvent); ok { + if event, ok := e.(*events.ComponentInteractionEvent); ok { if !c.Filter(event.ComponentInteraction) { return } diff --git a/core/collectors/config.go b/core/collectors/config.go index 3df5230c..3283b33d 100644 --- a/core/collectors/config.go +++ b/core/collectors/config.go @@ -8,11 +8,6 @@ var DefaultConfig = core.CollectorsConfig{ NewMessageReactionRemoveCollectorFunc: NewMessageReactionRemoveCollector, NewInteractionCollectorFunc: NewInteractionCollector, NewApplicationCommandInteractionCollectorFunc: NewApplicationCommandInteractionCollector, - NewSlashCommandCollectorFunc: NewSlashCommandCollector, - NewMessageCommandCollectorFunc: NewMessageCommandCollector, - NewUserCommandCollectorFunc: NewUserCommandCollector, NewComponentInteractionCollectorFunc: NewComponentInteractionCollector, - NewButtonClickCollectorFunc: NewButtonClickCollector, - NewSelectMenuSubmitCollectorFunc: NewSelectMenuSubmitCollector, - NewAutocompleteCollectorFunc: NewAutocompleteCollector, + NewAutocompleteCollectorFunc: NewAutocompleteInteractionCollector, } diff --git a/core/collectors/interaction_create_collector.go b/core/collectors/interaction_create_collector.go index 5fc38493..dd703397 100644 --- a/core/collectors/interaction_create_collector.go +++ b/core/collectors/interaction_create_collector.go @@ -33,7 +33,7 @@ type InteractionCollector struct { // OnEvent used to get events for the ButtonCollector func (c *InteractionCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.InteractionCreateEvent); ok { + if event, ok := e.(*events.InteractionEvent); ok { if !c.Filter(event.Interaction) { return } diff --git a/core/collectors/message_command_collector.go b/core/collectors/message_command_collector.go deleted file mode 100644 index 4ecbded8..00000000 --- a/core/collectors/message_command_collector.go +++ /dev/null @@ -1,42 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewMessageCommandCollector gives you a channel to receive on and a function to close the collector -//goland:noinspection GoUnusedExportedFunction -func NewMessageCommandCollector(disgo *core.Bot, filter core.MessageCommandInteractionFilter) (<-chan *core.MessageCommandInteraction, func()) { - ch := make(chan *core.MessageCommandInteraction) - - col := &MessageCommandCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(col) - } - col.Close = cls - disgo.EventManager.AddEventListeners(col) - - return ch, cls -} - -// MessageCommandCollector used to collect core.MessageCommandInteraction(s) from a core.Message using a ButtonFilter function -type MessageCommandCollector struct { - Filter core.MessageCommandInteractionFilter - Chan chan<- *core.MessageCommandInteraction - Close func() -} - -// OnEvent used to get events for the ButtonCollector -func (c *MessageCommandCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.MessageCommandEvent); ok { - if !c.Filter(event.MessageCommandInteraction) { - return - } - c.Chan <- event.MessageCommandInteraction - } -} diff --git a/core/collectors/select_menu_submit_collector.go b/core/collectors/select_menu_submit_collector.go deleted file mode 100644 index fd93ee57..00000000 --- a/core/collectors/select_menu_submit_collector.go +++ /dev/null @@ -1,41 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewSelectMenuSubmitCollector gives you a channel to receive on and a function to close the collector -func NewSelectMenuSubmitCollector(disgo *core.Bot, filter core.SelectMenuInteractionFilter) (<-chan *core.SelectMenuInteraction, func()) { - ch := make(chan *core.SelectMenuInteraction) - - collector := &SelectMenuSubmitCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(collector) - } - collector.Close = cls - disgo.EventManager.AddEventListeners(collector) - - return ch, cls -} - -// SelectMenuSubmitCollector used to collect core.SelectMenuInteraction(s) from a core.Message using a core.SelectMenuInteractionFilter function -type SelectMenuSubmitCollector struct { - Filter core.SelectMenuInteractionFilter - Chan chan<- *core.SelectMenuInteraction - Close func() -} - -// OnEvent used to get events for the SelectMenuSubmitCollector -func (c *SelectMenuSubmitCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.SelectMenuSubmitEvent); ok { - if !c.Filter(event.SelectMenuInteraction) { - return - } - c.Chan <- event.SelectMenuInteraction - } -} diff --git a/core/collectors/slash_command_collector.go b/core/collectors/slash_command_collector.go deleted file mode 100644 index a0ba7763..00000000 --- a/core/collectors/slash_command_collector.go +++ /dev/null @@ -1,42 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewSlashCommandCollector gives you a channel to receive on and a function to close the collector -//goland:noinspection GoUnusedExportedFunction -func NewSlashCommandCollector(disgo *core.Bot, filter core.SlashCommandInteractionFilter) (<-chan *core.SlashCommandInteraction, func()) { - ch := make(chan *core.SlashCommandInteraction) - - col := &SlashCommandCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(col) - } - col.Close = cls - disgo.EventManager.AddEventListeners(col) - - return ch, cls -} - -// SlashCommandCollector used to collect core.SlashCommandInteraction(s) from a core.Message using a ButtonFilter function -type SlashCommandCollector struct { - Filter core.SlashCommandInteractionFilter - Chan chan<- *core.SlashCommandInteraction - Close func() -} - -// OnEvent used to get events for the ButtonCollector -func (c *SlashCommandCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.SlashCommandEvent); ok { - if !c.Filter(event.SlashCommandInteraction) { - return - } - c.Chan <- event.SlashCommandInteraction - } -} diff --git a/core/collectors/user_command_collector.go b/core/collectors/user_command_collector.go deleted file mode 100644 index 05717785..00000000 --- a/core/collectors/user_command_collector.go +++ /dev/null @@ -1,42 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewUserCommandCollector gives you a channel to receive on and a function to close the collector -//goland:noinspection GoUnusedExportedFunction -func NewUserCommandCollector(disgo *core.Bot, filter core.UserCommandInteractionFilter) (<-chan *core.UserCommandInteraction, func()) { - ch := make(chan *core.UserCommandInteraction) - - col := &UserCommandCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(col) - } - col.Close = cls - disgo.EventManager.AddEventListeners(col) - - return ch, cls -} - -// UserCommandCollector used to collect core.UserCommandInteraction(s) from a core.Message using a ButtonFilter function -type UserCommandCollector struct { - Filter core.UserCommandInteractionFilter - Chan chan<- *core.UserCommandInteraction - Close func() -} - -// OnEvent used to get events for the ButtonCollector -func (c *UserCommandCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.UserCommandEvent); ok { - if !c.Filter(event.UserCommandInteraction) { - return - } - c.Chan <- event.UserCommandInteraction - } -} diff --git a/core/component_interaction.go b/core/component_interaction.go new file mode 100644 index 00000000..4fb1b643 --- /dev/null +++ b/core/component_interaction.go @@ -0,0 +1,93 @@ +package core + +import ( + "github.com/DisgoOrg/disgo/discord" + "github.com/DisgoOrg/disgo/rest" +) + +type ComponentInteractionFilter func(interaction *ComponentInteraction) bool + +// ComponentInteraction represents a generic ComponentInteraction received from discord +type ComponentInteraction struct { + discord.ComponentInteraction + *ReplyInteraction + Data ComponentInteractionData + Message *Message +} + +func (i ComponentInteraction) ButtonInteractionData() *ButtonInteractionData { + return i.Data.(*ButtonInteractionData) +} + +func (i ComponentInteraction) SelectMenuInteractionData() *SelectMenuInteractionData { + return i.Data.(*SelectMenuInteractionData) +} + +func (i ComponentInteraction) Update(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) error { + return i.Respond(discord.InteractionCallbackTypeUpdateMessage, messageUpdate, opts...) +} + +func (i ComponentInteraction) UpdateComponent(customID discord.CustomID, component discord.InteractiveComponent, opts ...rest.RequestOpt) error { + containerComponents := make([]discord.ContainerComponent, len(i.Message.Components)) + for ii := range i.Message.Components { + switch container := containerComponents[ii].(type) { + case discord.ActionRowComponent: + containerComponents[ii] = container.UpdateComponent(customID, component) + + default: + containerComponents[ii] = container + continue + } + } + + return i.Update(discord.NewMessageUpdateBuilder().SetContainerComponents(containerComponents...).Build(), opts...) +} + +func (i ComponentInteraction) DeferUpdate(opts ...rest.RequestOpt) error { + return i.Respond(discord.InteractionCallbackTypeDeferredUpdateMessage, nil, opts...) +} + +type ComponentInteractionData interface { + discord.ComponentInteractionData +} + +type ButtonInteractionData struct { + discord.ButtonInteractionData + interaction *ComponentInteraction +} + +// UpdateButton updates the clicked ButtonComponent with a new ButtonComponent +func (d *ButtonInteractionData) UpdateButton(button discord.ButtonComponent, opts ...rest.RequestOpt) error { + return d.interaction.UpdateComponent(d.CustomID, button, opts...) +} + +// ButtonComponent returns the ButtonComponent which issued this ButtonInteraction +func (d *ButtonInteractionData) ButtonComponent() discord.ButtonComponent { + // this should never be nil + return *d.interaction.Message.ButtonByID(d.CustomID) +} + +type SelectMenuInteractionData struct { + discord.SelectMenuInteractionData + interaction *ComponentInteraction +} + +// SelectMenuComponent returns the SelectMenuComponent which issued this SelectMenuInteraction +func (d *SelectMenuInteractionData) SelectMenuComponent() discord.SelectMenuComponent { + // this should never be nil + return *d.interaction.Message.SelectMenuByID(d.CustomID) +} + +// SelectedOptions returns the selected SelectMenuOption(s) +func (d *SelectMenuInteractionData) SelectedOptions() []discord.SelectMenuOption { + options := make([]discord.SelectMenuOption, len(d.Values)) + for ii, option := range d.SelectMenuComponent().Options { + for _, value := range d.Values { + if value == option.Value { + options[ii] = option + break + } + } + } + return options +} diff --git a/core/entity_builder.go b/core/entity_builder.go index abaccc6b..850246ff 100644 --- a/core/entity_builder.go +++ b/core/entity_builder.go @@ -74,243 +74,218 @@ func (b *entityBuilderImpl) Bot() *Bot { return b.bot } -// CreateInteraction creates an Interaction from the discord.Interaction response -func (b *entityBuilderImpl) CreateInteraction(interaction discord.Interaction, c chan<- discord.InteractionResponse, updateCache CacheStrategy) Interaction { - interactionFields := &InteractionFields{ - Bot: b.Bot(), +func (b *entityBuilderImpl) baseInteraction(baseInteraction discord.BaseInteraction, c chan<- discord.InteractionResponse, updateCache CacheStrategy) *BaseInteraction { + member, user := b.parseMemberOrUser(baseInteraction.GuildID, baseInteraction.Member, baseInteraction.User, updateCache) + return &BaseInteraction{ + BaseInteraction: baseInteraction, + Member: member, + User: user, ResponseChannel: c, + Bot: b.bot, } +} +// CreateInteraction creates an Interaction from the discord.Interaction response +func (b *entityBuilderImpl) CreateInteraction(interaction discord.Interaction, c chan<- discord.InteractionResponse, updateCache CacheStrategy) Interaction { switch i := interaction.(type) { - case discord.AutocompleteInteraction: - member, user := b.parseMemberOrUser(i.GuildID, i.Member, i.User, updateCache) - - autocompleteInteraction := &AutocompleteInteraction{ - AutocompleteInteraction: i, - InteractionFields: interactionFields, - User: user, - Member: member, - Data: AutocompleteInteractionData{ - AutocompleteInteractionData: i.Data, - }, - } - - unmarshalOptions := i.Data.Options - if len(unmarshalOptions) > 0 { - unmarshalOption := unmarshalOptions[0] - if option, ok := unmarshalOption.(discord.AutocompleteOptionSubCommandGroup); ok { - autocompleteInteraction.Data.SubCommandGroupName = &option.GroupName - unmarshalOptions = make([]discord.AutocompleteOption, len(option.Options)) - for i := range option.Options { - unmarshalOptions[i] = option.Options[i] - } - unmarshalOption = option.Options[0] + case discord.ApplicationCommandInteraction: + var interactionData ApplicationCommandInteractionData + switch d := i.Data.(type) { + case discord.SlashCommandInteractionData: + data := &SlashCommandInteractionData{ + SlashCommandInteractionData: d, + Resolved: &SlashCommandResolved{ + Users: map[discord.Snowflake]*User{}, + Members: map[discord.Snowflake]*Member{}, + Roles: map[discord.Snowflake]*Role{}, + Channels: map[discord.Snowflake]Channel{}, + }, } - if option, ok := unmarshalOption.(discord.AutocompleteOptionSubCommand); ok { - autocompleteInteraction.Data.SubCommandName = &option.CommandName - unmarshalOptions = option.Options + for id, u := range d.Resolved.Users { + data.Resolved.Users[id] = b.CreateUser(u, updateCache) } - } - autocompleteInteraction.Data.Options = make(map[string]discord.AutocompleteOption, len(unmarshalOptions)) - for _, option := range unmarshalOptions { - autocompleteInteraction.Data.Options[option.Name()] = option - } - - return autocompleteInteraction - - case discord.SlashCommandInteraction: - member, user := b.parseMemberOrUser(i.GuildID, i.Member, i.User, updateCache) - - slashCommandInteraction := &SlashCommandInteraction{ - SlashCommandInteraction: i, - InteractionFields: interactionFields, - User: user, - Member: member, - Data: SlashCommandInteractionData{ - SlashCommandInteractionData: i.Data, - }, - } - - resolved := &SlashCommandResolved{ - Users: map[discord.Snowflake]*User{}, - Members: map[discord.Snowflake]*Member{}, - Roles: map[discord.Snowflake]*Role{}, - Channels: map[discord.Snowflake]Channel{}, - } - slashCommandInteraction.Data.Resolved = resolved - for id, u := range i.Data.Resolved.Users { - resolved.Users[id] = b.CreateUser(u, updateCache) - } - - for id, m := range i.Data.Resolved.Members { - // discord omits the user field Oof - m.User = i.Data.Resolved.Users[id] - resolved.Members[id] = b.CreateMember(*i.GuildID, m, updateCache) - } - - for id, r := range i.Data.Resolved.Roles { - resolved.Roles[id] = b.CreateRole(*i.GuildID, r, updateCache) - } - - for id, c := range i.Data.Resolved.Channels { - resolved.Channels[id] = b.CreateChannel(c, updateCache) - } - - unmarshalOptions := i.Data.Options - if len(unmarshalOptions) > 0 { - unmarshalOption := unmarshalOptions[0] - if option, ok := unmarshalOption.(discord.SlashCommandOptionSubCommandGroup); ok { - slashCommandInteraction.Data.SubCommandGroupName = &option.OptionName - unmarshalOptions = make([]discord.SlashCommandOption, len(option.Options)) - for ii := range option.Options { - unmarshalOptions[ii] = option.Options[ii] - } - unmarshalOption = option.Options[0] + for id, m := range d.Resolved.Members { + // discord omits the user field Oof + m.User = d.Resolved.Users[id] + data.Resolved.Members[id] = b.CreateMember(*i.GuildID, m, updateCache) } - if option, ok := unmarshalOption.(discord.SlashCommandOptionSubCommand); ok { - slashCommandInteraction.Data.SubCommandName = &option.OptionName - unmarshalOptions = option.Options - } - } - slashCommandInteraction.Data.Options = make(map[string]SlashCommandOption, len(unmarshalOptions)) - for _, option := range unmarshalOptions { - var slashCommandOption SlashCommandOption - switch o := option.(type) { - case discord.SlashCommandOptionString: - slashCommandOption = SlashCommandOptionString{ - SlashCommandOptionString: o, - Resolved: resolved, - } - - case discord.SlashCommandOptionInt: - slashCommandOption = SlashCommandOptionInt{ - SlashCommandOptionInt: o, - } - - case discord.SlashCommandOptionBool: - slashCommandOption = SlashCommandOptionBool{ - SlashCommandOptionBool: o, - } - - case discord.SlashCommandOptionUser: - slashCommandOption = SlashCommandOptionUser{ - SlashCommandOptionUser: o, - Resolved: resolved, - } + for id, r := range d.Resolved.Roles { + data.Resolved.Roles[id] = b.CreateRole(*i.GuildID, r, updateCache) + } - case discord.SlashCommandOptionChannel: - slashCommandOption = SlashCommandOptionChannel{ - SlashCommandOptionChannel: o, - Resolved: resolved, - } + for id, c := range d.Resolved.Channels { + data.Resolved.Channels[id] = b.CreateChannel(c, updateCache) + } - case discord.SlashCommandOptionRole: - slashCommandOption = SlashCommandOptionRole{ - SlashCommandOptionRole: o, - Resolved: resolved, + unmarshalOptions := d.Options + if len(unmarshalOptions) > 0 { + unmarshalOption := unmarshalOptions[0] + if option, ok := unmarshalOption.(discord.SlashCommandOptionSubCommandGroup); ok { + data.SubCommandGroupName = &option.OptionName + unmarshalOptions = make([]discord.SlashCommandOption, len(option.Options)) + for ii := range option.Options { + unmarshalOptions[ii] = option.Options[ii] + } + unmarshalOption = option.Options[0] } - - case discord.SlashCommandOptionMentionable: - slashCommandOption = SlashCommandOptionMentionable{ - SlashCommandOptionMentionable: o, - Resolved: resolved, + if option, ok := unmarshalOption.(discord.SlashCommandOptionSubCommand); ok { + data.SubCommandName = &option.OptionName + unmarshalOptions = option.Options } + } - case discord.SlashCommandOptionFloat: - slashCommandOption = SlashCommandOptionFloat{ - SlashCommandOptionFloat: o, + data.Options = make(map[string]SlashCommandOption, len(unmarshalOptions)) + for _, option := range unmarshalOptions { + var slashCommandOption SlashCommandOption + switch o := option.(type) { + case discord.SlashCommandOptionString: + slashCommandOption = SlashCommandOptionString{ + SlashCommandOptionString: o, + Resolved: data.Resolved, + } + + case discord.SlashCommandOptionInt: + slashCommandOption = SlashCommandOptionInt{ + SlashCommandOptionInt: o, + } + + case discord.SlashCommandOptionBool: + slashCommandOption = SlashCommandOptionBool{ + SlashCommandOptionBool: o, + } + + case discord.SlashCommandOptionUser: + slashCommandOption = SlashCommandOptionUser{ + SlashCommandOptionUser: o, + Resolved: data.Resolved, + } + + case discord.SlashCommandOptionChannel: + slashCommandOption = SlashCommandOptionChannel{ + SlashCommandOptionChannel: o, + Resolved: data.Resolved, + } + + case discord.SlashCommandOptionRole: + slashCommandOption = SlashCommandOptionRole{ + SlashCommandOptionRole: o, + Resolved: data.Resolved, + } + + case discord.SlashCommandOptionMentionable: + slashCommandOption = SlashCommandOptionMentionable{ + SlashCommandOptionMentionable: o, + Resolved: data.Resolved, + } + + case discord.SlashCommandOptionFloat: + slashCommandOption = SlashCommandOptionFloat{ + SlashCommandOptionFloat: o, + } + + default: + b.Bot().Logger.Errorf("unknown slash command option with type %d received", option.Type()) + continue } - - default: - b.Bot().Logger.Errorf("unknown slash command option with type %d received", option.Type()) - continue + data.Options[option.Name()] = slashCommandOption } - slashCommandInteraction.Data.Options[option.Name()] = slashCommandOption - } - - return slashCommandInteraction + interactionData = data - case discord.UserCommandInteraction: - member, user := b.parseMemberOrUser(i.GuildID, i.Member, i.User, updateCache) - - userCommandInteraction := &UserCommandInteraction{ - UserCommandInteraction: i, - InteractionFields: interactionFields, - User: user, - Member: member, - Data: UserCommandInteractionData{ - UserCommandInteractionData: i.Data, + case discord.UserCommandInteractionData: + data := &UserCommandInteractionData{ + UserCommandInteractionData: d, Resolved: &UserCommandResolved{ Users: map[discord.Snowflake]*User{}, Members: map[discord.Snowflake]*Member{}, }, - }, - } - - for id, u := range i.Data.Resolved.Users { - userCommandInteraction.Data.Resolved.Users[id] = b.CreateUser(u, updateCache) - } - - for id, m := range i.Data.Resolved.Members { - // discord omits the user field Oof - m.User = i.Data.Resolved.Users[id] - userCommandInteraction.Data.Resolved.Members[id] = b.CreateMember(*i.GuildID, m, updateCache) - } - - return userCommandInteraction + } + for id, u := range d.Resolved.Users { + data.Resolved.Users[id] = b.CreateUser(u, updateCache) + } - case discord.MessageCommandInteraction: - member, user := b.parseMemberOrUser(i.GuildID, i.Member, i.User, updateCache) + for id, m := range d.Resolved.Members { + // discord omits the user field Oof + m.User = d.Resolved.Users[id] + data.Resolved.Members[id] = b.CreateMember(*i.GuildID, m, updateCache) + } + interactionData = data - messageCommandInteraction := &MessageCommandInteraction{ - MessageCommandInteraction: i, - InteractionFields: interactionFields, - User: user, - Member: member, - Data: MessageCommandInteractionData{ - MessageCommandInteractionData: i.Data, + case discord.MessageCommandInteractionData: + data := &MessageCommandInteractionData{ + MessageCommandInteractionData: d, Resolved: &MessageCommandResolved{ Messages: map[discord.Snowflake]*Message{}, }, - }, + } + for id, message := range d.Resolved.Messages { + data.Resolved.Messages[id] = b.CreateMessage(message, updateCache) + } + interactionData = data } - - for id, message := range i.Data.Resolved.Messages { - messageCommandInteraction.Data.Resolved.Messages[id] = b.CreateMessage(message, updateCache) + return &ApplicationCommandInteraction{ + ApplicationCommandInteraction: i, + ReplyInteraction: &ReplyInteraction{BaseInteraction: b.baseInteraction(i.BaseInteraction, c, updateCache)}, + Data: interactionData, } - return messageCommandInteraction - - case discord.ButtonInteraction: - member, user := b.parseMemberOrUser(i.GuildID, i.Member, i.User, updateCache) - - message := b.CreateMessage(i.Message, updateCache) + case discord.ComponentInteraction: + componentInteraction := &ComponentInteraction{ + ComponentInteraction: i, + ReplyInteraction: &ReplyInteraction{BaseInteraction: b.baseInteraction(i.BaseInteraction, c, updateCache)}, + Message: b.CreateMessage(i.Message, updateCache), + } + switch d := i.Data.(type) { + case discord.ButtonInteractionData: + componentInteraction.Data = &ButtonInteractionData{ + ButtonInteractionData: d, + interaction: componentInteraction, + } - return &ButtonInteraction{ - ButtonInteraction: i, - InteractionFields: interactionFields, - User: user, - Member: member, - Message: message, + case discord.SelectMenuInteractionData: + componentInteraction.Data = &SelectMenuInteractionData{ + SelectMenuInteractionData: d, + interaction: componentInteraction, + } } + return componentInteraction - case discord.SelectMenuInteraction: - member, user := b.parseMemberOrUser(i.GuildID, i.Member, i.User, updateCache) + case discord.AutocompleteInteraction: + autocompleteInteraction := &AutocompleteInteraction{ + AutocompleteInteraction: i, + BaseInteraction: b.baseInteraction(i.BaseInteraction, c, updateCache), + Data: AutocompleteInteractionData{ + AutocompleteInteractionData: i.Data, + }, + } - message := b.CreateMessage(i.Message, updateCache) + unmarshalOptions := i.Data.Options + if len(unmarshalOptions) > 0 { + unmarshalOption := unmarshalOptions[0] + if option, ok := unmarshalOption.(discord.AutocompleteOptionSubCommandGroup); ok { + autocompleteInteraction.Data.SubCommandGroupName = &option.GroupName + unmarshalOptions = make([]discord.AutocompleteOption, len(option.Options)) + for i := range option.Options { + unmarshalOptions[i] = option.Options[i] + } + unmarshalOption = option.Options[0] + } + if option, ok := unmarshalOption.(discord.AutocompleteOptionSubCommand); ok { + autocompleteInteraction.Data.SubCommandName = &option.CommandName + unmarshalOptions = option.Options + } + } - return &SelectMenuInteraction{ - SelectMenuInteraction: i, - InteractionFields: interactionFields, - User: user, - Member: member, - Message: message, + autocompleteInteraction.Data.Options = make(map[string]discord.AutocompleteOption, len(unmarshalOptions)) + for _, option := range unmarshalOptions { + autocompleteInteraction.Data.Options[option.Name()] = option } + return autocompleteInteraction + default: - b.Bot().Logger.Error("unknown interaction type %d received", interaction.InteractionType()) + b.Bot().Logger.Error("unknown interaction type %d received", interaction.Type()) return nil } } diff --git a/core/events/events_interactions.go b/core/events/events_interactions.go index 26e4d8b9..468ca5b1 100644 --- a/core/events/events_interactions.go +++ b/core/events/events_interactions.go @@ -2,50 +2,22 @@ package events import "github.com/DisgoOrg/disgo/core" -type InteractionCreateEvent struct { +type InteractionEvent struct { *GenericEvent core.Interaction } -type ApplicationCommandInteractionCreateEvent struct { +type ApplicationCommandInteractionEvent struct { *GenericEvent - core.ApplicationCommandInteraction + *core.ApplicationCommandInteraction } -// SlashCommandEvent indicates that a slash discord.ApplicationCommand was run -type SlashCommandEvent struct { +type ComponentInteractionEvent struct { *GenericEvent - *core.SlashCommandInteraction + *core.ComponentInteraction } -type UserCommandEvent struct { - *GenericEvent - *core.UserCommandInteraction -} - -type MessageCommandEvent struct { - *GenericEvent - *core.MessageCommandInteraction -} - -type ComponentInteractionCreateEvent struct { - *GenericEvent - core.ComponentInteraction -} - -// ButtonClickEvent indicates that a discord.ButtonComponent was clicked -type ButtonClickEvent struct { - *GenericEvent - *core.ButtonInteraction -} - -// SelectMenuSubmitEvent indicates that a discord.SelectMenuComponent was submitted -type SelectMenuSubmitEvent struct { - *GenericEvent - *core.SelectMenuInteraction -} - -type AutocompleteEvent struct { +type AutocompleteInteractionEvent struct { *GenericEvent *core.AutocompleteInteraction } diff --git a/core/events/listener_adapter.go b/core/events/listener_adapter.go index e3481fcf..0a74e38c 100644 --- a/core/events/listener_adapter.go +++ b/core/events/listener_adapter.go @@ -116,15 +116,10 @@ type ListenerAdapter struct { OnGuildScheduledEventUserRemove func(event *GuildScheduledEventUserRemoveEvent) // Interaction Events - OnInteractionCreate func(event *InteractionCreateEvent) - OnApplicationCommandInteractionCreate func(event *ApplicationCommandInteractionCreateEvent) - OnSlashCommand func(event *SlashCommandEvent) - OnUserCommand func(event *UserCommandEvent) - OnMessageCommand func(event *MessageCommandEvent) - OnComponentInteractionCreate func(event *ComponentInteractionCreateEvent) - OnButtonClick func(event *ButtonClickEvent) - OnSelectMenuSubmit func(event *SelectMenuSubmitEvent) - OnAutocomplete func(event *AutocompleteEvent) + OnInteraction func(event *InteractionEvent) + OnApplicationCommandInteraction func(event *ApplicationCommandInteractionEvent) + OnComponentInteraction func(event *ComponentInteractionEvent) + OnAutocompleteInteraction func(event *AutocompleteInteractionEvent) // Message Events OnMessageCreate func(event *MessageCreateEvent) @@ -487,40 +482,20 @@ func (l ListenerAdapter) OnEvent(event core.Event) { } // Interaction Events - case *InteractionCreateEvent: - if listener := l.OnInteractionCreate; listener != nil { + case *InteractionEvent: + if listener := l.OnInteraction; listener != nil { listener(e) } - case *ApplicationCommandInteractionCreateEvent: - if listener := l.OnApplicationCommandInteractionCreate; listener != nil { + case *ApplicationCommandInteractionEvent: + if listener := l.OnApplicationCommandInteraction; listener != nil { listener(e) } - case *SlashCommandEvent: - if listener := l.OnSlashCommand; listener != nil { + case *ComponentInteractionEvent: + if listener := l.OnComponentInteraction; listener != nil { listener(e) } - case *UserCommandEvent: - if listener := l.OnUserCommand; listener != nil { - listener(e) - } - case *MessageCommandEvent: - if listener := l.OnMessageCommand; listener != nil { - listener(e) - } - case *ComponentInteractionCreateEvent: - if listener := l.OnComponentInteractionCreate; listener != nil { - listener(e) - } - case *ButtonClickEvent: - if listener := l.OnButtonClick; listener != nil { - listener(e) - } - case *SelectMenuSubmitEvent: - if listener := l.OnSelectMenuSubmit; listener != nil { - listener(e) - } - case *AutocompleteEvent: - if listener := l.OnAutocomplete; listener != nil { + case *AutocompleteInteractionEvent: + if listener := l.OnAutocompleteInteraction; listener != nil { listener(e) } diff --git a/core/handlers/gateway_handler_interaction_create.go b/core/handlers/gateway_handler_interaction_create.go index ed5dceff..d117f632 100644 --- a/core/handlers/gateway_handler_interaction_create.go +++ b/core/handlers/gateway_handler_interaction_create.go @@ -29,71 +29,31 @@ func HandleInteraction(bot *core.Bot, sequenceNumber int, c chan<- discord.Inter genericEvent := events.NewGenericEvent(bot, sequenceNumber) - bot.EventManager.Dispatch(&events.InteractionCreateEvent{ + bot.EventManager.Dispatch(&events.InteractionEvent{ GenericEvent: genericEvent, Interaction: coreInteraction, }) switch i := coreInteraction.(type) { - case core.ApplicationCommandInteraction: - bot.EventManager.Dispatch(&events.ApplicationCommandInteractionCreateEvent{ + case *core.ApplicationCommandInteraction: + bot.EventManager.Dispatch(&events.ApplicationCommandInteractionEvent{ GenericEvent: genericEvent, ApplicationCommandInteraction: i, }) - switch ii := i.(type) { - case *core.SlashCommandInteraction: - bot.EventManager.Dispatch(&events.SlashCommandEvent{ - GenericEvent: genericEvent, - SlashCommandInteraction: ii, - }) - - case *core.UserCommandInteraction: - bot.EventManager.Dispatch(&events.UserCommandEvent{ - GenericEvent: genericEvent, - UserCommandInteraction: ii, - }) - - case *core.MessageCommandInteraction: - bot.EventManager.Dispatch(&events.MessageCommandEvent{ - GenericEvent: genericEvent, - MessageCommandInteraction: ii, - }) - - default: - bot.Logger.Errorf("unknown application command interaction with type %d received", ii.ApplicationCommandType()) - } - - case core.ComponentInteraction: - bot.EventManager.Dispatch(&events.ComponentInteractionCreateEvent{ + case *core.ComponentInteraction: + bot.EventManager.Dispatch(&events.ComponentInteractionEvent{ GenericEvent: genericEvent, ComponentInteraction: i, }) - switch ii := i.(type) { - case *core.ButtonInteraction: - bot.EventManager.Dispatch(&events.ButtonClickEvent{ - GenericEvent: genericEvent, - ButtonInteraction: ii, - }) - - case *core.SelectMenuInteraction: - bot.EventManager.Dispatch(&events.SelectMenuSubmitEvent{ - GenericEvent: genericEvent, - SelectMenuInteraction: ii, - }) - - default: - bot.Logger.Errorf("unknown component interaction with type %d received", ii.ComponentType()) - } - case *core.AutocompleteInteraction: - bot.EventManager.Dispatch(&events.AutocompleteEvent{ + bot.EventManager.Dispatch(&events.AutocompleteInteractionEvent{ GenericEvent: genericEvent, AutocompleteInteraction: i, }) default: - bot.Logger.Errorf("unknown interaction with type %d received", interaction.InteractionType()) + bot.Logger.Errorf("unknown interaction with type %d received", interaction.Type()) } } diff --git a/core/handlers/httpserver_handler_interaction_create.go b/core/handlers/httpserver_handler_interaction_create.go index b6b1144b..b5395553 100644 --- a/core/handlers/httpserver_handler_interaction_create.go +++ b/core/handlers/httpserver_handler_interaction_create.go @@ -18,7 +18,7 @@ func (h *httpserverHandlerInteractionCreate) HandleHTTPEvent(bot *core.Bot, c ch // we just want to pong all pings // no need for any event - if interaction.InteractionType() == discord.InteractionTypePing { + if interaction.Type() == discord.InteractionTypePing { bot.Logger.Info("received http interaction ping. responding with pong") c <- discord.InteractionResponse{ Type: discord.InteractionCallbackTypePong, diff --git a/core/interaction.go b/core/interaction.go index a7c58059..39670bc7 100644 --- a/core/interaction.go +++ b/core/interaction.go @@ -10,195 +10,113 @@ type InteractionFilter func(interaction Interaction) bool // Interaction represents a generic Interaction received from discord type Interaction interface { discord.Interaction + Respond(callbackType discord.InteractionCallbackType, callbackData discord.InteractionCallbackData, opts ...rest.RequestOpt) error } -type InteractionFields struct { - Bot *Bot +type BaseInteraction struct { + discord.BaseInteraction + Member *Member + User *User ResponseChannel chan<- discord.InteractionResponse Acknowledged bool + Bot *Bot } -type ApplicationCommandInteractionFilter func(interaction Interaction) bool - -// ApplicationCommandInteraction represents a generic ApplicationCommand Interaction received from discord -type ApplicationCommandInteraction interface { - discord.ApplicationCommandInteraction -} - -type ComponentInteractionFilter func(interaction Interaction) bool - -// ComponentInteraction represents a generic discord.Component Interaction received from discord -type ComponentInteraction interface { - discord.ComponentInteraction -} - -func commandPath(commandName string, subCommandName *string, subCommandGroupName *string) string { - path := commandName - if name := subCommandName; name != nil { - path += "/" + *name - } - if name := subCommandGroupName; name != nil { - path += "/" + *name - } - return path -} - -func respond(fields *InteractionFields, id discord.Snowflake, token string, callbackType discord.InteractionCallbackType, callbackData discord.InteractionCallbackData, opts ...rest.RequestOpt) error { - if fields.Acknowledged { +func (i *BaseInteraction) Respond(callbackType discord.InteractionCallbackType, callbackData discord.InteractionCallbackData, opts ...rest.RequestOpt) error { + if i.Acknowledged { return discord.ErrInteractionAlreadyReplied } - fields.Acknowledged = true + i.Acknowledged = true response := discord.InteractionResponse{ Type: callbackType, Data: callbackData, } - if fields.ResponseChannel != nil { - fields.ResponseChannel <- response + if i.ResponseChannel != nil { + i.ResponseChannel <- response return nil } - return fields.Bot.RestServices.InteractionService().CreateInteractionResponse(id, token, response, opts...) + return i.Bot.RestServices.InteractionService().CreateInteractionResponse(i.ID, i.Token, response, opts...) } -func deferCreate(fields *InteractionFields, id discord.Snowflake, token string, ephemeral bool, opts ...rest.RequestOpt) error { - var data discord.InteractionCallbackData - if ephemeral { - data = discord.MessageCreate{Flags: discord.MessageFlagEphemeral} +// Guild returns the Guild from the Caches +func (i *BaseInteraction) Guild() *Guild { + if i.GuildID == nil { + return nil } - return respond(fields, id, token, discord.InteractionCallbackTypeDeferredChannelMessageWithSource, data, opts...) + return i.Bot.Caches.Guilds().Get(*i.GuildID) } -func create(fields *InteractionFields, id discord.Snowflake, token string, messageCreate discord.MessageCreate, opts ...rest.RequestOpt) error { - return respond(fields, id, token, discord.InteractionCallbackTypeChannelMessageWithSource, messageCreate, opts...) +// Channel returns the Channel from the Caches +func (i *BaseInteraction) Channel() MessageChannel { + if ch := i.Bot.Caches.Channels().Get(i.ChannelID); ch != nil { + return ch.(MessageChannel) + } + return nil } -func getOriginal(fields *InteractionFields, applicationID discord.Snowflake, token string, opts ...rest.RequestOpt) (*Message, error) { - message, err := fields.Bot.RestServices.InteractionService().GetInteractionResponse(applicationID, token, opts...) - if err != nil { - return nil, err - } - return fields.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil +type ReplyInteraction struct { + *BaseInteraction } -func updateOriginal(fields *InteractionFields, applicationID discord.Snowflake, token string, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - message, err := fields.Bot.RestServices.InteractionService().UpdateInteractionResponse(applicationID, token, messageUpdate, opts...) +func (i ReplyInteraction) GetResponse(opts ...rest.RequestOpt) (*Message, error) { + message, err := i.Bot.RestServices.InteractionService().GetInteractionResponse(i.ApplicationID, i.Token, opts...) if err != nil { return nil, err } - return fields.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -func deleteOriginal(fields *InteractionFields, applicationID discord.Snowflake, token string, opts ...rest.RequestOpt) error { - return fields.Bot.RestServices.InteractionService().DeleteInteractionResponse(applicationID, token, opts...) + return i.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil } -func deferUpdate(fields *InteractionFields, applicationID discord.Snowflake, token string, opts ...rest.RequestOpt) error { - return respond(fields, applicationID, token, discord.InteractionCallbackTypeDeferredUpdateMessage, nil, opts...) -} - -func update(fields *InteractionFields, applicationID discord.Snowflake, token string, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) error { - return respond(fields, applicationID, token, discord.InteractionCallbackTypeUpdateMessage, messageUpdate, opts...) -} - -func updateComponent(fields *InteractionFields, applicationID discord.Snowflake, token string, message *Message, customID discord.CustomID, component discord.InteractiveComponent, opts ...rest.RequestOpt) error { - containerComponents := make([]discord.ContainerComponent, len(message.Components)) - for i := range message.Components { - switch container := containerComponents[i].(type) { - case discord.ActionRowComponent: - containerComponents[i] = container.UpdateComponent(customID, component) - - default: - containerComponents[i] = container - continue - } +func (i ReplyInteraction) UpdateResponse(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { + message, err := i.Bot.RestServices.InteractionService().UpdateInteractionResponse(i.ApplicationID, i.Token, messageUpdate, opts...) + if err != nil { + return nil, err } - - return update(fields, applicationID, token, discord.NewMessageUpdateBuilder().SetContainerComponents(containerComponents...).Build(), opts...) -} - -func result(fields *InteractionFields, applicationID discord.Snowflake, token string, choices []discord.AutocompleteChoice, opts ...rest.RequestOpt) error { - return respond(fields, applicationID, token, discord.InteractionCallbackTypeAutocompleteResult, discord.AutocompleteResult{Choices: choices}, opts...) + return i.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil } -func resultMapString(fields *InteractionFields, applicationID discord.Snowflake, token string, resultMap map[string]string, opts ...rest.RequestOpt) error { - choices := make([]discord.AutocompleteChoice, len(resultMap)) - ii := 0 - for name, value := range resultMap { - choices[ii] = discord.AutocompleteChoiceString{ - Name: name, - Value: value, - } - ii++ - } - return result(fields, applicationID, token, choices, opts...) +func (i ReplyInteraction) DeleteResponse(opts ...rest.RequestOpt) error { + return i.Bot.RestServices.InteractionService().DeleteInteractionResponse(i.ApplicationID, i.Token, opts...) } -func resultMapInt(fields *InteractionFields, applicationID discord.Snowflake, token string, resultMap map[string]int, opts ...rest.RequestOpt) error { - choices := make([]discord.AutocompleteChoice, len(resultMap)) - ii := 0 - for name, value := range resultMap { - choices[ii] = discord.AutocompleteChoiceInt{ - Name: name, - Value: value, - } - ii++ - } - return result(fields, applicationID, token, choices, opts...) +func (i ReplyInteraction) Create(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) error { + return i.Respond(discord.InteractionCallbackTypeChannelMessageWithSource, messageCreate, opts...) } -func resultMapFloat(fields *InteractionFields, applicationID discord.Snowflake, token string, resultMap map[string]float64, opts ...rest.RequestOpt) error { - choices := make([]discord.AutocompleteChoice, len(resultMap)) - ii := 0 - for name, value := range resultMap { - choices[ii] = discord.AutocompleteChoiceFloat{ - Name: name, - Value: value, - } - ii++ +func (i ReplyInteraction) DeferCreate(ephemeral bool, opts ...rest.RequestOpt) error { + var data discord.InteractionCallbackData + if ephemeral { + data = discord.MessageCreate{Flags: discord.MessageFlagEphemeral} } - return result(fields, applicationID, token, choices, opts...) + return i.Respond(discord.InteractionCallbackTypeDeferredChannelMessageWithSource, data, opts...) } -func getFollowup(fields *InteractionFields, applicationID discord.Snowflake, token string, messageID discord.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - message, err := fields.Bot.RestServices.InteractionService().GetFollowupMessage(applicationID, token, messageID, opts...) +func (i ReplyInteraction) GetFollowupMessage(messageID discord.Snowflake, opts ...rest.RequestOpt) (*Message, error) { + message, err := i.Bot.RestServices.InteractionService().GetFollowupMessage(i.ApplicationID, i.Token, messageID, opts...) if err != nil { return nil, err } - return fields.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil + return i.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil } -func createFollowup(fields *InteractionFields, applicationID discord.Snowflake, token string, messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - message, err := fields.Bot.RestServices.InteractionService().CreateFollowupMessage(applicationID, token, messageCreate, opts...) +func (i ReplyInteraction) CreateFollowupMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { + message, err := i.Bot.RestServices.InteractionService().CreateFollowupMessage(i.ApplicationID, i.Token, messageCreate, opts...) if err != nil { return nil, err } - return fields.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil + return i.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil } -func updateFollowup(fields *InteractionFields, applicationID discord.Snowflake, token string, messageID discord.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - message, err := fields.Bot.RestServices.InteractionService().UpdateFollowupMessage(applicationID, token, messageID, messageUpdate, opts...) +func (i ReplyInteraction) UpdateFollowupMessage(messageID discord.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { + message, err := i.Bot.RestServices.InteractionService().UpdateFollowupMessage(i.ApplicationID, i.Token, messageID, messageUpdate, opts...) if err != nil { return nil, err } - return fields.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -func deleteFollowup(fields *InteractionFields, applicationID discord.Snowflake, token string, messageID discord.Snowflake, opts ...rest.RequestOpt) error { - return fields.Bot.RestServices.InteractionService().DeleteFollowupMessage(applicationID, token, messageID, opts...) + return i.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil } -func channel(fields *InteractionFields, channelID discord.Snowflake) MessageChannel { - if ch := fields.Bot.Caches.Channels().Get(channelID); ch != nil { - return ch.(MessageChannel) - } - return nil -} - -func guild(fields *InteractionFields, guildID *discord.Snowflake) *Guild { - if guildID == nil { - return nil - } - return fields.Bot.Caches.Guilds().Get(*guildID) +func (i ReplyInteraction) DeleteFollowupMessage(messageID discord.Snowflake, opts ...rest.RequestOpt) error { + return i.Bot.RestServices.InteractionService().DeleteFollowupMessage(i.ApplicationID, i.Token, messageID, opts...) } diff --git a/core/message_command_interaction.go b/core/message_command_interaction.go deleted file mode 100644 index 54fcd38a..00000000 --- a/core/message_command_interaction.go +++ /dev/null @@ -1,79 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -type MessageCommandInteractionFilter func(messageCommandInteraction *MessageCommandInteraction) bool - -type MessageCommandInteraction struct { - discord.MessageCommandInteraction - *InteractionFields - User *User - Member *Member - Data MessageCommandInteractionData -} - -type MessageCommandInteractionData struct { - discord.MessageCommandInteractionData - Resolved *MessageCommandResolved -} - -func (i *MessageCommandInteraction) Respond(callbackType discord.InteractionCallbackType, callbackData discord.InteractionCallbackData, opts ...rest.RequestOpt) error { - return respond(i.InteractionFields, i.ID, i.Token, callbackType, callbackData, opts...) -} - -func (i *MessageCommandInteraction) Create(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) error { - return create(i.InteractionFields, i.ID, i.Token, messageCreate, opts...) -} - -func (i *MessageCommandInteraction) DeferCreate(ephemeral bool, opts ...rest.RequestOpt) error { - return deferCreate(i.InteractionFields, i.ID, i.Token, ephemeral, opts...) -} - -func (i *MessageCommandInteraction) GetOriginal(opts ...rest.RequestOpt) (*Message, error) { - return getOriginal(i.InteractionFields, i.ApplicationID, i.Token, opts...) -} - -func (i *MessageCommandInteraction) UpdateOriginal(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateOriginal(i.InteractionFields, i.ApplicationID, i.Token, messageUpdate, opts...) -} - -func (i *MessageCommandInteraction) DeleteOriginal(opts ...rest.RequestOpt) error { - return deleteOriginal(i.InteractionFields, i.ApplicationID, i.Token, opts...) -} - -func (i *MessageCommandInteraction) GetFollowup(messageID discord.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - return getFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, opts...) -} - -func (i *MessageCommandInteraction) CreateFollowup(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return createFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageCreate, opts...) -} - -func (i *MessageCommandInteraction) UpdateFollowup(messageID discord.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, messageUpdate, opts...) -} - -func (i *MessageCommandInteraction) DeleteFollowup(messageID discord.Snowflake, opts ...rest.RequestOpt) error { - return deleteFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, opts...) -} - -func (i *MessageCommandInteraction) TargetMessage() *Message { - return i.Data.Resolved.Messages[i.Data.TargetID] -} - -// Guild returns the Guild from the Caches -func (i *MessageCommandInteraction) Guild() *Guild { - return guild(i.InteractionFields, i.GuildID) -} - -// Channel returns the Channel from the Caches -func (i *MessageCommandInteraction) Channel() MessageChannel { - return channel(i.InteractionFields, i.ChannelID) -} - -type MessageCommandResolved struct { - Messages map[discord.Snowflake]*Message -} diff --git a/core/select_menu_interaction.go b/core/select_menu_interaction.go deleted file mode 100644 index d3781a6f..00000000 --- a/core/select_menu_interaction.go +++ /dev/null @@ -1,103 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -// SelectMenuInteractionFilter used to filter SelectMenuInteraction(s) in a collectors.SelectMenuSubmitCollector -type SelectMenuInteractionFilter func(selectMenuInteraction *SelectMenuInteraction) bool - -var _ Interaction = (*SelectMenuInteraction)(nil) -var _ ComponentInteraction = (*SelectMenuInteraction)(nil) - -type SelectMenuInteraction struct { - discord.SelectMenuInteraction - *InteractionFields - User *User - Member *Member - Message *Message -} - -func (i *SelectMenuInteraction) Respond(callbackType discord.InteractionCallbackType, callbackData discord.InteractionCallbackData, opts ...rest.RequestOpt) error { - return respond(i.InteractionFields, i.ID, i.Token, callbackType, callbackData, opts...) -} - -func (i *SelectMenuInteraction) Create(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) error { - return create(i.InteractionFields, i.ID, i.Token, messageCreate, opts...) -} - -func (i *SelectMenuInteraction) DeferCreate(ephemeral bool, opts ...rest.RequestOpt) error { - return deferCreate(i.InteractionFields, i.ID, i.Token, ephemeral, opts...) -} - -func (i *SelectMenuInteraction) GetOriginal(opts ...rest.RequestOpt) (*Message, error) { - return getOriginal(i.InteractionFields, i.ApplicationID, i.Token, opts...) -} - -func (i *SelectMenuInteraction) UpdateOriginal(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateOriginal(i.InteractionFields, i.ApplicationID, i.Token, messageUpdate, opts...) -} - -func (i *SelectMenuInteraction) DeleteOriginal(opts ...rest.RequestOpt) error { - return deleteOriginal(i.InteractionFields, i.ApplicationID, i.Token, opts...) -} - -func (i *SelectMenuInteraction) GetFollowup(messageID discord.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - return getFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, opts...) -} - -func (i *SelectMenuInteraction) CreateFollowup(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return createFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageCreate, opts...) -} - -func (i *SelectMenuInteraction) UpdateFollowup(messageID discord.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, messageUpdate, opts...) -} - -func (i *SelectMenuInteraction) DeleteFollowup(messageID discord.Snowflake, opts ...rest.RequestOpt) error { - return deleteFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, opts...) -} - -func (i *SelectMenuInteraction) Update(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) error { - return update(i.InteractionFields, i.ID, i.Token, messageUpdate, opts...) -} - -func (i *SelectMenuInteraction) DeferUpdate(opts ...rest.RequestOpt) error { - return deferUpdate(i.InteractionFields, i.ApplicationID, i.Token, opts...) -} - -// UpdateSelectMenu updates the used SelectMenuComponent with a new SelectMenuComponent -func (i *SelectMenuInteraction) UpdateSelectMenu(selectMenu discord.SelectMenuComponent, opts ...rest.RequestOpt) error { - return updateComponent(i.InteractionFields, i.ApplicationID, i.Token, i.Message, i.Data.CustomID, selectMenu, opts...) -} - -// SelectMenuComponent returns the SelectMenuComponent which issued this SelectMenuInteraction -func (i *SelectMenuInteraction) SelectMenuComponent() discord.SelectMenuComponent { - // this should never be nil - return *i.Message.SelectMenuByID(i.Data.CustomID) -} - -// SelectedOptions returns the selected SelectMenuOption(s) -func (i *SelectMenuInteraction) SelectedOptions() []discord.SelectMenuOption { - options := make([]discord.SelectMenuOption, len(i.Data.Values)) - for ii, option := range i.SelectMenuComponent().Options { - for _, value := range i.Data.Values { - if value == option.Value { - options[ii] = option - break - } - } - } - return options -} - -// Guild returns the Guild from the Caches -func (i *SelectMenuInteraction) Guild() *Guild { - return guild(i.InteractionFields, i.GuildID) -} - -// Channel returns the Channel from the Caches -func (i *SelectMenuInteraction) Channel() MessageChannel { - return channel(i.InteractionFields, i.ChannelID) -} diff --git a/core/slash_command_interaction.go b/core/slash_command_interaction.go deleted file mode 100644 index 028a704e..00000000 --- a/core/slash_command_interaction.go +++ /dev/null @@ -1,327 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -type SlashCommandInteractionFilter func(slashCommandInteraction *SlashCommandInteraction) bool - -type SlashCommandInteraction struct { - discord.SlashCommandInteraction - *InteractionFields - User *User - Member *Member - Data SlashCommandInteractionData -} - -type SlashCommandInteractionData struct { - discord.SlashCommandInteractionData - SubCommandName *string - SubCommandGroupName *string - Resolved *SlashCommandResolved - Options SlashCommandOptionsMap -} - -func (i *SlashCommandInteraction) Respond(callbackType discord.InteractionCallbackType, callbackData discord.InteractionCallbackData, opts ...rest.RequestOpt) error { - return respond(i.InteractionFields, i.ID, i.Token, callbackType, callbackData, opts...) -} - -func (i *SlashCommandInteraction) Create(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) error { - return create(i.InteractionFields, i.ID, i.Token, messageCreate, opts...) -} - -func (i *SlashCommandInteraction) DeferCreate(ephemeral bool, opts ...rest.RequestOpt) error { - return deferCreate(i.InteractionFields, i.ID, i.Token, ephemeral, opts...) -} - -func (i *SlashCommandInteraction) GetOriginal(opts ...rest.RequestOpt) (*Message, error) { - return getOriginal(i.InteractionFields, i.ApplicationID, i.Token, opts...) -} - -func (i *SlashCommandInteraction) UpdateOriginal(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateOriginal(i.InteractionFields, i.ApplicationID, i.Token, messageUpdate, opts...) -} - -func (i *SlashCommandInteraction) DeleteOriginal(opts ...rest.RequestOpt) error { - return deleteOriginal(i.InteractionFields, i.ApplicationID, i.Token, opts...) -} - -func (i *SlashCommandInteraction) GetFollowup(messageID discord.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - return getFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, opts...) -} - -func (i *SlashCommandInteraction) CreateFollowup(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return createFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageCreate, opts...) -} - -func (i *SlashCommandInteraction) UpdateFollowup(messageID discord.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, messageUpdate, opts...) -} - -func (i *SlashCommandInteraction) DeleteFollowup(messageID discord.Snowflake, opts ...rest.RequestOpt) error { - return deleteFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, opts...) -} - -// CommandPath returns the ApplicationCommand path -func (i *SlashCommandInteraction) CommandPath() string { - return commandPath(i.Data.CommandName, i.Data.SubCommandName, i.Data.SubCommandGroupName) -} - -// Guild returns the Guild from the Caches -func (i *SlashCommandInteraction) Guild() *Guild { - return guild(i.InteractionFields, i.GuildID) -} - -// Channel returns the Channel from the Caches -func (i *SlashCommandInteraction) Channel() MessageChannel { - return channel(i.InteractionFields, i.ChannelID) -} - -// SlashCommandResolved contains resolved mention data for SlashCommand(s) -type SlashCommandResolved struct { - Users map[discord.Snowflake]*User - Members map[discord.Snowflake]*Member - Roles map[discord.Snowflake]*Role - Channels map[discord.Snowflake]Channel -} - -type SlashCommandOptionsMap map[string]SlashCommandOption - -func (m SlashCommandOptionsMap) Get(name string) SlashCommandOption { - if option, ok := m[name]; ok { - return option - } - return nil -} - -func (m SlashCommandOptionsMap) StringOption(name string) *SlashCommandOptionString { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionString); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) String(name string) *string { - option := m.StringOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m SlashCommandOptionsMap) IntOption(name string) *SlashCommandOptionInt { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionInt); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Int(name string) *int { - option := m.IntOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m SlashCommandOptionsMap) BoolOption(name string) *SlashCommandOptionBool { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionBool); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Bool(name string) *bool { - option := m.BoolOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m SlashCommandOptionsMap) UserOption(name string) *SlashCommandOptionUser { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionUser); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) User(name string) *User { - option := m.Get(name) - if option == nil { - return nil - } - switch opt := option.(type) { - case SlashCommandOptionUser: - return opt.User() - case SlashCommandOptionMentionable: - return opt.User() - default: - return nil - } -} - -func (m SlashCommandOptionsMap) Member(name string) *Member { - option := m.Get(name) - if option == nil { - return nil - } - switch opt := option.(type) { - case SlashCommandOptionUser: - return opt.Member() - case SlashCommandOptionMentionable: - return opt.Member() - default: - return nil - } -} - -func (m SlashCommandOptionsMap) ChannelOption(name string) *SlashCommandOptionChannel { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionChannel); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Channel(name string) Channel { - option := m.ChannelOption(name) - if option == nil { - return nil - } - return option.Channel() -} - -func (m SlashCommandOptionsMap) RoleOption(name string) *SlashCommandOptionRole { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionRole); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Role(name string) *Role { - option := m.Get(name) - if option == nil { - return nil - } - switch opt := option.(type) { - case SlashCommandOptionRole: - return opt.Role() - case SlashCommandOptionMentionable: - return opt.Role() - default: - return nil - } -} - -func (m SlashCommandOptionsMap) MentionableOption(name string) *SlashCommandOptionMentionable { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionMentionable); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Snowflake(name string) *discord.Snowflake { - option := m.Get(name) - if option == nil { - return nil - } - switch opt := option.(type) { - case SlashCommandOptionChannel: - return &opt.Value - - case SlashCommandOptionRole: - return &opt.Value - - case SlashCommandOptionUser: - return &opt.Value - - case SlashCommandOptionMentionable: - return &opt.Value - - default: - return nil - } -} - -func (m SlashCommandOptionsMap) FloatOption(name string) *SlashCommandOptionFloat { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionFloat); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Float(name string) *float64 { - option := m.FloatOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m SlashCommandOptionsMap) GetAll() []SlashCommandOption { - options := make([]SlashCommandOption, len(m)) - i := 0 - for _, option := range m { - options[i] = option - i++ - } - return options -} - -func (m SlashCommandOptionsMap) GetByType(optionType discord.ApplicationCommandOptionType) []SlashCommandOption { - return m.FindAll(func(option SlashCommandOption) bool { - return option.Type() == optionType - }) -} - -func (m SlashCommandOptionsMap) Find(optionFindFunc func(option SlashCommandOption) bool) SlashCommandOption { - for _, option := range m { - if optionFindFunc(option) { - return option - } - } - return nil -} - -func (m SlashCommandOptionsMap) FindAll(optionFindFunc func(option SlashCommandOption) bool) []SlashCommandOption { - var options []SlashCommandOption - for _, option := range m { - if optionFindFunc(option) { - options = append(options, option) - } - } - return options -} diff --git a/core/slash_command_option.go b/core/slash_command_option.go index 04f1bf67..dd920b9d 100644 --- a/core/slash_command_option.go +++ b/core/slash_command_option.go @@ -136,3 +136,243 @@ func (o SlashCommandOptionMentionable) Role() *Role { type SlashCommandOptionFloat struct { discord.SlashCommandOptionFloat } + +type SlashCommandOptionsMap map[string]SlashCommandOption + +func (m SlashCommandOptionsMap) Get(name string) SlashCommandOption { + if option, ok := m[name]; ok { + return option + } + return nil +} + +func (m SlashCommandOptionsMap) StringOption(name string) *SlashCommandOptionString { + option := m.Get(name) + if option == nil { + return nil + } + if opt, ok := option.(SlashCommandOptionString); ok { + return &opt + } + return nil +} + +func (m SlashCommandOptionsMap) String(name string) *string { + option := m.StringOption(name) + if option == nil { + return nil + } + return &option.Value +} + +func (m SlashCommandOptionsMap) IntOption(name string) *SlashCommandOptionInt { + option := m.Get(name) + if option == nil { + return nil + } + if opt, ok := option.(SlashCommandOptionInt); ok { + return &opt + } + return nil +} + +func (m SlashCommandOptionsMap) Int(name string) *int { + option := m.IntOption(name) + if option == nil { + return nil + } + return &option.Value +} + +func (m SlashCommandOptionsMap) BoolOption(name string) *SlashCommandOptionBool { + option := m.Get(name) + if option == nil { + return nil + } + if opt, ok := option.(SlashCommandOptionBool); ok { + return &opt + } + return nil +} + +func (m SlashCommandOptionsMap) Bool(name string) *bool { + option := m.BoolOption(name) + if option == nil { + return nil + } + return &option.Value +} + +func (m SlashCommandOptionsMap) UserOption(name string) *SlashCommandOptionUser { + option := m.Get(name) + if option == nil { + return nil + } + if opt, ok := option.(SlashCommandOptionUser); ok { + return &opt + } + return nil +} + +func (m SlashCommandOptionsMap) User(name string) *User { + option := m.Get(name) + if option == nil { + return nil + } + switch opt := option.(type) { + case SlashCommandOptionUser: + return opt.User() + case SlashCommandOptionMentionable: + return opt.User() + default: + return nil + } +} + +func (m SlashCommandOptionsMap) Member(name string) *Member { + option := m.Get(name) + if option == nil { + return nil + } + switch opt := option.(type) { + case SlashCommandOptionUser: + return opt.Member() + case SlashCommandOptionMentionable: + return opt.Member() + default: + return nil + } +} + +func (m SlashCommandOptionsMap) ChannelOption(name string) *SlashCommandOptionChannel { + option := m.Get(name) + if option == nil { + return nil + } + if opt, ok := option.(SlashCommandOptionChannel); ok { + return &opt + } + return nil +} + +func (m SlashCommandOptionsMap) Channel(name string) Channel { + option := m.ChannelOption(name) + if option == nil { + return nil + } + return option.Channel() +} + +func (m SlashCommandOptionsMap) RoleOption(name string) *SlashCommandOptionRole { + option := m.Get(name) + if option == nil { + return nil + } + if opt, ok := option.(SlashCommandOptionRole); ok { + return &opt + } + return nil +} + +func (m SlashCommandOptionsMap) Role(name string) *Role { + option := m.Get(name) + if option == nil { + return nil + } + switch opt := option.(type) { + case SlashCommandOptionRole: + return opt.Role() + case SlashCommandOptionMentionable: + return opt.Role() + default: + return nil + } +} + +func (m SlashCommandOptionsMap) MentionableOption(name string) *SlashCommandOptionMentionable { + option := m.Get(name) + if option == nil { + return nil + } + if opt, ok := option.(SlashCommandOptionMentionable); ok { + return &opt + } + return nil +} + +func (m SlashCommandOptionsMap) Snowflake(name string) *discord.Snowflake { + option := m.Get(name) + if option == nil { + return nil + } + switch opt := option.(type) { + case SlashCommandOptionChannel: + return &opt.Value + + case SlashCommandOptionRole: + return &opt.Value + + case SlashCommandOptionUser: + return &opt.Value + + case SlashCommandOptionMentionable: + return &opt.Value + + default: + return nil + } +} + +func (m SlashCommandOptionsMap) FloatOption(name string) *SlashCommandOptionFloat { + option := m.Get(name) + if option == nil { + return nil + } + if opt, ok := option.(SlashCommandOptionFloat); ok { + return &opt + } + return nil +} + +func (m SlashCommandOptionsMap) Float(name string) *float64 { + option := m.FloatOption(name) + if option == nil { + return nil + } + return &option.Value +} + +func (m SlashCommandOptionsMap) GetAll() []SlashCommandOption { + options := make([]SlashCommandOption, len(m)) + i := 0 + for _, option := range m { + options[i] = option + i++ + } + return options +} + +func (m SlashCommandOptionsMap) GetByType(optionType discord.ApplicationCommandOptionType) []SlashCommandOption { + return m.FindAll(func(option SlashCommandOption) bool { + return option.Type() == optionType + }) +} + +func (m SlashCommandOptionsMap) Find(optionFindFunc func(option SlashCommandOption) bool) SlashCommandOption { + for _, option := range m { + if optionFindFunc(option) { + return option + } + } + return nil +} + +func (m SlashCommandOptionsMap) FindAll(optionFindFunc func(option SlashCommandOption) bool) []SlashCommandOption { + var options []SlashCommandOption + for _, option := range m { + if optionFindFunc(option) { + options = append(options, option) + } + } + return options +} diff --git a/core/user_command_interaction.go b/core/user_command_interaction.go deleted file mode 100644 index 6ba4f215..00000000 --- a/core/user_command_interaction.go +++ /dev/null @@ -1,84 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -type UserCommandInteractionFilter func(userCommandInteraction *UserCommandInteraction) bool - -type UserCommandInteraction struct { - discord.UserCommandInteraction - *InteractionFields - User *User - Member *Member - Data UserCommandInteractionData -} - -type UserCommandInteractionData struct { - discord.UserCommandInteractionData - Resolved *UserCommandResolved -} - -func (i *UserCommandInteraction) Respond(callbackType discord.InteractionCallbackType, callbackData discord.InteractionCallbackData, opts ...rest.RequestOpt) error { - return respond(i.InteractionFields, i.ID, i.Token, callbackType, callbackData, opts...) -} - -func (i *UserCommandInteraction) Create(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) error { - return create(i.InteractionFields, i.ID, i.Token, messageCreate, opts...) -} - -func (i *UserCommandInteraction) DeferCreate(ephemeral bool, opts ...rest.RequestOpt) error { - return deferCreate(i.InteractionFields, i.ID, i.Token, ephemeral, opts...) -} - -func (i *UserCommandInteraction) GetOriginal(opts ...rest.RequestOpt) (*Message, error) { - return getOriginal(i.InteractionFields, i.ApplicationID, i.Token, opts...) -} - -func (i *UserCommandInteraction) UpdateOriginal(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateOriginal(i.InteractionFields, i.ApplicationID, i.Token, messageUpdate, opts...) -} - -func (i *UserCommandInteraction) DeleteOriginal(opts ...rest.RequestOpt) error { - return deleteOriginal(i.InteractionFields, i.ApplicationID, i.Token, opts...) -} - -func (i *UserCommandInteraction) GetFollowup(messageID discord.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - return getFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, opts...) -} - -func (i *UserCommandInteraction) CreateFollowup(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return createFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageCreate, opts...) -} - -func (i *UserCommandInteraction) UpdateFollowup(messageID discord.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, messageUpdate, opts...) -} - -func (i *UserCommandInteraction) DeleteFollowup(messageID discord.Snowflake, opts ...rest.RequestOpt) error { - return deleteFollowup(i.InteractionFields, i.ApplicationID, i.Token, messageID, opts...) -} - -func (i *UserCommandInteraction) TargetUser() *User { - return i.Data.Resolved.Users[i.Data.TargetID] -} - -func (i *UserCommandInteraction) TargetMember() *Member { - return i.Data.Resolved.Members[i.Data.TargetID] -} - -// Guild returns the Guild from the Caches -func (i *UserCommandInteraction) Guild() *Guild { - return guild(i.InteractionFields, i.GuildID) -} - -// Channel returns the Channel from the Caches -func (i *UserCommandInteraction) Channel() MessageChannel { - return channel(i.InteractionFields, i.ChannelID) -} - -type UserCommandResolved struct { - Users map[discord.Snowflake]*User - Members map[discord.Snowflake]*Member -} diff --git a/discord/interaction.go b/discord/interaction.go index 4babd2a4..075f9639 100644 --- a/discord/interaction.go +++ b/discord/interaction.go @@ -23,17 +23,24 @@ type Interaction interface { interaction() } +type BaseInteraction struct { + ID Snowflake `json:"id"` + ApplicationID Snowflake `json:"application_id"` + Token string `json:"token"` + Version int `json:"version"` + GuildID *Snowflake `json:"guild_id,omitempty"` + ChannelID Snowflake `json:"channel_id"` + Member *Member `json:"member,omitempty"` + User *User `json:"user,omitempty"` +} + type UnmarshalInteraction struct { Interaction } func (i *UnmarshalInteraction) UnmarshalJSON(data []byte) error { var iType struct { - InteractionType InteractionType `json:"type"` - Data struct { - ApplicationCommandType ApplicationCommandType `json:"type"` - ComponentType ComponentType `json:"component_type"` - } `json:"data"` + Type InteractionType `json:"type"` } if err := json.Unmarshal(data, &iType); err != nil { @@ -45,7 +52,7 @@ func (i *UnmarshalInteraction) UnmarshalJSON(data []byte) error { err error ) - switch iType.InteractionType { + switch iType.Type { case InteractionTypePing: v := PingInteraction{} err = json.Unmarshal(data, &v) @@ -67,7 +74,7 @@ func (i *UnmarshalInteraction) UnmarshalJSON(data []byte) error { interaction = v default: - return fmt.Errorf("unkown interaction with type %d received", iType.InteractionType) + return fmt.Errorf("unkown interaction with type %d received", iType.Type) } if err != nil { return err @@ -87,7 +94,6 @@ type PingInteraction struct { } func (PingInteraction) interaction() {} - func (PingInteraction) Type() InteractionType { return InteractionTypePing } @@ -97,15 +103,8 @@ var ( ) type ApplicationCommandInteraction struct { - ID Snowflake `json:"id"` - ApplicationID Snowflake `json:"application_id"` - Token string `json:"token"` - Version int `json:"version"` - GuildID *Snowflake `json:"guild_id,omitempty"` - ChannelID Snowflake `json:"channel_id"` - Member *Member `json:"member,omitempty"` - User *User `json:"user,omitempty"` - Data ApplicationCommandInteractionData `json:"data"` + BaseInteraction + Data ApplicationCommandInteractionData `json:"data"` } func (ApplicationCommandInteraction) interaction() {} @@ -131,7 +130,7 @@ func (i *ApplicationCommandInteraction) UnmarshalJSON(data []byte) error { interactionData ApplicationCommandInteractionData err error ) - switch cType.Type { + switch cType.Data.Type { case ApplicationCommandTypeSlash: v := SlashCommandInteractionData{} err = json.Unmarshal(data, &v) @@ -148,7 +147,7 @@ func (i *ApplicationCommandInteraction) UnmarshalJSON(data []byte) error { interactionData = v default: - return fmt.Errorf("unkown application interaction data with type %d received", cType.Type) + return fmt.Errorf("unkown application interaction data with type %d received", cType.Data.Type) } if err != nil { return err @@ -253,16 +252,9 @@ var ( ) type ComponentInteraction struct { - ID Snowflake `json:"id"` - ApplicationID Snowflake `json:"application_id"` - Token string `json:"token"` - Version int `json:"version"` - GuildID *Snowflake `json:"guild_id,omitempty"` - ChannelID Snowflake `json:"channel_id"` - Member *Member `json:"member,omitempty"` - User *User `json:"user,omitempty"` - Data ComponentInteractionData `json:"data"` - Message Message `json:"message"` + BaseInteraction + Data ComponentInteractionData `json:"data"` + Message Message `json:"message"` } func (ComponentInteraction) interaction() {} @@ -299,7 +291,7 @@ func (i *ComponentInteraction) UnmarshalJSON(data []byte) error { interactionData = v default: - return fmt.Errorf("unkown application interaction data with type %d received", cType.Data.Type) + return fmt.Errorf("unkown component interaction data with type %d received", cType.Data.Type) } if err != nil { return err @@ -344,15 +336,8 @@ var ( ) type AutocompleteInteraction struct { - ID Snowflake `json:"id"` - ApplicationID Snowflake `json:"application_id"` - Token string `json:"token"` - Version int `json:"version"` - GuildID *Snowflake `json:"guild_id,omitempty"` - ChannelID Snowflake `json:"channel_id"` - Member *Member `json:"member,omitempty"` - User *User `json:"user,omitempty"` - Data AutocompleteInteractionData `json:"data"` + BaseInteraction + Data AutocompleteInteractionData `json:"data"` } func (AutocompleteInteraction) interaction() {} From 5b5304d511e4b09092a9a060451059d7a9ef63d9 Mon Sep 17 00:00:00 2001 From: TopiSenpai Date: Sun, 9 Jan 2022 17:37:31 +0100 Subject: [PATCH 3/4] fix unmarshalling of interactions --- discord/interaction.go | 53 +++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/discord/interaction.go b/discord/interaction.go index 075f9639..a1a4585b 100644 --- a/discord/interaction.go +++ b/discord/interaction.go @@ -115,14 +115,18 @@ func (ApplicationCommandInteraction) Type() InteractionType { func (i *ApplicationCommandInteraction) UnmarshalJSON(data []byte) error { type applicationCommandInteraction ApplicationCommandInteraction - var cType struct { - Data struct { - Type ApplicationCommandType `json:"type"` - } `json:"data"` + var interaction struct { + Data json.RawMessage `json:"data"` applicationCommandInteraction } - if err := json.Unmarshal(data, &cType); err != nil { + if err := json.Unmarshal(data, &interaction); err != nil { + return err + } + var cType struct { + Type ApplicationCommandType `json:"type"` + } + if err := json.Unmarshal(interaction.Data, &cType); err != nil { return err } @@ -130,30 +134,31 @@ func (i *ApplicationCommandInteraction) UnmarshalJSON(data []byte) error { interactionData ApplicationCommandInteractionData err error ) - switch cType.Data.Type { + + switch cType.Type { case ApplicationCommandTypeSlash: v := SlashCommandInteractionData{} - err = json.Unmarshal(data, &v) + err = json.Unmarshal(interaction.Data, &v) interactionData = v case ApplicationCommandTypeUser: v := UserCommandInteractionData{} - err = json.Unmarshal(data, &v) + err = json.Unmarshal(interaction.Data, &v) interactionData = v case ApplicationCommandTypeMessage: v := MessageCommandInteractionData{} - err = json.Unmarshal(data, &v) + err = json.Unmarshal(interaction.Data, &v) interactionData = v default: - return fmt.Errorf("unkown application interaction data with type %d received", cType.Data.Type) + return fmt.Errorf("unkown application interaction data with type %d received", cType.Type) } if err != nil { return err } - *i = ApplicationCommandInteraction(cType.applicationCommandInteraction) + *i = ApplicationCommandInteraction(interaction.applicationCommandInteraction) i.Data = interactionData return nil @@ -264,14 +269,20 @@ func (ComponentInteraction) Type() InteractionType { func (i *ComponentInteraction) UnmarshalJSON(data []byte) error { type componentInteraction ComponentInteraction - var cType struct { - Data struct { - Type ComponentType `json:"component_type"` - } `json:"data"` + var interaction struct { + Data json.RawMessage `json:"data"` componentInteraction } - if err := json.Unmarshal(data, &cType); err != nil { + if err := json.Unmarshal(data, &interaction); err != nil { + return err + } + + var cType struct { + Type ComponentType `json:"component_type"` + } + + if err := json.Unmarshal(interaction.Data, &cType); err != nil { return err } @@ -279,25 +290,25 @@ func (i *ComponentInteraction) UnmarshalJSON(data []byte) error { interactionData ComponentInteractionData err error ) - switch cType.Data.Type { + switch cType.Type { case ComponentTypeButton: v := ButtonInteractionData{} - err = json.Unmarshal(data, &v) + err = json.Unmarshal(interaction.Data, &v) interactionData = v case ComponentTypeSelectMenu: v := SelectMenuInteractionData{} - err = json.Unmarshal(data, &v) + err = json.Unmarshal(interaction.Data, &v) interactionData = v default: - return fmt.Errorf("unkown component interaction data with type %d received", cType.Data.Type) + return fmt.Errorf("unkown component interaction data with type %d received", cType.Type) } if err != nil { return err } - *i = ComponentInteraction(cType.componentInteraction) + *i = ComponentInteraction(interaction.componentInteraction) i.Data = interactionData return nil From 0d88c3ba6661100690192ca8b05f338bf227cfa1 Mon Sep 17 00:00:00 2001 From: TopiSenpai Date: Sun, 9 Jan 2022 17:50:08 +0100 Subject: [PATCH 4/4] remove unused func --- discord/interaction.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/discord/interaction.go b/discord/interaction.go index a1a4585b..27a5c165 100644 --- a/discord/interaction.go +++ b/discord/interaction.go @@ -107,8 +107,7 @@ type ApplicationCommandInteraction struct { Data ApplicationCommandInteractionData `json:"data"` } -func (ApplicationCommandInteraction) interaction() {} -func (ApplicationCommandInteraction) applicationCommandInteraction() {} +func (ApplicationCommandInteraction) interaction() {} func (ApplicationCommandInteraction) Type() InteractionType { return InteractionTypeApplicationCommand }