I am trying to create a reaction message, but whenever I try to use a console.log in the .then it only executes it once the message is deleted.
async execute(message) {
const role = message.guild.roles.cache.find(r => r.name == 'Founder');
if (!role) return message.channel.send(`**${message.author.username}**, role not found`);
await message.delete();
const filter = (reaction) => reaction.emoji.name === '✅';
const ReactionMessage = await message.channel.send('React to this message to get the Founder role');
ReactionMessage.react('✅');
ReactionMessage.awaitReactions(filter, { max: 10, time: 15000 })
.then(collected => console.log(collected.size))
.catch(err => console.error(err));
}
My end game is to have it add a role to all of those users who react to it, but it won't even console.log the collected size until I delete the message. Anyone able to help me get this working?
The awaitMessages() will only resolve once either the message is deleted or the time has run out. What you can do instead is make a reactionCollector and wait for the collect event.
Here is some resources: https://discordjs.guide/popular-topics/collectors.html#reaction-collectors, https://discord.js.org/#/docs/main/stable/class/Message?scrollTo=createReactionCollector
Try replacing console.log(collected.size) with console.log(collected) and see how that works out.
Related
Im a bit new creating Discord bots, my plan with this is to have like a book with the help command that if you press the arrow it changes to the next page, and if you press another arrow it changes to the previus page, I'll simpifly my code to make it more easier to understand.
async execute(message, client){
var msg1 = await message.channel.send('how are')
msg1.react('▶') //send the message
client.on('messageReactionAdd', async (reaction, user) =>{ //wait for the reaction
if(user.bot) return
if (message.reaction.id === msg1.id){
message.channel.messages.fetch(msg1.id).then(msg => msg.delete())
var msg2 = await message.channel.send('you?')
msg2.react('◀') //delete the previus message, send the second and react to it
}
else if (message.reaction.id === msg2.id){
message.channel.messages.fetch(msg2.id).then(msg => msg.delete())
var msg1 = await message.channel.send('how are')
msg1.react('▶') //delete the second message, send the first and react
}
})
}
I know this isnt going to work but i hope you understand the major idea, how can i do this so it actually works?
If you want to listen for reactions to old messages you need to fetch the messageId, etc. This is simple to understand. Here is a Guide.
If you only want it to send a message, react to it, and listen to the next reaction it's easier. There is also a Guide for it.
In your case with the book, I would use the second method and then loop it.
So if someone presses the button it starts the function from the beginning.
This is only an example I never tested it and can't say if it works, It's only made to show you what I meant:
const reactionName1 = '▶';
const reactionName2 = '◀';
const text1= 'How are';
const text2 = 'you?';
module.exports = {
async execute(message, client) {
if(message.author.user.bot) return;
message.channel.send('Hello!').then(msg => {
nextMessage(msg, message.author, reactionName1, text1)
});
},
}
function nextMessage(message, author, reactionName, text) {
message.edit(text).then(() => {
message.react(reactionName);
const filter = (reaction, user) => {
return [reactionName].includes(reaction.emoji.name) && user.id === author.id;
};
message.awaitReactions({ filter, max: 1, time: 60000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
message.reactions.removeAll();
if(reaction.emoji.name === reactionName1) return nextMessage(message, author, reactionName2, text2);
if(reaction.emoji.name === reactionName2) return nextMessage(message, author, reactionName1, text1);
})
.catch(collected => {
message.reactions.removeAll();
return message.edit('You had to press the reaction').then(() => message.delete({ timeout: 4000 })).catch(o_O=>{});
});
});
};
I hope that it was a bit helpful.
I'm running a dm prompt from my bot, where the player needs to reply before the bot continues asking. I set up a filter so that the bot doesn't detect and count its own message, but it doesn't seem to be triggering the ".then()" function.
My code:
let filter = m => m.author.id != client.user.id
channel.awaitMessages(filter, {max: 1, time: 1000*180, errors: ['time']})
.then(msg => {
console.log("got to the then")
let replymsgobject = msg.first()
let reply = replymsgobject.content
let checkstringarr = [
"payment",
"about",
"team",
"requirements"
]
if (contains("or", reply, checkstringarr)) {
channel.send(`Your post doesn't follow the format.`)
} else {
channel.send(`succesfully set your post message, would you like to add any extra comments?`)
let filter = m => m.author.id != client.user.id
channel.awaitMessages(filter, {max: 1, time: 1000*120, errors: ['time']})
.then(replymsg => {
if (contains("only", replymsg.content, "no")) {
//some stuff
} else {
//some stuff
}
})
.catch(collectedcatchmsg => {
channel.send(`timed out`)
})
}
})
.catch(collectedcatchmsg => {
channel.send(`timed out`)
})
#Toasty said (sorry Toasty), "it will wait until the timer is over". This is incorrect, it will give you the promise once for example the max messages have been reached.
why would it wait for 3 mins if it gets the required answer in 10secs??
Now I'm a little lost do you want the command executor to reply to that message collector or do you not? Because right now your filter is not accepting any messages sent by the command executor/message sender.
To fix this just edit your filter
const filter = m => m.author.id === message.author.id;
if you want someone else's message to be collected and not the message authors, then you would do
const filter = m => m.author.id !== message.author.id;
Turns out there were 2 errors! First off the filter dictionary was supposed to be inside the table with the requirements, etc., The second error was using != instead of !==, Thanks to #Patrik for helping out here!
I have a suggest command and I'm trying to make it so that when i react with emoji "x" message get's deleted. Can someone help me?
owner.send(embed).then(m => {
m.react("✅")
m.react('❌')
})
To listen react change on message is sent you need to using createReactionCollector() guide here
This code is what you are looking for
Note: Your exec or run function must be async function
const newMsg = await owner.send(embed);
await newMsg.react('❌');
const filter = (reaction, user) => {
return user.id === msg.author.id; // Note msg is start commands message
};
let collector = await newMsg.createReactionCollector(filter, {
time: 30000,
});
collector.on('collect', async (r) => {
if (r.emoji.name ==='❌') {
collector.stop('delete');
await newMsg.delete();
}
});
How do I edit an embed field with discord.js?
execute(client, connection, message, args) {
message.channel.send(client.helpers.get('CreateEmptyEmbed').execute("Poll", client, false)
.setTitle('test')
.addField(`0`)
).then(embedMessage => {
embedMessage.react(`✅`)
embedMessage.react(`❎`)
})
client.on('messageReactionAdd', (reaction, user) => {
if (user.id === client.user.id) return // if reaction is == bot return
if (reaction.emoji.name == '✅') message.channel.send(reaction.count)
embed.editfield("hi")
})
Any help would be greatly appriciated.
First of all, client.on('messageReactionAdd') fires for all reactions, and doesn't stop, it keeps firing until you stop the bot, so you need to use a Reaction Collector and to edit embed, you need to change the embeds field and edit the message itself.
execute(client, connection, message, args) {
message.channel.send(client.helpers.get('CreateEmptyEmbed').execute("Poll", client, false)
.setTitle('test')
.addField(`0`)
).then(embedMessage => {
embedMessage.react(`✅`)
embedMessage.react(`❎`)
const filter = (reaction, user) => user.bot!; //Ignores bot reactions
collector = embedMessage.createReactionCollector(filter,{time:15000)) //The time parameter (in milliseconds) specified for how much time the reactionCollector collects reactions
collector.on('collect',(reaction,user)=>{ //When a reaction is collected
const embed = embedMessage.embeds[0] // Get the embed that you want to edit.
embed.fields[0] = {name : 'The name of the new field' , value : 'Value of new field'}
await embedMessage.edit(embed)
})
collector.on('end',()=>{ //When the time we specified earlier is over
//Do stuff
})
})
let filter = m => m.author.id === message.author.id // to ensure same author is responding
message.channel.send(embedMessage).then(() =>{
message.channel.awaitMessages(filter, { // after he sends a message to the same channel
// You can also use ".awaitReactions" if you want to wait for reactions on the message sent
max: 1,// maximum responses
time: 30000,// timeout for waiting
errors: ['time']// type of error
})
.then(message =>{
// do what everyou like with the response
})
.catch(error => console.log)
});
I'm trying to send a message to the first 5 people who react to the message, however it only sends a DM to the first person who reacted and does not allow anyone else to react or receive a DM.
How would I do this?
case 'await':
message.channel.sendMessage('React for dm').then(sentMessage => {
sentMessage.react('1️⃣').then(() => sentMessage.react('2️⃣'));
const filter = (reaction, user) => {
return ['1️⃣', '2️⃣'].includes(reaction.emoji.name);
};
sentMessage.awaitReactions(filter, {
max: 1,
time: 60000,
errors: ['time']
})
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === '1️⃣') {
message.author.sendMessage('I told you I would!')
}
})
})
You have max: 1 That tells the collector to quit after it has successfully collected 1 reaction. You should set that to 5.
After that you need to loop through the collected to send a DM to all of them rather than using first().