Skip to content

Commands and storage

tostc edited this page Dec 31, 2020 · 2 revisions

Overview

In this chapter we make a deep dive into commands. We also learn how configurations, which are made with commands can be stored.

Let's get started

First things first I will use ! as command prefix inside this chapter, so don't be confused if you see something like !COMMAND.

ICommand interface

In chapter 1. Your first bot we've learned how to create a basic Hello World! command, which prints always Hello World! in the chat if you call the command !hello. As shown in chapter 1. every command must inherited from the interface ICommand, which contains a part of the routing logic used by the library, but later more. To register a new route inside the command you need to call RegisterCommandHandler which takes two parameters first the command name and second the method to call. This associates a command with a the method. The signature of each single command is void(CCommandContext), where CCommandContext contains the raw message, the command name and the parameters for a command.

Routing

As mentioned above all commands are registered as routes. Every route can contain meta information over the route like the name or the description, but there are many other information which you can find here. As mentioned above you must register the route inside the command, but also at the controller with RegisterCommand<T>(SCommandDescription Desc, Args ... args). The first parameter contains the meta description and the second one the parameters which should be passed to the constructor of the command. The template parameter is by the way the command type. With the meta descriptor it's also possible to protect a command from users to use. There are currently following modes for a command:

Values Descriptions
OWNER This command can only be accessed by the owner.
ROLE This command can only be accessed by a given role.
EVERYBODY Free for all.

Internals

"But how the routing now works under the hood?" - You might ask yourself. Everytime a user sends a message inside a text channel the controller interface OnMessage is called. Inside this method happens the magic. Ok it's not directly magic, but more a simple check if the message begins with the prefix and if the sended command known. If the command is known, then the meta descriptor is loaded, a check is executed, if the user has the rights to call this command. Now the parameters will be parsed and a new command instance is created. So every command is running inside it's own environment. Now the OnExecute of the command instance is called and this will call the command method. And that's all.

Builtin commands

By the way there are several builtin commands, which manages thinks like command role assignment or the server prefix. You can print all of them with the builtin !help command. These commands can theoretically be overridden by calling RegisterCommand of the controller again with the same name, but I think I should implement an override command method or something like that. 😄

Storage

The library comes with a builtin solution to store data of commands like the set role command to manage the access of roles. But the builtin solution is not recommend for production or for a large amount of servers. This solution save all data as json files, inside the application directory. But you can implement your own solution with the ICommandsConfig interface. You must only assign an instance of your implementation to the CmdsConfig member of the controller.