From f74e9b789738ac952240252b54b8fdf860d21ba7 Mon Sep 17 00:00:00 2001 From: Viktor Date: Thu, 14 May 2026 15:53:01 +0000 Subject: [PATCH] fix(wormhole): use inline links for foreign emojis instead of file attachments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit File attachments render as massive images in Discord. Replace the download-and-attach approach with clickable [:name:](cdn_url) inline links — keeps foreign emojis compact and inline with the message text. Removes aiohttp dependency and simplifies the helper to synchronous. Bumps to v3.4.5. --- wormhole/wormhole.py | 55 ++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 40 deletions(-) diff --git a/wormhole/wormhole.py b/wormhole/wormhole.py index 281efb9..beb58ba 100644 --- a/wormhole/wormhole.py +++ b/wormhole/wormhole.py @@ -34,8 +34,9 @@ Phase 5.3: Enhanced reply buttons — relayed replies now include a copy of the referenced message (if available in the target server) or falls back to the original message URL. Phase 5.4: Foreign emoji relay — custom emojis unknown to the bot are - replaced with :name: and their 64 px image is attached as a - file so users still see the emoji visually. + replaced with clickable [:name:](cdn_url) inline links so + they stay compact instead of rendering as massive file + attachments. """ from __future__ import annotations @@ -290,43 +291,25 @@ def _reply_jump_view(url: str) -> discord.ui.View: return view _CUSTOM_EMOJI_RE = re.compile(r'<(a?):(\w+):(\d+)>') -_EMOJI_IMAGE_LIMIT = 5 # max emoji images to attach per message -async def _resolve_foreign_emojis( - bot, content: str -) -> tuple[str, list[tuple[str, bytes]]]: - """Replace custom emojis the bot can't see with :name: and fetch images. +def _resolve_foreign_emojis(bot, content: str) -> str: + """Replace custom emojis the bot can't see with clickable :name: links. - Returns (new_content, [(filename, image_bytes), ...]). + Known emojis (from any server the bot is in) are left untouched. + Unknown emojis become [:name:](cdn_url) — a clickable inline link + that lets users view the emoji image without bloating the message. """ - unknown: list[tuple[str, int, str]] = [] # (name, id, ext) def _check(m: re.Match) -> str: animated, name, eid = m.group(1), m.group(2), int(m.group(3)) if bot.get_emoji(eid): return m.group(0) # known emoji — keep original syntax ext = "gif" if animated else "png" - unknown.append((name, eid, ext)) - return f":{name}:" + url = f"https://cdn.discordapp.com/emojis/{eid}.{ext}?size=48" + return f"[:{name}:]({url})" - new_content = _CUSTOM_EMOJI_RE.sub(_check, content) - - # Download images from Discord CDN (already public URLs, no auth needed) - emoji_data: list[tuple[str, bytes]] = [] - if unknown: - import aiohttp - async with aiohttp.ClientSession() as session: - for name, eid, ext in unknown[:_EMOJI_IMAGE_LIMIT]: - try: - url = f"https://cdn.discordapp.com/emojis/{eid}.{ext}?size=64" - async with session.get(url, timeout=aiohttp.ClientTimeout(total=5)) as resp: - if resp.status == 200: - emoji_data.append((f"{name}.{ext}", await resp.read())) - except Exception: - pass # best-effort — skip if CDN unreachable - - return new_content, emoji_data + return _CUSTOM_EMOJI_RE.sub(_check, content) _AUDIT_LIMIT = 500 @@ -437,7 +420,7 @@ class _ReportModal(discord.ui.Modal, title="Report Message"): class Wormhole(commands.Cog): """The ultimate cross-server relay: networks, DMs, starboard, auto-mod, invites, portals & more.""" - __version__ = "3.4.4" + __version__ = "3.4.5" def __init__(self, bot: Red): self.bot = bot @@ -4312,12 +4295,10 @@ class Wormhole(commands.Cog): extra_embeds = [e for e in message.embeds if e.type == "rich"] # ── Resolve foreign emojis ───────────────────────────────────────── - # If any custom emojis in the content are unknown to the bot, replace - # them with :name: and download the image from Discord CDN so it can - # be attached as a small file. - emoji_file_data: list[tuple[str, bytes]] = [] + # Unknown custom emojis become clickable [:name:](cdn_url) links so + # they stay inline and don't bloat the message as large file attachments. if content: - content, emoji_file_data = await _resolve_foreign_emojis(self.bot, content) + content = _resolve_foreign_emojis(self.bot, content) # ── Relay to channels ────────────────────────────────────────────── mapping: Dict[int, int] = {} @@ -4348,8 +4329,6 @@ class Wormhole(commands.Cog): for a in message.attachments: try: files.append(await a.to_file()) except: pass - for fname, fdata in emoji_file_data: - files.append(discord.File(io.BytesIO(fdata), filename=fname)) send_content = content if content else None if not send_content and not files and not extra_embeds: send_content = "*[empty message]*" @@ -4370,8 +4349,6 @@ class Wormhole(commands.Cog): for a in message.attachments: try: files2.append(await a.to_file()) except: pass - for fname, fdata in emoji_file_data: - files2.append(discord.File(io.BytesIO(fdata), filename=fname)) send_content = content if content else None if not send_content and not files2 and not extra_embeds: send_content = "*[empty message]*" @@ -4406,8 +4383,6 @@ class Wormhole(commands.Cog): for a in message.attachments: try: files.append(await a.to_file()) except: pass - for fname, fdata in emoji_file_data: - files.append(discord.File(io.BytesIO(fdata), filename=fname)) sent_msg = await ch.send(content=compact_format(g, display, content), files=files or None, **_view_kw) mapping[ch_id] = sent_msg.id