Discord Bot Programming Part I: Getting Started

Programming a Discord bot was my first real start to familiarizing myself with Node.js and what a ride it has been. This will be my stab at an overview of the process of making a Discord bot with the Discord.js library, both self bots and bot accounts. No prior knowledge of Node assumed. As with most new things, you need some sort of context or project before learning something new and maybe Discord bots could be that impetus as it was for me.

I see Discord as the successful spiritual successor to Raidcall: a VoIP software built for a scalable number of users (like TeamSpeak, but not Skype) but with on free server hosting, user identification, and friend's list. Although primarily marketed at gamers, Discord has achieved a wide enough audience, coupled with a sufficiently comprehensive permissions system and low barrier to entry, that it has also become usable for a general purpose. And so too has the demand for bots for various purposes grown.

Preparing the Project Side

You only really need to install one program to get started with Discord bot development, Node.js, in order to run a bot. (Though, since it's Javascript, it is possible to develop just on your brower.) Although it's not necessary, a text editor such as VSCode, Atom, and Sublime. Not to be confused with IDEs such as Visual Studio. I personally used plain Notepad (essentially featureless text editor) for several years before switching to VSCode more recently.

Once Node is installed, you want to import the Discord.js library. Though there's several ways, the prototypical way is via the Node package framework NPM. NPM packaging framework handles the downloading, specifying the correct version for libraries important for dependancy and collaborating with other developers, and providing "scripts" that imitate makefiles that automate the build process.
  1. Make a project directory folder
  2. Navigate to it in your command line
  3. Create a the main file for you bot. I suggest 'main.js' or 'bot.js' as names. You may also wish to put these files in a subfolder 'src/'.
  4. Run npm init. None of the options are particularly important. This will create the 'package.json' file, which explicitly lists your dependencies and scripts. Essentially your project metadata.
  5. Run npm install --save discord.js or npm i -S discord.js for short. This will create the node_modules folder. The --save flag updates tells npm to automatically update your package.json to include it as a production dependency.
  6. Optional: npm install --save-dev eslint or npm i -D eslint for short. A linter, especially for Javascript, helps enforce a style guide as well as catch the common errors to which Javascript development can be prone. The --save-dev tells npm to automatically update your package.json to include it as a developer dependency. Also see the Idiot's Guide for ESLint settings.
  7. Optional: You may wish to run npm run test and the following will be the output (error is to be expected but it should echo as the script suggests):

  8. You can now run your code with node bot.js
  9. Optional: Add a script to package.json file as a shortcut. For example add the line "build": "node bot.js", (inclusive of comma) above the test script. Note that you should run this in Wordpad or any of the text editors already suggests but not Notepad on Windows, any Unicode aware editor otherwise newlines will not show.

Version Control: Github and Git

While it is technically optional to create a version control history (source code repository), this is now a basic developer habit. All the steps to opening an online Github repository are marked optional; steps not marked optional are necessary for the local repository. This is a more careful explanation of this tutorial.

There are several version control softwares and Git is but one of them. I'm still rather new to using Git as my version control software so the explanations may not be 100%.
  1. Optional: Login/Signup to github, then create a new project. To save yourself work I'd select 'Initialize this repository with a README', select 'Node' from gitignore dropdown, and select the appropriate license: this will create one file per respectively. Click 'Create New Repository' green button.
  2. Optional: On this new project's page, click on the 'Clone or download' green button, then copy the entire .git link.
  3. Navigate to your project base folder (where package.json should be located) and in run git init in the command line. This creates the hidden '.git' folder. Note that this local repository is separate from the online repository.
  4. Optional: Now link to your github project by git remote add origin REPLACEME.git where you repalce REPLACEME.git with the .git link. This marks the remote .git link with the label origin. Origin is conventially the label for the base project. You may also wish run git remove -v in which case you should see both a fetch and push link associated with origin.
  5. Optional: Run git pull origin master to pull all three files created for you by Github and to set the header files (stored in the hidden .git folder) properly for commits. This pulls from the master branch of the repository linked by the label origin and merges (with nothing since no history) into your current working project.
  6. Create your '.gitignore' file if you did choose to do the optional steps. Make sure this file has node_modules/ as one of the lines. This is so your Git repository does not store any node modules imported via npm; the package.json file is the record of interactions with the NPM framework and encodes all imported library (npm package) changes.
  7. Run git push . to stage the change. In other words, add all the files in the local directory and its subdirectories to the list of files to check for changing. Sort of like adding all changes to a buffer.
  8. Run git commit -m "First commit" to commit all the staged changes into the local Git repository. "First commit" is the message that will appear in the logs to describe the reasoning for this change.
  9. Optional: Run git push origin master to propogate the loca Git repository commits to the remote repository linked by 'origin' to the 'master' branch. Enter your login details for Github.
You have to repeat steps 7–9 to make changes to both the local and remote repository.

Since I use VSCode, here's a tutorial on for it. You can also do the Git intialization, opening a console pre-navigated to your project home folder, or run commands with the in-built console that you can get to with Ctrl + ~.
  1. Click on Git menu and press on the + sign to stage changes.
  2. Type in the commit message into the box and Ctrl + Enter.
  3. Optional: Click on publish icon in the bottom left. Select origin/master if asked (branch and remote is changeable with menu left of publish icon). Then enter your login details for Github.

Preparing the Discord Side

The path splits here depending on whether you're making a standalone bot or a self bot.

Option A: Standalone Bot

  1. Go to Discord's developer section for Apps and login.
  2. You need only name it and hit 'Create App', then on next screen 'Create a Bot User'.
  3. Click 'Create a Bot User'
  4. Check "Public Bot" if you want to allow others to add this bot to their server without you adding it for them (otherwise they get an error). Save changes.

    Do not check "Require OAuth2 Code Grant" unless you know what you are doing. Inviting a bot to a server is primarily done through sharing and clicking a link, and this option is primarily for when you want users to be required to sign into an alternative site before they can add your bot to a server. (To impose exterior authentication on who can add your bot similar to how Mee6 does it.) Having this enabled does allow your bot to do a couple of extra things though, marked in the API documentation.
    Curtsey of Discord API server

  5. Click to reveal the Token and save it (used in your program). Save the Client ID for the invite link. https://discordapp.com/oauth2/authorize?client_id=APP_ID&scope=bot replace APP_ID with the number listed after Client ID. This is your invite link for the bot.

Option B: Self Bots

You only need to find out what your token is.
  1. Login to the client or the browser on Chrome. This method is possible to do with Firefox too but you need extensions that let you inspect the local storage.
  2. Press Ctrl + Shift + I  on your keyboard to open up Chrome Development Tools.
  3. Navigate to the 'Application' tab.
  4. Expand local storage and click on entry named like a link for Discord.
  5. Search for token line in the key-value table that shows and copy. You can right click the value side (right side) → Edit "Value" → Copy, to get the text.
    Curtesy of An Idiot's Guide

Preparing the Test Server

  1. Create a new server unless you have a server for testing. Keep in mind few people want to see you spam while testing your bot. Here is a server for bot testing, should you for some reason not want to make your own.
  2. If it's a standalone bot, invite the bot to the server by following the link you find in the last step (the one you had to change out the APP_ID), select the server, and click on Authorise. You must have 'Manage Server' permission to invite bots. You can safely ignore the random meme they have below 'Add a bot to a server'.

    At this step, if a &permissions=NUMBER is included in the link (which in my example it is not), you'll see a bunch of check boxes to tick. Ticking any of these check boxes will create an automatic personal role for your bot that cannot be deleted (may or may not be desirable). You may wish to look at this permissions calculator for getting the appropriate bit mask.
  3. Configure the role for your bot. For self bots, that means the permissions you yourself have. Some important ones you may wish to enable are:
    • Read Messages and Send Messages: Should be self explanatory.
    • Read Message History: You have access to messages via the Client object. Once you have the 'Read Messages' permission active, you get access to messages is via the arguments passed on a receive 'message' event. In order to get access to more than just the current message sent, you need this history permission enabled.
    • Embed Links: For sending messages that look the same as link previews. Definitely not every bot makes use of this.
    • Add Reactions: One of the uses some bots use reactions for is to help simulate navigation.
    • Etc.
  4. Now onwards to test!

First Test

The homepage of the Discord.js library has the following minimum test code. Do not blindly do this for a test bot as you will reply to every message, please refer to the section on self bots. All you have to do for self bots is insert a check that the author of the message has the same id as your own user id.

const Discord = require("discord.js");
const client = new Discord.Client();

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

client.on('message', msg => {
  if (msg.author.id === client.
  if (msg.content === 'ping') {


Replace the 'token' with the token of your bot. Make sure this is surrounded in quotes as it is meant to be a string of numbers. Now type ping into the channel that the bot can read and the bot should respond with 'Pong!'.

You may wish to perform a full commit to your Git and Github now that all the bare minimum boilerplate is in place and working.

Some Good Things to Know About

  • Rate limiting: Discord.js handles all of this internally. Some functions will be promises as a result. However with message spamming or deletion spamming, you only need to execute the function in a loop and Discord.js will queue it for you; you do not need to wait for a successful return from the promise.
  • Caching: Some properties only search the cache of users (eg. Client.users) as indicated by the documentation. Users who go offline do not appear in the cache. I believe this is a Discord.js-specific phenomenon.
  • API Caching: Standalone bots are limited to message history of 14 days (Need to double check). But, just as users can go to the beginnings of time, so can self bots.
  • Sharding: You can ignore this feature unless, according to the developers, you only want to make use of this feature when your bot is used on 2500+ guilds. One thing to note is a shard's cache is specific to said shard and not shared.
  • The Unofficial Rules of Self Bots: In particular, coming from what I have heard and read, your bot should not automatically ban or friend anyone. Your bot should not respond to anyone but yourself or you could get your account banned. Remember this is not applicable for standalone bots. Though even standalone bots should not be invite scrapping.

Further Reading

No comments:

Post a comment

Note: only a member of this blog may post a comment.