Search code examples
javascriptdiscorddiscord.jscommand

Why won't my discord.js bot commands refresh on start up?


I have implemented a piece of code that should refresh all of the bot's commands on start up, here is the code from index.js:

const token = require('./config.json')['token'];
const { Client, Collection, Events, GatewayIntentBits, GatewayVersion, REST, Routes } = require('discord.js');
const fs = require('node:fs');
const path = require('node:path');
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.DirectMessages, GatewayIntentBits.DirectMessageTyping, GatewayIntentBits.DirectMessageReactions, GatewayIntentBits.AutoModerationExecution, GatewayIntentBits.AutoModerationConfiguration, GatewayIntentBits.MessageContent] });
const clientId = '1184598822593253477';
client.commands = new Collection();
//Grab all command folders
const foldersPath = path.join(__dirname, 'commands');
const commandFolders = fs.readdirSync(foldersPath);

for (const folder of commandFolders) {
    const commandsPath = path.join(foldersPath, folder);
    const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
    for (const file of commandFiles) {
        const filePath = path.join(commandsPath, file);
        const command = require(filePath);
        if ('data' in command && 'execute' in command) {
            client.commands.set(command.data.name, command);
        } else {
            console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
        }
    }
}

const rest = new REST().setToken(token);

//On command, find the command in commands/utility folder, and run that command
client.on(Events.InteractionCreate, async interaction => {
    if (!interaction.isChatInputCommand()) return;

    const command = interaction.client.commands.get(interaction.commandName);

    if (!command) {
        console.error(`No command matching command named ${interaction.commandName} was found.`);
        return;
    }

    try {
        await command.execute(interaction);
    } catch (error) {
        console.error(error);
        if (interaction.replied || interaction.deferred) {
            await interaction.followUp({ content: 'There was an error while executing this command!', ephemeral: true });
        } else {
            await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
        }
    }
});

function reload_command(command_name) {
    const commandName = command_name;
    const command = client.commands.get(commandName);

    if (!command) {
        return console.log(`There is no command with name \`${commandName}\`!`);
    }
    delete require.cache[require.resolve(`./commands/utility/${command.data.name}.js`)];

    try {
        client.commands.delete(command.data.name);
        const newCommand = require(`./commands/utility/${command.data.name}.js`);
        client.commands.set(newCommand.data.name, newCommand);
        console.log(`Command \`${newCommand.data.name}\` was reloaded!`);
    } catch (error) {
        console.error(error);
        console.log(`There was an error while reloading a command \`${command.data.name}\`:\n\`${error.message}\``);
    }
}

//Once client is online...
client.once(Events.ClientReady, async readyClient => {
    reload_command('addkey');
    console.log(`Ready! Logged in as ${readyClient.user.tag}`);
});



client.login(token); //Rebuilds the bot and logs in

here is the code from addkey.js and from reload.js

const { SlashCommandBuilder } = require('discord.js');

module.exports = {
    data: new SlashCommandBuilder()
        //Command information
        .setName('addkey')
        .setDescription('Add a key.'),
    async execute(interaction) {
        await interaction.reply("Running add key");
    },
};
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
    data: new SlashCommandBuilder()
        .setName('reload')
        .setDescription('Reloads a command.'),
    async execute(interaction) {
        const commandName = interaction.options.getString('command', true).toLowerCase();
        const command = interaction.client.commands.get(commandName);

        if (!command) {
            return interaction.reply(`There is no command with name \`${commandName}\`!`);
        }

        delete require.cache[require.resolve(`../${command.category}/${command.data.name}.js`)];

        try {
            interaction.client.commands.delete(command.data.name);
            const newCommand = require(`../${command.category}/${command.data.name}.js`);
            interaction.client.commands.set(newCommand.data.name, newCommand);
            await interaction.reply(`Command \`${newCommand.data.name}\` was reloaded!`);
        } catch (error) {
            console.error(error);
            await interaction.reply(`There was an error while reloading a command \`${command.data.name}\`:\n\`${error.message}\``);
        }
    },
};

I was expecting to see the old commands to go away in the discord, and the new commands to appear. What I got was just the old command that I have since deleted, as well as the addkey command that has been in there since the start of making the bot.


Solution

  • First and foremost, you should never have your bot update its slash commands every time it goes online. You may update your bot in the future or have a crash that forces your bot to reboot, and this can lead to unnecessary API requests on startup that cause more downtime on your end and more strain on Discord's end (you may even get rate-limited). With that said, I would recommend creating a separate JavaScript file to run whenever you need to update your slash commands.

    Secondly, I noticed in your code that there is no line including rest.put(). This is an important step in updating slash commands because it's what sends the command data to Discord's servers. Here is the usage example pulled from Discord's guide on registering slash commands:

    await rest.put(
        Routes.applicationCommands(clientId),
        { body: commands },
    );