diff --git a/src/handler/CineHDPlus.ts b/src/handler/CineHDPlus.ts index e91779b..504b9d7 100644 --- a/src/handler/CineHDPlus.ts +++ b/src/handler/CineHDPlus.ts @@ -1,7 +1,7 @@ import { ContentType } from 'stremio-addon-sdk'; import * as cheerio from 'cheerio'; import { Handler } from './types'; -import { Fetcher, ImdbId, parseImdbId } from '../utils'; +import { Fetcher, ImdbId } from '../utils'; import { ExtractorRegistry } from '../extractor'; import { Context, CountryCode } from '../types'; @@ -27,7 +27,7 @@ export class CineHDPlus implements Handler { return []; } - const imdbId = parseImdbId(id); + const imdbId = ImdbId.fromString(id); const seriesPageUrl = await this.fetchSeriesPageUrl(ctx, imdbId); if (!seriesPageUrl) { diff --git a/src/handler/Eurostreaming.ts b/src/handler/Eurostreaming.ts index bd58bbf..97ce591 100644 --- a/src/handler/Eurostreaming.ts +++ b/src/handler/Eurostreaming.ts @@ -1,7 +1,7 @@ import { ContentType } from 'stremio-addon-sdk'; import * as cheerio from 'cheerio'; import { Handler } from './types'; -import { ImdbId, parseImdbId, Fetcher } from '../utils'; +import { ImdbId, Fetcher } from '../utils'; import { ExtractorRegistry } from '../extractor'; import { Context, CountryCode } from '../types'; @@ -27,7 +27,7 @@ export class Eurostreaming implements Handler { return []; } - const imdbId = parseImdbId(id); + const imdbId = ImdbId.fromString(id); const seriesPageUrl = await this.fetchSeriesPageUrl(ctx, imdbId); if (!seriesPageUrl) { diff --git a/src/handler/Frembed.ts b/src/handler/Frembed.ts index b7f2ee8..9efceac 100644 --- a/src/handler/Frembed.ts +++ b/src/handler/Frembed.ts @@ -1,6 +1,6 @@ import { ContentType } from 'stremio-addon-sdk'; import { Handler } from './types'; -import { parseImdbId, Fetcher, getTmdbIdFromImdbId, TmdbId, parseTmdbId } from '../utils'; +import { Fetcher, getTmdbIdFromImdbId, ImdbId, TmdbId } from '../utils'; import { ExtractorRegistry } from '../extractor'; import { Context, CountryCode } from '../types'; @@ -24,9 +24,9 @@ export class Frembed implements Handler { readonly handle = async (ctx: Context, _type: string, id: string) => { let tmdbId: TmdbId; if (id.startsWith('tt')) { - tmdbId = await getTmdbIdFromImdbId(ctx, this.fetcher, parseImdbId(id)); + tmdbId = await getTmdbIdFromImdbId(ctx, this.fetcher, ImdbId.fromString(id)); } else if (/^\d+:/.test(id)) { - tmdbId = parseTmdbId(id); + tmdbId = TmdbId.fromString(id); } else { return []; } diff --git a/src/handler/FrenchCloud.ts b/src/handler/FrenchCloud.ts index e1adfe9..20a54e0 100644 --- a/src/handler/FrenchCloud.ts +++ b/src/handler/FrenchCloud.ts @@ -1,7 +1,7 @@ import { ContentType } from 'stremio-addon-sdk'; import * as cheerio from 'cheerio'; import { Handler } from './types'; -import { Fetcher, parseImdbId } from '../utils'; +import { Fetcher, ImdbId } from '../utils'; import { ExtractorRegistry } from '../extractor'; import { Context, CountryCode } from '../types'; @@ -27,7 +27,7 @@ export class FrenchCloud implements Handler { return []; } - const pageUrl = new URL(`https://frenchcloud.cam/movie/${parseImdbId(id).id}`); + const pageUrl = new URL(`https://frenchcloud.cam/movie/${ImdbId.fromString(id).id}`); const html = await this.fetcher.text(ctx, pageUrl); const $ = cheerio.load(html); diff --git a/src/handler/KinoKiste.ts b/src/handler/KinoKiste.ts index 2fef2f7..a5e26d3 100644 --- a/src/handler/KinoKiste.ts +++ b/src/handler/KinoKiste.ts @@ -1,7 +1,7 @@ import { ContentType } from 'stremio-addon-sdk'; import * as cheerio from 'cheerio'; import { Handler } from './types'; -import { ImdbId, parseImdbId, Fetcher } from '../utils'; +import { ImdbId, Fetcher } from '../utils'; import { ExtractorRegistry } from '../extractor'; import { Context, CountryCode } from '../types'; @@ -27,7 +27,7 @@ export class KinoKiste implements Handler { return []; } - const imdbId = parseImdbId(id); + const imdbId = ImdbId.fromString(id); const seriesPageUrl = await this.fetchSeriesPageUrl(ctx, imdbId); if (!seriesPageUrl) { diff --git a/src/handler/MeineCloud.ts b/src/handler/MeineCloud.ts index d1c8e7e..0d68963 100644 --- a/src/handler/MeineCloud.ts +++ b/src/handler/MeineCloud.ts @@ -1,7 +1,7 @@ import { ContentType } from 'stremio-addon-sdk'; import * as cheerio from 'cheerio'; import { Handler } from './types'; -import { Fetcher, parseImdbId } from '../utils'; +import { Fetcher, ImdbId } from '../utils'; import { ExtractorRegistry } from '../extractor'; import { Context, CountryCode } from '../types'; @@ -27,7 +27,7 @@ export class MeineCloud implements Handler { return []; } - const pageUrl = new URL(`https://meinecloud.click/movie/${parseImdbId(id).id}`); + const pageUrl = new URL(`https://meinecloud.click/movie/${ImdbId.fromString(id).id}`); const html = await this.fetcher.text(ctx, pageUrl); const $ = cheerio.load(html); diff --git a/src/handler/MostraGuarda.ts b/src/handler/MostraGuarda.ts index 690e2db..d930023 100644 --- a/src/handler/MostraGuarda.ts +++ b/src/handler/MostraGuarda.ts @@ -1,7 +1,7 @@ import { ContentType } from 'stremio-addon-sdk'; import * as cheerio from 'cheerio'; import { Handler } from './types'; -import { Fetcher, parseImdbId } from '../utils'; +import { Fetcher, ImdbId } from '../utils'; import { ExtractorRegistry } from '../extractor'; import { Context, CountryCode } from '../types'; @@ -27,7 +27,7 @@ export class MostraGuarda implements Handler { return []; } - const pageUrl = new URL(`https://mostraguarda.stream/movie/${parseImdbId(id).id}`); + const pageUrl = new URL(`https://mostraguarda.stream/movie/${ImdbId.fromString(id).id}`); const html = await this.fetcher.text(ctx, pageUrl); const $ = cheerio.load(html); diff --git a/src/handler/Soaper.ts b/src/handler/Soaper.ts index d747d4d..129a7c7 100644 --- a/src/handler/Soaper.ts +++ b/src/handler/Soaper.ts @@ -6,8 +6,7 @@ import { getTmdbIdFromImdbId, getTmdbMovieDetails, getTmdbTvDetails, - parseImdbId, - parseTmdbId, + ImdbId, TmdbId, } from '../utils'; import { ExtractorRegistry } from '../extractor'; @@ -35,9 +34,9 @@ export class Soaper implements Handler { readonly handle = async (ctx: Context, _type: string, id: string) => { let tmdbId: TmdbId; if (id.startsWith('tt')) { - tmdbId = await getTmdbIdFromImdbId(ctx, this.fetcher, parseImdbId(id)); + tmdbId = await getTmdbIdFromImdbId(ctx, this.fetcher, ImdbId.fromString(id)); } else if (/^\d+:/.test(id)) { - tmdbId = parseTmdbId(id); + tmdbId = TmdbId.fromString(id); } else { return []; } diff --git a/src/handler/VerHdLink.ts b/src/handler/VerHdLink.ts index 13d5fe3..b4c886c 100644 --- a/src/handler/VerHdLink.ts +++ b/src/handler/VerHdLink.ts @@ -1,7 +1,7 @@ import { ContentType } from 'stremio-addon-sdk'; import * as cheerio from 'cheerio'; import { Handler } from './types'; -import { Fetcher, parseImdbId } from '../utils'; +import { Fetcher, ImdbId } from '../utils'; import { ExtractorRegistry } from '../extractor'; import { Context, CountryCode } from '../types'; @@ -27,7 +27,7 @@ export class VerHdLink implements Handler { return []; } - const pageUrl = new URL(`https://verhdlink.cam/movie/${parseImdbId(id).id}`); + const pageUrl = new URL(`https://verhdlink.cam/movie/${ImdbId.fromString(id).id}`); const html = await this.fetcher.text(ctx, pageUrl); const $ = cheerio.load(html); diff --git a/src/utils/imdb.test.ts b/src/utils/ImdbId.test.ts similarity index 66% rename from src/utils/imdb.test.ts rename to src/utils/ImdbId.test.ts index 17182c1..f7a8680 100644 --- a/src/utils/imdb.test.ts +++ b/src/utils/ImdbId.test.ts @@ -1,8 +1,8 @@ -import { parseImdbId } from './imdb'; +import { ImdbId } from './ImdbId'; -describe('imdb id parsing', () => { +describe('can be created from string', () => { test('splits id properly', () => { - const { id, series, episode } = parseImdbId('tt2085059:2:4'); + const { id, series, episode } = ImdbId.fromString('tt2085059:2:4'); expect(id).toBe('tt2085059'); expect(series).toBe(2); @@ -10,7 +10,7 @@ describe('imdb id parsing', () => { }); test('handles weird 0 prefixes in series and episode', () => { - const { id, series, episode } = parseImdbId('tt2085059:02:04'); + const { id, series, episode } = ImdbId.fromString('tt2085059:02:04'); expect(id).toBe('tt2085059'); expect(series).toBe(2); @@ -18,7 +18,7 @@ describe('imdb id parsing', () => { }); test('supports movie with missing series and episode', () => { - const { id, series, episode } = parseImdbId('tt2085059'); + const { id, series, episode } = ImdbId.fromString('tt2085059'); expect(id).toBe('tt2085059'); expect(series).toBeUndefined(); @@ -27,13 +27,13 @@ describe('imdb id parsing', () => { test('throws for empty ids', () => { expect(() => { - parseImdbId(''); + ImdbId.fromString(''); }).toThrow('IMDb ID "" is invalid'); }); test('throws for invalid ids', () => { expect(() => { - parseImdbId('foo'); + ImdbId.fromString('foo'); }).toThrow('IMDb ID "foo" is invalid'); }); }); diff --git a/src/utils/ImdbId.ts b/src/utils/ImdbId.ts new file mode 100644 index 0000000..ea8766b --- /dev/null +++ b/src/utils/ImdbId.ts @@ -0,0 +1,25 @@ +export class ImdbId { + public readonly id: string; + public readonly series: number | undefined; + public readonly episode: number | undefined; + + constructor(id: string, series: number | undefined, episode: number | undefined) { + this.id = id; + this.series = series; + this.episode = episode; + } + + public static fromString(id: string): ImdbId { + const idParts = id.split(':'); + + if (!idParts[0] || !/^tt\d+$/.test(idParts[0])) { + throw new Error(`IMDb ID "${id}" is invalid`); + } + + return new ImdbId( + idParts[0], + idParts[1] ? parseInt(idParts[1]) : undefined, + idParts[2] ? parseInt(idParts[2]) : undefined, + ); + } +} diff --git a/src/utils/TmdbId.test.ts b/src/utils/TmdbId.test.ts new file mode 100644 index 0000000..7bedb50 --- /dev/null +++ b/src/utils/TmdbId.test.ts @@ -0,0 +1,39 @@ +import { TmdbId } from './TmdbId'; + +describe('can be created from string', () => { + test('splits id properly', () => { + const { id, series, episode } = TmdbId.fromString('2085059:2:4'); + + expect(id).toBe(2085059); + expect(series).toBe(2); + expect(episode).toBe(4); + }); + + test('handles weird 0 prefixes in series and episode', () => { + const { id, series, episode } = TmdbId.fromString('2085059:02:04'); + + expect(id).toBe(2085059); + expect(series).toBe(2); + expect(episode).toBe(4); + }); + + test('supports movie with missing series and episode', () => { + const { id, series, episode } = TmdbId.fromString('2085059'); + + expect(id).toBe(2085059); + expect(series).toBeUndefined(); + expect(episode).toBeUndefined(); + }); + + test('throws for empty ids', () => { + expect(() => { + TmdbId.fromString(''); + }).toThrow('TMDB ID "" is invalid'); + }); + + test('throws for invalid ids', () => { + expect(() => { + TmdbId.fromString('foo'); + }).toThrow('TMDB ID "foo" is invalid'); + }); +}); diff --git a/src/utils/TmdbId.ts b/src/utils/TmdbId.ts new file mode 100644 index 0000000..d3acc7d --- /dev/null +++ b/src/utils/TmdbId.ts @@ -0,0 +1,25 @@ +export class TmdbId { + public readonly id: number; + public readonly series: number | undefined; + public readonly episode: number | undefined; + + constructor(id: number, series: number | undefined, episode: number | undefined) { + this.id = id; + this.series = series; + this.episode = episode; + } + + public static fromString(id: string): TmdbId { + const idParts = id.split(':'); + + if (!idParts[0] || !/^\d+$/.test(idParts[0])) { + throw new Error(`TMDB ID "${id}" is invalid`); + } + + return new TmdbId( + parseInt(idParts[0]), + idParts[1] ? parseInt(idParts[1]) : undefined, + idParts[2] ? parseInt(idParts[2]) : undefined, + ); + } +} diff --git a/src/utils/imdb.ts b/src/utils/imdb.ts deleted file mode 100644 index 8a076c6..0000000 --- a/src/utils/imdb.ts +++ /dev/null @@ -1,15 +0,0 @@ -export interface ImdbId { id: string; series: number | undefined; episode: number | undefined } - -export const parseImdbId = (id: string): ImdbId => { - const idParts = id.split(':'); - - if (!idParts[0] || !/^tt\d+$/.test(idParts[0])) { - throw new Error(`IMDb ID "${id}" is invalid`); - } - - return { - id: idParts[0], - series: idParts[1] ? parseInt(idParts[1]) : undefined, - episode: idParts[2] ? parseInt(idParts[2]) : undefined, - }; -}; diff --git a/src/utils/index.ts b/src/utils/index.ts index 30fd189..f9950e2 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,7 +2,8 @@ export * from './env'; export * from './Fetcher'; export * from './StreamResolver'; export * from './embed'; -export * from './imdb'; +export * from './ImdbId'; export * from './language'; export * from './manifest'; export * from './tmdb'; +export * from './TmdbId'; diff --git a/src/utils/tmdb.test.ts b/src/utils/tmdb.test.ts index 337ae03..58a36a9 100644 --- a/src/utils/tmdb.test.ts +++ b/src/utils/tmdb.test.ts @@ -1,86 +1,82 @@ -import { getImdbIdFromTmdbId, getTmdbIdFromImdbId, parseTmdbId } from './tmdb'; +import { getImdbIdFromTmdbId, getTmdbIdFromImdbId } from './tmdb'; import { Fetcher } from './Fetcher'; import { Context } from '../types'; +import { ImdbId } from './ImdbId'; +import { TmdbId } from './TmdbId'; jest.mock('../utils/Fetcher'); // @ts-expect-error No constructor args needed const fetcher = new Fetcher(); const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { de: 'on' } }; -describe('tmdb id parsing', () => { - test('splits id properly', () => { - const { id, series, episode } = parseTmdbId('2085059:2:4'); - - expect(id).toBe(2085059); - expect(series).toBe(2); - expect(episode).toBe(4); - }); - - test('handles weird 0 prefixes in series and episode', () => { - const { id, series, episode } = parseTmdbId('2085059:02:04'); - - expect(id).toBe(2085059); - expect(series).toBe(2); - expect(episode).toBe(4); - }); - - test('supports movie with missing series and episode', () => { - const { id, series, episode } = parseTmdbId('2085059'); - - expect(id).toBe(2085059); - expect(series).toBeUndefined(); - expect(episode).toBeUndefined(); - }); - - test('throws for empty ids', () => { - expect(() => { - parseTmdbId(''); - }).toThrow('TMDB ID "" is invalid'); - }); - - test('throws for invalid ids', () => { - expect(() => { - parseTmdbId('foo'); - }).toThrow('TMDB ID "foo" is invalid'); - }); -}); - describe('getTmdbIdFromImdbId', () => { test('series', async () => { - 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 + const tmdbId1 = await getTmdbIdFromImdbId(ctx, fetcher, new ImdbId('tt2085059', 2, 4)); + expect(tmdbId1).toBeInstanceOf(TmdbId); + expect(tmdbId1).toHaveProperty('id', 42009); + expect(tmdbId1).toHaveProperty('series', 2); + expect(tmdbId1).toHaveProperty('episode', 4); + + // from cache + const tmdbId2 = await getTmdbIdFromImdbId(ctx, fetcher, new ImdbId('tt2085059', 2, 4)); + expect(tmdbId2).toBeInstanceOf(TmdbId); + expect(tmdbId2).toHaveProperty('id', 42009); + expect(tmdbId2).toHaveProperty('series', 2); + expect(tmdbId2).toHaveProperty('episode', 4); }); test('movie', async () => { - 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 + const tmdbId1 = await getTmdbIdFromImdbId(ctx, fetcher, new ImdbId('tt29141112', undefined, undefined)); + expect(tmdbId1).toBeInstanceOf(TmdbId); + expect(tmdbId1).toHaveProperty('id', 931944); + expect(tmdbId1).toHaveProperty('series', undefined); + expect(tmdbId1).toHaveProperty('episode', undefined); + + // from cache + const tmdbId2 = await getTmdbIdFromImdbId(ctx, fetcher, new ImdbId('tt29141112', undefined, undefined)); + expect(tmdbId2).toBeInstanceOf(TmdbId); + expect(tmdbId2).toHaveProperty('id', 931944); + expect(tmdbId2).toHaveProperty('series', undefined); + expect(tmdbId2).toHaveProperty('episode', undefined); }); 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"'); + await expect(getTmdbIdFromImdbId(ctx, fetcher, new ImdbId('tt12345678', 1, 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 + const imdbId1 = await getImdbIdFromTmdbId(ctx, fetcher, new TmdbId(42009, 2, 4)); + expect(imdbId1).toBeInstanceOf(ImdbId); + expect(imdbId1).toHaveProperty('id', 'tt2085059'); + expect(imdbId1).toHaveProperty('series', 2); + expect(imdbId1).toHaveProperty('episode', 4); + + // from cache + const imdbId2 = await getImdbIdFromTmdbId(ctx, fetcher, new TmdbId(42009, 2, 4)); + expect(imdbId2).toBeInstanceOf(ImdbId); + expect(imdbId2).toHaveProperty('id', 'tt2085059'); + expect(imdbId2).toHaveProperty('series', 2); + expect(imdbId2).toHaveProperty('episode', 4); }); 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 + const imdbId1 = await getImdbIdFromTmdbId(ctx, fetcher, new TmdbId(931944, undefined, undefined)); + expect(imdbId1).toBeInstanceOf(ImdbId); + expect(imdbId1).toHaveProperty('id', 'tt29141112'); + expect(imdbId1).toHaveProperty('series', undefined); + expect(imdbId1).toHaveProperty('episode', undefined); + + // from cache + const imdbId2 = await getImdbIdFromTmdbId(ctx, fetcher, new TmdbId(931944, undefined, undefined)); + expect(imdbId2).toBeInstanceOf(ImdbId); + expect(imdbId2).toHaveProperty('id', 'tt29141112'); + expect(imdbId2).toHaveProperty('series', undefined); + expect(imdbId2).toHaveProperty('episode', undefined); }); test('throws with invalid tmdb id', async () => { - await expect(getImdbIdFromTmdbId(ctx, fetcher, { id: 12345678, series: 1, episode: 1 })).rejects.toThrow(Error); + await expect(getImdbIdFromTmdbId(ctx, fetcher, new TmdbId(12345678, 1, 1))).rejects.toThrow(Error); }); }); diff --git a/src/utils/tmdb.ts b/src/utils/tmdb.ts index cbad2a8..8820a78 100644 --- a/src/utils/tmdb.ts +++ b/src/utils/tmdb.ts @@ -1,10 +1,9 @@ -import { ImdbId } from './imdb'; +import { ImdbId } from './ImdbId'; +import { TmdbId } from './TmdbId'; import { Context } from '../types'; import { Fetcher } from './Fetcher'; import { envGet } from './env'; -export interface TmdbId { id: number; series: number | undefined; episode: number | undefined } - interface FindResponsePartial { movie_results: { id: number; @@ -28,20 +27,6 @@ interface TvDetailsResponsePartial { name: string; } -export const parseTmdbId = (id: string): TmdbId => { - const idParts = id.split(':'); - - if (!idParts[0] || !/^\d+$/.test(idParts[0])) { - throw new Error(`TMDB ID "${id}" is invalid`); - } - - return { - id: parseInt(idParts[0]), - series: idParts[1] ? parseInt(idParts[1]) : undefined, - episode: idParts[2] ? parseInt(idParts[2]) : undefined, - }; -}; - export const tmdbFetch = async (ctx: Context, fetcher: Fetcher, path: string): Promise => { const config = { 'headers': { Authorization: 'Bearer ' + envGet('TMDB_ACCESS_TOKEN') }, 'Content-Type': 'application/json' }; @@ -51,7 +36,7 @@ export const tmdbFetch = async (ctx: Context, fetcher: Fetcher, path: string): P const imdbTmdbMap = new Map(); export const getTmdbIdFromImdbId = async (ctx: Context, fetcher: Fetcher, imdbId: ImdbId): Promise => { if (imdbTmdbMap.has(imdbId.id)) { - return { id: imdbTmdbMap.get(imdbId.id) as number, series: imdbId.series, episode: imdbId.episode }; + return new TmdbId(imdbTmdbMap.get(imdbId.id) as number, imdbId.series, imdbId.episode); } const response = await tmdbFetch(ctx, fetcher, `/find/${imdbId.id}?external_source=imdb_id`) as FindResponsePartial; @@ -63,13 +48,13 @@ export const getTmdbIdFromImdbId = async (ctx: Context, fetcher: Fetcher, imdbId } imdbTmdbMap.set(imdbId.id, id); - return { id, series: imdbId.series, episode: imdbId.episode }; + return new TmdbId(id, imdbId.series, imdbId.episode); }; const tmdbImdbMap = new Map(); export const getImdbIdFromTmdbId = async (ctx: Context, fetcher: Fetcher, tmdbId: TmdbId): Promise => { if (tmdbImdbMap.has(tmdbId.id)) { - return { id: tmdbImdbMap.get(tmdbId.id) as string, series: tmdbId.series, episode: tmdbId.episode }; + return new ImdbId(tmdbImdbMap.get(tmdbId.id) as string, tmdbId.series, tmdbId.episode); } const type = tmdbId.series ? 'tv' : 'movie'; @@ -77,7 +62,7 @@ export const getImdbIdFromTmdbId = async (ctx: Context, fetcher: Fetcher, tmdbId const response = await tmdbFetch(ctx, fetcher, `/${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 }; + return new ImdbId(response.imdb_id, tmdbId.series, tmdbId.episode); }; export const getTmdbMovieDetails = async (ctx: Context, fetcher: Fetcher, tmdbId: TmdbId): Promise => {