From 413df837ff317d18946b92823678bb0b4029f0a0 Mon Sep 17 00:00:00 2001 From: zenfyr Date: Mon, 10 Aug 2026 07:45:44 +0700 Subject: [PATCH] bsky->mastodon: handle embeds not linked in the post text. --- bluesky/input.py | 10 ++++++++++ cross/attachments.py | 7 +++++++ mastodon/output.py | 22 ++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/bluesky/input.py b/bluesky/input.py index d87833e..164eae7 100644 --- a/bluesky/input.py +++ b/bluesky/input.py @@ -14,6 +14,7 @@ from bluesky.info import SERVICE, BlueskyService, validate_and_transform from bluesky.richtext import richtext_to_tokens from cross.attachments import ( Attachment, + ExternalEmbedAttachment, LabelsAttachment, LanguagesAttachment, MediaAttachment, @@ -120,6 +121,15 @@ class BlueskyBaseInputService(BlueskyService, InputService, ABC): ) if embed.get("media"): return handle_embeds(embed["media"]) + case "app.bsky.embed.external": + external = embed["external"] + attachments.append( + ExternalEmbedAttachment( + uri=external["uri"], + title=external["title"], + desc=external["description"], + ) + ) case "app.bsky.embed.images": for image in embed["images"]: blob_cid = image["image"]["ref"]["$link"] diff --git a/cross/attachments.py b/cross/attachments.py index 2a1e426..902ef1a 100644 --- a/cross/attachments.py +++ b/cross/attachments.py @@ -37,3 +37,10 @@ class MediaAttachment(Attachment): class QuoteAttachment(Attachment): quoted_id: str quoted_user: str + + +@dataclass(kw_only=True) +class ExternalEmbedAttachment(Attachment): + uri: str + title: str | None + desc: str | None diff --git a/mastodon/output.py b/mastodon/output.py index fde5088..15593a3 100644 --- a/mastodon/output.py +++ b/mastodon/output.py @@ -6,6 +6,7 @@ import httpx import misskey.mfm as mfm from cross.attachments import ( + ExternalEmbedAttachment, LanguagesAttachment, MediaAttachment, QuoteAttachment, @@ -313,6 +314,27 @@ class MastodonOutputService(MastodonService, OutputService): ) ) + # mastodon creates embeds itself, unlike bluesky + # if a bsky post has an embed that's not linked in the text, + # add the embed to the post text. + external_embed = post.attachments.get(ExternalEmbedAttachment) + if external_embed: + add_embed: bool = True + + for tk in post_tokens: + if isinstance(tk, LinkToken) and tk.href == external_embed.uri: + add_embed = False + break + + if add_embed: + if post_tokens: + post_tokens.append(TextToken(text="\n\n")) + post_tokens.append( + LinkToken( + href=external_embed.uri, label=external_embed.title or None + ) + ) + lang = "en" langs = post.attachments.get(LanguagesAttachment) if langs and langs.langs: -- 2.51.2