Discord.js slash command register code not working - node.js

I‘m working on a discord bot with node.js and I wanted to register slash commands. Now, when i run in the shell, the following error gets throwed:
What should I do to correct it?
Here is where I got the code from: https://discordjs.guide/creating-your-bot/command-deployment.html#command-registration.
And this is the code:
const { REST, Routes } = require('discord.js');
const { clientId, guildId, token } = require('./config.json');
const fs = require('node:fs');
const commands = [];
// Grab all the command files from the commands directory you created earlier
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
commands.push(JSON.stringify(command.data));
}
// Construct and prepare an instance of the REST module
const rest = new REST({ version: '10' }).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.applicationCommands(clientId),
{ 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);
}
})();

The only logic derivation that I find from my code is in line 12
commands.push(command.data.toJSON())
This is also the way discord.js guide suggests it: https://discordjs.guide/creating-your-bot/command-deployment.html#guild-commands

Related

onValue triggering multiple times

I'm using Node.js v18.12.1 and Discord.js v14. for developing the Discord bot. I need to read some data from Firebase. I'm confused because I'm used to how Java with Hibernate fetches data differently. Here, I need to use onValue() listener.
My onValue() acts strange. Instead of just reading the data from Firebase, it skips entirely, then it triggers multiple times, each time skipping the body block of its code, and then it actually does the code after.
I've read somewhere on this forum that this can happen because there are more onValue() listeners that are subscribed and they are all fired up. Someone mentioned I need to use the off() function somewhere "before" the onValue(). This confuses me because I'm using this listener in many locations. I need it in each command file, in execute(interaction) functions. You know, when you need to execute slash commands in Discord. I have it something like this:
async execute(interaction) {
const infographicRef = ref(db, '/infographics/arena/' + interaction.options.getString("arena-team"));
var imageUrl = null;
var postUrl = null;
onValue(infographicRef, (snapshot) => {
imageUrl = snapshot.child("image-url").val();
interaction.reply(imageUrl);
})
},
And I planned for each command, in each command.js file to have onValue(). I'm not sure exactly what to do.
Also, I tried to work around this with once() method, I see it in Firebase documentation, but I got the error: ref.once() is not a function.
It seems that after first triggering of onValue method when the body is not executed, my code in interactionCreate.js is triggered as well, it points for a command to be executed again:
const { Events } = require('discord.js');
module.exports = {
name: Events.InteractionCreate,
async execute(interaction) {
if (!interaction.isChatInputCommand()) return;
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
try {
await command.execute(interaction);
} catch (error) {
console.error(`Error executing ${interaction.commandName}`);
console.error(error);
}
},
};
my bot.js (which is in my case an index file)
const fs = require('node:fs');
const path = require('node:path');
const { Client, Collection, Events, GatewayIntentBits } = require('discord.js');
const { token } = require('./config.json');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));
for (const file of eventFiles) {
const filePath = path.join(eventsPath, file);
const event = require(filePath);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
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);
}
client.once(Events.ClientReady, () => {
console.log('Ready!');
});
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
});
client.login(token);
The onValue function registers a realtime listener, that continues to monitor the value on the database.
If you want to read a value once, that'd be done with get() function in v9 (which is the equivalent of the once method in earlier SDK versions). Have a look at the code sample in the documentation on reading data once.

Why am i getting this token error even though I have set it up correctly?

I am making a discord bot using dicord.js. And I have this following code in index.js.
require('dotenv').config();
const { BOT_TOKEN, APP_ID, GUILD_ID } = process.env;
const client = new Client({ intents: [], rest: { version: '10' } });
client.rest.setToken(BOT_TOKEN);
async function main() {
try {
client.slashCommands = new Collection();
await registerCommands(client, '../commands');
console.log(client.slashCommands);
const slashCommandsJson = client.slashCommands.map((cmd) =>
cmd.getSlashCommandJSON()
);
console.log(slashCommandsJson);
await client.rest.put(Routes.applicationGuildCommands(APP_ID, GUILD_ID), {
body: slashCommandsJson,
});
const registeredSlashCommands = await client.rest.get(
Routes.applicationGuildCommands(APP_ID, GUILD_ID)
);
console.log(registeredSlashCommands);
await client.login(BOT_TOKEN);
} catch (err) {
console.log(err);
}
}
main();`
I have set up the token code in .env file and yet i am still getting this error which I am not quite sure about
Error: Expected token to be set for this request, but none was present
at _RequestManager.resolveRequest (C:\Users\node_modules\#discordjs\rest\dist\lib\RequestManager.cjs:142:15)
at _RequestManager.queueRequest (C:\Users\node_modules\#discordjs\rest\dist\lib\RequestManager.cjs:115:46)
at REST.raw (C:\Users\node_modules\#discordjs\rest\dist\lib\REST.cjs:56:32)
at REST.request (C:\Users\node_modules\#discordjs\rest\dist\lib\REST.cjs:52:33)
at REST.put (C:\Users\node_modules\#discordjs\rest\dist\lib\REST.cjs:46:17)
at main (C:\Users\src\index.js:31:23)
I Actually Dont Know About ENV. So I Recommend Making A Config File Or Apply Token Directly :)

Discord Bot use slash command

i want to let a bot use slash commands of another bot. If i send a message like /help it will not use the Slash function, instead it will just send "/help" (is not using the Slash Command function).
Does anyone know if this is even possible?
Bots cannot use other bot's slash commands, as they're not able to send Application Command Interactions, only receive them.
If the other bot still uses regular message-prefix commands (like !help), you can try sending a message with the command, but most bots ignore commands from other bots as it is a best practice to do so.
If the bot on the other end is developed by you, you can program it to allow message commands from your first bot, but be very careful not to create infinite loops.
Assuming my comment is what you were looking for this should solve your query.
// Bot 1
const {
Client
} = require("discord.js")
const client = new Client({
intents: '...'
})
const prefix = '/'
client.on('messageCreate', async message => {
if (message.content.startsWith(prefix) && !message.author.bot) {
const command = `/${message.content}`
const response = message.reply(`${message.author}, relaying command`)
await response.then(message.channel.send(command))
}
})
// Bot 2
const {
Client
} = require("discord.js")
const client = new Client({
intents: '...'
})
const bot_1_id = '4654564984981981894654'
const prefix = '/'
client.on('messageCreate', async message => {
if (message.author.bot && message.author.id === bot_1_id && message.content.startsWith(prefix)) {
const args = message.content.slice(prefix.length).trim().split(/ +/)
const cmd = args.shift().toLowerCase()
const command = client.commands.get(cmd)
// if you don't have command files
if (cmd === 'help') {
message.channel.send(`${message.author} I recognized your help command`)
return
}
// if you have a command files see below script for file
if (!command) return
try {
command.execute(message, args)
} catch (error) {
console.error(error)
message.reply(`Couldn't run command`)
}
} else {
return
}
})
Optional if you want to/do use command files
// Command File
module.exports = {
name: 'help',
description: 'help command',
async execute(message, args) {
message.channel.send(`${message.author} I recognized your help command`)
return
}
}

Discord.js/Firestore .where() is not a function

I am trying to integrate my discord bot with firestore. Whenever I try to run a query I get .where is not a function and I don't understand why because everything else seems to work. Here is the relevant code. I have tried the require of firebase at the top of Remove.js and that doesn't seem to do anything.
Here is my thought to how I believe it should be working right now.
I run node . and it then runs my index.js file.
On an interaction create (i.e. a slash command is created) it checks the command file and in this case it is the remove command
It calls execute(interaction, db) where interaction is the interaction slash command and db is the admin.Firestore() db reference from index.js. I am fully able to use get commands (i.e. that first chunk of code works before I try to delete)
Because this is a reference I should be able to call .where() based on the Firestore documentation and yet I am hit with the error "TypeError: db.collection(...).doc(...).collection(...).doc(...).where is not a function"
// Index.js
// General Setup
const { Client, Collection, Intents } = require('discord.js')
const config = require('./config.json')
const fs = require('fs')
// Bot Setup
const myIntents = new Intents();
myIntents.add(Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MEMBERS)
const bot = new Client({intents: myIntents});
// Firebase Setup
const firebase = require('firebase/app')
const fieldValue = require('firebase-admin').firestore.FieldValue
const admin = require('firebase-admin')
const serviceAccount = require('./serviceAccount.json')
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
})
let db = admin.firestore();
// Command Setup
bot.commands = new Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'))
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
bot.commands.set(command.data.name, command);
}
// Bot Login
bot.once('ready', async () => {
console.log('Wheatley is online!');
});
bot.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) {
return
}
const command = bot.commands.get(interaction.commandName)
if (!command) {
return
}
try {
await command.execute(interaction, db)
} catch (error) {
console.error(error)
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true})
}
});
bot.login(config.bot_token);
///Remove.js
const { SlashCommandBuilder } = require('#discordjs/builders');
require('#firebase/firestore');
module.exports = {
data: new SlashCommandBuilder()
.setName('remove')
.setDescription('Removes object from collection')
.addStringOption(option =>
option.setName('item')
.setDescription('Enter an item in the collection to remove')
.setRequired(true)
),
async execute(interaction, db) {
const itemName = await interaction.options.getString('item')
const itemToDelete = db.collection('items').doc(interaction.guildId).collection('items').doc(itemName);
const doc = await itemToDelete.get();
if(!doc.exists) {
return interaction.reply({
content: `${itemName} does not exist in the collection. Try using /list to check for the right name.`,
ephemeral: true
})
}
const ownerId = interaction.user.id
const snapshot = db.collection('items').doc(interaction.guildId).collection('items').doc(itemName).where("ownerId", "==", ownerId).get();
if(!snapshot.exists) {
return interaction.reply({
content: `You are not the owner of ${itemName}. Please contact owner to delete this from the collection`,
ephemeral: true
})
}
itemToDelete.delete();
return await interaction.reply(`${itemName} was removed from the collection!`)
},
};
You are using where on a document, as where is a query function that is only available to collections.
Just be warned that the snapshot will return an array of snapshots as it is a query, not a single document.
Try this instead:
const snapshot = db.collection('items').doc(interaction.guildId).collection('items').where("ownerId", "==", ownerId).get();

Discord bot only registers first one slash command

I'm trying to upgrade one of my bots to use the new slash commands featured in Discord.js v13. I have done some research and figured out how to register slash commands, and how to respond to them. I then spent some time amending my current command handler and came up with this:
client.commands = new Map();
fs.readdir("./commands/", async (err, files) => {
if (err) return console.error(err);
if (!client.application?.owner) await client.application?.fetch();
let count = 0;
let commands = [];
for (let file of files) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
let commandData = { name: command.name };
count += 1;
const slashCommand = await client.guilds.cache.get("GUILD ID")?.commands.create(commandData);
}
console.log(`Registerd ${count} commands!`);
});
Here is also the code within my interactionCreate event and my two commands:
module.exports = async (client, interaction) => {
if (!interaction.isCommand()) return;
const command = await client.commands.get(interaction.commandName);
command.run(client, interaction);
}
module.exports = {
name: "ping",
async run(client, interaction) {
interaction.reply("Pong!");
}
}
module.exports = {
name: "pong",
async run(client, interaction) {
interaction.reply("Ping!");
}
}
All of this works almost perfectly, however my bot only seems to create the first slash command ping. The other command is added to the client.commands map fine, but when I try and run /pong nothing happens.

Resources