Creating your own Discord Bot with Discord.js

January 20, 2019

The goal

Create a simple Discord Bot that responds to keywords or phrases typed into a channel by other users.

Getting started

There’s a few basics we need to do before we get into the code.

  1. Sign in to the Discord Developers portal and create an app.

    Note this is a web link and not found in the Discord app. Here you can manage your Discord applications.

  2. Now click the Bot tab under the settings panel, and click the “Add Bot” button.

    Build a bot
  3. Create a folder for your project using your terminal, or finder window.
    mkdir my-first-discord-bot && cd my-first-discord-bot/ && npm init --yes

  4. Install Discord.js as a project dependency.
    npm install discord.js --save

  5. Next, create a config.json file.

    It will house two properties in our code. Add two properties called “prefix” and “token”.

    touch config.json

    {
      "prefix": "",
      "token": ""
    }

    We need a token for our bot to work, so let’s go back to our Developers portal.

    Go ahead and copy your token by clicking “Click to Reveal token”, pasting it into our “token” property.

    Discord Token

    You should now have something that looks like this. Remember everyone’s token will be different and it’s important to keep yours for your eyes only. Mine below is just an example.

    {
      "prefix": "",
      "token": "XyZDLQ.qm7d3oIJ8qw22fBzPmb.FezlFBD4NTM2NTcwNDI3NzA3NzuyNDc5"
    }

Now to write some code!

  1. Create an index.js file in your code editor of choice. Inside, we want to include our Discord library we just added, as-well as creating a reference to the Discord client so we can interact with the Discord.js API.

    // index.js file
    const Discord = require('discord.js');
    const client = new Discord.Client();
  2. So we have the above code to use. But what can we do with it? Let’s visit the Discord API documentation.

    • Under “Classes”, clicking Client shows us the available Properties, Methods and Events.

      API docs
    • There are two events and one method of interest for the purposes of this tutorial. The “ready” and “message” events, and the “login” method.

    • Under the ready event, we can see it’s described as “Emitted when the client becomes ready to start working.”

    • Under the message event, we can see it’s described as “Emitted whenever a message is created.”


    We now have the two events we want to listen to. The "message" event will give us a message that's sent in the channel by a user, and the "ready" event for when we can start listening to the channel.
    • Lastly, the login method shows us it requires a token as a parameter. That’s good, we have that already from step 5.
  3. Back to our index.js file lets go ahead and add some code to listen to our ready event and login.

    // Ready event from step 7.
    client.once('ready', () => onClientReady());
    function onClientReady()
    {
        console.log("Discord bot is ready!");
    }
    
    // Login Method from step 7.
    client.login(token);

    Note we now have a bot that should login, and once it’s ready we should see it log out “Discord bot is ready!“.

  4. Next we need to include our config.json to our index.js file.
    At the top of our index.js file add the following:

    const { token } = require('./config.json');

    This will pull the token value directly from our config object. Handy so we don’t have to do config.token!

    Our complete code so far should look as follows:

    const { token } = require('./config.json');
    
    const Discord = require('discord.js');
    const client = new Discord.Client();
    
    // Ready event from step 7.
    client.once('ready', () => onClientReady());
    function onClientReady()
    {
        console.log("Discord bot is ready!");
    }
    
    // Login Method from step 7.
    client.login(token);
  5. Now run node index.js in your terminal.

    You should see “Discord bot is ready!” - Press ctrl+c to exit.

    Great it’s ready, but where is it? Now that we have our bot it needs to be somewhere right? So lets do that next.

Adding our bot to a channel

Now that we have the basis of a bot, lets look at how we can add it to our Discord channel. Note, it should probably go without saying that you need to be a Discord admin of your channel to add a bot to it. So if you aren’t, create yourself a test discord channel that you can manage.

  1. Back to our Discord Developers portal.

    • Click our app we made from earlier.
    • Under the Settings panel, click “OAuth2”.
    • Scroll down to “Scopes” section and check the “bot” checkbox.

      OAuth2
    • Once checked, copy the link that is generated below and paste it into a new browser window.
    • You will now be able to choose where to add your Bot from a dropdown of channels you manage.

      Pick server
  2. Now check your channel you’ve added it to, you should now see it’s joined but offline.

    Bot offline

  3. Let’s boot up our Bot and see if it turns online.

    • Go back to our project, and in the terminal run node index.js
    • Waheey! We have a bot. But you will notice that when we chat, nothing happens. Let’s see how we can make my bot called Siri, speak.

      Bot joined channel

Making our Discord bot respond to channel messages

So we now have a bot in our channel and it’s online. Since I’ve called my bot Siri, I’m going to make my bot respond to a “Hey Siri” message.

To achieve that, we need to listen to the channel messages that we talked about in step 7. Just like our “ready” event, we’re now going to add code to listen to “channel” messages.

  1. In our ready function we’re adding our message event listener.

    function onClientReady()
    {
        // Listen to Messages in the channel
        client.on('message', (message) => onMessageReceived(message));
    }
    
    // Upon a message being received, handle how we interact
    function onMessageReceived(message)
    {
        if (message.content === 'hey')
        {
            console.log("Hey back at you!");
        }
    }

    Notice how we’re now looking specifically for the word “hey” in the onMessageReceived response.

    Run node index.js

    You should have got a response when you typed into the lobby “hey”. But type in “heyyyy” and we don’t. That seems limited but let’s revise that later.

  2. Let’s get our Bot speaking back now.

    In our function onMessageReceived(message) one of the parameters that is returned from the event is a message object. Back to our Discord API documentation, lets take a look at what “message” gives us.

    API Docs Message
    • Under Methods, there’s some exciting ones to utilise for all different types of scenarios, but for now, lets go ahead and look at “reply”.

    • Looks like we can just reply with message.reply("hello") as both parameters are optional.

      Let’s try that. Save and re-run the bot. node index.js

          function onClientReady()
          {
              // Listen to Messages in the channel
              client.on('message', (message) => onMessageReceived(message));
          }
      
          // Upon a message being received, handle how we interact
          function onMessageReceived(message)
          {
              if (message.content === 'hey')
              {
                  message.reply("hello");
              }
          }

      Sweet! Our bot now replies too. Let’s make it a little more air tight with how it responds to messages.

      Bot reply

Making our Bot respond to prefixed messages

I want my Bot to only respond to messages that start with “Hey Siri”.
Let’s go back to our config.json file and add update the value to “Hey Siri”

{
    "prefix": "Hey Siri",
}

Now in our index.js file, let’s go ahead and expose our prefix to the rest of our code.

    const { token, prefix } = require('./config.json');

This now means prefix is available as a variable to use anywhere in our file.

  • Now when receiving a message, I want to check our message starts with our prefix, which in this case is “Hey Siri”.
  • I also want to accept “hey siri”, or “HEY SIRI”, so we’re going to turn everything to lowercase and check it against our prefix.
    // Upon a message being received, handle how we interact
    function onMessageReceived(message)
    {
        // Stop if our message content does not have the prefix we are looking for
        if (!message.content.toLowerCase().startsWith(prefix.toLowerCase()))
        {
            return;
        }
        message.reply("I wish I was an Android");
    }
  • Let’s save our code and re-run node index.js

Perfect, the bot will now respond to any form of “hey siri”.

Hey siri

Let’s have some fun and add in some checks like the real Siri might respond to.

Note below how we’ve now updated the check to see if the message contains a word, instead of it being a direct match.

We’re now using message.content.includes("The message").

    // Upon a message being received, handle how we interact
    function onMessageReceived(message)
    {
        // Stop if our message content does not have the prefix we are looking to reply to
        if (!message.content.toLowerCase().startsWith(prefix.toLowerCase()))
        {
            return;
        }

        if (message.content.includes("time"))
        {
            message.reply("The time is " + new Date().toLocaleTimeString());
        }
        else if (message.content.includes("weather"))
        {
            message.reply("Do I look like a weather bot?");
        }
        else
        {
            message.reply("I wish I was an Android");
        }
    }



Now we’re ready to challenge Siri the Discord bot. We can now ask the time and weather. If no other words are matched, Siri will just announce “I wish I was an Android”.

Save the changes and reboot the bot. ctrl+c node index.js

Hey siri…

Hey siri responses

And there we have it!

Siri wishing she was an Android, declaring she’s no weather bot and was even clever enough to tell us the time.

That’s it! Where to download the source?

The source can be found on GitHub, if you found this tutorial helpful, feel free to give us a star and a follow.


Grant Bartlett

Front end JavaScript lover, more specifically TypeScript and React. Give us a follow - @grant_bartlett