Designing Commands - ShindouMihou/Nexus GitHub Wiki
Caution
Before we dive in, when using Nexus, it's advised to avoid employing the
event.interaction.respondLater()
methods provided by Javacord. This is due to the special handling of middleware in Nexus, which necessitates coordination between the command and middleware. Instead, it's recommended to useevent.respondLater()
orevent.respondLaterAsEphemeral()
.An even more streamlined option is auto-deferring, which takes care of these scenarios for you. To learn more, refer to Auto-deferring Commands.
Designing commands within Nexus is straightforward and elegant. However, before we delve into command design, it's essential to grasp some foundational guidelines that Nexus enforces:
- Commands must have distinct names. If you need to reuse a name, you can modify one of the commands with the
@IdentifiableAs
annotation for indexing purposes. - You must implement the
NexusHandler
interface for the command to be recognized by the engine. - Each command must include a name and description field, as Discord requires.
With these principles in mind, you can begin crafting a command by creating a class that implements the NexusHandler
interface:
object PingCommand: NexusHandler {
override fun onEvent(event: NexusCommandEvent) {
// Command logic will be added here
}
}
However, this alone won't suffice. To make it a recognized command, you need to provide the name
and description
fields:
object PingCommand: NexusHandler {
val name: String = "ping"
val description: String = "Ping, Pong!"
override fun onEvent(event: NexusCommandEvent) {
// Command logic will be added here
}
}
This simple structure creates a basic command. Let's delve deeper and add some functionality:
object PingCommand: NexusHandler {
val name: String = "ping"
val description: String = "Ping, Pong!"
override fun onEvent(event: NexusCommandEvent) {
val server = event.server.orElseThrow()
// Nexus provides two response options: auto-deferring and manual response.
// The example here demonstrates auto-deferred responses.
event.autoDefer(ephemeral = false) {
return@autoDefer NexusMessage.from("Hello ${server.name}")
}
// Alternatively, you can manually respond like this:
// event.respondNowWith("Hello ${server.name}!")
}
}
At this point, the command responds with a simple message like "Hello {server}!" However, there's a challenge: we can't ensure that it's executed within a server context. Not to worry, Nexus has a solution in the form of middlewares and afterwares, concepts commonly found in many web frameworks. Read more about this solution in Command Interceptors (middleware, afterware).
For more information about what properties to override, refer to:
Reactivity for Kotlin
In addition to the above-shown methods, Kotlin developers can enjoy a greater developer-experience in developing reactive, or highly-interactive bots using our newest rendering mechanism: Nexus.R. We recommend using it for developers who are more familiar with web development.
Auto-deferring Commands
Nexus introduces support for auto-deferring responses in both middlewares and commands. However, it's important to understand the context of slash commands in Nexus, specifically the three-second response requirement before deferring. There are two primary aspects within Nexus that can potentially impact this three-second requirement:
- Middlewares
- The command itself
To address the uncertainty about which aspect exactly triggers auto-deferring, Nexus introduces auto-deferring. However, enabling this feature requires you to enable auto-deferring in both middlewares and the command itself.
To activate auto-deferring in middlewares, please refer to the Deferred Middleware Responses section.
For enabling auto-deferring in commands, utilize the event.autoDefer(ephemeral, function)
method instead of other related methods. It's advisable to use this method, particularly when you have long-running middlewares, as it comprehensively handles cases where a middleware requests deferred responses.
Here's how to implement auto-deferring in commands:
override fun onEvent(event: NexusCommandEvent) {
event.autoDefer(ephemeral = true) {
// ... imagine a long-running task
return@autoDefer NexusMessage.from("Hello")
}
}
If you want to receive the response from Discord, you can do so by handling the response of the autoDefer
method:
override fun onEvent(event: NexusCommandEvent) {
event.autoDefer(ephemeral = true) {
// ... imagine a long-running task
return@autoDefer NexusMessage.with {
setContent("Hello!")
}
}.thenAccept { response ->
// The updater is only available if the message was processed through deferred response.
val updater = response.updater
// Using `getOrRequestMessage` calls `InteractionOriginalResponseUpdater.update()` if the interaction was
// answered without deferring. This is necessary because Javacord or Discord doesn't offer immediate access
// to the actual message from the response.
val message = response.getOrRequestMessage()
}
}
To configure the duration before auto-deferring triggers, you can modify the following setting:
// Default value
Nexus.configuration.global.autoDeferAfterMilliseconds = 2350
This setting controls the time delay, ensuring that auto-deferring only occurs after the specified duration.