fix(wormhole): use inline links for foreign emojis instead of file attachments
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.
This commit is contained in:
parent
424403cf4f
commit
f74e9b7897
1 changed files with 15 additions and 40 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue