How To Create a Discord Bot 🤖

9 min read

2022-01-09


Overview#

Pre-Prerequisites: This blog will assume that you have a code editor (such as VSCode), know how to navigate your file system, and how to use GitHub. Additionally, this blog assumes that you have npm already installed on your computer.

With that being said, we will be coding our discord bot in node.js, even though it is entirely possible to do it with other languages as well!

The discord bot we are building today will respond to user messages starting with the command $define, and define the word they specify after the command. However, this code is EASILY extendable to handling other commands.

Installing packages#

  1. Create a folder and name it whatever you'd like! I named mine blog-example-bot
  2. With that folder opened, create a new terminal (or command line).
  3. Navigate to the folder that you just created in the terminal
  4. Initialize npm using the command:
npm init -y

Running this command should create a new file in your directory called package.json, which tells npm which packages we are going to use. 5. To install the discord.js package, we will use the npm install command.

npm install discord.js
  1. To test our bot, we will be using the nodemon package, which can be installed with:
npm i nodemon
  1. To add secrets (such as our bot's login credentials), we will be using the dotenv package, which can be installed via:
npm i dotenv

This is what your file directory should look like so far!

Creating files and folders#

  1. Create a folder at the root of your application named src. This is where the code for the bot will go.
  2. Within the src folder, create a file called bot.js.
  3. At the root of your application, create a file called .env, which will store the secrets of our bot!

After creating files and folders, this is what your file directory should look like!

Using packages!#

  1. Within the src folder, navigate to the bot.js file.
  2. We will need to require the dotenv and discord.js packages in order to create our discord bot! The lines of code to require these packages are:
require('dotenv').config();
const { Client, Intents } = require('discord.js');

Creating a bot account#

Now, we will need to register our bot with discord!

  1. Navigate to the Discord Developer Portal

  2. Click the New Application button at the top right of the screen

  3. Give your bot a name! I'm going to name mine: Blog Example Bot

  4. Click the Create button!

  5. On the left side of the screen, click on the Bot tab.

  6. Click Add Bot

  7. Click Yes, do it!

  8. To get our bot token, click Click to Reveal Token

  9. Click the Copy button. Don't share your token with anyone else, I have blurred out my token.

  10. Within your .env file, set an environment variable called BOT_TOKEN, and paste the value you just copied!

BOT_TOKEN=your-pasted-bot-token

Adding the bot to our server#

  1. Within the Discord Developer Portal, head to the OAuth2. Look under that tab, and click on URL Generator.
  2. Check the bot box on the first set, and the Send Messages, Manage Messages, Read Message History, and Add Reactions bot permissions!
  3. Copy and paste this URL into your browser!
  4. Select a server to add the bot to, and authorize it! I am adding my bot to a server called Blog Example Bot Server
  5. If successful, you should see this!

Setting up the bot#

  1. Within our bot.js file, we need to declare which permission our bot has access to. Place the following line after the require statements:
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });
  1. We also need to define a prefix that our bot will listen for. This is what a "command" for the bot will begin with. This can be anything you want, but I will set mine to be $:
const PREFIX = "$";

Logging our discord bot in#

  1. To log our discord bot into discord, we need to use the client.login() command!
client.login(process.env.BOT_TOKEN);
  1. To check that our bot is actually online, we can log out a message to the console within a callback method.
client.on('ready', () => {
    console.log(`Logged in as ${client.user.tag}!`);
});
  1. Head to your package.json file, we will specify the command to run our bot! Place the following code into your package.json file, and change the name to be your folder's name!
{
  "name": "CHANGE_TO_YOUR_FOLDER_NAME",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "nodemon ./src/bot.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "discord.js": "^13.5.1",
    "dotenv": "^10.0.0",
    "nodemon": "^2.0.15"
  }
}
  1. Within our terminal, run the command npm run dev
  2. If everything was successful, you should see your discord bot online!

At this point, your bot.js file should look like:

require('dotenv').config();
const { Client, Intents } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });

client.on('ready', () => {
    console.log(`Logged in as ${client.user.tag}!`);
});

client.login(process.env.BOT_TOKEN);

Receiving messages#

  1. To receive messages on your discord bot, we add an event listener for when messages are created:
client.on('messageCreate', async (message) => {
    console.log(message);
});
  1. Make sure to save the bot.js file before sending a message!
  2. Send a message in the discord server, and that message should be logged out in your terminal!

So far, your bot.js file should look like:

require('dotenv').config();
const { Client, Intents } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });

client.on('ready', () => {
    console.log(`Logged in as ${client.user.tag}!`);
});

client.on('messageCreate', async (message) => {
    console.log(message.content);
});


client.login(process.env.BOT_TOKEN);
  1. To send a message whenever our bot receives one, we can use the command: message.reply();
  2. However, we first need to check whether or not it was our discord bot itself that sent the message. We don't want the bot to be invoking commands on itself, which may result in an infinite amount of messages being sent.
require('dotenv').config();
const { Client, Intents } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });

client.on('ready', () => {
    console.log(`Logged in as ${client.user.tag}!`);
});

client.on('messageCreate', async (message) => {
    if (message.author.bot) return;
    message.reply(`Hello ${message.author.username}!`);
});


client.login(process.env.BOT_TOKEN);

Responding to commands#

In order to have our user "summon" our bot, they will need to add a prefix (in our case is $) to show that we want the bot to respond.

For our discord bot, we are going to have it define simple words, so our command that we are going to handle is $define

  1. Within our messageCreate callback, delete the message.reply(), as we will not need it anymore.
  2. In its place, we will need to check whether or not the message the user sent was a command or not.
client.on('messageCreate', async (message) => {
    if (message.author.bot) return;

    if (message.content.startsWith(PREFIX)) {
        await handleCommand(message);
    }
});
  1. Let's create the handleCommand() function, which should take in the message object as a parameter.
  2. Within the handleCommand() function, we need to extract out both the command and the argument that the user is specifying with that command.
async function handleCommand(message) {
    const [command, ...args] = message.content
        .trim()
        .substring(PREFIX.length)
        .split(/\s+/);

    if (command === 'define') {
        handleDefine(message, args);
    }
}

Defining words#

Our bot will be able to define simple words that the user feeds it!

  1. Head to your terminal and install the word-definition npm package:
npm i word-definition
  1. To use the npm package you just installed, add this require statement under the require(discord.js) one
const wd = require("word-definition");
  1. Create a new function called handleDefine(message, args), which takes in the message object and the arguments that the user passed it.
  2. To get the definition of a word and send it back to the user, the code we need is:
async function handleDefine(message, args) {
    const word = args.join(" ");
    try {
        wd.getDef(word, "en", null, async function (definition) {
            let reply = `**${word}** (${definition.category}): ${definition.definition}`;
            if (!definition.definition) {
                reply = `No definition found`;
            }
            message.reply(reply);
        });
    } catch (e) {
        return message.reply(e);
    }
}

Great job! We're done!

Here is my entire bot.js file:

require('dotenv').config();
const { Client, Intents } = require('discord.js');
const wd = require("word-definition");
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });
const PREFIX = "$";

client.on('ready', () => {
    console.log(`Logged in as ${client.user.tag}!`);
});

client.on('messageCreate', async (message) => {
    if (message.author.bot) return;

    if (message.content.startsWith(PREFIX)) {
        await handleCommand(message);
    }
});

async function handleCommand(message) {
    const [command, ...args] = message.content
        .trim()
        .substring(PREFIX.length)
        .split(/\s+/);

    if (command === 'define') {
        handleDefine(message, args);
    }
}

async function handleDefine(message, args) {
    const word = args.join(" ");
    try {
        wd.getDef(word, "en", null, async function (definition) {
            let reply = `**${word}** (${definition.category}): ${definition.definition}`;
            if (!definition.definition) {
                reply = `No definition found`;
            }
            message.reply(reply);
        });
    } catch (e) {
        return message.reply(e);
    }
}

client.login(process.env.BOT_TOKEN);

My package.json:

{
  "name": "blog-example-bot",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "nodemon ./src/bot.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "discord.js": "^13.5.1",
    "dotenv": "^10.0.0",
    "nodemon": "^2.0.15",
    "word-definition": "^2.1.6"
  }
}

My file structure:

Next steps#

Now, if you want the bot to be active FULL TIME, not just when you run the command npm run dev in your terminal, you can deploy it for free using Heroku.

Here is a great resource on how to do that!

Share this blog on Twitter!


~ Ganning Xu © 2024