Repository: Cog-Creators/Red-DiscordBot

Issue:
Casesfor AttributeError
# Command bugs

<!-- 
Did you find a bug with a command? Fill out the following:
-->

#### Command name

casesfor

#### What cog is this command from?

ModLog

#### What were you expecting to happen?

To showcases on the member or say user doesn't have any cases

#### What actually happened?

Errored out with an AttributeError:
```py
Traceback (most recent call last):
  File "/red-v32/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "/red-v32/lib/python3.8/site-packages/redbot/cogs/modlog/modlog.py", line 142, in casesfor
    rendered_cases = [await case.message_content(embed=embed_requested) for case in cases]
  File "/red-v32/lib/python3.8/site-packages/redbot/cogs/modlog/modlog.py", line 142, in <listcomp>
    rendered_cases = [await case.message_content(embed=embed_requested) for case in cases]
  File "/red-v32/lib/python3.8/site-packages/redbot/core/modlog.py", line 296, in message_content
    moderator = escape_spoilers(f"{self.moderator} ({self.moderator.id})")
AttributeError: 'int' object has no attribute 'id'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/red-v32/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 892, in invoke
    await ctx.command.invoke(ctx)
  File "/red-v32/lib/python3.8/site-packages/discord/ext/commands/core.py", line 824, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "/red-v32/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'int' object has no attribute 'id'
```

#### How can we reproduce this issue?

Try to check someone's cases...Sometimes this works other times this errors.



Discussion:

Resolving patch:
diff --git a/redbot/core/modlog.py b/redbot/core/modlog.py
--- a/redbot/core/modlog.py
+++ b/redbot/core/modlog.py
@@ -208,12 +208,12 @@ def __init__(
         created_at: int,
         action_type: str,
         user: Union[discord.User, int],
-        moderator: discord.User,
+        moderator: Optional[Union[discord.User, int]],
         case_number: int,
         reason: str = None,
         until: int = None,
         channel: Optional[Union[discord.TextChannel, discord.VoiceChannel, int]] = None,
-        amended_by: Optional[discord.User] = None,
+        amended_by: Optional[Union[discord.User, int]] = None,
         modified_at: Optional[int] = None,
         message: Optional[discord.Message] = None,
         last_known_username: Optional[str] = None,
@@ -294,10 +294,12 @@ async def message_content(self, embed: bool = True):
         else:
             reason = _("**Reason:** Use the `reason` command to add it")
 
-        if self.moderator is not None:
-            moderator = escape_spoilers(f"{self.moderator} ({self.moderator.id})")
-        else:
+        if self.moderator is None:
             moderator = _("Unknown")
+        elif isinstance(self.moderator, int):
+            moderator = f"[Unknown or Deleted User] ({self.moderator})"
+        else:
+            moderator = escape_spoilers(f"{self.moderator} ({self.moderator.id})")
         until = None
         duration = None
         if self.until:
@@ -309,13 +311,12 @@ async def message_content(self, embed: bool = True):
             until = end_fmt
             duration = dur_fmt
 
-        amended_by = None
         if self.amended_by:
-            amended_by = escape_spoilers(
-                "{}#{} ({})".format(
-                    self.amended_by.name, self.amended_by.discriminator, self.amended_by.id
-                )
-            )
+            amended_by = None
+        elif isinstance(self.amended_by, int):
+            amended_by = f"[Unknown or Deleted User] ({self.amended_by})"
+        else:
+            amended_by = escape_spoilers(f"{self.amended_by} ({self.amended_by.id})")
 
         last_modified = None
         if self.modified_at:
@@ -383,10 +384,14 @@ def to_json(self) -> dict:
             The case in the form of a dict
 
         """
-        if self.moderator is not None:
+        if self.moderator is None or isinstance(self.moderator, int):
+            mod = self.moderator
+        else:
             mod = self.moderator.id
+        if self.amended_by is None or isinstance(self.amended_by, int):
+            amended_by = self.amended_by
         else:
-            mod = None
+            amended_by = self.amended_by.id
         if isinstance(self.user, int):
             user_id = self.user
         else:
@@ -402,7 +407,7 @@ def to_json(self) -> dict:
             "reason": self.reason,
             "until": self.until,
             "channel": self.channel.id if hasattr(self.channel, "id") else None,
-            "amended_by": self.amended_by.id if hasattr(self.amended_by, "id") else None,
+            "amended_by": amended_by,
             "modified_at": self.modified_at,
             "message": self.message.id if hasattr(self.message, "id") else None,
         }


Test patch: