Merge pull request #29 from dangeredwolf/api-multi-video

Multi-Video API
This commit is contained in:
dangered wolf 2022-08-13 02:50:51 -04:00 committed by GitHub
commit 49b854edda
Signed by: DevComp
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 106 additions and 12 deletions

View file

@ -23,6 +23,7 @@ const processMedia = (media: TweetMedia): APIPhoto | APIVideo | null => {
return { return {
url: bestVariant?.url || '', url: bestVariant?.url || '',
thumbnail_url: media.media_url_https, thumbnail_url: media.media_url_https,
duration: (media.video_info?.duration_millis || 0) / 1000,
width: media.original_info.width, width: media.original_info.width,
height: media.original_info.height, height: media.original_info.height,
format: bestVariant?.content_type || '', format: bestVariant?.content_type || '',
@ -93,6 +94,16 @@ const populateTweetProperties = async (
apiTweet.twitter_card = 'player'; apiTweet.twitter_card = 'player';
apiTweet.media = apiTweet.media || {}; apiTweet.media = apiTweet.media || {};
apiTweet.media.video = mediaObject as APIVideo; apiTweet.media.video = mediaObject as APIVideo;
apiTweet.media.videos = apiTweet.media.videos || [];
apiTweet.media.videos.push(mediaObject);
apiTweet.media.video = {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
WARNING:
'video is deprecated and will be removed. Please use videos[0] instead.',
...mediaObject
};
} }
} }
}); });

View file

@ -5,7 +5,7 @@ export const linkFixer = (tweet: TweetPartial, text: string): string => {
text = text.replace(url.url, url.expanded_url); text = text.replace(url.url, url.expanded_url);
}); });
text = text.replace(/ ?https:\/\/t\.co\/\w{10}/, ''); text = text.replace(/ ?https:\/\/t\.co\/\w{10}/g, '');
} }
return text; return text;

View file

@ -49,10 +49,11 @@ export const handleStatus = async (
if (flags?.direct && tweet.media) { if (flags?.direct && tweet.media) {
let redirectUrl: string | null = null; let redirectUrl: string | null = null;
if (tweet.media.video) { if (tweet.media.videos) {
redirectUrl = tweet.media.video.url; const { videos } = tweet.media;
redirectUrl = (videos[(mediaNumber || 1) - 1] || videos[0]).url;
} else if (tweet.media.photos) { } else if (tweet.media.photos) {
const photos = tweet.media.photos; const { photos } = tweet.media;
redirectUrl = (photos[(mediaNumber || 1) - 1] || photos[0]).url; redirectUrl = (photos[(mediaNumber || 1) - 1] || photos[0]).url;
} }
if (redirectUrl) { if (redirectUrl) {
@ -68,7 +69,7 @@ export const handleStatus = async (
let authorText = getAuthorText(tweet) || Strings.DEFAULT_AUTHOR_TEXT; let authorText = getAuthorText(tweet) || Strings.DEFAULT_AUTHOR_TEXT;
const engagementText = authorText.replace(/ {4}/g, ' '); const engagementText = authorText.replace(/ {4}/g, ' ');
const siteName = Constants.BRANDING_NAME; let siteName = Constants.BRANDING_NAME;
let newText = tweet.text; let newText = tweet.text;
const headers = [ const headers = [
@ -102,14 +103,15 @@ export const handleStatus = async (
} }
/* Video renderer */ /* Video renderer */
if (tweet.media?.video) { if (tweet.media?.videos) {
authorText = newText || ''; authorText = newText || '';
if (tweet?.translation) { if (tweet?.translation) {
authorText = tweet.translation?.text || ''; authorText = tweet.translation?.text || '';
} }
const { video } = tweet.media; const { videos } = tweet.media;
const video = videos[(mediaNumber || 1) - 1];
/* Multiplying by 0.5 is an ugly hack to fix Discord /* Multiplying by 0.5 is an ugly hack to fix Discord
disliking videos that are too large lol */ disliking videos that are too large lol */
@ -123,6 +125,24 @@ export const handleStatus = async (
sizeMultiplier = 2; sizeMultiplier = 2;
} }
const videoCounter = Strings.VIDEO_COUNT.format({
number: String(videos.indexOf(video) + 1),
total: String(videos.length)
});
authorText =
authorText === Strings.DEFAULT_AUTHOR_TEXT
? videoCounter
: `${authorText}${authorText ? ' ― ' : ''}${videoCounter}`;
let siteName = `${Constants.BRANDING_NAME} - ${videoCounter}`;
if (engagementText) {
siteName = `${Constants.BRANDING_NAME} - ${engagementText} - ${videoCounter}`;
}
headers.push(`<meta property="og:site_name" content="${siteName}"/>`);
headers.push( headers.push(
`<meta name="twitter:player:stream:content_type" content="${video.format}"/>`, `<meta name="twitter:player:stream:content_type" content="${video.format}"/>`,
`<meta name="twitter:player:height" content="${video.height * sizeMultiplier}"/>`, `<meta name="twitter:player:height" content="${video.height * sizeMultiplier}"/>`,
@ -160,15 +180,13 @@ export const handleStatus = async (
authorText = authorText =
authorText === Strings.DEFAULT_AUTHOR_TEXT authorText === Strings.DEFAULT_AUTHOR_TEXT
? photoCounter ? photoCounter
: `${authorText}${photoCounter}`; : `${authorText}${authorText ? ' ― ' : ''}${photoCounter}`;
let siteName = `${Constants.BRANDING_NAME} - ${photoCounter}`; siteName = `${Constants.BRANDING_NAME} - ${photoCounter}`;
if (engagementText) { if (engagementText) {
siteName = `${Constants.BRANDING_NAME} - ${engagementText} - ${photoCounter}`; siteName = `${Constants.BRANDING_NAME} - ${engagementText} - ${photoCounter}`;
} }
headers.push(`<meta property="og:site_name" content="${siteName}"/>`);
} }
headers.push( headers.push(

View file

@ -72,6 +72,7 @@ This is caused by Twitter API downtime or a new bug. Try again in a little while
TRANSLATE_TEXT: `═ ↘️ Translated from {language} ═════`, TRANSLATE_TEXT: `═ ↘️ Translated from {language} ═════`,
TRANSLATE_TEXT_INTL: `═ ↘️ {source} ➡️ {destination} ═════`, TRANSLATE_TEXT_INTL: `═ ↘️ {source} ➡️ {destination} ═════`,
PHOTO_COUNT: `Photo {number} of {total}`, PHOTO_COUNT: `Photo {number} of {total}`,
VIDEO_COUNT: `Video {number} of {total}`,
SINGULAR_DAY_LEFT: 'day left', SINGULAR_DAY_LEFT: 'day left',
PLURAL_DAYS_LEFT: 'days left', PLURAL_DAYS_LEFT: 'days left',

2
src/types.d.ts vendored
View file

@ -101,6 +101,7 @@ interface APIVideo {
width: number; width: number;
height: number; height: number;
format: string; format: string;
duration: number;
} }
interface APITweet { interface APITweet {
@ -125,6 +126,7 @@ interface APITweet {
external?: APIExternalMedia; external?: APIExternalMedia;
photos?: APIPhoto[]; photos?: APIPhoto[];
video?: APIVideo; video?: APIVideo;
videos?: APIVideo[];
mosaic?: APIMosaicPhoto; mosaic?: APIMosaicPhoto;
}; };

View file

@ -114,13 +114,14 @@ test('API fetch video Tweet', async () => {
expect(tweet.lang).toEqual('en'); expect(tweet.lang).toEqual('en');
expect(tweet.replying_to).toBeNull(); expect(tweet.replying_to).toBeNull();
expect(tweet.media?.video).toBeTruthy(); expect(tweet.media?.video).toBeTruthy();
const video = tweet.media?.video as APIVideo; const video = tweet.media?.videos?.[0] as APIVideo;
expect(video.url).toEqual( expect(video.url).toEqual(
'https://video.twimg.com/amplify_video/854415175776059393/vid/720x720/dNEi0crU-jA4mTtr.mp4' 'https://video.twimg.com/amplify_video/854415175776059393/vid/720x720/dNEi0crU-jA4mTtr.mp4'
); );
expect(video.thumbnail_url).toEqual('https://pbs.twimg.com/media/C9t-btLVoAEqZI1.jpg'); expect(video.thumbnail_url).toEqual('https://pbs.twimg.com/media/C9t-btLVoAEqZI1.jpg');
expect(video.width).toEqual(1596); expect(video.width).toEqual(1596);
expect(video.height).toEqual(1600); expect(video.height).toEqual(1600);
expect(video.duration).toEqual(65.667);
expect(video.format).toEqual('video/mp4'); expect(video.format).toEqual('video/mp4');
expect(video.type).toEqual('video'); expect(video.type).toEqual('video');
}); });
@ -179,3 +180,64 @@ test('API fetch multi-photo Tweet', async () => {
'https://mosaic.fxtwitter.com/webp/1554870933449482240/FZQCeMmXwAAOJTt/FZQCl-lWIAMtoW9/FZQCsQPX0AIbY6H/FZQCxmLXEAMST4q' 'https://mosaic.fxtwitter.com/webp/1554870933449482240/FZQCeMmXwAAOJTt/FZQCl-lWIAMtoW9/FZQCsQPX0AIbY6H/FZQCxmLXEAMST4q'
); );
}); });
test('API fetch multi-video Tweet', async () => {
const result = await cacheWrapper(
new Request('https://api.fxtwitter.com/dangeredwolf/status/1557914172763127808', {
method: 'GET',
headers: botHeaders
})
);
expect(result.status).toEqual(200);
const response = (await result.json()) as APIResponse;
expect(response).toBeTruthy();
expect(response.code).toEqual(200);
expect(response.message).toEqual('OK');
const tweet = response.tweet as APITweet;
expect(tweet).toBeTruthy();
expect(tweet.url).toEqual(
'https://twitter.com/dangeredwolf/status/1557914172763127808'
);
expect(tweet.id).toEqual('1557914172763127808');
expect(tweet.text).toEqual('');
expect(tweet.author.screen_name?.toLowerCase()).toEqual('dangeredwolf');
expect(tweet.author.name).toBeTruthy();
expect(tweet.author.avatar_url).toBeTruthy();
expect(tweet.author.banner_url).toBeTruthy();
expect(tweet.author.avatar_color).toBeTruthy();
expect(tweet.twitter_card).toEqual('player');
expect(tweet.created_at).toEqual('Fri Aug 12 02:17:38 +0000 2022');
expect(tweet.created_timestamp).toEqual(1660270658);
expect(tweet.replying_to).toBeNull();
expect(tweet.media?.videos).toBeTruthy();
const videos = tweet.media?.videos as APIVideo[];
expect(videos[0].url).toEqual('https://video.twimg.com/ext_tw_video/1539029945124528130/pu/vid/1662x1080/ZQP4eoQhnGnKcLEb.mp4?tag=14');
expect(videos[0].thumbnail_url).toEqual("https://pbs.twimg.com/ext_tw_video_thumb/1539029945124528130/pu/img/6Z1MXMliums60j03.jpg");
expect(videos[0].width).toEqual(3548);
expect(videos[0].height).toEqual(2304);
expect(videos[0].duration).toEqual(37.75);
expect(videos[0].format).toEqual('video/mp4');
expect(videos[0].type).toEqual('video');
expect(videos[1].url).toEqual('https://video.twimg.com/ext_tw_video/1543316856697769984/pu/vid/1920x1080/3fo7b4EnWv2WO8Z1.mp4?tag=14');
expect(videos[1].thumbnail_url).toEqual("https://pbs.twimg.com/ext_tw_video_thumb/1543316856697769984/pu/img/eCl67JRWO8r4r8A4.jpg");
expect(videos[1].width).toEqual(1920);
expect(videos[1].height).toEqual(1080);
expect(videos[1].duration).toEqual(71.855);
expect(videos[1].format).toEqual('video/mp4');
expect(videos[1].type).toEqual('video');
expect(videos[2].url).toEqual('https://video.twimg.com/ext_tw_video/1543797953105625088/pu/vid/1920x1080/GHSLxzBrwiDLhLYD.mp4?tag=14');
expect(videos[2].thumbnail_url).toEqual("https://pbs.twimg.com/ext_tw_video_thumb/1543797953105625088/pu/img/2eX2QQkd7b2S1YDl.jpg");
expect(videos[2].width).toEqual(1920);
expect(videos[2].height).toEqual(1080);
expect(videos[2].duration).toEqual(22.018);
expect(videos[2].format).toEqual('video/mp4');
expect(videos[2].type).toEqual('video');
expect(videos[3].url).toEqual('https://video.twimg.com/ext_tw_video/1548602342488129536/pu/vid/720x1280/I_D3svYfjBl7_xGS.mp4?tag=14');
expect(videos[3].thumbnail_url).toEqual("https://pbs.twimg.com/ext_tw_video_thumb/1548602342488129536/pu/img/V_1u5Nv5BwKBynwv.jpg");
expect(videos[3].width).toEqual(720);
expect(videos[3].height).toEqual(1280);
expect(videos[3].duration).toEqual(25.133);
expect(videos[3].format).toEqual('video/mp4');
expect(videos[3].type).toEqual('video');
});