import discord from discord.ext import commands import asyncio import re class Moderation(commands.Cog): def __init__(self, bot): self.bot = bot @commands.command() @commands.has_permissions(ban_members=True) async def ban(self, ctx, member: discord.Member, *, reason: str): await member.ban(reason=reason) await ctx.send(f"{member.mention} has been banned for {reason}.") # Notify user via DM try: await member.send(f"You have been banned from **{ctx.guild.name}** for **{reason}**.") except: pass @commands.command() @commands.has_permissions(ban_members=True) async def unban(self, ctx, user_id: str): """ Unban a member by ID :param ctx: Context of the command :param user_id: ID of the member to unban """ try: user_id = int(user_id) except ValueError: await ctx.send('Invalid user ID') return try: user = await self.bot.fetch_user(user_id) await ctx.guild.unban(user) await ctx.send(f'Unbanned {user.mention}') except discord.Forbidden: await ctx.send('I do not have permission to unban members') except discord.HTTPException as e: await ctx.send(f'Failed to unban member: {e.text}') except discord.NotFound: await ctx.send('User not found') except Exception as e: await ctx.send(f'An unexpected error occurred: {e}') @commands.command() @commands.has_permissions(kick_members=True) async def kick(self, ctx, member: discord.Member, *, reason: str): await member.kick(reason=reason) await ctx.send(f"{member.mention} has been kicked for {reason}.") # Notify user via DM try: await member.send(f"You have been kicked from **{ctx.guild.name}** for **{reason}**.") except: pass @commands.command() @commands.has_permissions(manage_messages=True) async def clear(self, ctx, member: discord.Member, amount: int): def is_user(m): return m.author == member deleted = await ctx.channel.purge(limit=amount, check=is_user) await ctx.send(f"Deleted {len(deleted)} messages from {member.mention}.") @commands.command() @commands.has_permissions(manage_messages=True) async def purge(self, ctx, amount: int): deleted = await ctx.channel.purge(limit=amount) await ctx.send(f"Deleted {len(deleted)} messages.") @commands.command() @commands.has_permissions(manage_messages=True) async def botclean(self, ctx, amount: int = 1): def is_bot(m): return m.author == self.bot.user deleted = await ctx.channel.purge(limit=amount + 1, check=is_bot) await ctx.message.add_reaction('') @commands.command() @commands.has_permissions(manage_roles=True) async def mute(self, ctx, member: discord.Member, duration: str, *, reason: str): mute_role = discord.utils.get(ctx.guild.roles, name="Muted") if not mute_role: mute_role = await ctx.guild.create_role(name="Muted") for channel in ctx.guild.channels: await channel.set_permissions(mute_role, send_messages=False) # Parse duration duration_seconds = self.parse_duration(duration) await member.add_roles(mute_role, reason=reason) await ctx.send(f"{member.mention} has been muted for {duration}.") await asyncio.sleep(duration_seconds) await member.remove_roles(mute_role) @commands.command() @commands.has_permissions(manage_roles=True) async def unmute(self, ctx, member: discord.Member, *, reason: str): mute_role = discord.utils.get(ctx.guild.roles, name="Muted") if mute_role in member.roles: await member.remove_roles(mute_role, reason=reason) await ctx.send(f"{member.mention} has been unmuted.") else: await ctx.send(f"{member.mention} is not muted.") @commands.command(aliases=['rc']) @commands.has_permissions(administrator=True) async def roleicon(self, ctx, url: str, role: discord.Role): try: async with self.bot.session.get(url) as resp: if resp.status != 200: return await ctx.send("Invalid URL.") image_data = await resp.read() await role.edit(icon=image_data) await ctx.send(f"Icon updated for role {role.name}.") except Exception as e: await ctx.send(f"An error occurred: {e}") @commands.command() async def warn(self, ctx, member: discord.Member, *, reason: str): if ctx.author.guild_permissions.kick_members: await member.send(f"You have been warned in {ctx.guild.name} for: {reason}") await ctx.send(f"{member.mention} has been warned for: {reason}") else: await ctx.send("You don't have permission to use this command.") @commands.command() # doesnt actually log user warns async def warns(self, ctx): warns = [] if warns: await ctx.send("Your most recent warns are:") for warn in warns: await ctx.send(warn) else: await ctx.send("You don't have any recent warns.") @commands.command() async def history(self, ctx): await ctx.send("Your punishment history is empty.") @commands.command() async def image(self, ctx, member: discord.Member, *, reason: str): if ctx.author.guild_permissions.manage_roles: role = discord.utils.get(ctx.guild.roles, name="📸") if role in member.roles: await member.remove_roles(role, reason=reason) await ctx.send(f"Image permissions removed for {member.mention} for reason: {reason}") else: await member.add_roles(role, reason=reason) await ctx.send(f"Image permissions granted for {member.mention} for reason: {reason}") else: await ctx.send("You don't have permission to use this command.") def parse_duration(self, duration: str) -> int: pattern = r"(\d+)([a-z]+)" matches = re.findall(pattern, duration.lower()) if not matches: raise commands.BadArgument("Invalid duration format.") duration_seconds = 0 for num, unit in matches: num = int(num) unit_multipliers = { "s": 1, "sec": 1, "secs": 1, "second": 1, "seconds": 1, "m": 60, "min": 60, "mins": 60, "minute": 60, "minutes": 60, "h": 3600, "hr": 3600, "hrs": 3600, "hour": 3600, "hours": 3600, "d": 86400, "day": 86400, "days": 86400 } if unit not in unit_multipliers: raise commands.BadArgument(f"Invalid duration unit: {unit}") duration_seconds += num * unit_multipliers[unit] return duration_seconds async def setup(bot): await bot.add_cog(Moderation(bot))