How to delete a role with discord.py? - python

Using the following lines of code:
#bot.command(pass_context=True)
async def ban_role(ctx, *,role_name):
role = discord.utils.get(ctx.message.server.roles, name=role_name)
if role:
try:
await ctx.delete_role(ctx.message.server, role)
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!")
I get the error:

You're using outdated syntax from v0.16 of discord.py that isn't supported anymore.
See the migration guide for v1, specifically how Server is now Guild.
You can also just get the guild directly from the Context object's guild attribute, instead of going through its message attribute.
Aditionally, unless you've overridden your Context, it's not going to have a delete_role method.
You'll want to use the Role.delete method instead.
For help with markdown, see https://stackoverflow.com/editing-help.

Related

How can I get the mentioned members from a Discord message?

I am trying to make custom commands and thus I am using the on_message event, but one issue I am having is getting the mentioned member in the message, so for example ;give #member.
if message.content.lower().startswith(f";{command}") and message.raw_mentions and content == "None":
mention = message.raw_mentions[0]
if message.content.lower() == f";{command} {mention}":
try:
role = get(message.guild.roles, id=role)
if role:
member = message.guild.get_member(mention)
if member:
await member.add_roles(role)
await message.add_reaction("✅")
except:
return await message.channel.send("I do not have the permissions to give roles, If this is incorrect, You may need to move my role above the role you want to receive/give")
This what I currently have and I haven't been getting any errors, but I'm mainly having issues getting the member that is mentioned.
You don't need the unnecessary steps to get the mention out of the message.
If you want to check if the entered message has user mentions, you can just check the attribute message.mentions. It returns an entire list of all Discord users that was mentioned in the message.
So you can write some code like this:
if message.mentions:
as an example to check if users were mentioned in the message. And of course, you can get every mentioned user directly from the list with a small loop.
Aside from that, your method to get a role is really old. Instead, you should switch to the newer version of it to avoid bugs.
# Check if users are mentioned
if message.mentions:
# check if the role exists
role = message.guild.get_role(int(role))
if role is None:
return
# Add roles to all mentioned members
for member in message.mentions:
await member.add_roles(role)
# Add an reaction after all roles was added
await message.add_reaction("✅")
You should read these articles for more detailed documentation:
message.mentions
guild.get_role

How do I remove roles from a user?

I'm currently trying to add reaction roles to my bot, but I'm having trouble getting the bot to remove roles when the reactions are removed
#client.event
async def on_raw_reaction_add(payload):
print("Reaction Added")
if ((payload.message_id == 874372383736205343) and (payload.emoji.name == '🎓')):
guild = client.get_guild(payload.guild_id)
role = guild.get_role(874364790099836948)
await payload.member.add_roles(role)
#client.event
async def on_raw_reaction_remove(payload):
print("Reaction Removed")
if ((payload.message_id == 874372383736205343) and (payload.emoji.name == '🎓')):
guild = client.get_guild(payload.guild_id)
role = guild.get_role(874364790099836948)
await payload.remove_roles(role)
Adding roles works perfectly as intended but whenever I try removing a reaction I always get some kind of error. I've tried a few different things, but the code that I provided returns "Attribute Error: "RawReactionAddEvent" object has no attribute "remove_roles"
As I said, I've tried things other than remove_roles but none of them worked.
I'm pretty new to discord.py and python as a whole so this is probably a really obvious mistake but I just can't seem to find anything that works.
You'll need to retrieve a member object in order to remove the roles. You're currently trying to remove a role from payload instead of a valid member.
guild = client.get_guild(payload.guild_id)
member = await guild.fetch_member(payload.user_id)
role = guild.get_role(874364790099836948)
await member.remove_roles(role)
As Lukasz points out, you can't use payload.member when a reaction is removed because it is only available when a reaction is added. Docs.

Discord.py guild invite bot

If the code is correct, I want to make a bot where the bot invites me to a specific server.
but it has error.
Here's my code:
#client.command()
async def invite(ctx, *, code):
if code == "12320001":
guild = "851841115896152084"
invite = await ctx.guild.create_invite(max_uses=1)
await ctx.send(f"Here's your invite : {invite}")
else:
await ctx.send(f"Code is wrong!")
and error:
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'NoneType' object has no attribute 'create_invite'
ctx.guild is None, that is why you are getting this Exception.
You can check the value of ctx.guild before passing ctx as a parameter while calling invite function.
As the error suggests, ctx.guild is None. This usually occurs when invoking a command in a DM rather than in a server, as there obviously is no server in DMs.
Judging by the fact that you have a guild variable that you never used I assume that you're trying to invite people to that guild instead.
# Make sure the id is an int, NOT a string
guild = client.get_guild(85184111589615208)
# Invite users to the guild with the above id instead
invite = await guild.create_invite(max_uses=1)
You need a Channel object to create an invite as the Guild class doesn't have a create_invite() method. You can the code given below. Note that the server should have at least one channel.
#client.command()
async def invite(ctx, code):
if code == "12320001":
guild = client.get_guild(851841115896152084)
invite = await guild.channels[0].create_invite(max_uses = 1)
await ctx.send(f"Here's your invite: {invite}")
else:
await ctx.send("Invalid code!")

Deleting a role in discord.py

So, I came up with this command similar to my createrole command. Everything works except the last line of code. I just don’t understand why it won’t delete. Every time I send the code, this error comes up: discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: delete() got an unexpected keyword argument ‘name’. I am using the latest version of python and discord.py.
#client.command(aliases=['delrole'])
#commands.has_permissions(manage_roles=True)
async def deleterole(ctx, *,role, reason=None):
delrole = role
guild = ctx.guild
for role in guild.roles:
if role.name == delrole:
await ctx.send(delrole)
await role.delete(name=delrole)
Get rid of name=delrole and just leave it as role.delete(), This should delete the role! Add ctx.send(‘The role has been deleted’) to the end so you know when if the role was deleted. You can also deleted ctx.send(delrole) to make it more clean but, I left it.
#commands.has_permissions(manage_roles=True)
async def deleterole(ctx, *,role, reason=None):
delrole = role
guild = ctx.guild
for role in guild.roles:
if role.name == delrole:
await ctx.send(delrole)
await role.delete()
await ctx.send(f’The role {delrole} has been deleted!’)```

Permission Check Discord.py Bot

I am working on a discord bot for basic moderation which does kick, ban and mute for now at least. But the problem is other members can use it too. I want only a few specified role who can use it.
Don't want to work on it depending on the #role either because the name of the roles across different servers aren't the same. Also wanting to keep the bot as simple as possible.
Now, I started out as this:
#client.command(name='ban')
async def mod_ban(member: discord.User):
try:
await client.ban(member, delete_message_days=0)
await client.say('**{0}** has been banned.'.format(str(member)))
except Exception as error:
await client.say(error)
But any member can use the commands then. So, tried follow this one = Permission System for Discord.py Bot and ended up with this:
#client.command(name='ban')
async def mod_ban(context, member: discord.User):
if context.message.author.server_premission.administrator:
try:
await client.ban(member, delete_message_days=0)
await client.say('**{0}** has been banned.'.format(str(member)))
except Exception as error:
await client.say(error)
else:
await client.say('Looks like you don\'t have the perm.')
Which lands me with this error: ;-;
raise MissingRequiredArgument('{0.name} is a required argument that is missing.'.format(param))
discord.ext.commands.errors.MissingRequiredArgument: member is a required argument that is missing.
Also, besides context.message.author.server_premission.administrator I don't only want the roles with Admin perm to use this command. I also want a few other roles with have few perms like manage message, manage roles etc. to use to command too.
Thanks in advance for the help! Also, sorry if I've missed anything stupid or silly ;-;
You aren't passing the context into the coroutine in your second example (and as #Andrei suggests, you can only ban members):
#client.command(name='ban', pass_context=True)
async def mod_ban(context, member: discord.Member):
...
Also, I should probably update my answer to that question. In the context of commands, you can use the very powerful checks built into discord.ext.commands to do a lot of this for you. has_permissions does exactly what you're looking for, validating that the user has any of the necessary permissions.
from discord.ext.commands import has_permissions, CheckFailure
#client.command(name='ban', pass_context=true)
#has_permissions(administrator=True, manage_messages=True, manage_roles=True)
async def mod_ban(ctx, member: discord.Member):
await client.ban(member, delete_message_days=0)
await client.say('**{0}** has been banned.'.format(str(member)))
#mod_ban.error
async def mod_ban_error(error, ctx):
if isinstance(error, CheckFailure):
await client.send_message(ctx.message.channel, "Looks like you don't have the perm.")
As far as I can see in the discord.py documentation discord.User is not the same as discord.Member.
Try to change
async def mod_ban(context, member: discord.User):
to
async def mod_ban(context, member: discord.Member):
If you are using discord.py rewrite, you can use checks (Discord.py rewrite checks)
Which (obviusly) checks for certain things suchs as roles or permissions on the command invoker
You can use both of this decorators, below your first decorator
#commands.has_role("rolename"/roleid)
#commands.has_any_role("rolename"/roleid,"rolename"/roleid,"rolename"/roleid ...)
Where rolename is a string containing the EXACT name of the role, letter by letter and space by space, and roleid is the id of the role, which, in case it's mentionable, you can get it by typing #rolename on any of your server chatrooms
Note how you must use the second decorator if you want to pass more than one role to check

Categories