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 6.8 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. # The Command Service
  2. [Discord.Commands](xref:Discord.Commands) provides an Attribute-based Command Parser.
  3. ### Setup
  4. To use Commands, you must create a [Commands Service](xref:Discord.Commands.CommandService) and a Command Handler.
  5. Included below is a very bare-bones Command Handler. You can extend your Command Handler as much as you like, however the below is the bare minimum.
  6. [!code-csharp[Barebones Command Handler](samples/command_handler.cs)]
  7. ## Commands
  8. In 1.0, Commands are no longer implemented at runtime with a builder pattern.
  9. While a builder pattern may be provided later, commands are created primarily with
  10. attributes.
  11. ### Basic Structure
  12. All commands belong to a Module. (See the below section for creating modules.)
  13. All commands in a module must be defined as an `Task`, with at least one argument,
  14. being the @Discord.IUserMessage representing the context of the command.
  15. To add parameters to your command, add additional arguments to the `Task` of the command.
  16. You are _not_ required to accept all arguments as `String`, they will be automatically parsed
  17. into the type you specify for the arument. See the Example Module for an example of command parameters.
  18. ## Modules
  19. Modules serve as a host for commands you create.
  20. To create a module, create a class that you will place commands in. Flag this class with the `[Module]` attribute. You may optionally pass in a string to the `Module` attribute to set a prefix for all of the commands inside the module.
  21. ### Example Module
  22. [!code-csharp[Modules](samples/module.cs)]
  23. #### Loading Modules Automatically
  24. The Command Service can automatically discover all classes in an Assembly that are flagged with the `Module` attribute, and load them.
  25. To have a module opt-out of auto-loading, pass `autoload: false` in the Module attribute.
  26. Invoke [CommandService.LoadAssembly](xref:Discord.Commands.CommandService#Discord_Commands_CommandService_LoadAssembly) to discover modules and install them.
  27. #### Loading Modules Manually
  28. To manually load a module, invoke [CommandService.Load](xref:Discord.Commands.CommandService#Discord_Commands_CommandService_Load), and pass in an instance of your module.
  29. ### Module Constructors
  30. When automatically loading modules, you are limited in your constructor. Using a constructor that accepts _no arguments_, or a constructor that accepts a @Discord.Commands.CommandService will always work.
  31. Alternatively, you can use an @Discord.Commands.IDependencyMap, as shown below.
  32. ### Command Groups
  33. Command groups function similarly to Modules, but they must be contained inside a module. Simply create a **public** class inside a module, and flag it with the @Discord.Commands.GroupAttribute
  34. [!code-csharp[Groups Sample](samples/groups.cs)]
  35. ## Dependency Injection
  36. The Commands Service includes a very basic implementation of Dependency Injection that allows you to have completely custom constructors, within certain limitations.
  37. ### Setup
  38. First, you need to create an @Discord.Commands.IDependencyMap . The library includes @Discord.Commands.DependencyMap to help with this, however you may create your own IDependencyMap if you wish.
  39. Next, add the dependencies your modules will use to the map.
  40. Finally, pass the map into the `LoadAssembly` method. Your modules will automatically be loaded with this dependency map.
  41. [!code-csharp[DependencyMap Setup](samples/dependency_map_setup.cs)]
  42. ### Usage in Modules
  43. In the constructor of your module, any parameters will be filled in by the @Discord.Commands.IDependencyMap you pass into `LoadAssembly`.
  44. >[!NOTE]
  45. >If you accept `CommandService` or `IDependencyMap` as a parameter in your constructor, these parameters will be filled by the CommandService the module was loaded from, and the DependencyMap passed into it, respectively.
  46. [!code-csharp[DependencyMap in Modules](samples/dependency_module.cs)]
  47. # Preconditions
  48. Preconditions serve as a permissions system for your commands. Keep in mind, however, that they are
  49. not limited to _just_ permissions, and can be as complex as you want them to be.
  50. >[!NOTE]
  51. >Preconditions can be applied to Modules, Groups, or Commands.
  52. ## Bundled Preconditions
  53. @Discord.Commands ships with two built-in preconditions, @Discord.Commands.RequireContextAttribute
  54. and @Discord.Commands.RequirePermissionAttribute.
  55. ### RequireContext
  56. @Discord.Commands.RequireContextAttribute is a precondition that requires your command to be
  57. executed in the specified context.
  58. You may require three different types of context:
  59. * Guild
  60. * DM
  61. * Group
  62. Since these are `Flags`, you may OR them together.
  63. [!code-csharp[RequireContext](samples/require_context.cs)]
  64. ### RequirePermission
  65. @Discord.Commands.RequirePermissionAttribute is a precondition that allows you to quickly
  66. specfiy that a user must poesess a permission to execute a command.
  67. You may require either a @Discord.GuildPermission or @Discord.ChannelPermission
  68. [!code-csharp[RequireContext](samples/require_permission.cs)]
  69. ## Custom Preconditions
  70. To write your own preconditions, create a new class that inherits from @Discord.Commands.PreconditionAttribute
  71. In order for your precondition to function, you will need to override `CheckPermissions`,
  72. which is a `Task<PreconditionResult>`.
  73. Your IDE should provide an option to fill this in for you.
  74. Return `PreconditionResult.FromSuccess()` if the context met the required parameters, otherwise
  75. return `PreconditionResult.FromError()`, optionally including an error message.
  76. [!code-csharp[Custom Precondition](samples/require_owner.cs)]
  77. # Type Readers
  78. Type Readers allow you to parse different types of arguments in your commands.
  79. By default, the following Types are supported arguments:
  80. - string
  81. - sbyte/byte
  82. - ushort/short
  83. - uint/int
  84. - ulong/long
  85. - float, double, decimal
  86. - DateTime/DateTimeOffset
  87. - IUser/IGuildUser
  88. - IChannel/IGuildChannel/ITextChannel/IVoiceChannel/IGroupChannel
  89. - IRole
  90. - IMessage/IUserMessage
  91. ### Creating a Type Readers
  92. To create a TypeReader, create a new class that imports @Discord and @Discord.Commands . Ensure your class inherits from @Discord.Commands.TypeReader
  93. Next, satisfy the `TypeReader` class by overriding `Task<TypeReaderResult> Read(IUserMessage context, string input)`.
  94. >[!NOTE]
  95. >In many cases, Visual Studio can fill this in for you, using the "Implement Abstract Class" IntelliSense hint.
  96. Inside this task, add whatever logic you need to parse the input string.
  97. Finally, return a `TypeReaderResult`. If you were able to successfully parse the input, return `TypeReaderResult.FromSuccess(parsedInput)`. Otherwise, return `TypeReaderResult.FromError`.
  98. #### Sample
  99. [!code-csharp[TypeReaders](samples/typereader.cs)]
  100. ### Installing TypeReaders
  101. TypeReaders are not automatically discovered by the Command Service, and must be explicitly added. To install a TypeReader, invoke [CommandService.AddTypeReader](xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddTypeReader__1_Discord_Commands_TypeReader_).