Kali
Kali

Reputation: 65

How to give a role without specifying the exact name of the role

I was wondering if there was a way to self-assign roles without having to specify the exact name of the role. For instance, if I wanted the role 'D.Bch.100', I could just write 'bch' and still get the role. Here's my code:

@client.command(name = "giverole", aliases = ["giveroles"])
async def giverole(ctx, *, rolename):
    role = discord.utils.get(ctx.guild.roles, name=rolename)
    user = ctx.message.author
    await user.add_roles(role)
    await ctx.channel.send("Done! Added " + rolename + (" role to {0.author.mention}. Enjoy it!").format(ctx))

Upvotes: 0

Views: 212

Answers (1)

stijndcl
stijndcl

Reputation: 5647

You can use a for-loop (or alternatively a regex) to iterate over all roles & their names, and check if the entered string is anywhere in the name. Do keep in mind that this will match another role unintentionally, as for example te is in both test and testing. You could force a minimum query length optionally, but that also doesn't make sure this doesn't happen. You can also prevent this issue & show a list of all matched roles, asking the user which one they want.

@client.command(name = "giverole", aliases = ["giveroles"])
async def giverole(ctx, *, rolename):
    role_to_give = None
    for role in ctx.guild.roles:
        if rolename in role.name.lower():
            role_to_give = role # found it
            break
    if role_to_give is None:
        # no role contains their query in the name
    else:
        await user.add_roles(role)
await ctx.channel.send("Done! Added " + role_to_give.name + (" role to {0.author.mention}. Enjoy it!").format(ctx))

Casting the role name to lowercase to make it work case insensitively.

Though I do strongly recommend tagging a role instead, as was suggested in the comments. Unlike what you mentioned in a comment, roles having long names should not pose an issue, as Discord provides suggestions based on what you're typing, so typing part of it should already bring it up. You can even use a built-in converter to instantly get the role instance as well.

@client.command(name = "giverole", aliases = ["giveroles"])
async def giverole(ctx, *, rolename: discord.Role):
    await ctx.author.add_roles(rolename)
    await ctx.send("Added " + rolename.name)

Also, you don't have to use ctx.message.author to get the author, ctx.author works as well & is a bit shorter.

Lastly, I don't fully understand why you're using format strings while still concatenating them? It kind of defeats the purpose of using a format string in the first place. string_a + string_b + string_c.format(d) might as well be "string_a {} {}".format(string_b, string_d).

Upvotes: 1

Related Questions