From 1c8d475362b808dbc3004e74de64538615764d74 Mon Sep 17 00:00:00 2001 From: Cynthia Foxwell Date: Mon, 11 Nov 2024 11:09:18 -0700 Subject: [PATCH] fedimbed.bluesky: https://tenor.com/view/12766761978490409957 --- src/modules/fedimbed.js | 101 ++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 41 deletions(-) diff --git a/src/modules/fedimbed.js b/src/modules/fedimbed.js index 3184e69..2197d50 100644 --- a/src/modules/fedimbed.js +++ b/src/modules/fedimbed.js @@ -120,6 +120,61 @@ async function signedFetch(url, options) { return await fetch(url, options); } +// https://tenor.com/view/12766761978490409957 +// https://github.com/bluesky-social/atproto/blob/main/packages/api/src/rich-text/unicode.ts +const encoder = new TextEncoder(); +const decoder = new TextDecoder(); +function utf16Slice(utf8, start, end) { + return decoder.decode(utf8.slice(start, end)); +} + +function processBlueskyFacets(str, facets) { + const utf16 = str; + const utf8 = encoder.encode(utf16); + + const splitString = []; + + let start = 0; + for (const facet of facets) { + splitString.push({text: utf16Slice(utf8, start, facet.index.byteStart)}); + + splitString.push({ + text: utf16Slice(utf8, facet.index.byteStart, facet.index.byteEnd), + features: facet.features, + }); + start = facet.index.byteEnd; + } + splitString.push({text: utf16Slice(utf8, start)}); + + for (const part of splitString) { + if (part.features) + for (const feature of part.features) { + switch (feature.$type) { + case "app.bsky.richtext.facet#link": { + if (part.text == feature.uri.replace(/^https?:\/\//, "")) { + part.text = feature.uri; + } else { + part.text = `[${part.text}](${feature.uri})`; + } + break; + } + case "app.bsky.richtext.facet#mention": { + part.text = `[${part.text}](https://bsky.app/profile/${feature.did})`; + break; + } + case "app.bsky.richtext.facet#tag": { + part.text = `[${part.text}](https://bsky.app/hashtag/${feature.tag})`; + break; + } + default: + break; + } + } + } + + return splitString.map((part) => part.text).join(""); +} + async function blueskyQuoteEmbed(quote) { const embeds = []; const videos = []; @@ -139,6 +194,10 @@ async function blueskyQuoteEmbed(quote) { timestamp: quote.value.createdAt, }; + if (quote.value.facets?.length > 0) { + mainEmbed.description = processBlueskyFacets(mainEmbed.description, quote.value.facets); + } + if (quote.embeds?.[0]) { const embed = quote.embeds[0]; switch (embed.$type) { @@ -239,47 +298,7 @@ async function bluesky(msg, url, spoiler = false) { }; if (post.record.facets?.length > 0) { - const splitString = []; - const chars = [...mainEmbed.description]; // emojis... - let start = 0; - for (const facet of post.record.facets) { - splitString.push({text: chars.slice(start, facet.index.byteStart).join("")}); - - splitString.push({ - text: chars.slice(facet.index.byteStart, facet.index.byteEnd).join(""), - features: facet.features, - }); - start = facet.index.byteEnd; - } - splitString.push({text: chars.slice(start).join("")}); - - for (const part of splitString) { - if (part.features) - for (const feature of part.features) { - switch (feature.$type) { - case "app.bsky.richtext.facet#link": { - if (part.text == feature.uri.replace(/^https?:\/\//, "")) { - part.text = feature.uri; - } else { - part.text = `[${part.text}](${feature.uri})`; - } - break; - } - case "app.bsky.richtext.facet#mention": { - part.text = `[${part.text}](https://bsky.app/profile/${feature.did})`; - break; - } - case "app.bsky.richtext.facet#tag": { - part.text = `[${part.text}](https://bsky.app/hashtag/${feature.tag})`; - break; - } - default: - break; - } - } - } - - mainEmbed.description = splitString.map((part) => part.text).join(""); + mainEmbed.description = processBlueskyFacets(mainEmbed.description, post.record.facets); } if (data.thread.parent) {