Discord.JS Command Handler Subfolders Search

I have a command handler for my discord bot that searches through the folder ./commands/ in which all the .js commands are listed. I want to clean up all of the commands and instead of having them all in the same folder, have them each on their own category folders. Now the problem is I have no idea how to make the bot search through sub directories of the ./commands/ folder to find each command in its own category folder. Below I have the code I use to search in ./commands/. Any idea to make it search through every directory in ./commands/?

client.commands = new Discord.Collection();
client.aliases = new Discord.Collection();

fs.readdir("./commands/", (err, files) => {
  if (err) return console.error(err);
  console.log(`Loading a total of ${files.length} commands.`);
  files.forEach(file => {
    if (!file.endsWith(".js")) return;
    let props = require(`./commands/${file}`);
    console.log(`Loading Command: ${props.help.name} ✔`);
    client.commands.set(props.help.name, props);
        props.conf.aliases.forEach(alias => {
      client.aliases.set(alias, props.help.name);
    });
  });
});

Edit:

This is the answer that jakemingolla helped me create:

function walk(dir, callback) {
    fs.readdir(dir, function(err, files) {
        if (err) throw err;
        files.forEach(function(file) {
            console.log(`Loading a total of ${files.length} commands.`);
            var filepath = path.join(dir, file);
            fs.stat(filepath, function(err,stats) {
                if (stats.isDirectory()) {
                    walk(filepath, callback);
                } else if (stats.isFile() && file.endsWith('.js')) {
                    let props = require(`./${filepath}`);
                    console.log(`Loading Command: ${props.help.name} ✔`);
                    client.commands.set(props.help.name, props);
                    props.conf.aliases.forEach(alias => {
                    client.aliases.set(alias, props.help.name);
                  });
                }
            });
        });
    });
}
walk(`./commands/`)

Answer

Use a function to encapsulate repeated work!

You’re already halfway there – you have a function that can take a single directory and list the files within it. If you instead encounter a directory, repeat the process:

function walk(dir, callback) {
    fs.readdir(dir, function(err, files) {
        if (err) throw err;
        files.forEach(function(file) {
            var filepath = path.join(dir, file);
            fs.stat(filepath, function(err,stats) {
                if (stats.isDirectory()) {
                    walk(filepath, callback);
                } else if (stats.isFile() && file.endsWith('.js')) {
                    ... your logic here ...
                }
            });
        });
    });
}

Leave a Reply

Your email address will not be published. Required fields are marked *