Frossy
Frossy

Reputation: 458

Object.forEach in filter function

I am using Discord.js to write a Discord bot in this project. I am trying to put a ReactionCollector on a message and check if the reaction used is inside my data.

The data is stored in this config.json

{
  "botId": "xxxxxxxxxxxxxxx",
  "emojis": {
    "classes": [{
      "one": "716821724884238506",
      "two": "716821724863266876",
      "three": "716821724884369488"
    }]
  }
}

This is the filter I want to assign to the ReactionController. It should trigger if the found reaction is inside the config.json and is not written by the bot itself.

const filter = (reaction, user) => {

  if(user.id === CONFIG.botId) {
    return false;
  }

  CONFIG.emojis.classes.forEach(obj => {
    Object.entries(obj).forEach(([key, value]) => {
      if(value === reaction.emoji.id) {
        console.log(`key: ${key}, value: ${value}`)
        return true;
      }
    });
  });
}

And finally the collector i want to use the filter in:

const collector = message.createReactionCollector(filter);
collector.on('collect', (reaction, user) => {
  console.log(`Collected: ${reaction.emoji.id}`);
  let alreadySetClass = '';
  if (message.channel.name.includes(reaction.emoji.name.toLowerCase())) {
    alreadySetClass = reaction.emoji.name.toLowerCase()
  }

  console.log("setClass: " + alreadySetClass)
  setChannelName(message.channel, reaction.emoji.name, alreadySetClass)

})

The response i get by collecting the reaction is a MessageReaction object.

The consol.log of the filter will print the key, value pair correctly. But the console.log('collected: ') inside the collector won't execute at all. There are no errors in the console. I don't know what I'm missing here. I think there is something wrong with the way I wrote the filter. Some help would be awesome. Thx in advance.

Upvotes: 0

Views: 394

Answers (1)

Federico Grandi
Federico Grandi

Reputation: 6806

That's because in your filter you're returning true from the callback of the forEach method: that means that the callback will return true, but your filter won't receive any return and so will return undefined, which is interpreted as false (and so won't collect any reaction).
Instead of forEach, try using the Array.some() method: if any of the callbacks return true for one element, the method will return true.

Here's how I would do it:

const filter = (reaction, user) => {
  // Check if the id is different and if for any of the classes ...
  return user.id != CONFIG.botId && CONFIG.emojis.classes.some(obj => {
    // ... at least one entry ...
    return Object.entries(obj).some(([key, value]) => {
      // ... has a value that matches the emoji id
      if (value == reaction.emoji.id) {
        console.log(`key: ${key}, value: ${value}`)
        // If so, return true
        return true
      }
    })
  })
}

PS: I know there's a lot of nested functions and it's not the most readable code, but it should do the trick.

Upvotes: 2

Related Questions