You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

06-subcommands.md 6.6 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. ---
  2. uid: Guides.SlashCommands.SubCommand
  3. title: Sub Commands
  4. ---
  5. # Subcommands
  6. Subcommands allow you to have multiple commands available in a single command. They can be useful for representing sub options for a command. For example: A settings command. Let's first look at some limitations with subcommands set by discord.
  7. - An app can have up to 25 subcommand groups on a top-level command
  8. - An app can have up to 25 subcommands within a subcommand group
  9. - commands can have up to 25 `options`
  10. - options can have up to 25 `choices`
  11. ```
  12. VALID
  13. command
  14. |
  15. |__ subcommand
  16. |
  17. |__ subcommand
  18. ----
  19. command
  20. |
  21. |__ subcommand-group
  22. |
  23. |__ subcommand
  24. |
  25. |__ subcommand-group
  26. |
  27. |__ subcommand
  28. -------
  29. INVALID
  30. command
  31. |
  32. |__ subcommand-group
  33. |
  34. |__ subcommand-group
  35. |
  36. |__ subcommand-group
  37. |
  38. |__ subcommand-group
  39. ----
  40. INVALID
  41. command
  42. |
  43. |__ subcommand
  44. |
  45. |__ subcommand-group
  46. |
  47. |__ subcommand
  48. |
  49. |__ subcommand-group
  50. ```
  51. Let's write a settings command that can change 3 fields in our bot.
  52. ```cs
  53. public string FieldA { get; set; } = "test";
  54. public int FieldB { get; set; } = 10;
  55. public bool FieldC { get; set; } = true;
  56. public async Task Client_Ready()
  57. {
  58. ulong guildId = 848176216011046962;
  59. var guildCommand = new SlashCommandBuilder()
  60. .WithName("settings")
  61. .WithDescription("Changes some settings within the bot.")
  62. .AddOption(new SlashCommandOptionBuilder()
  63. .WithName("field-a")
  64. .WithDescription("Gets or sets the field A")
  65. .WithType(ApplicationCommandOptionType.SubCommandGroup)
  66. .AddOption(new SlashCommandOptionBuilder()
  67. .WithName("set")
  68. .WithDescription("Sets the field A")
  69. .WithType(ApplicationCommandOptionType.SubCommand)
  70. .AddOption("value", ApplicationCommandOptionType.String, "the value to set the field", isRequired: true)
  71. ).AddOption(new SlashCommandOptionBuilder()
  72. .WithName("get")
  73. .WithDescription("Gets the value of field A.")
  74. .WithType(ApplicationCommandOptionType.SubCommand)
  75. )
  76. ).AddOption(new SlashCommandOptionBuilder()
  77. .WithName("field-b")
  78. .WithDescription("Gets or sets the field B")
  79. .WithType(ApplicationCommandOptionType.SubCommandGroup)
  80. .AddOption(new SlashCommandOptionBuilder()
  81. .WithName("set")
  82. .WithDescription("Sets the field B")
  83. .WithType(ApplicationCommandOptionType.SubCommand)
  84. .AddOption("value", ApplicationCommandOptionType.Integer, "the value to set the fie to.", isRequired: true)
  85. ).AddOption(new SlashCommandOptionBuilder()
  86. .WithName("get")
  87. .WithDescription("Gets the value of field B.")
  88. .WithType(ApplicationCommandOptionType.SubCommand)
  89. )
  90. ).AddOption(new SlashCommandOptionBuilder()
  91. .WithName("field-c")
  92. .WithDescription("Gets or sets the field C")
  93. .WithType(ApplicationCommandOptionType.SubCommandGroup)
  94. .AddOption(new SlashCommandOptionBuilder()
  95. .WithName("set")
  96. .WithDescription("Sets the field C")
  97. .WithType(ApplicationCommandOptionType.SubCommand)
  98. .AddOption("value", ApplicationCommandOptionType.Boolean, "the value to set the fie to.", isRequired: true)
  99. ).AddOption(new SlashCommandOptionBuilder()
  100. .WithName("get")
  101. .WithDescription("Gets the value of field C.")
  102. .WithType(ApplicationCommandOptionType.SubCommand)
  103. )
  104. );
  105. try
  106. {
  107. await client.Rest.CreateGuildCommand(guildCommand.Build(), guildId);
  108. }
  109. catch(ApplicationCommandException exception)
  110. {
  111. var json = JsonConvert.SerializeObject(exception.Error, Formatting.Indented);
  112. Console.WriteLine(json);
  113. }
  114. }
  115. ```
  116. All that code generates a command that looks like this:
  117. ![settings](images/settings1.png)
  118. Now that we have our command made, we need to handle the multiple options with this command. So lets add this into our handler:
  119. ```cs
  120. private async Task SlashCommandHandler(SocketSlashCommand command)
  121. {
  122. // Let's add a switch statement for the command name so we can handle multiple commands in one event.
  123. switch(command.Data.Name)
  124. {
  125. case "list-roles":
  126. await HandleListRoleCommand(command);
  127. break;
  128. case "settings":
  129. await HandleSettingsCommand(command);
  130. break;
  131. }
  132. }
  133. private async Task HandleSettingsCommand(SocketSlashCommand command)
  134. {
  135. // First lets extract our variables
  136. var fieldName = command.Data.Options.First().Name;
  137. var getOrSet = command.Data.Options.First().Options.First().Name;
  138. // Since there is no value on a get command, we use the ? operator because "Options" can be null.
  139. var value = command.Data.Options.First().Options.First().Options?.FirstOrDefault().Value;
  140. switch (fieldName)
  141. {
  142. case "field-a":
  143. {
  144. if(getOrSet == "get")
  145. {
  146. await command.RespondAsync($"The value of `field-a` is `{FieldA}`");
  147. }
  148. else if (getOrSet == "set")
  149. {
  150. this.FieldA = (string)value;
  151. await command.RespondAsync($"`field-a` has been set to `{FieldA}`");
  152. }
  153. }
  154. break;
  155. case "field-b":
  156. {
  157. if (getOrSet == "get")
  158. {
  159. await command.RespondAsync($"The value of `field-b` is `{FieldB}`");
  160. }
  161. else if (getOrSet == "set")
  162. {
  163. this.FieldB = (int)value;
  164. await command.RespondAsync($"`field-b` has been set to `{FieldB}`");
  165. }
  166. }
  167. break;
  168. case "field-c":
  169. {
  170. if (getOrSet == "get")
  171. {
  172. await command.RespondAsync($"The value of `field-c` is `{FieldC}`");
  173. }
  174. else if (getOrSet == "set")
  175. {
  176. this.FieldC = (bool)value;
  177. await command.RespondAsync($"`field-c` has been set to `{FieldC}`");
  178. }
  179. }
  180. break;
  181. }
  182. }
  183. ```
  184. Now, let's try this out! Running the 3 get commands seems to get the default values we set.
  185. ![settings get](images/settings2.png)
  186. Now let's try changing each to a different value.
  187. ![settings set](images/settings3.png)
  188. That has worked! Next, let't look at choices in commands.