How to make this function start via a slash command - javascript

I have a piece of code that automatically runs every 4 hours to send a set message to a specific discord channel on my discord server but I would like to have this function start upon command and I would like that command to be in a separate file from my main index code if someone could give me a template for this code as a slash command I would greatly appreciate it you would be saving me days possibly weeks of tedious research and trial and error I need code that is up to date with v13 of discord.js and that will be compatible with my main index file code which will be set below the specific function that I want accomplished.
setInterval(() => {
client.channels.cache.get("916642101989617684").send("!stats");
}, (1000 * 60) * 240);
const fs = require('fs');
const { Client, Collection, Intents } = require('discord.js');
const { token } = require('./config.json');
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
client.commands = new Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.data.name, command);
}
const eventFiles = fs.readdirSync('./events').filter(file => file.endsWith('.js'));
for (const file of eventFiles) {
const event = require(`./events/${file}`);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
client.once('ready', () => {
console.log('Ready!');
});
setInterval(() => {
client.channels.cache.get("916642101989617684").send("!stats");
}, (1000 * 60) * 240);
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
return interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
});
client.login(token);

Simply put it in an interactionCreate event, but make sure it's once so that it doesn't constantly make more intervals
client.once("interactionCreate", async (interaction) => {
if (interaction.commandName === "register") { //or whatever name the command should be
//the code you want to start here
})

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 do I Build a discord button that replies with a new set of button

I want it to be where you type in your slashcommand example:"/bank" and it'll show 2 different buttons "offense" "defense" then when you click one of those buttons it'll pop up another set up buttons to click from. Right now it works to where I do /bank and it'll reply with the two buttons offense and defense and it'll reply with you clicked which ever button was clicked. But I want to to reply with another set up buttons.
// this is my button command
bank.js
const { SlashCommandBuilder } = require('#discordjs/builders');
const { MessageActionRow, MessageButton, MessageEmbed } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('bank')
.setDescription('Replies with some buttons!'),
async execute(interaction) {
const row = new MessageActionRow()
.addComponents(
new MessageButton()
.setCustomId('offense')
.setLabel('Offense')
.setStyle('SUCCESS'),
new MessageButton()
.setCustomId(' defense')
.setLabel('Defense')
.setStyle('DANGER'),
);
const embed = new MessageEmbed()
.setColor('#0099ff')
.setTitle('Map: BANK ')
.setURL('https://discord.js.org')
.setImage('https://i.imgur.com/s54Riow.jpeg')
.setDescription('Choose your team shitter');
await interaction.reply({ ephemeral: true, embeds: [embed], components: [row] });
},
};
this is my
interactionCreate.js
module.exports = {
name: 'interactionCreate',
async execute(interaction, client) {
if(interaction.isButton())
interaction.reply("you clicked" + interaction.customId);
console.log(interaction);
if (!interaction.isCommand()) return;
if (!interaction.isButton()) return;
const command = client.command.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 action"})
}
console.log(`${interaction.user.tag} in #${interaction.channel.name} triggered an interaction.`);
},
};
this is my index.js
// Require the necessary discord.js classes
const fs = require('node:fs');
const path = require('node:path');
const { Client, Collection, Intents } = require('discord.js');
const { token } = require('./config.json');
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
client.commands = new Collection();
// command files
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);
}
// event files
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));
}
}
// When the client is ready, run this code (only once)
client.once('ready', c => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
// When any message is sent in any channel it'll all be logged into the terminal
client.on('message', async msg => {
if(!msg.content.startsWith(config.prefix)) return;
var command = msg.content.substring(1);
if(!client.commands.has(command)) return;
try{
await client.commands.get(command).execute(msg);
} catch(error) {
console.error(error);
await msg.reply({content: "there was an error", epthemeral: true})
}
});
// interaction files
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) 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 });
}
});
// Login to Discord with your client's token
client.login(token);
this is my deploy-commands.js
const fs = require('node:fs');
const path = require('node:path');
const { REST } = require('#discordjs/rest');
const { Routes } = require('discord-api-types/v9');
const { clientId, guildId, token } = require('./config.json');
const commands = [];
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
commands.push(command.data.toJSON());
}
const rest = new REST({ version: '9' }).setToken(token);
(async () => {
try {
console.log('Started refreshing application (/) commands.');
await rest.put(
Routes.applicationGuildCommands(clientId, guildId),
{ body: commands },
);
console.log('Successfully reloaded application (/) commands.');
} catch (error) {
console.error(error);
}
})();
We will be working inside of your interactionCreate.js where you collect the buttons.
We will need to update the interaction with the new message. docs
I am noticing duplicate code in your index.js and interactionCreate.js. This is where you run the slash commands. As a recommendation, you may want to remove the if (!interaction.isCommand()) return; in the interactionCreate.js and remove the index.js listener. Just to have one file handing the interactionCreate event. I'll be doing this in the example.
Also you may find a problem in the future since in blank.js there is a space inside of the interaction customId.
Example with one Listener
const { MessageButton, MessageActionRow } = require('discord.js');
module.exports = {
name: 'interactionCreate',
async execute(interaction, client) {
if (interaction.isCommand()) { // Checks if the interaction is a command and runs the `
const command = client.command.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 action"})
}
console.log(`${interaction.user.tag} in #${interaction.channel.name} triggered an interaction.`);
return;
} else if (interaction.isButton()) { // Checks if the interaction is a button
interaction.reply("you clicked" + interaction.customId);
console.log(interaction);
if (interaction.customId === 'offense') { // Check for the customId of the button
console.log(`${interaction.user.tag} in #${interaction.channel.name} clicked the offense button.`);
const ActionRow = new MessageActionRow().setComponents(new MessageButton() // Create the button inside of an action Row
.setCustomId('CustomId')
.setLabel('Label')
.setStyle('PRIMARY'));
return interaction.update({ // update the interaction with the new action row
content: 'Hey',
components: [ActionRow],
ephemeral: true
});
}
}
},
};
With the original example
module.exports = {
name: 'interactionCreate',
async execute(interaction, client) {
if(interaction.isButton()) {
interaction.reply("you clicked" + interaction.customId);
console.log(interaction);
if (interaction.customId === 'offense') { // Check for the customId of the button
console.log(`${interaction.user.tag} in #${interaction.channel.name} clicked the offense button.`);
const ActionRow = new MessageActionRow().setComponents(new MessageButton() // Create the button inside of an action Row
.setCustomId('CustomId')
.setLabel('Label')
.setStyle('PRIMARY'));
return interaction.update({ // update the interaction with the new action row
content: 'Hey',
components: [ActionRow],
ephemeral: true
});
}
return;
}
if (!interaction.isCommand()) return;
if (!interaction.isButton()) return;
const command = client.command.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 action"})
}
console.log(`${interaction.user.tag} in #${interaction.channel.name} triggered an interaction.`);
},
};
If you need to get the embed that was sent in the original message, you can use <interaction>.embeds to get the embed and then edit it to your liking.
Now if you don't want to edit the interaction and reply with a new message remember that if your original message is an ephemeral you can't delete it. You can use replying methods.
Explanation
We are checking for the customId that was used when building the button. After we create an action row and add the new message button. Then we are updating the original message content with different components.
Feel free to leave a comment if you run into any problems

JavaS. Cannot read property 'filter' of undefined

I have such a question because I no longer know what to do. I have a BOT on Suggestion to a certain channel. When I run the bot via Visual Studio Code, the bot runs and everything works. But as soon as I load a boot on heroku.com, the program suddenly writes an error:
files = files.filter(f => f.endsWith(".js"))
Someone could help me, I would be very happy. Have a nice day
Index.js is here:
client.once('ready', () => {
console.log('Tutorial Bot is online!');
});
client.commands = new Discord.Collection()
const fs = require("fs")
fs.readdir("./commands/", (error, files) => {
files = files.filter(f => f.endsWith(".js"))
files.forEach(f => {
const command = require(`./commands/${f}`)
client.commands.set(command.name, command)
console.log(`Command ${command.name} was loaded!`)
});
});
client.on("message", message => {
if (message.author.bot) return;
if (message.channel.type === "dm") return;
if (!message.content.startsWith(config.prefix)) return;
const args = message.content.slice(config.prefix.length).split(" ")
const command = args.shift()
const cmd = client.commands.get(command)
if (cmd) {
cmd.run(client, message, args)
} else return;
});
bot.login(config.token);
Suggest.js is here
const { MessageEmbed } = require("discord.js");
module.exports = {
name: "suggest",
aliases: [],
description: "Make a suggestion and have the community vote",
category: "utility",
usage: "suggest <suggestion>",
run: async (client, message, args) => {
let suggestion = args.slice(0).join(" ");
let SuggestionChannel = message.guild.channels.cache.find(channel => channel.name === "suggestions");
if (!SuggestionChannel) return message.channel.send("Please create a channel named suggestions before using this command!");
const embed = new MessageEmbed()
.setTitle("New Suggestion")
.setDescription(suggestion)
.setColor("RANDOM")
.setFooter(`${message.author.tag} | ID: ${message.author.id}`)
.setTimestamp()
SuggestionChannel.send(embed).then(msg => {
msg.react("👍🏼")
msg.react("👎🏼")
message.channel.send("Your suggestion has been sent!");
});
}
}
You forgot to check for errors in your callback. In case of an error files will be undefined, thus resulting in the error you've observed. So you should do something like:
fs.readdir("./commands/", (error, files) => {
if(error) {
// handle error
} else {
files = files.filter(f => f.endsWith(".js"))
files.forEach(f => {
const command = require(`./commands/${f}`)
client.commands.set(command.name, command)
console.log(`Command ${command.name} was loaded!`)
});
}
});

Discord.js bot can't send message to specific channel

I'm trying to make my bot send a message to a specific channel on Discord. However, when I use the command it results in an error: TypeError: Cannot read property 'cache' of undefined .
Here's my code:
module.exports = {
name: 'send',
description: 'sends a message testing',
execute(client) {
const channel01 = client.channels.cache.find(channel => channel.id === "768667222527705148");
channel01.send('Hi');
},
};
In my index.js file, I have the following in the beginning, so I don't think the client usage in front of .channels is the problem.
const fs = require('fs');
const Discord = require('discord.js');
const { prefix, token } = require('./config.json');
const client = new Discord.Client();
client.commands = new Discord.Collection();
Here's my Index.js file.
const fs = require('fs');
const Discord = require('discord.js');
const { prefix, token } = require('./config.json');
const client = new Discord.Client();
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
const cooldowns = new Discord.Collection();
client.once('ready', () => {
console.log('Ready!');
client.user.setActivity("KevinYT", {
type: "WATCHING",
url: "https://www.youtube.com/channel/UCUr50quaTjBKWL1fLuWRvCg?view_as=subscriber"
});
});
client.on('message', message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).trim().split(/ +/);
const commandName = args.shift().toLowerCase();
const command = client.commands.get(commandName)
|| client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
if (!command) return;
if (command.guildOnly && message.channel.type === 'dm') {
return message.reply('I can\'t execute that command inside DMs!');
}
if (command.args && !args.length) {
let reply = `You didn't provide any arguments, ${message.author}!`;
if (command.usage) {
reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``;
}
return message.channel.send(reply);
}
if (!cooldowns.has(command.name)) {
cooldowns.set(command.name, new Discord.Collection());
}
const now = Date.now();
const timestamps = cooldowns.get(command.name);
const cooldownAmount = (command.cooldown || 3) * 1000;
if (timestamps.has(message.author.id)) {
const expirationTime = timestamps.get(message.author.id) + cooldownAmount;
if (now < expirationTime) {
const timeLeft = (expirationTime - now) / 1000;
return message.reply(`please wait ${timeLeft.toFixed(1)} more second(s) before reusing the \`${command.name}\` command.`);
}
}
timestamps.set(message.author.id, now);
setTimeout(() => timestamps.delete(message.author.id), cooldownAmount);
try {
command.execute(message, args);
} catch (error) {
console.error(error);
message.reply('there was an error trying to execute that command!');
}
});
client.login(token);
What am I missing? Thanks!
command.execute(message, args)
You're passing the execute function message (a Message object) as the first argument but you're trying to use it as a Client object. The code fails since message.channels is undefined (the confusion arises from the argument name used in the execute function).
You can use message.client to get access to the Client object.
module.exports = {
// ...
execute (message) {
const channel01 = message.client.channels.cache.find(
(channel) => channel.id === '768667222527705148'
)
// ...
},
}

How do I make a discord bot welcome command and leave command

I want to create an embedded welcome command and leave command. I would like an embedded DMS message for the person who joined the server.
This is the code I have so far:
const fs = require('fs');
const Discord = require('discord.js');
const {
prefix,
token
} = require('./config.json');
const client = new Discord.Client();
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
const cooldowns = new Discord.Collection();
client.on('guildMemberAdd', member => {
if (!member.guild) return;
let guild = member.guild
let channel = guild.channels.cache.find(c => c.name === "welcome");
let membercount = guild.members
if (!channel) return;
let embed = new Discord.MessageEmbed().setColor("GREEN").setTitle("New Server Member!").setDescription(`Welcome, ${member.user.tag} to **${guild.name}!**`).setThumbnail(member.user.displayAvatarURL()).setFooter(`You are the ${membercount}th member to join`);
message.guild.channels.cache.find(i => i.name === 'sp').send(embed)
});
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
client.user.setPresence({
status: "idle", //You can show online, idle.... activity: {
name: "with lower lifeforms!", //The message shown type: "PLAYING", // url: "" //PLAYING: WATCHING: LISTENING: STREAMING:
}
});
});
client.on('message', message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).trim().split(/ +/);
const commandName = args.shift().toLowerCase();
const command = client.commands.get(commandName) || client.commands.find.Discord(cmd => cmd.aliases && cmd.aliases.includes(commandName));
if (!command) return;
if (command.guildOnly && message.channel.type === 'dm') {
return message.reply('I can\'t execute that command inside DMs!');
}
if (command.args && !args.length) {
let reply = `You didn't provide any arguments, ${message.author}!`;
if (command.usage) {
reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``;
}
return message.channel.send(reply);
}
if (!cooldowns.has(command.name)) {
cooldowns.set(command.name, new Discord.Collection());
}
const now = Date.now();
const timestamps = cooldowns.get(command.name);
const cooldownAmount = (command.cooldown || 3) * 1000;
if (timestamps.has(message.author.id)) {
if (timestamps.has(message.author.id)) {
const expirationTime = timestamps.get(message.author.id) + cooldownAmount;
timestamps.set(message.author.id, now);
setTimeout(() => timestamps.delete(message.author.id), cooldownAmount);
if (now < expirationTime) {
const timeLeft = (expirationTime - now) / 1000;
return message.reply(`please wait ${timeLeft.toFixed(1)} more second(s) before reusing the \`${command.name}\` command.`);
}
}
}
try {
command.execute(message, args);
} catch (error) {
console.error(error);
message.reply('there was an error trying to execute that command!');
}
});
client.login(token);
Now on Discord, you will need to enable intents. To do this, go to the Discord Developer Portal, select your application, and go onto the Bot tab. If you scroll about half way down, you'll see a section called Privileged Gateway Intents. You need to tick Server Members Intent under that title. For what you're doing, Presence Intent shouldn't be required, but you can tick it in case you do ever need it.

Categories

Resources