diff options
Diffstat (limited to '')
| -rw-r--r-- | bot/exts/moderation/modlog.py (renamed from bot/cogs/moderation/modlog.py) | 150 | 
1 files changed, 61 insertions, 89 deletions
| diff --git a/bot/cogs/moderation/modlog.py b/bot/exts/moderation/modlog.py index 41472c64c..b01de0ee3 100644 --- a/bot/cogs/moderation/modlog.py +++ b/bot/exts/moderation/modlog.py @@ -12,10 +12,10 @@ from deepdiff import DeepDiff  from discord import Colour  from discord.abc import GuildChannel  from discord.ext.commands import Cog, Context -from discord.utils import escape_markdown  from bot.bot import Bot  from bot.constants import Categories, Channels, Colours, Emojis, Event, Guild as GuildConstant, Icons, URLs +from bot.utils.messages import format_user  from bot.utils.time import humanize_delta  log = logging.getLogger(__name__) @@ -24,7 +24,6 @@ GUILD_CHANNEL = t.Union[discord.CategoryChannel, discord.TextChannel, discord.Vo  CHANNEL_CHANGES_UNSUPPORTED = ("permissions",)  CHANNEL_CHANGES_SUPPRESSED = ("_overwrites", "position") -MEMBER_CHANGES_SUPPRESSED = ("status", "activities", "_client_status", "nick")  ROLE_CHANGES_UNSUPPORTED = ("colour", "permissions")  VOICE_STATE_ATTRIBUTES = { @@ -64,7 +63,7 @@ class ModLog(Cog, name="ModLog"):                          'id': message.id,                          'author': message.author.id,                          'channel_id': message.channel.id, -                        'content': message.content, +                        'content': message.content.replace("\0", ""),  # Null chars cause 400.                          'embeds': [embed.to_dict() for embed in message.embeds],                          'attachments': attachment,                      } @@ -121,8 +120,17 @@ class ModLog(Cog, name="ModLog"):              else:                  content = "@everyone" +        # Truncate content to 2000 characters and append an ellipsis. +        if content and len(content) > 2000: +            content = content[:2000 - 3] + "..." +          channel = self.bot.get_channel(channel_id) -        log_message = await channel.send(content=content, embed=embed, files=files) +        log_message = await channel.send( +            content=content, +            embed=embed, +            files=files, +            allowed_mentions=discord.AllowedMentions(everyone=True) +        )          if additional_embeds:              if additional_embeds_msg: @@ -388,7 +396,7 @@ class ModLog(Cog, name="ModLog"):          await self.send_log_message(              Icons.user_ban, Colours.soft_red, -            "User banned", f"{member} (`{member.id}`)", +            "User banned", format_user(member),              thumbnail=member.avatar_url_as(static_format="png"),              channel_id=Channels.user_log          ) @@ -399,12 +407,10 @@ class ModLog(Cog, name="ModLog"):          if member.guild.id != GuildConstant.id:              return -        member_str = escape_markdown(str(member)) -        message = f"{member_str} (`{member.id}`)"          now = datetime.utcnow()          difference = abs(relativedelta(now, member.created_at)) -        message += "\n\n**Account age:** " + humanize_delta(difference) +        message = format_user(member) + "\n\n**Account age:** " + humanize_delta(difference)          if difference.days < 1 and difference.months < 1 and difference.years < 1:  # New user account!              message = f"{Emojis.new} {message}" @@ -426,10 +432,9 @@ class ModLog(Cog, name="ModLog"):              self._ignored[Event.member_remove].remove(member.id)              return -        member_str = escape_markdown(str(member))          await self.send_log_message(              Icons.sign_out, Colours.soft_red, -            "User left", f"{member_str} (`{member.id}`)", +            "User left", format_user(member),              thumbnail=member.avatar_url_as(static_format="png"),              channel_id=Channels.user_log          ) @@ -444,14 +449,28 @@ class ModLog(Cog, name="ModLog"):              self._ignored[Event.member_unban].remove(member.id)              return -        member_str = escape_markdown(str(member))          await self.send_log_message(              Icons.user_unban, Colour.blurple(), -            "User unbanned", f"{member_str} (`{member.id}`)", +            "User unbanned", format_user(member),              thumbnail=member.avatar_url_as(static_format="png"),              channel_id=Channels.mod_log          ) +    @staticmethod +    def get_role_diff(before: t.List[discord.Role], after: t.List[discord.Role]) -> t.List[str]: +        """Return a list of strings describing the roles added and removed.""" +        changes = [] +        before_roles = set(before) +        after_roles = set(after) + +        for role in (before_roles - after_roles): +            changes.append(f"**Role removed:** {role.name} (`{role.id}`)") + +        for role in (after_roles - before_roles): +            changes.append(f"**Role added:** {role.name} (`{role.id}`)") + +        return changes +      @Cog.listener()      async def on_member_update(self, before: discord.Member, after: discord.Member) -> None:          """Log member update event to user log.""" @@ -462,74 +481,27 @@ class ModLog(Cog, name="ModLog"):              self._ignored[Event.member_update].remove(before.id)              return -        diff = DeepDiff(before, after) -        changes = [] -        done = [] - -        diff_values = {} - -        diff_values.update(diff.get("values_changed", {})) -        diff_values.update(diff.get("type_changes", {})) -        diff_values.update(diff.get("iterable_item_removed", {})) -        diff_values.update(diff.get("iterable_item_added", {})) - -        diff_user = DeepDiff(before._user, after._user) - -        diff_values.update(diff_user.get("values_changed", {})) -        diff_values.update(diff_user.get("type_changes", {})) -        diff_values.update(diff_user.get("iterable_item_removed", {})) -        diff_values.update(diff_user.get("iterable_item_added", {})) - -        for key, value in diff_values.items(): -            if not key:  # Not sure why, but it happens -                continue - -            key = key[5:]  # Remove "root." prefix +        changes = self.get_role_diff(before.roles, after.roles) -            if "[" in key: -                key = key.split("[", 1)[0] +        # The regex is a simple way to exclude all sequence and mapping types. +        diff = DeepDiff(before, after, exclude_regex_paths=r".*\[.*") -            if "." in key: -                key = key.split(".", 1)[0] +        # A type change seems to always take precedent over a value change. Furthermore, it will +        # include the value change along with the type change anyway. Therefore, it's OK to +        # "overwrite" values_changed; in practice there will never even be anything to overwrite. +        diff_values = {**diff.get("values_changed", {}), **diff.get("type_changes", {})} -            if key in done or key in MEMBER_CHANGES_SUPPRESSED: +        for attr, value in diff_values.items(): +            if not attr:  # Not sure why, but it happens.                  continue -            if key == "_roles": -                new_roles = after.roles -                old_roles = before.roles - -                for role in old_roles: -                    if role not in new_roles: -                        changes.append(f"**Role removed:** {role.name} (`{role.id}`)") - -                for role in new_roles: -                    if role not in old_roles: -                        changes.append(f"**Role added:** {role.name} (`{role.id}`)") - -            else: -                new = value.get("new_value") -                old = value.get("old_value") - -                if new and old: -                    changes.append(f"**{key.title()}:** `{old}` **→** `{new}`") - -            done.append(key) - -        if before.name != after.name: -            changes.append( -                f"**Username:** `{before.name}` **→** `{after.name}`" -            ) +            attr = attr[5:]  # Remove "root." prefix. +            attr = attr.replace("_", " ").replace(".", " ").capitalize() -        if before.discriminator != after.discriminator: -            changes.append( -                f"**Discriminator:** `{before.discriminator}` **→** `{after.discriminator}`" -            ) +            new = value.get("new_value") +            old = value.get("old_value") -        if before.display_name != after.display_name: -            changes.append( -                f"**Display name:** `{before.display_name}` **→** `{after.display_name}`" -            ) +            changes.append(f"**{attr}:** `{old}` **→** `{new}`")          if not changes:              return @@ -539,12 +511,13 @@ class ModLog(Cog, name="ModLog"):          for item in sorted(changes):              message += f"{Emojis.bullet} {item}\n" -        member_str = escape_markdown(str(after)) -        message = f"**{member_str}** (`{after.id}`)\n{message}" +        message = f"{format_user(after)}\n{message}"          await self.send_log_message( -            Icons.user_update, Colour.blurple(), -            "Member updated", message, +            icon_url=Icons.user_update, +            colour=Colour.blurple(), +            title="Member updated", +            text=message,              thumbnail=after.avatar_url_as(static_format="png"),              channel_id=Channels.user_log          ) @@ -571,17 +544,16 @@ class ModLog(Cog, name="ModLog"):          if author.bot:              return -        author_str = escape_markdown(str(author))          if channel.category:              response = ( -                f"**Author:** {author_str} (`{author.id}`)\n" +                f"**Author:** {format_user(author)}\n"                  f"**Channel:** {channel.category}/#{channel.name} (`{channel.id}`)\n"                  f"**Message ID:** `{message.id}`\n"                  "\n"              )          else:              response = ( -                f"**Author:** {author_str} (`{author.id}`)\n" +                f"**Author:** {format_user(author)}\n"                  f"**Channel:** #{channel.name} (`{channel.id}`)\n"                  f"**Message ID:** `{message.id}`\n"                  "\n" @@ -667,9 +639,6 @@ class ModLog(Cog, name="ModLog"):          if msg_before.content == msg_after.content:              return -        author = msg_before.author -        author_str = escape_markdown(str(author)) -          channel = msg_before.channel          channel_name = f"{channel.category}/#{channel.name}" if channel.category else f"#{channel.name}" @@ -701,7 +670,7 @@ class ModLog(Cog, name="ModLog"):                  content_after.append(sub)          response = ( -            f"**Author:** {author_str} (`{author.id}`)\n" +            f"**Author:** {format_user(msg_before.author)}\n"              f"**Channel:** {channel_name} (`{channel.id}`)\n"              f"**Message ID:** `{msg_before.id}`\n"              "\n" @@ -753,12 +722,11 @@ class ModLog(Cog, name="ModLog"):              self._cached_edits.remove(event.message_id)              return -        author = message.author          channel = message.channel          channel_name = f"{channel.category}/#{channel.name}" if channel.category else f"#{channel.name}"          before_response = ( -            f"**Author:** {author} (`{author.id}`)\n" +            f"**Author:** {format_user(message.author)}\n"              f"**Channel:** {channel_name} (`{channel.id}`)\n"              f"**Message ID:** `{message.id}`\n"              "\n" @@ -766,7 +734,7 @@ class ModLog(Cog, name="ModLog"):          )          after_response = ( -            f"**Author:** {author} (`{author.id}`)\n" +            f"**Author:** {format_user(message.author)}\n"              f"**Channel:** {channel_name} (`{channel.id}`)\n"              f"**Message ID:** `{message.id}`\n"              "\n" @@ -844,9 +812,8 @@ class ModLog(Cog, name="ModLog"):          if not changes:              return -        member_str = escape_markdown(str(member))          message = "\n".join(f"{Emojis.bullet} {item}" for item in sorted(changes)) -        message = f"**{member_str}** (`{member.id}`)\n{message}" +        message = f"{format_user(member)}\n{message}"          await self.send_log_message(              icon_url=icon, @@ -856,3 +823,8 @@ class ModLog(Cog, name="ModLog"):              thumbnail=member.avatar_url_as(static_format="png"),              channel_id=Channels.voice_log          ) + + +def setup(bot: Bot) -> None: +    """Load the ModLog cog.""" +    bot.add_cog(ModLog(bot)) | 
