chore(tmdb): add getImdbIdFromTmdbId and cache both ID transformations
This commit is contained in:
parent
876698825f
commit
a0e83f287d
5 changed files with 72 additions and 18 deletions
1
src/utils/__fixtures__/Fetcher/https:api.themoviedb.org3movie931944external_ids
generated
Normal file
1
src/utils/__fixtures__/Fetcher/https:api.themoviedb.org3movie931944external_ids
generated
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"id":931944,"imdb_id":"tt29141112","wikidata_id":"Q123992189","facebook_id":null,"instagram_id":null,"twitter_id":null}
|
||||
1
src/utils/__fixtures__/Fetcher/https:api.themoviedb.org3tv12345678external_ids.error
generated
Normal file
1
src/utils/__fixtures__/Fetcher/https:api.themoviedb.org3tv12345678external_ids.error
generated
Normal file
|
|
@ -0,0 +1 @@
|
|||
Fetcher error: 404: Not Found
|
||||
1
src/utils/__fixtures__/Fetcher/https:api.themoviedb.org3tv42009external_ids
generated
Normal file
1
src/utils/__fixtures__/Fetcher/https:api.themoviedb.org3tv42009external_ids
generated
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"id":42009,"imdb_id":"tt2085059","freebase_mid":"/m/0hhs506","freebase_id":null,"tvdb_id":253463,"tvrage_id":30348,"wikidata_id":"Q558112","facebook_id":"BlackMirrorNetflix","instagram_id":"","twitter_id":"blackmirror"}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { getTmdbIdFromImdbId } from './tmdb';
|
||||
import { getImdbIdFromTmdbId, getTmdbIdFromImdbId } from './tmdb';
|
||||
import { Fetcher } from './Fetcher';
|
||||
import { Context } from '../types';
|
||||
jest.mock('../utils/Fetcher');
|
||||
|
|
@ -9,26 +9,40 @@ const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { de: 'on' } };
|
|||
|
||||
describe('getTmdbIdFromImdbId', () => {
|
||||
test('series', async () => {
|
||||
const tmdbId = await getTmdbIdFromImdbId(ctx, fetcher, { id: 'tt2085059', series: 2, episode: 4 });
|
||||
|
||||
expect(tmdbId).toStrictEqual({
|
||||
id: 42009,
|
||||
series: 2,
|
||||
episode: 4,
|
||||
});
|
||||
expect(await getTmdbIdFromImdbId(ctx, fetcher, { id: 'tt2085059', series: 2, episode: 4 }))
|
||||
.toStrictEqual({ id: 42009, series: 2, episode: 4 });
|
||||
expect(await getTmdbIdFromImdbId(ctx, fetcher, { id: 'tt2085059', series: 2, episode: 4 }))
|
||||
.toStrictEqual({ id: 42009, series: 2, episode: 4 }); // from cache
|
||||
});
|
||||
|
||||
test('movie', async () => {
|
||||
const tmdbId = await getTmdbIdFromImdbId(ctx, fetcher, { id: 'tt29141112', series: undefined, episode: undefined });
|
||||
|
||||
expect(tmdbId).toStrictEqual({
|
||||
id: 931944,
|
||||
series: undefined,
|
||||
episode: undefined,
|
||||
});
|
||||
expect(await getTmdbIdFromImdbId(ctx, fetcher, { id: 'tt29141112', series: undefined, episode: undefined }))
|
||||
.toStrictEqual({ id: 931944, series: undefined, episode: undefined });
|
||||
expect(await getTmdbIdFromImdbId(ctx, fetcher, { id: 'tt29141112', series: undefined, episode: undefined }))
|
||||
.toStrictEqual({ id: 931944, series: undefined, episode: undefined }); // from cache
|
||||
});
|
||||
|
||||
test('throws with invalid imdb id', async () => {
|
||||
await expect(getTmdbIdFromImdbId(ctx, fetcher, { id: 'tt12345678', series: 1, episode: 1 })).rejects.toThrow('Could not get TMDB ID of IMDb ID "tt12345678"');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getImdbIdFromTmdbId', () => {
|
||||
test('series', async () => {
|
||||
expect(await getImdbIdFromTmdbId(ctx, fetcher, { id: 42009, series: 2, episode: 4 }))
|
||||
.toStrictEqual({ id: 'tt2085059', series: 2, episode: 4 });
|
||||
expect(await getImdbIdFromTmdbId(ctx, fetcher, { id: 42009, series: 2, episode: 4 }))
|
||||
.toStrictEqual({ id: 'tt2085059', series: 2, episode: 4 }); // from cache
|
||||
});
|
||||
|
||||
test('movie', async () => {
|
||||
expect(await getImdbIdFromTmdbId(ctx, fetcher, { id: 931944, series: undefined, episode: undefined }))
|
||||
.toStrictEqual({ id: 'tt29141112', series: undefined, episode: undefined });
|
||||
expect(await getImdbIdFromTmdbId(ctx, fetcher, { id: 931944, series: undefined, episode: undefined }))
|
||||
.toStrictEqual({ id: 'tt29141112', series: undefined, episode: undefined }); // from cache
|
||||
});
|
||||
|
||||
test('throws with invalid tmdb id', async () => {
|
||||
await expect(getImdbIdFromTmdbId(ctx, fetcher, { id: 12345678, series: 1, episode: 1 })).rejects.toThrow(Error);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,10 +5,32 @@ import { envGet } from './env';
|
|||
|
||||
export interface TmdbId { id: number; series: number | undefined; episode: number | undefined }
|
||||
|
||||
export const getTmdbIdFromImdbId = async (ctx: Context, fetcher: Fetcher, imdbId: ImdbId): Promise<TmdbId> => {
|
||||
const url = new URL(`https://api.themoviedb.org/3/find/${imdbId.id}?external_source=imdb_id`);
|
||||
interface FindResponsePartial {
|
||||
movie_results: {
|
||||
id: number;
|
||||
}[];
|
||||
tv_results: {
|
||||
id: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
interface ExternalIdsResponsePartial {
|
||||
imdb_id: string;
|
||||
}
|
||||
|
||||
const fetch = async (ctx: Context, fetcher: Fetcher, url: URL): Promise<unknown> => {
|
||||
const config = { 'headers': { Authorization: 'Bearer ' + envGet('TMDB_ACCESS_TOKEN') }, 'Content-Type': 'application/json' };
|
||||
const response = JSON.parse(await fetcher.text(ctx, url, config));
|
||||
|
||||
return JSON.parse(await fetcher.text(ctx, url, config));
|
||||
};
|
||||
|
||||
const imdbTmdbMap = new Map<string, number>();
|
||||
export const getTmdbIdFromImdbId = async (ctx: Context, fetcher: Fetcher, imdbId: ImdbId): Promise<TmdbId> => {
|
||||
if (imdbTmdbMap.has(imdbId.id)) {
|
||||
return { id: imdbTmdbMap.get(imdbId.id) as number, series: imdbId.series, episode: imdbId.episode };
|
||||
}
|
||||
|
||||
const response = await fetch(ctx, fetcher, new URL(`https://api.themoviedb.org/3/find/${imdbId.id}?external_source=imdb_id`)) as FindResponsePartial;
|
||||
|
||||
const id = (imdbId.series ? response.tv_results[0] : response.movie_results[0])?.id;
|
||||
|
||||
|
|
@ -16,5 +38,20 @@ export const getTmdbIdFromImdbId = async (ctx: Context, fetcher: Fetcher, imdbId
|
|||
throw new Error(`Could not get TMDB ID of IMDb ID "${imdbId.id}"`);
|
||||
}
|
||||
|
||||
imdbTmdbMap.set(imdbId.id, id);
|
||||
return { id, series: imdbId.series, episode: imdbId.episode };
|
||||
};
|
||||
|
||||
const tmdbImdbMap = new Map<number, string>();
|
||||
export const getImdbIdFromTmdbId = async (ctx: Context, fetcher: Fetcher, tmdbId: TmdbId): Promise<ImdbId> => {
|
||||
if (tmdbImdbMap.has(tmdbId.id)) {
|
||||
return { id: tmdbImdbMap.get(tmdbId.id) as string, series: tmdbId.series, episode: tmdbId.episode };
|
||||
}
|
||||
|
||||
const type = tmdbId.series ? 'tv' : 'movie';
|
||||
|
||||
const response = await fetch(ctx, fetcher, new URL(`https://api.themoviedb.org/3/${type}/${tmdbId.id}/external_ids`)) as ExternalIdsResponsePartial;
|
||||
|
||||
tmdbImdbMap.set(tmdbId.id, response.imdb_id);
|
||||
return { id: response.imdb_id, series: tmdbId.series, episode: tmdbId.episode };
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue