I just started having a problem with my discord.js role management bot. The bot will successfully add a role upon reaction event. If a user then removes the reaction, the role should disappear.
I have a helper method that early returns if the user doesn't have the role (to avoid unnecessary work, and keep logging clean). This method is preventing the role from being removed on the first reaction removal event. The sequence is as follows:
guild.members.cache.get(user.id).roles.cache.has(role.id) returns false.The role properly appears in discord correctly the first time, however I did some sleuthing, and added the following code to the bot:
guild.members.cache.get(member.id).roles.add(role.id)
.then(() => guild.members.cache.get(author.id))
.then(user => console.log(user._roles));
The output doesn't include the new role, despite the user being promoted in the client, so it seems the cache is not updated immediately. How can I make sure I'm fetching the most up to date information?
Edit: I ended up working around this by creating my own cache to store roles in, but for posterity, here's some additional code to try to isolate the cause:
let guild;
const messageId = //some value
const roleId = //some value
const channelId = //some value
const emojiName = //some value
client.on('messageReactionAdd', async (reaction, user) => {
handleReactionAdded(reaction, user)
});
client.on('messageReactionRemove', async (reaction, user) => {
handleReactionRemoval(reaction, user)
});
const handleReactionAdded = async (reaction, user) => {
if (reaction.message.partial) await reaction.message.fetch();
if (reaction.partial) await reaction.fetch();
if (user.bot || !reaction.message.guild) return;
if (reaction.message.id == messageId && reaction.message.channel.id == channelId && reaction.emoji.name === emojiName) {
guild = reaction.message.guild
if (_hasRole(user)) return;
guild.members.cache
.get(user.id)
.roles
.add(roleId)
}
const handleReactionAdded = async (reaction, user) => {
if (reaction.message.partial) await reaction.message.fetch();
if (reaction.partial) await reaction.fetch();
if (user.bot || !reaction.message.guild) return;
if (reaction.message.id == messageId && reaction.message.channel.id == channelId && reaction.emoji.name === emojiName) {
guild = reaction.message.guild
if (!_hasRole(user)) return;
guild.members.cache
.get(user.id)
.roles
.remove(roleId)
}
const _hasRole = user => {
return guild.members.cache.get(user.id).roles.has(roleId);
}
If it's an issue with the cache being out of date, force fetching the member from the API after you add the role might resolve it, since the roles manager doesn't seem to have its own fetch method, but I'm not certain.
await guild.members.fetch({user, force: true})