| @@ -5,10 +5,10 @@ title: Post-command Execution Handling | |||||
| # Preface | # Preface | ||||
| When developing a command system or modules, you may want to consider | |||||
| building a post-execution handling system so you can have a finer | |||||
| control over commands. Discord.Net offers several different | |||||
| post-execution workflow for you to work with. | |||||
| When developing commands, you may want to consider building a | |||||
| post-execution handling system so you can have a 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've shown the following | ||||
| example for executing and handling commands, | example for executing and handling commands, | ||||
| @@ -17,27 +17,27 @@ example for executing and handling commands, | |||||
| You may notice that after we perform [ExecuteAsync], we store the | You may notice that after we perform [ExecuteAsync], we store the | ||||
| result and print it to the chat. This is essentially the most | result and print it to the chat. This is essentially the most | ||||
| basic post-execution handling. With this in mind, we could start doing | |||||
| things like the following, | |||||
| basic post-execution handling. | |||||
| With this in mind, we could start doing things like the following, | |||||
| [!code[Basic Command Handler](samples/post-execution_basic.cs)] | [!code[Basic Command Handler](samples/post-execution_basic.cs)] | ||||
| **But!** This may not always be preferred, because you are | |||||
| However, this may not always be preferred, because you are | |||||
| creating your post-execution logic *with* the essential command | creating your post-execution logic *with* the essential command | ||||
| handler. This could lead to messy code and has another potential | |||||
| issue, working with `RunMode.Async`. | |||||
| handler. This could lead to messy code and could potentially be a | |||||
| violation of the SRP (Single Responsibility Principle). | |||||
| If your command is marked with `RunMode.Async`, [ExecuteAsync] will | |||||
| **always** return a successful [ExecuteResult] instead of whatever | |||||
| results the actual command may return. Because of the way | |||||
| `RunMode.Async` [works](xref:FAQ.Commands), handling within the | |||||
| command handler may not always achieve the desired effect. | |||||
| Another major issue is if your command is marked with | |||||
| `RunMode.Async`, [ExecuteAsync] will **always** return a successful | |||||
| [ExecuteResult] instead of the actual result. You can learn more | |||||
| about the impact in the [FAQ](xref:FAQ.Commands). | |||||
| ## CommandExecuted Event | ## CommandExecuted Event | ||||
| Enter [CommandExecuted], an event that was introduced in | Enter [CommandExecuted], an event that was introduced in | ||||
| Discord.Net 2.0. This event is raised when the command is | |||||
| sucessfully executed **without any runtime exceptions** or **without | |||||
| 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 | any parsing or precondition failure**. This means this event can be | ||||
| used to streamline your post-execution design, and the best thing | used to streamline your post-execution design, and the best thing | ||||
| about this event is that it is not prone to `RunMode.Async`'s | about this event is that it is not prone to `RunMode.Async`'s | ||||
| @@ -53,35 +53,39 @@ next? We can take this further by using [RuntimeResult]. | |||||
| ### RuntimeResult | ### RuntimeResult | ||||
| This class was introduced in 1.0, but it wasn't widely adopted due to | This class was introduced in 1.0, but it wasn't widely adopted due to | ||||
| the previously mentioned [ExecuteAsync] drawback. Since we now have | |||||
| access to proper result handling via the [CommandExecuted] event, | |||||
| the aforementioned [ExecuteAsync] drawback. Since we now have | |||||
| access to a proper result-handler via the [CommandExecuted] event, | |||||
| we can start making use of this class. | we can start making use of this class. | ||||
| #### What is it? | #### What is it? | ||||
| `RuntimeResult` was introduced to allow developers to centralize | `RuntimeResult` was introduced to allow developers to centralize | ||||
| their command result logic. It is a result type that is designed to | |||||
| be returned when the command has finished its logic. | |||||
| 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. | |||||
| #### How to make use of it? | #### How to make use of it? | ||||
| 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 own version of | ||||
| `RuntimeResult`. You can achieve this by inheriting the `RuntimeResult` | `RuntimeResult`. You can achieve this by inheriting the `RuntimeResult` | ||||
| class. The following creates a bare-minimum for a sub-class | |||||
| class. | |||||
| The following creates a bare-minimum required for a sub-class | |||||
| of `RuntimeResult`, | of `RuntimeResult`, | ||||
| [!code[Base Use](samples/customresult_base.cs)] | [!code[Base Use](samples/customresult_base.cs)] | ||||
| The sky's the limit from here. You can add any additional information | The sky's the limit from here. You can add any additional information | ||||
| you'd like regarding the execution result. For example, you may | |||||
| want to add your own result type or other helpful information | |||||
| regarding the execution, or something simple like static methods to | |||||
| help you create return types easily. | |||||
| you'd like regarding the execution result. | |||||
| For example, you may want to add your own 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)] | [!code[Extended Use](samples/customresult_extended.cs)] | ||||
| After you're done creating your own [RuntimeResult], you can | After you're done creating your own [RuntimeResult], you can | ||||
| implement it in your command by marking its return type to | |||||
| implement it in your command by marking the command return type to | |||||
| `Task<RuntimeResult>`. | `Task<RuntimeResult>`. | ||||
| > [!NOTE] | > [!NOTE] | ||||
| @@ -105,9 +109,10 @@ failure (i.e. exceptions). To resolve this, we can make use of the | |||||
| [CommandService.Log] event. | [CommandService.Log] event. | ||||
| All exceptions thrown during a command execution will be caught and | All exceptions thrown during a command execution will be 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. | |||||
| be 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. | |||||
| [!code[Logger Sample](samples/command_exception_log.cs)] | [!code[Logger Sample](samples/command_exception_log.cs)] | ||||