Improve library documentation (#826)
* Improve the Command Service documentation
The following changes have been added to this PR:
• Fix minor grammatical errors.
• Capitalize terms such as Commands, Modules and such, as the context is specific to the lib.
• Wrap methods and properties in code blocks.
The docs page currently has several issues that remains to be fixed.
1.
```md
>[!WARNING]
>This article is out of date and has not been rewritten yet.
Information is not guaranteed to be accurate.
```
The docs doesn't necessarily seem "out of date" as the warning claims. The basics seem pretty relevant to the latest version of the lib.
2.
>“To manually load a module, invoke [CommandService.AddModuleAsync], by passing in the generic type of your module and optionally, a dependency map.”
The latter part of the sentence seems off. Where should the user pass the dependency map to? It seems to suggest that `AddModuleAsync` has an argument to pass the dependency to. If it is referring to `AddModuleAsync(Type type)`, then I feel like it should be clarified here - or perhaps change the wording of the sentence.
3.
>“First, you need to create an @System.IServiceProvider You may create your own IServiceProvider if you wish.”
Any mention of @System.IServiceProvider is currently broken on the docs.
4.
>“Submodules are Modules that reside within another one. Typically, submodules are used to create nested groups (although not required to create nested groups).”
Clarification on the part after "although?"
5.
>“Finally, pass the map into the LoadAssembly method. Your modules will automatically be loaded with this dependency map.”
Where is this `LoadAssembly` method?
6.
```md
>[!NOTE]
>Preconditions can be applied to Modules, Groups, or Commands.
```
The docs should mention `ParameterPreconditionAttribute`'s existence.
* Update line breaks to comply with docs standard
* Change "you should..." to "instead, ..."
* Trim trailing spaces
* Change "inherits" to "inherit"
* Fix Context warning note and add ReplyAsync xref
* Fix broken xrefs
* Fix [Command Service] xref
* Fix consistency between TypeReaders and Preconditions returns
* Add missing semi-colons in ServiceProvider sample
* Change CommandContext to SocketCommandContext & change variable naming
* Cleanup TypeReader section
* Wrap [DontInject] in code block
* Fix commands docs linking in intro
* Improve Getting Started - Installation
- Fix character misalignment to comply with docs standard.
- Fix image numbering issues by moving the tooltips above some of the steps.
- Add codeblocks to search terms like `Discord.Net`.
- Remove broken `addons` reference.
- Specify `.NET 4.6.1` as `.NET Framework 4.6.1`.
- Minor cross-reference cleanup.
* Fix Getting Started - Intro
- Minor grammartical fixes.
- Wrap mentions of the methods, properties, and events in code block.
- Replace `Discord.Net` to `Discord.NET`.
- Fix steps numbering under `Creating a Discord Bot` and `Adding your bot to a server`.
- Change `Task-based Asynchronous Pattern ([TAP])` linking to mark the entire term instead.
- Change code block of `Pong!` to quotation mark instead.
* Fix cross references in Sending Voice
* Mention parameter precondition attribute
* Change `Discord.NET` to `Discord.Net` for consistency
* Wrap project names in code blocks & minor fixes in Terminology
* Change `add-ons` to `addons` for consistency
* Fix cross references in Logging
* Fix minor grammatical issues in "Working with Events"
* Missed a tilda
* Remove out-of-date warning in Commands
* Minor grammatical fixes for Entities
* Fix broken xref in Logging
* Adjust service collection sample
...according to f89aecb7bf (r141530227)
* Update Command Handler sample
- Update Main for C# 7.1.
- Inject CommandService and DiscordSocketClient into the service collection.
- Add Async suffix to asynchronous methods.
* Minor grammatical fixes in Events
* Revert 2 incorrect grammar corrections
* Revert async Main sample
* Add hardcode token notice in sample
* Fix missing method for Command Handler
* Modify module samples to use SocketCommandContext instead
* Emphasize CommandContext and SocketCommandContext
* Fix formatting for module sample
* Add SocketCommandContext for Groups sample
* Remove comma
* Fix DepMap sample formatting
* Replace [DontInject] with DontInjectAttribute with cross reference
* Remove connection logic note
There is no reason that this note should still be here since Ready event exists.
* Add a new warning message informing the users the existence of CommandService
* Make command handler private
excellent change
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26228.4
|
VisualStudioVersion = 15.0.26730.12
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Core", "src\Discord.Net.Core\Discord.Net.Core.csproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Core", "src\Discord.Net.Core\Discord.Net.Core.csproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -142,4 +142,10 @@ Global
|
|||||||
{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7} = {B0657AAE-DCC5-4FBF-8E5D-1FB578CF3012}
|
{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7} = {B0657AAE-DCC5-4FBF-8E5D-1FB578CF3012}
|
||||||
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}
|
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {D2404771-EEC8-45F2-9D71-F3373F6C1495}
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(CodealikeProperties) = postSolution
|
||||||
|
SolutionGuid = a45217b4-a401-4dbf-8654-34d2ec034cd9
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@@ -1,24 +1,20 @@
|
|||||||
# The Command Service
|
# The Command Service
|
||||||
|
|
||||||
>[!WARNING]
|
|
||||||
>This article is out of date, and has not been rewritten yet.
|
|
||||||
Information is not guaranteed to be accurate.
|
|
||||||
|
|
||||||
[Discord.Commands](xref:Discord.Commands) provides an Attribute-based
|
[Discord.Commands](xref:Discord.Commands) provides an Attribute-based
|
||||||
Command Parser.
|
command parser.
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
To use Commands, you must create a [Commands Service] and a
|
To use Commands, you must create a [Command Service] and a Command
|
||||||
Command Handler.
|
Handler.
|
||||||
|
|
||||||
Included below is a very bare-bones Command Handler. You can extend
|
Included below is a very barebone Command Handler. You can extend your
|
||||||
your Command Handler as much as you like, however the below is the
|
Command Handler as much as you like; however, the below is the bare
|
||||||
bare minimum.
|
minimum.
|
||||||
|
|
||||||
The CommandService optionally will accept a [CommandServiceConfig],
|
The `CommandService` will optionally accept a [CommandServiceConfig],
|
||||||
which _does_ set a few default values for you. It is recommended to
|
which _does_ set a few default values for you. It is recommended to
|
||||||
look over the properties in [CommandServiceConfig], and their default
|
look over the properties in [CommandServiceConfig] and their default
|
||||||
values.
|
values.
|
||||||
|
|
||||||
[!code-csharp[Command Handler](samples/command_handler.cs)]
|
[!code-csharp[Command Handler](samples/command_handler.cs)]
|
||||||
@@ -28,32 +24,32 @@ values.
|
|||||||
|
|
||||||
## With Attributes
|
## With Attributes
|
||||||
|
|
||||||
In 1.0, Commands can be defined ahead of time, with attributes, or
|
In 1.0, Commands can be defined ahead of time with attributes, or at
|
||||||
at runtime, with builders.
|
runtime with builders.
|
||||||
|
|
||||||
For most bots, ahead-of-time commands should be all you need, and this
|
For most bots, ahead-of-time Commands should be all you need, and this
|
||||||
is the recommended method of defining commands.
|
is the recommended method of defining Commands.
|
||||||
|
|
||||||
### Modules
|
### Modules
|
||||||
|
|
||||||
The first step to creating commands is to create a _module_.
|
The first step to creating Commands is to create a _module_.
|
||||||
|
|
||||||
Modules are an organizational pattern that allow you to write your
|
A Module is an organizational pattern that allows you to write your
|
||||||
commands in different classes, and have them automatically loaded.
|
Commands in different classes and have them automatically loaded.
|
||||||
|
|
||||||
Discord.Net's implementation of Modules is influenced heavily from
|
Discord.Net's implementation of Modules is influenced heavily from
|
||||||
ASP.Net Core's Controller pattern. This means that the lifetime of a
|
ASP.NET Core's Controller pattern. This means that the lifetime of a
|
||||||
module instance is only as long as the command being invoked.
|
module instance is only as long as the Command is being invoked.
|
||||||
|
|
||||||
**Avoid using long-running code** in your modules wherever possible.
|
**Avoid using long-running code** in your modules wherever possible.
|
||||||
You should **not** be implementing very much logic into your modules;
|
You should **not** be implementing very much logic into your modules,
|
||||||
outsource to a service for that.
|
instead, outsource to a service for that.
|
||||||
|
|
||||||
If you are unfamiliar with Inversion of Control, it is recommended to
|
If you are unfamiliar with Inversion of Control, it is recommended to
|
||||||
read the MSDN article on [IoC] and [Dependency Injection].
|
read the MSDN article on [IoC] and [Dependency Injection].
|
||||||
|
|
||||||
To begin, create a new class somewhere in your project, and
|
To begin, create a new class somewhere in your project and inherit the
|
||||||
inherit the class from [ModuleBase]. This class **must** be `public`.
|
class from [ModuleBase]. This class **must** be `public`.
|
||||||
|
|
||||||
>[!NOTE]
|
>[!NOTE]
|
||||||
>[ModuleBase] is an _abstract_ class, meaning that you may extend it
|
>[ModuleBase] is an _abstract_ class, meaning that you may extend it
|
||||||
@@ -61,6 +57,7 @@ inherit the class from [ModuleBase]. This class **must** be `public`.
|
|||||||
>extension of ModuleBase.
|
>extension of ModuleBase.
|
||||||
|
|
||||||
By now, your module should look like this:
|
By now, your module should look like this:
|
||||||
|
|
||||||
[!code-csharp[Empty Module](samples/empty-module.cs)]
|
[!code-csharp[Empty Module](samples/empty-module.cs)]
|
||||||
|
|
||||||
[IoC]: https://msdn.microsoft.com/en-us/library/ff921087.aspx
|
[IoC]: https://msdn.microsoft.com/en-us/library/ff921087.aspx
|
||||||
@@ -69,72 +66,75 @@ By now, your module should look like this:
|
|||||||
|
|
||||||
### Adding Commands
|
### Adding Commands
|
||||||
|
|
||||||
The next step to creating commands, is actually creating commands.
|
The next step to creating Commands is actually creating the Commands.
|
||||||
|
|
||||||
To create a command, add a method to your module of type `Task`.
|
To create a Command, add a method to your module of type `Task`.
|
||||||
Typically, you will want to mark this method as `async`, although it is
|
Typically, you will want to mark this method as `async`, although it
|
||||||
not required.
|
is not required.
|
||||||
|
|
||||||
Adding parameters to a command is done by adding parameters to the
|
Adding parameters to a Command is done by adding parameters to the
|
||||||
parent Task.
|
parent Task.
|
||||||
|
|
||||||
For example, to take an integer as an argument, add `int arg`. To take
|
For example, to take an integer as an argument from the user, add `int
|
||||||
a user as an argument, add `IUser user`. In 1.0, a command can accept
|
arg`; to take a user as an argument from the user, add `IUser user`.
|
||||||
nearly any type of argument; a full list of types that are parsed by
|
In 1.0, a Command can accept nearly any type of argument; a full list
|
||||||
default can be found in the below section on _Type Readers_.
|
of types that are parsed by default can be found in the below section
|
||||||
|
on _Type Readers_.
|
||||||
|
|
||||||
Parameters, by default, are always required. To make a parameter
|
Parameters, by default, are always required. To make a parameter
|
||||||
optional, give it a default value. To accept a comma-separated list,
|
optional, give it a default value. To accept a comma-separated list,
|
||||||
set the parameter to `params Type[]`.
|
set the parameter to `params Type[]`.
|
||||||
|
|
||||||
Should a parameter include spaces, it **must** be wrapped in quotes.
|
Should a parameter include spaces, it **must** be wrapped in quotes.
|
||||||
For example, for a command with a parameter `string food`, you would
|
For example, for a Command with a parameter `string food`, you would
|
||||||
execute it with `!favoritefood "Key Lime Pie"`.
|
execute it with `!favoritefood "Key Lime Pie"`.
|
||||||
|
|
||||||
If you would like a parameter to parse until the end of a command,
|
If you would like a parameter to parse until the end of a Command,
|
||||||
flag the parameter with the [RemainderAttribute]. This will allow a
|
flag the parameter with the [RemainderAttribute]. This will allow a
|
||||||
user to invoke a command without wrapping a parameter in quotes.
|
user to invoke a Command without wrapping a parameter in quotes.
|
||||||
|
|
||||||
Finally, flag your command with the [CommandAttribute]. (You must
|
Finally, flag your Command with the [CommandAttribute] (you must
|
||||||
specify a name for this command, except for when it is part of a
|
specify a name for this Command, except for when it is part of a
|
||||||
module group - see below).
|
Module Group - see below).
|
||||||
|
|
||||||
[RemainderAttribute]: xref:Discord.Commands.RemainderAttribute
|
[RemainderAttribute]: xref:Discord.Commands.RemainderAttribute
|
||||||
[CommandAttribute]: xref:Discord.Commands.CommandAttribute
|
[CommandAttribute]: xref:Discord.Commands.CommandAttribute
|
||||||
|
|
||||||
### Command Overloads
|
### Command Overloads
|
||||||
|
|
||||||
You may add overloads of your commands, and the command parser will
|
You may add overloads to your Commands, and the Command parser will
|
||||||
automatically pick up on it.
|
automatically pick up on it.
|
||||||
|
|
||||||
If, for whatever reason, you have too commands which are ambiguous to
|
If for whatever reason, you have two Commands which are ambiguous to
|
||||||
each other, you may use the @Discord.Commands.PriorityAttribute to
|
each other, you may use the @Discord.Commands.PriorityAttribute to
|
||||||
specify which should be tested before the other.
|
specify which should be tested before the other.
|
||||||
|
|
||||||
Priority's are sorted in ascending order; the higher priority will be
|
The `Priority` attributes are sorted in ascending order; the higher
|
||||||
called first.
|
priority will be called first.
|
||||||
|
|
||||||
### CommandContext
|
### Command Context
|
||||||
|
|
||||||
Every command can access the execution context through the [Context]
|
Every Command can access the execution context through the [Context]
|
||||||
property on [ModuleBase]. CommandContext allows you to access the
|
property on [ModuleBase]. `ICommandContext` allows you to access the
|
||||||
message, channel, guild, and user that the command was invoked from,
|
message, channel, guild, and user that the Command was invoked from,
|
||||||
as well as the underlying discord client the command was invoked from.
|
as well as the underlying Discord client that the Command was invoked
|
||||||
|
from.
|
||||||
|
|
||||||
Different types of Contexts may be specified using the generic variant
|
Different types of Contexts may be specified using the generic variant
|
||||||
of [ModuleBase]. When using a [SocketCommandContext], for example,
|
of [ModuleBase]. When using a [SocketCommandContext], for example, the
|
||||||
the properties on this context will already be Socket entities. You
|
properties on this context will already be Socket entities, so you
|
||||||
will not need to cast them.
|
will not need to cast them.
|
||||||
|
|
||||||
To reply to messages, you may also invoke [ReplyAsync], instead of
|
To reply to messages, you may also invoke [ReplyAsync], instead of
|
||||||
accessing the channel through the [Context] and sending a message.
|
accessing the channel through the [Context] and sending a message.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
>Contexts should **NOT** be mixed! You cannot have one module that
|
||||||
|
>uses `CommandContext` and another that uses `SocketCommandContext`.
|
||||||
|
|
||||||
[Context]: xref:Discord.Commands.ModuleBase`1#Discord_Commands_ModuleBase_1_Context
|
[Context]: xref:Discord.Commands.ModuleBase`1#Discord_Commands_ModuleBase_1_Context
|
||||||
[SocketCommandContext]: xref:Discord.Commands.SocketCommandContext
|
[SocketCommandContext]: xref:Discord.Commands.SocketCommandContext
|
||||||
|
[ReplyAsync]: xref:Discord.Commands.ModuleBase`1#Discord_Commands_ModuleBase_1_ReplyAsync_System_String_System_Boolean_Discord_Embed_Discord_RequestOptions_
|
||||||
>![WARNING]
|
|
||||||
>Contexts should **NOT** be mixed! You cannot have one module that
|
|
||||||
>uses CommandContext, and another that uses SocketCommandContext.
|
|
||||||
|
|
||||||
### Example Module
|
### Example Module
|
||||||
|
|
||||||
@@ -144,50 +144,50 @@ At this point, your module should look comparable to this example:
|
|||||||
#### Loading Modules Automatically
|
#### Loading Modules Automatically
|
||||||
|
|
||||||
The Command Service can automatically discover all classes in an
|
The Command Service can automatically discover all classes in an
|
||||||
Assembly that inherit [ModuleBase], and load them.
|
Assembly that inherit [ModuleBase] and load them.
|
||||||
|
|
||||||
To opt a module out of auto-loading, flag it with
|
To opt a module out of auto-loading, flag it with
|
||||||
[DontAutoLoadAttribute]
|
[DontAutoLoadAttribute].
|
||||||
|
|
||||||
Invoke [CommandService.AddModulesAsync] to discover modules and
|
Invoke [CommandService.AddModulesAsync] to discover modules and
|
||||||
install them.
|
install them.
|
||||||
|
|
||||||
[DontAutoLoadAttribute]: xref:Discord.Commands.DontAutoLoadAttribute
|
[DontAutoLoadAttribute]: xref:Discord.Commands.DontAutoLoadAttribute
|
||||||
[CommandService.AddModulesAsync]: xref:Discord_Commands_CommandService#Discord_Commands_CommandService_AddModulesAsync_Assembly_
|
[CommandService.AddModulesAsync]: xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddModulesAsync_Assembly_
|
||||||
|
|
||||||
#### Loading Modules Manually
|
#### Loading Modules Manually
|
||||||
|
|
||||||
To manually load a module, invoke [CommandService.AddModuleAsync],
|
To manually load a module, invoke [CommandService.AddModuleAsync] by
|
||||||
by passing in the generic type of your module, and optionally
|
passing in the generic type of your module and optionally, a
|
||||||
a dependency map.
|
dependency map.
|
||||||
|
|
||||||
[CommandService.AddModuleAsync]: xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddModuleAsync__1
|
[CommandService.AddModuleAsync]: xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddModuleAsync__1
|
||||||
|
|
||||||
### Module Constructors
|
### Module Constructors
|
||||||
|
|
||||||
Modules are constructed using Dependency Injection. Any parameters
|
Modules are constructed using Dependency Injection. Any parameters
|
||||||
that are placed in the constructor must be injected into an
|
that are placed in the Module's constructor must be injected into an
|
||||||
@System.IServiceProvider. Alternatively, you may accept an
|
@System.IServiceProvider first. Alternatively, you may accept an
|
||||||
IServiceProvider as an argument and extract services yourself.
|
`IServiceProvider` as an argument and extract services yourself.
|
||||||
|
|
||||||
### Module Properties
|
### Module Properties
|
||||||
|
|
||||||
Modules with public settable properties will have them injected after module
|
Modules with `public` settable properties will have the dependencies
|
||||||
construction.
|
injected after the construction of the Module.
|
||||||
|
|
||||||
### Module Groups
|
### Module Groups
|
||||||
|
|
||||||
Module Groups allow you to create a module where commands are prefixed.
|
Module Groups allow you to create a module where Commands are
|
||||||
To create a group, flag a module with the
|
prefixed. To create a group, flag a module with the
|
||||||
@Discord.Commands.GroupAttribute
|
@Discord.Commands.GroupAttribute.
|
||||||
|
|
||||||
Module groups also allow you to create **nameless commands**, where the
|
Module groups also allow you to create **nameless Commands**, where
|
||||||
[CommandAttribute] is configured with no name. In this case, the
|
the [CommandAttribute] is configured with no name. In this case, the
|
||||||
command will inherit the name of the group it belongs to.
|
Command will inherit the name of the group it belongs to.
|
||||||
|
|
||||||
### Submodules
|
### Submodules
|
||||||
|
|
||||||
Submodules are modules that reside within another module. Typically,
|
Submodules are Modules that reside within another one. Typically,
|
||||||
submodules are used to create nested groups (although not required to
|
submodules are used to create nested groups (although not required to
|
||||||
create nested groups).
|
create nested groups).
|
||||||
|
|
||||||
@@ -199,54 +199,62 @@ create nested groups).
|
|||||||
|
|
||||||
## Dependency Injection
|
## Dependency Injection
|
||||||
|
|
||||||
The commands service is bundled with a very barebones Dependency
|
The Command Service is bundled with a very barebone Dependency
|
||||||
Injection service for your convienence. It is recommended that
|
Injection service for your convenience. It is recommended that you use
|
||||||
you use DI when writing your modules.
|
DI when writing your modules.
|
||||||
|
|
||||||
### Setup
|
### Setup
|
||||||
|
|
||||||
First, you need to create an @System.IServiceProvider
|
First, you need to create an @System.IServiceProvider; you may create
|
||||||
You may create your own IServiceProvider if you wish.
|
your own one if you wish.
|
||||||
|
|
||||||
Next, add the dependencies your modules will use to the map.
|
Next, add the dependencies that your modules will use to the map.
|
||||||
|
|
||||||
Finally, pass the map into the `LoadAssembly` method.
|
Finally, pass the map into the `LoadAssembly` method. Your modules
|
||||||
Your modules will automatically be loaded with this dependency map.
|
will be automatically loaded with this dependency map.
|
||||||
|
|
||||||
[!code-csharp[IServiceProvider Setup](samples/dependency_map_setup.cs)]
|
[!code-csharp[IServiceProvider Setup](samples/dependency_map_setup.cs)]
|
||||||
|
|
||||||
### Usage in Modules
|
### Usage in Modules
|
||||||
|
|
||||||
In the constructor of your module, any parameters will be filled in by
|
In the constructor of your Module, any parameters will be filled in by
|
||||||
the @System.IServiceProvider you pass into `LoadAssembly`.
|
the @System.IServiceProvider that you've passed into `LoadAssembly`.
|
||||||
|
|
||||||
Any publicly settable properties will also be filled in the same manner.
|
Any publicly settable properties will also be filled in the same
|
||||||
|
manner.
|
||||||
|
|
||||||
>[!NOTE]
|
>[!NOTE]
|
||||||
> Annotating a property with the [DontInject] attribute will prevent it from
|
> Annotating a property with a [DontInjectAttribute] attribute will prevent the
|
||||||
being injected.
|
property from being injected.
|
||||||
|
|
||||||
>[!NOTE]
|
>[!NOTE]
|
||||||
>If you accept `CommandService` or `IServiceProvider` as a parameter in
|
>If you accept `CommandService` or `IServiceProvider` as a parameter
|
||||||
your constructor or as an injectable property, these entries will be filled
|
in your constructor or as an injectable property, these entries will
|
||||||
by the CommandService the module was loaded from, and the ServiceProvider passed
|
be filled by the `CommandService` that the Module is loaded from and
|
||||||
into it, respectively.
|
the `ServiceProvider` that is passed into it respectively.
|
||||||
|
|
||||||
[!code-csharp[ServiceProvider in Modules](samples/dependency_module.cs)]
|
[!code-csharp[ServiceProvider in Modules](samples/dependency_module.cs)]
|
||||||
|
|
||||||
|
[DontInjectAttribute]: xref:Discord.Commands.DontInjectAttribute
|
||||||
|
|
||||||
# Preconditions
|
# Preconditions
|
||||||
|
|
||||||
Preconditions serve as a permissions system for your commands. Keep in
|
Precondition serve as a permissions system for your Commands. Keep in
|
||||||
mind, however, that they are not limited to _just_ permissions, and
|
mind, however, that they are not limited to _just_ permissions and can
|
||||||
can be as complex as you want them to be.
|
be as complex as you want them to be.
|
||||||
|
|
||||||
>[!NOTE]
|
>[!NOTE]
|
||||||
>Preconditions can be applied to Modules, Groups, or Commands.
|
>There are two types of Preconditions.
|
||||||
|
[PreconditionAttribute] can be applied to Modules, Groups, or Commands;
|
||||||
|
[ParameterPreconditionAttribute] can be applied to Parameters.
|
||||||
|
|
||||||
|
[PreconditionAttribute]: xref:Discord.Commands.PreconditionAttribute
|
||||||
|
[ParameterPreconditionAttribute]: xref:Discord.Commands.ParameterPreconditionAttribute
|
||||||
|
|
||||||
## Bundled Preconditions
|
## Bundled Preconditions
|
||||||
|
|
||||||
Commands ships with four bundled preconditions; you may view their
|
Commands ship with four bundled Preconditions; you may view their
|
||||||
usages on their API page.
|
usages on their respective API pages.
|
||||||
|
|
||||||
- @Discord.Commands.RequireContextAttribute
|
- @Discord.Commands.RequireContextAttribute
|
||||||
- @Discord.Commands.RequireOwnerAttribute
|
- @Discord.Commands.RequireOwnerAttribute
|
||||||
@@ -255,21 +263,23 @@ usages on their API page.
|
|||||||
|
|
||||||
## Custom Preconditions
|
## Custom Preconditions
|
||||||
|
|
||||||
To write your own preconditions, create a new class that inherits from
|
To write your own Precondition, create a new class that inherits from
|
||||||
@Discord.Commands.PreconditionAttribute
|
either [PreconditionAttribute] or [ParameterPreconditionAttribute]
|
||||||
|
depending on your use.
|
||||||
|
|
||||||
In order for your precondition to function, you will need to override
|
In order for your Precondition to function, you will need to override
|
||||||
[CheckPermissions].
|
the [CheckPermissions] method.
|
||||||
|
|
||||||
Your IDE should provide an option to fill this in for you.
|
Your IDE should provide an option to fill this in for you.
|
||||||
|
|
||||||
Return [PreconditionResult.FromSuccess] if the context met the
|
If the context meets the required parameters, return
|
||||||
required parameters, otherwise return [PreconditionResult.FromError],
|
[PreconditionResult.FromSuccess], otherwise return
|
||||||
optionally including an error message.
|
[PreconditionResult.FromError] and include an error message if
|
||||||
|
necessary.
|
||||||
|
|
||||||
[!code-csharp[Custom Precondition](samples/require_owner.cs)]
|
[!code-csharp[Custom Precondition](samples/require_owner.cs)]
|
||||||
|
|
||||||
[CheckPermissions]: xref:Discord.Commands.PreconditionAttribute#Discord_Commands_PreconditionAttribute_CheckPermissions_Discord_Commands_CommandContext_Discord_Commands_CommandInfo_Discord_Commands_IDependencyMap_
|
[CheckPermissions]: xref:Discord.Commands.PreconditionAttribute#Discord_Commands_PreconditionAttribute_CheckPermissions_Discord_Commands_ICommandContext_Discord_Commands_CommandInfo_IServiceProvider_
|
||||||
[PreconditionResult.FromSuccess]: xref:Discord.Commands.PreconditionResult#Discord_Commands_PreconditionResult_FromSuccess
|
[PreconditionResult.FromSuccess]: xref:Discord.Commands.PreconditionResult#Discord_Commands_PreconditionResult_FromSuccess
|
||||||
[PreconditionResult.FromError]: xref:Discord.Commands.PreconditionResult#Discord_Commands_PreconditionResult_FromError_System_String_
|
[PreconditionResult.FromError]: xref:Discord.Commands.PreconditionResult#Discord_Commands_PreconditionResult_FromError_System_String_
|
||||||
|
|
||||||
@@ -296,22 +306,28 @@ By default, the following Types are supported arguments:
|
|||||||
|
|
||||||
### Creating a Type Readers
|
### Creating a Type Readers
|
||||||
|
|
||||||
To create a TypeReader, create a new class that imports @Discord and
|
To create a `TypeReader`, create a new class that imports @Discord and
|
||||||
@Discord.Commands. Ensure your class inherits from @Discord.Commands.TypeReader
|
@Discord.Commands and ensure the class inherits from
|
||||||
|
@Discord.Commands.TypeReader.
|
||||||
|
|
||||||
Next, satisfy the `TypeReader` class by overriding [Read].
|
Next, satisfy the `TypeReader` class by overriding the [Read] method.
|
||||||
|
|
||||||
>[!NOTE]
|
>[!NOTE]
|
||||||
>In many cases, Visual Studio can fill this in for you, using the
|
>In many cases, Visual Studio can fill this in for you, using the
|
||||||
>"Implement Abstract Class" IntelliSense hint.
|
>"Implement Abstract Class" IntelliSense hint.
|
||||||
|
|
||||||
Inside this task, add whatever logic you need to parse the input string.
|
Inside this task, add whatever logic you need to parse the input
|
||||||
|
string.
|
||||||
|
|
||||||
Finally, return a `TypeReaderResult`. If you were able to successfully
|
If you are able to successfully parse the input, return
|
||||||
parse the input, return `TypeReaderResult.FromSuccess(parsedInput)`.
|
[TypeReaderResult.FromSuccess] with the parsed input, otherwise return
|
||||||
Otherwise, return `TypeReaderResult.FromError`.
|
[TypeReaderResult.FromError] and include an error message if
|
||||||
|
necessary.
|
||||||
|
|
||||||
[Read]: xref:Discord.Commands.TypeReader#Discord_Commands_TypeReader_Read_Discord_Commands_CommandContext_System_String_
|
[TypeReaderResult]: xref:Discord.Commands.TypeReaderResult
|
||||||
|
[TypeReaderResult.FromSuccess]: xref:Discord.Commands.TypeReaderResult#Discord_Commands_TypeReaderResult_FromSuccess_Discord_Commands_TypeReaderValue_
|
||||||
|
[TypeReaderResult.FromError]: xref:Discord.Commands.TypeReaderResult#Discord_Commands_TypeReaderResult_FromError_Discord_Commands_CommandError_System_String_
|
||||||
|
[Read]: xref:Discord.Commands.TypeReader#Discord_Commands_TypeReader_Read_Discord_Commands_ICommandContext_System_String_IServiceProvider_
|
||||||
|
|
||||||
#### Sample
|
#### Sample
|
||||||
|
|
||||||
@@ -319,5 +335,9 @@ Otherwise, return `TypeReaderResult.FromError`.
|
|||||||
|
|
||||||
### Installing TypeReaders
|
### Installing TypeReaders
|
||||||
|
|
||||||
TypeReaders are not automatically discovered by the Command Service,
|
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_).
|
and must be explicitly added.
|
||||||
|
|
||||||
|
To install a TypeReader, invoke [CommandService.AddTypeReader].
|
||||||
|
|
||||||
|
[CommandService.AddTypeReader]: xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddTypeReader__1_Discord_Commands_TypeReader_
|
||||||
@@ -8,39 +8,42 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
|
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
private CommandService commands;
|
private CommandService _commands;
|
||||||
private DiscordSocketClient client;
|
private DiscordSocketClient _client;
|
||||||
private IServiceProvider services;
|
private IServiceProvider _services;
|
||||||
|
|
||||||
static void Main(string[] args) => new Program().Start().GetAwaiter().GetResult();
|
private static void Main(string[] args) => new Program().StartAsync().GetAwaiter().GetResult();
|
||||||
|
|
||||||
public async Task Start()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
client = new DiscordSocketClient();
|
_client = new DiscordSocketClient();
|
||||||
commands = new CommandService();
|
_commands = new CommandService();
|
||||||
|
|
||||||
|
// Avoid hard coding your token. Use an external source instead in your code.
|
||||||
string token = "bot token here";
|
string token = "bot token here";
|
||||||
|
|
||||||
services = new ServiceCollection()
|
_services = new ServiceCollection()
|
||||||
.BuildServiceProvider();
|
.AddSingleton(_client)
|
||||||
|
.AddSingleton(_commands)
|
||||||
|
.BuildServiceProvider();
|
||||||
|
|
||||||
await InstallCommands();
|
await InstallCommandsAsync();
|
||||||
|
|
||||||
await client.LoginAsync(TokenType.Bot, token);
|
await _client.LoginAsync(TokenType.Bot, token);
|
||||||
await client.StartAsync();
|
await _client.StartAsync();
|
||||||
|
|
||||||
await Task.Delay(-1);
|
await Task.Delay(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InstallCommands()
|
public async Task InstallCommandsAsync()
|
||||||
{
|
{
|
||||||
// Hook the MessageReceived Event into our Command Handler
|
// Hook the MessageReceived Event into our Command Handler
|
||||||
client.MessageReceived += HandleCommand;
|
_client.MessageReceived += HandleCommandAsync;
|
||||||
// Discover all of the commands in this assembly and load them.
|
// Discover all of the commands in this assembly and load them.
|
||||||
await commands.AddModulesAsync(Assembly.GetEntryAssembly());
|
await _commands.AddModulesAsync(Assembly.GetEntryAssembly());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task HandleCommand(SocketMessage messageParam)
|
private async Task HandleCommandAsync(SocketMessage messageParam)
|
||||||
{
|
{
|
||||||
// Don't process the command if it was a System Message
|
// Don't process the command if it was a System Message
|
||||||
var message = messageParam as SocketUserMessage;
|
var message = messageParam as SocketUserMessage;
|
||||||
@@ -48,13 +51,13 @@ public class Program
|
|||||||
// Create a number to track where the prefix ends and the command begins
|
// Create a number to track where the prefix ends and the command begins
|
||||||
int argPos = 0;
|
int argPos = 0;
|
||||||
// Determine if the message is a command, based on if it starts with '!' or a mention prefix
|
// Determine if the message is a command, based on if it starts with '!' or a mention prefix
|
||||||
if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))) return;
|
if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return;
|
||||||
// Create a Command Context
|
// Create a Command Context
|
||||||
var context = new CommandContext(client, message);
|
var context = new SocketCommandContext(_client, message);
|
||||||
// Execute the command. (result does not indicate a return value,
|
// Execute the command. (result does not indicate a return value,
|
||||||
// rather an object stating if the command executed successfully)
|
// rather an object stating if the command executed successfully)
|
||||||
var result = await commands.ExecuteAsync(context, argPos, service);
|
var result = await _commands.ExecuteAsync(context, argPos, _services);
|
||||||
if (!result.IsSuccess)
|
if (!result.IsSuccess)
|
||||||
await context.Channel.SendMessageAsync(result.ErrorReason);
|
await context.Channel.SendMessageAsync(result.ErrorReason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
using Discord;
|
private IServiceProvider _services;
|
||||||
using Discord.Commands;
|
private CommandService _commands;
|
||||||
using Discord.WebSocket;
|
|
||||||
using foxboat.Services;
|
|
||||||
|
|
||||||
public class Commands
|
public async Task InstallAsync(DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
public async Task Install(DiscordSocketClient client)
|
// Here, we will inject the ServiceProvider with
|
||||||
{
|
// all of the services our client will use.
|
||||||
// Here, we will inject the ServiceProvider with
|
_services = new ServiceCollection()
|
||||||
// all of the services our client will use.
|
.AddSingleton(client)
|
||||||
_serviceCollection.AddSingleton(client)
|
.AddSingleton(_commands)
|
||||||
_serviceCollection.AddSingleton(new NotificationService())
|
// You can pass in an instance of the desired type
|
||||||
_serviceCollection.AddSingleton(new DatabaseService())
|
.AddSingleton(new NotificationService())
|
||||||
// ...
|
// ...or by using the generic method.
|
||||||
await _commands.AddModulesAsync(Assembly.GetEntryAssembly());
|
.AddSingleton<DatabaseService>()
|
||||||
}
|
.BuildServiceProvider();
|
||||||
}
|
// ...
|
||||||
|
await _commands.AddModulesAsync(Assembly.GetEntryAssembly());
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
|
||||||
public class InfoModule : ModuleBase
|
public class InfoModule : ModuleBase<SocketCommandContext>
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
[Group("admin")]
|
[Group("admin")]
|
||||||
public class AdminModule : ModuleBase
|
public class AdminModule : ModuleBase<SocketCommandContext>
|
||||||
{
|
{
|
||||||
[Group("clean")]
|
[Group("clean")]
|
||||||
public class CleanModule : ModuleBase
|
public class CleanModule : ModuleBase<SocketCommandContext>
|
||||||
{
|
{
|
||||||
// ~admin clean 15
|
// ~admin clean 15
|
||||||
[Command]
|
[Command]
|
||||||
|
|||||||
@@ -1,42 +1,41 @@
|
|||||||
using Discord;
|
|
||||||
using Discord.Commands;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
|
|
||||||
// Create a module with no prefix
|
// Create a module with no prefix
|
||||||
public class Info : ModuleBase
|
public class Info : ModuleBase<SocketCommandContext>
|
||||||
{
|
{
|
||||||
// ~say hello -> hello
|
// ~say hello -> hello
|
||||||
[Command("say"), Summary("Echos a message.")]
|
[Command("say")]
|
||||||
public async Task Say([Remainder, Summary("The text to echo")] string echo)
|
[Summary("Echos a message.")]
|
||||||
{
|
public async Task SayAsync([Remainder] [Summary("The text to echo")] string echo)
|
||||||
// ReplyAsync is a method on ModuleBase
|
{
|
||||||
await ReplyAsync(echo);
|
// ReplyAsync is a method on ModuleBase
|
||||||
}
|
await ReplyAsync(echo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a module with the 'sample' prefix
|
// Create a module with the 'sample' prefix
|
||||||
[Group("sample")]
|
[Group("sample")]
|
||||||
public class Sample : ModuleBase
|
public class Sample : ModuleBase<SocketCommandContext>
|
||||||
{
|
{
|
||||||
// ~sample square 20 -> 400
|
// ~sample square 20 -> 400
|
||||||
[Command("square"), Summary("Squares a number.")]
|
[Command("square")]
|
||||||
public async Task Square([Summary("The number to square.")] int num)
|
[Summary("Squares a number.")]
|
||||||
{
|
public async Task SquareAsync([Summary("The number to square.")] int num)
|
||||||
// We can also access the channel from the Command Context.
|
{
|
||||||
await Context.Channel.SendMessageAsync($"{num}^2 = {Math.Pow(num, 2)}");
|
// We can also access the channel from the Command Context.
|
||||||
}
|
await Context.Channel.SendMessageAsync($"{num}^2 = {Math.Pow(num, 2)}");
|
||||||
|
}
|
||||||
|
|
||||||
// ~sample userinfo --> foxbot#0282
|
// ~sample userinfo --> foxbot#0282
|
||||||
// ~sample userinfo @Khionu --> Khionu#8708
|
// ~sample userinfo @Khionu --> Khionu#8708
|
||||||
// ~sample userinfo Khionu#8708 --> Khionu#8708
|
// ~sample userinfo Khionu#8708 --> Khionu#8708
|
||||||
// ~sample userinfo Khionu --> Khionu#8708
|
// ~sample userinfo Khionu --> Khionu#8708
|
||||||
// ~sample userinfo 96642168176807936 --> Khionu#8708
|
// ~sample userinfo 96642168176807936 --> Khionu#8708
|
||||||
// ~sample whois 96642168176807936 --> Khionu#8708
|
// ~sample whois 96642168176807936 --> Khionu#8708
|
||||||
[Command("userinfo"), Summary("Returns info about the current user, or the user parameter, if one passed.")]
|
[Command("userinfo")]
|
||||||
[Alias("user", "whois")]
|
[Summary("Returns info about the current user, or the user parameter, if one passed.")]
|
||||||
public async Task UserInfo([Summary("The (optional) user to get info for")] IUser user = null)
|
[Alias("user", "whois")]
|
||||||
{
|
public async Task UserInfoAsync([Summary("The (optional) user to get info for")] SocketUser user = null)
|
||||||
var userInfo = user ?? Context.Client.CurrentUser;
|
{
|
||||||
await ReplyAsync($"{userInfo.Username}#{userInfo.Discriminator}");
|
var userInfo = user ?? Context.Client.CurrentUser;
|
||||||
}
|
await ReplyAsync($"{userInfo.Username}#{userInfo.Discriminator}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ Discord API.
|
|||||||
### Inheritance
|
### Inheritance
|
||||||
|
|
||||||
Due to the nature of the Discord API, some entities are designed with
|
Due to the nature of the Discord API, some entities are designed with
|
||||||
multiple variants, for example, `SocketUser` and `SocketGuildUser`.
|
multiple variants; for example, `SocketUser` and `SocketGuildUser`.
|
||||||
|
|
||||||
All models will contain the most detailed version of an entity
|
All models will contain the most detailed version of an entity
|
||||||
possible, even if the type is less detailed.
|
possible, even if the type is less detailed.
|
||||||
@@ -61,8 +61,11 @@ a variant of the type that you need.
|
|||||||
### Tips
|
### Tips
|
||||||
|
|
||||||
Avoid using boxing-casts to coerce entities into a variant, use the
|
Avoid using boxing-casts to coerce entities into a variant, use the
|
||||||
`as` keyword, and a null-conditional operator.
|
[`as`] keyword, and a null-conditional operator instead.
|
||||||
|
|
||||||
This allows you to write safer code, and avoid InvalidCastExceptions.
|
This allows you to write safer code and avoid [InvalidCastExceptions].
|
||||||
|
|
||||||
For example, `(message.Author as SocketGuildUser)?.Nickname`.
|
For example, `(message.Author as SocketGuildUser)?.Nickname`.
|
||||||
|
|
||||||
|
[`as`]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/as
|
||||||
|
[InvalidCastExceptions]: https://msdn.microsoft.com/en-us/library/system.invalidcastexception(v=vs.110).aspx
|
||||||
@@ -4,27 +4,27 @@ title: Working with Events
|
|||||||
|
|
||||||
Events in Discord.Net are consumed in a similar manner to the standard
|
Events in Discord.Net are consumed in a similar manner to the standard
|
||||||
convention, with the exception that every event must be of the type
|
convention, with the exception that every event must be of the type
|
||||||
`System.Threading.Tasks.Task`, and instead of using EventArgs, the
|
`System.Threading.Tasks.Task` and instead of using `EventArgs`, the
|
||||||
event's parameters are passed directly into the handler.
|
event's parameters are passed directly into the handler.
|
||||||
|
|
||||||
This allows for events to be handled in an async context directly,
|
This allows for events to be handled in an async context directly
|
||||||
instead of relying on async void.
|
instead of relying on `async void`.
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
To receive data from an event, hook into it using C#'s delegate
|
To receive data from an event, hook into it using C#'s delegate
|
||||||
event pattern.
|
event pattern.
|
||||||
|
|
||||||
You may opt either to hook an event to an anonymous function (lambda)
|
You may either opt to hook an event to an anonymous function (lambda)
|
||||||
or a named function.
|
or a named function.
|
||||||
|
|
||||||
### Safety
|
### Safety
|
||||||
|
|
||||||
All events are designed to be thread-safe, in that events are executed
|
All events are designed to be thread-safe; events are executed
|
||||||
synchronously off the gateway task, in the same context as the gateway
|
synchronously off the gateway task in the same context as the gateway
|
||||||
task.
|
task.
|
||||||
|
|
||||||
As a side effect, this makes it possible to deadlock the gateway task,
|
As a side effect, this makes it possible to deadlock the gateway task
|
||||||
and kill a connection. As a general rule of thumb, any task that takes
|
and kill a connection. As a general rule of thumb, any task that takes
|
||||||
longer than three seconds should **not** be awaited directly in the
|
longer than three seconds should **not** be awaited directly in the
|
||||||
context of an event, but should be wrapped in a `Task.Run` or
|
context of an event, but should be wrapped in a `Task.Run` or
|
||||||
@@ -62,7 +62,7 @@ This pattern is typically only found on `EntityUpdated` events.
|
|||||||
|
|
||||||
An event handler with a signature of `Func<Cacheable, Entity, Task>`
|
An event handler with a signature of `Func<Cacheable, Entity, Task>`
|
||||||
means that the `before` state of the entity was not provided by the
|
means that the `before` state of the entity was not provided by the
|
||||||
API, so it can either be pulled from the client's cache, or
|
API, so it can either be pulled from the client's cache or
|
||||||
downloaded from the API.
|
downloaded from the API.
|
||||||
|
|
||||||
See the documentation for [Cacheable] for more information on this
|
See the documentation for [Cacheable] for more information on this
|
||||||
@@ -76,8 +76,8 @@ object.
|
|||||||
|
|
||||||
### Tips
|
### Tips
|
||||||
|
|
||||||
Many events relating to a Message entity, e.g. `MessageUpdated`
|
Many events relating to a Message entity (i.e. `MessageUpdated` and
|
||||||
and `ReactionAdded` rely on the client's message cache, which is
|
`ReactionAdded`) rely on the client's message cache, which is
|
||||||
**not** enabled by default. Set the `MessageCacheSize` flag in
|
**not** enabled by default. Set the `MessageCacheSize` flag in
|
||||||
[DiscordSocketConfig] to enable it.
|
[DiscordSocketConfig] to enable it.
|
||||||
|
|
||||||
|
|||||||
@@ -14,12 +14,14 @@ section.
|
|||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
To receive log events, simply hook the discord client's log method
|
To receive log events, simply hook the discord client's log method
|
||||||
to a Task with a single parameter of type [LogMessage]
|
to a `Task` with a single parameter of type [LogMessage].
|
||||||
|
|
||||||
It is recommended that you use an established function instead of a
|
It is recommended that you use an established function instead of a
|
||||||
lambda for handling logs, because most [addons] accept a reference
|
lambda for handling logs, because most addons accept a reference
|
||||||
to a logging function to write their own messages.
|
to a logging function to write their own messages.
|
||||||
|
|
||||||
|
[LogMessage]: xref:Discord.LogMessage
|
||||||
|
|
||||||
### Usage in Commands
|
### Usage in Commands
|
||||||
|
|
||||||
Discord.Net's [CommandService] also provides a log event, identical
|
Discord.Net's [CommandService] also provides a log event, identical
|
||||||
@@ -29,6 +31,9 @@ Data logged through this event is typically coupled with a
|
|||||||
[CommandException], where information about the command's context
|
[CommandException], where information about the command's context
|
||||||
and error can be found and handled.
|
and error can be found and handled.
|
||||||
|
|
||||||
|
[CommandService]: xref:Discord.Commands.CommandService
|
||||||
|
[CommandException]: xref:Discord.Commands.CommandException
|
||||||
|
|
||||||
#### Samples
|
#### Samples
|
||||||
|
|
||||||
[!code-csharp[Logging Sample](samples/logging.cs)]
|
[!code-csharp[Logging Sample](samples/logging.cs)]
|
||||||
|
|||||||
@@ -2,84 +2,87 @@
|
|||||||
title: Installing Discord.Net
|
title: Installing Discord.Net
|
||||||
---
|
---
|
||||||
|
|
||||||
Discord.Net is distributed through the NuGet package manager, and it is
|
Discord.Net is distributed through the NuGet package manager, and it
|
||||||
recommended to use NuGet to get started.
|
is recommended to use NuGet to get started.
|
||||||
|
|
||||||
Optionally, you may compile from source and install yourself.
|
Optionally, you may compile from source and install yourself.
|
||||||
|
|
||||||
# Supported Platforms
|
# Supported Platforms
|
||||||
|
|
||||||
Currently, Discord.Net targets [.NET Standard] 1.3, and offers support for
|
Currently, Discord.Net targets [.NET Standard] 1.3 and offers support
|
||||||
.NET Standard 1.1. If your application will be targeting .NET Standard 1.1,
|
for .NET Standard 1.1. If your application will be targeting .NET
|
||||||
please see the [additional steps](#installing-on-net-standard-11).
|
Standard 1.1, please see the [additional steps].
|
||||||
|
|
||||||
Since Discord.Net is built on the .NET Standard, it is also recommended to
|
Since Discord.Net is built on the .NET Standard, it is also
|
||||||
create applications using [.NET Core], though you are not required to. When
|
recommended to create applications using [.NET Core], though not
|
||||||
using .NET Framework, it is suggested to target `.NET 4.6.1` or higher.
|
required. When using .NET Framework, it is suggested to target
|
||||||
|
`.NET Framework 4.6.1` or higher.
|
||||||
|
|
||||||
[.NET Standard]: https://docs.microsoft.com/en-us/dotnet/articles/standard/library
|
[.NET Standard]: https://docs.microsoft.com/en-us/dotnet/articles/standard/library
|
||||||
[.NET Core]: https://docs.microsoft.com/en-us/dotnet/articles/core/
|
[.NET Core]: https://docs.microsoft.com/en-us/dotnet/articles/core/
|
||||||
|
[additional steps]: #installing-on-net-standard-11
|
||||||
|
|
||||||
# Installing with NuGet
|
# Installing with NuGet
|
||||||
|
|
||||||
Release builds of Discord.Net 1.0 will be published to the
|
Release builds of Discord.Net 1.0 will be published to the
|
||||||
[official NuGet feed].
|
[official NuGet feed].
|
||||||
|
|
||||||
Development builds of Discord.Net 1.0, as well as [addons](TODO) are published
|
Development builds of Discord.Net 1.0, as well as addons *(TODO)* are
|
||||||
to our development [MyGet feed].
|
published to our development [MyGet feed].
|
||||||
|
|
||||||
Direct feed link: `https://www.myget.org/F/discord-net/api/v3/index.json`
|
Direct feed link: `https://www.myget.org/F/discord-net/api/v3/index.json`
|
||||||
|
|
||||||
Not sure how to add a direct feed? See how [with Visual Studio]
|
Not sure how to add a direct feed? See how [with Visual Studio] or
|
||||||
or [without Visual Studio](#configuring-nuget-without-visual-studio)
|
[without Visual Studio].
|
||||||
|
|
||||||
[official NuGet feed]: https://nuget.org
|
[official NuGet feed]: https://nuget.org
|
||||||
[MyGet feed]: https://www.myget.org/feed/Packages/discord-net
|
[MyGet feed]: https://www.myget.org/feed/Packages/discord-net
|
||||||
[with Visual Studio]: https://docs.microsoft.com/en-us/nuget/tools/package-manager-ui#package-sources
|
[with Visual Studio]: https://docs.microsoft.com/en-us/nuget/tools/package-manager-ui#package-sources
|
||||||
|
[without Visual Studio]: #configuring-nuget-without-visual-studio
|
||||||
|
|
||||||
## Using Visual Studio
|
## Using Visual Studio
|
||||||
|
|
||||||
1. Create a solution for your bot
|
|
||||||
2. In Solution Explorer, find the 'Dependencies' element under your bot's
|
|
||||||
project
|
|
||||||
3. Right click on 'Dependencies', and select 'Manage NuGet packages'
|
|
||||||

|
|
||||||
4. In the 'browse' tab, search for 'Discord.Net'
|
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
Don't forget to change your package source if you're installing from the
|
>Don't forget to change your package source if you're installing from
|
||||||
developer feed.
|
the developer feed.
|
||||||
Also make sure to check 'Enable Prereleases' if installing a dev build!
|
>Also make sure to check "Enable Prereleases" if installing a dev
|
||||||
|
build!
|
||||||
5. Install the 'Discord.Net' package
|
|
||||||
|
|
||||||
|
1. Create a solution for your bot.
|
||||||
|
2. In Solution Explorer, find the "Dependencies" element under your
|
||||||
|
bot's project.
|
||||||
|
3. Right click on "Dependencies", and select "Manage NuGet packages."
|
||||||
|

|
||||||
|
4. In the "Browse" tab, search for `Discord.Net`.
|
||||||
|
5. Install the `Discord.Net` package.
|
||||||

|

|
||||||
|
|
||||||
## Using JetBrains Rider
|
## Using JetBrains Rider
|
||||||
|
|
||||||
1. Create a new solution for your bot
|
|
||||||
2. Open the NuGet window (Tools > NuGet > Manage NuGet packages for Solution)
|
|
||||||

|
|
||||||
3. In the 'Packages' tab, search for 'Discord.Net'
|
|
||||||

|
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
Make sure to check the 'Prerelease' box if installing a dev build!
|
Make sure to check the "Prerelease" box if installing a dev build!
|
||||||
|
|
||||||
4. Install by adding the package to your project
|
1. Create a new solution for your bot.
|
||||||
|
2. Open the NuGet window (Tools > NuGet > Manage NuGet packages for
|
||||||
|
Solution).
|
||||||
|

|
||||||
|
3. In the "Packages" tab, search for `Discord.Net`.
|
||||||
|

|
||||||
|
4. Install by adding the package to your project.
|
||||||

|

|
||||||
|
|
||||||
## Using Visual Studio Code
|
## Using Visual Studio Code
|
||||||
|
|
||||||
1. Create a new project for your bot
|
> [!TIP]
|
||||||
2. Add Discord.Net to your .csproj
|
Don't forget to add the package source to a [NuGet.Config file] if
|
||||||
|
you're installing from the developer feed.
|
||||||
|
|
||||||
|
1. Create a new project for your bot.
|
||||||
|
2. Add `Discord.Net` to your .csproj.
|
||||||
|
|
||||||
[!code-xml[Sample .csproj](samples/project.csproj)]
|
[!code-xml[Sample .csproj](samples/project.csproj)]
|
||||||
|
|
||||||
> [!TIP]
|
[NuGet.Config file]: #configuring-nuget-without-visual-studio
|
||||||
Don't forget to add the package source to a [NuGet.Config file](#configuring-nuget-without-visual-studio) if you're installing from the
|
|
||||||
developer feed.
|
|
||||||
|
|
||||||
# Compiling from Source
|
# Compiling from Source
|
||||||
|
|
||||||
@@ -90,8 +93,8 @@ In order to compile Discord.Net, you require the following:
|
|||||||
- [Visual Studio 2017](https://www.visualstudio.com/)
|
- [Visual Studio 2017](https://www.visualstudio.com/)
|
||||||
- [.NET Core SDK 1.0](https://www.microsoft.com/net/download/core#/sdk)
|
- [.NET Core SDK 1.0](https://www.microsoft.com/net/download/core#/sdk)
|
||||||
|
|
||||||
The .NET Core and Docker (Preview) workload is required during Visual Studio
|
The .NET Core and Docker (Preview) workload is required during Visual
|
||||||
installation.
|
Studio installation.
|
||||||
|
|
||||||
### Using Command Line
|
### Using Command Line
|
||||||
|
|
||||||
@@ -101,26 +104,27 @@ installation.
|
|||||||
|
|
||||||
## Installing on .NET Standard 1.1
|
## Installing on .NET Standard 1.1
|
||||||
|
|
||||||
For applications targeting a runtime corresponding with .NET Standard 1.1 or 1.2,
|
For applications targeting a runtime corresponding with .NET Standard
|
||||||
the builtin WebSocket and UDP provider will not work. For applications which
|
1.1 or 1.2, the builtin WebSocket and UDP provider will not work. For
|
||||||
utilize a WebSocket connection to Discord (WebSocket or RPC), third-party
|
applications which utilize a WebSocket connection to Discord
|
||||||
provider packages will need to be installed and configured.
|
(WebSocket or RPC), third-party provider packages will need to be
|
||||||
|
installed and configured.
|
||||||
|
|
||||||
First, install the following packages through NuGet, or compile yourself, if
|
First, install the following packages through NuGet, or compile
|
||||||
you prefer:
|
yourself, if you prefer:
|
||||||
|
|
||||||
- Discord.Net.Providers.WS4Net
|
- Discord.Net.Providers.WS4Net
|
||||||
- Discord.Net.Providers.UDPClient
|
- Discord.Net.Providers.UDPClient
|
||||||
|
|
||||||
Note that `Discord.Net.Providers.UDPClient` is _only_ required if your bot will
|
Note that `Discord.Net.Providers.UDPClient` is _only_ required if your
|
||||||
be utilizing voice chat.
|
bot will be utilizing voice chat.
|
||||||
|
|
||||||
Next, you will need to configure your [DiscordSocketClient] to use these custom
|
Next, you will need to configure your [DiscordSocketClient] to use
|
||||||
providers over the default ones.
|
these custom providers over the default ones.
|
||||||
|
|
||||||
To do this, set the `WebSocketProvider` and optionally `UdpSocketProvider`
|
To do this, set the `WebSocketProvider` and the optional
|
||||||
properties on the [DiscordSocketConfig] that you are passing into your
|
`UdpSocketProvider` properties on the [DiscordSocketConfig] that you
|
||||||
client.
|
are passing into your client.
|
||||||
|
|
||||||
[!code-csharp[NET Standard 1.1 Example](samples/netstd11.cs)]
|
[!code-csharp[NET Standard 1.1 Example](samples/netstd11.cs)]
|
||||||
|
|
||||||
@@ -129,13 +133,14 @@ client.
|
|||||||
|
|
||||||
## Configuring NuGet without Visual Studio
|
## Configuring NuGet without Visual Studio
|
||||||
|
|
||||||
If you plan on deploying your bot or developing outside of Visual Studio, you
|
If you plan on deploying your bot or developing outside of Visual
|
||||||
will need to create a local NuGet configuration file for your project.
|
Studio, you will need to create a local NuGet configuration file for
|
||||||
|
your project.
|
||||||
|
|
||||||
To do this, create a file named `nuget.config` alongside the root of your
|
To do this, create a file named `nuget.config` alongside the root of
|
||||||
application, where the project solution is located.
|
your application, where the project solution is located.
|
||||||
|
|
||||||
Paste the following snippets into this configuration file, adding any additional
|
Paste the following snippets into this configuration file, adding any
|
||||||
feeds as necessary.
|
additional feeds as necessary.
|
||||||
|
|
||||||
[!code-xml[NuGet Configuration](samples/nuget.config)]
|
[!code-xml[NuGet Configuration](samples/nuget.config)]
|
||||||
|
|||||||
@@ -13,42 +13,46 @@ diverse commands later, but for now, it is a good starting point.
|
|||||||
Before you can begin writing your bot, it is necessary to create a bot
|
Before you can begin writing your bot, it is necessary to create a bot
|
||||||
account on Discord.
|
account on Discord.
|
||||||
|
|
||||||
1. Visit the [Discord Applications Portal]
|
1. Visit the [Discord Applications Portal].
|
||||||
2. Create a New Application
|
2. Create a New Application.
|
||||||
3. Give the application a name (this will be the bot's initial
|
3. Give the application a name (this will be the bot's initial
|
||||||
username).
|
username).
|
||||||
4. Create the Application
|
4. Create the Application.
|
||||||

|
|
||||||
5. In the application review page, click **Create a Bot User**
|

|
||||||

|
|
||||||
6. Confirm the popup
|
5. In the application review page, click **Create a Bot User**.
|
||||||
7. If this bot will be public, check 'Public Bot'.
|
|
||||||
**Do not tick any other options!**
|

|
||||||
|
|
||||||
|
6. Confirm the popup.
|
||||||
|
7. If this bot will be public, check "Public Bot." **Do not tick any
|
||||||
|
other options!**
|
||||||
|
|
||||||
[Discord Applications Portal]: https://discordapp.com/developers/applications/me
|
[Discord Applications Portal]: https://discordapp.com/developers/applications/me
|
||||||
|
|
||||||
## Adding your bot to a server
|
## Adding your bot to a server
|
||||||
|
|
||||||
Bots **can not** use invite links, they must be explicitly invited
|
Bots **cannot** use invite links, they must be explicitly invited
|
||||||
through the OAuth2 flow.
|
through the OAuth2 flow.
|
||||||
|
|
||||||
1. Open your bot's application on the [Discord Applications Portal]
|
1. Open your bot's application on the [Discord Applications Portal].
|
||||||
2. Retrieve the app's **Client ID**.
|
2. Retrieve the app's **Client ID**.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
3. Create an OAuth2 authorization URL
|
3. Create an OAuth2 authorization URL
|
||||||
`https://discordapp.com/oauth2/authorize?client_id=<CLIENT ID>&scope=bot`
|
`https://discordapp.com/oauth2/authorize?client_id=<CLIENT ID>&scope=bot`
|
||||||
4. Open the authorization URL in your browser
|
4. Open the authorization URL in your browser.
|
||||||
5. Select a server
|
5. Select a server.
|
||||||
|
6. Click on authorize.
|
||||||
|
|
||||||
|
>[!NOTE]
|
||||||
|
Only servers where you have the `MANAGE_SERVER` permission will be
|
||||||
|
present in this list.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
>[!NOTE]
|
|
||||||
Only servers where you have the `MANAGE_SERVER` permission will be
|
|
||||||
present in this list.
|
|
||||||
|
|
||||||
6. Click authorize
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Connecting to Discord
|
## Connecting to Discord
|
||||||
|
|
||||||
@@ -57,10 +61,10 @@ do that now. (see the [Installing](installing.md) section)
|
|||||||
|
|
||||||
### Async
|
### Async
|
||||||
|
|
||||||
Discord.Net uses .NET's Task-based Asynchronous Pattern ([TAP])
|
Discord.Net uses .NET's [Task-based Asynchronous Pattern (TAP)]
|
||||||
extensively - nearly every operation is asynchronous.
|
extensively - nearly every operation is asynchronous.
|
||||||
|
|
||||||
It is highly recommended that these operations be awaited in a
|
It is highly recommended that these operations are awaited in a
|
||||||
properly established async context whenever possible. Establishing an
|
properly established async context whenever possible. Establishing an
|
||||||
async context can be problematic, but not hard.
|
async context can be problematic, but not hard.
|
||||||
|
|
||||||
@@ -70,27 +74,29 @@ async main.
|
|||||||
|
|
||||||
[!code-csharp[Async Context](samples/intro/async-context.cs)]
|
[!code-csharp[Async Context](samples/intro/async-context.cs)]
|
||||||
|
|
||||||
As a result of this, your program will now start, and immidiately
|
As a result of this, your program will now start and immidiately
|
||||||
jump into an async context. This will allow us later on to create a
|
jump into an async context. This will allow us to create a connection
|
||||||
connection to Discord, without needing to worry about setting up the
|
to Discord later on without needing to worry about setting up the
|
||||||
correct async implementation.
|
correct async implementation.
|
||||||
|
|
||||||
>[!TIP]
|
>[!TIP]
|
||||||
If your application throws any exceptions within an async context,
|
If your application throws any exceptions within an async context,
|
||||||
they will be thrown all the way back up to the first non-async method.
|
they will be thrown all the way back up to the first non-async method;
|
||||||
Since our first non-async method is the program's Main method, this
|
since our first non-async method is the program's `Main` method, this
|
||||||
means that **all** unhandled exceptions will be thrown up there, which
|
means that **all** unhandled exceptions will be thrown up there, which
|
||||||
will crash your application. Discord.Net will prevent exceptions in
|
will crash your application. Discord.Net will prevent exceptions in
|
||||||
event handlers from crashing your program, but any exceptions in your
|
event handlers from crashing your program, but any exceptions in your
|
||||||
async main **will** cause the application to crash.
|
async main **will** cause the application to crash.
|
||||||
|
|
||||||
|
[Task-based Asynchronous Pattern (TAP)]: https://docs.microsoft.com/en-us/dotnet/articles/csharp/async
|
||||||
|
|
||||||
### Creating a logging method
|
### Creating a logging method
|
||||||
|
|
||||||
Before we create and configure a Discord client, we will add a method
|
Before we create and configure a Discord client, we will add a method
|
||||||
to handle Discord.Net's log events.
|
to handle Discord.Net's log events.
|
||||||
|
|
||||||
To allow agnostic support of as many log providers as possible, we
|
To allow agnostic support of as many log providers as possible, we
|
||||||
log information through a Log event, with a proprietary LogMessage
|
log information through a `Log` event with a proprietary `LogMessage`
|
||||||
parameter. See the [API Documentation] for this event.
|
parameter. See the [API Documentation] for this event.
|
||||||
|
|
||||||
If you are using your own logging framework, this is where you would
|
If you are using your own logging framework, this is where you would
|
||||||
@@ -99,10 +105,12 @@ the Console.
|
|||||||
|
|
||||||
[!code-csharp[Async Context](samples/intro/logging.cs)]
|
[!code-csharp[Async Context](samples/intro/logging.cs)]
|
||||||
|
|
||||||
|
[API Documentation]: xref:Discord.Rest.BaseDiscordClient#Discord_Rest_BaseDiscordClient_Log
|
||||||
|
|
||||||
### Creating a Discord Client
|
### Creating a Discord Client
|
||||||
|
|
||||||
Finally, we can create a connection to Discord. Since we are writing
|
Finally, we can create a connection to Discord. Since we are writing
|
||||||
a bot, we will be using a [DiscordSocketClient], along with socket
|
a bot, we will be using a [DiscordSocketClient] along with socket
|
||||||
entities. See the [terminology](terminology.md) if you're unsure of
|
entities. See the [terminology](terminology.md) if you're unsure of
|
||||||
the differences.
|
the differences.
|
||||||
|
|
||||||
@@ -110,22 +118,24 @@ To do so, create an instance of [DiscordSocketClient] in your async
|
|||||||
main, passing in a configuration object only if necessary. For most
|
main, passing in a configuration object only if necessary. For most
|
||||||
users, the default will work fine.
|
users, the default will work fine.
|
||||||
|
|
||||||
Before connecting, we should hook the client's log event to the
|
Before connecting, we should hook the client's `Log` event to the
|
||||||
log handler that was just created. Events in Discord.Net work
|
log handler that was just created. Events in Discord.Net work
|
||||||
similarly to other events in C#, so hook this event the way that
|
similarly to other events in C#, so hook this event the way that
|
||||||
you typically would.
|
you typically would.
|
||||||
|
|
||||||
Next, you will need to 'login to Discord' with the `LoginAsync` method.
|
Next, you will need to "login to Discord" with the `LoginAsync`
|
||||||
|
method.
|
||||||
|
|
||||||
You may create a variable to hold your bot's token (this can be found
|
You may create a variable to hold your bot's token (this can be found
|
||||||
on your bot's application page on the [Discord Applications Portal]).
|
on your bot's application page on the [Discord Applications Portal]).
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
>[!IMPORTANT]
|
>[!IMPORTANT]
|
||||||
Your bot's token can be used to gain total access to your bot, so
|
Your bot's token can be used to gain total access to your bot, so
|
||||||
**do __NOT__ share this token with anyone!** It may behoove you to
|
**do __NOT__ share this token with anyone else!** It may behoove you
|
||||||
store this token in an external file if you plan on distributing the
|
to store this token in an external file if you plan on distributing
|
||||||
source code for your bot.
|
the source code for your bot.
|
||||||
|
|
||||||
We may now invoke the client's `StartAsync` method, which will
|
We may now invoke the client's `StartAsync` method, which will
|
||||||
start connection/reconnection logic. It is important to note that
|
start connection/reconnection logic. It is important to note that
|
||||||
@@ -134,14 +144,9 @@ start connection/reconnection logic. It is important to note that
|
|||||||
Any methods that rely on the client's state should go in an event
|
Any methods that rely on the client's state should go in an event
|
||||||
handler.
|
handler.
|
||||||
|
|
||||||
>[!NOTE]
|
|
||||||
Connection logic is incomplete as of the current build. Events will
|
|
||||||
soon be added to indicate when the client's state is ready for use;
|
|
||||||
(rewrite this section when possible)
|
|
||||||
|
|
||||||
Finally, we will want to block the async main method from returning
|
Finally, we will want to block the async main method from returning
|
||||||
until after the application is exited. To do this, we can await an
|
until after the application is exited. To do this, we can await an
|
||||||
infinite delay, or any other blocking method, such as reading from
|
infinite delay or any other blocking method, such as reading from
|
||||||
the console.
|
the console.
|
||||||
|
|
||||||
The following lines can now be added:
|
The following lines can now be added:
|
||||||
@@ -154,51 +159,55 @@ online in Discord.
|
|||||||
>[!TIP]
|
>[!TIP]
|
||||||
Encountering a `PlatformNotSupportedException` when starting your bot?
|
Encountering a `PlatformNotSupportedException` when starting your bot?
|
||||||
This means that you are targeting a platform where .NET's default
|
This means that you are targeting a platform where .NET's default
|
||||||
WebSocket client is not supported. Refer to the [installing guide]
|
WebSocket client is not supported. Refer to the [installation guide]
|
||||||
for how to fix this.
|
for how to fix this.
|
||||||
|
|
||||||
[TAP]: https://docs.microsoft.com/en-us/dotnet/articles/csharp/async
|
|
||||||
[API Documentation]: xref:Discord.Rest.BaseDiscordClient#Discord_Rest_BaseDiscordClient_Log
|
|
||||||
[DiscordSocketClient]: xref:Discord.WebSocket.DiscordSocketClient
|
[DiscordSocketClient]: xref:Discord.WebSocket.DiscordSocketClient
|
||||||
[installing guide]: installing.md#installing-on-net-standard-11
|
[installation guide]: installing.md#installing-on-net-standard-11
|
||||||
|
|
||||||
### Handling a 'ping'
|
### Handling a 'ping'
|
||||||
|
|
||||||
|
>[!WARNING]
|
||||||
|
Please note that this is *not* a proper way to create a command.
|
||||||
|
Use the `CommandService` provided by the library instead, as explained
|
||||||
|
in the [Command Guide] section.
|
||||||
|
|
||||||
Now that we have learned how to open a connection to Discord, we can
|
Now that we have learned how to open a connection to Discord, we can
|
||||||
begin handling messages that users are sending.
|
begin handling messages that users are sending.
|
||||||
|
|
||||||
To start out, our bot will listen for any message where the content
|
To start out, our bot will listen for any message where the content
|
||||||
is equal to `!ping`, and respond back with `Pong!`.
|
is equal to `!ping` and respond back with "Pong!".
|
||||||
|
|
||||||
Since we want to listen for new messages, the event to hook in to
|
Since we want to listen for new messages, the event to hook into
|
||||||
is [MessageReceived].
|
is [MessageReceived].
|
||||||
|
|
||||||
In your program, add a method that matches the signature of the
|
In your program, add a method that matches the signature of the
|
||||||
MessageReceived event - it must be a method (`Func`) that returns the
|
`MessageReceived` event - it must be a method (`Func`) that returns
|
||||||
type `Task`, and takes a single parameter, a [SocketMessage]. Also,
|
the type `Task` and takes a single parameter, a [SocketMessage]. Also,
|
||||||
since we will be sending data to Discord in this method, we will flag
|
since we will be sending data to Discord in this method, we will flag
|
||||||
it as `async`.
|
it as `async`.
|
||||||
|
|
||||||
In this method, we will add an `if` block, to determine if the message
|
In this method, we will add an `if` block to determine if the message
|
||||||
content fits the rules of our scenario - recall that it must be equal
|
content fits the rules of our scenario - recall that it must be equal
|
||||||
to `!ping`.
|
to `!ping`.
|
||||||
|
|
||||||
Inside the branch of this condition, we will want to send a message
|
Inside the branch of this condition, we will want to send a message
|
||||||
back to the channel from which the message came - `Pong!`. To find the
|
back to the channel from which the message comes from - "Pong!". To
|
||||||
channel, look for the `Channel` property on the message parameter.
|
find the channel, look for the `Channel` property on the message
|
||||||
|
parameter.
|
||||||
|
|
||||||
Next, we will want to send a message to this channel. Since the
|
Next, we will want to send a message to this channel. Since the
|
||||||
channel object is of type [SocketMessageChannel], we can invoke the
|
channel object is of type [SocketMessageChannel], we can invoke the
|
||||||
`SendMessageAsync` instance method. For the message content, send back
|
`SendMessageAsync` instance method. For the message content, send back
|
||||||
a string containing 'Pong!'.
|
a string containing "Pong!".
|
||||||
|
|
||||||
You should have now added the following lines:
|
You should have now added the following lines:
|
||||||
|
|
||||||
[!code-csharp[Message](samples/intro/message.cs)]
|
[!code-csharp[Message](samples/intro/message.cs)]
|
||||||
|
|
||||||
Now, your first bot is complete. You may continue to add on to this
|
Now your first bot is complete. You may continue to add on to this
|
||||||
if you desire, but for any bot that will be carrying out multiple
|
if you desire, but for any bots that will be carrying out multiple
|
||||||
commands, it is strongly encouraged to use the command framework, as
|
commands, it is strongly recommended to use the command framework as
|
||||||
shown below.
|
shown below.
|
||||||
|
|
||||||
For your reference, you may view the [completed program].
|
For your reference, you may view the [completed program].
|
||||||
@@ -207,13 +216,14 @@ For your reference, you may view the [completed program].
|
|||||||
[SocketMessage]: xref:Discord.WebSocket.SocketMessage
|
[SocketMessage]: xref:Discord.WebSocket.SocketMessage
|
||||||
[SocketMessageChannel]: xref:Discord.WebSocket.ISocketMessageChannel
|
[SocketMessageChannel]: xref:Discord.WebSocket.ISocketMessageChannel
|
||||||
[completed program]: samples/intro/complete.cs
|
[completed program]: samples/intro/complete.cs
|
||||||
|
[Command Guide]: ../commands/commands.md
|
||||||
|
|
||||||
# Building a bot with commands
|
# Building a bot with commands
|
||||||
|
|
||||||
This section will show you how to write a program that is ready for
|
This section will show you how to write a program that is ready for
|
||||||
[commands](commands/commands.md). Note that this will not be explaining _how_
|
[Commands](../commands/commands.md). Note that we will not be
|
||||||
to write commands or services, it will only be covering the general
|
explaining _how_ to write Commands or Services, it will only be
|
||||||
structure.
|
covering the general structure.
|
||||||
|
|
||||||
For reference, view an [annotated example] of this structure.
|
For reference, view an [annotated example] of this structure.
|
||||||
|
|
||||||
@@ -224,4 +234,4 @@ should be to separate the program (initialization and command handler),
|
|||||||
the modules (handle commands), and the services (persistent storage,
|
the modules (handle commands), and the services (persistent storage,
|
||||||
pure functions, data manipulation).
|
pure functions, data manipulation).
|
||||||
|
|
||||||
**todo:** diagram of bot structure
|
**todo:** diagram of bot structure
|
||||||
@@ -7,32 +7,34 @@ title: Terminology
|
|||||||
|
|
||||||
## Preface
|
## Preface
|
||||||
|
|
||||||
Most terms for objects remain the same between 0.9 and 1.0. The major difference is that the ``Server`` is now called ``Guild``, to stay in line with Discord internally
|
Most terms for objects remain the same between 0.9 and 1.0. The major
|
||||||
|
difference is that the ``Server`` is now called ``Guild`` to stay in
|
||||||
|
line with Discord internally.
|
||||||
|
|
||||||
## Implementation Specific Entities
|
## Implementation Specific Entities
|
||||||
|
|
||||||
Discord.Net 1.0 is split into a core library, and three different
|
Discord.Net 1.0 is split into a core library and three different
|
||||||
implementations - Discord.Net.Core, Discord.Net.Rest, Discord.Net.Rpc,
|
implementations - `Discord.Net.Core`, `Discord.Net.Rest`,
|
||||||
and Discord.Net.WebSockets.
|
`Discord.Net.Rpc`, and `Discord.Net.WebSockets`.
|
||||||
|
|
||||||
As a bot developer, you will only need to use Discord.Net.WebSockets,
|
As a bot developer, you will only need to use `Discord.Net.WebSockets`,
|
||||||
but you should be aware of the differences between them.
|
but you should be aware of the differences between them.
|
||||||
|
|
||||||
`Discord.Net.Core` provides a set of interfaces that model Discord's
|
`Discord.Net.Core` provides a set of interfaces that models Discord's
|
||||||
API. These interfaces are consistent throughout all implementations of
|
API. These interfaces are consistent throughout all implementations of
|
||||||
Discord.Net, and if you are writing an implementation-agnostic library
|
Discord.Net, and if you are writing an implementation-agnostic library
|
||||||
or addon, you can rely on the core interfaces to ensure that your
|
or addon, you can rely on the core interfaces to ensure that your
|
||||||
addon will run on all platforms.
|
addon will run on all platforms.
|
||||||
|
|
||||||
`Discord.Net.Rest` provides a set of concrete classes to be used
|
`Discord.Net.Rest` provides a set of concrete classes to be used
|
||||||
**strictly** with the REST portion of Discord's API. Entities in
|
**strictly** with the REST portion of Discord's API. Entities in this
|
||||||
this implementation are prefixed with `Rest`, e.g. `RestChannel`.
|
implementation are prefixed with `Rest` (e.g. `RestChannel`).
|
||||||
|
|
||||||
`Discord.Net.Rpc` provides a set of concrete classes that are used with
|
`Discord.Net.Rpc` provides a set of concrete classes that are used
|
||||||
Discord's RPC API. Entities in this implementation are prefixed with
|
with Discord's RPC API. Entities in this implementation are prefixed
|
||||||
`Rpc`, e.g. `RpcChannel`.
|
with `Rpc` (e.g. `RpcChannel`).
|
||||||
|
|
||||||
`Discord.Net.WebSocket` provides a set of concrete classes that are used
|
`Discord.Net.WebSocket` provides a set of concrete classes that are
|
||||||
primarily with Discord's WebSocket API, or entities that are kept in
|
used primarily with Discord's WebSocket API or entities that are kept
|
||||||
cache. When developing bots, you will be using this implementation. All
|
in cache. When developing bots, you will be using this implementation.
|
||||||
entities are prefixed with `Socket`, e.g. `SocketChannel`.
|
All entities are prefixed with `Socket` (e.g. `SocketChannel`).
|
||||||
@@ -17,7 +17,7 @@ when developing on .NET Core, this is where you execute `dotnet run`
|
|||||||
from; typically the same directory as your csproj).
|
from; typically the same directory as your csproj).
|
||||||
|
|
||||||
For Windows Users, precompiled binaries are available for your
|
For Windows Users, precompiled binaries are available for your
|
||||||
convienence [here](https://discord.foxbot.me/binaries/)
|
convienence [here](https://discord.foxbot.me/binaries/).
|
||||||
|
|
||||||
For Linux Users, you will need to compile [Sodium] and [Opus] from
|
For Linux Users, you will need to compile [Sodium] and [Opus] from
|
||||||
source, or install them from your package manager.
|
source, or install them from your package manager.
|
||||||
@@ -31,7 +31,7 @@ Joining a channel is the first step to sending audio, and will return
|
|||||||
an [IAudioClient] to send data with.
|
an [IAudioClient] to send data with.
|
||||||
|
|
||||||
To join a channel, simply await [ConnectAsync] on any instance of an
|
To join a channel, simply await [ConnectAsync] on any instance of an
|
||||||
@Discord.IVoiceChannel.
|
@Discord.IAudioChannel.
|
||||||
|
|
||||||
[!code-csharp[Joining a Channel](samples/joining_audio.cs)]
|
[!code-csharp[Joining a Channel](samples/joining_audio.cs)]
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ guild. To switch channels within a guild, invoke [ConnectAsync] on
|
|||||||
another voice channel in the guild.
|
another voice channel in the guild.
|
||||||
|
|
||||||
[IAudioClient]: xref:Discord.Audio.IAudioClient
|
[IAudioClient]: xref:Discord.Audio.IAudioClient
|
||||||
[ConnectAsync]: xref:Discord.IVoiceChannel#Discord_IVoiceChannel_ConnectAsync
|
[ConnectAsync]: xref:Discord.IAudioChannel#Discord_IAudioChannel_ConnectAsync_Action_IAudioClient__
|
||||||
|
|
||||||
## Transmitting Audio
|
## Transmitting Audio
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ Channels should be left at `2`, unless you specified a different value
|
|||||||
for `-ac 2` when creating FFmpeg.
|
for `-ac 2` when creating FFmpeg.
|
||||||
|
|
||||||
[AudioOutStream]: xref:Discord.Audio.AudioOutStream
|
[AudioOutStream]: xref:Discord.Audio.AudioOutStream
|
||||||
[IAudioClient.CreatePCMStream]: xref:Discord.Audio.IAudioClient#Discord_Audio_IAudioClient_CreatePCMStream_System_Int32_System_Int32_System_Nullable_System_Int32__System_Int32_
|
[IAudioClient.CreatePCMStream]: xref:Discord.Audio.IAudioClient#Discord_Audio_IAudioClient_CreateDirectPCMStream_Discord_Audio_AudioApplication_System_Nullable_System_Int32__System_Int32_
|
||||||
|
|
||||||
Finally, audio will need to be piped from FFmpeg's stdout into your
|
Finally, audio will need to be piped from FFmpeg's stdout into your
|
||||||
AudioOutStream. This step can be as complex as you'd like it to be, but
|
AudioOutStream. This step can be as complex as you'd like it to be, but
|
||||||
|
|||||||
Reference in New Issue
Block a user