Hi I'm making a Javascript based Discord bot, and I really wanted to implement the new Discord Buttons feature, the problem is, even using the documentation examples, I get the same error, again and again :
(node:6184) UnhandledPromiseRejectionWarning: DiscordAPIError: Cannot send an empty message
Here is the code (I am using module.exports with separated files for each commands) :
const { MessageButton } = require('discord-buttons')
module.exports = {
name: 'invite',
descritipion: 'test command',
async execute(client, message, args) {
let button = new MessageButton()
.setStyle('url')
.setURL('https://npmjs.com/discord-buttons')
.setLabel('Click me !')
await message.channel.send('Hey, I am powered by npm discord-buttons : https://npmjs.com/discord-buttons');
await message.channel.send(button);
}
}
You cannot just send a button on its own. Instead, try adding the button to the previous message so they both get sent in one message as shown below
The official documentation for this is here
// Replace these
const { MessageButton } = require('discord-buttons')
await message.channel.send('Hey, I am powered by npm discord-buttons : https://npmjs.com/discord-buttons');
await message.channel.send(button);
// With these
const { MessageButton, MessageActionRow } = require('discord-buttons')
await message.channel.send('Hey, I am powered by npm discord-buttons : https://npmjs.com/discord-buttons', {
component: new MessageActionRow().addComponent(button)
});
Also, did you forget to initialize DiscordButtons? Do it when you initialize your discord bot
// Where you initialized your discord bot
const bot = new Discord.Client()
// Add this line
require("discord-button")(bot)
Related
actually i´m working and learning about discord.js and node.js to make a bot, but i have a simple issue, and i don´t know why the embed messages doesn´t work, i tried with the documentarion examples and code of other devs, but in all cases when i try to send the message to a channel, using client.reply(embed) throws me an error saying me that can send an empty message.
i´m using the last version of discord.js (v13.3.1) and i´m using the basic documentation event and the command handlers (works perfectly if i don´t try to send embeds).
This is my index.js and my help.js files:
//This is my index.js i don´t have problem with this but i include it if there are an issue related with this topic.
const fs = require('fs');
const { Client, Collection, Intents } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });
const { token } = require('./config.json');
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);
}
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: 'Parece que ha ocurrido algun problema con el comando.', ephemeral: true });
}
});
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.login(token);
Now the help.js , this is going to be a Command, but i don´t wanna only to code the commands using the SlashCommands, because of it i´m triying to create this as an event:
//This is the help command using an event
const { clientId } = require("../config.json");
const { MessageEmbed } = require("discord.js");
//testx is going to store the embed message
const testx = new MessageEmbed().setTitle('Test').setDescription('Test');
module.exports = {
name: 'messageCreate',
execute(client) {
//This condition determines if isn´t a message of the bot, and if the written command is !!help
if (client.author.id !== clientId && client.content === '!!help') {
//if the condition is true, send the embed message
//client.reply(testx); //the problem is here.
console.log(testx);
}
},
};
And this is the error i got from the terminal:
DiscordAPIError: Cannot send an empty message
at RequestHandler.execute (C:\Users\ //...and more info of my dirs
if i print the testx const in my console, i can see the two values i setted in the const filled with the text "Test", i don´t know why isn´t work or what i need to take this to work.
Thanks and i appreciate any help.
In V13, embeds must be sent differently.
client.reply({embeds: [testx]});
I also recommend editing client to interaction in your command files as it may be misleading, or to actually pass the client and interaction, as you'll most likely need to access the client at some point.
Also, you seem to be confusing interactions with messages.
Interactions do not have an author property, you must use user or member.
They also do not have a content property, to get an argument you must use interaction.options
You also, as far as I can see, are not actually deploying your commands. It looks like you've merged the V12 and V13 command handler tutorial together. I reccomend reading this tutorial again, and making sure you're doing it properly for V13.
How can I have it so that the bot sends a message to a specific channel, while using .deferReply and .editReply? Currently, I'm getting an error saying that suggestionChannel.deferReply is not a function. Here's my code:
const { SlashCommandBuilder } = require("#discordjs/builders");
const { MessageEmbed } = require("discord.js");
module.exports = {
data: new SlashCommandBuilder()
.setName("suggest")
.setDescription("Send your suggestion to the specified channel")
.addStringOption((option) =>
option
.setName("suggestion")
.setDescription("Your suggestion")
.setRequired(true)
),
async execute(interaction, client) {
var suggestionChannelID = "900982140504793109";
var suggestionChannel = client.channels.cache.get(suggestionChannelID);
const embed = new MessageEmbed()
.setColor("#0099ff")
.setTitle(`New suggestion by ${interaction.member.displayName}`)
.setDescription(`${interaction.options.getString("suggestion")}`);
await suggestionChannel.deferReply();
await suggestionChannel
.editReply({
embeds: [embed],
})
.then(function (interaction) {
interaction.react(`👍`).then(interaction.react(`👎`));
});
},
};
How can I have it so that the bot sends a message to a specific
channel, while using .deferReply and .editReply?
Well, the short answer is; you can't. But you can do this:
As the error already says, deferReply() is not a method of the TextBasedChannels class, defined by your suggestionChannel.
Instead, try sending a message to the channel instead of replying. Replies can only be executed in the interaction's channel:
var suggestionChannelID = "900982140504793109";
var suggestionChannel = client.channels.cache.get(suggestionChannelID);
const embed = new MessageEmbed()
.setColor("#0099ff")
.setTitle(`New suggestion by ${interaction.member.displayName}`)
.setDescription(`${interaction.options.getString("suggestion")}`);
// use this instead
await suggestionChannel.send({
embeds: [embed],
});
P.S side note, deferReply() starts a 15-minute timer before the interaction expires and triggers that 'x is thinking...' text to appear when the client is calculating stuff, so try to call it as soon as possible. By default, interactions expire after 3 seconds, so if your bot fails to finish whatever it needs to accomplish within that timeframe, that interaction will fail.
I am trying to import a variable from one of my files (File 1) and use it in File 2. I have imported File 2 into File 1 but I am receiving error. My channel ID is correct, in this case you would have to choose the channel so the channel ID is not the issue here.
TypeError: setr.send is not a function
File 1
const Discord = require("discord.js");
const axios = require("axios");
let config = require("../config.json");
module.exports = {
name: "setrestart",
description: "sets the restart channel",
async execute(message, args) {
const perm = new Discord.MessageEmbed()
.setDescription(":x: You do not have permission to use this command.")
.setColor("#E74C3C");
if (!message.guild.me.hasPermission("ADMINISTRATOR"))
return message.channel.send(perm);
if (message.author.id !== "ID")
return message.channel.send(perm);
const channelx =
message.mentions.channels.first() ||
message.guild.channels.cache.find((c) => c.id === args[0]);
if (!channelx)
return message.channel.send(
`:x: Please specify the channel where server restarts will go!`
);
message.reply(`All server restart logs will now go to ${channelx}.`)
},
};
File 2
const Discord = require("discord.js");
const axios = require("axios");
let config = require("../config.json");
let setr = require("./setrestart"); // This is importing file 1
module.exports = {
name: "restart",
description: "send a restart message in status channel",
async execute(message, args) {
const perm = new Discord.MessageEmbed()
.setDescription(":x: You do not have permission to use this command.")
.setColor("#E74C3C");
if (!message.guild.me.hasPermission("ADMINISTRATOR"))
return message.channel.send(perm);
if (message.author.id !== "ID")
return message.channel.send(perm);
const restart = new Discord.MessageEmbed()
.setTitle(" Server Restarted! ")
.setDescription(`F8 connect to ${config.SERVER_URL} `)
.setColor("RANDOM")
.setTimestamp()
.setFooter(`${config.SERVER_LOGO}`);
setr.channelx.send(restart) // This does not work.
},
};
Help is much appreciated.
Edit: I left out the most crucial thing about what I am trying to import.
I am trying to import channelx which is in File 1 and I am trying to use the variable in File 2.
Output
User: /setrestart #channel
Bot: All server restart logs will now go to ${channelx}.
User: /restart
Bot: Embed sent in channelx
The variable channelx is accessible only in the function scope of execute(), you can't import it. Basically after the function goes out of scope the variable is lost. Use a global object, note that the object is destroyed when the program exits. So if you are trying to make some kind of bot's configuration, you want to save the object to a file.
Here is an example of how to properly implement what you are trying to do.
File 1 (file1.js):
// ... Load storage from a JSON file ...
const storage = {};
module.exports = {
name: "setrestart",
description: "sets the restart channel",
async execute(message, args) {
// ... Permission checking ...
const channelx = message.mentions.channels.first() ||
message.guild.channels.cache.find((c) => c.id === args[0]);
if (!channelx) {
return message.channel.send(
`:x: Please specify the channel where server restarts will go!`
);
}
// Store restart channel id per guild
storage[message.guild.id] = channelx.id;
message.reply(`All server restart logs will now go to ${channelx}.`);
// ... Write to the storage JSON file and update it with new data ...
},
};
module.exports.storage = storage;
File 2 (file2.js):
const Discord = require("discord.js");
const file1 = require("./file1.js");
module.exports = {
name: "restart",
description: "send a restart message in status channel",
async execute(message, args) {
// ... Permission checking ...
const restart = new Discord.MessageEmbed()
.setTitle(" Server Restarted! ")
.setColor("RANDOM")
.setTimestamp();
const channelId = file1.storage[message.guild.id];
// If there is no restart channel set, default to the system channel
if (!channelId) channelId = message.guild.systemChannelID;
const channel = await message.client.channels.fetch(channelId);
channel.send(restart);
},
};
Note that I have remove some parts of your code, to make it work on my machine.
Using discord.js ^12.5.3.
I am pretty sure you can't use the module.exports in that way. You should just add the channelx to the exports instead.
using this.channelx = channelx.
This is not how importing and exporting works. Your channelx variable is defined within the execution of a function, and you are not returning it.
I am not sure how the whole Discord API works and what are the shapes that get returned, but you should be able to do something like this:
File 1
module.exports = {
name: "setrestart",
description: "sets the restart channel",
async execute(message, args) {
// ... everything as per your file
message.reply(`All server restart logs will now go to ${channelx}.`);
return channelx;
},
};
File 2
module.exports = {
name: "restart",
description: "send a restart message in status channel",
async execute(message, args) {
// ... everything the same as per your file
const channelx = await setr.execute(message, args);
channelx.send(restart);
},
};
Basically, what is happening here is that the first module exposes a function that figures out your target channel and then returns it.
Once you return it, you can do whatever you want with that.
Please be aware that your first function might not need to be async as you don't have any await instruction.
Read more about scope: https://developer.mozilla.org/en-US/docs/Glossary/Scope
EDIT: I JUST NEEDED TO PASS THE CLIENT
this is the code that i made in its own file
const Discord = require("discord.js");
const bot= new Discord.Client();
module.exports = {
name: 'set' ,
execute(message, args){
if(message.member.hasPermission("MANAGE_GUILD"))
{
if (args[2]==='picture')
{const image=message.attachments.first().url;
bot.user.setAvatar(image);}
else if (args[2]==='activity')
{
let initial = message.content ;
initial= initial.replace('asb set activity','').replace(args[3],'');
bot.user.setActivity(initial, { type: args[3] });
}
else
message.reply('invalid command');
}
else
return message.reply('You can use this command only if u have permisions to manage the server');
}
}
and this is the error
bot.user.setActivity(initial, { type: args[3] });
^
TypeError: Cannot read property 'setActivity' of null
if i remove the bot client and use client.message it gives me the same error
The problem here is that bot is a new Discord.Client();
What you should do instead is pass the client object from your index.js file to the command file and use that to set its activity.
Or you can get the client also with: message.client , so your code would be something like:
message.client.user.setActivity(...);
My bot currently runs fine. I decided to add a 'playing ' status to it. This is the relevant code:
// Import the discord.js modules required
const Discord = require('discord.js');
// Create an instance of a Discord client
const client = new Discord.Client();
// Load config properties from 'config.json'
const config = require("./config.json");
const contest = config.contest;
// Set bots status to playing 'contest' defined in 'config.json'
client.user.setPresence({
game:{
name:contest
},
status:'online'
});
In 'config.json':
{
"contest": "Example Game"
}
When I add this, the bot no longer works, and appears offline. Any ideas?
EDIT:
Source of the information:
https://discord.js.org/#/docs/main/stable/class/ClientUser?scrollTo=setPresence
In the example section:
// Set the client user's presence
client.user.setPresence({ game: { name: 'with discord.js' }, status: 'idle' })
.then(console.log)
.catch(console.error);
You need to read the config, instead of
const config = require(...)
You need
const fs = require("fs");
const config = JSON.parse(fs.readFileSync("config.json"));
const contest = config.contest;
Then
game:{
name:contest
}
Figured it out - this needs to be placed inside an event, otherwise it's just floating code. For example, I placed this inside a
client.on('ready) event.