From bf75350a7c8913e0922782327a57505a76ec2df5 Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 6 Jun 2025 06:48:50 +0000 Subject: [PATCH 1/4] refactor logging commands to use views --- cogs/logging_cog.py | 82 +++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/cogs/logging_cog.py b/cogs/logging_cog.py index 560f22a..a553904 100644 --- a/cogs/logging_cog.py +++ b/cogs/logging_cog.py @@ -116,17 +116,15 @@ class LoggingCog(commands.Cog): self.container = ui.Container(accent_colour=color) self.add_item(self.container) + self.header_section = ui.Section() if author is not None: - header = ui.Section( - accessory=ui.Thumbnail(media=author.display_avatar.url) + self.header_section.accessory = ui.Thumbnail( + media=author.display_avatar.url ) - else: - header = ui.Section() - - header.add_item(ui.TextDisplay(f"**{title}**")) + self.header_section.add_item(ui.TextDisplay(f"**{title}**")) if description: - header.add_item(ui.TextDisplay(description)) - self.container.add_item(header) + self.header_section.add_item(ui.TextDisplay(description)) + self.container.add_item(self.header_section) self.container.add_item( ui.Separator(spacing=discord.SeparatorSpacing.small) ) @@ -148,6 +146,12 @@ class LoggingCog(commands.Cog): def add_field(self, name: str, value: str, inline: bool = False) -> None: self.content_container.add_item(ui.TextDisplay(f"**{name}:** {value}")) + def set_author(self, user: discord.abc.User) -> None: + """Update the header with a user thumbnail and footer with the ID.""" + self.header_section.accessory = ui.Thumbnail(media=user.display_avatar.url) + if "User ID:" not in self.footer_display.content: + self.footer_display.content += f" | User ID: {user.id}" + def _user_display(self, user: Union[discord.Member, discord.User]) -> str: """Return display name, username and ID string for a user.""" display = user.display_name if isinstance(user, discord.Member) else user.name @@ -539,44 +543,38 @@ class LoggingCog(commands.Cog): guild_id = ctx.guild.id toggles = await settings_manager.get_all_log_event_toggles(guild_id) - embed = discord.Embed( - title=f"Logging Status for {ctx.guild.name}", color=discord.Color.blue() - ) lines = [] for key in ALL_EVENT_KEYS: - # Get status, defaulting to True if not explicitly in the DB/cache map is_enabled = toggles.get(key, True) status_emoji = "โœ…" if is_enabled else "โŒ" lines.append(f"{status_emoji} `{key}`") - # Paginate if too long for one embed description description = "" for line in lines: - if ( - len(description) + len(line) + 1 > 4000 - ): # Embed description limit (approx) - embed.description = description - await ctx.send(embed=embed, allowed_mentions=AllowedMentions.none()) - description = line + "\n" # Start new description - embed = discord.Embed( - color=discord.Color.blue() - ) # New embed for continuation + if len(description) + len(line) + 1 > 4000: + view = self._create_log_embed( + title=f"Logging Status for {ctx.guild.name}", + description=description.strip(), + color=discord.Color.blue(), + ) + await ctx.send(view=view, allowed_mentions=AllowedMentions.none()) + description = line + "\n" else: description += line + "\n" - if description: # Send the last embed page - embed.description = description.strip() - await ctx.send(embed=embed, allowed_mentions=AllowedMentions.none()) + if description: + view = self._create_log_embed( + title=f"Logging Status for {ctx.guild.name}", + description=description.strip(), + color=discord.Color.blue(), + ) + await ctx.send(view=view, allowed_mentions=AllowedMentions.none()) @log_group.command(name="list_keys") async def log_list_keys(self, ctx: commands.Context): """Lists all valid event keys for use with the 'log toggle' command.""" - embed = discord.Embed( - title="Available Logging Event Keys", color=discord.Color.purple() - ) keys_text = "\n".join(f"`{key}`" for key in ALL_EVENT_KEYS) - # Paginate if needed if len(keys_text) > 4000: parts = [] current_part = "" @@ -590,16 +588,22 @@ class LoggingCog(commands.Cog): if current_part: parts.append(current_part) - embed.description = parts[0] - await ctx.send(embed=embed, allowed_mentions=AllowedMentions.none()) - for part in parts[1:]: - await ctx.send( - embed=discord.Embed(description=part, color=discord.Color.purple()), - allowed_mentions=AllowedMentions.none(), + first = True + for part in parts: + view = self._create_log_embed( + title="Available Logging Event Keys" if first else "", + description=part.strip(), + color=discord.Color.purple(), ) + await ctx.send(view=view, allowed_mentions=AllowedMentions.none()) + first = False else: - embed.description = keys_text - await ctx.send(embed=embed, allowed_mentions=AllowedMentions.none()) + view = self._create_log_embed( + title="Available Logging Event Keys", + description=keys_text, + color=discord.Color.purple(), + ) + await ctx.send(view=view, allowed_mentions=AllowedMentions.none()) # --- Thread Events --- @commands.Cog.listener() @@ -617,9 +621,7 @@ class LoggingCog(commands.Cog): footer=f"Thread ID: {thread.id} | Parent ID: {thread.parent_id}", ) if thread.owner: # Sometimes owner isn't cached immediately - embed.set_author( - name=str(thread.owner), icon_url=thread.owner.display_avatar.url - ) + embed.set_author(thread.owner) await self._send_log_embed(guild, embed) @commands.Cog.listener() From 57a535358d08f0a02beb6d6deccfb6c3ca82e5db Mon Sep 17 00:00:00 2001 From: Slipstream Date: Fri, 6 Jun 2025 06:53:43 +0000 Subject: [PATCH 2/4] Applying previous commit. --- cogs/logging_cog.py | 82 +++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/cogs/logging_cog.py b/cogs/logging_cog.py index 560f22a..a553904 100644 --- a/cogs/logging_cog.py +++ b/cogs/logging_cog.py @@ -116,17 +116,15 @@ class LoggingCog(commands.Cog): self.container = ui.Container(accent_colour=color) self.add_item(self.container) + self.header_section = ui.Section() if author is not None: - header = ui.Section( - accessory=ui.Thumbnail(media=author.display_avatar.url) + self.header_section.accessory = ui.Thumbnail( + media=author.display_avatar.url ) - else: - header = ui.Section() - - header.add_item(ui.TextDisplay(f"**{title}**")) + self.header_section.add_item(ui.TextDisplay(f"**{title}**")) if description: - header.add_item(ui.TextDisplay(description)) - self.container.add_item(header) + self.header_section.add_item(ui.TextDisplay(description)) + self.container.add_item(self.header_section) self.container.add_item( ui.Separator(spacing=discord.SeparatorSpacing.small) ) @@ -148,6 +146,12 @@ class LoggingCog(commands.Cog): def add_field(self, name: str, value: str, inline: bool = False) -> None: self.content_container.add_item(ui.TextDisplay(f"**{name}:** {value}")) + def set_author(self, user: discord.abc.User) -> None: + """Update the header with a user thumbnail and footer with the ID.""" + self.header_section.accessory = ui.Thumbnail(media=user.display_avatar.url) + if "User ID:" not in self.footer_display.content: + self.footer_display.content += f" | User ID: {user.id}" + def _user_display(self, user: Union[discord.Member, discord.User]) -> str: """Return display name, username and ID string for a user.""" display = user.display_name if isinstance(user, discord.Member) else user.name @@ -539,44 +543,38 @@ class LoggingCog(commands.Cog): guild_id = ctx.guild.id toggles = await settings_manager.get_all_log_event_toggles(guild_id) - embed = discord.Embed( - title=f"Logging Status for {ctx.guild.name}", color=discord.Color.blue() - ) lines = [] for key in ALL_EVENT_KEYS: - # Get status, defaulting to True if not explicitly in the DB/cache map is_enabled = toggles.get(key, True) status_emoji = "โœ…" if is_enabled else "โŒ" lines.append(f"{status_emoji} `{key}`") - # Paginate if too long for one embed description description = "" for line in lines: - if ( - len(description) + len(line) + 1 > 4000 - ): # Embed description limit (approx) - embed.description = description - await ctx.send(embed=embed, allowed_mentions=AllowedMentions.none()) - description = line + "\n" # Start new description - embed = discord.Embed( - color=discord.Color.blue() - ) # New embed for continuation + if len(description) + len(line) + 1 > 4000: + view = self._create_log_embed( + title=f"Logging Status for {ctx.guild.name}", + description=description.strip(), + color=discord.Color.blue(), + ) + await ctx.send(view=view, allowed_mentions=AllowedMentions.none()) + description = line + "\n" else: description += line + "\n" - if description: # Send the last embed page - embed.description = description.strip() - await ctx.send(embed=embed, allowed_mentions=AllowedMentions.none()) + if description: + view = self._create_log_embed( + title=f"Logging Status for {ctx.guild.name}", + description=description.strip(), + color=discord.Color.blue(), + ) + await ctx.send(view=view, allowed_mentions=AllowedMentions.none()) @log_group.command(name="list_keys") async def log_list_keys(self, ctx: commands.Context): """Lists all valid event keys for use with the 'log toggle' command.""" - embed = discord.Embed( - title="Available Logging Event Keys", color=discord.Color.purple() - ) keys_text = "\n".join(f"`{key}`" for key in ALL_EVENT_KEYS) - # Paginate if needed if len(keys_text) > 4000: parts = [] current_part = "" @@ -590,16 +588,22 @@ class LoggingCog(commands.Cog): if current_part: parts.append(current_part) - embed.description = parts[0] - await ctx.send(embed=embed, allowed_mentions=AllowedMentions.none()) - for part in parts[1:]: - await ctx.send( - embed=discord.Embed(description=part, color=discord.Color.purple()), - allowed_mentions=AllowedMentions.none(), + first = True + for part in parts: + view = self._create_log_embed( + title="Available Logging Event Keys" if first else "", + description=part.strip(), + color=discord.Color.purple(), ) + await ctx.send(view=view, allowed_mentions=AllowedMentions.none()) + first = False else: - embed.description = keys_text - await ctx.send(embed=embed, allowed_mentions=AllowedMentions.none()) + view = self._create_log_embed( + title="Available Logging Event Keys", + description=keys_text, + color=discord.Color.purple(), + ) + await ctx.send(view=view, allowed_mentions=AllowedMentions.none()) # --- Thread Events --- @commands.Cog.listener() @@ -617,9 +621,7 @@ class LoggingCog(commands.Cog): footer=f"Thread ID: {thread.id} | Parent ID: {thread.parent_id}", ) if thread.owner: # Sometimes owner isn't cached immediately - embed.set_author( - name=str(thread.owner), icon_url=thread.owner.display_avatar.url - ) + embed.set_author(thread.owner) await self._send_log_embed(guild, embed) @commands.Cog.listener() From 7c7c53bf01daf268cae04981ac2c54daa0b212de Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 6 Jun 2025 06:59:57 +0000 Subject: [PATCH 3/4] Fix LogView header section --- cogs/logging_cog.py | 46 +++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/cogs/logging_cog.py b/cogs/logging_cog.py index a553904..d6d2195 100644 --- a/cogs/logging_cog.py +++ b/cogs/logging_cog.py @@ -116,15 +116,23 @@ class LoggingCog(commands.Cog): self.container = ui.Container(accent_colour=color) self.add_item(self.container) - self.header_section = ui.Section() + title_display = ui.TextDisplay(f"**{title}**") + desc_display = ui.TextDisplay(description) if description else None + self.header_items: list[ui.TextDisplay] = [title_display] + if desc_display: + self.header_items.append(desc_display) + + self.header_section: Optional[ui.Section] = None if author is not None: - self.header_section.accessory = ui.Thumbnail( - media=author.display_avatar.url + self.header_section = ui.Section( + accessory=ui.Thumbnail(media=author.display_avatar.url) ) - self.header_section.add_item(ui.TextDisplay(f"**{title}**")) - if description: - self.header_section.add_item(ui.TextDisplay(description)) - self.container.add_item(self.header_section) + for item in self.header_items: + self.header_section.add_item(item) + self.container.add_item(self.header_section) + else: + for item in self.header_items: + self.container.add_item(item) self.container.add_item( ui.Separator(spacing=discord.SeparatorSpacing.small) ) @@ -147,8 +155,24 @@ class LoggingCog(commands.Cog): self.content_container.add_item(ui.TextDisplay(f"**{name}:** {value}")) def set_author(self, user: discord.abc.User) -> None: - """Update the header with a user thumbnail and footer with the ID.""" - self.header_section.accessory = ui.Thumbnail(media=user.display_avatar.url) + """Add or update the thumbnail and append the user ID to the footer.""" + if self.header_section is None: + self.header_section = ui.Section( + accessory=ui.Thumbnail(media=user.display_avatar.url) + ) + for item in self.header_items: + self.container.remove_item(item) + self.header_section.add_item(item) + # Insert at the beginning to keep layout consistent + if hasattr(self.container, "children"): + self.container.children.insert(0, self.header_section) + else: + self.container.add_item(self.header_section) + else: + self.header_section.accessory = ui.Thumbnail( + media=user.display_avatar.url + ) + if "User ID:" not in self.footer_display.content: self.footer_display.content += f" | User ID: {user.id}" @@ -617,11 +641,9 @@ class LoggingCog(commands.Cog): title="๐Ÿงต Thread Created", description=f"Thread {thread.mention} (`{thread.name}`) created in {thread.parent.mention}.", color=discord.Color.dark_blue(), - # Creator might be available via thread.owner_id or audit log + author=thread.owner if thread.owner else None, footer=f"Thread ID: {thread.id} | Parent ID: {thread.parent_id}", ) - if thread.owner: # Sometimes owner isn't cached immediately - embed.set_author(thread.owner) await self._send_log_embed(guild, embed) @commands.Cog.listener() From d7519b3c7b02332d2740062e1524348a7a86bef4 Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 6 Jun 2025 07:02:05 +0000 Subject: [PATCH 4/4] Fix merge conflicts in logging cog --- cogs/logging_cog.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cogs/logging_cog.py b/cogs/logging_cog.py index 4beee82..1cd7f8b 100644 --- a/cogs/logging_cog.py +++ b/cogs/logging_cog.py @@ -643,11 +643,6 @@ class LoggingCog(commands.Cog): author=thread.owner if thread.owner else None, footer=f"Thread ID: {thread.id} | Parent ID: {thread.parent_id}", ) -<<<<<<< HEAD -======= - if thread.owner: # Sometimes owner isn't cached immediately - embed.set_author(thread.owner) ->>>>>>> bf75350a7c8913e0922782327a57505a76ec2df5 await self._send_log_embed(guild, embed) @commands.Cog.listener()