#commands.has_permissions(administrator=True) not working properly? - discord

I am trying to make a simple moderator bot.
the code looks something like this.
import discord
from discord.ext import commands
from random import choice
import os
client = commands.Bot(command_prefix=commands.when_mentioned_or("%"), description='A simple Moderator bot')
def colour():
l = [ 1752220, 3066993, 3447003, 10181046, 15844367, 15105570, 15158332, 3426654, 16580705 ]
return choice(l)
#client.event
async def on_ready():
change_status.start()
print("The Bot is online!")
#client.command()
#commands.has_permissions(administrator=True)
async def kick(ctx, user : discord.Member = None, *,reason = "No reason provided"):
await user.kick(reason = reason)
await ctx.send("Kicked the user.")
#client.command()
#commands.has_permissions(administrator=True)
async def ban(ctx, user : discord.Member = None, *,reason = "No reason provided"):
await user.ban(reason = reason)
await ctx.send("Banned the user")
#client.command()
#commands.has_permissions(administrator=True)
async def warn(ctx, user : discord.Member = None, *,reason = "No reason provided"):
await user.send(f"You have been **Warned** by **{ctx.author.name}** in the **{ctx.guild.name}** for the reason: **{reason}** ")
await ctx.send("Warned the user")
client.run(os.environ['token'])
In this only warn command is working successfully rest all the commands throws an error which looks like this.
Ignoring exception in command kick:
Traceback (most recent call last):
File "main.py", line 140, in kick
await user.kick(reason = reason)
File "/app/.heroku/python/lib/python3.6/site-packages/discord/member.py", line 524, in kick
await self.guild.kick(self, reason=reason)
File "/app/.heroku/python/lib/python3.6/site-packages/discord/guild.py", line 1886, in kick
await self._state.http.kick(user.id, self.id, reason=reason)
File "/app/.heroku/python/lib/python3.6/site-packages/discord/http.py", line 241, in request
raise Forbidden(r, data)
discord.errors.Forbidden: 403 Forbidden (error code: 50013): Missing Permissions
It is throwing a missing permission but I am the owner of the server and even added the bot as an admistrator.
Even tried by making an administrator role and giving all the permissions to it but still no luck.
This error is coming again and again.
Even if anyone know how to check between multiple roles like if anyone has administrator or kick member permission then do this, please let me know how to do that.
Thanks in advance for the help.
If any more information needed, do let me know.

The error you are getting on the last line from your console; discord.errors.Forbidden: 403 Forbidden (error code: 50013): Missing Permissions Is because the bot is missing permissions to perform these actions against the given permissions the bot currently has.
This could occur from the following;
Sufficient Bot permissions haven't been enabled from the invite link
The member has a higher or equal role than the bot
The #everyone role has no permissions
Moreover, these issues aren't at fault with the code you have written and is something that can be fixed in your server with the role hierarchy or bot invite link permissions.
I would also recommend comparing roles to make sure users can't attempt moderation on a higher level member in the first place, this could also help to mitigate the problem
With this, you can use >= and the top_role attribute which would compare the roles that the user compared to the member you are attempting to take moderation on, if your permissions are lower than the member you are attempting to moderate, it will prevent the rest of the code running. Here is a simple way of doing this,
if member.top_role >= ctx.author.top_role:
await ctx.send(f"You can only moderate members below your role")
return

Related

Is there a way to have multiple arguments in a command with discord py

I’m creating a discord bot using discord py and would like to have a kick command that dms the user a reason upon being kicked.
-kick #user reason
When I kick the user with a reason attached it doesn’t kick the user and I get an error in console saying can not find the user
Here is the code
#client.command(aliases=['Kick'])
#commands.has_permissions(administrator=True)
async def kick(ctx,member : discord.Member,*,reason= 'no reason'):
await ctx.send(f'{member.name} was kicked from the Server!\nand a Dm was sendet by me as a Information for him')
await asyncio.sleep(5)
await ctx.channel.purge(limit=2)
await member.send(f'**You was kicked from {ctx.guild.name}\nthe Stuff Team dont tell me the reason?**')
await member.kick(reason=reason)
print(f"{ctx.author} ----> just used {prefix}kick")
And yes I have tried Google, the discord py API guide with no luck
Can anyone help? Thanks
You can give a nice error message. It raises MemberNotFound.
Then you can make a local error handler.
#kick.error
async def kick_command_error(ctx, err):
if isinstance(err, commands.MemberNotFound):
await ctx.send('Hey! The member you gave is invalid or was not found. Please try again by `#`mentioning them or using the ID.')

issues with dicord bot

#was making a sort of capcha system works on my main account with admin but after going on my alt #account and test getting this error even after giving ult admin
#bot.command(pass_context=True, name="cat")
#commands.has_permissions(manage_messages=True)
async def cat(ctx):
member = ctx.message.author
role = discord.utils.get(member.guild.roles, name="user")
await member.add_roles(role)
await ctx.channel.purge(limit=1)
Error:
#raise MissingPermissions(missing)
#discord.ext.commands.errors.MissingPermissions: You are missing Manage Messages permission(s) to #run this command.
I dont see why you would need help, the error is just telling you that the account does not have a role with that perm.

Asking for Kick Member permission despite having given admin rights to Bot

So I am setting up a bot, and I am testing it out. A little function I have there is to kick, ban and unban users, set up in a cog, which goes as follows:
import discord
from discord.ext import commands
class Moderator(commands.Cog):
def __init__(self, bot):
self.bot = bot
#KICK command
#commands.command()
#commands.has_permissions(kick_members=True)
async def kick(self, ctx, member : discord.Member, *, reason=None):
('About to kick')
await member.kick(reason = reason)
#commands.command()
#commands.has_permissions(kick_members=False)
async def kick(self, ctx, member : discord.Member, *, reason=None):
await ctx.send(f'You do not have permission to kick any member, {ctx.message.author.mention}!')
#BAN command
#commands.command()
#commands.has_permissions(ban_members=True)
async def ban(self, ctx, member : discord.Member, *, reason=None):
await member.ban(reason = reason)
await ctx.send(f'Banned {member.mention}')
#commands.command()
#commands.has_permissions(kick_members=False)
async def ban(self, ctx, member : discord.Member, *, reason=None):
await ctx.send(f'You do not have permission to ban any member, {ctx.message.author.mention}!')
#UNBAN command
#commands.command()
#commands.has_permissions(ban_members=True)
async def unban(self, ctx, *, member):
banned_users = await ctx.guild.bans()
member_name, member_discriminator = member.split('#')
for ban_entry in banned_users:
user = ban_entry.user
if (user.name, user.discriminator) == (member_name, member_discriminator):
await ctx.guild.unban(user)
await ctx.send(f'Unbanned {user.mention}')
return
#commands.command()
#commands.has_permissions(kick_members=False)
async def unban(self, ctx, member : discord.Member, *, reason=None):
await ctx.send(f'You do not have permission to unban any member, {ctx.message.author.mention}!')
#CLEAR MESSAGES
#commands.command()
#commands.has_permissions(manage_messages=True)
async def clear(self, ctx, amount=2):
await ctx.channel.purge(limit=amount)
#commands.command()
#commands.has_permissions(manage_messages=False)
async def clear(self, ctx, amount=2):
await ctx.send(f'You do not have permission to delete messages in this way, {ctx.message.author.mention}!')
def setup(bot):
bot.add_cog(Moderator(bot))
Now I have formatted the above code with some spaces so that it fits in one codeblock, so you might face indentation errors if you copy paste it elsewhere.
Moving on, the bot itself has Administrator rights and separate Kicking and Banning rights too. It is also placed at the top of the role hierarchy, which is seen as:
The name of my bot is JunkBot.
Now, whenever I, being the server owner, try using the command .kick #user, it pops up the following error:
The textual form of the error is:
Ignoring exception in command kick:
Traceback (most recent call last):
File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 855, in invoke
await self.prepare(ctx)
File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 777, in prepare
if not await self.can_run(ctx):
File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 1087, in can_run
return await discord.utils.async_all(predicate(ctx) for predicate in predicates)
File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\utils.py", line 348, in async_all
for elem in gen:
File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 1087, in <genexpr>
return await discord.utils.async_all(predicate(ctx) for predicate in predicates)
File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 1790, in predicate
raise MissingPermissions(missing)
discord.ext.commands.errors.MissingPermissions: You are missing Kick Members permission(s) to run this command.
Similar errors are raised for the ban, unban and clear messages commands.
Interesting part is, I, being the owner, get this error, but supposing another user, a friend of mine who does not have the kicking, banning or message managing role, runs their lines of codes perfectly, where she gets the message from the bot that she does not have permission to kick, ban or clear messages. The screenshot is enclosed.
I don't know where I went wrong. Please help me debug it.
Your problem is in rewriting the functions. I'm assuming that you are hoping to make an errorhandler. However, this isn't the way to do so.
Instead of rewriting the functions with different has_permissions arguments, you will need to make a proper version of an error handler.
First, delete all the duplicate functions. These are the functions that require False on the has_permissions arguments.
Next, make a errorhandler function. You can make one for the Cog commands only, for all commands, or a specific command. If its for all commands, you will use the event on_command_error, (I suggest using it in the main file or as a listener). If it's for the Cog, then you will have to use cog_command_error. If it's for a specific command, you should make the Command.error decorator.
I will be showing the Cog specific handler, but switching back and forth shouldn't take too long.
# Indent into Cog level
async def cog_command_error(self, ctx, error):
# Allows us to check for original exceptions raised and sent to CommandInvokeError.
# If nothing is found. We keep the exception passed to on_command_error.
error = getattr(error, 'original', error)
if isinstance(error, commands.BotMissingPermissions): # Check if bot is missing permissions
await ctx.send(f'I am missing these permissions to do this command:\n{self.lts(error.missing_perms)}')
elif isinstance(error, commands.MissingPermissions): # Check if user is missing permissions
await ctx.send(f'You are missing these permissions to do this command:\n{self.lts(error.missing_perms)}')
#staticmethod
def lts(list_: list): # Used to make reading the list of permissions easier.
"""List to string.
For use in `self.on_command_error`"""
return ', '.join([obj.name if isinstance(obj, discord.Role) else str(obj).replace('_', ' ') for obj in list_])
Here is the list of exceptions you can use in the handler: Exceptions
FYI, the lts function I have isn't required for the handler. It's used to make the list of permissions readable in one string. You can always remove it or change it to your needs.
That is not how error handling works. You should check out the error handling section of the docs for how to deal with missing permissions.
EDIT because people reminded me to give some more information
You shouldn't be handling errors through has_permissions. From what I can tell from your code, you are looking to send a message when the invoker doesn't have the permissions required to use the command. This can be achieved with an error handler. THe error handler will catch the MissingPermissions exception and do something based on that. Here is an example:
#commands.Cog.listener()
async def on_command_error(self, ctx, error): #this is the event that catches errors
if isinstance(error, commands.MissingPermissions): #seeing if the error is the missing permissions error
await ctx.send(f"You do not have the permission to do this, {ctx.author.mention}!")
This uses a global error handler, meaning that whenever an error is caught, this will catch it. However if you want an error handler for each command, all you have to change is the decorater and function name. EX:
#kick.error
async def on_kick_error(self, ctx, error):
if isinstance(error, commands.MissingPermissions):
await ctx.send(f"You do not have the permission to kick any member, {ctx.author.mention} ")
This one will only trigger on the kick command error, none of the others.

How make massban in discord.py?

I used this command, but the bot not ban anyone and does not write an error to the console.
#bot.command()
async def massban(ctx):
for user in ctx.guild.members:
try:
await user.ban()
except:
pass
As Fixator also mentioned, you won't be able to see the error as far as you're excepting every error and passing it.
#bot.command()
async def massban(ctx):
for user in ctx.guild.members:
try:
await user.ban()
except Exception as error:
print(error)
pass
That's how you can catch the error without interrupting the for-loop.
Please also doublecheck the permissions of your bot and the member listing.
If you sure that bot has a ban perms on server.
Check if bot has enough cache for that operation. For example, send len(guild.members) into channel before iterating over members. If it says 1-2, you, most likely, dont have enough intents.
Bot can't ban users that has roles above bot's top role:

Trying to set up permissions for a discord bot but can't seem to be able to

So I'm making a discord bot for a server that I use and wanted to add a censor feature so that if a user said something in the "bannedWords" list while not in a specific channel (working) it would edit the message to have "[redacted]" in its place. I believe the code itself is working but I get this error message every time I test it. I've tried adding permissions via the Discord Developer Portal (selecting "OAuth2," choosing the "bot" scope, and the manage roles, view channels, send messages, manage messages, read message history, and mention everyone permissions), copied the link and added it to my testing server but it still didn't seem to work along with having the proper permissions via role.
Full Error:
Traceback (most recent call last):
File "C:\Users\Me\AppData\Local\Programs\Python\Python36\lib\site-packages\discord\client.py", line 312, in _run_event
await coro(*args, **kwargs)
File "C:\Users\Me\Desktop\Productive\Programming Projects\Python 3\Other\MyBot\bot.py", line 32, in on_message
await message.edit(content = editedMessage)
File "C:\Users\Me\AppData\Local\Programs\Python\Python36\lib\site-packages\discord\message.py", line 843, in edit
data = await self._state.http.edit_message(self.channel.id, self.id, **fields)
File "C:\Users\Me\AppData\Local\Programs\Python\Python36\lib\site-packages\discord\http.py", line 241, in request
raise Forbidden(r, data)
discord.errors.Forbidden: 403 Forbidden (error code: 50005): Cannot edit a message authored by another user
Code
import discord
bot=discord.Client()
#bot.event
async def on_ready():
print('Logged in')
print("Username: %s" % (bot.user.name))
print("Userid: %s" % (bot.user.id))
#bot.event
async def on_message(message):
if message.author.id == bot.user.id:
return
bannedWords=['chink','dyke','fag','ook','molest','nig','rape','retard','spic','zipperhead','tranny']
print(str(message))
print(str(message.content))
if "name='no-rules-lol'" not in str(message): #probably a better way to do this but it works
for word in bannedWords:
if word in message.content.lower():
await message.channel.send('{0.author.mention}, you have used a word that is black-listed please read <#754763230169006210> to get a full list of black-listed words'.format(message))
#await message.edit(content = message + 'this has been edited')
editedMessage=str(message.content.replace(word,'[redacted]'))
await message.edit(content = editedMessage)
bot.run(Token)
You cannot edit a message that is not sent by the bot.
Instead, just try deleting the message.
await message.delete()
It is as easy as that.
If you are adding more commands into your bot, you can just add this to your on_message at last:
await bot.process_commands(message)
Thank you.

Resources