Handle mentionless nickname command - python

So I'm trying to create a nickname command that has the ability to set the nickname of both the author and a pinged user. I am able to nickname a pinged user, but when I try to nickname myself (as in the author) I get discord.ext.commands.errors.MemberNotFound: Member "[NICKNAME]" not found.
#client.command(aliases=['nickname'])
#commands.has_permissions(change_nickname=True)
async def nick(ctx, member: discord.Member=None, *, nickname):
if member is None:
member = ctx.author
await member.edit(nick=nickname)
await ctx.send(f'`Sucessfully changed nickname!`')

Related

Trying to have a bot that adds role to someone in a server if they send a certain thing to the bot in DMS discord.py

I want a bot that gives users a certain role in my server if they send a certain phrase to the bot in DMs.
This is what I have so far:
if message.guild is None:
if passphrase in message.content:
await message.channel.send("You've been verified!")
serv = client.get_guild(00000000000000000000)
role = serv.get_role(000000000000000000000)
if message.author in serv.members:
message.author.add_roles(role, reason="Member was verified via DMs.")
await message.channel.send("You've been verified!")
If the passphrase is in the message, the user gets "You've been verified!" in their DM but the user doesn't get the role specified in the server.
How do I fix this?
message.author is a discord.User object. Is has not add_roles method you need to get it as a guild member using serv.get_member(message.author.id).
add_roles is a coroutine therefore you need to await it using await keyword
Your code should looks like this:
if message.guild is None:
if passphrase in message.content:
await message.channel.send("You've been verified!")
serv = client.get_guild(00000000000000000000)
role = serv.get_role(000000000000000000000)
member = serv.get_member(message.author.id)
if member us not None
await member.add_roles(role, reason="Member was verified via DMs.")
await message.channel.send("You've been verified!")

I want to change my ban command to not ban any staff members discord.py

I want to be able to change this code to where staff cannot ban staff regardless of position and not go off higher roles like admins can't ban mods. I tried to tie it to the staff role but the bot does not send an output.
#commands.command()
#commands.has_permissions(ban_members=True)
#commands.bot_has_guild_permissions(ban_members=True)
async def ban(self, ctx, user, *, reason: commands.clean_content = '[No reason given]'):
""" Ban a user from the current guild. """
author = ctx.author
guild = ctx.guild
user = await self.fetch_user(ctx, user)
if guild.get_member(user.id) and (guild.get_member(user.id).top_role.position >= guild.me.top_role.position): >This is where heirarchy comes into play
raise GenericCustomException(
"Sorry, but I can not ban that user. Maybe try checking my role hierarchy?"
)
else: # this is where I try to pass the mod role to be ignored from banning each other
if discord.utils.get(user.roles, id=<insert mod role id here>):
return await ctx.send("you cannot ban a staff member")
I'd try searching if the user has a certain permission that one of your roles have, then if true, send the message. For example, if I wanted to see if the user had ban_members permissions:
if user.guild_permissions.ban_members:
return await ctx.send("you cannot ban a staff member")
Make sure to replace ban_members with any other permission that suits your needs.
You can iterate through the roles of the user and check if he has a role in a list of mod roles. I prefer to use the role IDs since it can't be changed.
#commands.command()
#commands.has_permissions(ban_members=True)
#commands.bot_has_guild_permissions(ban_members=True)
async def ban(self, ctx, user, *, reason: commands.clean_content = '[No reason given]'):
""" Ban a user from the current guild. """
author = ctx.author
guild = ctx.guild
user = await self.fetch_user(ctx, user)
if guild.get_member(user.id) and (guild.get_member(user.id).top_role.position >= guild.me.top_role.position): >This is where heirarchy comes into play
raise GenericCustomException(
"Sorry, but I can not ban that user. Maybe try checking my role hierarchy?"
)
else:
whitelisted_roles = [123456, 456789, 789012] # List of Mod roles
for role in user.roles:
if role.id in whitelisted_roles:
return await ctx.send("You can't ban this user! He is a moderator!")
else:
# ban the user
pass

How can i create roles and put them on top?discord.py

my bot has a command called mute and basically, it creates a role and gives it to the person but the problem is when it does that ppl with higher roles still are able to talk. how can I put the mute role on top of every role in the server? and I mean in every server, not just one
So you can't put the mute role above the bot role, but the following should help:
#commands.command()
async def mute(self, ctx, member: discord.Member):
guild = ctx.guild
role = await guild.create_role(name='muted', hoist=True)
all_roles = await guild.fetch_roles()
num_roles = len(all_roles)
print(f'The server has {num_roles} roles.')
await role.edit(reason=None, position=num_roles - 2)
print('Created new role!')
await member.add_roles(role)
await ctx.send(f'{member} has been muted.)
So what we did is check how many roles the server has, create a new role and put it to the top/under the bot role.
If you're changing a role to a position lower than the top, I would suggest using the role.edit method, passing a position value.
However, as for your question, which is putting a role at the top after creating this, you should use the discord.Client.move_role()
As for actually creating the role:
If you're on the rewrite, use this
guild = ctx.guild
await guild.create_role(name="role name")
and change "role name" with the name of the role you want to create. If you want to make the role depending on what the user says you can do something likes this:
#client.command()
async def rolecreate(ctx, arg):
guild = ctx.guild
await guild.create_role(name=arg)
Here, you'd have to do (lets say your prefix is !): "!rolecreate Moderator" and it would only create a role.
For the async branch:
author = ctx.message.author
await client.create_role(author.server, name="role name")
Just in case you want the bot to have a command that adds the role here you go:
For the rewrite branch
role = discord.utils.get(ctx.guild.roles, name="role to add name")
user = ctx.message.author
await user.add_roles(role)
If you want to add a role mentioned in the command, you do for example:
#client.command()
async def addrole(ctx, arg):
role = discord.utils.get(ctx.guild.roles, name=arg)
user = ctx.message.author
await user.add_roles(role)
For the async branch:
user = ctx.message.author
role = discord.utils.get(user.server.roles, name="role to add name")
await client.add_roles(user, role)
Hope this helped!

Find role id by name discord rewrite

Right now I'm working on a command for my discord bot where I create a role named after a user, and then automatically assign it to that user. The only problem I'm running into is trying to assign the role without knowing its id yet to the person mentioned.
My command so far:
#client.command(aliases = ["cmr", "CMR"])
#commands.has_permissions(manage_roles=True)
async def creatememberrole(ctx, *, member:discord.Member):
author = ctx.message.author
guild = ctx.guild
print(author.display_name)
await guild.create_role(name=str(member.display_name))
await member.add_roles()
#need help here ^
It can be done by utils.get easily, no need of for loop
role = discord.utils.get(ctx.guild.roles, name=member.display_name)
await member.add_roles(role)
In your case there is no need of any for loop/utils.get, just assign the create_role() method to a variable and use that variable
#client.command(aliases = ["cmr", "CMR"])
#commands.has_permissions(manage_roles=True)
async def creatememberrole(ctx, *, member:discord.Member):
author = ctx.message.author
guild = ctx.guild
print(author.display_name)
role = await guild.create_role(name=str(member.display_name))
await member.add_roles(role)
You could go trough the list of all the roles, and find the role you created and assign this role. Here's an example:
for role in message.channel.guild.roles:
if role.name == str(member.display_name):
await member.add_roles(role)

Missing permission when trying to remove a role with string variable as the argument in name parameter

I have a function which removes a role from an user for a certain time. It works fine with predefined role names like:
role_to_remove = discord.utils.get(ctx.guild.roles, name="placeholder")
But it doesn't work when I'm setting roles using commands, which save the user input in string variable.
Here is the function which removes roles:
role1_name = ''
role2_name = ''
roleDefault_name = ''
#client.command()
#commands.has_role('VIP')
async def deleterole(ctx, member: discord.Member, *, reason=None):
role_to_remove = roleDefault_name
for role in member.roles:
if role == role2_name:
role_to_remove = discord.utils.get(ctx.guild.roles, name=role2_name)
elif role == role1_name:
role_to_remove = discord.utils.get(ctx.guild.roles, name=role1_name)
else:
await ctx.send(f"None of the roles specified in config are assigned to {member}")
role_to_remove = discord.utils.get(ctx.guild.roles, name=roleDefault_name)
await member.remove_roles(role_to_remove)
await asyncio.sleep(60.0)
await member.add_roles(role_to_remove)
These are functions which are used to set role names by user:
#client.command()
#commands.has_permissions(administrator=True)
async def set_role1_name(ctx, role1):
global role1_name
role1_name = role1
#client.command()
#commands.has_permissions(administrator=True)
async def set_role2_name(ctx, role2):
global role2_name
role2_name = role2
#client.command()
#commands.has_permissions(administrator=True)
async def set_role_default(ctx, roledefault):
global roleDefault_name
roleDefault_name = roledefault
When I use the deleterole command, I get the following error (despite the fact that the bot has administrator permissions):
discord.errors.Forbidden: 403 Forbidden (error code: 50013): Missing Permissions
Are you sure you are actually getting the correct role to remove and not None?
discord.utils.get returns None when it does not find a role with the specified name and trying to remove a role that does not exist might trigger a 403 Forbidden.

Categories

Resources