diff --git a/jarvis/cogs/admin/modcase.py b/jarvis/cogs/admin/modcase.py index d183789..071da4a 100644 --- a/jarvis/cogs/admin/modcase.py +++ b/jarvis/cogs/admin/modcase.py @@ -1,5 +1,5 @@ """JARVIS Moderation Case management.""" -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, List, Optional from jarvis_core.db import q from jarvis_core.db.models import Modlog, actions @@ -34,9 +34,9 @@ ACTIONS_LOOKUP = { class CaseCog(Cog): """JARVIS CaseCog.""" - async def get_embed(self, mod_case: Modlog, guild: "Guild") -> Embed: + async def get_summary_embed(self, mod_case: Modlog, guild: "Guild") -> Embed: """ - Get Moderation case embed. + Get Moderation case summary embed. Args: mod_case: Moderation case @@ -59,10 +59,10 @@ class CaseCog(Cog): parent_action = await ACTIONS_LOOKUP[action.action_type].find_one(q(id=action.parent)) if not parent_action: action.orphaned = True - action_table.add_row(action.action_type.title(), "N/A", "N/A") + action_table.add_row(action.action_type.title(), "[N/A]", "[N/A]") else: admin = await self.bot.fetch_user(parent_action.admin) - admin_text = "Deleted User" + admin_text = "[N/A]" if admin: admin_text = f"{admin.username}#{admin.discriminator}" action_table.add_row(action.action_type.title(), admin_text, parent_action.reason) @@ -81,7 +81,7 @@ class CaseCog(Cog): notes = sorted(mod_case.notes, key=lambda x: x.created_at) for idx, note in enumerate(notes): admin = await self.bot.fetch_user(note.admin) - admin_text = "N/A" + admin_text = "[N/A]" if admin: admin_text = f"{admin.username}#{admin.discriminator}" note_table.add_row(admin_text, note.content) @@ -99,8 +99,8 @@ class CaseCog(Cog): status = "Open" if mod_case.open else "Closed" user = await self.bot.fetch_user(mod_case.user) - username = "Deleted User" - user_text = "Deleted User" + username = "[N/A]" + user_text = "[N/A]" if user: username = f"{user.username}#{user.discriminator}" user_text = user.mention @@ -134,6 +134,53 @@ class CaseCog(Cog): await mod_case.commit() return embed + async def get_action_embeds(self, mod_case: Modlog, guild: "Guild") -> List[Embed]: + """ + Get Moderation case action embeds. + + Args: + mod_case: Moderation case + guild: Originating guild + """ + embeds = [] + user = await self.bot.fetch_user(mod_case.user) + username = "[N/A]" + user_mention = "[N/A]" + avatar_url = None + if user: + username = f"{user.username}#{user.discriminator}" + avatar_url = user.avatar.url + user_mention = user.mention + + for action in mod_case.actions: + if action.orphaned: + continue + parent_action = await ACTIONS_LOOKUP[action.action_type].find_one(q(id=action.parent)) + if not parent_action: + action.orphaned = True + continue + + admin = await self.bot.fetch_user(parent_action.admin) + admin_text = "[N/A]" + if admin: + admin_text = admin.mention + + fields = ( + EmbedField(name="Admin", value=admin_text), + EmbedField(name="Reason", value=parent_action.reason), + ) + embed = build_embed( + title="Moderation Case Action", + description=f"{user_mention} was warned by {admin_text}", + fields=fields, + timestamp=parent_action.created_at, + ) + embed.set_author(name=username, icon_url=avatar_url) + embeds.append(embed) + + await mod_case.commit() + return embeds + cases = SlashCommand(name="cases", description="Manage moderation cases") @cases.subcommand(sub_cmd_name="list", sub_cmd_description="List moderation cases") @@ -164,24 +211,38 @@ class CaseCog(Cog): await ctx.send("No cases to view", ephemeral=True) return - pages = [await self.get_embed(c, ctx.guild) for c in cases] + pages = [await self.get_summary_embed(c, ctx.guild) for c in cases] paginator = Paginator.create_from_embeds(self.bot, *pages, timeout=300) await paginator.send(ctx) case = SlashCommand(name="case", description="Manage a moderation case") + show = case.group(name="show", description="Show information about a specific case") - @case.subcommand(sub_cmd_name="show", sub_cmd_description="Show a specific case") + @show.subcommand(sub_cmd_name="summary", sub_cmd_description="Summarize a specific case") @slash_option(name="cid", description="Case ID", opt_type=OptionTypes.STRING, required=True) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) - async def _case_show(self, ctx: InteractionContext, cid: str) -> None: + async def _case_show_summary(self, ctx: InteractionContext, cid: str) -> None: case = await Modlog.find_one(q(guild=ctx.guild.id, nanoid=cid)) if not case: await ctx.send(f"Could not find case with ID {cid}", ephemeral=True) return - embed = await self.get_embed(case, ctx.guild) + embed = await self.get_summary_embed(case, ctx.guild) await ctx.send(embed=embed) + @show.subcommand(sub_cmd_name="actions", description="Get case actions") + @slash_option(name="cid", description="Case ID", opt_type=OptionTypes.STRING, required=True) + @check(admin_or_permissions(Permissions.BAN_MEMBERS)) + async def _case_show_actions(self, ctx: InteractionContext, cid: str) -> None: + case = await Modlog.find_one(q(guild=ctx.guild.id, nanoid=cid)) + if not case: + await ctx.send(f"Could not find case with ID {cid}", ephemeral=True) + return + + pages = await self.get_action_embeds(case, ctx.guild) + paginator = Paginator.create_from_embeds(self.bot, *pages, timeout=300) + await paginator.send(ctx) + @case.subcommand(sub_cmd_name="close", sub_cmd_description="Show a specific case") @slash_option(name="cid", description="Case ID", opt_type=OptionTypes.STRING, required=True) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) @@ -194,5 +255,5 @@ class CaseCog(Cog): case.open = False await case.commit() - embed = await self.get_embed(case, ctx.guild) + embed = await self.get_summary_embed(case, ctx.guild) await ctx.send(embed=embed)