| @@ -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`). | |||