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.

commands.md 7.7 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. # The Command Service
  2. [Discord.Commands](xref:Discord.Commands) provides an Attribute-based
  3. Command Parser.
  4. ### Setup
  5. To use Commands, you must create a
  6. [Commands Service](xref:Discord.Commands.CommandService)
  7. and a Command Handler.
  8. Included below is a very bare-bones Command Handler. You can extend
  9. your Command Handler as much as you like, however the below is the
  10. bare minimum.
  11. [!code-csharp[Barebones Command Handler](samples/command_handler.cs)]
  12. ## Commands
  13. In 1.0, Commands are no longer implemented at runtime with a builder
  14. pattern. While a builder pattern may be provided later, commands are
  15. created primarily with attributes.
  16. ### Basic Structure
  17. All commands belong to a Module. (See the below section for creating
  18. modules).
  19. All commands in a module must be defined as a `Task`.
  20. To add parameters to your command, you simply need to add parameters
  21. to the Task that represents the command. You are _not_ required to
  22. accept all arguments as `String`, they will be automatically parsed
  23. into the type you specify for the arument. See the Example Module
  24. for an example of command parameters.
  25. ## Modules
  26. Modules are an organizational pattern that allow you to write your
  27. commands in different classes, and have them automatically loaded.
  28. Discord.Net's implementation of Modules is influenced heavily from
  29. ASP.Net Core's Controller pattern. This means that the lifetime of a
  30. module instance is only as long as the command being ran in it.
  31. **Avoid using long-running code** in your modules whereever possible.
  32. You should **not** be implementing very much logic into your modules;
  33. outsource to a service for that.
  34. If you are unfamiliar with Inversion of Control, it is recommended to
  35. read the MSDN article on [IoC] and [Dependency Injection].
  36. To create a module, create a class that inherits from
  37. @Discord.Commands.ModuleBase.
  38. [IoC]: https://msdn.microsoft.com/en-us/library/ff921087.aspx
  39. [Dependency Injection]: https://msdn.microsoft.com/en-us/library/ff921152.aspx
  40. ### Example Module
  41. [!code-csharp[Modules](samples/module.cs)]
  42. #### Loading Modules Automatically
  43. The Command Service can automatically discover all classes in an
  44. Assembly that inherit @Discord.Commands.ModuleBase, and load them.
  45. To have a module opt-out of auto-loading, pass `autoload: false` in
  46. the Module attribute.
  47. Invoke [CommandService.AddModules] to discover modules and install them.
  48. [CommandService.AddModules]: xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddModules
  49. #### Loading Modules Manually
  50. To manually load a module, invoke [CommandService.AddModule],
  51. by passing in the generic type of your module, and optionally
  52. a dependency map.
  53. [CommandService.AddModule]: xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddModule__1_Discord_Commands_IDependencyMap_
  54. ### Module Constructors
  55. Modules are constructed using Dependency Injection. Any parameters
  56. that are placed in the constructor must be injected into an
  57. @Discord.Commands.IDependencyMap. Alternatively, you may accept an
  58. IDependencyMap as an argument and extract services yourself.
  59. ### Command Groups
  60. Command Groups allow you to create a module where commands are prefixed.
  61. To create a group, create a new module and flag it with the
  62. @Discord.Commands.GroupAttribute.
  63. >[!NOTE]
  64. >Groups do not _need_ to be modules. Only classes with commands should
  65. >inherit from ModuleBase. If you plan on using a group for strictly
  66. >organizational purposes, there is no reason to make it a module.
  67. [!code-csharp[Groups Sample](samples/groups.cs)]
  68. ## Dependency Injection
  69. The commands service is bundled with a very barebones Dependency
  70. Injection service for your convienence. It is recommended that
  71. you use DI when writing your modules.
  72. ### Setup
  73. First, you need to create an @Discord.Commands.IDependencyMap.
  74. The library includes @Discord.Commands.DependencyMap to help with
  75. this, however you may create your own IDependencyMap if you wish.
  76. Next, add the dependencies your modules will use to the map.
  77. Finally, pass the map into the `LoadAssembly` method.
  78. Your modules will automatically be loaded with this dependency map.
  79. [!code-csharp[DependencyMap Setup](samples/dependency_map_setup.cs)]
  80. ### Usage in Modules
  81. In the constructor of your module, any parameters will be filled in by
  82. the @Discord.Commands.IDependencyMap you pass into `LoadAssembly`.
  83. >[!NOTE]
  84. >If you accept `CommandService` or `IDependencyMap` as a parameter in
  85. your constructor, these parameters will be filled by the
  86. CommandService the module was loaded from, and the DependencyMap passed
  87. into it, respectively.
  88. [!code-csharp[DependencyMap in Modules](samples/dependency_module.cs)]
  89. # Preconditions
  90. Preconditions serve as a permissions system for your commands. Keep in
  91. mind, however, that they are not limited to _just_ permissions, and
  92. can be as complex as you want them to be.
  93. >[!NOTE]
  94. >Preconditions can be applied to Modules, Groups, or Commands.
  95. ## Bundled Preconditions
  96. @Discord.Commands ships with two built-in preconditions,
  97. @Discord.Commands.RequireContextAttribute and
  98. @Discord.Commands.RequirePermissionAttribute.
  99. ### RequireContext
  100. @Discord.Commands.RequireContextAttribute is a precondition that
  101. requires your command to be executed in the specified context.
  102. You may require three different types of context:
  103. * Guild
  104. * DM
  105. * Group
  106. Since these are `Flags`, you may OR them together.
  107. [!code-csharp[RequireContext](samples/require_context.cs)]
  108. ### RequirePermission
  109. @Discord.Commands.RequirePermissionAttribute is a precondition that
  110. allows you to quickly specfiy that a user must poesess a permission
  111. to execute a command.
  112. You may require either a @Discord.GuildPermission or
  113. @Discord.ChannelPermission
  114. [!code-csharp[RequireContext](samples/require_permission.cs)]
  115. ## Custom Preconditions
  116. To write your own preconditions, create a new class that inherits from
  117. @Discord.Commands.PreconditionAttribute
  118. In order for your precondition to function, you will need to override
  119. `CheckPermissions`, which is a `Task<PreconditionResult>`.
  120. Your IDE should provide an option to fill this in for you.
  121. Return `PreconditionResult.FromSuccess()` if the context met the
  122. required parameters, otherwise return `PreconditionResult.FromError()`,
  123. optionally including an error message.
  124. [!code-csharp[Custom Precondition](samples/require_owner.cs)]
  125. # Type Readers
  126. Type Readers allow you to parse different types of arguments in
  127. your commands.
  128. By default, the following Types are supported arguments:
  129. - string
  130. - sbyte/byte
  131. - ushort/short
  132. - uint/int
  133. - ulong/long
  134. - float, double, decimal
  135. - DateTime/DateTimeOffset
  136. - IUser/IGuildUser
  137. - IChannel/IGuildChannel/ITextChannel/IVoiceChannel/IGroupChannel
  138. - IRole
  139. - IMessage/IUserMessage
  140. ### Creating a Type Readers
  141. To create a TypeReader, create a new class that imports @Discord and
  142. @Discord.Commands. Ensure your class inherits from @Discord.Commands.TypeReader
  143. Next, satisfy the `TypeReader` class by overriding `Task<TypeReaderResult> Read(CommandContext context, string input)`.
  144. >[!NOTE]
  145. >In many cases, Visual Studio can fill this in for you, using the
  146. >"Implement Abstract Class" IntelliSense hint.
  147. Inside this task, add whatever logic you need to parse the input string.
  148. Finally, return a `TypeReaderResult`. If you were able to successfully
  149. parse the input, return `TypeReaderResult.FromSuccess(parsedInput)`.
  150. Otherwise, return `TypeReaderResult.FromError`.
  151. #### Sample
  152. [!code-csharp[TypeReaders](samples/typereader.cs)]
  153. ### Installing TypeReaders
  154. TypeReaders are not automatically discovered by the Command Service,
  155. and must be explicitly added. To install a TypeReader, invoke [CommandService.AddTypeReader](xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddTypeReader__1_Discord_Commands_TypeReader_).