How To Create a Discord Bot 🤖

9 min read
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#
- Create a folder and name it whatever you'd like! I named mine
blog-example-bot
- With that folder opened, create a new terminal (or command line).
- Navigate to the folder that you just created in the terminal
- 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
- To test our bot, we will be using the
nodemon
package, which can be installed with:
npm i nodemon
- 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#
- Create a folder at the root of your application named
src
. This is where the code for the bot will go. - Within the
src
folder, create a file calledbot.js
. - At the root of your application, create a file called
.env
, which will store the secrets of our bot!using
dotenv
allows us to reference sensitive information through environment variables!
After creating files and folders, this is what your file directory should look like!
Using packages!#
- Within the
src
folder, navigate to thebot.js
file. - We will need to require the
dotenv
anddiscord.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');
These lines of code should be at the top of your bot.js
file.
Creating a bot account#
Now, we will need to register our bot with discord!
Navigate to the Discord Developer Portal
Click the
New Application
button at the top right of the screenGive your bot a name! I'm going to name mine:
Blog Example Bot
Click the
Create
button!On the left side of the screen, click on the
Bot
tab.Click
Add Bot
Click
Yes, do it!
To get our bot token, click
Click to Reveal Token
Click the
Copy
button. Don't share your token with anyone else, I have blurred out my token.Within your
.env
file, set an environment variable calledBOT_TOKEN
, and paste the value you just copied!
BOT_TOKEN=your-pasted-bot-token
Adding the bot to our server#
- Within the Discord Developer Portal, head to the
OAuth2
. Look under that tab, and click onURL Generator
. - Check the
bot
box on the first set, and theSend Messages
,Manage Messages
,Read Message History
, andAdd Reactions
bot permissions! - Copy and paste this URL into your browser!
- Select a server to add the bot to, and authorize it! I am adding my bot to a server called
Blog Example Bot Server
- If successful, you should see this!
Setting up the bot#
- Within our
bot.js
file, we need to declare which permission our bot has access to. Place the following line after therequire
statements:
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });
- 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#
- To log our discord bot into discord, we need to use the
client.login()
command!
client.login(process.env.BOT_TOKEN);
We are using the BOT_TOKEN
env variable that we set previously!
- 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}!`);
});
- Head to your
package.json
file, we will specify the command to run our bot! Place the following code into yourpackage.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"
}
}
- Within our terminal, run the command
npm run dev
- 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#
- 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);
});
- Make sure to save the
bot.js
file before sending a message! - 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);
- To send a message whenever our bot receives one, we can use the command:
message.reply();
- 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
- Within our
messageCreate
callback, delete themessage.reply()
, as we will not need it anymore. - 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);
}
});
- Let's create the
handleCommand()
function, which should take in themessage
object as a parameter. - 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!
- Head to your terminal and install the
word-definition
npm package:
npm i word-definition
- To use the npm package you just installed, add this require statement under the
require(discord.js)
one
const wd = require("word-definition");
- Create a new function called
handleDefine(message, args)
, which takes in the message object and the arguments that the user passed it. - 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);
}
}
If the bot can find a definition, we will reply to the message with the definition of that word, but if it can't, the reply is "No definition found"
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 © 2023