@@ -8,7 +8,7 @@ title: Questions about Basic Operations | |||
## How should I safely check a type? | |||
> [!WARNING] | |||
> Direct casting (e.g. `(Type)type`) is **the least recommended** | |||
> Direct casting (e.g., `(Type)type`) is **the least recommended** | |||
> way of casting, as it *can* throw an [InvalidCastException] | |||
> when the object isn't the desired type. | |||
> | |||
@@ -28,9 +28,9 @@ A good and safe casting example: | |||
## How do I send a message? | |||
> [!TIP] | |||
> The [GetChannel] method by default returns an [IChannel]. | |||
> This means channels such as [IVoiceChannel], [ICategoryChannel] | |||
> can be returned. This is why that you cannot send message | |||
> The [GetChannel] method by default returns an [IChannel], allowing | |||
> channel types such as [IVoiceChannel], [ICategoryChannel] | |||
> to be returned; consequently, you cannot send a message | |||
> to channels like those. | |||
Any implementation of [IMessageChannel] has a [SendMessageAsync] | |||
@@ -21,7 +21,7 @@ There are few possible reasons why this may occur. | |||
bot account created from the Discord Developer portal, you should | |||
be using `TokenType.Bot`. | |||
2. You are not using the correct login credentials. Please keep in | |||
mind that tokens is **different** from a *client secret*. | |||
mind that a token is **different** from a *client secret*. | |||
[TokenType]: xref:Discord.TokenType | |||
[827]: https://github.com/RogueException/Discord.Net/issues/827 | |||
@@ -33,11 +33,11 @@ There are few possible reasons why this may occur. | |||
Your bot should **not** attempt to interact in any way with | |||
guilds/servers until the [Ready] event fires. When the bot | |||
connects, it first has to download guild information from | |||
Discord in order for you to get access to any server | |||
Discord for you to get access to any server | |||
information; the client is not ready at this point. | |||
Technically, the [GuildAvailable] event fires once the data for a | |||
particular guild has downloaded; however, it's best to wait for all | |||
particular guild has downloaded; however, it is best to wait for all | |||
guilds to be downloaded. Once all downloads are complete, the [Ready] | |||
event is triggered, then you can proceed to do whatever you like. | |||
@@ -46,7 +46,7 @@ event is triggered, then you can proceed to do whatever you like. | |||
## How do I get a message's previous content when that message is edited? | |||
If you need to do anything with messages (e.g. checking Reactions, | |||
If you need to do anything with messages (e.g., checking Reactions, | |||
checking the content of edited/deleted messages), you must set the | |||
[MessageCacheSize] in your [DiscordSocketConfig] settings in order to | |||
use the cached message entity. Read more about it [here](xref:Guides.Concepts.Events#cacheable). | |||
@@ -8,25 +8,27 @@ title: Beginner Questions / How to Get Started | |||
## How do I add my bot to my server/guild? | |||
You can do so by using the [permission calculator] provided | |||
by FiniteReality. | |||
This tool allows you to set the permissions that the bot will be | |||
added with, and invite the bot into your guild. With this method, | |||
bots will also be assigned their own special roles that normal users | |||
cannot use; this is what we call a `Managed` role, and this is a much | |||
safer method of permission management than to create a role that any | |||
users can be assigned to. | |||
by [FiniteReality]. | |||
This tool allows you to set permissions that the bot will be assigned | |||
with, and invite the bot into your guild. With this method, bots will | |||
also be assigned a unique role that a regular user cannot use; this | |||
is what we call a `Managed` role. Because you cannot assign this | |||
role to any other users, it is much safer than creating a single | |||
role which, intentionally or not, can be applied to other users | |||
to escalate their privilege. | |||
[FiniteReality]: https://github.com/FiniteReality/permissions-calculator | |||
[permission calculator]: https://finitereality.github.io/permissions-calculator | |||
## What is a token? | |||
A token is a credential used to log into an account. This information | |||
should be kept **private** and for your eyes only. Anyone with your | |||
token can log into your account. This applies to both user and bot | |||
accounts. That also means that you should never ever hardcode your | |||
token or add it into source control, as your identity may be stolen | |||
by scrape bots on the internet that scours through constantly to | |||
obtain a token. | |||
token can log into your account. This risk applies to both user | |||
and bot accounts. That also means that you should **never** hardcode | |||
your token or add it into source control, as your identity may be | |||
stolen by scrape bots on the internet that scours through | |||
constantly to obtain a token. | |||
## What is a client/user/object ID? | |||
@@ -5,37 +5,35 @@ title: Questions about Commands | |||
# Command-related Questions | |||
## How can I restrict some of my commands so only certain users can execute them? | |||
## How can I restrict some of my commands so only specific users can execute them? | |||
Based on how you want to implement the restrictions, you can use the | |||
built-in [RequireUserPermission] precondition, which allows you to | |||
restrict the command based on the user's current permissions in the | |||
guild or channel (*e.g. `GuildPermission.Administrator`, | |||
`ChannelPermission.ManageMessages` etc.*). | |||
guild or channel (*e.g., `GuildPermission.Administrator`, | |||
`ChannelPermission.ManageMessages`*). | |||
If, however, you wish to restrict the commands based on the user's | |||
role, you can either create your own custom precondition or use | |||
role, you can either create your custom precondition or use | |||
Joe4evr's [Preconditions Addons] that provides a few custom | |||
preconditions that aren't provided in the stock library. | |||
Its source can also be used as an example for creating your own | |||
Its source can also be used as an example for creating your | |||
custom preconditions. | |||
[RequireUserPermission]: xref:Discord.Commands.RequireUserPermissionAttribute | |||
[Preconditions Addons]: https://github.com/Joe4evr/Discord.Addons/tree/master/src/Discord.Addons.Preconditions | |||
## I'm getting an error about `Assembly#GetEntryAssembly`. | |||
## I am getting an error about `Assembly.GetEntryAssembly`. | |||
You may be confusing [CommandService#AddModulesAsync] with | |||
[CommandService#AddModuleAsync]. The former is used to add modules | |||
via the assembly, while the latter is used to add a single module. | |||
[CommandService#AddModulesAsync]: xref:Discord.Commands.CommandService.AddModulesAsync* | |||
[CommandService#AddModuleAsync]: xref:Discord.Commands.CommandService.AddModuleAsync* | |||
You may be confusing @Discord.Commands.CommandService.AddModulesAsync* | |||
with @Discord.Commands.CommandService.AddModuleAsync*. The former | |||
is used to add modules via the assembly, while the latter is used to | |||
add a single module. | |||
## What does [Remainder] do in the command signature? | |||
The [RemainderAttribute] leaves the string unparsed, meaning you | |||
don't have to add quotes around the text for the text to be | |||
do not have to add quotes around the text for the text to be | |||
recognized as a single object. Please note that if your method has | |||
multiple parameters, the remainder attribute can only be applied to | |||
the last parameter. | |||
@@ -47,13 +45,14 @@ the last parameter. | |||
## What is a service? Why does my module not hold any data after execution? | |||
In Discord.Net, modules are created similarly to ASP.NET, meaning | |||
that they have a transient nature. This means that they are spawned | |||
every time when a request is received, and are killed from memory | |||
when the execution finishes. This is why you cannot store persistent | |||
data inside a module. To workaround this, consider using a service. | |||
Service is often used to hold data externally, so that they will | |||
persist throughout execution. Think of it like a chest that holds | |||
that they have a transient nature; modules are spawned whenever a | |||
request is received, and are killed from memory when the execution | |||
finishes. In other words, you cannot store persistent | |||
data inside a module. Consider using a service if you wish to | |||
workaround this. | |||
Service is often used to hold data externally so that they persist | |||
throughout execution. Think of it like a chest that holds | |||
whatever you throw at it that won't be affected by anything unless | |||
you want it to. Note that you should also learn Microsoft's | |||
implementation of [Dependency Injection] \([video]) before proceeding, | |||
@@ -68,15 +67,23 @@ A brief example of service and dependency injection can be seen below. | |||
## I have a long-running Task in my command, and Discord.Net keeps saying that a `MessageReceived` handler is blocking the gateway. What gives? | |||
By default, all commands are executed on the same thread as the | |||
gateway task, which is responsible for keeping the connection from | |||
your client to Discord alive. When you execute a command, | |||
this blocks the gateway from communicating for as long as the command | |||
task is being executed. The library will warn you about any long | |||
running event handler (in this case, the command handler) that | |||
persists for **more than 3 seconds**. | |||
By default, the library warns the user about any long-running event | |||
handler that persists for **more than 3 seconds**. Any event | |||
handlers that are run on the same thread as the gateway task, the task | |||
in charge of keeping the connection alive, may block the processing of | |||
heartbeat, and thus terminating the connection. | |||
In this case, the library detects that a `MessageReceived` | |||
event handler is blocking the gateway thread. This warning is | |||
typically associated with the command handler as it listens for that | |||
particular event. If the command handler is blocking the thread, then | |||
this **might** mean that you have a long-running command (in rare | |||
cases, runtime errors can also cause blockage, usually associated | |||
with Mono, which is not supported by this library). | |||
To resolve this, the library has designed a flag called [RunMode]. | |||
To prevent a long-running command from blocking the gateway | |||
thread, a flag called [RunMode] is explicitly designed to resolve | |||
this issue. | |||
There are 2 main `RunMode`s. | |||
@@ -84,7 +91,7 @@ There are 2 main `RunMode`s. | |||
2. `RunMode.Async` | |||
You can set the `RunMode` either by specifying it individually via | |||
the `CommandAttribute`, or by setting the global default with | |||
the `CommandAttribute` or by setting the global default with | |||
the [DefaultRunMode] flag under `CommandServiceConfig`. | |||
# [CommandAttribute](#tab/cmdattrib) | |||
@@ -101,10 +108,9 @@ the [DefaultRunMode] flag under `CommandServiceConfig`. | |||
> [!IMPORTANT] | |||
> While specifying `RunMode.Async` allows the command to be spun off | |||
> to a different thread instead of the gateway thread, | |||
> keep in mind that there will be **potential consequences** | |||
> by doing so. Before applying this flag, please | |||
> consider whether it is necessary to do so. | |||
> to a different thread, keep in mind that by doing so, there will be | |||
> **potentially unwanted consequences**. Before applying this flag, | |||
> please consider whether it is necessary to do so. | |||
> | |||
> Further details regarding `RunMode.Async` can be found below. | |||
@@ -115,16 +121,15 @@ the [DefaultRunMode] flag under `CommandServiceConfig`. | |||
## How does `RunMode.Async` work, and why is Discord.Net *not* using it by default? | |||
`RunMode.Async` works by spawning a new `Task` with an unawaited | |||
[Task.Run], essentially making `ExecuteAsyncInternalAsync`, the task | |||
that is used to invoke the command task, to be finished on a | |||
different thread. This means that [ExecuteAsync] will be forced to | |||
return a successful [ExecuteResult] regardless of the actual | |||
execution result. | |||
[Task.Run], essentially making the task that is used to invoke the | |||
command task to be finished on a different thread. This design means | |||
that [ExecuteAsync] will be forced to return a successful | |||
[ExecuteResult] regardless of the actual execution result. | |||
The following are the known caveats with `RunMode.Async`, | |||
1. You can potentially introduce race condition. | |||
2. Unnecessary overhead caused by [async state machine]. | |||
1. You can potentially introduce a race condition. | |||
2. Unnecessary overhead caused by the [async state machine]. | |||
3. [ExecuteAsync] will immediately return [ExecuteResult] instead of | |||
other result types (this is particularly important for those who wish | |||
to utilize [RuntimeResult] in 2.0). | |||
@@ -16,5 +16,5 @@ public Task EchoAsync(string text) => ReplyAsync(text); | |||
// Wrapping the message in quotes solves this. | |||
// This way, the system knows the entire message is to be parsed as a | |||
// single String. | |||
// e.g. | |||
// e.g., | |||
// !echo "Coffee Cake" |
@@ -7,8 +7,8 @@ title: Questions about Legacy Versions | |||
## X, Y, Z does not work! It doesn't return a valid value anymore | |||
If you're currently using an older version in stable branch, please | |||
upgrade to the latest pre-release version to ensure maximum | |||
If you are currently using an older version of the stable branch, | |||
please upgrade to the latest pre-release version to ensure maximum | |||
compatibility. Several features may be broken in older | |||
versions and will likely not be fixed in the version branch due to | |||
their breaking nature. | |||
@@ -107,7 +107,7 @@ be found in @Guides.Commands.TypeReaders. | |||
#### Optional Parameters | |||
Parameters, by default, are always required. To make a parameter | |||
optional, give it a default value (i.e. `int num = 0`). | |||
optional, give it a default value (i.e., `int num = 0`). | |||
#### Parameters with Spaces | |||
@@ -6,18 +6,18 @@ title: Post-command Execution Handling | |||
# Preface | |||
When developing commands, you may want to consider building a | |||
post-execution handling system so you can have a finer control | |||
post-execution handling system so you can have finer control | |||
over commands. Discord.Net offers several post-execution workflows | |||
for you to work with. | |||
If you recall, in the [Command Guide], we've shown the following | |||
If you recall, in the [Command Guide], we have shown the following | |||
example for executing and handling commands, | |||
[!code[Command Handler](samples/command_handler.cs)] | |||
You may notice that after we perform [ExecuteAsync], we store the | |||
result and print it to the chat. This is essentially the most | |||
basic post-execution handling. | |||
result and print it to the chat, essentially creating the most | |||
fundamental form of a post-execution handler. | |||
With this in mind, we could start doing things like the following, | |||
@@ -25,8 +25,8 @@ With this in mind, we could start doing things like the following, | |||
However, this may not always be preferred, because you are | |||
creating your post-execution logic *with* the essential command | |||
handler. This could lead to messy code and could potentially be a | |||
violation of the SRP (Single Responsibility Principle). | |||
handler. This design could lead to messy code and could potentially | |||
be a violation of the SRP (Single Responsibility Principle). | |||
Another major issue is if your command is marked with | |||
`RunMode.Async`, [ExecuteAsync] will **always** return a successful | |||
@@ -37,8 +37,8 @@ about the impact in the [FAQ](xref:FAQ.Commands). | |||
Enter [CommandExecuted], an event that was introduced in | |||
Discord.Net 2.0. This event is raised whenever a command is | |||
successfully executed **without any run-time exceptions** or **without | |||
any parsing or precondition failure**. This means this event can be | |||
successfully executed **without any run-time exceptions** or **any | |||
parsing or precondition failure**. This means this event can be | |||
used to streamline your post-execution design, and the best thing | |||
about this event is that it is not prone to `RunMode.Async`'s | |||
[ExecuteAsync] drawbacks. | |||
@@ -52,7 +52,7 @@ next? We can take this further by using [RuntimeResult]. | |||
### RuntimeResult | |||
`RuntimeResult` was originally introduced in 1.0 to allow | |||
`RuntimeResult` was initially introduced in 1.0 to allow | |||
developers to centralize their command result logic. | |||
In other words, it is a result type that is designed to be | |||
returned when the command has finished its execution. | |||
@@ -62,7 +62,7 @@ However, it wasn't widely adopted due to the aforementioned | |||
result-handler via the [CommandExecuted] event, we can start | |||
making use of this class. | |||
The best way to make use of it is to create your own version of | |||
The best way to make use of it is to create your version of | |||
`RuntimeResult`. You can achieve this by inheriting the `RuntimeResult` | |||
class. | |||
@@ -71,16 +71,16 @@ of `RuntimeResult`, | |||
[!code[Base Use](samples/customresult_base.cs)] | |||
The sky's the limit from here. You can add any additional information | |||
you'd like regarding the execution result. | |||
The sky is the limit from here. You can add any additional information | |||
you would like regarding the execution result. | |||
For example, you may want to add your own result type or other | |||
For example, you may want to add your result type or other | |||
helpful information regarding the execution, or something | |||
simple like static methods to help you create return types easily. | |||
[!code[Extended Use](samples/customresult_extended.cs)] | |||
After you're done creating your own [RuntimeResult], you can | |||
After you're done creating your [RuntimeResult], you can | |||
implement it in your command by marking the command return type to | |||
`Task<RuntimeResult>`. | |||
@@ -100,12 +100,12 @@ And now we can check for it in our [CommandExecuted] handler: | |||
## CommandService.Log Event | |||
We have so far covered the handling of various result types, but we | |||
haven't talked about what to do if the command enters a catastrophic | |||
failure (i.e. exceptions). To resolve this, we can make use of the | |||
have not talked about what to do if the command enters a catastrophic | |||
failure (i.e., exceptions). To resolve this, we can make use of the | |||
[CommandService.Log] event. | |||
All exceptions thrown during a command execution will be caught and | |||
be sent to the Log event under the [LogMessage.Exception] property | |||
All exceptions thrown during a command execution are caught and sent | |||
to the Log event under the [LogMessage.Exception] property | |||
as a [CommandException] type. The [CommandException] class allows | |||
us to access the exception thrown, as well as the context | |||
of the command. | |||
@@ -11,14 +11,14 @@ stopped. | |||
To start a connection, invoke the `StartAsync` method on a client that | |||
supports a WebSocket connection; to end a connection, invoke the | |||
`StopAsync` method. This will gracefully close any open WebSocket or | |||
`StopAsync` method, which gracefully closes any open WebSocket or | |||
UdpSocket connections. | |||
Since the Start/Stop methods only signal to an underlying connection | |||
manager that a connection needs to be started, **they return before a | |||
connection is actually made.** | |||
connection is made.** | |||
As a result, you will need to hook into one of the connection-state | |||
As a result, you need to hook into one of the connection-state | |||
based events to have an accurate representation of when a client is | |||
ready for use. | |||
@@ -29,7 +29,7 @@ ready to be used. | |||
A separate event, `Ready`, is provided on [DiscordSocketClient], which | |||
is raised only when the client has finished guild stream or guild | |||
sync, and has a complete guild cache. | |||
sync and has a completed guild cache. | |||
[DiscordSocketClient]: xref:Discord.WebSocket.DiscordSocketClient | |||
@@ -41,8 +41,8 @@ sync, and has a complete guild cache. | |||
> [!TIP] | |||
> Avoid running long-running code on the gateway! If you deadlock the | |||
> gateway (as explained in [events]), the connection manager will be | |||
> unable to recover and reconnect. | |||
> gateway (as explained in [events]), the connection manager will | |||
> **NOT** be able to recover and reconnect. | |||
Assuming the client disconnected because of a fault on Discord's end, | |||
and not a deadlock on your end, we will always attempt to reconnect | |||
@@ -50,6 +50,6 @@ and resume a connection. | |||
Don't worry about trying to maintain your own connections, the | |||
connection manager is designed to be bulletproof and never fail - if | |||
your client doesn't manage to reconnect, you've found a bug! | |||
your client does not manage to reconnect, you have found a bug! | |||
[events]: xref:Guides.Concepts.Events |
@@ -68,7 +68,7 @@ for use on another machine without installing the dependencies first. | |||
This can be achieved by using the dotnet CLI too on the development | |||
machine: | |||
`dotnet publish -c Release` | |||
* `dotnet publish -c Release` | |||
Additionally, you may want to target a specific platform when | |||
publishing the application so you may use the application without | |||
@@ -80,7 +80,7 @@ For example, when targeting a Windows 10 machine, you may want to use | |||
the following to create the application in Windows executable | |||
format (.exe): | |||
`dotnet publish -c Release -r win10-x64` | |||
* `dotnet publish -c Release -r win10-x64` | |||
[.NET Core application deployment]: https://docs.microsoft.com/en-us/dotnet/core/deploying/ | |||
[Runtime ID]: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog |
@@ -56,7 +56,7 @@ DiscordSocketClient. | |||
> [FAQ](xref:FAQ.Basics.GetStarted) page. | |||
More detailed versions of entities can be pulled from the basic | |||
entities, e.g. `SocketGuild.GetUser`, which returns a | |||
entities, e.g., `SocketGuild.GetUser`, which returns a | |||
`SocketGuildUser`, or `SocketGuild.GetChannel`, which returns a | |||
`SocketGuildChannel`. Again, you may need to cast these objects to get | |||
a variant of the type that you need. | |||
@@ -74,7 +74,7 @@ object. | |||
[Cacheable]: xref:Discord.Cacheable`2 | |||
> [!NOTE] | |||
> Many events relating to a Message entity (i.e. `MessageUpdated` and | |||
> Many events relating to a Message entity (i.e., `MessageUpdated` and | |||
> `ReactionAdded`) rely on the client's message cache, which is | |||
> **not** enabled by default. Set the `MessageCacheSize` flag in | |||
> @Discord.WebSocket.DiscordSocketConfig to enable it. | |||
@@ -16,7 +16,7 @@ section. | |||
> [!WARNING] | |||
> Due to the nature of Discord.Net's event system, all log event | |||
> handlers will be executed synchronously on the gateway thread. If your | |||
> log output will be dumped to a Web API (e.g. Sentry), you are advised | |||
> log output will be dumped to a Web API (e.g., Sentry), you are advised | |||
> to wrap your output in a `Task.Run` so the gateway thread does not | |||
> become blocked while waiting for logging data to be written. | |||
@@ -28,13 +28,13 @@ addon will run on all platforms. | |||
`Discord.Net.Rest` provides a set of concrete classes to be used | |||
**strictly** with the REST portion of Discord's API. Entities in 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's RPC API. Entities in this implementation are prefixed | |||
with `Rpc` (e.g. `RpcChannel`). | |||
with `Rpc` (e.g., `RpcChannel`). | |||
`Discord.Net.WebSocket` provides a set of concrete classes that are | |||
used primarily with Discord's WebSocket API or entities that are kept | |||
in cache. When developing bots, you will be using this implementation. | |||
All entities are prefixed with `Socket` (e.g. `SocketChannel`). | |||
All entities are prefixed with `Socket` (e.g., `SocketChannel`). |