Discord JS add role by reaction command doesn’t work after restart

Tags: , ,



I’m trying to make a “add role by reaction” command. So when a member reacts to a specific message, the member gets a role. It actually works but when I restart my bot, it doesn’t add a role anymore. Can anyone help?

here the code:

bot.on('message', msg=>{
    if(msg.content.startsWith(prefix + "react")){
        let embed = new Discord.MessageEmbed()
        .setTitle("Reactions Roles")
        .setDescription("React to get a role!")
        .setColor("BLUE")
        msg.channel.send(embed).then(m=> m.react("emoji_id"))
    }
})

bot.on("messageReactionAdd", async (reaction, user)=>{
    if (reaction.message.partial) await reaction.message.fetch();
    if (reaction.partial) await reaction.fetch();
    if(user.bot) return;
    if(!reaction.message.guild) return;
    if(reaction.message.channel.id === "channel_id"){
        if(reaction.emoji.id === "emoji_id"){
            await reaction.message.guild.members.cache.get(user.id).roles.add("role_id")
        }
    }
})

bot.on('messageReactionRemove', async (reaction, user)=>{
    if(reaction.message.partial) await reaction.message.fetch();
    if(reaction.partial) await reaction.fetch();

    if(user.bot) return;
    if(!reaction.message.guild) return;

    if(reaction.message.channel.id === "channel_id"){
        if(reaction.emoji.id === "emoji_id"){
            await reaction.message.guild.members.cache.get(user.id).roles.remove("role_id")
        }
    }
})

Answer

To make your bot check if previous messages have been reacted upon you could use a code similar to this

let guildID = "xxx";
let channelID = "xxx";
let emojiID = "xxx";
let roleID = "xxx";


bot.on("ready", async () => {

    let guild = bot.guilds.cache.find(guild => guild.id == guildID);
    let channel = await guild.channels.cache.find(ch => ch.id == channelID)

    // You can set any limit you want, for performance I used a low number
    channel.messages.fetch({ limit: 10 })
        .then(async messages => {
            messages.forEach(async message => {

                if (message.partial) await message.fetch();
                if (!message.guild) return;

                for (let reactionObj of message.reactions.cache) {
                    for (let reaction of reactionObj) {
                        if (typeof reaction == "string") continue;
                        if (reaction.emoji.id != emojiID) continue;
                        reaction.users.fetch()
                            .then(async users => {
                                users.forEach(async user => {
                                    if (user.bot) return;
                                    console.log("Adding role")
                                    await reaction.message.guild.members.cache.get(user.id).roles.add(roleID)
                                })
                            })
                    }
                }

            });
        })
        .catch(console.error);
});

You might want to make some changes, but this works.

To break it down…

  1. Get messages in a specific channel (or multiple)
  2. Check if the message has reactions
  3. Check if any of the reactions match a specific emoji
  4. Add the role to the guild member
  5. Optionally check if the member already has the role before attempted to add it

Please note that this code might very well not be the most efficient, but it gets the job done. Also, it does NOT work with “non-custom” emojis, for that you’ll have to check for emoji.name instead of emoji.id.

As suggested by @michael.grigoryan it is very recommended to check out the documentation.

Edit: Removed previous answer, to remove confusion



Source: stackoverflow