0
votes

I've been trying to code a discord bot in discord.js with a command that allows user to react to the message and receive a role. This is my current code. I am unsure how to make it where when a user's added a reaction it gives a role and when the reaction for a user has removed the role it took away.

const { RichEmbed } = require('discord.js');
const Discord = require("discord.js");
const colors = require("../colors");
const botconfig = require("../botconfig");



exports.run = async (client, message, args) => {

   await message.delete().catch(O_o=>{});

  const role1 = message.guild.roles.get('688477558982836344'); // Replace with Updates ID
  const role2 = message.guild.roles.get('688477690344374283'); // Replace with Events ID
  const role3 = message.guild.roles.get('688477467840872452'); // Replace with QOTD ID
  const role4 = message.guild.roles.get('688477868078137369'); // Replace with Polls ID
  const role5 = message.guild.roles.get('687498488295981069'); // Replace with Social Media ID

  const embed = new Discord.RichEmbed()
        .setTitle('Pinged Roles')
        .setDescription(`

        Tip: *Double React to remove a role*

        ❤️ ${role1.toString()}
        ???? ${role2.toString()}
        ???? ${role3.toString()}
        ???? ${role4.toString()}
        ???? ${role5.toString()}

        `)
        .setColor(colors.purple)
        .setFooter('mc.advancius.net')

  message.channel.send(embed).then(async msg => {

    await msg.react('❤️');
    await msg.react('????');
    await msg.react('????');
    await msg.react('????');
    await msg.react('????');


    }); 

}

module.exports.help = {
    name: "roles"
};
1

1 Answers

1
votes

From your code it seems like you are using Discord.js v11, but I'll include code for v12 as well because that's the latest version.

v11

You'll need to use the messageReactionAdd and messageReactionRemove events of Client as ReactionCollector has no remove event.

// I added this object because I prefer having this than having lots of repeated code
// you can still do this the way you were doing before
const roles = {
  '❤️': '688477558982836344',
  '🧡': '688477690344374283',
  '💛': '688477467840872452',
  '💚': '688477868078137369',
  '💙': '687498488295981069'
}

exports.run = async (client, message, args) => {
  await message.delete()

  const embed = new RichEmbed()
    .setTitle('Pinged Roles')
    .setDescription(`
      Tip: *Double React to remove a role*

      ${Object.entries(roles)
        .map(([emoji, id]) => `${emoji} ${message.guild.roles.get(id).toString()}`)
        .join('\n')}
    `)
    .setColor(colors.purple)
    .setFooter('mc.advancius.net')

  message.channel.send(embed).then(async msg => {
    // react with every emoji
    for (const emoji of Object.keys(roles)) await msg.react(emoji)

    client.on('messageReactionAdd', ({emoji, message}, user) => {
      // if the message that the user reacted to is the same as the message with
      // the reactions, add the role
      if (message.id === msg.id) message.guild.members.get(user.id).addRole(roles[emoji.name])
    })

    client.on('messageReactionRemove', ({emoji, message}, user) => {
      // same as above but remove the role
      if (message.id === msg.id) message.guild.members.get(user.id).removeRole(roles[emoji.name])
    })
  })
}

v12/v13

You can use createReactionCollector as ReactionCollector has a remove event, which fires when a reaction is removed.

// I added this object because I prefer having this than having lots of repeated code
// you can still do this the way you were doing before
const roles = {
  '❤️': '688477558982836344',
  '🧡': '688477690344374283',
  '💛': '688477467840872452',
  '💚': '688477868078137369',
  '💙': '687498488295981069'
}

exports.run = async (client, message, args) => {
  await message.delete()

  // because RoleManager.fetch is async
  const rolesArray = await Promise.all(Object.entries(roles)
    .map(async ([emoji, id]) => `${emoji} ${(await message.guild.roles.fetch(id)).toString()}`)
  )
  const embed = new MessageEmbed()
    .setTitle('Pinged Roles')
    .setDescription(`
      Tip: *Double React to remove a role*

      ${rolesArray.join('\n')}
    `)
    .setColor(colors.purple)
    .setFooter('mc.advancius.net')

  // for v12:
  // message.channel.send(embed).then(async msg => {
  message.channel.send({embeds: [embed]}).then(async msg => {
    const emojis = Object.keys(roles)
    for (const emoji of emojis) await msg.react(emoji)

    // only collect reactions that are the role emojis
    // for v12:
    // const collector = msg.createReactionCollector(({emoji}) => emojis.includes(emoji.name))
    const collector = msg.createReactionCollector({
      filter: ({emoji}) => emojis.includes(emoji.name)
    })

    collector.on('collect', ({emoji, message}, user) => {
      message.guild.members.fetch(user).then(member => {
        member.roles.add(roles[emoji.name])
      })
    })

    collector.on('remove', ({emoji, message}, user) => {
      message.guild.members.fetch(user).then(member => {
        member.roles.remove(roles[emoji.name])
      })
    })
  })
}