How to create a Discord bot that shares memes for free

Β·

6 min read

In this article, I will be walking you through the steps to make your first discord bot. We will be building the Bot using NodeJS and host it for free on Heroku.

We all know that Reddit is the place where all the memes are born. People who share memes on Twitter and Instagram mostly reshare those from Reddit. So, Let's make a bot that shares programming memes from famous subreddits. Thereby I decided to call this Bot the MemeDealer.

Prerequisites

Create a Bot account.

  1. Log in to Discord on the browser and go to the Discord developer portal.
  2. Click on the New Application button on the top right corner. create-new-application
  3. Give a name to your app and click on create. name-your-app
  4. Now click on the Bot tab to your left and then click, Add Bot. add-bot
  5. Click on Copy to copy your bot token and save it for later use. click-copy

Set Permissions and add MemeDealer to your server

Now, we have to define the permissions for the Bot.

  1. Click on the OAuth2 tab from the settings. image.png
  2. Scroll down to the scopes section and enable the bot scope. You can notice that a URL appears at the bottom, and there's a new section called Bot Permissions. image.png
  3. Now enable Send Messages and Read Message History in the "Bot Permissions" section image.png
  4. Now copy the above URL and paste it into the browser. You will be asked to authorize the Bot into any of the servers that you are in. Select the test server you created and click on Authorize image.png

Now the Bot has been added to your server. Let's start coding our Bot. We will be using a library called discord.js. So, we can start by setting up the project and installing the dependencies.

Project Setup

  1. Create a new folder meme-dealer and run
    npm init
    
  2. The command line will ask for basic details about the repo.
  3. After completing that, run the following command to install the required dependencies.
     npm install discord.js dotenv axios
    

Code!!!

We will use the dotenv package to load the environment variables from a .env file which contains the bot token for MemeDealer.

Create a new .env file and paste the following

TOKEN=<your-token>

Replace the placeholder with the actual token that you copied earlier.

Log in with bot token

Now, create a new file called index.js and add the following code.

require('dotenv').config();
const Discord = require('discord.js');

const client = new Discord.Client();
const TOKEN = process.env.TOKEN;

client.login(TOKEN);

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

The dotenv makes sure that the Environment Variables are available in the Node Process. Then, we create a new instance of the Discord client and log in using the bot token. To make sure our bot client is working correctly, discord.js emits an event called ready when the client becomes active.

Now save and run the code using the following command.

node index.js

You will see something similar to this. image.png If you open your discord server, now you can see that MemeDealer is online.

image.png

Listen to messages/commands

Now we have to make sure that the Bot can read the messages and respond accordingly. The message event is emitted whenever a new message is created on the server. Also, we need not want our Bot to respond to all messages. So we have to bring in a prefix for our Bot. The Bot will respond only to those messages with the registered prefix character.

const prefix = "!";

client.on('message', (message) => {
  if (message.content.startsWith(prefix)) {
    let command = getCommand(message.content);
    if (command == "ping") {
      message.reply("pong");
    }
  }
})

function getCommand(content) {
  const command = content.replace(prefix, "").split(" ")[0];
  return command;
}

The getCommand strips and returns the command alone from the message. The function message.reply() replies to the message by mentioning. image.png

But where are the Memes.

Let's create a new Bot command called meme and reply with cool memes from various subreddits. We will be using Axios to fetch data from the subreddits. You can take any subreddit's homepage URL, and add .json at the end to get the data in JSON format. What we want to do is to create an array of subreddits that we like.

const subReddits = [
  "r/programmerreactions",
  "r/ProgrammerHumor",
  "r/programme_irl",
  "r/softwaregore",
  "r/badUIbattles"
];

Now we need to create a random integer generation function to select a random subreddit from the array.

function randomInt(min, max) {
  return (Math.floor(Math.random() * (max - min))) + min;
}

Now we have to modify the message event to listen only to the !meme command and respond with a meme. Let's fetch the subreddit data from one of the subreddits and in turn fetch a random post from the list of posts on that subreddit.

client.on('message', (message) => {
  if (message.content.startsWith(prefix)) {
    let command = getCommand(message.content);
    if (command == "meme") {
      const randomIndex = randomInt(0, subReddits.length);
      axios
        .get(`https://reddit.com/${subReddits[randomIndex]}/.json`)
        .then((resp) => {
          const {
            title,
            url,
            subreddit_name_prefixed: subreddit
          } = getRandomPost(resp.data.data.children);
          message.channel.send(`${title}\n${url}\n from ${subreddit}`);
        })
    }
  }
})

function getRandomPost(posts) {
  const randomIndex = randomInt(0, posts.length);
  return posts[randomIndex].data;
}

The message.channel.send() function is used to send the message to the channel without replying to the command message. We could send the image as an attachment by adding the file option to the send function. But, if the image size is more than 8MB, the function will throw an error. Sending the image link alone is enough as Discord is so generous in rendering the image for us.

Now go and send the command !meme on your server, and you will receive a meme like this.

image.png

Time for celebration, right? Except it's not. Are you intending to run the Bot on your laptop 24/7? Well, if you are like me, you wouldn't. Let's run this Bot on Heroku. Heroku has a generous free tier where you get 550 free dyno hours initially. You can get an extra 450 free dyno hours by just adding a credit card.

Heroku apps include a Procfile that specifies the commands executed by the app on startup. You can use the Procfile to declare a variety of process types. In our case, it's the worker dyno type.

Create a new file called Procfile and add the following line.

worker: node index.js

Now we have to deploy the Bot into Heroku. For that, we need the Heroku CLI. If you do not have it installed, install it and log in to the CLI by following this official article.

Then, we need to run the following commands in our workspace to create a Heroku app and push the code to the app.

heroku create meme-dealer
git init
git add .
git commit -m "initial commit"
heroku git:remote -a reddit-memer
git push heroku main

The above commands are responsible for

  • creating a new app called "meme-dealer" in your Heroku dashboard.
  • Initializing a git repository and committing our changes.
  • Setting the remote.
  • Pushing the changes to the remote.

Finally, to scale your app as a worker dyno, run the following command.

heroku ps:scale worker=1

It's testing time. To ensure we did everything correctly, let's open up our test discord server and send the bot command. GIF-showcasing-discord-bot-working Yay!!!πŸ™ŒπŸŽ‰

MemeDealer is up and running. You can add MemeDealer to your servers if you wishπŸ˜….

The code to this Bot can be found in my GitHub.

Β