DJS - Edit the embed when someone reacts with specific emoji - javascript

What I'm trying to do is to change the color of an embed when someone adds a reaction.
The struggle I'm currently facing is making it the if statement fire. So haven't gotten very far.
I'm also probably not targeting any specific embed. As the embed (suggestionsEmbed) has been sent multiple times.
EDIT: Updated with current code. This is working except for one thing. No embed other than the last sent can be edited. See what I mean here.
// SUGGESTIONS EMBED - BEGINS
var suggestionsEmbed;
client.on('messageCreate', async message => {
if (message.channel.id === channelSuggestions && !message.author.bot) {
db.add('counterP.plus', 1);
const embed = new MessageEmbed()
.setColor('#f9db73')
.setTitle(`Suggestion #${await db.fetch('counterP.plus') + await db.fetch('counterM.minus')}`)
.setDescription(message.content)
.setAuthor({ name: message.author.username, iconURL: message.author.displayAvatarURL() })
.setTimestamp()
.setFooter({ text: message.author.id });
suggestionsEmbed = await message.channel.send({ embeds: [embed] })
suggestionsEmbed.react('👍')
suggestionsEmbed.react('👎');
message.delete({ timeout: 0 });
console.log(db.fetch('counterP.plus'));
}
})
// SUGGESTIONS EMBED - ENDS
// CHANGE EMBED COLOR - BEGINS
const suggestionsApproved = '🟢';
const suggestionsDenied = '🔴';
client.on('messageReactionAdd', (reaction, user) => {
if (reaction.message.channel.id === channelSuggestions) {
if (reaction.emoji.name === suggestionsApproved && reaction.message.id === suggestionsEmbed.id) {
const suggestionsEmbedApproved = new MessageEmbed(suggestionsEmbed.embeds[0]).setColor('#76de51')
suggestionsEmbed.edit({ embeds: [suggestionsEmbedApproved] });
}
}
})

After the introduction of discord.js v13, you need intents declared in your bot. They were introduced so that developers could choose which types of events their bot wanted to receive. You can learn more about Intents here => Gateway Intents. First, you have to add the GUILD_MESSAGE_REACTIONS intent in your client by using:
const { Client, Intents } = require('discord.js')
const client = new Client({
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.GUILD_MESSAGE_REACTIONS
]
})
Then after that, you can just use your original code to do whatever you want. Although you might get an error saying DiscordAPIError: Invalid Form Body embeds[0].description: This field is required, so to fix that, all you have to do is add the .setDescription() to your edited embed and then send it. Your final code might look something like this:
const { Client, Intents, MessageEmbed } = require('discord.js')
const client = new Client({
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.GUILD_MESSAGE_REACTIONS
]
})
const suggestionsApproved = '🟢';
const suggestionsDenied = '🔴';
const channelSuggestions = 'your channel id'
client.on('messageReactionAdd', (reaction, user) => {
if (reaction.message.channel.id === channelSuggestions) { // Check if the reaction was in a particular channel
if (reaction.emoji.name === suggestionsApproved) { // Check which emoji was selected
const suggestionsEmbedApproved = new MessageEmbed()
.setColor('your color')
.setDescription('your description');
suggestionsEmbed.edit({ embeds: [suggestionsEmbedApproved]});
}
}
})
Edit
In response to the new question, here is the answer:
Instead of naming the embed as suggestionsEmbed, the correct way to do it would be to first create an embed with a different name and then use const suggestionsEmbed = await message.channel.send({ embeds: [embedName] }) so that the code will be like:
const embed = new MessageEmbed()
.setTitle('title')
.setDescription('description')
.setColor('color')
const suggestionsEmbed = await message.channel.send({
embeds: [embed]
})
Second Edit
Since you are already using await message.channel.send(), you don't have to use .then(). All you have to do is change this:
const suggestionsEmbed = await message.channel.send({ embeds: [embed] }).then(sentEmbed => {
sentEmbed.react("👍")
sentEmbed.react("👎")
});
to this:
const suggestionsEmbed = await message.channel.send({ embeds: [embed] })
suggestionsEmbed.react('👍')
suggestionsEmbed.react('👎')
Editing the Embed:
Use:
const suggestionsEmbedApproved = new MessageEmbed(suggestionsEmbed.embeds[0]).setTitle('asdfasdf')
suggestionsEmbed.edit({ embeds: [suggestionsEmbedApproved] });

So your code is trying to edit the embed rather than the message that the embed is in, (weird I know) but this should work for you.
Discord intents may vary based on your coding but should look similiar
const client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MESSAGE_REACTIONS],
partials: ['MESSAGE', 'CHANNEL', 'REACTION'],
})
It should be able to pick up those reactions with the below.
const suggestionsApproved = 'insertReactionEmojiName'
const suggestionsDenied = 'insertReactionEmojiName'
const channelSuggestions = 'yaddayadda'
// I would use a different emoji, one that you can get an name from like this
// 👍 which in discord is named :thumbsup:
client.on('messageReactionAdd', (reaction, user) => {
if (reaction.partial) {
// If the message this reaction belongs to was removed, the fetching might result in an API error which should be handled
try {
await reaction.fetch();
} catch (error) {
console.error('Something went wrong when fetching the message:', error);
// Return as `reaction.message.author` may be undefined/null
return;
}
}
const targetMessage = reaction.message
const channel = targetMessage.channel
if (channel.id === channelSuggestions) {
if (reaction.emoji.name === suggestionsApproved) {
const suggestionsEmbedApproved = new MessageEmbed()
.setColor('#1dce1d')
targetMessage.edit({
embeds: [suggestionsEmbedApproved]
})
console.log('fired!')
}
}
})

To edit any embed which was reacted to instead of only the previous sent one, you can use:
const suggestionsEmbedApproved = new MessageEmbed(reaction.message.embeds[0]).setColor("Your color")
reaction.message.edit({ embeds: [suggestionsEmbedApproved] });

Related

"DiscordAPIError[40060]: Interaction has already been acknowledged." Throws this when ever i run a command on discord [duplicate]

I am creating a bot using guide by Discord.js, however after like 3 or sometimes 3 commands the bot stops working and i get
discord message
i have tried to restart it many times but after sometime it just stop working again and again
const fs = require('node:fs');
const path = require('node:path')
const { Client, Events, GatewayIntentBits, Collection ,ActionRowBuilder,EmbedBuilder, StringSelectMenuBuilder } = require('discord.js');
const { token } = require('./config.json');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
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);
if('data' in command && 'execute' in command){
client.commands.set(command.data.name,command);
}else{
console.log(`[WARNING] The command at ${filePath} is missing`);
}
}
client.once(Events.ClientReady, () => {
console.log('Ready!');
})
//menu
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
const row = new ActionRowBuilder()
.addComponents(
new StringSelectMenuBuilder()
.setCustomId('select')
.setPlaceholder('Nothing selected')
);
const embed = new EmbedBuilder()
.setColor(0x0099FF)
.setTitle('pong')
.setDescription('Some description here')
.setImage('https://media.istockphoto.com/id/1310339617/vector/ping-pong-balls-isolated-vector-illustration.jpg?s=612x612&w=0&k=20&c=sHlz5sbJrymDo7vfTQIuaj4lbmwlvAhVE7Uk_631ZA8=')
await interaction.reply({ content: 'Pong!', ephemeral: true, embeds: [embed]});
}
});
//======================================================================================================================
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand ||
interaction.isButton() ||
interaction.isModalSubmit()) 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);
await interaction.reply({content: 'There was an error while executing this command!', ephemeral: true});
}
console.log(interaction);
});
client.login(token);
Error i get in terminal
I wanted this bot to continue to execute commands as long as it's up and running
This is a common error in Discord.JS that occurs when you already replied to an interaction and you attempt to reply again.
From the discord.js discord server:
You have already replied to the interaction.
• Use .followUp() to send a new message
• If you deferred reply it's better to use .editReply()
• Responding to slash commands / buttons / select menus
To fix this error, you can use .followUp() to send another message to the channel or .editReply() to edit the reply as shown above.
You can see the documentation on a command interaction here
Yes the problem is that you cant reply to a slash command more then once in discords api so instead you should use
interaction.channel.send()
or
interaction.editReply()

Bot isn't replying to any message

I'm trying to make a simple Discord bot, but I haven't been able to get it to respond to any of my messages.
const Discord = require("discord.js");
const { GatewayIntentBits } = require('discord.js');
const client = new Discord.Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
]
});
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`)
})
client.on("messageCreate", msg => {
if(msg.content === "ping") {
msg.reply("pong");
}
})
const token = process.env['TOKEN']
client.login(token)
The bot is logging into discord, I'm not getting any errors in the console, and I've toggled on all the privileged gateway intents.
Edit
So, my previous answer was wrong, but is most definitely a better way to send messages.
There's not anything else that I can see is wrong with the code -- so I guess I'll try to debunk?
const { Client, GatewayIntentBits } = require("discord.js");
const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent ]});
client.on("ready", async() => {
console.log(`${client.user.tag} logged in.`);
});
client.on("messageCreate", async(message) => {
if(message.content.toLowerCase() === "ping") {
message.reply({ content: "pong!" }); // or message.reply("pong!");
}
});
client.login(process.env.TOKEN);
This should be a runnable instance of your code. What you should do is see if you're even getting the messageCreate event at all, by running it like this:
client.on("messageCreate", (message) => {
console.log(`Received message!`);
});
If you do get something, then it is unable to correctly parse the message content. Are you ensuring it's the same capitalization wise? Is it spelt correctly?
If you don't get something, it's an issue with your Intents, or the way your event is structured.
Try adding parenthesis around your msg, though that shouldn't affect anything. Just a thought.
Incorrect Answer
In discord.js#13.x.x, the way to send messages has changed.
Formerly, you could do the following:
message.reply("Hello world!");
But now, to make formatting what provided property is what, it goes as follows:
message.reply({
content: "Hello world!",
});
You can also add things such as Embeds by using embeds: [], or Components by: components: [] (which requires Action Rows, not base Components).
Hope this helps.

I am trying to make a discord bot automatically send a one-time-use invite when a user reacts to my message. I'm a bit new and could use help :)

I copied the skeleton of another user, and tried editing a few things but I just can't get the bot to a spot where when I react with the message it automatically generates the code and sends it.
My intentions are to react to a permanent message and have the reactee receive a DM from the bot with a unique link. Ideally they can only receive the link one time, even if they leave and join the channel again. I'm sure I've got some big errors in here for my functionality, I'd appreciate some guidance!
const { Client, Intents } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });
const mySecret = process.env['token']
client.once('ready', () => {
console.log('I am awake');
});
client.on('message', message => {
if(reaction.message.name === "\:thumbsup:" || message.author.bot)
return;
const args = message.content.slice(prefix.length).split(' ');
const command = args.shift().toLowerCase();
const replyWithInvite = async (message) => {
let invite = await message.channel.createInvite(
{
maxAge: 10 * 60 * 1000, // maximum time for the invite, in milliseconds
maxUses: 1 // maximum times it can be used
},
`Requested with command by ${message.author.tag}`
)
.catch(console.log);
message.author.send(invite ? `Here's your invite: ${invite}` : "There has been an error during the creation of the invite.");
}
if (command === 'invite') {
replyWithInvite(message);
}
});
client.login(mySecret);```
The first problem in ur code is you're event. in
const { Client, Intents } = require('discordjs');
require('dotenv').config() // If u're using environment variables for ur token
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MEMBERS, Intents.FLAGS.GUILD_BANS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_BANS], partials: ['MESSAGE', 'CHANNEL', 'REACTION'] });
client.once('ready', () => {
console.log('I am awake');
});
client.on('messageReactionAdd', async (reaction, user) => {
// Check if the reaction is on ur intended message or just some random message on the server
if (reaction.message.id != urMessageid) return;
//check if the reaction is thumbsup or not
if (reaction.emoji.name != 'thumbsup') return;
// Create the invite now
const defaultChannel = reaction.message.guild.channels.find(c=> c.permissionsFor(guild.me).has("SEND_MESSAGES"));
let invite = await defaultChannel.createInvite({
maxAge: 10 * 60 * 1000, // maximum time for the invite, in milliseconds
maxUses: 1 ,// maximum times it can be used
reason: `Requested with command by ${user.tag}`
}).then(invite => invite).catch(error => console.log(error));
user.send(`Here's your invite ${invite}`).catch(error => console.log(error));
});
client.login(process.env.TOKEN);
You can find some examples on reactions on the Discordjs V12 guide.
Also on a side note for future references you shouldnt use the message event since its deprecated. You can use client#messageCreate

I can't understand why does it not send Discord.js v13

I can't understand why doesn't send the welcome message
Here's Code from index.js
client.on('guildMemberAdd', (member) => {
let chx = db.get(`welchannel_${member.guild.id}`);
if (chx === null) {
return;
}
client.channels.cache.get(chx).send(`Welcome to ${message.guild.name}`);
});
Here's Code From channel.js
module.exports = {
name: "channel",
description: "Help Command",
category: "Help",
execute(client, message, args, Discord) {
const db = require("quick.db")
let channel = message.mentions.channels.first() //mentioned channel
if(!channel) { //if channel is not mentioned
return message.channel.send("Please Mention the channel first")
}
db.set(`welchannel_${message.guild.id}`, channel.id)
const embed = new Discord.MessageEmbed()
.setColor('#b5b5b5')
.setTitle(`Channel set: ${channel.name} `)
message.channel.send({ embeds: [embed] });
}
}
EDIT: I found out the problem i didn't have a intent flag GUILD_MEMBERS
and also thanks UltraX that helped also
Basically, the reason is simple, you need to go to your dev portal then after choosing your bot/application just go to bot and you need to enable member intents Server Member Intent after that it should work, if it didn't just give it a 10 minute, then try again!
The best way to ensure you get a channel object within the event is to use the guild property off the emitted member.
client.on("guildMemberAdd", (member) => {
const { guild } = member;
let chx = db.get(`welchannel_${member.guild.id}`);
if(chx === null) {return}
const channel = guild.channels.cache.get(chx);
if (!channel) return;
channel.send(`Welcome to ${message.guild.name}`)
.catch(console.error);
})
You will need the Guild Member's intent enabled as stated in This Answer for the event to emit.

How can I check if someone is in a voice channel in DiscordJS V13?

I'm trying to check if the user who initiated a command is currently in a voice channel, and while after I run the bot my code works and I get the voice channel information back if I then LEAVE the channel and re-initiate the command I'm getting back the same voice channel information like it was cached? The only way to receive up-to-date information is to restart my bot entirely.
export const interactionListener = async (interaction, client) => {
if (!interaction.isCommand()) return;
const { commandName } = interaction;
switch (commandName) {
case 'play':
let user = await interaction.member.fetch();
let channel = await user.voice.channel;
if (!channel) {
interaction.reply('you are not in a voice channel');
} else {
interaction.channel.send('do something else');
}
}
};
and that code is running on an interactionCreate here
client.on('interactionCreate', async (interaction) => {
interactionListener(interaction, client);
});
FIXED: I needed another intent
Previous intents were:
const client = new Client({
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.GUILD_MEMBERS,
Intents.FLAGS.GUILD_PRESENCES,
],
});
NEW Intents are:
const client = new Client({
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.GUILD_MEMBERS,
Intents.FLAGS.GUILD_PRESENCES,
Intents.FLAGS.GUILD_VOICE_STATES,
],
});
I was missing
Intents.FLAGS.GUILD_VOICE_STATES

Categories