diff --git a/examples/slash_commands/main.go b/examples/slash_commands/main.go index 5ac892635..b0016cc9b 100644 --- a/examples/slash_commands/main.go +++ b/examples/slash_commands/main.go @@ -119,14 +119,14 @@ var ( // will cause the registration of the command to fail { - Name: "scmd-grp", + Name: "subcommand-group", Description: "Subcommands group", Options: []*discordgo.ApplicationCommandOption{ // Also, subcommand groups aren't capable of // containing options, by the name of them, you can see // they can only contain subcommands { - Name: "nst-subcmd", + Name: "nested-subcommand", Description: "Nested subcommand", Type: discordgo.ApplicationCommandOptionSubCommand, }, @@ -139,7 +139,7 @@ var ( // Read the intro of slash-commands docs on Discord dev portal // to get more information { - Name: "subcmd", + Name: "subcommand", Description: "Top-level subcommand", Type: discordgo.ApplicationCommandOptionSubCommand, }, @@ -172,6 +172,7 @@ var ( Description: "Followup messages", }, } + commandHandlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){ "basic-command": func(s *discordgo.Session, i *discordgo.InteractionCreate) { s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ @@ -197,37 +198,62 @@ var ( }) }, "options": func(s *discordgo.Session, i *discordgo.InteractionCreate) { - margs := []interface{}{ - // Here we need to convert raw interface{} value to wanted type. - // Also, as you can see, here is used utility functions to convert the value - // to particular type. Yeah, you can use just switch type, - // but this is much simpler - i.ApplicationCommandData().Options[0].StringValue(), - i.ApplicationCommandData().Options[1].IntValue(), - i.ApplicationCommandData().Options[2].FloatValue(), - i.ApplicationCommandData().Options[3].BoolValue(), + // Access options in the order provided by the user. + options := i.ApplicationCommandData().Options + + // Or convert the slice into a map + optionMap := make(map[string]*discordgo.ApplicationCommandInteractionDataOption, len(options)) + for _, opt := range options { + optionMap[opt.Name] = opt + } + + // This example stores the provided arguments in an []interface{} + // which will be used to format the bot's response + margs := make([]interface{}, 0, len(options)) + msgformat := "You learned how to use command options! " + + "Take a look at the value(s) you entered:\n" + + // Get the value from the option map. + // When the option exists, ok = true + if option, ok := optionMap["string-option"]; ok { + // Option values must be type asserted from interface{}. + // Discordgo provides utility functions to make this simple. + margs = append(margs, option.StringValue()) + msgformat += "> string-option: %s\n" + } + + if opt, ok := optionMap["integer-option"]; ok { + margs = append(margs, opt.IntValue()) + msgformat += "> integer-option: %d\n" + } + + if opt, ok := optionMap["number-option"]; ok { + margs = append(margs, opt.FloatValue()) + msgformat += "> number-option: %f\n" + } + + if opt, ok := optionMap["bool-option"]; ok { + margs = append(margs, opt.BoolValue()) + msgformat += "> bool-option: %v\n" } - msgformat := - ` Now you just learned how to use command options. Take a look to the value of which you've just entered: - > string_option: %s - > integer_option: %d - > number_option: %f - > bool_option: %v -` - if len(i.ApplicationCommandData().Options) >= 5 { - margs = append(margs, i.ApplicationCommandData().Options[4].ChannelValue(nil).ID) + + if opt, ok := optionMap["channel-option"]; ok { + margs = append(margs, opt.ChannelValue(nil).ID) msgformat += "> channel-option: <#%s>\n" } - if len(i.ApplicationCommandData().Options) >= 6 { - margs = append(margs, i.ApplicationCommandData().Options[5].UserValue(nil).ID) + + if opt, ok := optionMap["user-option"]; ok { + margs = append(margs, opt.UserValue(nil).ID) msgformat += "> user-option: <@%s>\n" } - if len(i.ApplicationCommandData().Options) >= 7 { - margs = append(margs, i.ApplicationCommandData().Options[6].RoleValue(nil, "").ID) + + if opt, ok := optionMap["role-option"]; ok { + margs = append(margs, opt.RoleValue(nil, "").ID) msgformat += "> role-option: <@&%s>\n" } + s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ - // Ignore type for now, we'll discuss them in "responses" part + // Ignore type for now, they will be discussed in "responses" Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: fmt.Sprintf( @@ -238,27 +264,25 @@ var ( }) }, "subcommands": func(s *discordgo.Session, i *discordgo.InteractionCreate) { + options := i.ApplicationCommandData().Options content := "" - // As you can see, the name of subcommand (nested, top-level) or subcommand group - // is provided through arguments. - switch i.ApplicationCommandData().Options[0].Name { - case "subcmd": - content = - "The top-level subcommand is executed. Now try to execute the nested one." - default: - if i.ApplicationCommandData().Options[0].Name != "scmd-grp" { - return - } - switch i.ApplicationCommandData().Options[0].Options[0].Name { - case "nst-subcmd": + // As you can see, names of subcommands (nested, top-level) + // and subcommand groups are provided through the arguments. + switch options[0].Name { + case "subcommand": + content = "The top-level subcommand is executed. Now try to execute the nested one." + case "subcommand-group": + options = options[0].Options + switch options[0].Name { + case "nested-subcommand": content = "Nice, now you know how to execute nested commands too" default: - // I added this in the case something might go wrong - content = "Oops, something gone wrong.\n" + + content = "Oops, something went wrong.\n" + "Hol' up, you aren't supposed to see this message." } } + s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ @@ -419,5 +443,5 @@ func main() { } } - log.Println("Gracefully shutdowning") + log.Println("Gracefully shutting down.") }