diff --git a/cogs/moderation.py b/cogs/moderation.py index 8063e941..2d89275d 100644 --- a/cogs/moderation.py +++ b/cogs/moderation.py @@ -19,7 +19,7 @@ from datetime import timedelta from typing import Optional import discord -from discord import Member, Embed, DMChannel, NotFound +from discord import Member, Embed, DMChannel, NotFound, User from discord.ext.commands import command, guild_only, has_guild_permissions, bot_has_guild_permissions, Greedy, \ cooldown, BucketType, Cog @@ -208,21 +208,20 @@ async def unban_members(self, ctx, targets, reason): # Get the list of banned users from the server bans = await ctx.guild.bans() - ban_ids = list(map(lambda m: m.user.id, bans)) + ban_users = list(map(lambda m: m.user, bans)) for target in targets: - if target not in ban_ids: + if target not in ban_users: await self.bot.generate_embed(ctx, desc=f"{ctx.bot.cross} **Member Is Not In Ban's List!** {ctx.bot.cross}") else: # Get the member and unban them - user = await self.bot.fetch_user(target) - await ctx.guild.unban(user, reason=reason) + await ctx.guild.unban(target, reason=reason) # Send confirmation to the channel that the user is in - await self.bot.generate_embed(ctx, desc=f"{ctx.bot.tick} **{user}** Was Unbanned! {ctx.bot.tick}") + await self.bot.generate_embed(ctx, desc=f"{ctx.bot.tick} **{target}** Was Unbanned! {ctx.bot.tick}") - await send_to_modlogs(self, ctx, user, reason, action="Unbanned") + await send_to_modlogs(self, ctx, target, reason, action="Unbanned") async def kick_members(self, ctx, targets, reason): @@ -364,12 +363,14 @@ class Moderation(Cog): # Power ban users from guilds without them being in there for user in users: if user in ban_ids: - await self.bot.generate_embed(ctx, desc="❌ **Member Is Already Banned!** ❌") + await self.bot.generate_embed(ctx, + desc=f"{self.bot.cross} **Member Is Already Banned!** {self.bot.cross}") else: await ctx.guild.ban(discord.Object(id=user)) target = await self.bot.fetch_user(user) # Send confirmation to the channel that the user is in - await self.bot.generate_embed(ctx, desc=f"✅ **{target}** Was Power Banned! ✅") + await self.bot.generate_embed(ctx, + desc=f"{self.bot.tick} **{target}** Was Power Banned! {self.bot.tick}") await send_to_modlogs(self, ctx, target, reason, action="Power Banned") @@ -378,7 +379,7 @@ class Moderation(Cog): @has_guild_permissions(ban_members=True) @bot_has_guild_permissions(ban_members=True) @cooldown(1, 1, BucketType.user) - async def unban(self, ctx, members: Greedy[int], *, reason: Optional[str] = "No Reason Given"): + async def unban(self, ctx, members: Greedy[User], *, reason: Optional[str] = "No Reason Given"): """ Unban Member(s) from Server Multiple Members can be Unbanned At Once @@ -680,19 +681,32 @@ class Moderation(Cog): f"\n**Message ID -->** {after.id}" \ f"\n**Edited Message -->** [Jump To Message]({after.jump_url})" - # When the message context exceeds 500 characters, only display the first 500 characters in the logs - before_value = f"{before.content[:1000]} ..." if len(before.content) >= 1000 else before.content - after_value = f"{after.content[:1000]} ..." if len(after.content) >= 1000 else after.content + # Allowing messages of all sizes to be logged + def message_fields(status): + if status == "Before": + if len(before.content) <= 1024: + fields = [(f"Before", before.content, False)] + else: + fields = [(f"Before Message Content #1", before.content[:1000], False), + (f"Before Message Content #2", before.content[1000:], False)] + else: + if len(after.content) <= 1024: + fields = [(f"After", after.content, False)] + else: + fields = [(f"After Message Content #1", after.content[:1000], False), + (f"After Message Content #2", after.content[1000:], False)] + + # Add fields to the embed + for name, value, inline in fields: + embed.add_field(name=name, value=value, inline=inline) embed = Embed(title="Message Edited", description=desc, colour=self.bot.admin_colour, timestamp=datetime.datetime.utcnow()) embed.set_author(name=after.author, icon_url=after.author.avatar_url) - embed.add_field(name="Before", - value=before_value or "No Content", inline=False) - embed.add_field(name="After", - value=after_value or "No Content", inline=False) + message_fields("Before") + message_fields("After") embed.set_footer(text="Message Edited") await modlogs_channel.send(embed=embed) @@ -737,18 +751,23 @@ class Moderation(Cog): if channel and not message.author.bot: modlogs_channel = self.bot.get_channel(channel) + # Allowing messages of all sizes to be logged + if len(message.content) <= 1024: + fields = [("Message Content", message.content or "View Attachment", False)] + else: + fields = [("Message Content #1", message.content[:1000], False), + ("Message Content #2", message.content[1000:], False)] + if not message.attachments: desc = f"**Channel --> {message.channel.mention}**" \ f"\n**Author ID -->** {message.author.id}" \ f"\n**Message ID -->** {message.id}" - fields = [("Message Content", message.content or "No Content", False)] else: attach_string = "".join(f"[Here]({attach.proxy_url})" for attach in message.attachments) desc = f"**Channel --> {message.channel.mention}**" \ f"\n**Author ID -->** {message.author.id}" \ f"\n**Message ID -->** {message.id}" - fields = [("Message Content", message.content or "View Attachment", False), - ("Attachment Link(s)", attach_string, False)] + fields += [("Attachment Link(s)", attach_string, False)] embed = Embed(title="Message Deleted", description=desc, @@ -992,6 +1011,72 @@ class Moderation(Cog): await modlogs_channel.send(embed=embed) + @Cog.listener() + async def on_guild_emojis_update(self, guild, before, after): + """Logging any emoji updates""" + + if modlogs := self.bot.get_modlog_for_guild(guild.id): + modlogs_channel = self.bot.get_channel(modlogs) + + # Retrieve the emoji that were removed/added to the guild + new_emojis = [emojis for emojis in after if emojis not in before] + old_emojis = [emojis for emojis in before if emojis not in after] + + # Assuming that only one emoji is returned all the time + new_emojis_string = str(new_emojis[0]) + old_emojis_string = str(old_emojis[0]) + + if len(new_emojis) == 1: + field = ("") + + # As long as roles were added to the Member, log the role(s) that were given + if len(new_emojis) >= 1: + new_roles_string = " **|** ".join(str(r) for r in new_emojis) + + # Change the description of the embed depending on how many roles were added + if len(new_emojis) == 1: + field = ("Role Added", new_roles_string, False) + footer = "Role Added" + else: + field = ("Roles Added", new_roles_string, False) + footer = "Roles Added" + + embed = Embed(title=footer, + description=f"**Member --> {after.mention} |** {after}" + f"\n**ID -->** {after.id}", + colour=self.bot.admin_colour, + timestamp=datetime.datetime.utcnow()) + embed.set_author(name=after, icon_url=after.avatar_url) + embed.add_field(name=field[0], value=field[1], inline=field[2]) + embed.add_field(name="All Roles", value=role or "No Roles", inline=False) + embed.set_footer(text=footer) + + await modlogs_channel.send(embed=embed) + + # As long as roles were removed from the member, log the role(s) that were removed + if len(old_roles) >= 1: + old_roles_string = " **|** ".join(r.mention for r in old_roles) + + # Change the description of the embed depending on how many roles were removed + if len(old_roles) == 1: + field = ("Role Removed", old_roles_string, False) + footer = "Role Removed" + else: + field = ("Roles Removed", old_roles_string, False) + footer = "Roles Removed" + + embed = Embed(title=footer, + description=f"**Member --> {after.mention} |** {after}" + f"\n**ID -->** {after.id}", + colour=self.bot.admin_colour, + timestamp=datetime.datetime.utcnow()) + embed.set_author(name=after, icon_url=after.avatar_url) + embed.add_field(name=field[0], value=field[1], inline=field[2]) + embed.add_field(name="All Roles", value=role or "No Roles", inline=False) + embed.set_footer(text=footer) + + await modlogs_channel.send(embed=embed) + def setup(bot): bot.add_cog(Moderation(bot))