From 96cf2e86ba43edd8a7c0d23e982771a8d3818823 Mon Sep 17 00:00:00 2001 From: disqualifier Date: Mon, 6 Jul 2026 00:18:52 -0400 Subject: [PATCH] fix: log a warning on duplicate attachment filenames in lookup() (dpycache-2) lookup()'s {filename: FileRef} comprehension silently kept only the last attachment when a foreign message carried duplicate filenames (Discord permits this; cache()'s own upload path already rejects it loudly, so the gap is only a foreign message passed to lookup()). Refs still resolve correctly by attachment_id, so keep the last-wins map (non-breaking) but log the collision instead of staying silent about it. Signed-off-by: disqualifier --- src/dpy_cache/dpy_cache.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/dpy_cache/dpy_cache.py b/src/dpy_cache/dpy_cache.py index abe5858..928cd9f 100644 --- a/src/dpy_cache/dpy_cache.py +++ b/src/dpy_cache/dpy_cache.py @@ -200,12 +200,23 @@ class DPYCache: async def lookup(self, message: "str | int | discord.Message") -> dict[str, FileRef]: """reverse lookup: a jump-url, message id (``int`` or a digit-only ``str``, matching the snowflake shape stored in JSON/DBs), or Message -> {filename: FileRef}; raises - (NotFound) if the message is gone, never an empty map for a missing message""" + (NotFound) if the message is gone, never an empty map for a missing message + + keyed by filename, so a foreign message with duplicate attachment filenames (Discord + allows this; ``cache()`` itself never produces one) collapses to the last attachment + of that name in the map - logged, not silent. every ref still resolves correctly by + its own ``attachment_id`` regardless""" resolved = await self._resolve_message(message) - return { - attachment.filename: _ref_from_attachment(attachment.filename, attachment, resolved) - for attachment in resolved.attachments - } + refs: dict[str, FileRef] = {} + for attachment in resolved.attachments: + if attachment.filename in refs: + log.warning( + "dpy_cache: message %s has more than one attachment named %r; " + "lookup() keeps only the last (attachment_id=%s)", + resolved.id, attachment.filename, attachment.id, + ) + refs[attachment.filename] = _ref_from_attachment(attachment.filename, attachment, resolved) + return refs def _normalize(self, files: "dict[str, FileContent] | list[FileContent]") -> "list[tuple[str, FileContent]]": """normalize dict/list input to an ordered list of (name, source); raises ValueError