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) {
 | 
					async function blueskyQuoteEmbed(quote) {
 | 
				
			||||||
  const embeds = [];
 | 
					  const images = [];
 | 
				
			||||||
  const videos = [];
 | 
					  const videos = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let hidden = false;
 | 
					  let hidden = false;
 | 
				
			||||||
| 
						 | 
					@ -341,76 +341,36 @@ async function blueskyQuoteEmbed(quote) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const mainEmbed = {
 | 
					  const components = [];
 | 
				
			||||||
    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: {
 | 
					 | 
				
			||||||
      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 header = {
 | 
				
			||||||
    const handle = quote.author.handle.replace(".ap.brid.gy", "");
 | 
					    type: 9,
 | 
				
			||||||
    const split = handle.split(".");
 | 
					    components: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
    const username = split.shift();
 | 
					        type: 10,
 | 
				
			||||||
    const domain = split.join(".");
 | 
					        content: `### <:i:1308640087759654922> Quoted Post\n## ${quote.author.displayName}\n[@${
 | 
				
			||||||
    const authorUrl = `https://${domain}/users/${username}`;
 | 
					          quote.author.handle
 | 
				
			||||||
 | 
					        }](https://bsky.app/profile/${quote.author.did})\n${
 | 
				
			||||||
    const authorData = await signedFetch(authorUrl, {
 | 
					          quote.value.facets?.length ?? 0 > 0
 | 
				
			||||||
      headers: {
 | 
					            ? processBlueskyFacets(quote.value.text, quote.value.facets)
 | 
				
			||||||
        "User-Agent": FRIENDLY_USERAGENT,
 | 
					            : quote.value.text
 | 
				
			||||||
        Accept: "application/activity+json",
 | 
					        }`.trim(),
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
    })
 | 
					    ],
 | 
				
			||||||
      .then((res) => res.json())
 | 
					    accessory: {
 | 
				
			||||||
      .catch((err) => {
 | 
					      type: 11,
 | 
				
			||||||
        logger.error("fedimbed", `Failed to get author for "${authorUrl}": ${err}`);
 | 
					      media: {
 | 
				
			||||||
      });
 | 
					        url: quote.author.avatar,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
    if (authorData) {
 | 
					    },
 | 
				
			||||||
      const platform = (await resolvePlatform(authorUrl)) ?? "<no nodeinfo>";
 | 
					  };
 | 
				
			||||||
      let color = PLATFORM_COLORS[platform.toLowerCase()];
 | 
					  components.push(header);
 | 
				
			||||||
      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);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (quote.embeds?.[0]) {
 | 
					  if (quote.embeds?.[0]) {
 | 
				
			||||||
    const embed = quote.embeds[0];
 | 
					    const embed = quote.embeds[0];
 | 
				
			||||||
    switch (embed.$type) {
 | 
					    switch (embed.$type) {
 | 
				
			||||||
      case "app.bsky.embed.images#view": {
 | 
					      case "app.bsky.embed.images#view": {
 | 
				
			||||||
        embeds.push(
 | 
					        images.push(...embed.images.map((image) => ({media: {url: image.fullsize}, description: image.alt})));
 | 
				
			||||||
          ...embed.images.map((image) => ({...mainEmbed, image: {url: image.fullsize, description: image.alt}}))
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      case "app.bsky.embed.video#view": {
 | 
					      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 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 videoUrl = `${domain}/xrpc/com.atproto.sync.getBlob?did=${quote.author.did}&cid=${embed.cid}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const contentType = await fetch(videoUrl, {
 | 
					        videos.push({media: {url: videoUrl}, description: embed.alt});
 | 
				
			||||||
          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})`}]});
 | 
					 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      case "app.bsky.embed.recordWithMedia#view": {
 | 
					      case "app.bsky.embed.recordWithMedia#view": {
 | 
				
			||||||
        if (embed.media.$type === "app.bsky.embed.images#view") {
 | 
					        if (embed.media.$type === "app.bsky.embed.images#view") {
 | 
				
			||||||
          embeds.push(
 | 
					          images.push(...embed.media.images.map((image) => ({media: {url: image.fullsize}, description: image.alt})));
 | 
				
			||||||
            ...embed.media.images.map((image) => ({...mainEmbed, image: {url: image.fullsize, description: image.alt}}))
 | 
					 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
        } else if (embed.media.$type === "app.bsky.embed.video#view") {
 | 
					        } 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 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 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 videoUrl = `${domain}/xrpc/com.atproto.sync.getBlob?did=${quote.author.did}&cid=${embed.media.cid}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          const contentType = await fetch(videoUrl, {
 | 
					          videos.push({media: {url: videoUrl}, description: embed.alt});
 | 
				
			||||||
            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})`}]});
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -452,22 +398,37 @@ async function blueskyQuoteEmbed(quote) {
 | 
				
			||||||
          const url = new URL(embed.external.uri);
 | 
					          const url = new URL(embed.external.uri);
 | 
				
			||||||
          url.searchParams.delete("hh");
 | 
					          url.searchParams.delete("hh");
 | 
				
			||||||
          url.searchParams.delete("ww");
 | 
					          url.searchParams.delete("ww");
 | 
				
			||||||
          embeds.push({...mainEmbed, image: {url: url.toString()}});
 | 
					          images.push({media: {url: url.toString()}});
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          embeds.push(mainEmbed);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        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) {
 | 
					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 = [];
 | 
					  const warnings = [];
 | 
				
			||||||
  if (hidden) {
 | 
					  if (hidden) {
 | 
				
			||||||
    warnings.push(":warning: Post marked as 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 = {
 | 
					  const warningText = {
 | 
				
			||||||
    type: 10,
 | 
					    type: 10,
 | 
				
			||||||
    content: `## ${warnings.join("\n## ")}`,
 | 
					    content: `## ${warnings.join("\n## ")}`,
 | 
				
			||||||
| 
						 | 
					@ -595,169 +621,9 @@ async function bluesky(msg, url, spoiler = false) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const footer = {
 | 
					  const footer = {
 | 
				
			||||||
    type: 10,
 | 
					    type: 10,
 | 
				
			||||||
    content: `${getStatsBluesky(post)}\n-# Bluesky \u2022 <t:${Math.floor(
 | 
					    content: `${getStatsBluesky(post)}\n<t:${Math.floor(new Date(post.record.createdAt).getTime() / 1000)}:F>`,
 | 
				
			||||||
      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) {
 | 
					  if (images.length > 0) {
 | 
				
			||||||
    container.components.push({
 | 
					    container.components.push({
 | 
				
			||||||
      type: 12,
 | 
					      type: 12,
 | 
				
			||||||
| 
						 | 
					@ -774,6 +640,22 @@ async function bluesky(msg, url, spoiler = false) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (quoteOnly && !hasQuote) return {};
 | 
					  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 {
 | 
					  return {
 | 
				
			||||||
    response: {
 | 
					    response: {
 | 
				
			||||||
      flags: 1 << 15,
 | 
					      flags: 1 << 15,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue