From c7c2ebf353287763d2af83e1adc0943494806822 Mon Sep 17 00:00:00 2001 From: WebStreamr <210764791+webstreamr@users.noreply.github.com> Date: Fri, 22 Aug 2025 14:46:51 +0000 Subject: [PATCH] feat: support TMDB IDs --- src/controller/StreamController.ts | 23 +++++++++++++------ src/utils/__snapshots__/manifest.test.ts.snap | 1 + src/utils/manifest.ts | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/controller/StreamController.ts b/src/controller/StreamController.ts index 6853042..d45e957 100644 --- a/src/controller/StreamController.ts +++ b/src/controller/StreamController.ts @@ -3,7 +3,7 @@ import { Request, Response, Router } from 'express'; import { ContentType } from 'stremio-addon-sdk'; import winston from 'winston'; import { Source } from '../source'; -import { contextFromRequestAndResponse, envIsProd, ImdbId, StreamResolver } from '../utils'; +import { contextFromRequestAndResponse, envIsProd, Id, ImdbId, StreamResolver, TmdbId } from '../utils'; const locks = new Map(); @@ -27,22 +27,31 @@ export class StreamController { private async getStream(req: Request, res: Response) { const type: ContentType = (req.params['type'] || '') as ContentType; - const id: string = req.params['id'] || ''; + const rawId: string = req.params['id'] || ''; + + let id: Id; + if (rawId.startsWith('tmdb:')) { + id = TmdbId.fromString(rawId.replace('tmdb:', '')); + } else if (rawId.startsWith('tt')) { + id = ImdbId.fromString(rawId); + } else { + throw new Error(`Unsupported ID: ${rawId}`); + } const ctx = contextFromRequestAndResponse(req, res); - this.logger.info(`Search stream for type "${type}" and id "${id}" for ip ${ctx.ip}`, ctx); + this.logger.info(`Search stream for type "${type}" and id "${rawId}" for ip ${ctx.ip}`, ctx); const sources = this.sources.filter(source => source.countryCodes.filter(countryCode => countryCode in ctx.config).length); - let mutex = locks.get(id); + let mutex = locks.get(rawId); if (!mutex) { mutex = new Mutex(); - locks.set(id, mutex); + locks.set(rawId, mutex); } await mutex.runExclusive(async () => { - const { streams, ttl } = await this.streamResolver.resolve(ctx, sources, type, ImdbId.fromString(id)); + const { streams, ttl } = await this.streamResolver.resolve(ctx, sources, type, id); if (ttl && envIsProd()) { res.setHeader('Cache-Control', `max-age=${ttl / 1000}, public`); @@ -53,7 +62,7 @@ export class StreamController { }); if (!mutex.isLocked()) { - locks.delete(id); + locks.delete(rawId); } }; } diff --git a/src/utils/__snapshots__/manifest.test.ts.snap b/src/utils/__snapshots__/manifest.test.ts.snap index 8cff835..9b73a44 100644 --- a/src/utils/__snapshots__/manifest.test.ts.snap +++ b/src/utils/__snapshots__/manifest.test.ts.snap @@ -70,6 +70,7 @@ exports[`buildManifest default manifest 1`] = ` "description": "Provides HTTP URLs from streaming websites. Configure add-on for additional languages. Add MediaFlow proxy for more URLs. Supported languages: German, English, Castilian Spanish, French, Italian, Latin American Spanish", "id": "webstreamr", "idPrefixes": [ + "tmdb:", "tt", ], "name": "WebStreamr", diff --git a/src/utils/manifest.ts b/src/utils/manifest.ts index f858576..c377bdd 100644 --- a/src/utils/manifest.ts +++ b/src/utils/manifest.ts @@ -21,7 +21,7 @@ export const buildManifest = (sources: Source[], extractors: Extractor[], config 'series', ], catalogs: [], - idPrefixes: ['tt'], + idPrefixes: ['tmdb:', 'tt'], behaviorHints: { p2p: false, configurable: true,