import { Constants } from './constants';
import { handleQuote } from './quote';
import { sanitizeText } from './utils';
import { Strings } from './strings';
import { getAuthorText } from './author';
import { statusAPI } from './api';
export const returnError = (error: string): StatusResponse => {
return {
text: Strings.BASE_HTML.format({
lang: '',
headers: [
``,
``
].join('')
})
};
};
export const handleStatus = async (
status: string,
mediaNumber?: number,
userAgent?: string,
flags?: InputFlags,
language?: string
): Promise => {
console.log('Direct?', flags?.direct);
const api = await statusAPI(status, language);
const tweet = api?.tweet as APITweet;
if (flags?.api) {
return {
response: new Response(JSON.stringify(api), {
headers: { ...Constants.RESPONSE_HEADERS, 'content-type': 'application/json' },
status: api.code
})
};
}
switch (api.code) {
case 401:
return returnError(Strings.ERROR_PRIVATE);
case 404:
return returnError(Strings.ERROR_TWEET_NOT_FOUND);
case 500:
return returnError(Strings.ERROR_API_FAIL);
}
if (flags?.direct && tweet.media) {
let redirectUrl: string | null = null;
if (tweet.media.video) {
redirectUrl = tweet.media.video.url;
} else if (tweet.media.photos) {
const photos = tweet.media.photos;
redirectUrl = (photos[(mediaNumber || 1) - 1] || photos[0]).url;
}
if (redirectUrl) {
return { response: Response.redirect(redirectUrl, 302) };
}
}
/* Use quote media if there is no media */
if (!tweet.media && tweet.quote?.media) {
tweet.media = tweet.quote.media;
tweet.twitter_card = tweet.quote.twitter_card;
}
let authorText = getAuthorText(tweet) || Strings.DEFAULT_AUTHOR_TEXT;
const engagementText = authorText.replace(/ {4}/g, ' ');
const siteName = Constants.BRANDING_NAME;
let newText = tweet.text;
const headers = [
``,
``,
``,
``,
``
];
if (userAgent?.indexOf('Telegram') === -1) {
headers.push(
``
);
}
if (tweet.translation) {
const { translation } = tweet;
const formatText =
language === 'en'
? Strings.TRANSLATE_TEXT.format({
language: translation.source_lang_en
})
: Strings.TRANSLATE_TEXT_INTL.format({
source: translation.source_lang.toUpperCase(),
destination: translation.target_lang.toUpperCase()
});
newText = `${translation.text}\n\n` + `${formatText}\n\n` + `${newText}`;
}
/* Video renderer */
if (tweet.media?.video) {
authorText = newText || '';
if (tweet?.translation) {
authorText = tweet.translation?.text || '';
}
const { video } = tweet.media;
/* Multiplying by 0.5 is an ugly hack to fix Discord
disliking videos that are too large lol */
let sizeMultiplier = 1;
if (video.width > 1920 || video.height > 1920) {
sizeMultiplier = 0.5;
}
if (video.width < 400 && video.height < 400) {
sizeMultiplier = 2;
}
headers.push(
``,
``,
``,
``,
``,
``,
``,
``,
``
);
}
/* Photo renderer */
if (tweet.media?.photos) {
const { photos } = tweet.media;
let photo = photos[(mediaNumber || 1) - 1];
if (typeof mediaNumber !== 'number' && tweet.media.mosaic) {
photo = {
url:
userAgent?.indexOf('Telegram') === -1
? tweet.media.mosaic.formats.webp
: tweet.media.mosaic.formats.jpeg,
width: tweet.media.mosaic.width,
height: tweet.media.mosaic.height,
type: 'photo'
};
} else if (photos.length > 1) {
const photoCounter = Strings.PHOTO_COUNT.format({
number: String(photos.indexOf(photo) + 1),
total: String(photos.length)
});
authorText =
authorText === Strings.DEFAULT_AUTHOR_TEXT
? photoCounter
: `${authorText} ― ${photoCounter}`;
let siteName = `${Constants.BRANDING_NAME} - ${photoCounter}`;
if (engagementText) {
siteName = `${Constants.BRANDING_NAME} - ${engagementText} - ${photoCounter}`;
}
headers.push(``);
}
headers.push(
``,
``,
``,
``,
``,
``
);
}
/* External media renderer (i.e. YouTube) */
if (tweet.media?.external) {
const { external } = tweet.media;
authorText = newText || '';
headers.push(
``,
``,
``,
``,
``,
``,
``,
``
);
}
/* Poll renderer */
if (tweet.poll) {
const { poll } = tweet;
let barLength = 36;
let str = '';
if (userAgent?.indexOf('Telegram') !== -1) {
barLength = 24;
}
tweet.poll.choices.forEach(choice => {
// render bar
const bar = '█'.repeat((choice.percentage / 100) * barLength);
// eslint-disable-next-line no-irregular-whitespace
str += `${bar}\n${choice.label} (${choice.percentage}%)
`;
});
str += `\n${poll.total_votes} votes · ${poll.time_left_en}`;
newText += `\n\n${str}`;
}
if (!tweet.media?.video && !tweet.media?.photos) {
headers.push(
// Use a slightly higher resolution image for profile pics
``,
``
);
}
if (api.tweet?.quote) {
const quoteText = handleQuote(api.tweet.quote);
newText += `\n${quoteText}`;
}
headers.push(
``,
``,
``
);
/* Special reply handling if authorText is not overriden */
if (tweet.replying_to && authorText === Strings.DEFAULT_AUTHOR_TEXT) {
authorText = `↪ Replying to @${tweet.replying_to}`;
}
/* The additional oembed is pulled by Discord to enable improved embeds.
Telegram does not use this. */
headers.push(
``
);
/* When dealing with a Tweet of unknown lang, fall back to en */
const lang = tweet.lang === 'unk' ? 'en' : tweet.lang || 'en';
return {
text: Strings.BASE_HTML.format({
lang: `lang="${lang}"`,
headers: headers.join('')
})
};
};