Discord Bot Framework
Tags: tutorial, typescript
Published: 2021-07-04 21:50:16

In this post I am going to be explaining the fully extensible discord bot built using [DiscordJs](https://discord.js.org/#/). I am going to skip the part where you connect the bot to a discord server because this is explained in many other discord related blog postings. I will be running through and explaining the core files of the project.

## Launcher

```
const main = () => {
  const prisma = new PrismaClient();
  const client = new Client();
  const control = new CommandControl(client, prisma);

  client.once(Constants.Events.CLIENT_READY, () => {
    prisma
      .$connect()
      .then(() => console.log("Prisma Connected"))
      .finally(() => console.log("Application Ready"));
  });

  client.on(Constants.Events.DISCONNECT, () => {
    prisma
      .$disconnect()
      .then(() => console.log("Prisma Disconnected"))
      .finally(() => console.log("Application Disconnected"));
  });

  client.on(Constants.Events.MESSAGE_CREATE, (message) => {
    control.handleMessage(message);
  });

  client.login(process.env.Bot_Token);
};

main();
```

This project relies heavily on typescript to keep writing consistent. Important variables to note are the `client` and `control`. All commands come in as Messages and are handled when the message event is listened to. If you are unfamiliar with the `EventListener` in node check out this [link](https://nodejs.org/api/events.html).

## CommandControl

This class delegates all commands to their respective handlers.

```
 handleMessage(message: Message) {
    if (this.isAdmissableMessage(message)) {
      const command = this.parseForCommand(message);
      switch (command) {
        case UserEconomyCmds.LIST:
          this.Economy.listCommands(message);
          break;
        case UserEconomyCmds.CREATE_WALLET:
          this.Economy.createCommand(message);
          break;
        case UserEconomyCmds.BALANCE:
          this.Economy.balanceCommand(message);
          break;
        case UserEconomyCmds.MERCHANDISE:
          this.Economy.getMerchandiseCommand(message);
          break;
        case UserEconomyCmds.POSSESSIONS:
          this.Economy.getPossessionsCommand(message);
          break;
        case UserEconomyCmds.PURCHASE:
          break;
        case AdminEconomyCmds.SUMMARY:
          this.Economy.summaryWalletCommand(message);
          break;
        default:
          console.log(command);
      }
    }
  }
```

This is just an example so is already populated with optional commands. Firstly, `isAdmissableMessage` checks to make sure that the message the bot is listening to is going into a guild channel, not coming from the bot, starts with the command prefix, and is coming from a member of the guild. Secondly, the message is parsed to get the string connected to prefix, optimistically that is one of the commands being handled, but if it is not then it is ignored.

## Utils

The only util as of this moment is a parser that ensures consistency oin the command format. I wanted to make a bot that accepted commands similar to a cli and `parser.ts` is what holds all this. There are three functions in the file, `parseForArguments`, `hasAdminPermission`, and `argumentsFulfilled`. These functions ensure that the message comes in like cli arguments.

Here is an example of a proper command: `$deposit amount=10 @person`.

### parseForArguments

The message is split based on the spaces. The function accepts an array of strings that will function as the keys that are searched for in each of the strings in the newly made array. When in the key is found then the string is split again based on the "=" and returns the second part, optimistically that would be the correct variable. The function also accepts a boolean indicating whether the command requires a mention. The mention is for commands where you need to identify a specific guild member.

### argumentsFulfilled

This function accepts the same array of strings that are keys for the command. This function makes sure that each one of those keys is returned from the parseForArguments function.

## Cogs

This directory would be where you can add aspects into the bot. For example, I started an Economy cog with the class Economy which has a method handling each of the accepted commands.

## Github

[Space-Invader-Bot](https://github.com/Ces-D/Space-Invader-Bot)