diff --git a/src/embed/status.ts b/src/embed/status.ts
index 5076034..96ff371 100644
--- a/src/embed/status.ts
+++ b/src/embed/status.ts
@@ -75,7 +75,7 @@ export const handleStatus = async (
}
/* Catch direct media request (d.fxtwitter.com, or .mp4 / .jpg) */
- if (flags?.direct && tweet.media) {
+ if (flags?.direct && !flags?.textOnly && tweet.media) {
let redirectUrl: string | null = null;
const all = tweet.media.all || [];
// if (tweet.media.videos) {
@@ -98,16 +98,6 @@ export const handleStatus = async (
}
}
- /* Use quote media if there is no media in this Tweet */
- if (!tweet.media && tweet.quote?.media) {
- tweet.media = tweet.quote.media;
- tweet.twitter_card = tweet.quote.twitter_card;
- }
-
- if (flags?.textOnly) {
- tweet.media = undefined;
- }
-
/* At this point, we know we're going to have to create a
regular embed because it's not an API or direct media request */
@@ -121,7 +111,9 @@ export const handleStatus = async (
const headers = [
``,
``,
- ``,
+ ``,
``,
``,
``
@@ -165,92 +157,95 @@ export const handleStatus = async (
console.log('overrideMedia', JSON.stringify(overrideMedia));
- if (overrideMedia) {
- let instructions: ResponseInstructions;
+ if (!flags?.textOnly) {
+ const media = tweet.media || tweet.quote?.media;
+ if (overrideMedia) {
+ let instructions: ResponseInstructions;
- switch (overrideMedia.type) {
- case 'photo':
- /* This Tweet has a photo to render. */
- instructions = renderPhoto(
- {
- tweet: tweet,
- authorText: authorText,
- engagementText: engagementText,
- userAgent: userAgent,
- isOverrideMedia: true
- },
- overrideMedia as APIPhoto
- );
- headers.push(...instructions.addHeaders);
- if (instructions.authorText) {
- authorText = instructions.authorText;
- }
- if (instructions.siteName) {
- siteName = instructions.siteName;
- }
- break;
- case 'video':
- instructions = renderVideo(
- { tweet: tweet, userAgent: userAgent, text: newText, isOverrideMedia: true },
- overrideMedia as APIVideo
- );
- headers.push(...instructions.addHeaders);
- if (instructions.authorText) {
- authorText = instructions.authorText;
- }
- if (instructions.siteName) {
- siteName = instructions.siteName;
- }
- /* This Tweet has a video to render. */
- break;
+ switch (overrideMedia.type) {
+ case 'photo':
+ /* This Tweet has a photo to render. */
+ instructions = renderPhoto(
+ {
+ tweet: tweet,
+ authorText: authorText,
+ engagementText: engagementText,
+ userAgent: userAgent,
+ isOverrideMedia: true
+ },
+ overrideMedia as APIPhoto
+ );
+ headers.push(...instructions.addHeaders);
+ if (instructions.authorText) {
+ authorText = instructions.authorText;
+ }
+ if (instructions.siteName) {
+ siteName = instructions.siteName;
+ }
+ break;
+ case 'video':
+ instructions = renderVideo(
+ { tweet: tweet, userAgent: userAgent, text: newText, isOverrideMedia: true },
+ overrideMedia as APIVideo
+ );
+ headers.push(...instructions.addHeaders);
+ if (instructions.authorText) {
+ authorText = instructions.authorText;
+ }
+ if (instructions.siteName) {
+ siteName = instructions.siteName;
+ }
+ /* This Tweet has a video to render. */
+ break;
+ }
+ } else if (media?.mosaic) {
+ const instructions = renderPhoto(
+ {
+ tweet: tweet,
+ authorText: authorText,
+ engagementText: engagementText,
+ userAgent: userAgent
+ },
+ media.mosaic
+ );
+ headers.push(...instructions.addHeaders);
+ } else if (media?.videos) {
+ const instructions = renderVideo(
+ { tweet: tweet, userAgent: userAgent, text: newText },
+ media.videos[0]
+ );
+ headers.push(...instructions.addHeaders);
+ if (instructions.authorText) {
+ authorText = instructions.authorText;
+ }
+ if (instructions.siteName) {
+ siteName = instructions.siteName;
+ }
+ } else if (media?.photos) {
+ const instructions = renderPhoto(
+ {
+ tweet: tweet,
+ authorText: authorText,
+ engagementText: engagementText,
+ userAgent: userAgent
+ },
+ media.photos[0]
+ );
+ headers.push(...instructions.addHeaders);
+ } else if (media?.external) {
+ const { external } = media;
+ authorText = newText || '';
+ headers.push(
+ ``,
+ ``,
+ ``,
+ ``,
+ ``,
+ ``,
+ ``,
+ ``
+ );
}
- } else if (tweet.media?.mosaic) {
- const instructions = renderPhoto(
- {
- tweet: tweet,
- authorText: authorText,
- engagementText: engagementText,
- userAgent: userAgent
- },
- tweet.media?.mosaic
- );
- headers.push(...instructions.addHeaders);
- } else if (tweet.media?.videos) {
- const instructions = renderVideo(
- { tweet: tweet, userAgent: userAgent, text: newText },
- tweet.media?.videos[0]
- );
- headers.push(...instructions.addHeaders);
- if (instructions.authorText) {
- authorText = instructions.authorText;
- }
- if (instructions.siteName) {
- siteName = instructions.siteName;
- }
- } else if (tweet.media?.photos) {
- const instructions = renderPhoto(
- {
- tweet: tweet,
- authorText: authorText,
- engagementText: engagementText,
- userAgent: userAgent
- },
- tweet.media?.photos[0]
- );
- headers.push(...instructions.addHeaders);
- } else if (tweet.media?.external) {
- const { external } = tweet.media;
- authorText = newText || '';
- headers.push(
- ``,
- ``,
- ``,
- ``,
- ``,
- ``,
- ``,
- ``
- );
}
/* This Tweet contains a poll, so we'll render it */
@@ -292,7 +287,13 @@ export const handleStatus = async (
}
/* If we have no media to display, instead we'll display the user profile picture in the embed */
- if (!tweet.media?.videos && !tweet.media?.photos && !flags?.textOnly) {
+ if (
+ !tweet.media?.videos &&
+ !tweet.media?.photos &&
+ !tweet.quote?.media?.photos &&
+ !tweet.quote?.media?.videos &&
+ !flags?.textOnly
+ ) {
/* Use a slightly higher resolution image for profile pics */
const avatar = tweet.author.avatar_url;
if (!useIV) {
diff --git a/src/render/instantview.ts b/src/render/instantview.ts
index c184cb5..64a982b 100644
--- a/src/render/instantview.ts
+++ b/src/render/instantview.ts
@@ -58,34 +58,50 @@ const htmlifyHashtags = (input: string): string => {
});
};
+function paragraphify(text: string, isQuote = false): string {
+ const tag = isQuote ? 'blockquote' : 'p';
+ return text
+ .split('\n')
+ .map(line => line.trim())
+ .filter(line => line.length > 0)
+ .map(line => `<${tag}>${line}${tag}>`)
+ .join('\n');
+}
+
/* TODO: maybe refactor so all tweets pull from this */
const generateTweet = (tweet: APITweet, isQuote = false): string => {
- let text = sanitizeText(tweet.text).replace(/\n/g, '
');
+ let text = paragraphify(sanitizeText(tweet.text));
text = htmlifyLinks(text);
text = htmlifyHashtags(text);
text = populateUserLinks(tweet, text);
return `
- ${!isQuote ? `
' : ''} ${text} - ${isQuote ? '' : ''} ${generateTweetMedia(tweet)} - ${(!isQuote && tweet.quote) ? generateTweet(tweet.quote, true) : ''} -