Introduction
Discord is a chat app that allows millions of users around the world to message and voice chat online in communities called guilds or servers. Discord also offers an extensive API that developers can use to build powerful Discord bots. Bots can perform a variety of actions, such as sending messages to servers, DMing users, moderating servers, and playing audio in voice chats. This allows developers to build powerful bots with advanced and complex features, such as moderation tools or games. For example, the Dyno Tool bot serves millions of communities and has useful features like spam protection, a music player, and other useful functions. Learning to create Discord bots will allow you to implement a wide range of features, which thousands of people can interact with daily.
In this tutorial, you'll build a Discord bot from scratch using Node.js and the Discord.js library, which allows users to interact directly with the Discord API. You'll set up a profile for a Discord bot, obtain authentication tokens for the bot, and program the bot to process commands with user arguments.
Prerequisites
Before you start, you will need:
- Node.js is installed on your development machine.
- Any text editor of your choice, such as Visual Studio Code, Atom, Sublime, or Nano.
- A free Discord account with a verified email account and a free Discord server that you will use to test your Discord bot.
Step 1 – Setting up the Discord bot
In this step, you use the Discord developer graphical user interface (GUI) to launch the Discord bot and obtain the bot token, which you pass to your application.
To register a bot on the Discord platform, use the Discord app dashboard. This is where developers can create Discord apps, including Discord bots.
To get started, click New Application. Discord will ask you to enter a name for your new application. Then click Create to create the application.
Note: The name of your app is independent of the name of the bot, and the bot does not have to be the name of the app.
Now open your app dashboard. To add a bot to your app, go to the Bot tab in the left navigation bar.
Click the Add Bot button to add a bot to the app. Click Yes, do it! when it asks you to confirm. You will then be taken to a dashboard that contains details of the bot name, authentication token, and your profile picture.
You can change your bot name or profile picture here in the dashboard. You will also need to copy the bot authentication token by clicking on Click to reveal token and copying the token that appears.
Warning: Never share or upload your bot token as it allows anyone to log into your bot.
Now you need to create an invitation to add the bot to the Discord community so you can test it. First, go to the URL Generator page under the OAuth2 tab of the app dashboard. To create an invitation, scroll down and select the bot under Scopes. You will also need to set permissions to control the actions your bot can take in the communities. For this tutorial, select Administrator, which will allow your bot to perform almost all actions in the Guild. Copy the link with the Copy button.
Then add the bot to the server. Follow the invite link you created. You can add the bot to any server you own, or have administrator permissions on in the drop-down menu.
Now click Continue. Make sure you check the box next to Administrator – this will give the bot administrator permissions. Then click Authorize. Discord will ask you to solve a CAPTCHA before the bot can join the server. You will now have the Discord bot offline in the list of members of the server you added the bot to.
You have successfully created a Discord bot and added it to a server. Next, you will write a program to log in to the bot.
Step 2 – Create your project
In this step, you set up the initial coding environment where you build your bot and programmatically enter the bot.
First, you need to set up a project folder and the necessary project files for the robot.
Create your project folder:
mkdir discord-bot
Go to the project folder you created:
cd discord-bot
Next, use your text editor to create a file called config.json to store your bot's authentication password:
nano config.json
Then add the following code to the config file and replace the highlighted text with your bot's authentication token:
{ "BOT_TOKEN": "YOUR BOT TOKEN" }
Save the file and exit.
Next, you will create a package.json file that stores the details of your project and information about the dependencies you are using for the project. You will create a package.json file by running the following npm command:
npm init
npm will ask you for various details about your project.
Now you will install the discord.js package which you will use to interact with the Discord API. You can install discord.js via npm with the following command:
npm install discord.js
Now that you have set up the configuration file and installed the necessary dependencies, you are ready to start building your bot. In a real application, a large bot would be split across many files, but for this tutorial, your bot code will be in a single file.
First, create a file called index.js in the discord-bot folder for the code:
nano index.js
Start coding the bot by requiring the discord.js dependency and a configuration file with the bot token:
const Discord = require("discord.js"); const config = require("./config.json");
After this, add the next two lines of code:
... const client = new Discord.Client({intents: ["GUILDS", "GUILD_MESSAGES"]}); client.login(config.BOT_TOKEN);
Save your file and exit.
The first line of code creates a new Discord client and assigns it to the fixed client. This client is partly how you interact with the Discord API and how Discord is notified of events like new messages. The client actually represents the Discord bot. The object passed to the Client constructor specifies the gateway intents of your bot. This specifies which WebSocket events your bot will listen for. Here you have specified GUILDS and GUILD_MESSAGES so that the bot can receive message events in the forums.
The second line of code uses the client-side login method to log in to the Discord bot you created, using the password in the config.json file as the password. The token lets the Discord API know which bot the application is for and that you are authenticated to use the bot.
Now run the index.js file using Node:
node index.js
Your bot's status will change to online on the Discord server you added it to.
You've successfully set up a coding environment and created the basic code to log into your Discord bot. Next, you'll handle user commands and make your bot perform actions like sending messages.
Step 3 – Handling the user's first command
In this step you create a bot that can handle user commands. You execute your first ping command which responds with a “ping” and the time it took to respond to the command.
First, you need to detect and receive messages that users send so that you can process any commands. Using the on method in the Discord client, Discord will send you a notification about new events. The on method takes two arguments: the name of the event to wait for and a function that will be executed each time that event occurs. With this method, you can wait for the event message — this happens every time a message is sent to a forum that the bot has permission to view messages in. So you will create a function that will be executed each time a message is sent to process commands.
First, open your file:
nano index.js
Add the following code to your file:
... const client = new Discord.Client({intents: ["GUILDS", "GUILD_MESSAGES"]}); client.on("messageCreate", function(message) { }); client.login(config.BOT_TOKEN);
This function, which runs on the messageCreate event, takes the message as a parameter. The message will be a Discord.js message instance containing information about the message being sent and methods to help the bot respond.
Now add the following line of code to your command control function:
... client.on("messageCreate", function(message) { if (message.author.bot) return; }); ...
This line checks whether the author of the message is a bot, and if so, stops processing the command. This is important because, in general, you don't want to process or respond to bot messages. Bots usually don't need to use information from other bots, so ignoring their messages saves processing power and prevents random responses.
Now you're going to write a controller command. To do this, it's a good idea to understand the typical format of a Discord command. Typically, the structure of a Discord command consists of three parts in this order: a prefix, a command name, and (sometimes) command arguments.
- Prefix: A prefix can be anything, but it is usually a piece of punctuation or an abstract phrase that is not usually at the beginning of a message. This means that when you enter the prefix at the beginning of a message, the bot understands that this command is intended to be processed by a bot.
- Command name: The name of the command the user wants to use. This means that the bot can support multiple commands with different functions and allow users to choose between them by providing a different command name.
- Arguments: Sometimes if the command requires or uses additional information from the user, the user can provide arguments after the command name, with each argument separated by a space.
Note: There is no mandatory command structure and bots can process commands however they like, but the structure presented here is a workable one that the vast majority of bots use.
To start creating a command parser that handles this format, add the following lines of code to the message handler function:
... const prefix = "!"; client.on("messageCreate", function(message) { if (message.author.bot) return; if (!message.content.startsWith(prefix)) return; }); ...
You add the first line of code to the value “!” to the constant prefix that you will use as the robot prefix.
The second line of code you add checks whether the content of the message the bot is processing starts with the prefix you set, and if it doesn't, it stops processing the message.
Now you need to convert the rest of the message into the command name and any arguments in the message. Add the following highlighted lines:
... client.on("messageCreate", function(message) { if (message.author.bot) return; if (!message.content.startsWith(prefix)) return; const commandBody = message.content.slice(prefix.length); const args = commandBody.split(' '); const command = args.shift().toLowerCase(); }); ...
You use the first line here to remove the prefix from the message content and assign the result to the constant command body. This is necessary because you don't want to include the prefix in the parsed command name.
The second line takes the message with the prefix removed and uses the split method on it, with a space as the separator. This splits it into an array of substrings, and a split occurs wherever there is a space. This results in an array that contains the command name, and then, if included in the message, any arguments. You assign this array to the constant args.
The third line removes the first element from the args array (which will be the name of the command provided), converts it to lowercase, and then assigns it to the constant command. This allows you to isolate the command name and leave only the arguments in the array. You also use the toLowerCase method because commands are usually not case-sensitive in Discord bots.
You have completed building a command parser, implementing a required prefix, and retrieving the command name and any arguments from messages. Now you will implement and generate the code for specific commands.
Add the following code to start the ping command:
... const args = commandBody.split(' '); const command = args.shift().toLowerCase(); if (command === "ping") { } }); ...
This if statement checks whether the command name you parsed (assigned to the constant command) matches “ping”. If it does, it indicates that the user wants to use the “ping” command. You put the specific command code in the if statement block. You will repeat this pattern for other commands that you want to execute.
Now you can implement the “ping” command code:
... if (command === "ping") { const timeTaken = Date.now() - message.createdTimestamp; message.reply(`Pong! This message had a latency of ${timeTaken}ms.`); } ...
Save your file and exit.
You add a “ping” command block that calculates the difference in milliseconds between the current time – found using the new method on the Date object – and the timestamp of the message that was created. This calculation calculates the time it took to process the message and “ping” the bot.
The second line responds to the user's command using the reply method in the message constant. The reply method pings the user who invoked the command (which notifies the user and highlights the message for the specified user) followed by the content provided as the first argument to the method. You provide a literal pattern containing a message and the computed ping as the response that the reply method will use.
This ends the execution of the “ping” command.
Run your bot using the following command (in the same folder as index.js):
node index.js
You can now use the “!ping” command on any channel the bot can see and send messages to, and get a response as a result.
You have successfully created a bot that can handle user commands and executed your first command. Next, you will continue developing your bot by executing the sum command.
Step 4 – Execute the Sum command
Now you will extend your program by running the “!sum” command. The command takes any number of arguments and adds them together, before returning the sum of all the arguments to the user.
If your Discord bot is still running, you can stop its process with CTRL + C.
Reopen your index.js file:
nano index.js
You use an else-if block to start executing the “!sum” command. After checking the command name ping, it checks to see if the command name is equal to “sum”. You will use the else-if block because only one command is processed at a time, so if the program matches the command name “ping”, it does not need to check the “sum” command. Add the following highlighted lines to your file:
... if (command === "ping") { const timeTaken = Date.now() - message.createdTimestamp; message.reply(`Ping! This message had a latency of ${timeTaken}ms.`); } else if (command === "sum") { } }); ...
You can start executing the “sum” statement code. The “sum” statement code goes inside the else-if block you just created. Now add the following code:
... else if (command === "sum") { const numArgs = args.map(x => parseFloat(x)); const sum = numArgs.reduce((counter, x) => counter += x); message.reply(`The sum of all the arguments you provided is ${sum}!`); } ...
You use the map method on the argument list to create a new list using the parseFloat function on each item in the args array. This creates a new array (assigned to the constant numArgs) where all the items are numbers instead of strings. This means that later you can successfully find the sum of the numbers by adding them together.
The second line uses the reduce method on the constant numArgs, which provides a function that sums all the elements in the list. You assign the sum of all the elements in numArgs to the constant sum.
You then use the reply method on the message object to respond to the user's command with an actual pattern, which includes the sum of all the arguments the user sends to the bot.
This ends the execution of the “sum” command. Now run the bot using the following command (in the same index.js folder):
node index.js
You can now use the “!sum” command in any channel that the bot can view and send messages to.
The following is a complete version of the index.js bot script:
const Discord = require("discord.js");
const config = require("./config.json");
const client = new Discord.Client({intents: ["GUILDS", "GUILD_MESSAGES"]});
const prefix = "!";
client.on("messageCreate", function(message) {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
const commandBody = message.content.slice(prefix.length);
const args = commandBody.split(' ');
const command = args.shift().toLowerCase();
if (command === "ping") {
const timeTaken = Date.now() - message.createdTimestamp;
message.reply(`Pong! This message had a latency of ${timeTaken}ms.`);
}
else if (command === "sum") {
const numArgs = args.map(x => parseFloat(x));
const sum = numArgs.reduce((counter, x) => counter += x);
message.reply(`The sum of all the arguments you provided is ${sum}!`);
}
});
client.login(config.BOT_TOKEN);
At this point, you have developed your Discord bot by running the sum command.
Result
You have successfully implemented a Discord bot that can handle several different user commands and command arguments. If you want to expand your bot, you can probably run more commands or try out more parts of the Discord API to build a powerful Discord bot.










