In our last article, we explored how we can use Collectors to prompt a user for additional input. Reaction Collectors work in a similar way, but collect Reactions or Emojis to a particular message. This technique is used in a lot of bots where input might need to be gathered from multiple people, such as a voting system.

Creating a Reaction Collector

In this example, we’re going to add a basic reaction collector to respond to two possible reactions: 👍 and 👎. Depending on the reaction, our bot will respond in different ways. Add the following code to your message handler;

if (msg.content.startsWith('!react')) {
    // Use a promise to wait for the question to reach Discord first
    msg.channel.send('Which emoji do you prefer?').then((question) => {
      // Have our bot guide the user by reacting with the correct reactions
      question.react('👍');
      question.react('👎');

      // Set a filter to ONLY grab those reactions & discard the reactions from the bot
      const filter = (reaction, user) => {
        return ['👍', '👎'].includes(reaction.emoji.name) && !user.bot;
      };

      // Create the collector
      const collector = question.createReactionCollector(filter, {
        max: 1,
        time: 15000
      });

      collector.on('end', (collected, reason) => {
        if (reason === 'time') {
          msg.reply('Ran out of time ☹...');
        } else {
          // Grab the first reaction in the array
          let userReaction = collected.array()[0];
          // Grab the name of the reaction (which is the emoji itself)
          let emoji = userReaction._emoji.name;

          // Handle accordingly
          if (emoji === '👍') {
            msg.reply('Glad your reaction is 👍!');
          } else if (emoji === '👎') {
            msg.reply('Sorry your reaction is 👎');
          } else {
            // This should be filtered out, but handle it just in case
            msg.reply(`I dont understand ${emoji}...`);
          }
        }
      });
    });
  }

There are a few things you’ll notice about this code. The first is that instead of replying directly to the user, we’re sending messages directly into the channel. Sending a message to the channel actually returns a Promise so we can chain another function with the output of the promise, which contains info about the message we just sent.

Once the promise returns, we can take that message and react to it directly. Then we create a reaction collector with createReactionCollector with a filter and options just like we did for the standard collector. We handle the end event pretty much like we did with the standard collector as well. Here are the results;

In the next article, we’ll put everything we’ve learned so far into creating a command that allows users to create surveys!