-
-
Notifications
You must be signed in to change notification settings - Fork 42
fix(bookmarks): Better handle attachments to prevent errors #1131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,9 +8,11 @@ | |||||||||||||||||||||||||||
| from __future__ import annotations | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| import io | ||||||||||||||||||||||||||||
| from collections.abc import Sequence | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| import aiohttp | ||||||||||||||||||||||||||||
| import discord | ||||||||||||||||||||||||||||
| from discord import StickerFormatType, StickerItem | ||||||||||||||||||||||||||||
| from discord.abc import Messageable | ||||||||||||||||||||||||||||
| from discord.ext import commands | ||||||||||||||||||||||||||||
| from loguru import logger | ||||||||||||||||||||||||||||
|
|
@@ -181,7 +183,7 @@ async def _get_files_from_attachments( | |||||||||||||||||||||||||||
| The list to append extracted files to. | ||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||
| for attachment in message.attachments: | ||||||||||||||||||||||||||||
| if len(files) >= 10: | ||||||||||||||||||||||||||||
| if len(files) > 10: | ||||||||||||||||||||||||||||
This comment was marked as outdated.
Sorry, something went wrong. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix off-by-one error in file limit check. The condition 🔎 Proposed fix- if len(files) > 10:
+ if len(files) >= 10:
break📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
| break | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if attachment.content_type and "image" in attachment.content_type: | ||||||||||||||||||||||||||||
|
|
@@ -240,11 +242,11 @@ async def _get_files_from_embeds( | |||||||||||||||||||||||||||
| files : list[discord.File] | ||||||||||||||||||||||||||||
| The list to append extracted files to. | ||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||
| if len(files) >= 10: | ||||||||||||||||||||||||||||
| if len(files) > 10: | ||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| for embed in message.embeds: | ||||||||||||||||||||||||||||
| if len(files) >= 10: | ||||||||||||||||||||||||||||
| if len(files) > 10: | ||||||||||||||||||||||||||||
| break | ||||||||||||||||||||||||||||
|
Comment on lines
+245
to
250
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same off-by-one error as in Both checks at lines 241 and 245 use 🔎 Proposed fix- if len(files) > 10:
+ if len(files) >= 10:
return
for embed in message.embeds:
- if len(files) > 10:
+ if len(files) >= 10:
break📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if embed.image and embed.image.url: | ||||||||||||||||||||||||||||
|
|
@@ -311,13 +313,56 @@ def _create_bookmark_embed(self, message: discord.Message) -> discord.Embed: | |||||||||||||||||||||||||||
| if len(content) > EMBED_MAX_DESC_LENGTH: | ||||||||||||||||||||||||||||
| content = f"{content[: EMBED_MAX_DESC_LENGTH - 4]}..." | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Prepare attachment bullets | ||||||||||||||||||||||||||||
| attachment_list = "" | ||||||||||||||||||||||||||||
| if message.attachments: | ||||||||||||||||||||||||||||
| attachment_list = "\n".join( | ||||||||||||||||||||||||||||
| f"• [{att.filename}]({att.url})" for att in message.attachments | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| sticker_list: str = "" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| stickers: Sequence[StickerItem] = message.stickers | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: The code calls Suggested FixTo fix this, you must first fetch the full Prompt for AI AgentDid we get this right? 👍 / 👎 to inform future reviews. |
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if stickers: | ||||||||||||||||||||||||||||
| bullets: list[str] = [ | ||||||||||||||||||||||||||||
| f"• [{sticker.name}](https://cdn.discordapp.com/stickers/{sticker.id}.png)" | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: The code hardcodes the Suggested FixInstead of manually constructing the URL, revert to using the Prompt for AI AgentDid we get this right? 👍 / 👎 to inform future reviews. |
||||||||||||||||||||||||||||
| if sticker.format in {StickerFormatType.png, StickerFormatType.apng} | ||||||||||||||||||||||||||||
| and sticker.id != 0 | ||||||||||||||||||||||||||||
| else f"• {sticker.name}" | ||||||||||||||||||||||||||||
|
Comment on lines
+329
to
+332
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: Yes — discord.py exposes an id attribute on StickerItem. The docs show StickerItem.id is an int (the sticker's ID) and you can call StickerItem.fetch() to resolve the full sticker (StandardSticker/GuildSticker). See the API docs for StickerItem and StandardSticker. [1][2] Sources:
🏁 Script executed: # Check the bookmarks.py file context around lines 327-330
fd "bookmarks.py" --type f | head -5Repository: allthingslinux/tux Length of output: 99 🏁 Script executed: # Look for how stickers are sourced in this file
rg "sticker" src/tux/modules/features/bookmarks.py -B 5 -A 5 | head -60Repository: allthingslinux/tux Length of output: 2017 🏁 Script executed: # Read the specific section around lines 327-330
sed -n '320,335p' src/tux/modules/features/bookmarks.pyRepository: allthingslinux/tux Length of output: 621 🌐 Web query:
💡 Result: Use the sticker's class or its type/fields. Examples (discord.py / pycord-style):
Short snippet: References: Discord sticker objects and types; library models for StandardSticker / GuildSticker. [1][2] Sources 🏁 Script executed: # Search for sticker-related code in the bookmarks file to understand context
rg "sticker" src/tux/modules/features/bookmarks.py -B 2 -A 2 | grep -A 20 "sticker.id"Repository: allthingslinux/tux Length of output: 706 🏁 Script executed: # Check imports at the top of bookmarks.py
head -50 src/tux/modules/features/bookmarks.py | grep -E "^import|^from"Repository: allthingslinux/tux Length of output: 511 🏁 Script executed: # Check for discord imports and StickerItem/StandardSticker/GuildSticker references
rg "StickerItem|StandardSticker|GuildSticker|StickerType" src/tux/modules/features/bookmarks.pyRepository: allthingslinux/tux Length of output: 171 🏁 Script executed: # Get full imports section
sed -n '1,100p' src/tux/modules/features/bookmarks.py | grep -A 100 "^import\|^from" | head -80Repository: allthingslinux/tux Length of output: 2541 Use the proper discord.py approach to identify built-in stickers instead of checking The condition 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
| for sticker in stickers | ||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||
| sticker_list = "\n".join(bullets) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Combine everything into the embed description and enforce the max length | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| parts: list[str] = [] | ||||||||||||||||||||||||||||
| if content: | ||||||||||||||||||||||||||||
| parts.append(content) | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
| parts.append("> No content available to display") | ||||||||||||||||||||||||||||
| if attachment_list: | ||||||||||||||||||||||||||||
| parts.append(f"**Attachments:**\n{attachment_list}") | ||||||||||||||||||||||||||||
| if sticker_list: | ||||||||||||||||||||||||||||
| parts.append(f"**Stickers:**\n{sticker_list}") | ||||||||||||||||||||||||||||
| description = "\n\n".join(parts) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| limit_warning = "\n\n*(Message cut off due to character limit.)*" | ||||||||||||||||||||||||||||
| # Ensure we never exceed Discord's embed description limit | ||||||||||||||||||||||||||||
| if len(description) > EMBED_MAX_DESC_LENGTH: | ||||||||||||||||||||||||||||
| # reserve space for the notice | ||||||||||||||||||||||||||||
| cutoff = EMBED_MAX_DESC_LENGTH - len(limit_warning) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # avoid negative slice sizes in extreme cases | ||||||||||||||||||||||||||||
| cutoff = max(0, cutoff) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| description = description[:cutoff].rstrip() + limit_warning | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| embed = EmbedCreator.create_embed( | ||||||||||||||||||||||||||||
| bot=self.bot, | ||||||||||||||||||||||||||||
| embed_type=EmbedCreator.INFO, | ||||||||||||||||||||||||||||
| title="Message Bookmarked", | ||||||||||||||||||||||||||||
| description=f"{content}" | ||||||||||||||||||||||||||||
| if content | ||||||||||||||||||||||||||||
| else "> No content available to display", | ||||||||||||||||||||||||||||
| description=description, | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Add author to the embed | ||||||||||||||||||||||||||||
|
|
@@ -341,18 +386,6 @@ def _create_bookmark_embed(self, message: discord.Message) -> discord.Embed: | |||||||||||||||||||||||||||
| value=f"[Click Here]({message.jump_url})", | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Add attachments to the embed | ||||||||||||||||||||||||||||
| if message.attachments: | ||||||||||||||||||||||||||||
|
Comment on lines
342
to
-345
This comment was marked as outdated.
Sorry, something went wrong. |
||||||||||||||||||||||||||||
| attachments = "\n".join( | ||||||||||||||||||||||||||||
| f"[{a.filename}]({a.url})" for a in message.attachments | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| embed.add_field(name="Attachments", value=attachments, inline=False) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Add stickers to the embed | ||||||||||||||||||||||||||||
| if message.stickers: | ||||||||||||||||||||||||||||
| stickers = "\n".join(f"[{s.name}]({s.url})" for s in message.stickers) | ||||||||||||||||||||||||||||
| embed.add_field(name="Stickers", value=stickers, inline=False) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Handle embeds | ||||||||||||||||||||||||||||
| if message.embeds: | ||||||||||||||||||||||||||||
| embed.add_field( | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): The changed comparison allows collecting 11 files instead of 10, which is likely off-by-one relative to the intended cap.
The old
>= 10check ensured you never collected more than 10 files; with> 10, the loop now allows 11 before breaking. If the limit is meant to stay at 10, keep>= 10(or guard the body with< 10). If you do want a higher cap, consider introducing a named constant for the limit instead of using a magic number.