From 9a5f5fcc44c4687de34f0ad6318a95ddba791558 Mon Sep 17 00:00:00 2001 From: SubJunk Date: Sat, 18 Jul 2026 10:15:58 +1200 Subject: [PATCH 1/4] Prevent deprecated (UMS pre-v11) endpoints from writing to the database, they now just return existing results that were created by newer versions --- src/controllers/deprecated/media.ts | 147 ++++++++++++---------------- src/services/external-api-helper.ts | 2 +- 2 files changed, 61 insertions(+), 88 deletions(-) diff --git a/src/controllers/deprecated/media.ts b/src/controllers/deprecated/media.ts index ac4d4b46..f774b5fc 100644 --- a/src/controllers/deprecated/media.ts +++ b/src/controllers/deprecated/media.ts @@ -1,12 +1,11 @@ -import _ from 'lodash'; +import episodeParser from 'episode-parser'; import { LookupFailedInternalError, MediaNotFoundError, ValidationError } from '../../helpers/customErrors'; import FailedLookups, { FailedLookupsInterface } from '../../models/FailedLookups'; import MediaMetadata, { MediaMetadataInterface } from '../../models/MediaMetadata'; import SeriesMetadata, { SeriesMetadataInterface } from '../../models/SeriesMetadata'; -import * as externalAPIHelper from '../../services/external-api-helper'; import * as deprecatedExternalAPIHelper from '../../services/deprecated/external-api-helper'; -import { addSearchMatchByIMDbID } from '../media'; +import { traceLog } from '../../helpers/logging'; /** * Since this is deprecated, it will only return a result that has been created @@ -94,7 +93,7 @@ export const getByImdbID = async(ctx): Promise => { const { imdbID, title, year }: UmsQueryParams = ctx.query; @@ -102,8 +101,61 @@ export const getSeries = async(ctx): Promise => { const { title, imdbID }: UmsQueryParams = ctx.query; const { episode, season, year }: UmsQueryParams = ctx.query; - const [seasonNumber, yearNumber] = [season, year].map(param => param ? Number(param) : null); - let episodeNumbers = null; - if (episode) { - const episodes = episode.split('-'); - episodeNumbers = episodes.map(Number); - } if (!title && !imdbID) { throw new ValidationError('title or imdbId is a required parameter'); @@ -143,7 +184,7 @@ export const getVideo = async(ctx): Promise => { const query = []; const failedQuery = []; - let imdbIdToSearch = imdbID; + const imdbIdToSearch = imdbID; if (imdbIdToSearch) { query.push({ imdbID: imdbIdToSearch }); @@ -176,73 +217,5 @@ export const getVideo = async(ctx): Promise => { return ctx.body = existingResult; } - const existingFailedResult = await FailedLookups.findOne({ $or: failedQuery }, null, { lean: true }).exec(); - if (existingFailedResult) { - throw new MediaNotFoundError(); - } - - // the database does not have a record of this file, so begin search for metadata on TMDB. - - const failedLookupQuery = { episode, imdbID, season, title, year }; - - if (!title && !imdbIdToSearch) { - // TMDB requires either a title or IMDb ID, so return if we don't have one - const reason = 'getVideo (deprecated) failed because there is no title or imdbId'; - await FailedLookups.updateOne(failedLookupQuery, { $inc: { count: 1 }, reason }, { upsert: true, setDefaultsOnInsert: true }).exec(); - throw new MediaNotFoundError(); - } - - // Start TMDB lookups - let tmdbData: MediaMetadataInterface; - try { - tmdbData = await externalAPIHelper.getFromTMDBAPI(title, null, imdbIdToSearch, yearNumber, seasonNumber, episodeNumbers); - imdbIdToSearch = imdbIdToSearch || tmdbData?.imdbID; - } catch (e) { - // Log the error but continue - if (e.message && e.message.includes('404') && e.response?.config?.url) { - console.log('Received 404 response from ' + e.response.config.url); - } else { - console.log(e); - } - } - - // if the client did not pass an imdbID, but we found one on TMDB, see if we have an existing record for the now-known media. - if (!imdbID && imdbIdToSearch) { - { - const existingResult = await MediaMetadata.findOne({ imdbID: imdbIdToSearch }, null, { lean: true }).exec(); - if (existingResult) { - return ctx.body = await addSearchMatchByIMDbID(imdbIdToSearch, title); - } - } - } - // End TMDB lookups - - if (!tmdbData || _.isEmpty(tmdbData)) { - const reason = `getVideo (deprecated) failed because no data was found on TMDB for ${failedLookupQuery}`; - await FailedLookups.updateOne(failedLookupQuery, { $inc: { count: 1 }, reason }, { upsert: true, setDefaultsOnInsert: true }).exec(); - throw new MediaNotFoundError(); - } - - try { - if (title) { - tmdbData.searchMatches = [title]; - } - - // Ensure that we return and cache the same episode number that was searched for - if (episodeNumbers && episodeNumbers.length > 1 && episodeNumbers[0] === tmdbData.episode) { - tmdbData.episode = episode; - } - - const dbMeta = await MediaMetadata.create(tmdbData); - - // TODO: Investigate why we need this "as" syntax - let leanMeta = dbMeta.toObject({ useProjection: true }) as MediaMetadataInterface; - leanMeta = await deprecatedExternalAPIHelper.addPosterFromImages(leanMeta); - return ctx.body = leanMeta; - } catch (e) { - console.error(e, tmdbData); - const reason = `getVideo (deprecated) failed because an error occurred: ${e}`; - await FailedLookups.updateOne(failedLookupQuery, { $inc: { count: 1 }, reason }, { upsert: true, setDefaultsOnInsert: true }).exec(); - throw new MediaNotFoundError(); - } + throw new MediaNotFoundError(); }; diff --git a/src/services/external-api-helper.ts b/src/services/external-api-helper.ts index ea7def69..d1ce9785 100644 --- a/src/services/external-api-helper.ts +++ b/src/services/external-api-helper.ts @@ -160,7 +160,7 @@ export const getSeriesMetadata = async( // Return early for previously-failed lookups const previousFailedLookup = await FailedLookups.findOne(failedLookupQuery, '_id', { lean: true }).exec(); if (previousFailedLookup) { - const reason = `getSeriesMetadata found previous failed lookup ${failedLookupQuery.toString()}`; + const reason = `getSeriesMetadata found previous failed lookup ${JSON.stringify(failedLookupQuery)}`; traceLog(reason); await FailedLookups.updateOne(failedLookupQuery, { $inc: { count: 1 } }).exec(); From c990e82cf38d9f09aa1f2c1ee723f7134c592d58 Mon Sep 17 00:00:00 2001 From: SubJunk Date: Sat, 18 Jul 2026 10:17:41 +1200 Subject: [PATCH 2/4] Lint --- src/controllers/deprecated/media.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/deprecated/media.ts b/src/controllers/deprecated/media.ts index f774b5fc..e440a93b 100644 --- a/src/controllers/deprecated/media.ts +++ b/src/controllers/deprecated/media.ts @@ -1,6 +1,6 @@ import episodeParser from 'episode-parser'; -import { LookupFailedInternalError, MediaNotFoundError, ValidationError } from '../../helpers/customErrors'; +import { MediaNotFoundError, ValidationError } from '../../helpers/customErrors'; import FailedLookups, { FailedLookupsInterface } from '../../models/FailedLookups'; import MediaMetadata, { MediaMetadataInterface } from '../../models/MediaMetadata'; import SeriesMetadata, { SeriesMetadataInterface } from '../../models/SeriesMetadata'; From 8ef265cc711df99f42e3d30fd071204698611623 Mon Sep 17 00:00:00 2001 From: SubJunk Date: Sat, 18 Jul 2026 10:24:31 +1200 Subject: [PATCH 3/4] Added more info to logging --- src/controllers/media.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controllers/media.ts b/src/controllers/media.ts index fdf32230..f8e24b7c 100644 --- a/src/controllers/media.ts +++ b/src/controllers/media.ts @@ -39,7 +39,8 @@ export const getLocalize = async(ctx): Promise Date: Sat, 18 Jul 2026 10:33:40 +1200 Subject: [PATCH 4/4] Formatting --- src/controllers/media.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/media.ts b/src/controllers/media.ts index f8e24b7c..967a1518 100644 --- a/src/controllers/media.ts +++ b/src/controllers/media.ts @@ -33,7 +33,7 @@ export const addSearchMatchByIMDbID = async(imdbID: string, title: string): Prom export const getLocalize = async(ctx): Promise> => { const { language, mediaType, imdbID, tmdbID }: UmsQueryParams = ctx.query; const { episode, season }: UmsQueryParams = ctx.query; - let seasonNumber: number|undefined; + let seasonNumber: number | undefined; if (season) { seasonNumber = Number(season); }