Over the past few weeks, we’ve explored a lot of different ways that you can use a Discord Bot and communicate with it, have it communicate back, build interactive commands, etc. All of this with one interesting issue, we’re putting all of our commands into one file in a giant if statement. It works, but its not pretty.

Today we’re going to fix that by setting up the index.js file to scan a directory and import all of our commands for is. This will provide a clean way to separate our commands into separate files which helps with organization and extending it going forward.

Reorganizing Our Commands

We’re going to put each command  into a separate file to keep things organized. Create a folder called commands and then a file called hello.js. You guessed it, were going all the way back to the beginning! But trust me, it will be worth it. We’re going to structure our command file into two parts to be exported; the prefix & the function.

Here is the hello.js file;

module.exports = {
  // Define the prefix
  prefix: "!hello",
  // Define a function to pass the message to
  fn: (msg) => {
    msg.reply("world!")
  }
}

Scanning for Commands

Back in index.js, we need to add the code to scan our commands directory for what to import. To do this, we’re going to use fs.readdirSync() to get a list of the filenames, the iterate over the files to parse the prefix & function. Put this code after your other require statements, but before your logon event handler;

const fs = require('fs')

// Create the empty commands object
const commands = {}
// Get the file names from the commands directory
const files = fs.readdirSync('./commands')
// Filter out any non-js files
const jsFiles = files.filter(file => file.endsWith('.js'))
// Foreach, require the file, check for the right exports, then add to the commands object
jsFiles.forEach(commandFile => {
  const command = require(`./commands/${commandFile}`)
  if (command.prefix && command.fn) {
    commands[command.prefix] = command.fn;
  }
})

So now that our commands have been registered to the commands object, we need to check the incoming command to see if it matches. Lets remove everything from the start of our message handler through the !hello block and replace it with the following code.

// Grab the prefix, which should be the content before the first space
const prefix = msg.content.split(' ')[0];
// Filter out bad commands and bots
if (commands[prefix] === undefined || msg.author.bot) {
  return
}

// Execute the fn of the prefix object, passing in the message
commands[prefix](msg);

Now try and issue the !hello command in your server. The bot should respond just the same as it did before.

Now we’ve run into another issue, none of our other commands work! This is because were checking the input up front and if it doesn’t match a command registered in our commands array, the bot basically quits. The solution is quite simple though, you’ll need reorganize the other commands in the same way. I’ll leave that one to you, but you can always check the GitHub repo associated with this project to guide you along.

In our next article, I’ll explain how you can use your bot to integrate with third party APIs.