Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions src/services/external-api-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { jaroWinkler } from '@skyra/jaro-winkler';
import * as episodeParser from 'episode-parser';
import * as _ from 'lodash';
import { FlattenMaps, Types } from 'mongoose';
import { Episode, EpisodeRequest, ExternalId, SearchMovieRequest, SearchTvRequest, SimpleEpisode, TvExternalIdsResponse } from 'moviedb-promise/dist/request-types';
import { Episode, EpisodeRequest, ExternalId, SearchMovieRequest, SearchTvRequest, SimpleEpisode, TvExternalIdsResponse, TvResult } from 'moviedb-promise/dist/request-types';

import { tmdb } from './tmdb-api';
import { ValidationError } from '../helpers/customErrors';
Expand All @@ -29,11 +29,27 @@ const getSeriesTMDBIDFromTMDBAPI = async(imdbID?: string, seriesTitle?: string,
if (language) {
tmdbQuery.language = language;
}

const searchResults = await tmdb.searchTv(tmdbQuery);
if (searchResults?.results && searchResults.results[0] && searchResults.results[0].id) {
const searchResult = searchResults.results[0];

if (searchResults?.results && searchResults.results[0]) {
let searchResult: TvResult;
let didMatchYear: boolean;
if (year) {
const resultWithMatchingYear = _.find(searchResults.results, function(result) {
return result.first_air_date.substring(0, 4) === year.toString();
});
if (resultWithMatchingYear?.id) {
searchResult = resultWithMatchingYear;
didMatchYear = true;
}
}

if (!searchResult) {
searchResult = searchResults.results[0];
}

if (didMatchYear) {
// a wrong year could cause a wrong result, so also do a similarity check to be sure
const resultNameLowerCase = searchResult.name.toLowerCase();
const requestNameLowerCase = seriesTitle.toLowerCase();
Expand Down
12 changes: 9 additions & 3 deletions test/e2e/media-series.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,15 @@ describe('Media Metadata endpoints', () => {
expect(response.data).toHaveProperty('title', 'Galactica 1980');
});

it('should return series even when the year is when the episode aired, not the series start year', async() => {
const response = await axios.get(`${appUrl}/api/media/series/v2?title=From&year=2023`) as UmsApiSeriesAxiosResponse;
expect(response.data).toHaveProperty('title', 'FROM');
// this used to return a result but it was really a workaround for a client bug, it should not return
it('should NOT return series when the year is when the episode aired, not the series start year', async() => {
let error;
try {
await axios.get(`${appUrl}/api/media/series/v2?title=From&year=2023`) as UmsApiSeriesAxiosResponse;
} catch (err) {
error = err;
}
expect(error.message).toBe('Request failed with status code 404');
});

it('should not return series when the year has no overlap with episode air dates', async() => {
Expand Down
30 changes: 29 additions & 1 deletion test/e2e/media-video.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ const EPISODE_PRISONBREAK = {
'seriesIMDbID': 'tt0455275',
};

const EPISODE_DOCTORWHO = {
'episodeTitle': 'Lucky Day',
'title': 'Doctor Who',
'season': '2',
'episode': '4',
"seriesIMDbID": "tt31433814",
'year': 2024,
};

const EPISODE_AVATAR = {
'episodeTitle': 'The Boiling Rock (1) & The Boiling Rock (2)',
'osdbHash': 'de334f38f153fb6f',
Expand Down Expand Up @@ -211,7 +220,7 @@ describe('get by all', () => {
expect(response.data.seriesIMDbID).toEqual(EPISODE_LOST.seriesIMDbID);
});

test('should return an episode by when passed all possible params, from source APIs then store', async() => {
test('should return an episode by all possible params, from source APIs then store', async() => {
const url = `${appUrl}/api/media/video/v2?`+
`osdbHash=${EPISODE_PRISONBREAK.osdbHash}`+
`&filebytesize=${EPISODE_PRISONBREAK.filebytesize}`+
Expand All @@ -232,6 +241,25 @@ describe('get by all', () => {
expect(response.data.seriesIMDbID).toEqual(EPISODE_PRISONBREAK.seriesIMDbID);
});

test('should return the episode from the correct series, when multiple series exist with different years, from source APIs then store', async() => {
const url = `${appUrl}/api/media/video/v2?`+
`title=${EPISODE_DOCTORWHO.title}`+
`&season=${EPISODE_DOCTORWHO.season}`+
`&episode=${EPISODE_DOCTORWHO.episode}`+
`&year=${EPISODE_DOCTORWHO.year}`;
let response = await axios.get(url) as UmsApiMediaAxiosResponse;
expect(response.data.title).toEqual(EPISODE_DOCTORWHO.episodeTitle);
expect(response.data.type).toEqual('episode');

expect(response.data.seriesIMDbID).toEqual(EPISODE_DOCTORWHO.seriesIMDbID);

// subsequent calls should return MongoDB result rather than calling external apis
response = await axios.get(url);
expect(response.data.title).toEqual(EPISODE_DOCTORWHO.episodeTitle);
expect(response.data.type).toEqual('episode');
expect(response.data.seriesIMDbID).toEqual(EPISODE_DOCTORWHO.seriesIMDbID);
});

test('should return two episodes when passed all possible params, from source APIs then store', async() => {
const url = `${appUrl}/api/media/video/v2?`+
`osdbHash=${EPISODE_AVATAR.osdbHash}`+
Expand Down
Loading