Build a Discord command bot in minutes with Appwrite Cloud Functions

Deborah Emeni - Nov 29 '23 - - Dev Community

If you’re a developer looking for a secure and efficient solution to build your Discord bots rapidly, then you’ve come to the right place. In this article, we’ll discuss an excellent tool that you can use to suit your needs called Appwrite Functions.

Appwrite Functions is a feature provided by Appwrite that enables developers to create and automatically run custom backend code in response to events triggered by Appwrite or according to a predefined schedule. With Appwrite Functions, you can access several benefits, including scalability and enhanced security.

Why use a template for your Discord bots? Templates save time and effort by providing pre-built code for custom commands and features. Appwrite Functions offers a Discord command bot template, simplifying the development process. You can customize the template to meet your needs and seamlessly integrate unique functionalities.

This tutorial will walk you through the process of building your Discord command bot in minutes using Appwrite Functions.

So, without further ado, let's dive in!

Prerequisites

Ensure that you have the following to follow along with the tutorial:

Creating your Appwrite project

Log into your Appwrite Cloud account and create your Appwrite project to gain access to Appwrite's services. You’ll also gain access to your project ID and API key, which are required for using the Appwrite SDK. Set a name for your project, such as 'Discord Command Bot,' and then click the Create Project button:

Creating your Appwrite Project

Creating an Appwrite Function with the Discord command bot template

Here, we’ll easily create an Appwrite Function to automate your backend tasks and extend Appwrite with custom code.

Navigate to the side menu on your project dashboard and click on Functions to access the template:

Opening Functions in Appwrite

Click on the Templates tab on the Functions page:

Opening Templates

Search for the Discord Command Bot template in the Search templates box as follows:

Click the Create function button:

Select Node.js-18.0 as the runtime for your discord command bot and click Next:

Before you proceed, you’ll need to retrieve several values from your Discord Developer Portal, namely the public key, ID, and Bot token of your application in your Discord Developer Portal. They will serve as the values for the environment variables passed to your function at runtime.

On your Discord Developer Portal, click on New Application:

Enter the name of your application and click on the Create button:

Once you do that, your application ID and public key will be generated. Copy both of them:

Then, go back to your Functions in Appwrite and paste your copied Application ID and Public key as the values of your environment variables that will be passed to your function at runtime:

Go back to your Discord Developer Portal to get your DISCORD_TOKEN variable, and on the slide menu, click on Bot, then click on the Reset Token button:

Once you do that, you’ll see the following message: click Yes, do it!

Once you do that, you’ll get a 6-digit authentication code in your 2FA authentication app or whichever verification method you use. After entering the 2FA code, click on Submit:

Once you do that, your token will be generated. Click the Copy button to copy your token:

Go back to your Appwrite Functions, paste your copied token as the value for your DISCORD_TOKEN variable, and click the Next button:

This will take you to the next step of connecting your function to a new repository or an existing one within a selected Git organization. Select Create a new repository and click Next:

You need to select a Git repository that will trigger your function deployments when updated. Choose GitHub from the options and click Next:

Grant Appwrite permission to your GitHub account by clicking the Install & Authorize button:

Once that is done, you will be redirected to Appwrite to continue your installation. Now that Appwrite has access to your GitHub, you can go back to choose the Create a new repository option, and this time, you will see the following:

As you can see, a discord-command-bot repository has been automatically created for you. You can change the repository name if you so choose. You can leave your repository private and click Next. Afterward, your repository will be successfully created.

Next, name your production branch or leave it as main, then click the Create button:

Once you do that, you will see an alert saying that your Discord Command Bot has been created:

Your deployment will automatically display the deployment ID, build time, size, source, and link to your domains. Copy the link to your domains:

Configuring an interactions endpoint for your app

Go back to your Discord developer portal from your side menu, click on General Information, and scroll down to the Interactions Endpoint URL to configure an interactions endpoint to receive interactions via HTTP POSTs rather than over Gateway with a bot user:

Paste the link to your domains that you copied to configure an interactions endpoint by adding the https:// in front of it and the “interactions” endpoint at the end. Your link should look like this: https://[your domains]/interactions. Afterward, ensure that you save your changes by clicking the Save Changes button:

Generating an invite link for your app

Next, generate an invite link for your application by picking the scopes and permissions it needs to function. To do this, go to OAuth2 on the side menu, and in the dropdown menu, click on URL Generator. From the SCOPES section, select bot:

Under the Bot Permissions section, select Administrator:

Once you select your scope and bot permissions, a URL will be generated. Scroll down to the bottom of the page and click the Copy button to copy your generated URL:

Adding your application to your Discord server

Go to your favorite browser and paste the URL in the search bar. This will open Discord with a message telling you that an external application wants to access your Discord account with information about what you are permitted to do, which includes adding a bot to a server and creating a command. Remember to have a server created and ready to go.

Select the server that you would like to add from your list of servers and click the Continue button:

Grant administrator permission to your server and click the Authorize button:

Once you do that, you’ll be required to confirm that you are not a robot:

Once you’ve been verified, your application will be successfully authorized and added to the server you created on Discord. Click on the Go to Appwrite Bot Server button to go to your server:

This will take you to your server on Discord:

Now, you can add commands to your Discord command bot using Appwrite functions.

Customizing the template by adding Commands to your Discord command bot

With the Discord command template provided by Appwrite functions, you have access to a variety of customization options. You can do the following:

  • Add, remove, or modify commands.
  • Customize the responses of the Discord bot to commands.
  • Set permissions for who can use the commands.
  • Register the Discord bot to listen for and respond to Discord events, including reactions when a member leaves the Discord server or messages.

Not only do you have access to several customization options, but you also benefit from the speed that the Discord command bot template provides. For instance, instead of spending time developing the Discord bot from scratch, the Discord command bot template offers you a pre-built foundation with code that you can use to get started quickly. If you want to add more features to your discord bot, such as commands, you can easily customize the template by creating a new function and registering it with the Discord bot.

Let’s see this in action by customizing the template by adding a command to your Discord server that tells jokes.

In your Discord command bot GitHub repository, you have a setup.js file that registers the command on Discord by defining a name and description for the command. By default, the template already registers a “Hello World Command”.

Here’s the link to the complete source code.

Let’s create another command by registering the command in the setup.js file. Modify the code in your setup.js file with the following:

    import { fetch } from 'undici';
    import { throwIfMissing } from './utils.js';
    async function setup() {
      throwIfMissing(process.env, [
        'DISCORD_PUBLIC_KEY',
        'DISCORD_APPLICATION_ID',
        'DISCORD_TOKEN',
      ]);
      const registerApi = `https://discord.com/api/v9/applications/${process.env.DISCORD_APPLICATION_ID}/commands`;
      const commands = [
        {
          name: "hello",
          description: "Hello World Command"
        },
        {
          name: "jokes",
          description: "Tell a random joke"
        }
      ]

      const responses = await Promise.all(commands.map((command) => {
        return fetch(registerApi, {
          method: 'POST',
          headers: {
            Authorization: `Bot ${process.env.DISCORD_TOKEN}`,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(command),
        });
      }))
      if (responses.some((response) => !response.ok)) {
        throw new Error('Failed to register command');
      }
      console.log('Command registered successfully');
    }
    setup();
Enter fullscreen mode Exit fullscreen mode

Here’s a detailed explanation of what this code does:

  • The throwIfMissing() function checks if the environment variables that you set in your Appwrite function exist — here, this will include your DISCORD_PUBLIC_KEY, DISCORD_APPLICATION_ID, and DISCORD_TOKEN.
  • The registerApi saves the URL to add the command to the Discord bot.
  • The commands variable is an array of the commands you want to add to Discord.
  • The responses variable stores the response from Discord after a request is made to register the command on your Discord server. If it fails, it throws an error; if it is successful, it logs a message to the console saying, “Command registered successfully.”

Next, go to the main.js file, which contains the code that handles the request to add a command to Discord and modify the code with the following:


    import {
      InteractionResponseType,
      InteractionType,
      verifyKey,
    } from 'discord-interactions';
    import { throwIfMissing } from './utils.js';
    export default async ({ req, res, error, log }) => {
      throwIfMissing(process.env, [
        'DISCORD_PUBLIC_KEY',
        'DISCORD_APPLICATION_ID',
        'DISCORD_TOKEN',
      ]);
      if (
        !verifyKey(
          req.bodyRaw,
          req.headers['x-signature-ed25519'],
          req.headers['x-signature-timestamp'],
          process.env.DISCORD_PUBLIC_KEY
        )
      ) {
        error('Invalid request.');
        return res.json({ error: 'Invalid request signature' }, 401);
      }
      log('Valid request');
      const interaction = req.body;
      if (
        interaction.type === InteractionType.APPLICATION_COMMAND &&
        interaction.data.name === 'hello'
      ) {
        log('Matched hello command - returning message');
        return res.json(
          {
            type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
            data: {
              content: 'Hello, World!',
            },
          },
          200
        );
      }
       if (
        interaction.type === InteractionType.APPLICATION_COMMAND &&
        interaction.data.name === 'jokes'
      ) {
        log('Matched jokes command - returning message');
        const response = await fetch("https://v2.jokeapi.dev/joke/Any?type=twopart");
        const data = await response.json();
        return res.json(
          {
            type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
            data: {
              content: `${data.setup} ---------- ${data.delivery}`,
            },
          },
          200
        );
      }
      log("Didn't match command - returning PONG");
      return res.json({ type: InteractionResponseType.PONG }, 200);
    };
Enter fullscreen mode Exit fullscreen mode

The code does the following:

  • It verifies the data coming from the Discord server.
  • It gets the name of the registered command, and it responds with the appropriate data.

After customizing the template, commit your changes and push them to GitHub.

Once you commit and push your changes, your building process will start, and your code will be deployed on Appwrite. Go to your Appwrite Functions and click on the Deployments tab; you will see your build time and other information.

Scroll down on your Deployments tab to see the status of your deployment:

Finally, you can test this out to see if your command was successfully added to your Discord server by going to your discord server and typing “/jokes” as follows:

You can see the description of your command that you set below your command name:

Once you hit enter, it starts sending your command to the Appwrite Function for execution and displays a response:

Conclusion

This tutorial demonstrated the use of Appwrite Cloud Functions, which provides a Discord command bot template for building a Discord command bot. You learned how to customize the template and add commands to your Discord server.

Resources

You may find the following resources useful:


. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .