fedimbed.bluesky: finish quotes
This commit is contained in:
parent
19b1bdcbbe
commit
3c1b2c2ec2
1 changed files with 139 additions and 257 deletions
|
@ -317,7 +317,7 @@ function getStatsBluesky(post) {
|
|||
}
|
||||
|
||||
async function blueskyQuoteEmbed(quote) {
|
||||
const embeds = [];
|
||||
const images = [];
|
||||
const videos = [];
|
||||
|
||||
let hidden = false;
|
||||
|
@ -341,76 +341,36 @@ async function blueskyQuoteEmbed(quote) {
|
|||
}
|
||||
}
|
||||
|
||||
const mainEmbed = {
|
||||
color: PLATFORM_COLORS.bluesky,
|
||||
url: `https://bsky.app/profile/${quote.author.handle}/post/${quote.uri.substring(quote.uri.lastIndexOf("/") + 1)}`,
|
||||
author: {name: "Quoted Post", icon_url: "https://cdn.discordapp.com/emojis/1308640087759654922.png"},
|
||||
title: `${quote.author.displayName} (@${quote.author.handle})`,
|
||||
thumbnail: {
|
||||
const components = [];
|
||||
|
||||
const header = {
|
||||
type: 9,
|
||||
components: [
|
||||
{
|
||||
type: 10,
|
||||
content: `### <:i:1308640087759654922> Quoted Post\n## ${quote.author.displayName}\n[@${
|
||||
quote.author.handle
|
||||
}](https://bsky.app/profile/${quote.author.did})\n${
|
||||
quote.value.facets?.length ?? 0 > 0
|
||||
? processBlueskyFacets(quote.value.text, quote.value.facets)
|
||||
: quote.value.text
|
||||
}`.trim(),
|
||||
},
|
||||
],
|
||||
accessory: {
|
||||
type: 11,
|
||||
media: {
|
||||
url: quote.author.avatar,
|
||||
},
|
||||
description: quote.value.text,
|
||||
footer: {
|
||||
text: `${getStatsBluesky(quote)}\nBluesky`,
|
||||
icon_url: "https://bsky.app/static/apple-touch-icon.png",
|
||||
},
|
||||
timestamp: quote.value.createdAt,
|
||||
};
|
||||
|
||||
/*if (quote.author.handle.endsWith(".ap.brid.gy")) {
|
||||
const handle = quote.author.handle.replace(".ap.brid.gy", "");
|
||||
const split = handle.split(".");
|
||||
|
||||
const username = split.shift();
|
||||
const domain = split.join(".");
|
||||
const authorUrl = `https://${domain}/users/${username}`;
|
||||
|
||||
const authorData = await signedFetch(authorUrl, {
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
Accept: "application/activity+json",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.catch((err) => {
|
||||
logger.error("fedimbed", `Failed to get author for "${authorUrl}": ${err}`);
|
||||
});
|
||||
|
||||
if (authorData) {
|
||||
const platform = (await resolvePlatform(authorUrl)) ?? "<no nodeinfo>";
|
||||
let color = PLATFORM_COLORS[platform.toLowerCase()];
|
||||
let platformName = normalizePlatform(platform);
|
||||
|
||||
const crawled = await getCrawledData(authorUrl, color, platformName);
|
||||
if (!color && crawled?.color) {
|
||||
color = crawled.color;
|
||||
}
|
||||
if (crawled?.platformName) {
|
||||
platformName = crawled.platformName;
|
||||
}
|
||||
platformName += " [via Bluesky via Bridgy]";
|
||||
|
||||
mainEmbed.footer = {
|
||||
text: platformName,
|
||||
icon_url: crawled?.icon,
|
||||
};
|
||||
mainEmbed.title = `${authorData.name} (${authorData.preferredUsername}@${domain})`;
|
||||
mainEmbed.color = color;
|
||||
mainEmbed.thumbnail.url = authorData?.icon?.url ?? quote.author.avatar;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (quote.value.facets?.length > 0) {
|
||||
mainEmbed.description = processBlueskyFacets(mainEmbed.description, quote.value.facets);
|
||||
}
|
||||
components.push(header);
|
||||
|
||||
if (quote.embeds?.[0]) {
|
||||
const embed = quote.embeds[0];
|
||||
switch (embed.$type) {
|
||||
case "app.bsky.embed.images#view": {
|
||||
embeds.push(
|
||||
...embed.images.map((image) => ({...mainEmbed, image: {url: image.fullsize, description: image.alt}}))
|
||||
);
|
||||
images.push(...embed.images.map((image) => ({media: {url: image.fullsize}, description: image.alt})));
|
||||
break;
|
||||
}
|
||||
case "app.bsky.embed.video#view": {
|
||||
|
@ -418,32 +378,18 @@ async function blueskyQuoteEmbed(quote) {
|
|||
const domain = lookup.service.find((service) => service.id === "#atproto_pds").serviceEndpoint;
|
||||
const videoUrl = `${domain}/xrpc/com.atproto.sync.getBlob?did=${quote.author.did}&cid=${embed.cid}`;
|
||||
|
||||
const contentType = await fetch(videoUrl, {
|
||||
method: "HEAD",
|
||||
}).then((res) => res.headers.get("Content-Type"));
|
||||
|
||||
videos.push({url: videoUrl, desc: embed.alt, type: contentType});
|
||||
|
||||
embeds.push({...mainEmbed, fields: [{name: "\u200b", value: `[Video Link](${videoUrl})`}]});
|
||||
videos.push({media: {url: videoUrl}, description: embed.alt});
|
||||
break;
|
||||
}
|
||||
case "app.bsky.embed.recordWithMedia#view": {
|
||||
if (embed.media.$type === "app.bsky.embed.images#view") {
|
||||
embeds.push(
|
||||
...embed.media.images.map((image) => ({...mainEmbed, image: {url: image.fullsize, description: image.alt}}))
|
||||
);
|
||||
images.push(...embed.media.images.map((image) => ({media: {url: image.fullsize}, description: image.alt})));
|
||||
} else if (embed.media.$type === "app.bsky.embed.video#view") {
|
||||
const lookup = await fetch(`https://plc.directory/${quote.author.did}`).then((res) => res.json());
|
||||
const domain = lookup.service.find((service) => service.id === "#atproto_pds").serviceEndpoint;
|
||||
const videoUrl = `${domain}/xrpc/com.atproto.sync.getBlob?did=${quote.author.did}&cid=${embed.media.cid}`;
|
||||
|
||||
const contentType = await fetch(videoUrl, {
|
||||
method: "HEAD",
|
||||
}).then((res) => res.headers.get("Content-Type"));
|
||||
|
||||
videos.push({url: videoUrl, desc: embed.alt, type: contentType});
|
||||
|
||||
embeds.push({...mainEmbed, fields: [{name: "\u200b", value: `[Video Link](${videoUrl})`}]});
|
||||
videos.push({media: {url: videoUrl}, description: embed.alt});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -452,22 +398,37 @@ async function blueskyQuoteEmbed(quote) {
|
|||
const url = new URL(embed.external.uri);
|
||||
url.searchParams.delete("hh");
|
||||
url.searchParams.delete("ww");
|
||||
embeds.push({...mainEmbed, image: {url: url.toString()}});
|
||||
} else {
|
||||
embeds.push(mainEmbed);
|
||||
images.push({media: {url: url.toString()}});
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
embeds.push(mainEmbed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
embeds.push(mainEmbed);
|
||||
}
|
||||
|
||||
return {embeds, videos, adult, hidden, spoiler, tags};
|
||||
const footer = {
|
||||
type: 10,
|
||||
content: `${getStatsBluesky(quote)}\n<t:${Math.floor(new Date(quote.value.createdAt).getTime() / 1000)}:F>`,
|
||||
};
|
||||
|
||||
if (images.length > 0) {
|
||||
components.push({
|
||||
type: 12,
|
||||
items: images,
|
||||
});
|
||||
}
|
||||
for (const video of videos) {
|
||||
components.push({
|
||||
type: 12,
|
||||
items: [video],
|
||||
});
|
||||
}
|
||||
components.push(footer);
|
||||
|
||||
const url = `https://bsky.app/profile/${quote.author.did}/post/${quote.uri.substring(
|
||||
quote.uri.lastIndexOf("/") + 1
|
||||
)}`;
|
||||
|
||||
return {components, url, adult, hidden, spoiler, tags};
|
||||
}
|
||||
|
||||
async function bluesky(msg, url, spoiler = false) {
|
||||
|
@ -529,6 +490,76 @@ async function bluesky(msg, url, spoiler = false) {
|
|||
}
|
||||
}
|
||||
|
||||
const videos = [];
|
||||
const images = [];
|
||||
let quoteData;
|
||||
|
||||
if (post.embed) {
|
||||
switch (post.embed.$type) {
|
||||
case "app.bsky.embed.images#view": {
|
||||
images.push(post.embed.images.map((image) => ({media: {url: image.fullsize}, description: image.alt})));
|
||||
break;
|
||||
}
|
||||
case "app.bsky.embed.video#view": {
|
||||
const lookup = await fetch(`https://plc.directory/${post.author.did}`).then((res) => res.json());
|
||||
const domain = lookup.service.find((service) => service.id === "#atproto_pds").serviceEndpoint;
|
||||
const videoUrl = `${domain}/xrpc/com.atproto.sync.getBlob?did=${post.author.did}&cid=${post.embed.cid}`;
|
||||
|
||||
videos.push({media: {url: videoUrl}, description: post.embed.alt});
|
||||
break;
|
||||
}
|
||||
case "app.bsky.embed.record#view": {
|
||||
hasQuote = true;
|
||||
const quote = post.embed.record;
|
||||
quoteData = await blueskyQuoteEmbed(quote);
|
||||
|
||||
if (quoteData.adult) adult = true;
|
||||
if (quoteData.hidden) hidden = true;
|
||||
if (quoteData.spoiler) spoiler = true;
|
||||
if (quoteData.tags.length > 0) tags.push(...quoteData.tags);
|
||||
|
||||
break;
|
||||
}
|
||||
case "app.bsky.embed.recordWithMedia#view": {
|
||||
hasQuote = true;
|
||||
|
||||
if (post.embed.media.$type === "app.bsky.embed.images#view") {
|
||||
images.push(post.embed.media.images.map((image) => ({media: {url: image.fullsize}, description: image.alt})));
|
||||
} else if (post.embed.media.$type === "app.bsky.embed.video#view") {
|
||||
const lookup = await fetch(`https://plc.directory/${post.author.did}`).then((res) => res.json());
|
||||
const domain = lookup.service.find((service) => service.id === "#atproto_pds").serviceEndpoint;
|
||||
const videoUrl = `${domain}/xrpc/com.atproto.sync.getBlob?did=${post.author.did}&cid=${post.embed.media.cid}`;
|
||||
|
||||
videos.push({media: {url: videoUrl}, description: post.embed.alt});
|
||||
} else if (post.embed.media.$type === "app.bsky.embed.external#view") {
|
||||
if (post.embed.media.external.uri.includes("tenor.com")) {
|
||||
const url = new URL(post.embed.media.external.uri);
|
||||
url.searchParams.delete("hh");
|
||||
url.searchParams.delete("ww");
|
||||
}
|
||||
}
|
||||
|
||||
const quoteData = await blueskyQuoteEmbed(post.embed.record.record);
|
||||
|
||||
if (quoteData.adult) adult = true;
|
||||
if (quoteData.hidden) hidden = true;
|
||||
if (quoteData.spoiler) spoiler = true;
|
||||
if (quoteData.tags.length > 0) tags.push(...quoteData.tags);
|
||||
|
||||
break;
|
||||
}
|
||||
case "app.bsky.embed.external#view": {
|
||||
if (post.embed.external.uri.includes("tenor.com")) {
|
||||
const url = new URL(post.embed.external.uri);
|
||||
url.searchParams.delete("hh");
|
||||
url.searchParams.delete("ww");
|
||||
images.push({media: {url: url.toString()}});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const warnings = [];
|
||||
if (hidden) {
|
||||
warnings.push(":warning: Post marked as hidden");
|
||||
|
@ -545,11 +576,6 @@ async function bluesky(msg, url, spoiler = false) {
|
|||
}
|
||||
}
|
||||
|
||||
const videos = [];
|
||||
const images = [];
|
||||
//const embeds = [];
|
||||
//let sendWait = false;
|
||||
|
||||
const warningText = {
|
||||
type: 10,
|
||||
content: `## ${warnings.join("\n## ")}`,
|
||||
|
@ -595,169 +621,9 @@ async function bluesky(msg, url, spoiler = false) {
|
|||
|
||||
const footer = {
|
||||
type: 10,
|
||||
content: `${getStatsBluesky(post)}\n-# Bluesky \u2022 <t:${Math.floor(
|
||||
new Date(post.record.createdAt).getTime() / 1000
|
||||
)}:F>`,
|
||||
content: `${getStatsBluesky(post)}\n<t:${Math.floor(new Date(post.record.createdAt).getTime() / 1000)}:F>`,
|
||||
};
|
||||
|
||||
/*if (post.author.handle.endsWith(".ap.brid.gy")) {
|
||||
const handle = post.author.handle.replace(".ap.brid.gy", "");
|
||||
const split = handle.split(".");
|
||||
|
||||
const username = split.shift();
|
||||
const domain = split.join(".");
|
||||
const authorUrl = `https://${domain}/@${username}`;
|
||||
|
||||
const authorData = await signedFetch(authorUrl, {
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
Accept: "application/activity+json",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.catch((err) => {
|
||||
logger.error("fedimbed", `Failed to get author for "${authorUrl}": ${err}`);
|
||||
});
|
||||
|
||||
if (authorData) {
|
||||
const platform = (await resolvePlatform(authorUrl)) ?? "<no nodeinfo>";
|
||||
let color = PLATFORM_COLORS[platform];
|
||||
let platformName = normalizePlatform(platform);
|
||||
|
||||
const crawled = await getCrawledData(authorUrl, color, platformName);
|
||||
if (!color && crawled?.color) {
|
||||
color = crawled.color;
|
||||
}
|
||||
if (crawled?.platformName) {
|
||||
platformName = crawled.platformName;
|
||||
}
|
||||
platformName += " [via Bluesky via Bridgy]";
|
||||
|
||||
mainEmbed.footer = {
|
||||
text: platformName,
|
||||
icon_url: crawled?.icon,
|
||||
};
|
||||
mainEmbed.title = `${authorData.name} (${authorData.preferredUsername}@${domain})`;
|
||||
mainEmbed.color = color;
|
||||
mainEmbed.thumbnail.url = authorData?.icon?.url ?? post.author.avatar;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (post.embed) {
|
||||
switch (post.embed.$type) {
|
||||
case "app.bsky.embed.images#view": {
|
||||
images.push(post.embed.images.map((image) => ({media: {url: image.fullsize}, description: image.alt})));
|
||||
break;
|
||||
}
|
||||
case "app.bsky.embed.video#view": {
|
||||
const lookup = await fetch(`https://plc.directory/${post.author.did}`).then((res) => res.json());
|
||||
const domain = lookup.service.find((service) => service.id === "#atproto_pds").serviceEndpoint;
|
||||
const videoUrl = `${domain}/xrpc/com.atproto.sync.getBlob?did=${post.author.did}&cid=${post.embed.cid}`;
|
||||
|
||||
videos.push({media: {url: videoUrl}, description: post.embed.alt});
|
||||
break;
|
||||
}
|
||||
case "app.bsky.embed.record#view": {
|
||||
hasQuote = true;
|
||||
const quote = post.embed.record;
|
||||
const quoteData = await blueskyQuoteEmbed(quote);
|
||||
|
||||
if (quoteData.videos.length > 0) videos.push(...quoteData.videos);
|
||||
|
||||
//embeds.push(mainEmbed, ...quoteData.embeds);
|
||||
|
||||
if (quoteData.adult) adult = true;
|
||||
if (quoteData.hidden) hidden = true;
|
||||
if (quoteData.spoiler) spoiler = true;
|
||||
if (quoteData.tags.length > 0) tags.push(...quoteData.tags);
|
||||
|
||||
break;
|
||||
}
|
||||
case "app.bsky.embed.recordWithMedia#view": {
|
||||
//hasQuote = true;
|
||||
|
||||
if (post.embed.media.$type === "app.bsky.embed.images#view") {
|
||||
images.push(post.embed.media.images.map((image) => ({media: {url: image.fullsize}, description: image.alt})));
|
||||
} else if (post.embed.media.$type === "app.bsky.embed.video#view") {
|
||||
const lookup = await fetch(`https://plc.directory/${post.author.did}`).then((res) => res.json());
|
||||
const domain = lookup.service.find((service) => service.id === "#atproto_pds").serviceEndpoint;
|
||||
const videoUrl = `${domain}/xrpc/com.atproto.sync.getBlob?did=${post.author.did}&cid=${post.embed.media.cid}`;
|
||||
|
||||
videos.push({media: {url: videoUrl}, description: post.embed.alt});
|
||||
|
||||
//embeds.push({...mainEmbed, fields: [{name: "\u200b", value: `[Video Link](${videoUrl})`}]});
|
||||
} else if (post.embed.media.$type === "app.bsky.embed.external#view") {
|
||||
if (post.embed.media.external.uri.includes("tenor.com")) {
|
||||
const url = new URL(post.embed.media.external.uri);
|
||||
url.searchParams.delete("hh");
|
||||
url.searchParams.delete("ww");
|
||||
//embeds.push({...mainEmbed, image: {url: url.toString()}});
|
||||
}
|
||||
}
|
||||
|
||||
const quoteData = await blueskyQuoteEmbed(post.embed.record.record);
|
||||
if (quoteData.videos.length > 0) videos.push(...quoteData.videos);
|
||||
//embeds.push(...quoteData.embeds);
|
||||
|
||||
if (quoteData.adult) adult = true;
|
||||
if (quoteData.hidden) hidden = true;
|
||||
if (quoteData.spoiler) spoiler = true;
|
||||
if (quoteData.tags.length > 0) tags.push(...quoteData.tags);
|
||||
|
||||
break;
|
||||
}
|
||||
case "app.bsky.embed.external#view": {
|
||||
if (post.embed.external.uri.includes("tenor.com")) {
|
||||
const url = new URL(post.embed.external.uri);
|
||||
url.searchParams.delete("hh");
|
||||
url.searchParams.delete("ww");
|
||||
images.push({media: {url: url.toString()}});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*if (videos.length > 0) {
|
||||
sendWait = true;
|
||||
if (msg instanceof Message) await msg.addReaction("\uD83D\uDCE4");
|
||||
}
|
||||
|
||||
const files = [];
|
||||
if (videos.length > 0) {
|
||||
for (const attachment of videos) {
|
||||
const size = await fetch(attachment.url, {
|
||||
method: "HEAD",
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
},
|
||||
}).then((res) => Number(res.headers.get("Content-Length")));
|
||||
|
||||
let limit = getUploadLimit(guild);
|
||||
if (msg.attachmentSizeLimit != null) limit = msg.attachmentSizeLimit;
|
||||
|
||||
if (size <= limit) {
|
||||
const file = await fetch(attachment.url, {
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
},
|
||||
})
|
||||
.then((res) => res.arrayBuffer())
|
||||
.then((buf) => Buffer.from(buf));
|
||||
|
||||
files.push({
|
||||
filename:
|
||||
(spoiler ? "SPOILER_" : "") +
|
||||
(attachment.type.indexOf("/") > -1
|
||||
? attachment.type.replace("/", ".").replace("quicktime", "mov")
|
||||
: attachment.type + "." + (url.match(/\.([a-z0-9]{3,4})$/)?.[0] ?? "mp4")),
|
||||
file,
|
||||
description: attachment.desc,
|
||||
});
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (images.length > 0) {
|
||||
container.components.push({
|
||||
type: 12,
|
||||
|
@ -774,6 +640,22 @@ async function bluesky(msg, url, spoiler = false) {
|
|||
|
||||
if (quoteOnly && !hasQuote) return {};
|
||||
|
||||
if (quoteData) container.components.push({type: 14}, ...quoteData.components);
|
||||
|
||||
const buttons = {
|
||||
type: 1,
|
||||
components: [
|
||||
{
|
||||
type: 2,
|
||||
style: 5,
|
||||
label: "Post",
|
||||
url,
|
||||
},
|
||||
],
|
||||
};
|
||||
if (quoteData?.url) buttons.components.push({type: 2, style: 5, label: "Quoted Post", url: quoteData.url});
|
||||
container.components.push(buttons);
|
||||
|
||||
return {
|
||||
response: {
|
||||
flags: 1 << 15,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue