fedimbed: attempt to components v2 fedi posts
This commit is contained in:
		
							parent
							
								
									15f709ed13
								
							
						
					
					
						commit
						fd98ba3667
					
				
					 1 changed files with 184 additions and 444 deletions
				
			
		| 
						 | 
					@ -1,5 +1,3 @@
 | 
				
			||||||
const {Message} = require("@projectdysnomia/dysnomia");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const fs = require("node:fs");
 | 
					const fs = require("node:fs");
 | 
				
			||||||
const httpSignature = require("@peertube/http-signature");
 | 
					const httpSignature = require("@peertube/http-signature");
 | 
				
			||||||
const {XMLParser} = require("fast-xml-parser");
 | 
					const {XMLParser} = require("fast-xml-parser");
 | 
				
			||||||
| 
						 | 
					@ -11,7 +9,6 @@ const InteractionCommand = require("#lib/interactionCommand.js");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const {Icons} = require("#util/constants.js");
 | 
					const {Icons} = require("#util/constants.js");
 | 
				
			||||||
const {MessageFlags, ApplicationCommandOptionTypes, Permissions} = require("#util/dconstants.js");
 | 
					const {MessageFlags, ApplicationCommandOptionTypes, Permissions} = require("#util/dconstants.js");
 | 
				
			||||||
const {getUploadLimit} = require("#util/misc.js");
 | 
					 | 
				
			||||||
const {htmlToMarkdown} = require("#util/html.js");
 | 
					const {htmlToMarkdown} = require("#util/html.js");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const FRIENDLY_USERAGENT =
 | 
					const FRIENDLY_USERAGENT =
 | 
				
			||||||
| 
						 | 
					@ -715,7 +712,7 @@ async function bluesky(msg, url, spoiler = false) {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    response: {
 | 
					    response: {
 | 
				
			||||||
      flags: 1 << 15,
 | 
					      flags: 1 << 15,
 | 
				
			||||||
      components: [warnings.length > 0 ? warningText : false, container].filter((x) => !!x),
 | 
					      components: [warnings.length > 0 && warningText, container].filter((x) => !!x),
 | 
				
			||||||
      allowedMentions: {
 | 
					      allowedMentions: {
 | 
				
			||||||
        repliedUser: false,
 | 
					        repliedUser: false,
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
| 
						 | 
					@ -910,18 +907,20 @@ async function getStatsAS(post) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const stats = [];
 | 
					  const stats = [];
 | 
				
			||||||
  if (replyCount > 0) stats.push(`\u21a9 ${statsFormatter.format(replyCount)}`);
 | 
					  if (replyCount > 0) stats.push(`${Icons.fedimbed.reply} ${statsFormatter.format(replyCount)}`);
 | 
				
			||||||
  if (post.shares?.totalItems ?? 0 > 0) stats.push(`\ud83d\udd01 ${statsFormatter.format(post.shares.totalItems)}`);
 | 
					  if (post.shares?.totalItems ?? 0 > 0)
 | 
				
			||||||
  if (post.likes?.totalItems ?? 0 > 0) stats.push(`\u2665 ${statsFormatter.format(post.likes.totalItems)}`);
 | 
					    stats.push(`${Icons.fedimbed.repost} ${statsFormatter.format(post.shares.totalItems)}`);
 | 
				
			||||||
 | 
					  if (post.likes?.totalItems ?? 0 > 0)
 | 
				
			||||||
 | 
					    stats.push(`${Icons.fedimbed.like} ${statsFormatter.format(post.likes.totalItems)}`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return stats.join("\u3000");
 | 
					  return stats.join("\u3000");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getStatsMasto(post) {
 | 
					function getStatsMasto(post) {
 | 
				
			||||||
  const stats = [];
 | 
					  const stats = [];
 | 
				
			||||||
  if (post.replies_count > 0) stats.push(`\u21a9 ${statsFormatter.format(post.replies_count)}`);
 | 
					  if (post.replies_count > 0) stats.push(`${Icons.fedimbed.reply} ${statsFormatter.format(post.replies_count)}`);
 | 
				
			||||||
  if (post.reblogs_count > 0) stats.push(`\ud83d\udd01 ${statsFormatter.format(post.reblogs_count)}`);
 | 
					  if (post.reblogs_count > 0) stats.push(`${Icons.fedimbed.repost} ${statsFormatter.format(post.reblogs_count)}`);
 | 
				
			||||||
  if (post.favourites_count > 0) stats.push(`\u2665 ${statsFormatter.format(post.favourites_count)}`);
 | 
					  if (post.favourites_count > 0) stats.push(`${Icons.fedimbed.like} ${statsFormatter.format(post.favourites_count)}`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return stats.join("\u3000");
 | 
					  return stats.join("\u3000");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1061,58 +1060,23 @@ async function processUrl(msg, url, spoiler = false, command = false) {
 | 
				
			||||||
    const attachments = postData.media_attachments ?? postData.files;
 | 
					    const attachments = postData.media_attachments ?? postData.files;
 | 
				
			||||||
    if (attachments) {
 | 
					    if (attachments) {
 | 
				
			||||||
      for (const attachment of attachments) {
 | 
					      for (const attachment of attachments) {
 | 
				
			||||||
        const contentType = await fetch(attachment.url, {
 | 
					        const type = attachment.type?.toLowerCase();
 | 
				
			||||||
          method: "HEAD",
 | 
					 | 
				
			||||||
        }).then((res) => res.headers.get("Content-Type"));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (contentType) {
 | 
					        if (type.startsWith("image")) {
 | 
				
			||||||
          if (contentType.startsWith("image/")) {
 | 
					          images.push({
 | 
				
			||||||
            images.push({
 | 
					            media: {url: attachment.url},
 | 
				
			||||||
              url: attachment.url,
 | 
					            description: attachment.description ?? attachment.comment,
 | 
				
			||||||
              desc: attachment.description ?? attachment.comment,
 | 
					          });
 | 
				
			||||||
              type: contentType,
 | 
					        } else if (type.startsWith("video")) {
 | 
				
			||||||
            });
 | 
					          videos.push({
 | 
				
			||||||
          } else if (contentType.startsWith("video/")) {
 | 
					            media: {url: attachment.url},
 | 
				
			||||||
            videos.push({
 | 
					            description: attachment.description ?? attachment.comment,
 | 
				
			||||||
              url: attachment.url,
 | 
					          });
 | 
				
			||||||
              desc: attachment.description ?? attachment.comment,
 | 
					        } else if (type.startsWith("audio")) {
 | 
				
			||||||
              type: contentType,
 | 
					          audios.push({
 | 
				
			||||||
            });
 | 
					            url: attachment.url,
 | 
				
			||||||
          } else if (contentType.startsWith("audio/")) {
 | 
					            description: attachment.description ?? attachment.comment,
 | 
				
			||||||
            audios.push({
 | 
					          });
 | 
				
			||||||
              url: attachment.url,
 | 
					 | 
				
			||||||
              desc: attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
              type: contentType,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          const type = attachment.type?.toLowerCase();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          const fileType =
 | 
					 | 
				
			||||||
            attachment.pleroma?.mime_type ?? type.indexOf("/") > -1
 | 
					 | 
				
			||||||
              ? type
 | 
					 | 
				
			||||||
              : type +
 | 
					 | 
				
			||||||
                "/" +
 | 
					 | 
				
			||||||
                (url.match(/\.([a-z0-9]{3,4})$/)?.[0] ?? type == "image" ? "png" : type == "video" ? "mp4" : "mpeg");
 | 
					 | 
				
			||||||
          if (type.startsWith("image")) {
 | 
					 | 
				
			||||||
            images.push({
 | 
					 | 
				
			||||||
              url: attachment.url,
 | 
					 | 
				
			||||||
              desc: attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
              type: fileType,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
          } else if (type.startsWith("video")) {
 | 
					 | 
				
			||||||
            videos.push({
 | 
					 | 
				
			||||||
              url: attachment.url,
 | 
					 | 
				
			||||||
              desc: attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
              type: fileType,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
          } else if (type.startsWith("audio")) {
 | 
					 | 
				
			||||||
            audios.push({
 | 
					 | 
				
			||||||
              url: attachment.url,
 | 
					 | 
				
			||||||
              desc: attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
              type: fileType,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -1156,19 +1120,19 @@ async function processUrl(msg, url, spoiler = false, command = false) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (postData.inReplyTo) {
 | 
					    if (postData.inReplyTo) {
 | 
				
			||||||
      contextUrl = postData.inReplyTo;
 | 
					      contextUrl = postData.inReplyTo;
 | 
				
			||||||
      context = "Replying to: ";
 | 
					      context = `-# ${Icons.fedimbed.reply} Replying to: `;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const replyData = await fetchPost(postData.inReplyTo, platform);
 | 
					      const replyData = await fetchPost(postData.inReplyTo, platform);
 | 
				
			||||||
      if (replyData) {
 | 
					      if (replyData) {
 | 
				
			||||||
        if (replyData._fedimbed_mastoapi) {
 | 
					        if (replyData._fedimbed_mastoapi) {
 | 
				
			||||||
          context += `${
 | 
					          context += `[${
 | 
				
			||||||
            replyData.account?.display_name ??
 | 
					            replyData.account?.display_name ??
 | 
				
			||||||
            replyData.account?.username ??
 | 
					            replyData.account?.username ??
 | 
				
			||||||
            replyData.user?.name ??
 | 
					            replyData.user?.name ??
 | 
				
			||||||
            replyData.user?.username
 | 
					            replyData.user?.username
 | 
				
			||||||
          } (@${
 | 
					          } (@${
 | 
				
			||||||
            replyData.account?.fqn ?? `${replyData.account?.username ?? replyData.user?.username}@${urlObj.hostname}`
 | 
					            replyData.account?.fqn ?? `${replyData.account?.username ?? replyData.user?.username}@${urlObj.hostname}`
 | 
				
			||||||
          })`;
 | 
					          })](${contextUrl})`;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          const authorData = await signedFetch(replyData.actor ?? replyData.attributedTo, {
 | 
					          const authorData = await signedFetch(replyData.actor ?? replyData.attributedTo, {
 | 
				
			||||||
            headers: {
 | 
					            headers: {
 | 
				
			||||||
| 
						 | 
					@ -1183,13 +1147,13 @@ async function processUrl(msg, url, spoiler = false, command = false) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          if (authorData) {
 | 
					          if (authorData) {
 | 
				
			||||||
            const authorUrlObj = new URL(authorData.url ?? authorData.id);
 | 
					            const authorUrlObj = new URL(authorData.url ?? authorData.id);
 | 
				
			||||||
            context += `${authorData.name} (${authorData.preferredUsername}@${authorUrlObj.hostname})`;
 | 
					            context += `[${authorData.name} (${authorData.preferredUsername}@${authorUrlObj.hostname})](${contextUrl})`;
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            // bootleg author
 | 
					            // bootleg author
 | 
				
			||||||
            const authorUrl = replyData.actor ?? replyData.attributedTo;
 | 
					            const authorUrl = replyData.actor ?? replyData.attributedTo;
 | 
				
			||||||
            const authorUrlObj = new URL(authorUrl);
 | 
					            const authorUrlObj = new URL(authorUrl);
 | 
				
			||||||
            const name = authorUrlObj.pathname.substring(authorUrlObj.pathname.lastIndexOf("/") + 1);
 | 
					            const name = authorUrlObj.pathname.substring(authorUrlObj.pathname.lastIndexOf("/") + 1);
 | 
				
			||||||
            context += `${name}@${authorUrlObj.hostname}`;
 | 
					            context += `[${name}@${authorUrlObj.hostname}](${authorUrl})`;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
| 
						 | 
					@ -1201,36 +1165,18 @@ async function processUrl(msg, url, spoiler = false, command = false) {
 | 
				
			||||||
      // NB: everyone else except gts doesnt follow the spec (they should be using attachments)
 | 
					      // NB: everyone else except gts doesnt follow the spec (they should be using attachments)
 | 
				
			||||||
      const attachments = Array.isArray(postData.attachment) ? postData.attachment : [postData.attachment];
 | 
					      const attachments = Array.isArray(postData.attachment) ? postData.attachment : [postData.attachment];
 | 
				
			||||||
      for (const attachment of attachments) {
 | 
					      for (const attachment of attachments) {
 | 
				
			||||||
        if (attachment.mediaType) {
 | 
					        if (attachment.url) {
 | 
				
			||||||
          if (attachment.mediaType.startsWith("video/")) {
 | 
					          const type = attachment.type?.toLowerCase();
 | 
				
			||||||
            videos.push({
 | 
					
 | 
				
			||||||
              url: attachment.url,
 | 
					 | 
				
			||||||
              desc: attachment.name ?? attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
              type: attachment.mediaType,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
          } else if (attachment.mediaType.startsWith("image/")) {
 | 
					 | 
				
			||||||
            images.push({
 | 
					 | 
				
			||||||
              url: attachment.url,
 | 
					 | 
				
			||||||
              desc: attachment.name ?? attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
              type: attachment.mediaType,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
          } else if (attachment.mediaType.startsWith("audio/")) {
 | 
					 | 
				
			||||||
            audios.push({
 | 
					 | 
				
			||||||
              url: attachment.url,
 | 
					 | 
				
			||||||
              desc: attachment.name ?? attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
              type: attachment.mediaType,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        } else if (attachment.url) {
 | 
					 | 
				
			||||||
          let attUrl = attachment.url;
 | 
					          let attUrl = attachment.url;
 | 
				
			||||||
          if (Array.isArray(attachment.url)) {
 | 
					          if (Array.isArray(attachment.url)) {
 | 
				
			||||||
            switch (attachment.type) {
 | 
					            switch (type) {
 | 
				
			||||||
              case "Image": {
 | 
					              case "image": {
 | 
				
			||||||
                const newUrl = attachment.url.find((a) => a.mediaType?.startsWith("image/"))?.href;
 | 
					                const newUrl = attachment.url.find((a) => a.mediaType?.startsWith("image/"))?.href;
 | 
				
			||||||
                if (newUrl) attUrl = newUrl;
 | 
					                if (newUrl) attUrl = newUrl;
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
              case "Video": {
 | 
					              case "video": {
 | 
				
			||||||
                const newUrl = attachment.url.find((a) => a.mediaType?.startsWith("video/"))?.href;
 | 
					                const newUrl = attachment.url.find((a) => a.mediaType?.startsWith("video/"))?.href;
 | 
				
			||||||
                if (newUrl) attUrl = newUrl;
 | 
					                if (newUrl) attUrl = newUrl;
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
| 
						 | 
					@ -1240,60 +1186,21 @@ async function processUrl(msg, url, spoiler = false, command = false) {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          let contentType;
 | 
					          if (type.startsWith("image")) {
 | 
				
			||||||
          if (attUrl != null)
 | 
					            images.push({
 | 
				
			||||||
            contentType = await fetch(attUrl, {
 | 
					              media: {url: attUrl},
 | 
				
			||||||
              method: "HEAD",
 | 
					              description: attachment.name ?? attachment.description ?? attachment.comment,
 | 
				
			||||||
            }).then((res) => res.headers.get("Content-Type"));
 | 
					            });
 | 
				
			||||||
 | 
					          } else if (type.startsWith("video")) {
 | 
				
			||||||
          if (contentType) {
 | 
					            videos.push({
 | 
				
			||||||
            if (contentType.startsWith("image/")) {
 | 
					              media: {url: attUrl},
 | 
				
			||||||
              images.push({
 | 
					              description: attachment.name ?? attachment.description ?? attachment.comment,
 | 
				
			||||||
                url: attUrl,
 | 
					            });
 | 
				
			||||||
                desc: attachment.name ?? attachment.description ?? attachment.comment,
 | 
					          } else if (type.startsWith("audio")) {
 | 
				
			||||||
                type: contentType,
 | 
					            audios.push({
 | 
				
			||||||
              });
 | 
					              url: attUrl,
 | 
				
			||||||
            } else if (contentType.startsWith("video/")) {
 | 
					              description: attachment.name ?? attachment.description ?? attachment.comment,
 | 
				
			||||||
              videos.push({
 | 
					            });
 | 
				
			||||||
                url: attUrl,
 | 
					 | 
				
			||||||
                desc: attachment.name ?? attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
                type: contentType,
 | 
					 | 
				
			||||||
              });
 | 
					 | 
				
			||||||
            } else if (contentType.startsWith("audio/")) {
 | 
					 | 
				
			||||||
              audios.push({
 | 
					 | 
				
			||||||
                url: attUrl,
 | 
					 | 
				
			||||||
                desc: attachment.name ?? attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
                type: contentType,
 | 
					 | 
				
			||||||
              });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            const type = attachment.type?.toLowerCase();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const fileType =
 | 
					 | 
				
			||||||
              type.indexOf("/") > -1
 | 
					 | 
				
			||||||
                ? type
 | 
					 | 
				
			||||||
                : type +
 | 
					 | 
				
			||||||
                  "/" +
 | 
					 | 
				
			||||||
                  (url.match(/\.([a-z0-9]{3,4})$/)?.[0] ?? type == "image" ? "png" : type == "video" ? "mp4" : "mpeg");
 | 
					 | 
				
			||||||
            if (type.startsWith("image")) {
 | 
					 | 
				
			||||||
              images.push({
 | 
					 | 
				
			||||||
                url: attUrl,
 | 
					 | 
				
			||||||
                desc: attachment.name ?? attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
                type: fileType,
 | 
					 | 
				
			||||||
              });
 | 
					 | 
				
			||||||
            } else if (type.startsWith("video")) {
 | 
					 | 
				
			||||||
              videos.push({
 | 
					 | 
				
			||||||
                url: attUrl,
 | 
					 | 
				
			||||||
                desc: attachment.name ?? attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
                type: fileType,
 | 
					 | 
				
			||||||
              });
 | 
					 | 
				
			||||||
            } else if (type.startsWith("audio")) {
 | 
					 | 
				
			||||||
              audios.push({
 | 
					 | 
				
			||||||
                url: attUrl,
 | 
					 | 
				
			||||||
                desc: attachment.name ?? attachment.description ?? attachment.comment,
 | 
					 | 
				
			||||||
                type: fileType,
 | 
					 | 
				
			||||||
              });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          logger.warn("fedimbed", `Unhandled attachment structure! ${JSON.stringify(attachment)}`);
 | 
					          logger.warn("fedimbed", `Unhandled attachment structure! ${JSON.stringify(attachment)}`);
 | 
				
			||||||
| 
						 | 
					@ -1306,14 +1213,8 @@ async function processUrl(msg, url, spoiler = false, command = false) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (postData.image?.url) {
 | 
					    if (postData.image?.url) {
 | 
				
			||||||
      const imageUrl = new URL(postData.image.url);
 | 
					 | 
				
			||||||
      const contentType = await fetch(postData.image.url, {
 | 
					 | 
				
			||||||
        method: "HEAD",
 | 
					 | 
				
			||||||
      }).then((res) => res.headers.get("Content-Type"));
 | 
					 | 
				
			||||||
      images.push({
 | 
					      images.push({
 | 
				
			||||||
        url: postData.image.url,
 | 
					        media: {url: postData.image.url},
 | 
				
			||||||
        desc: "",
 | 
					 | 
				
			||||||
        type: contentType ?? "image/" + imageUrl.pathname.substring(imageUrl.pathname.lastIndexOf(".") + 1),
 | 
					 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1328,7 +1229,7 @@ async function processUrl(msg, url, spoiler = false, command = false) {
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
      .then((res) => res.json())
 | 
					      .then((res) => res.json())
 | 
				
			||||||
      .catch((err) => {
 | 
					      .catch((err) => {
 | 
				
			||||||
        /*if (platform !== "cohost")*/ logger.error("fedimbed", `Failed to get author for "${url}": ${err}`);
 | 
					        logger.error("fedimbed", `Failed to get author for "${url}": ${err}`);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (authorData) {
 | 
					    if (authorData) {
 | 
				
			||||||
| 
						 | 
					@ -1394,31 +1295,15 @@ async function processUrl(msg, url, spoiler = false, command = false) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let desc = "";
 | 
					  let desc = "";
 | 
				
			||||||
  let MAX_LENGTH = 3999;
 | 
					  let MAX_LENGTH = 3999;
 | 
				
			||||||
  if ((cw != "" || sensitive) && images.length == 0 && videos.length == 0 && audios.length == 0) {
 | 
					  if (cw != "" || sensitive) {
 | 
				
			||||||
    const ors = content.split("||");
 | 
					    const ors = content.split("||");
 | 
				
			||||||
    desc += `||${content.replaceAll("||", "|\u200b|")}||`;
 | 
					    desc += `||${content.replaceAll("||", "|\u200b|")}||`;
 | 
				
			||||||
    MAX_LENGTH -= ors.length - 1;
 | 
					    MAX_LENGTH -= ors.length - 1;
 | 
				
			||||||
    MAX_LENGTH -= 4;
 | 
					    MAX_LENGTH -= 4;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (cw != "") {
 | 
					 | 
				
			||||||
      desc = "\u26a0 " + cw + "\n\n" + desc;
 | 
					 | 
				
			||||||
      MAX_LENGTH -= 4 - cw.length;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    desc = content;
 | 
					    desc = content;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (desc.length > MAX_LENGTH) {
 | 
					 | 
				
			||||||
    if (desc.endsWith("||")) {
 | 
					 | 
				
			||||||
      desc = desc.substring(0, MAX_LENGTH - 2);
 | 
					 | 
				
			||||||
      desc += "\u2026||";
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      desc = desc.substring(0, MAX_LENGTH) + "\u2026";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  let user = author.name ? `${author.name} (${author.handle})` : author.handle;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const crawled = await getCrawledData(url, color, platformName);
 | 
					  const crawled = await getCrawledData(url, color, platformName);
 | 
				
			||||||
  if (!color && crawled?.color) {
 | 
					  if (!color && crawled?.color) {
 | 
				
			||||||
    color = crawled.color;
 | 
					    color = crawled.color;
 | 
				
			||||||
| 
						 | 
					@ -1429,328 +1314,184 @@ async function processUrl(msg, url, spoiler = false, command = false) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (platformName.includes("Nitter") && platformName.includes(" \u2022 ")) {
 | 
					  if (platformName.includes("Nitter") && platformName.includes(" \u2022 ")) {
 | 
				
			||||||
    const [nn, ns] = platformName.split(" \u2022 ");
 | 
					    const [nn, ns] = platformName.split(" \u2022 ");
 | 
				
			||||||
    stats = ns;
 | 
					    stats = ns
 | 
				
			||||||
 | 
					      .replace("\u21a9", Icons.fedimbed.reply)
 | 
				
			||||||
 | 
					      .replace("\ud83d\udd01", Icons.fedimbed.repost)
 | 
				
			||||||
 | 
					      .replace("\u2198", Icons.fedimbed.quote)
 | 
				
			||||||
 | 
					      .replace("\u2665", Icons.fedimbed.like)
 | 
				
			||||||
 | 
					      .replace("\ud83d\udd16", Icons.fedimbed.bookmark)
 | 
				
			||||||
 | 
					      .replace("\ud83d\udc41", Icons.fedimbed.views)
 | 
				
			||||||
 | 
					      .replaceAll(/ <:i:/g, "\u3000<:i:");
 | 
				
			||||||
    platformName = nn;
 | 
					    platformName = nn;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (platformName == "Nitter") {
 | 
					  if (platformName == "Nitter") {
 | 
				
			||||||
    const newHandle = author.handle.split("@")[0];
 | 
					    const newHandle = author.handle.split("@")[0];
 | 
				
			||||||
    user = `${author.name} (@${newHandle})`;
 | 
					    author.handle = "@" + newHandle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (context) {
 | 
					    if (context) {
 | 
				
			||||||
      const contextHandle = context.match(/\(([^@]+?@.+?)\)/)?.[1];
 | 
					      const contextHandle = context.match(/\(([^@]+?@.+?)\)/)?.[1];
 | 
				
			||||||
      if (contextHandle) {
 | 
					      if (contextHandle) {
 | 
				
			||||||
        const newContextHandle = "@" + contextHandle.split("@")[0];
 | 
					        const newContextHandle = contextHandle.split("@")[0];
 | 
				
			||||||
        context = context.replace(contextHandle, newContextHandle);
 | 
					        context = context.replace(contextHandle, "@" + newContextHandle);
 | 
				
			||||||
 | 
					        context = context.replace(/: (.+?)$/, `: [$1](${contextUrl})`);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const baseEmbed = {
 | 
					  const warningText = {
 | 
				
			||||||
    color,
 | 
					    type: 10,
 | 
				
			||||||
    url,
 | 
					    content: `## ${cw}`,
 | 
				
			||||||
    timestamp,
 | 
					 | 
				
			||||||
    description: desc,
 | 
					 | 
				
			||||||
    title: title ?? user,
 | 
					 | 
				
			||||||
    author: title
 | 
					 | 
				
			||||||
      ? {
 | 
					 | 
				
			||||||
          name: user,
 | 
					 | 
				
			||||||
          url: author.url,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      : context
 | 
					 | 
				
			||||||
      ? {
 | 
					 | 
				
			||||||
          name: context,
 | 
					 | 
				
			||||||
          url: contextUrl,
 | 
					 | 
				
			||||||
          icon_url: "https://cdn.discordapp.com/emojis/1308640078825787412.png",
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      : null,
 | 
					 | 
				
			||||||
    footer: {
 | 
					 | 
				
			||||||
      icon_url: crawled?.icon,
 | 
					 | 
				
			||||||
      text: (stats != null && stats != "" ? stats + "\n" : "") + platformName,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    thumbnail: {
 | 
					 | 
				
			||||||
      url: author.avatar,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    fields: [],
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  if (images.length > 0) {
 | 
					 | 
				
			||||||
    if (images.length > 1) {
 | 
					 | 
				
			||||||
      const links = images.map((attachment, index) => `[Image ${index + 1}](${attachment.url})`).join("\u3000\u3000");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (links.length <= 1024)
 | 
					  const container = {
 | 
				
			||||||
        baseEmbed.fields.push({
 | 
					    type: 17,
 | 
				
			||||||
          name: "Images",
 | 
					    accent_color: color,
 | 
				
			||||||
          value: links,
 | 
					    components: [],
 | 
				
			||||||
          inline: true,
 | 
					    spoiler,
 | 
				
			||||||
        });
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let headerContent = `${author.name ? `## ${author.name}\n` : ""}-# [${author.handle}](${author.url})`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (title) headerContent += "\n### " + title;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  MAX_LENGTH -= headerContent.length + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (desc.length > MAX_LENGTH) {
 | 
				
			||||||
 | 
					    if (desc.endsWith("||")) {
 | 
				
			||||||
 | 
					      desc = desc.substring(0, MAX_LENGTH - 2);
 | 
				
			||||||
 | 
					      desc += "\u2026||";
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      baseEmbed.fields.push({
 | 
					      desc = desc.substring(0, MAX_LENGTH) + "\u2026";
 | 
				
			||||||
        name: "Image",
 | 
					 | 
				
			||||||
        value: `[Click for image](${images[0].url})`,
 | 
					 | 
				
			||||||
        inline: true,
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (videos.length > 0) {
 | 
					 | 
				
			||||||
    if (videos.length > 1) {
 | 
					 | 
				
			||||||
      baseEmbed.fields.push({
 | 
					 | 
				
			||||||
        name: "Videos",
 | 
					 | 
				
			||||||
        value: videos.map((attachment, index) => `[Video ${index + 1}](${attachment.url})`).join("\u3000\u3000"),
 | 
					 | 
				
			||||||
        inline: true,
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      baseEmbed.fields.push({
 | 
					 | 
				
			||||||
        name: "Video",
 | 
					 | 
				
			||||||
        value: `[Click for video](${videos[0].url})`,
 | 
					 | 
				
			||||||
        inline: true,
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (audios.length > 0) {
 | 
					 | 
				
			||||||
    if (audios.length > 1) {
 | 
					 | 
				
			||||||
      baseEmbed.fields.push({
 | 
					 | 
				
			||||||
        name: "Audios",
 | 
					 | 
				
			||||||
        value: audios.map((attachment, index) => `[Audio ${index + 1}](${attachment.url})`).join("\u3000\u3000"),
 | 
					 | 
				
			||||||
        inline: true,
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      baseEmbed.fields.push({
 | 
					 | 
				
			||||||
        name: "Audio",
 | 
					 | 
				
			||||||
        value: `[Click for audio](${audios[0].url})`,
 | 
					 | 
				
			||||||
        inline: true,
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  headerContent += "\n" + desc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const header = [
 | 
				
			||||||
 | 
					    context && {
 | 
				
			||||||
 | 
					      type: 10,
 | 
				
			||||||
 | 
					      content: context,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      type: 9,
 | 
				
			||||||
 | 
					      components: [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          type: 10,
 | 
				
			||||||
 | 
					          content: headerContent,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      accessory: {
 | 
				
			||||||
 | 
					        type: 11,
 | 
				
			||||||
 | 
					        media: {
 | 
				
			||||||
 | 
					          url: author.avatar,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ].filter((x) => !!x);
 | 
				
			||||||
 | 
					  container.components.push(...header);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (poll) {
 | 
					  if (poll) {
 | 
				
			||||||
    const pollTime = poll.end.getTime();
 | 
					    const pollTime = poll.end.getTime();
 | 
				
			||||||
    const now = Date.now();
 | 
					    const now = Date.now();
 | 
				
			||||||
    baseEmbed.fields.push({
 | 
					    container.components.push({
 | 
				
			||||||
      name: "Poll",
 | 
					      type: 10,
 | 
				
			||||||
      value:
 | 
					      content:
 | 
				
			||||||
        poll.options
 | 
					        poll.options
 | 
				
			||||||
          .map((o) => {
 | 
					          .map((o) => {
 | 
				
			||||||
            const percent = o.count / poll.total;
 | 
					            const percent = o.count / poll.total;
 | 
				
			||||||
            const bar = Math.round(percent * 32);
 | 
					            const bar = Math.round(percent * 32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return `**${o.name}** (${numberFormatter.format(o.count)}, ${Math.round(
 | 
					            return `> **${o.name}** (${numberFormatter.format(o.count)}, ${Math.round(
 | 
				
			||||||
              percent * 100
 | 
					              percent * 100
 | 
				
			||||||
            )}%)\n\`${"\u2588".repeat(bar)}${" ".repeat(32 - bar)}\``;
 | 
					            )}%)> \n\`${"\u2588".repeat(bar)}${" ".repeat(32 - bar)}\``;
 | 
				
			||||||
          })
 | 
					          })
 | 
				
			||||||
          .join("\n\n") +
 | 
					          .join("> \n> \n") +
 | 
				
			||||||
        `\n\n${poll.total} votes \u2022 End${pollTime > now ? "s" : "ed"} <t:${Math.floor(pollTime / 1000)}:R>`,
 | 
					        `> \n> \n${poll.total} votes \u2022 End${pollTime > now ? "s" : "ed"} <t:${Math.floor(pollTime / 1000)}:R>`,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let sendWait = false;
 | 
					  const footer = {
 | 
				
			||||||
  if (videos.length > 0 || audios.length > 0 || images.length > 4) {
 | 
					    type: 9,
 | 
				
			||||||
    sendWait = true;
 | 
					    components: [
 | 
				
			||||||
    if (msg instanceof Message) await msg.addReaction("\uD83D\uDCE4");
 | 
					      {
 | 
				
			||||||
 | 
					        type: 10,
 | 
				
			||||||
 | 
					        content: `-# ${stats}\n${platformName} \u2022 <t:${Math.floor(new Date(timestamp).getTime() / 1000)}:F>`,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    accessory: {
 | 
				
			||||||
 | 
					      type: 2,
 | 
				
			||||||
 | 
					      style: 5,
 | 
				
			||||||
 | 
					      label: "View Post",
 | 
				
			||||||
 | 
					      url,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (const image in images) {
 | 
				
			||||||
 | 
					    if (image.description?.length === 0) image.description = null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const embeds = [];
 | 
					 | 
				
			||||||
  const files = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const guild = msg.channel?.guild ?? (msg.guildID ? hf.bot.guilds.get(msg.guildID) : false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  let limit = getUploadLimit(guild);
 | 
					 | 
				
			||||||
  if (msg.attachmentSizeLimit != null) limit = msg.attachmentSizeLimit;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (images.length > 0) {
 | 
					  if (images.length > 0) {
 | 
				
			||||||
    if (images.length <= 4) {
 | 
					    if (images.length > 10) {
 | 
				
			||||||
      for (const attachment of images) {
 | 
					      while (images.length > 10) {
 | 
				
			||||||
        const embed = Object.assign({}, baseEmbed);
 | 
					        container.components.push({
 | 
				
			||||||
        embed.image = {
 | 
					          type: 12,
 | 
				
			||||||
          url: attachment.url,
 | 
					          items: images.splice(0, 10),
 | 
				
			||||||
          description: attachment.desc,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        embeds.push(embed);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    } else if (images.length > 4 && images.length <= 10) {
 | 
					 | 
				
			||||||
      for (const attachment of images) {
 | 
					 | 
				
			||||||
        const size = await fetch(attachment.url, {
 | 
					 | 
				
			||||||
          method: "HEAD",
 | 
					 | 
				
			||||||
          headers: {
 | 
					 | 
				
			||||||
            "User-Agent": FRIENDLY_USERAGENT,
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
        }).then((res) => Number(res.headers.get("Content-Length")));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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:
 | 
					 | 
				
			||||||
              (cw != "" || spoiler ? "SPOILER_" : "") +
 | 
					 | 
				
			||||||
              (attachment.type.indexOf("/") > -1
 | 
					 | 
				
			||||||
                ? attachment.type.replace("/", ".")
 | 
					 | 
				
			||||||
                : attachment.type + "." + (url.match(/\.([a-z0-9]{3,4})$/)?.[0] ?? "png")),
 | 
					 | 
				
			||||||
            file,
 | 
					 | 
				
			||||||
            description: attachment.desc,
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      embeds.push(baseEmbed);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      const ten = images.slice(0, 10);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      for (const attachment of ten) {
 | 
					 | 
				
			||||||
        const size = await fetch(attachment.url, {
 | 
					 | 
				
			||||||
          method: "HEAD",
 | 
					 | 
				
			||||||
          headers: {
 | 
					 | 
				
			||||||
            "User-Agent": FRIENDLY_USERAGENT,
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
        }).then((res) => Number(res.headers.get("Content-Length")));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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:
 | 
					 | 
				
			||||||
              (cw != "" || spoiler ? "SPOILER_" : "") +
 | 
					 | 
				
			||||||
              (attachment.type.indexOf("/") > -1
 | 
					 | 
				
			||||||
                ? attachment.type.replace("/", ".")
 | 
					 | 
				
			||||||
                : attachment.type + "." + (url.match(/\.([a-z0-9]{3,4})$/)?.[0] ?? "png")),
 | 
					 | 
				
			||||||
            file,
 | 
					 | 
				
			||||||
            description: attachment.desc,
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (images.length <= 14) {
 | 
					 | 
				
			||||||
        const fourteen = images.slice(10, 14);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (const attachment of fourteen) {
 | 
					 | 
				
			||||||
          const embed = Object.assign({}, baseEmbed);
 | 
					 | 
				
			||||||
          embed.image = {
 | 
					 | 
				
			||||||
            url: attachment.url,
 | 
					 | 
				
			||||||
            description: attachment.desc,
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
          embeds.push(embed);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      } else if (images.length <= 18) {
 | 
					 | 
				
			||||||
        const fourteen = images.slice(10, 14);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (const attachment of fourteen) {
 | 
					 | 
				
			||||||
          const embed = Object.assign({}, baseEmbed);
 | 
					 | 
				
			||||||
          embed.image = {
 | 
					 | 
				
			||||||
            url: attachment.url,
 | 
					 | 
				
			||||||
            description: attachment.desc,
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
          embeds.push(embed);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const eighteen = images.slice(14, 18);
 | 
					 | 
				
			||||||
        const _embed = {
 | 
					 | 
				
			||||||
          color: baseEmbed.color,
 | 
					 | 
				
			||||||
          url: baseEmbed.url + "?_",
 | 
					 | 
				
			||||||
          title: "Additional Images",
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (const attachment of eighteen) {
 | 
					 | 
				
			||||||
          const embed = Object.assign({}, _embed);
 | 
					 | 
				
			||||||
          embed.image = {
 | 
					 | 
				
			||||||
            url: attachment.url,
 | 
					 | 
				
			||||||
            description: attachment.desc,
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
          embeds.push(embed);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    embeds.push(baseEmbed);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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")));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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:
 | 
					 | 
				
			||||||
            (cw != "" || 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,
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    container.components.push({
 | 
				
			||||||
 | 
					      type: 12,
 | 
				
			||||||
 | 
					      items: images,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  for (const video of videos) {
 | 
				
			||||||
 | 
					    if (video.description?.length === 0) video.description = null;
 | 
				
			||||||
 | 
					    container.components.push({
 | 
				
			||||||
 | 
					      type: 12,
 | 
				
			||||||
 | 
					      items: [video],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (audios.length > 0) {
 | 
					  if (audios.length > 0) {
 | 
				
			||||||
    for (const attachment of audios) {
 | 
					    container.components.push(
 | 
				
			||||||
      const size = await fetch(attachment.url, {
 | 
					      {
 | 
				
			||||||
        method: "HEAD",
 | 
					        type: 10,
 | 
				
			||||||
        headers: {
 | 
					        content: "### Audio Attachments",
 | 
				
			||||||
          "User-Agent": FRIENDLY_USERAGENT,
 | 
					      },
 | 
				
			||||||
        },
 | 
					      {
 | 
				
			||||||
      }).then((res) => Number(res.headers.get("Content-Length")));
 | 
					        type: 1,
 | 
				
			||||||
 | 
					        components: audios.map((a) => ({
 | 
				
			||||||
      if (size <= limit) {
 | 
					          type: 2,
 | 
				
			||||||
        const file = await fetch(attachment.url, {
 | 
					          style: 5,
 | 
				
			||||||
          headers: {
 | 
					          emoji: {name: "silk_sound", id: "1273119755376529418", animated: false},
 | 
				
			||||||
            "User-Agent": FRIENDLY_USERAGENT,
 | 
					          label:
 | 
				
			||||||
          },
 | 
					            a.description?.length > 0
 | 
				
			||||||
        })
 | 
					              ? `"${a.description.length > 78 ? a.description.substring(0, 77) + "\u2026" : a.description}"`
 | 
				
			||||||
          .then((res) => res.arrayBuffer())
 | 
					              : "Audio",
 | 
				
			||||||
          .then((buf) => Buffer.from(buf));
 | 
					          url: a.url,
 | 
				
			||||||
 | 
					        })),
 | 
				
			||||||
        files.push({
 | 
					 | 
				
			||||||
          filename:
 | 
					 | 
				
			||||||
            (cw != "" || spoiler ? "SPOILER_" : "") +
 | 
					 | 
				
			||||||
            (attachment.type.indexOf("/") > -1
 | 
					 | 
				
			||||||
              ? attachment.type.replace("/", ".").replace("mpeg", "mp3").replace("vnd.wave", "wav").replace("x-", "")
 | 
					 | 
				
			||||||
              : attachment.type + "." + (url.match(/\.([a-z0-9]{3,4})$/)?.[0] ?? "mp3")),
 | 
					 | 
				
			||||||
          file,
 | 
					 | 
				
			||||||
          description: attachment.desc,
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  container.components.push(footer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (quoteRes) {
 | 
					  if (quoteRes) {
 | 
				
			||||||
    if (!sendWait && quoteRes.sendWait) sendWait = true;
 | 
					    const quoteComponents = quoteRes.response.components[0].components;
 | 
				
			||||||
    files.push(...quoteRes.response.attachments);
 | 
					    const quoteContext = `-# ${Icons.fedimbed.quote} Quoted Post`;
 | 
				
			||||||
    const quoteEmbed = quoteRes.response.embeds[0];
 | 
					    if (quoteComponents[0].type == 10) {
 | 
				
			||||||
    quoteEmbed.author = {name: "Quoted Post", icon_url: "https://cdn.discordapp.com/emojis/1308640087759654922.png"};
 | 
					      quoteComponents[0].content = quoteContext + "\n" + quoteComponents[0].content;
 | 
				
			||||||
    embeds.push(quoteEmbed);
 | 
					    } else {
 | 
				
			||||||
 | 
					      quoteComponents.splice(0, 0, {type: 10, content: quoteContext});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    container.components.push({type: 14}, ...quoteComponents);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    response: {
 | 
					    response: {
 | 
				
			||||||
      content:
 | 
					      flags: 1 << 15,
 | 
				
			||||||
        cw != "" && (images.length > 0 || videos.length > 0 || audios.length > 0)
 | 
					      components: [cw.length > 0 ? warningText : false, container].filter((x) => !!x),
 | 
				
			||||||
          ? `:warning: ${cw} || ${url} ||`
 | 
					 | 
				
			||||||
          : spoiler
 | 
					 | 
				
			||||||
          ? `|| ${url} ||`
 | 
					 | 
				
			||||||
          : "",
 | 
					 | 
				
			||||||
      embeds,
 | 
					 | 
				
			||||||
      attachments: files,
 | 
					 | 
				
			||||||
      allowedMentions: {
 | 
					      allowedMentions: {
 | 
				
			||||||
        repliedUser: false,
 | 
					        repliedUser: false,
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
| 
						 | 
					@ -1758,7 +1499,6 @@ async function processUrl(msg, url, spoiler = false, command = false) {
 | 
				
			||||||
        messageID: msg.id,
 | 
					        messageID: msg.id,
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    sendWait,
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue