Gagak
Gagak

Reputation: 161

discord.py command can only work for user with one of several role in a list

I am currently building a discord bot using Discord py with one of its command can only be used by a user with one of several roles that I have set up.

Currently, I store all of the role name in a list since I also have a command to add new role to that list. This is a snippet of what I have right now

role_name = ["Moderator"]

@bot.command(name='role',help='adding role for staff moderating role (admin only command)')
@commands.has_permissions(administrator=True)
async def add_role(ctx, role):
    if role not in role_name:
        role_name.append(role)

    print(*role_name) #use case 1: when run this command to add 'mine' it print "Moderator mine"

@bot.command(name='add',help='Add channel, when you run this command, you must be in the channel ')
@commands.has_any_role(role_name)
async def add_channel(ctx):
    if ctx.channel.id not in channel_id:
        channel_id.append(ctx.channel.id)

I have double check on my account's role on discord and it already have Moderator role

enter image description here

However, when I run the command to test - this is what i got

discord.ext.commands.errors.MissingAnyRole: You are missing at least one of the required roles: '['Moderator']'

Is there any way to do what I want?

/Edit: Add the adding role to the role_name for the sake of clarity. I also have tried ",".join(role_name) in has_any_role() however, I still get this issue discord.ext.commands.errors.MissingAnyRole: You are missing at least one of the required roles: ''

Upvotes: 0

Views: 1402

Answers (2)

Gagak
Gagak

Reputation: 161

After some extra research regarding the decorator. Apparently, based on this answer https://stackoverflow.com/a/64544809/10467473 -

A decorator is invoked once as soon as the module is imported, and then the function that gets called is whatever was provided by the decorator definition.

Therefore, I tried a different approach to check the role like how I wanted it to be and now it works perfectly fine! This is the method that I use.

role_name=[]

@bot.command(name='role',help='adding role for staff moderating role (admin only command)')
@commands.has_permissions(administrator=True)
async def add_role(ctx, role):
    if role not in role_name:
        role_name.append(role)

@bot.command(name='add',help='Add channel, when you run this command, you must be in the channel ')
async def add_channel(ctx):
    global role_name
    user_role = ctx.author.roles
    for rl in user_role:
        if (rl.name in role_name):
           if ctx.channel.id not in channel_id:
              channel_id.append(ctx.channel.id)
              break

Upvotes: 0

Emmanuel
Emmanuel

Reputation: 333

has_any_role() accepts *items and is looking for str or int objects. The list is read as a string '["Moderator"]'. You can check this by trying to rename your rolename as well.

A simple fix for this would be: @commands.has_any_role(*role_name) for your bot from read the list as a string.

So it looks like this:

role_name = ["Moderator"]

@bot.command(name='add',help='Add channel, when you run this command, you must be in the channel ')
@commands.has_any_role(*role_name)
async def add_channel(ctx):
    if ctx.channel.id not in channel_id:
        channel_id.append(ctx.channel.id)

Upvotes: 1

Related Questions