diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/DownloadDecisionMakerFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/DownloadDecisionMakerFixture.cs index 7efd8eb71..5332589be 100644 --- a/src/NzbDrone.Core.Test/DecisionEngineTests/DownloadDecisionMakerFixture.cs +++ b/src/NzbDrone.Core.Test/DecisionEngineTests/DownloadDecisionMakerFixture.cs @@ -19,7 +19,6 @@ namespace NzbDrone.Core.Test.DecisionEngineTests { private List _reports; private RemoteMovie _remoteEpisode; - private FindMovieResult _mappingResult; private Mock _pass1; private Mock _pass2; @@ -55,10 +54,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests ParsedMovieInfo = new ParsedMovieInfo() }; - _mappingResult = new FindMovieResult(new Movie(), MovieMatchType.Title); - Mocker.GetMock() - .Setup(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny())).Returns(_remoteEpisode); + .Setup(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(_remoteEpisode); } private void GivenSpecifications(params Mock[] mocks) @@ -128,30 +125,13 @@ namespace NzbDrone.Core.Test.DecisionEngineTests Subject.GetRssDecision(_reports).ToList(); - Mocker.GetMock().Verify(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never()); + Mocker.GetMock().Verify(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never()); _pass1.Verify(c => c.IsSatisfiedBy(It.IsAny(), null), Times.Never()); _pass2.Verify(c => c.IsSatisfiedBy(It.IsAny(), null), Times.Never()); _pass3.Verify(c => c.IsSatisfiedBy(It.IsAny(), null), Times.Never()); } - [Test] - public void should_not_attempt_to_map_episode_if_series_title_is_blank() - { - GivenSpecifications(_pass1, _pass2, _pass3); - _reports[0].Title = "1937 - Snow White and the Seven Dwarves"; - - var results = Subject.GetRssDecision(_reports).ToList(); - - Mocker.GetMock().Verify(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never()); - - _pass1.Verify(c => c.IsSatisfiedBy(It.IsAny(), null), Times.Never()); - _pass2.Verify(c => c.IsSatisfiedBy(It.IsAny(), null), Times.Never()); - _pass3.Verify(c => c.IsSatisfiedBy(It.IsAny(), null), Times.Never()); - - results.Should().NotBeEmpty(); - } - [Test] public void should_return_rejected_result_for_unparsable_search() { @@ -160,7 +140,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests Subject.GetSearchDecision(_reports, new MovieSearchCriteria()).ToList(); - Mocker.GetMock().Verify(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never()); + Mocker.GetMock().Verify(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never()); _pass1.Verify(c => c.IsSatisfiedBy(It.IsAny(), null), Times.Never()); _pass2.Verify(c => c.IsSatisfiedBy(It.IsAny(), null), Times.Never()); @@ -186,7 +166,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests { GivenSpecifications(_pass1); - Mocker.GetMock().Setup(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny())) + Mocker.GetMock().Setup(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Throws(); _reports = new List @@ -198,7 +178,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests Subject.GetRssDecision(_reports); - Mocker.GetMock().Verify(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(_reports.Count)); + Mocker.GetMock().Verify(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(_reports.Count)); ExceptionVerification.ExpectedErrors(3); } @@ -249,7 +229,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests { GivenSpecifications(_pass1); - Mocker.GetMock().Setup(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny())) + Mocker.GetMock().Setup(c => c.Map(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Throws(); _reports = new List diff --git a/src/NzbDrone.Core.Test/Download/DownloadClientTests/DownloadClientFixtureBase.cs b/src/NzbDrone.Core.Test/Download/DownloadClientTests/DownloadClientFixtureBase.cs index 63dcc449c..1518227a1 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadClientTests/DownloadClientFixtureBase.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadClientTests/DownloadClientFixtureBase.cs @@ -32,7 +32,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests .Returns(30); Mocker.GetMock() - .Setup(s => s.Map(It.IsAny(), It.IsAny(), (SearchCriteriaBase)null)) + .Setup(s => s.Map(It.IsAny(), It.IsAny(), It.IsAny(), (SearchCriteriaBase)null)) .Returns(() => CreateRemoteMovie()); Mocker.GetMock() diff --git a/src/NzbDrone.Core.Test/Download/TrackedDownloads/TrackedDownloadServiceFixture.cs b/src/NzbDrone.Core.Test/Download/TrackedDownloads/TrackedDownloadServiceFixture.cs index 3cae416c9..bb3606005 100644 --- a/src/NzbDrone.Core.Test/Download/TrackedDownloads/TrackedDownloadServiceFixture.cs +++ b/src/NzbDrone.Core.Test/Download/TrackedDownloads/TrackedDownloadServiceFixture.cs @@ -55,7 +55,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads }; Mocker.GetMock() - .Setup(s => s.Map(It.Is(i => i.PrimaryMovieTitle == "A Movie"), It.IsAny(), null)) + .Setup(s => s.Map(It.Is(i => i.PrimaryMovieTitle == "A Movie"), It.IsAny(), It.IsAny(), null)) .Returns(remoteMovie); var client = new DownloadClientDefinition() @@ -101,7 +101,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads }; Mocker.GetMock() - .Setup(s => s.Map(It.IsAny(), It.IsAny(), null)) + .Setup(s => s.Map(It.IsAny(), It.IsAny(), It.IsAny(), null)) .Returns(remoteMovie); Mocker.GetMock() @@ -131,7 +131,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads Subject.GetTrackedDownloads().Should().HaveCount(1); Mocker.GetMock() - .Setup(s => s.Map(It.IsAny(), It.IsAny(), null)) + .Setup(s => s.Map(It.IsAny(), It.IsAny(), It.IsAny(), null)) .Returns(default(RemoteMovie)); Subject.Handle(new MoviesDeletedEvent(new List { remoteMovie.Movie }, false, false)); @@ -158,7 +158,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads }; Mocker.GetMock() - .Setup(s => s.Map(It.IsAny(), It.IsAny(), null)) + .Setup(s => s.Map(It.IsAny(), It.IsAny(), It.IsAny(), null)) .Returns(default(RemoteMovie)); Mocker.GetMock() @@ -188,7 +188,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads Subject.GetTrackedDownloads().Should().HaveCount(1); Mocker.GetMock() - .Setup(s => s.Map(It.IsAny(), It.IsAny(), null)) + .Setup(s => s.Map(It.IsAny(), It.IsAny(), It.IsAny(), null)) .Returns(default(RemoteMovie)); Subject.Handle(new MoviesDeletedEvent(new List { remoteMovie.Movie }, false, false)); diff --git a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs index 06c901040..c0ab1eb7c 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs @@ -129,7 +129,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests { GivenMatchByMovieTitle(); - Subject.Map(_parsedMovieInfo, "", null); + Subject.Map(_parsedMovieInfo, "", 0, null); Mocker.GetMock() .Verify(v => v.FindByTitle(It.IsAny>(), It.IsAny(), It.IsAny>(), null), Times.Once()); @@ -140,7 +140,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests { GivenMatchByMovieTitle(); - Subject.Map(_parsedMovieInfo, "", _movieSearchCriteria); + Subject.Map(_parsedMovieInfo, "", 0, _movieSearchCriteria); Mocker.GetMock() .Verify(v => v.FindByTitle(It.IsAny()), Times.Never()); @@ -149,26 +149,26 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests [Test] public void should_match_alternative_title() { - Subject.Map(_alternativeTitleInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie); + Subject.Map(_alternativeTitleInfo, "", 0, _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie); } [Test] public void should_match_translation_title() { - Subject.Map(_translationTitleInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie); + Subject.Map(_translationTitleInfo, "", 0, _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie); } [Test] public void should_match_roman_title() { - Subject.Map(_romanTitleInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie); + Subject.Map(_romanTitleInfo, "", 0, _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie); } [Test] public void should_match_umlauts() { - Subject.Map(_umlautInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie); - Subject.Map(_umlautAltInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie); + Subject.Map(_umlautInfo, "", 0, _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie); + Subject.Map(_umlautAltInfo, "", 0, _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie); } } } diff --git a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs index f0d07c989..de8fd3ca2 100644 --- a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs +++ b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs @@ -80,7 +80,7 @@ namespace NzbDrone.Core.DecisionEngine if (parsedMovieInfo != null && !parsedMovieInfo.PrimaryMovieTitle.IsNullOrWhiteSpace()) { - var remoteMovie = _parsingService.Map(parsedMovieInfo, report.ImdbId.ToString(), searchCriteria); + var remoteMovie = _parsingService.Map(parsedMovieInfo, report.ImdbId.ToString(), report.TmdbId, searchCriteria); remoteMovie.Release = report; if (remoteMovie.Movie == null) diff --git a/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs b/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs index 00111cfe5..4f911aa21 100644 --- a/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs +++ b/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs @@ -122,7 +122,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads if (parsedMovieInfo != null) { - trackedDownload.RemoteMovie = _parsingService.Map(parsedMovieInfo, "", null); + trackedDownload.RemoteMovie = _parsingService.Map(parsedMovieInfo, "", 0, null); _aggregationService.Augment(trackedDownload.RemoteMovie); } @@ -205,7 +205,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads { var parsedMovieInfo = Parser.Parser.ParseMovieTitle(trackedDownload.DownloadItem.Title); - trackedDownload.RemoteMovie = parsedMovieInfo == null ? null : _parsingService.Map(parsedMovieInfo, "", null); + trackedDownload.RemoteMovie = parsedMovieInfo == null ? null : _parsingService.Map(parsedMovieInfo, "", 0, null); _aggregationService.Augment(trackedDownload.RemoteMovie); } diff --git a/src/NzbDrone.Core/Parser/ParsingService.cs b/src/NzbDrone.Core/Parser/ParsingService.cs index a75e5a475..3496d37c8 100644 --- a/src/NzbDrone.Core/Parser/ParsingService.cs +++ b/src/NzbDrone.Core/Parser/ParsingService.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using NLog; -using NzbDrone.Core.DecisionEngine; +using NzbDrone.Common.Extensions; using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.Movies; using NzbDrone.Core.Parser.Model; @@ -13,7 +13,7 @@ namespace NzbDrone.Core.Parser public interface IParsingService { Movie GetMovie(string title); - RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, string imdbId, SearchCriteriaBase searchCriteria = null); + RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, string imdbId, int tmdbId, SearchCriteriaBase searchCriteria = null); RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, int movieId); ParsedMovieInfo ParseMinimalPathMovieInfo(string path); } @@ -67,7 +67,9 @@ namespace NzbDrone.Core.Parser return _movieService.FindByTitle(title); } - if (TryGetMovieByTitleAndOrYear(parsedMovieInfo, out var result)) + var result = TryGetMovieByTitleAndOrYear(parsedMovieInfo); + + if (result != null) { return result.Movie; } @@ -75,9 +77,9 @@ namespace NzbDrone.Core.Parser return null; } - public RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, string imdbId, SearchCriteriaBase searchCriteria = null) + public RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, string imdbId, int tmdbId, SearchCriteriaBase searchCriteria = null) { - return Map(parsedMovieInfo, imdbId, null, searchCriteria); + return Map(parsedMovieInfo, imdbId, tmdbId, null, searchCriteria); } public RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, int movieId) @@ -89,7 +91,7 @@ namespace NzbDrone.Core.Parser }; } - public RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, string imdbId, Movie movie, SearchCriteriaBase searchCriteria) + public RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, string imdbId, int tmdbId, Movie movie, SearchCriteriaBase searchCriteria) { var remoteMovie = new RemoteMovie { @@ -98,7 +100,7 @@ namespace NzbDrone.Core.Parser if (movie == null) { - var movieMatch = FindMovie(parsedMovieInfo, imdbId, searchCriteria); + var movieMatch = FindMovie(parsedMovieInfo, imdbId, tmdbId, searchCriteria); if (movieMatch != null) { @@ -117,62 +119,67 @@ namespace NzbDrone.Core.Parser return remoteMovie; } - private FindMovieResult FindMovie(ParsedMovieInfo parsedMovieInfo, string imdbId, SearchCriteriaBase searchCriteria) + private FindMovieResult FindMovie(ParsedMovieInfo parsedMovieInfo, string imdbId, int tmdbId, SearchCriteriaBase searchCriteria) { FindMovieResult result = null; if (!string.IsNullOrWhiteSpace(imdbId) && imdbId != "0") { - if (TryGetMovieByImDbId(parsedMovieInfo, imdbId, out result)) + result = TryGetMovieByImDbId(parsedMovieInfo, imdbId); + } + + if (result == null && tmdbId > 0) + { + result = TryGetMovieByTmdbId(parsedMovieInfo, tmdbId); + } + + if (result == null) + { + if (searchCriteria != null) { - return result; + result = TryGetMovieBySearchCriteria(parsedMovieInfo, imdbId, tmdbId, searchCriteria); + } + else + { + result = TryGetMovieByTitleAndOrYear(parsedMovieInfo); } } - if (searchCriteria != null) + if (result == null) { - if (TryGetMovieBySearchCriteria(parsedMovieInfo, searchCriteria, out result)) - { - return result; - } - } - else - { - if (TryGetMovieByTitleAndOrYear(parsedMovieInfo, out result)) - { - return result; - } + _logger.Debug($"No matching movie for titles {string.Join(", ", parsedMovieInfo.MovieTitles)} ({parsedMovieInfo.Year})"); } - // nothing found up to here => logging that and returning null - _logger.Debug($"No matching movie for titles {string.Join(", ", parsedMovieInfo.MovieTitles)} ({parsedMovieInfo.Year})"); return result; } - private bool TryGetMovieByImDbId(ParsedMovieInfo parsedMovieInfo, string imdbId, out FindMovieResult result) + private FindMovieResult TryGetMovieByImDbId(ParsedMovieInfo parsedMovieInfo, string imdbId) { var movie = _movieService.FindByImdbId(imdbId); // Should fix practically all problems, where indexer is shite at adding correct imdbids to movies. - if (movie != null && parsedMovieInfo.Year > 1800 && (parsedMovieInfo.Year != movie.MovieMetadata.Value.Year && movie.MovieMetadata.Value.SecondaryYear != parsedMovieInfo.Year)) + if (movie != null && (parsedMovieInfo.Year < 1800 || movie.MovieMetadata.Value.Year == parsedMovieInfo.Year || movie.MovieMetadata.Value.SecondaryYear == parsedMovieInfo.Year)) { - result = new FindMovieResult(movie, MovieMatchType.Id); - return false; + return new FindMovieResult(movie, MovieMatchType.Id); } - if (movie != null) - { - result = new FindMovieResult(movie, MovieMatchType.Id); - } - else - { - result = new FindMovieResult(movie, MovieMatchType.Unknown); - } - - return movie != null; + return null; } - private bool TryGetMovieByTitleAndOrYear(ParsedMovieInfo parsedMovieInfo, out FindMovieResult result) + private FindMovieResult TryGetMovieByTmdbId(ParsedMovieInfo parsedMovieInfo, int tmdbId) + { + var movie = _movieService.FindByTmdbId(tmdbId); + + // Should fix practically all problems, where indexer is shite at adding correct imdbids to movies. + if (movie != null && (parsedMovieInfo.Year < 1800 || movie.MovieMetadata.Value.Year == parsedMovieInfo.Year || movie.MovieMetadata.Value.SecondaryYear == parsedMovieInfo.Year)) + { + return new FindMovieResult(movie, MovieMatchType.Id); + } + + return null; + } + + private FindMovieResult TryGetMovieByTitleAndOrYear(ParsedMovieInfo parsedMovieInfo) { var candidates = _movieService.FindByTitleCandidates(parsedMovieInfo.MovieTitles, out var otherTitles); @@ -182,8 +189,7 @@ namespace NzbDrone.Core.Parser movieByTitleAndOrYear = _movieService.FindByTitle(parsedMovieInfo.MovieTitles, parsedMovieInfo.Year, otherTitles, candidates); if (movieByTitleAndOrYear != null) { - result = new FindMovieResult(movieByTitleAndOrYear, MovieMatchType.Title); - return true; + return new FindMovieResult(movieByTitleAndOrYear, MovieMatchType.Title); } // Only default to not using year when one is parsed if only one movie candidate exists @@ -192,33 +198,31 @@ namespace NzbDrone.Core.Parser movieByTitleAndOrYear = _movieService.FindByTitle(parsedMovieInfo.MovieTitles, null, otherTitles, candidates); if (movieByTitleAndOrYear != null) { - result = new FindMovieResult(movieByTitleAndOrYear, MovieMatchType.Title); - return false; + return new FindMovieResult(movieByTitleAndOrYear, MovieMatchType.Title); } } - result = new FindMovieResult(movieByTitleAndOrYear, MovieMatchType.Unknown); - return false; + return null; } movieByTitleAndOrYear = _movieService.FindByTitle(parsedMovieInfo.MovieTitles, null, otherTitles, candidates); if (movieByTitleAndOrYear != null) { - result = new FindMovieResult(movieByTitleAndOrYear, MovieMatchType.Title); - return true; + return new FindMovieResult(movieByTitleAndOrYear, MovieMatchType.Title); } - result = new FindMovieResult(movieByTitleAndOrYear, MovieMatchType.Unknown); - return false; + return null; } - private bool TryGetMovieBySearchCriteria(ParsedMovieInfo parsedMovieInfo, SearchCriteriaBase searchCriteria, out FindMovieResult result) + private FindMovieResult TryGetMovieBySearchCriteria(ParsedMovieInfo parsedMovieInfo, string imdbId, int tmdbId, SearchCriteriaBase searchCriteria) { Movie possibleMovie = null; - var possibleTitles = new List(); - - possibleTitles.Add(searchCriteria.Movie.MovieMetadata.Value.CleanTitle); + var possibleTitles = new List + { + searchCriteria.Movie.MovieMetadata.Value.CleanTitle + }; + possibleTitles.AddIfNotNull(searchCriteria.Movie.MovieMetadata.Value.CleanOriginalTitle); possibleTitles.AddRange(searchCriteria.Movie.MovieMetadata.Value.AlternativeTitles.Select(t => t.CleanTitle)); possibleTitles.AddRange(searchCriteria.Movie.MovieMetadata.Value.Translations.Select(t => t.CleanTitle)); @@ -237,17 +241,21 @@ namespace NzbDrone.Core.Parser { if (parsedMovieInfo.Year < 1800 || possibleMovie.MovieMetadata.Value.Year == parsedMovieInfo.Year || possibleMovie.MovieMetadata.Value.SecondaryYear == parsedMovieInfo.Year) { - result = new FindMovieResult(possibleMovie, MovieMatchType.Title); - return true; + return new FindMovieResult(possibleMovie, MovieMatchType.Title); } - - result = new FindMovieResult(possibleMovie, MovieMatchType.Title); - return false; } - result = new FindMovieResult(searchCriteria.Movie, MovieMatchType.Unknown); + if (tmdbId > 0 && tmdbId == searchCriteria.Movie.TmdbId) + { + return new FindMovieResult(searchCriteria.Movie, MovieMatchType.Id); + } - return false; + if (imdbId.IsNotNullOrWhiteSpace() && imdbId == searchCriteria.Movie.ImdbId) + { + return new FindMovieResult(searchCriteria.Movie, MovieMatchType.Id); + } + + return null; } } } diff --git a/src/Radarr.Api.V3/Parse/ParseController.cs b/src/Radarr.Api.V3/Parse/ParseController.cs index 19543cbb5..2aa993334 100644 --- a/src/Radarr.Api.V3/Parse/ParseController.cs +++ b/src/Radarr.Api.V3/Parse/ParseController.cs @@ -43,7 +43,7 @@ namespace Radarr.Api.V3.Parse }; } - var remoteMovie = _parsingService.Map(parsedMovieInfo, ""); + var remoteMovie = _parsingService.Map(parsedMovieInfo, "", 0); _aggregationService.Augment(remoteMovie);