I have been looking for this all day, and I can't seem to find a proper way of assigning roles to members. I tried a couple ways of assigning roles:
#client.command(pass_context=True)
async def claimrank(ctx, role: discord.Role):
user = ctx.message.author
await user.add_roles(role='Rookie')
and:
#client.command()
async def claimrank(member):
role = get(member.guild.roles, name="Rookie")
await member.add_roles(role)
What's worse, is that with both of these attempts, I don't get any errors, but the code doesn't do anything.
Please help!
Thanks in advance.
I got this from a post recently today. I'll write the code and look for the original post.
#client.command(pass_context=True)
async def addrole(ctx):
user = ctx.message.author
role = 'role' #change the role here
try:
await user.add_roles(discord.utils.get(user.guild.roles, name=role))
except Exception as e:
await ctx.send('Cannot assign role. Error: ' + str(e))
Found the original post by #Patrick Haugh: Give and remove roles with a bot, Discord.py
Related
My Goals:
When the user tried to use the command but mentioning a roles, it will sends an errors to the users.
My Current Codes:
#bot.command()
async def say(ctx, *, message: str):
try:
take_roles = ctx.guild
roles = [role.mention for role in take_roles.roles]
if message in roles:
await ctx.send(
f"{ctx.author.mention}, Hm? Trying to Abusing Me? Mention `#roles` is **NOT** Allowed on Say Command!"
)
else:
await ctx.message.delete()
await ctx.send(message)
You were trying to find the whole message in roles. A better idea is to look for role mentions inside of the message.
#bot.command()
async def say(ctx, *, message: str):
for role in ctx.guild.roles:
if role.mention in message:
await ctx.send(f"{ctx.author.mention}, Hm? Trying to Abusing Me? Mention `#roles` is **NOT** Allowed on Say Command!")
return # stops function if the role mention is in message
# if it didn't match any roles:
await ctx.message.delete()
await ctx.send(message)
So the entirety of this command works but I keep getting an error that says:
NotFound: 404 Not Found (error code: 10011): Unknown Role.
I have tried using so many things from the role id to discord.guild.get_role and I keep getting the same error. Any help is appreciated!
#bot.command(pass_context = True)
async def mute(ctx, member: discord.Member):
if ctx.message.author.guild_permissions.administrator:
role = discord.utils.get(ctx.guild.roles, name="Muted")
await member.add_roles(member, role)
embed=discord.Embed(title="User Muted!", description="**{0}** was muted by **{1}**!".format(member, ctx.message.author), color=0xff00f6)
await bot.say(embed=embed)
else:
embed=discord.Embed(title="Permission Denied.", description="You don't have permission to use this command.", color=0xff00f6)
await bot.say(embed=embed)
Your code is partly outdated and the reason you have this error is coming from:
await member.add_roles(member, role)
Before v1.0, you needed to pass member in the method's argument but it's no longer necessary. So here, you're trying to add a discord.Role that is a discord.Member.
Other parts that are outdated:
pass_context=True is also no longer necessary, you can remove it.
bot.say doesn't exist, you can use ctx.send(embed=embed).
You can read more about the v1.0 migration here : Migrating to v1.0
await member.add_roles(role)
That is what you are looking for, as MrSpaar just told you.
Another suggestion I would like to make is doing the following.
Change this
async def mute(ctx, member: discord.Member):
To this:
async def mute(ctx, member: discord.Member = None, *, reason=None):
if not member:
await ctx.send("You must specify a user.")
return
if not reason:
await ctx.send("You must specify a reason.")
return
If you have any further questions let me know.
I simply want my bot to add a role to a user in discord. Although the syntax seems simply, apparently I'm doing something wrong.I'm new to python, so I'd appreciate some pointers in the right direction!
bot = commands.Bot(command_prefix='!')
def getdiscordid(discordname):
for guild in bot.guilds:
for member in guild.members:
if member.name == discordname:
return member.id
#bot.command(name='role')
async def role(ctx):
await ctx.message.channel.send("Testing roles")
discordid = getdiscordid("Waldstein")
print ("id: " , discordid)
member = bot.get_user(discordid)
print ("member: ", member)
role = get(ctx.message.guild.roles, name="Egg")
print("role: ", role.name)
await member.add_roles(role)
print("done")
# error handler
#bot.event
async def on_command_error(ctx, error):
if isinstance(error, commands.errors.CheckFailure):
await ctx.send(error)
bot.run(TOKEN)
In this example he successfully retrieves the member, he can't find the Egg role, and doesn't add the role. [Edit: I corrected the line to retrieve the role, that works but still no added role. Added the error handler]
The key issue is that add_roles() adds roles to a Member object not a user.
Made a couple of tweaks...
Changed the get id to get member and return the member object.
changed the name of the command to add_role() to avoid using role as the command and a variable.
changed to await member.add_roles(role)
Try:
def get_member(discordname):
for guild in bot.guilds:
for member in guild.members:
if member.name == discordname:
return member
#bot.command(name='add_role')
async def add_role(ctx):
await ctx.message.channel.send("Testing roles")
member = get_member("Waldstein")
print(f'member is {member} type {type(member)}')
role = get(ctx.guild.roles, name="Egg")
print("role: ", role.name)
await member.add_roles(role)
print("done")
For the answer's sake, I'm writing the whole discord.utils.get instead of just get. Here's your command rewritten:
import discord
#bot.command()
async def role(ctx):
await ctx.send("Testing roles!")
member = discord.utils.get(bot.get_all_members(), name="Waldstein")
# be careful when getting objects via their name, as if there are duplicates,
# then it might not return the one you expect
print(f"id: {member.id}")
print(f"member: {member}")
role = discord.utils.get(ctx.guild.roles, name="Egg") # you can do it by ID as well
print(f"role: {role.name}")
await member.add_roles(role) # adding to a member object, not a user
print("Done!")
If this doesn't work, try printing out something like so:
print(ctx.guild.roles)
and it should return each role that the bot can see. This way you can manually debug it.
One thing that might cause this issue is that if the bot doesn't have the necessary permissions, or if its role is below the role you're attempting to get i.e. Egg is in position 1 in the hierarchy, and the bot's highest role is in position 2.
References:
Guild.roles
Client.get_all_members()
Member.add_roles()
utils.get()
commands.Context - I noticed you were using some superfluous code, take a look at this to see all the attributes of ctx
Here is the sendMessage function:
async def sendMessage(color, title, value, should_delete=True, channel=""):
embed = discord.Embed(color=color)
embed.add_field(name=title, value=value, inline=False)
if channel == "":
msg = await client.send_message(message_obj.channel, embed=embed)
else:
msg = await client.send_message(client.get_channel(channel), embed=embed)
if should_delete:
await delete_msg(msg)
The bot can mention anyone but everyone and here. Despite having mention everyone permission.
sendMessage(OK_COLOR_HASH, "title", "Hello #everyone")
Edit: When I converted the message type to the normal one instead of embed one, it worked.
You can try to sending a mention to everyone through the default_role attribute
#bot.command(pass_context=True)
async def evy(msg):
await bot.say(msg.message.server.default_role)
You can try this block code. roles return a list all guild's roles, but first role always a default guild role (default_role) and that's why you must use slicing function.
#bot.command()
async def test(ctx):
await ctx.send(ctx.message.guild.roles[0])
Or you can do something like this.
#bot.command()
async def test(ctx):
await ctx.send(ctx.message.guild.default_role)
I have tried and researched a lot of times but still could not find it. I want to make a command that deletes a selected role in the server. Here is what I came up with (Don't currently care about permissions):
#bot.command(pass_context=True)
async def delrole(ctx, role: discord.Role):
await bot.delete_role(role)
await bot.say("The role {} has been deleted!".format(role.name))
If you could help that would be awesome. I used role: discord.Role and delete_role(). Thank you for reading. If you have a solution, feel free to comment it.
NOTICE: This post was for the old version of discord.py and will no longer work. If you are looking for an equivalent solution for the rewrite (v1) version of discord.py, you can use the following code:
#bot.command(pass_context=True)
async def delrole(ctx, *, role_name):
role = discord.utils.get(ctx.message.guild.roles, name=role_name)
if role:
try:
await role.delete()
await ctx.send("The role {} has been deleted!".format(role.name))
except discord.Forbidden:
await ctx.send("Missing Permissions to delete this role!")
else:
await ctx.send("The role doesn't exist!")
You could do something like this to avoid being able to only delete roles that are mentionable
#bot.command(pass_context=True)
async def delrole(ctx, *,role_name):
role = discord.utils.get(ctx.message.server.roles, name=role_name)
if role:
try:
await bot.delete_role(ctx.message.server, role)
await bot.say("The role {} has been deleted!".format(role.name))
except discord.Forbidden:
await bot.say("Missing Permissions to delete this role!")
else:
await bot.say("The role doesn't exist!")
where you do !delrole name_of_role and use discord.utils.get to find the role by its name from the list of roles on the server.
Then if it's found you can delete it with bot.delete_role which takes 2 arguments, the server you want to delete the role from and the role itself
All you're missing is the server argument to delete_role, (which it shouldn't need, as every Role knows what Server it is from)
#bot.command(pass_context=True)
async def delrole(ctx, role: discord.Role):
await bot.delete_role(role.server, role)
await bot.say("The role {} has been deleted!".format(role.name))
You were already on the right track using converters
The above solutions will not work server has to be guild and the actual role deletion can be a lot easier.
#bot.command(pass_context=True)
async def delrole(ctx, *, role_name):
role = discord.utils.get(ctx.message.guild.roles, name=f"{role_name}")
await role.delete()
await ctx.send(f"[{role_name}] Has been deleted!")
This solution is working as of 28/08/2021.