From d6630dd1c54c095e91d5ba656fbe001b3df7eafb Mon Sep 17 00:00:00 2001 From: rambros Date: Sat, 7 Mar 2026 14:48:04 +0530 Subject: [PATCH] fix stoat embeds --- src/fluxer/writer.py | 14 ++++++++++++-- src/stoat/writer.py | 46 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/fluxer/writer.py b/src/fluxer/writer.py index 25507f7..30fb3c6 100644 --- a/src/fluxer/writer.py +++ b/src/fluxer/writer.py @@ -259,6 +259,16 @@ class FluxerWriter: if files: fluxer_files = [File(io.BytesIO(f["data"]), filename=f["filename"]) for f in files] + # Normalize embeds (ensure they are dicts, handling fluxer.Embed objects or dicts) + normalized_embeds = None + if embeds: + normalized_embeds = [] + for e in embeds: + if hasattr(e, "to_dict"): + normalized_embeds.append(e.to_dict()) + else: + normalized_embeds.append(e) + try: # Current limitation: fluxer.py execute_webhook doesn't support 'message_reference' yet. # So if we have a reply, we MUST use the bot's direct send method. @@ -268,7 +278,7 @@ class FluxerWriter: username=f"{author_name} (discord)", avatar_url=author_avatar_url, files=fluxer_files, - embeds=embeds, + embeds=normalized_embeds, wait=True ) return str(msg.id) if msg else None @@ -290,7 +300,7 @@ class FluxerWriter: channel_id=channel_id, content=final_bot_content, files=fluxer_files, - embeds=embeds, + embeds=normalized_embeds, message_reference=message_reference ) return str(msg_data["id"]) if msg_data else None diff --git a/src/stoat/writer.py b/src/stoat/writer.py index f34e85f..806d5aa 100644 --- a/src/stoat/writer.py +++ b/src/stoat/writer.py @@ -256,12 +256,56 @@ class StoatWriter: attachments.append((f["filename"], f["data"])) try: + # Stoat requires SendableEmbed objects, not raw dicts + stoat_embeds = [] + if embeds: + for e in embeds: + # Convert integer color to hex string if present + color = None + if e.get("color"): + color = f"#{e['color']:06x}" + + # Map Discord fields to Stoat SendableEmbed fields + # icon_url: author or footer icon + icon_url = None + if e.get("author"): + icon_url = e["author"].get("icon_url") + if not icon_url and e.get("footer"): + icon_url = e["footer"].get("icon_url") + + # media: image or thumbnail. + # Stoat's SendableEmbed.media expects a file ID or ResolvableResource (Upload). + # It does NOT properly handle external URLs in the 'media' field (causes 404). + media = None + image_url = e.get("image", {}).get("url") + thumbnail_url = e.get("thumbnail", {}).get("url") + + # If we have an image/thumbnail URL and no icon_url, use it as icon_url + # (Stoat icons can be URLs and show up as small images) + if not icon_url: + icon_url = thumbnail_url or image_url + + # Only use media if it's NOT a URL (likely a file ID from a previous Stoat message) + if image_url and not image_url.startswith("http"): + media = image_url + elif thumbnail_url and not thumbnail_url.startswith("http"): + media = thumbnail_url + + stoat_embeds.append(stoat.SendableEmbed( + title=e.get("title"), + description=e.get("description"), + icon_url=icon_url, + url=e.get("url"), + media=media, + color=color + )) + msg = await channel.send( content=final_content, masquerade=masquerade, replies=replies, attachments=attachments, - embeds=embeds + embeds=stoat_embeds ) return str(msg.id) if msg else None except Exception as e: