From f6dcd74dfbfd3696c6462b1963c7e2645eb3d99f Mon Sep 17 00:00:00 2001 From: WebStreamr <210764791+webstreamr@users.noreply.github.com> Date: Fri, 18 Jul 2025 16:42:17 +0000 Subject: [PATCH] refactor: make TMDB detail fetching more DRY --- src/source/Cuevana.ts | 6 ++---- src/source/Eurostreaming.ts | 8 ++++---- src/source/KinoGer.ts | 20 ++++---------------- src/source/Soaper.ts | 23 ++++++----------------- src/utils/tmdb.ts | 18 +++++++++++++++--- 5 files changed, 31 insertions(+), 44 deletions(-) diff --git a/src/source/Cuevana.ts b/src/source/Cuevana.ts index 6e0e660..1d32730 100644 --- a/src/source/Cuevana.ts +++ b/src/source/Cuevana.ts @@ -1,7 +1,7 @@ import * as cheerio from 'cheerio'; import { ContentType } from 'stremio-addon-sdk'; import { Context, CountryCode } from '../types'; -import { Fetcher, getTmdbId, getTmdbMovieDetails, getTmdbTvDetails, Id, TmdbId } from '../utils'; +import { Fetcher, getTmdbId, getTmdbNameAndYear, Id, TmdbId } from '../utils'; import { Source, SourceResult } from './types'; export class Cuevana implements Source { @@ -22,9 +22,7 @@ export class Cuevana implements Source { public async handle(ctx: Context, _type: string, id: Id): Promise { const tmdbId = await getTmdbId(ctx, this.fetcher, id); - const name = tmdbId.season - ? (await getTmdbTvDetails(ctx, this.fetcher, tmdbId, 'es')).name - : (await getTmdbMovieDetails(ctx, this.fetcher, tmdbId, 'es')).title; + const [name] = await getTmdbNameAndYear(ctx, this.fetcher, tmdbId, 'es'); const pageUrl = await this.fetchPageUrl(ctx, name); if (!pageUrl) { diff --git a/src/source/Eurostreaming.ts b/src/source/Eurostreaming.ts index 689d231..45c297e 100644 --- a/src/source/Eurostreaming.ts +++ b/src/source/Eurostreaming.ts @@ -1,7 +1,7 @@ import * as cheerio from 'cheerio'; import { ContentType } from 'stremio-addon-sdk'; import { Context, CountryCode } from '../types'; -import { Fetcher, getTmdbId, getTmdbTvDetails, Id } from '../utils'; +import { Fetcher, getTmdbId, getTmdbNameAndYear, Id } from '../utils'; import { Source, SourceResult } from './types'; export class Eurostreaming implements Source { @@ -21,9 +21,9 @@ export class Eurostreaming implements Source { public async handle(ctx: Context, _type: string, id: Id): Promise { const tmdbId = await getTmdbId(ctx, this.fetcher, id); - const tmdbTvDetails = await getTmdbTvDetails(ctx, this.fetcher, tmdbId, 'it'); + const [name] = await getTmdbNameAndYear(ctx, this.fetcher, tmdbId, 'it'); - const seriesPageUrl = await this.fetchSeriesPageUrl(ctx, tmdbTvDetails.name); + const seriesPageUrl = await this.fetchSeriesPageUrl(ctx, name); if (!seriesPageUrl) { return []; } @@ -32,7 +32,7 @@ export class Eurostreaming implements Source { const $ = cheerio.load(html); - const title = `${tmdbTvDetails.name} ${tmdbId.season}x${tmdbId.episode}`; + const title = `${name} ${tmdbId.season}x${tmdbId.episode}`; return Promise.all( $(`[data-num="${tmdbId.season}x${tmdbId.episode}"]`) diff --git a/src/source/KinoGer.ts b/src/source/KinoGer.ts index 465f484..a9bdcdd 100644 --- a/src/source/KinoGer.ts +++ b/src/source/KinoGer.ts @@ -1,7 +1,7 @@ import * as cheerio from 'cheerio'; import { ContentType } from 'stremio-addon-sdk'; import { Context, CountryCode } from '../types'; -import { Fetcher, getTmdbId, getTmdbMovieDetails, getTmdbTvDetails, Id, TmdbId } from '../utils'; +import { Fetcher, getTmdbId, getTmdbNameAndYear, Id } from '../utils'; import { Source, SourceResult } from './types'; export class KinoGer implements Source { @@ -24,14 +24,14 @@ export class KinoGer implements Source { public async handle(ctx: Context, _type: string, id: Id): Promise { const tmdbId = await getTmdbId(ctx, this.fetcher, id); - const [keyword, year] = await this.getKeywordAndYear(ctx, tmdbId); + const [name, year] = await getTmdbNameAndYear(ctx, this.fetcher, tmdbId, 'de'); - const pageUrl = await this.fetchPageUrl(ctx, keyword, year); + const pageUrl = await this.fetchPageUrl(ctx, name, year); if (!pageUrl) { return []; } - const title = tmdbId.season ? `${keyword} ${tmdbId.season}x${tmdbId.episode}` : `${keyword} (${year})`; + const title = tmdbId.season ? `${name} ${tmdbId.season}x${tmdbId.episode}` : `${name} (${year})`; const seasonIndex = (tmdbId.season ?? 1) - 1; const episodeIndex = (tmdbId.episode ?? 1) - 1; @@ -73,16 +73,4 @@ export class KinoGer implements Source { .map((_i, el) => new URL($(el).attr('href') as string, this.baseUrl)) .get(0); }; - - private readonly getKeywordAndYear = async (ctx: Context, tmdbId: TmdbId): Promise<[string, number]> => { - if (tmdbId.season) { - const tmdbDetails = await getTmdbTvDetails(ctx, this.fetcher, tmdbId, 'de'); - - return [tmdbDetails.name, (new Date(tmdbDetails.first_air_date)).getFullYear()]; - } - - const tmdbDetails = await getTmdbMovieDetails(ctx, this.fetcher, tmdbId, 'de'); - - return [tmdbDetails.title, (new Date(tmdbDetails.release_date)).getFullYear()]; - }; } diff --git a/src/source/Soaper.ts b/src/source/Soaper.ts index e3f264b..394a1c0 100644 --- a/src/source/Soaper.ts +++ b/src/source/Soaper.ts @@ -1,7 +1,7 @@ import * as cheerio from 'cheerio'; import { ContentType } from 'stremio-addon-sdk'; import { Context, CountryCode } from '../types'; -import { Fetcher, getTmdbId, getTmdbMovieDetails, getTmdbTvDetails, Id, TmdbId } from '../utils'; +import { Fetcher, getTmdbId, getTmdbNameAndYear, Id } from '../utils'; import { Source, SourceResult } from './types'; export class Soaper implements Source { @@ -24,9 +24,10 @@ export class Soaper implements Source { public async handle(ctx: Context, _type: string, id: Id): Promise { const tmdbId = await getTmdbId(ctx, this.fetcher, id); - const [keyword, year, hrefPrefix] = await this.getKeywordYearAndHrefPrefix(ctx, tmdbId); + const [name, year] = await getTmdbNameAndYear(ctx, this.fetcher, tmdbId); + const hrefPrefix = tmdbId.season ? '/tv_' : '/movie_'; - const pageUrl = await this.fetchPageUrl(ctx, keyword, year, hrefPrefix); + const pageUrl = await this.fetchPageUrl(ctx, name, year, hrefPrefix); if (!pageUrl) { return []; } @@ -42,12 +43,12 @@ export class Soaper implements Source { } const episodeUrl = new URL(episodePageHref, this.baseUrl); - const title = `${keyword} ${tmdbId.season}x${tmdbId.episode}`; + const title = `${name} ${tmdbId.season}x${tmdbId.episode}`; return [{ countryCode: CountryCode.en, title, url: episodeUrl }]; } - const title = `${keyword} (${year})`; + const title = `${name} (${year})`; return [{ countryCode: CountryCode.en, title, url: pageUrl }]; }; @@ -69,16 +70,4 @@ export class Soaper implements Source { return exactKeyWordMatchUrl ?? yearMatchUrl; }; - - private readonly getKeywordYearAndHrefPrefix = async (ctx: Context, tmdbId: TmdbId): Promise<[string, number, string]> => { - if (tmdbId.season) { - const tmdbDetails = await getTmdbTvDetails(ctx, this.fetcher, tmdbId); - - return [tmdbDetails.name, (new Date(tmdbDetails.first_air_date)).getFullYear(), '/tv_']; - } - - const tmdbDetails = await getTmdbMovieDetails(ctx, this.fetcher, tmdbId); - - return [tmdbDetails.title, (new Date(tmdbDetails.release_date)).getFullYear(), '/movie_']; - }; } diff --git a/src/utils/tmdb.ts b/src/utils/tmdb.ts index adf8880..12317d9 100644 --- a/src/utils/tmdb.ts +++ b/src/utils/tmdb.ts @@ -27,7 +27,7 @@ interface TvDetailsResponsePartial { name: string; } -export const tmdbFetch = async (ctx: Context, fetcher: Fetcher, path: string, searchParams?: Record): Promise => { +const tmdbFetch = async (ctx: Context, fetcher: Fetcher, path: string, searchParams?: Record): Promise => { const config: CustomRequestInit = { headers: { 'Authorization': 'Bearer ' + envGet('TMDB_ACCESS_TOKEN'), @@ -79,10 +79,22 @@ export const getImdbIdFromTmdbId = async (ctx: Context, fetcher: Fetcher, tmdbId return new ImdbId(response.imdb_id, tmdbId.season, tmdbId.episode); }; -export const getTmdbMovieDetails = async (ctx: Context, fetcher: Fetcher, tmdbId: TmdbId, language?: string): Promise => { +const getTmdbMovieDetails = async (ctx: Context, fetcher: Fetcher, tmdbId: TmdbId, language?: string): Promise => { return await tmdbFetch(ctx, fetcher, `/movie/${tmdbId.id}`, { language }) as MovieDetailsResponsePartial; }; -export const getTmdbTvDetails = async (ctx: Context, fetcher: Fetcher, tmdbId: TmdbId, language?: string): Promise => { +const getTmdbTvDetails = async (ctx: Context, fetcher: Fetcher, tmdbId: TmdbId, language?: string): Promise => { return await tmdbFetch(ctx, fetcher, `/tv/${tmdbId.id}`, { language }) as TvDetailsResponsePartial; }; + +export const getTmdbNameAndYear = async (ctx: Context, fetcher: Fetcher, tmdbId: TmdbId, language?: string): Promise<[string, number]> => { + if (tmdbId.season) { + const tmdbDetails = await getTmdbTvDetails(ctx, fetcher, tmdbId, language); + + return [tmdbDetails.name, (new Date(tmdbDetails.first_air_date)).getFullYear()]; + } + + const tmdbDetails = await getTmdbMovieDetails(ctx, fetcher, tmdbId, language); + + return [tmdbDetails.title, (new Date(tmdbDetails.release_date)).getFullYear()]; +};