creating a help command for my discord bot - javascript

I am trying to create a help page that lists all the commands for my discord bot...
currently everything is coming through as Undefined within the discord and I am confused as to why.
Here is my help.js
const fs = require('fs');
const { SlashCommandBuilder } = require('#discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('help')
.setDescription('Lists all available commands'),
async execute(interaction) {
let str = '';
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./${file}`);
str += `Name: ${command.name}, Description: ${command.description} \n`;
}
return void interaction.reply({
content: str,
ephemeral: true,
});
},
};
I could try to do the v12 way, but I am trying to make a bot that is completely up to date with v13...

Assuming all of your commands are structured like the code you presented, you were only missing a couple things. First was that the command name and description would be under command.data not just command. Also with let you can leave it empty (as I have) and fill it with anything.
const fs = require('fs');
const { SlashCommandBuilder } = require('#discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('help')
.setDescription('Lists all available commands'),
async execute(interaction) {
let str
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./${file}`);
str += `Name: ${command.data.name}, Description: ${command.data.description} \n`;
}
return interaction.reply({
content: str,
ephemeral: true,
});
},
};

Related

Javascript Discord bot not running correct function

Im trying to create a discord bot, theres one command that returns the ping when /ping is typed, and another one im trying to add that restarts the bot when /restart is typed. But when I type /restart, it functions like I typed /ping and replied with the ping. I cannot find a solution to my problem so any help is appreciated. If you need more information on this please reply to me.
Here is a file called "handleCommands" with its code:
const { REST } = require('discord.js');
const { Routes } = require('discord-api-types/v9');
const fs = require('fs');
const pingCommand = require(`./src/commands/tools/ping.js`);
const restartCommand = require('../../commands/tools/restart.js');
module.exports = (client) => {
client.handleCommands = async () => {
const commandFolders = fs.readdirSync('./src/commands');
for (const folder of commandFolders) {
const commandFiles = fs
.readdirSync(`./src/commands/${folder}`)
.filter((file) => file.endsWith(".js"));
const { commands, commandArray } = client;
for (const file of commandFiles) {
const command = require(`../../commands/${folder}/${file}`);
if (command.data.name !== 'restart') {
commands.set(command.data.name, command);
commandArray.push(command.data.toJSON());
} else {
commands.set(restartCommand.data.name, restartCommand);
commandArray.push(restartCommand.data.toJSON());
}
}
}
const clientId = '(BotsClientIdWentHere)';
const guildId = '(ServersClientIdWentHere';
const rest = new REST({ version: '9' }).setToken(process.env.token);
try {
console.log('Started refreshing application (/) commands.');
await rest.put(
Routes.applicationGuildCommands(clientId, guildId), {
body: client.commandArray,
});
console.log('Successfully reloaded application (/) commands.')
} catch (error) {
console.error(error);
}
};
};
Here is code from restart.js:
const { SlashCommandBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('restart')
.setDescription('Restarts the bot (Debug)'),
async execute(interaction, client) {
// Shut down the bot
await client.destroy();
// Log the bot back in to Discord
await client.login(MyBotsTokenWentHere);
// Send a message to confirm that the bot has been restarted
await interaction.editReply({
content: 'Bot restarted successfully'
});
}
}
A file called "interactionCreate":
module.exports = {
name: "interactionCreate",
async execute(interaction, client) {
console.log("Received interaction event:", interaction);
if (interaction.isChatInputCommand()) {
console.log("Received chat input command:", interaction.commandName);
const { commands } = client;
const { commandName } = interaction;
const command = commands.get(commandName);
if (!command) return;
try {
await command.execute(interaction, client);
} catch (error) {
console.error(error);
await interaction.reply({
content: `Something went wrong.. Please try again later. If this issue persists, please message my creator.`,
ephermeral: true,
});
}
}
},
};
And bot.js:
require("dotenv").config();
const { token } = process.env;
const { Client, Collection, GatewayIntentBits } = require("discord.js");
const fs = require("fs");
const client = new Client({ intents: GatewayIntentBits.Guilds });
client.commands = new Collection();
client.commandArray = [];
const functionFolders = fs.readdirSync(`./src/functions`);
for (const folder of functionFolders) {
const functionFiles = fs
.readdirSync (`./src/functions/${folder}`)
.filter((file) => file.endsWith('.js'));
for (const file of functionFiles)
require(`./functions/${folder}/${file}`)(client);
}
client.handleEvents();
client.handleCommands();
client.login(token);
Here is also the ping file code:
const { SlashCommandBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ping')
.setDescription('Returns the bots ping (Debug)'),
async execute(interaction, client) {
const message = await interaction.deferReply({
fetchReply: true
});
const currentTime = Date.now();
const responseTime = currentTime - interaction.createdTimestamp;
const responseTimeSeconds = responseTime / 1000; // convert to seconds
const newMessage = `API Latency: ${client.ws.ping}\nClient Ping: ${message.createdTimestamp - interaction.createdTimestamp}\nTime: ${responseTimeSeconds} seconds`
await interaction.editReply({
content: newMessage
});
}
}
And here I attacked a picture of the file heirarchy.
enter image description here
I tried to add functions that were supposed to add the function to table and add logs to the console to try to see what its printing but in the end the last error was "ReferenceError: (MyBotsTokenWentHere) is not defined". Any help appreciated.
Edit: Problem solved. Here is the updated restart.js and handleCommands files:
const { SlashCommandBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('restart')
.setDescription('Restarts the bot (Debug)'),
async execute(interaction, client) {
// Send a reply to the command message
await interaction.deferReply({
content: 'Restarting the bot...'
});
// Shut down the bot
await client.destroy();
// Log the bot back in to Discord
await client.login(MyBotsTokenWentHere);
// Edit the reply to confirm that the bot has been restarted
await interaction.editReply({
content: 'Bot restarted successfully'
});
}
}
handleCommands:
const { REST } = require('discord.js');
const { Routes } = require('discord-api-types/v9');
const fs = require('fs');
const pingCommand = require(`../../commands/tools/ping.js`);
const restartCommand = require('../../commands/tools/restart.js');
module.exports = (client) => {
client.handleCommands = async () => {
const commandFolders = fs.readdirSync('./src/commands');
for (const folder of commandFolders) {
const commandFiles = fs
.readdirSync(`./src/commands/${folder}`)
.filter((file) => file.endsWith(".js"));
const { commands, commandArray } = client;
for (const file of commandFiles) {
const command = require(`../../commands/${folder}/${file}`);
//console.log(`loading ${command.data.name} from commands/${folder}/${file}`)
if (command.data.name !== 'restart') {
commands.set(command.data.name, command);
commandArray.push(command.data.toJSON());
} else {
commands.set(restartCommand.data.name, restartCommand);
commandArray.push(restartCommand.data.toJSON());
}
}
}
const clientId = '(ClientIdWentHere)';
const guildId = '(GuildIdWentHere)';
const rest = new REST({ version: '9' }).setToken(process.env.token);
try {
console.log('Started refreshing application (/) commands.');
await rest.put(
Routes.applicationGuildCommands(clientId, guildId), {
body: client.commandArray,
});
console.log('Successfully reloaded application (/) commands.')
} catch (error) {
console.error(error);
}
};
};

How to set up a SlashCommand with custom options for discord

I've been at this for 4h now... I'm making a discord bot that should take a user's input and define the word using an API call. I have an index.js that should call my urban.js file and define a word a user inputs. For example, if a user inputs "/urban cow," the bot should put the definition of a cow. However, right now it cannot read the option after "/urban" no matter what I try.
// THIS IS MY urban.js FILE
const {
SlashCommandBuilder,
SlashCommandStringOption
} = require('#discordjs/builders');
const {
request
} = require('undici');
const {
MessageEmbed
} = require('discord.js');
const wait = require('node:timers/promises').setTimeout;
const trim = (str, max) => (str.length > max ? `${str.slice(0, max - 3)}...` : str);
async function getJSONResponse(body) {
let fullBody = '';
for await (const data of body) {
fullBody += data.toString();
}
return JSON.parse(fullBody);
}
module.exports = {
data: new SlashCommandBuilder()
.setName('urban')
.setDescription('Replies with definition!')
.addStringOption(option =>
option.setName('input')
.setDescription('word to define')
.setRequired(true)),
async execute(interaction) {
const term = interaction.options.getString('input')
console.log(term);
const query = new URLSearchParams({
term
});
const dictResult = await request(`https://api.urbandictionary.com/v0/define?${query}`);
const {
list
} = await getJSONResponse(dictResult.body);
if (!list.length) {
return interaction.editReply(`No results found for **${term}**.`);
}
const [answer] = list;
const embed = new MessageEmbed()
.setColor('#EFFF00')
.setTitle(answer.word)
.setURL(answer.permalink)
.addFields({
name: 'Definition',
value: trim(answer.definition, 1024)
}, {
name: 'Example',
value: trim(answer.example, 1024)
}, {
name: 'Rating',
value: `${answer.thumbs_up} thumbs up. ${answer.thumbs_down} thumbs down.`,
}, );
interaction.editReply({
embeds: [embed]
});
},
};
// THIS IS THE INDEX JS FILE. It's not a filepath issue.
const {
token
} = require('./config.json');
const fs = require('node:fs');
const path = require('node:path');
const {
Client,
Collection,
Intents,
MessageEmbed,
DiscordAPIError
} = require('discord.js');
const wait = require('node:timers/promises').setTimeout;
const client = new Client({
intents: [Intents.FLAGS.GUILDS]
});
client.commands = new Collection();
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
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));
}
}
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
// Set a new item in the Collection
// With the key as the command name and the value as the exported module
client.commands.set(command.data.name, command);
}
client.once('ready', () => {
console.log('Ready!');
});
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
await interaction.deferReply({
ephemeral: true
});
await wait(4000);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
}
});
console.log(token)
client.login(token)
When I console.log(interaction.options.getString('input'))
it just gives me null.
when I console.log interaction it gives me a detailed account of the command and everything else like the user that sent it. But none of the information from the SlashCommand data. Please help.

Cannot read properties of null (reading 'id') [Discord Slash Commands]

I'm trying to get a little familiar with the slash command handler, but I get an error when trying to grab the member id, this happens with just about everything I try to grab.
Here at the top is directly my command, where I try to send a message with the content "user.id".
this is my command:
const { SlashCommandBuilder } = require("#discordjs/builders");
module.exports = {
data: new SlashCommandBuilder()
.setName("avatar")
.setDescription("SERVUSSS")
.addUserOption(option => option.setName("member").setDescription("memberdings").setRequired(true)),
async execute(interaction) {
const user = interaction.options.getUser('target');
await interaction.reply(`${user.id}`);
}
}
this is my deploy file:
require("dotenv").config();
const fs = require("fs");
const { REST } = require("#discordjs/rest");
const { Routes } = require("discord-api-types/v9");
const commands = [];
const commandFiles = fs.readdirSync("./src/commands").filter(file => file.endsWith(".js"));
commandFiles.forEach(commandFile => {
const command = require(`./commands/${commandFile}`);
commands.push(command.data.toJSON());
});
const restClient = new REST({version: "9"}).setToken(process.env.TOKEN);
restClient.put(Routes.applicationGuildCommands(process.env.APPLICATION_ID, process.env.GUILD_ID),
{body: commands }).then(() => console.log("success")).catch(console.error);
my index file:
require("dotenv").config();
const { Client, Collection } = require("discord.js");
const fs = require("fs");
const client = new Client({intents: []});
client.commands = new Collection();
const commandFiles = fs.readdirSync("./src/commands").filter(file => file.endsWith(".js"));
commandFiles.forEach(commandFile => {
const command = require(`./commands/${commandFile}`);
client.commands.set(command.data.name, command);
});
client.once("ready", () => {
console.log("ready!!");
});
client.on("interactionCreate", async (interaction) => {
if(!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName)
if(command) {
try {
await command.execute(interaction)
} catch(error) {
console.log(error)
if(interaction.deferred || interaction.replied) {
interaction.editReply("error")
} else {
interaction.reply("error")
}
}
}
})
client.login(process.env.TOKEN)
I actually stick to it pretty much all the time
https://discordjs.guide/ just do not understand what I'm doing wrong
Since option name is member then it's going to be
const user = interaction.options.getUser('member');
In your command file, the name for the option is given as member, but when you are using interaction.options.getUser(), you are passing the name as 'target'. So all you have to do is change the line where you are declaring the user to: const user = interaction.options.getUser('member')

My slash command handler doesn't work, but there are no errors

I was adapting my command handler to work with slash and it worked, but now I have other problems
1 - When I try to run the /ping command, "interaction failed" appears and there is no error on the console
2 - I put some console.log() to see if it was delivering the right value, but some variables gave undefined
This is my command handler (index.js):
const fs = require('fs');
const pComandos = fs.readdirSync('Comandos');
client.commands = new Discord.Collection();
client.description = new Discord.Collection();
for (const folder of pComandos) {
const file = fs.readdirSync('Comandos/' + folder);
for (const comando of file) {
let cmd = require(`./Comandos/${folder}/${comando}`);
commandsArray = [];
console.log(chalk.green(`[ C ] O comando ` + chalk.bold(comando) + ` foi carregado!`))
client.commands.set(cmd.help.name, cmd)
if (cmd.help.description) {
cmd.desc = true
cmd.help.description.forEach(desc => client.commands.set(desc, cmd))
}
client.commands.set(cmd)
commandsArray.push({
name: cmd.help.name,
description: cmd.help.description.join("")
})
if (cmd.init) cmd.init(client)
client.on("ready", async() => {
const server = await client.guilds.cache.get("892210305558532116")
server.commands.set(commandsArray)
})
}
}
The interaction event (interactionCreate.js):
const { Interaction, CommandInteraction } = require("discord.js");
const fs = require("fs");
exports.run = (client, interaction) => {
if (interaction.isCommand()) {
const pComandos = fs.readdirSync('./Comandos');
for (const folder of pComandos) {
let file = fs.readdirSync("./Comandos/" + folder);
console.log(file) // [ 'ping.js' ]
for (const comando of file) {
let cmd = require(`../../Comandos/${folder}/${comando}`);
console.log(cmd)
/*
{
run: [AsyncFunction (anonymous)],
help: { name: 'ping', description: [ 'Pong!' ] },
desc: true
}
*/
let command =
client.commands.get(cmd) ||
client.commands.get(client.description.get(cmd));
console.log(command) // undefined
console.log(client.commands.get(cmd)) // undefined
if (command) {
command.run(client, interaction);
}
}
}
}
};
The ping command (ping.js):
const discord = require("discord.js");
exports.run = async (client, interaction) => {
interaction.deferUpdate();
var latencia = Date.now() - interaction.createdTimestamp
interaction.reply({content: `<:emoji_3:892431734203891722> | Ping atual do client: ${client.ws.ping} (${latencia}).\n🗺 | Timezone: ${process.env.TZ}`});
};
exports.help = {
name: "ping",
description: ["Pong!"]
};
This is my file organization: https://prnt.sc/20ddh4e
And the console (Console.log values ​​are in the interactionCreate.js code): https://prnt.sc/20ddnlv
You should call interaction.deferReply() followed by interaction.editReply(content). interaction.deferUpdate() is used for updates, not replies.

Making a Server User ID function | Discord.js

I am trying to get all user's ID and name from a server which I done so by using this:
const list = client.guilds.cache.get("GUILD_ID");
list.members.cache.forEach(member => console.log('Name: ' + member.user.username + ' ID: ' + member.user.id));
But i want to input those member ID's and names into a .json file and I tried doing this via a function:
const Discord = require('discord.js');
const client = new Discord.Client();
const token = 'TOKEN';
const prefix = 'a';
const getuser = require('./GetUserId/getID.json');
const fs = require('fs');
const { readdirSync } = require("fs");
const { join } = require("path");
client.commands = new Discord.Collection();
const commandFiles = readdirSync(join(__dirname, "GetUserId")).filter(file => file.endsWith(".js"));
for (const file of commandFiles) {
const command = require(join(__dirname, "GetUserId", `${file}`));
client.commands.set(command.name, command);
}
client.on('message', message => {
if (message.content === 'getID'){
getuser(message);
function getuser (message) {
const list = client.guilds.cache.get("749337851174322288");
if(!getuser[message.author.id]){
getuser[message.author.id] = {
ID: `${list.members.cache.forEach(member => member.user.id)}`,
Name: `${list.members.cache.forEach(member => member.user.username)}`
}
}
fs.writeFile('./GetUserId/getID.json', JSON.stringify(getuser, null, 2), (err) => {
if (err) console.log(err)
})
}
message.delete()
message.channel.send(`*Done.*`)
}
})
client.login(token);
So I tried this code and this came on the .json file:
{
"709827684888215582": {
"ID": "undefined",
"Name": "undefined"
}
}
How would I make the "ID" display user ID's and display all members username in "Name:" in a server/guild in that .json file?
You're looking for Array.prototype.map(), not Array.prototype.forEach()
forEach() simply executes a function on all elements of an array (or a Collection, in this case). map() creates a new array populated with the results of the function.

Categories

Resources