Search code examples
javascriptnode.jsdiscorddiscord.jsbots

Discord collector reaction filter way to set a max limit


I'm doing a command to translate every messages that have a certain reaction to the language of the flag emoji (the one that the user reacted with).

But I want the bot to only translate once for one language (if there's two users that react with the us flag, it will translate the message to English only once).

I can use the reaction filter, but in my case for a better code, I'm using a switch statement, so if I use the max property in the reaction filter, I wouldn't be able to translate multiple times a message (only once).

Here's my code :

bot.on('message', async (msg) => {
  const reactionFilter = (reaction, user) => {
    return msg.author.id !== '724682218454253588';
  };
  collector = msg.createReactionCollector(reactionFilter);

  collector.on('collect', async (reaction, user) => {
    switch (reaction.emoji.name) {
      case 'πŸ‡«πŸ‡·':
        TranslateMessage(msg, 'fr');
        break;
      case 'πŸ‡ΊπŸ‡Έ':
        TranslateMessage(msg, 'en');
        break;
      case 'πŸ‡©πŸ‡ͺ':
        TranslateMessage(msg, 'de');
        break;
      case 'πŸ‡ͺπŸ‡Έ':
        TranslateMessage(msg, 'es');
        break;
      case 'πŸ‡―πŸ‡΅':
        TranslateMessage(msg, 'ja');
        break;
    }
  });
});

(I have a lot more of langues than that in this switch statement, but for the question it's easier to read)

And here's the TranslateMessage function :

async function TranslateMessage(msg, lang) {
  try {
    const traduction = await traduire(msg.content, lang);
    const MessEmbed = new MessageEmbed()
      .setAuthor(msg.author.username, msg.author.avatarURL)
      .setDescription(traduction);

    return msg.channel.send(MessEmbed);
  } catch (error) {
    return msg.channel.send("There's an error, try again !");
  }
}

Solution

  • You can check reaction.count that returns the number of people that have given the same reaction. If it's larger than 1, you don't need to translate the message to that language.

    collector.on('collect', async (reaction, user) => {
      if (reaction.count > 1) return; // there is already a translation for this reaction
      
      switch (reaction.emoji.name) {
        case 'πŸ‡«πŸ‡·':
          TranslateMessage(msg, 'fr');
          break;
        case 'πŸ‡ΊπŸ‡Έ':
          TranslateMessage(msg, 'en');
          break;
        case 'πŸ‡©πŸ‡ͺ':
          TranslateMessage(msg, 'de');
          break;
        case 'πŸ‡ͺπŸ‡Έ':
          TranslateMessage(msg, 'es');
          break;
        case 'πŸ‡―πŸ‡΅':
          TranslateMessage(msg, 'ja');
          break;
      }
    });
    

    If you want to avoid sending a new translation when a user removes the last reaction (meaning reaction.count will be zero again) and then adds it again, you can use the messageReactionRemove event. It's emitted whenever a reaction is removed, so you can check if the reaction.count is dropped to zero, and react as a bot with the same emoji. Of course it would also trigger a translation, so you'll need to filter out bot's reaction:

    bot.on('message', async (msg) => {
      const reactionFilter = () => {
        return msg.author.id !== '724682218454253588';
      };
      const collector = msg.createReactionCollector(reactionFilter);
    
      collector.on('collect', (reaction, user) => {
        if (reaction.count > 1 || user.bot) return;
    
        switch (reaction.emoji.name) {
          case 'πŸ‡«πŸ‡·':
            TranslateMessage(msg, 'fr');
            break;
          case 'πŸ‡ΊπŸ‡Έ':
            TranslateMessage(msg, 'en');
            break;
          case 'πŸ‡©πŸ‡ͺ':
            TranslateMessage(msg, 'de');
            break;
          case 'πŸ‡ͺπŸ‡Έ':
            TranslateMessage(msg, 'es');
            break;
          case 'πŸ‡―πŸ‡΅':
            TranslateMessage(msg, 'ja');
            break;
        }
      });
    });
    
    bot.on('messageReactionRemove', (reaction) => {
      if (reaction.count === 0)
        reaction.message.react(reaction.emoji);
    });