Daniel Arputharaj
Daniel Arputharaj

Reputation: 13

'User' object has no attribute 'add_roles'

When trying to do await member.add_roles(role) where member is a User, it gives me the following error:

'User' object has no attribute 'add_roles'

However, when I look online, there is no mention of such an error, implying that this error isn't supposed to happen.

If it helps, this is the section of the code where this error happens:

@bot.event
async def on_raw_reaction_add(payload):
    EMOJI = '✅'
    guild = discord.utils.get(bot.guilds, name='The Molehill')
    channel = bot.get_channel(740608959207047250)
    member = await bot.fetch_user(payload.user_id)
    message = await channel.fetch_message(payload.message_id)
    MESSAGE = "{user.name} is now part of the Mole Workforce!"
    rules_message = message=await channel.fetch_message(740891855666806866)
    role = discord.utils.get(guild.roles, name="Worker Mole", id=739514340465705027)
    if payload.emoji.name == EMOJI:
        if message == rules_message:
            await member.add_roles(role)
            await bot.send(MESSAGE)

Upvotes: 1

Views: 4051

Answers (2)

Deru
Deru

Reputation: 1173

A user object is not directly linked with a guild. This is the reason it doesnt have functions to add roles to it. As roles are part of guild functionality.

If we want to fix this we need to get an object that is linked with a guild. The closest match is in this case the member object.

So instead of retrieving the user object and retrieving a member object instead should solve the problem:

@bot.event
async def on_raw_reaction_add(payload):
    EMOJI = '✅'
    guild = discord.utils.get(bot.guilds, name='The Molehill')
    channel = bot.get_channel(740608959207047250)
    member = await guild.get_member(payload.user_id)
    message = await channel.fetch_message(payload.message_id)
    MESSAGE = "{user.name} is now part of the Mole Workforce!"
    rules_message = message=await channel.fetch_message(740891855666806866)
    role = discord.utils.get(guild.roles, name="Worker Mole", id=739514340465705027)
    if payload.emoji.name == EMOJI:
        if message == rules_message:
            await member.add_roles(role)
            await bot.send(MESSAGE)

But when we read the documentation about the on_raw_reaction_add. We see that this can be much more efficient without needing lookups through the bot.

For example in the event documentation you see we get a payload object. The payload object has the following data (and more just read the documentation):

Notice that we have a member object. We can retrieve the following from it:

So updating the old code to the following increases the performance as we dont need to look up stuff through the bot unnessecarily. Note: I removed some redundant code in this example, I assume you only run this bot in 1 guild, because you are using specific ID's that wont work in other guilds.

@bot.event
async def on_raw_reaction_add(payload):
    EMOJI = '✅'
    member = payload.member
    guild = member.guild
    # If you want to run your bot on multiple guilds. Then the code under this comment should be updated.
    channel = guild.get_channel(740608959207047250)
    MESSAGE = "{user.name} is now part of the Mole Workforce!"
    role = guild.get_role(739514340465705027)
    if payload.emoji.name == EMOJI:
            await member.add_roles(role)
            await bot.send(MESSAGE)

Upvotes: 2

onesome
onesome

Reputation: 96

You are trying to add a role to a user object, however they can only be added to member objects. While a user represents a user on discord a member represents a member of a guild. More information on members in the documentation

Upvotes: 2

Related Questions