Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slash commands example: parse options into a map #1129

Merged
merged 7 commits into from Apr 4, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
106 changes: 65 additions & 41 deletions examples/slash_commands/main.go
Expand Up @@ -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,
},
Expand All @@ -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,
},
Expand Down Expand Up @@ -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{
Expand All @@ -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(
Expand All @@ -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{
Expand Down Expand Up @@ -419,5 +443,5 @@ func main() {
}
}

log.Println("Gracefully shutdowning")
log.Println("Gracefully shutting down.")
}