skip to Main Content

I’m trying to figure out why my bots slash commands aren’t showing up in my server. I have given it the applications.commands and bot scopes as well as the Administrator permission, so I don’t believe it’s a permissions issue.

Here is my current index.js,

require("dotenv").config();
const {REST} = require("@discordjs/rest");
const { Client, Events, GatewayIntentBits, Collection } = require('discord.js');
const { Routes } = require("discord-api-types/v10");
const { Player } = require("discord-player");

const fs = require("node:fs");
const path = require("node:path");

const client = new Client({
    intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildVoiceStates] 
});


client.once(Events.ClientReady, readyClient => {
    console.log(`Ready! Logged in as ${readyClient.user.tag}`);
});

const commands = [];
client.commands = new Collection();

const commandsPath = path.join(__dirname, "commands");
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);

    client.commands.set(command.data.name, command);
    commands.push(command.data.toJSON());
}

client.player = new Player(client, {
    ytdlOptions: {
        quality: "highestaudio",
        highWaterMark: 1 << 25
    }

});

client.on("ready", () => {
    const guild_ids = client.guilds.cache.map(guild => guild.id);

    const rest = new REST({version: "10"}).setToken(process.env.TOKEN);
    for (const guildId of guild_ids)
    {
        rest.put(Routes.applicationGuildCommands(process.env.CLIENT_ID, guildId), {
            body: commands
        })
        .then(() => console.log(`Added commands to ${guildId}`))
        .catch(console.error);
    }

});

client.on("interactionCreate", async interaction => {
    if(!interaction.isChatInputCommand()) return;

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

    try
    {
        await command.execute({client, interaction});
    }
    catch(err)
    {
        console.error(err);
        await interaction.reply("An error occured executing this command. Try again.");
    }
});

// Log in to Discord with your client's token
client.login(process.env.TOKEN);

along with one of my slash commands.

const { SlashCommandBuilder } = require("@discordjs/builders");
const { MessageEmbed } = require("discord.js");
const { QueryType } = require("discord-player");


module.exports = {
    data: new SlashCommandBuilder()
        .setName('play')
        .setDescription('Play a song.')
        .addSubcommand(subcommand => {
            subcommand
                .setName('search')
                .setDescription('Search for a song.')
                .addStringOption(option => {
                    option
                        .setName('searchterms')
                        .setDescription('Search keywords')
                        .setRequired(true);
                })
        })
        .addSubcommand(subcommand => {
            subcommand
                .setName('playlist')
                .setDescription('Plays a playlist from YT')
                .addStringOption(option => {
                    option
                        .setName('url')
                        .setDescription('Playlist URL')
                        .setRequired(true);
                })
        })
        .addSubcommand(subcommand => {
            subcommand
                .setName('playurl')
                .setDescription('Plays a song from YT using URL')
                .addStringOption(option => {
                    option
                        .setName('url')
                        .setDescription('URL for a song')
                        .setRequired(true);
                })
        }),
    execute: async ({client, interactions}) => {
        if (!interaction.member.voice.channel)
        {
            await interaction.reply(':warning: You must be in a voice channel to use this command!');
            return;
        }

        const queue = await client.player.createQueue(interacton.guild);

        if (!queue.connection) await queue.connect(interaction.member.voice.channel)

        let embed = new MessageEmbed();
        if(interaction.options.getSubcommand() === 'song')
        {
            let url = interaction.options.getString('url');

            const result = await client.player.search(url, {
                requestedBy: interaction.user,
                searchEngine: QueryType.YOUTUBE_VIDEO,
            });

            if (result.tracks.length === 0)
            {
                await interaction.reply(':warning: No results found!')
                return
            }

            const song = result.tracks[0];
            await queue.addTrack(song);

            embed
                .setDescription(`Added **[${song.title}](${song.url})** to the queue.`)
                .setThumbnail(song.thumbnail)
                .setFooter({text: `Duration: ${song.duration}`});
        }
        else if(interaction.options.getSubcommand() === 'playlist')
            {
                let url = interaction.options.getString('url');
    
                const result = await client.player.search(url, {
                    requestedBy: interaction.user,
                    searchEngine: QueryType.YOUTUBE_PLAYLIST,
                });
    
                if (result.tracks.length === 0)
                {
                    await interaction.reply(':warning: No playlist found!')
                    return
                }
    
                const playlist = result.playlist;
                await queue.addTracks(playlist);
    
                embed
                    .setDescription(`Added **[${playlist.title}](${playlist.url})** to the queue.`)
                    .setThumbnail(playlist.thumbnail)
                    .setFooter({text: `Duration: ${playlist.duration}`});        
        }
        else if(interaction.options.getSubcommand() === 'search')
            {
                let url = interaction.options.getString('searchterms');
    
                const result = await client.player.search(url, {
                    requestedBy: interaction.user,
                    searchEngine: QueryType.YOUTUBE_PLAYLIST,
                });
    
                if (result.tracks.length === 0)
                {
                    await interaction.reply(':warning: No results found!')
                    return
                }
    
                const song = result.tracks[0];
                await queue.addTrack(song);

                embed
                    .setDescription(`Added **[${song.title}](${song.url})** to the queue.`)
                    .setThumbnail(song.thumbnail)
                    .setFooter({text: `Duration: ${song.duration}`});
        }

        if(!queue.playing) await queue.play();

        await interaction.reply({
            embeds: 
        })

    }
    
}

When running node index.js in terminal, it does successfully run the .then(() => console.log(`Added commands to ${guildId}`)) code line, but for some reason I’m not seeing any slash commands for my bot, only other bots.

2

Answers


  1. Chosen as BEST ANSWER

    Modern slash commands requires use of the deploy-commands.js file to deploy commands to your server.

    Below is an example deployment script.

    const { REST, Routes } = require('discord.js');
    const { clientId, guildId, token } = require('./config.json');
    const fs = require('node:fs');
    const path = require('node:path');
    
    const commands = [];
    // Grab all the command folders from the commands directory you created earlier
    const foldersPath = path.join(__dirname, 'commands');
    const commandFolders = fs.readdirSync(foldersPath);
    
    for (const folder of commandFolders) {
        // Grab all the command files from the commands directory you created earlier
        const commandsPath = path.join(foldersPath, folder);
        const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
        // Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
        for (const file of commandFiles) {
            const filePath = path.join(commandsPath, file);
            const command = require(filePath);
            if ('data' in command && 'execute' in command) {
                commands.push(command.data.toJSON());
            } else {
                console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
            }
        }
    }
    
    // Construct and prepare an instance of the REST module
    const rest = new REST().setToken(token);
    
    // and deploy your commands!
    (async () => {
        try {
            console.log(`Started refreshing ${commands.length} application (/) commands.`);
    
            // The put method is used to fully refresh all commands in the guild with the current set
            const data = await rest.put(
                Routes.applicationGuildCommands(clientId, guildId),
                { body: commands },
            );
    
            console.log(`Successfully reloaded ${data.length} application (/) commands.`);
        } catch (error) {
            // And of course, make sure you catch and log any errors!
            console.error(error);
        }
    })();
    

  2. I’ve noticed while developing that it may take a while before your Discord client actually sees your slash commands. You could check whether the commands show up when using the Discord app on your phone. Another way is to open a private browser and log into your account. Both these methods have worked for me in the past.

    Are you sure Discord actually acknowledges that the commands have been created/updated? I’m not sure how that could be done but I’d imagine discord.js will return an error when it failed.

    I digged a bit further into this and noticed an issue was filed on GitHub a couple of years ago. It states that the period to wait is up to 1 hour apparently.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search