I was playing around with the message.react
function and the awaitReactions
function and I noticed something that bother me.
I was trying to determine if I should use a collector or the client.on('messageReactionAdd')
(that is another question) for the following method:
- sending a message
- adding reactions to it
- doing something every time a reaction is added (for X seconds)
So I made a simple example to start, with a filter which return true
every time, and I noticed that the collector was collecting the last emoji my bot was adding to the messages. Here is the code
const emojiNext = '➡';
const emojiPrevious = '⬅';
const emojiClap = '????';
function filter(reaction) {
console.log('reacted to: ', reaction.emoji.name);
return true;
}
function sleep(ms, a){
return new Promise(resolve=>{
setTimeout(resolve,ms);
}).then(d => a);
}
function sendList(channel){
channel.send('foo')
.then(msg => {
console.log('First');
return msg.react(emojiPrevious);
})
.then(msgReaction => {
console.log('Second', msgReaction.message.reactions.keys());
return msgReaction.message.react(emojiNext);
})
.then(msgReaction => {
console.log('Third', msgReaction.message.reactions.keys());
return msgReaction.message.react(emojiClap);
})
// .then(msgReaction =>{
// return sleep(100, msgReaction);
// })
.then(msgReaction => {
console.log('Fourth', msgReaction.message.reactions.keys());
msgReaction.message.awaitReactions(filter, {max: 2, time: 1000, errors: ['time']})
.then(collected => {
console.log('ending', collected);
})
.catch(collected => {
console.log(`After 5 sec, only ${collected.size} out of 2 reacted: ${collected.map((v,k) => k)}`);
});
});
}
Debug
This example is a bit more developed than the first one I did because I tried some debug.
The example send a message, append with chained promise 3 emojis, and then start collecting emojis. However, as the following log show, the last emoji is collected (I never pressed any emoji myself, and I'm alone on my server):
First
Second [Map Iterator] { '⬅' }
Third [Map Iterator] { '⬅', '➡' }
Fourth [Map Iterator] { '⬅', '➡', '????' }
reacted to: ????
After 5 sec, only 1 out of 2 reacted: ????
But sometimes (it depends) it works fine and the log are like this:
First
Second [Map Iterator] { '⬅' }
Third [Map Iterator] { '⬅', '➡' }
Fourth [Map Iterator] { '⬅', '➡', '????' }
After 5 sec, only 0 out of 2 reacted:
I was lastly testing in the train, with an irregular network which might be the cause.
So I tried something else, I added the sleep function, which take an amount of ms and a value, and return a promise, which will return the value once resolved after the amount of ms has passed. (uncomment the 3 line to have this debug). This way the collector never collect the last emoji.
I also tried to return the promise before the then
with the collector (let res = await channel.send...
) and then execute the rest of the code. I still had the last emoji collected.
I know that I can use my filter to ignore bots or my emoji, and only focus on user's one (see code below) but I want to know what cause this behavior. Is there something I did bad? Is there something I didn't understand about promise?
function filter(reaction, user) {
if(user.id === client.user.id) { return false; } // or user.bot to ignore all bot
console.log('reacted to: ', reaction.emoji.name);
return true;
}
In my opinion, and after seeing in the debug that the collector react after the log of everything, I think that the promise being resolved and Discord sending the information to the collector/the callback are different, but it's only a guess
note:
node.js version: v11.15.0
discord.js version: v11.5.1