discord.py Chunk kick command - discord

#commands.command()
async def chunkkick(self, ctx, members: commands.Greedy[discord.Member]):
embed = discord.Embed(description="<:ocheckmark:839069223749812264> "+f"Successfully chunk kicked ".join([member for member in members]), color=discord.Color.orange())
for member in members:
await member.kick(reason=f"{ctx.author} | User was in a chunk kick")
await ctx.reply(embed=embed, mention_author=False)
I am making a chunk kick command that kicks multiple users at once. It stopped working when I added .join. I am also not receiving errors.

Try using single quotes instead of double quotes and you need two of them. Like so:
#commands.command()
async def chunkkick(self, ctx, members: commands.Greedy[discord.Member]):
embed = discord.Embed(description="<:ocheckmark:839069223749812264> "+f"Successfully chunk kicked {''.join([member for member in members])}, color=discord.Color.orange())
for member in members:
await member.kick(reason=f"{ctx.author} | User was in a chunk kick")
await ctx.reply(embed=embed, mention_author=False)
Since python thinks you ended the string with the double quote
Its like doing
"Hello"World"

Related

TypeError: context menu callback 'slash' requires 2 parameters, first one being the interaction and other one explicitly annotated with discord.User

I want with this application code it to send a message to channel it is used and delete the channel
#tree.context_menu(guild=discord.Object(id=941748573937209344), name='tester')
async def slash(interaction: discord.Interaction, ctx, user: discord.User):
title = "ID deleted."
embed = discord.Embed(title=title, color=0xf1c40f)
msg = await ctx.send(embed=embed)
await asyncio.sleep(2)
channel = ctx.channel
await channel.delete()
but when I run it, I get the following error:
TypeError: context menu callback 'slash' requires 2 parameters, the first one being the interaction and the other one explicitly annotated with either discord.Message, discord.User, discord.Member, or a typing.Union of discord.Member and discord.User
it works when I delete ctx, but I can't send a message to the channel it's using and then make it delete the channel
can I use something else instead of ctx or where else can I write ctx
You should use the interaction object to get your channel object instead of ctx.
#tree.context_menu(guild=discord.Object(id=941748573937209344), name='tester')
async def slash(interaction: discord.Interaction, user: discord.User):
title = "ID deleted."
embed = discord.Embed(title=title, color=0xf1c40f)
msg = await interaction.response.send_message(embed=embed)
await asyncio.sleep(2)
channel = interaction.channel
await channel.delete()

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 can I allow people to only kick members lower than their role with discord.py?

I'm trying to make a kick command using Python and the discord.py library, though I cannot figure out how to allow people to only be able to kick members lower than their role, so Moderators wouldn't be able to kick Admins.
enter image description here
You can compare the Member object with a function called top_role
An example code would be:
#client.command()
#commands.has_permissions(kick_members=True)
async def kick(ctx, member: discord.Member, *, reason=None):
if member.top_role >= ctx.author.top_role: # Check if the role is below the authors role
await ctx.send("You can only kick users with a lower role!")
return
else:
await member.kick(reason=reason)
await ctx.send(f"{member.id} got kicked with the reason: {reason}.")
Add all the moderators to a list and regular users to another list.
Like this;
string[] moderator = all moderators.
string[] regularUsers = all regular users.

Discord.py banning user not working if DM's disabled

I've got this code for my discord bot, which can ban people and DM them the reason for the ban first.
cooldown = []
#bot.command(pass_context = True)
#commands.has_role('Senior Moderator')
async def ban(ctx, member: discord.Member = None, *, reason = None):
author = str(ctx.author)
if author in cooldown:
await ctx.send('Calm down! You\'ve already banned someone less than two hours ago.')
return
try:
if reason == None:
reason = 'breaking the rules.'
await member.send(f'You have been banned from **{ctx.guild.name}** for **{reason}**')
await member.ban(reason = f"Banned by {ctx.message.author} for "+reason)
await ctx.send(f'{member.mention} has been banned.')
cooldown.append(author)
await asyncio.sleep(2 * 60 * 60) #The argument is in seconds. 2hr = 7200s
cooldown.remove(author)
except:
await ctx.send('Error. Please check you are typing the command correctly. `!ban #username (reason)`.')
However, if the user I am trying to ban has DM's disabled, the bot can't send the ban reason message, so therefore doesn't proceed to the next step, which is banning them, and returns the error message, which is Error. Please check you are typing the command correctly. !ban #username (reason)
Please can you rewrite the code to allow it to try to DM someone the reasoning before banning them, but if they have DM's disabled, it shall still ban them anyway. Thank you!
By simply moving the ban to be executed first (as it is a priority), then it will attempt to dm the user.
I also re-adjusted some parts of the code. It will now try to send a dm, if not, it will still ban but a message will be sent to the channel alerting a message was not sent to the banned user.
#bot.command(pass_context = True)
#commands.has_role('Senior Moderator')
async def ban(ctx, member: discord.Member = None, *, reason = None):
author = ctx.author
if author in cooldown:
await ctx.send('Calm down! You\'ve already banned someone less than two hours ago.')
return
if member == None:
await ctx.send('Please mention a member to ban!')
return
if reason == None:
reason = 'breaking the rules.'
await member.ban(reason = f"Banned by {ctx.message.author} for " + reason)
try:
await member.send(f'You have been banned from **{ctx.guild.name}** for **{reason}**')
except:
await ctx.send(f'A reason could not be sent to {ctx.message.author} as they had their dms off.')
await ctx.send(f'{member.mention} has been banned.')
cooldown.append(author)
await asyncio.sleep(2 * 60 * 60)
cooldown.remove(author)
I too noticed the same thing when I first made my bot ban command, I did the following to fix my ban command. First I tried a scenario where the bot could dm the user, if it can, then It will dm the user and then ban the user (Note: Do not ban the user before DMing the user as the bot can only DM the user when the user and the bot share a common server). However, I then made an Exception that if the bot couldn't dm the user, it will send a message in the channel the command was executed "Couldn't dm the user" then ban the user
try:
await member.send(embed=embo)
await ctx.guild.ban(member, reason=reason)
except Exception:
await ctx.send("Couldn't send dm to the user")
await ctx.guild.ban(member, reason=reason)
EDIT:
you can also opt for the following:
try:
await member.send(embed=embo)
await ctx.guild.ban(member, reason=reason)
except discord.HTTPException:
await ctx.send("Couldn't send dm to the user")
await ctx.guild.ban(member, reason=reason)
before I specified this, I encountered the following error.
I fixed it, afterward, adding the exception case.

discord.py rewrite tempmute command

I have a mute command in my bot but i want to add a timer on it, not really sure how to tho, this is my current code. It adds the code correctly and it all sends correctly but the duration i'm not really sure about. Any help would be appreciated!
Edit: I got the duration working, but how would i convert it into minutes/hours etc.?
#client.command()
#commands.has_permissions(manage_messages=True)
async def mute(ctx, member: discord.Member, mute_time : int, *, reason=None):
role = discord.utils.get(ctx.guild.roles, name="[Muted]")
await member.add_roles(role)
await ctx.send(f'**Muted** {member.mention}\n**Reason: **{reason}\n**Duration:** {mute_time}')
embed = discord.Embed(color=discord.Color.green())
embed.add_field(name=f"You've been **Muted** in {ctx.guild.name}.", value=f"**Action By: **{ctx.author.mention}\n**Reason: **{reason}\n**Duration:** {mute_time}")
await member.send(embed=embed)
await asyncio.sleep(mute_time)
await member.remove_roles(role)
await ctx.send(f"**Unmuted {member.mention}**")
I use your code in minimal example and it's work well. What problems do you have? Example:
#client.command()
#commands.has_permissions(manage_messages=True)
async def mute(ctx, mute_time : int):
await ctx.send("Muted")
await asyncio.sleep(mute_time)
await ctx.send("Unmuted")
Exactly one minute passed. Result:

Resources