mirror of https://github.com/Radarr/Radarr
New: Support AKA release titles
Co-Authored-By: aeonnoea <46950349+0aeonnoea0@users.noreply.github.com>
This commit is contained in:
parent
f9dab9d780
commit
9d6614b14a
|
@ -55,7 +55,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
{
|
||||
var remoteMovie = new RemoteMovie();
|
||||
remoteMovie.ParsedMovieInfo = new ParsedMovieInfo();
|
||||
remoteMovie.ParsedMovieInfo.MovieTitle = "A Movie";
|
||||
remoteMovie.ParsedMovieInfo.MovieTitles = new List<string> { "A Movie" };
|
||||
remoteMovie.ParsedMovieInfo.Year = 1998;
|
||||
remoteMovie.ParsedMovieInfo.Quality = quality;
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
|||
{
|
||||
Quality = quality,
|
||||
Year = 1998,
|
||||
MovieTitle = "A Movie",
|
||||
MovieTitles = new List<string> { "A Movie" },
|
||||
},
|
||||
Movie = movie,
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
|||
_pending.Add(new PendingRelease
|
||||
{
|
||||
Id = id,
|
||||
ParsedMovieInfo = new ParsedMovieInfo { MovieTitle = title, Year = year },
|
||||
ParsedMovieInfo = new ParsedMovieInfo { MovieTitles = new List<string> { title }, Year = year },
|
||||
MovieId = _movie.Id
|
||||
});
|
||||
}
|
||||
|
|
|
@ -49,13 +49,13 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
|||
|
||||
ParsedMovieInfo = new ParsedMovieInfo()
|
||||
{
|
||||
MovieTitle = "A Movie",
|
||||
MovieTitles = new List<string> { "A Movie" },
|
||||
Year = 1998
|
||||
}
|
||||
};
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.Is<ParsedMovieInfo>(i => i.MovieTitle == "A Movie"), It.IsAny<string>(), null))
|
||||
.Setup(s => s.Map(It.Is<ParsedMovieInfo>(i => i.PrimaryMovieTitle == "A Movie"), It.IsAny<string>(), null))
|
||||
.Returns(new MappingResult { RemoteMovie = remoteEpisode });
|
||||
|
||||
ParseMovieTitle();
|
||||
|
@ -97,7 +97,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
|||
|
||||
ParsedMovieInfo = new ParsedMovieInfo()
|
||||
{
|
||||
MovieTitle = "A Movie",
|
||||
MovieTitles = { "A Movie" },
|
||||
Year = 1998
|
||||
}
|
||||
};
|
||||
|
@ -156,7 +156,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
|||
|
||||
ParsedMovieInfo = new ParsedMovieInfo()
|
||||
{
|
||||
MovieTitle = "A Movie",
|
||||
MovieTitles = { "A Movie" },
|
||||
Year = 1998
|
||||
}
|
||||
};
|
||||
|
|
|
@ -73,7 +73,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
|
|||
|
||||
_fileInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = "The Office",
|
||||
MovieTitles = new List<string> { "The Office" },
|
||||
Year = 2018,
|
||||
Quality = _quality
|
||||
};
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.Movies.AlternativeTitles;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class FindByTitleFixture : CoreTest<MovieService>
|
||||
{
|
||||
private List<Movie> _candidates;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_candidates = Builder<Movie>.CreateListOfSize(3)
|
||||
.TheFirst(1)
|
||||
.With(x => x.CleanTitle = "batman")
|
||||
.With(x => x.Year = 2000)
|
||||
.TheNext(1)
|
||||
.With(x => x.CleanTitle = "batman")
|
||||
.With(x => x.Year = 1999)
|
||||
.TheRest()
|
||||
.With(x => x.CleanTitle = "darkknight")
|
||||
.With(x => x.Year = 2008)
|
||||
.With(x => x.AlternativeTitles = new List<AlternativeTitle>
|
||||
{
|
||||
new AlternativeTitle
|
||||
{
|
||||
CleanTitle = "batman"
|
||||
}
|
||||
})
|
||||
.Build()
|
||||
.ToList();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_find_by_title_year()
|
||||
{
|
||||
var movie = Subject.FindByTitle(new List<string> { "batman" }, 2000, new List<string>(), _candidates);
|
||||
|
||||
movie.Should().NotBeNull();
|
||||
movie.Year.Should().Be(2000);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_find_candidates_by_alt_titles()
|
||||
{
|
||||
var movie = Subject.FindByTitle(new List<string> { "batman" }, 2008, new List<string>(), _candidates);
|
||||
movie.Should().NotBeNull();
|
||||
movie.Year.Should().Be(2008);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -95,7 +95,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
public void should_properly_parse_hashed_releases(string path, string title, Quality quality, string releaseGroup)
|
||||
{
|
||||
var result = Parser.Parser.ParseMoviePath(path);
|
||||
result.MovieTitle.Should().Be(title);
|
||||
result.PrimaryMovieTitle.Should().Be(title);
|
||||
result.Quality.Quality.Should().Be(quality);
|
||||
result.ReleaseGroup.Should().Be(releaseGroup);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
[TestCase("www.Torrenting.org - Movie.2008.720p.X264-DIMENSION", "Movie")]
|
||||
public void should_parse_movie_title(string postTitle, string title)
|
||||
{
|
||||
Parser.Parser.ParseMovieTitle(postTitle).MovieTitle.Should().Be(title);
|
||||
Parser.Parser.ParseMovieTitle(postTitle).PrimaryMovieTitle.Should().Be(title);
|
||||
}
|
||||
|
||||
[TestCase("Movie.Aufbruch.nach.Pandora.Extended.2009.German.DTS.720p.BluRay.x264-SoW", "Movie Aufbruch nach Pandora", "Extended", 2009)]
|
||||
|
@ -99,16 +99,85 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
ParsedMovieInfo movie = Parser.Parser.ParseMovieTitle(postTitle);
|
||||
using (new AssertionScope())
|
||||
{
|
||||
movie.MovieTitle.Should().Be(title);
|
||||
movie.PrimaryMovieTitle.Should().Be(title);
|
||||
movie.Edition.Should().Be(edition);
|
||||
movie.Year.Should().Be(year);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase("L'hypothèse.du.tableau.volé.AKA.The.Hypothesis.of.the.Stolen.Painting.1978.1080p.CINET.WEB-DL.AAC2.0.x264-Cinefeel.mkv",
|
||||
new string[]
|
||||
{
|
||||
"L'hypothèse du tableau volé AKA The Hypothesis of the Stolen Painting",
|
||||
"L'hypothèse du tableau volé",
|
||||
"The Hypothesis of the Stolen Painting"
|
||||
})]
|
||||
[TestCase("Akahige.AKA.Red.Beard.1965.CD1.CRiTERiON.DVDRip.XviD-KG.avi",
|
||||
new string[]
|
||||
{
|
||||
"Akahige AKA Red Beard",
|
||||
"Akahige",
|
||||
"Red Beard"
|
||||
})]
|
||||
[TestCase("Akasen.chitai.AKA.Street.of.Shame.1956.1080p.BluRay.x264.FLAC.1.0.mkv",
|
||||
new string[]
|
||||
{
|
||||
"Akasen chitai AKA Street of Shame",
|
||||
"Akasen chitai",
|
||||
"Street of Shame"
|
||||
})]
|
||||
[TestCase("Time.Under.Fire.(aka.Beneath.the.Bermuda.Triangle).1997.DVDRip.x264.CG-Grzechsin.mkv",
|
||||
new string[]
|
||||
{
|
||||
"Time Under Fire (aka Beneath the Bermuda Triangle)",
|
||||
"Time Under Fire",
|
||||
"Beneath the Bermuda Triangle"
|
||||
})]
|
||||
[TestCase("Nochnoy.prodavet. AKA.Graveyard.Shift.2005.DVDRip.x264-HANDJOB.mkv",
|
||||
new string[]
|
||||
{
|
||||
"Nochnoy prodavet AKA Graveyard Shift",
|
||||
"Nochnoy prodavet",
|
||||
"Graveyard Shift"
|
||||
})]
|
||||
[TestCase("AKA.2002.DVDRip.x264-HANDJOB.mkv",
|
||||
new string[]
|
||||
{
|
||||
"AKA"
|
||||
})]
|
||||
[TestCase("Unbreakable.2000.BluRay.1080p.DTS.x264.dxva-EuReKA.mkv",
|
||||
new string[]
|
||||
{
|
||||
"Unbreakable"
|
||||
})]
|
||||
[TestCase("Aka Ana (2008).avi",
|
||||
new string[]
|
||||
{
|
||||
"Aka Ana"
|
||||
})]
|
||||
[TestCase("Return to Return to Nuke 'em High aka Volume 2 (2018) 1080p.mp4",
|
||||
new string[]
|
||||
{
|
||||
"Return to Return to Nuke 'em High aka Volume 2",
|
||||
"Return to Return to Nuke 'em High",
|
||||
"Volume 2"
|
||||
})]
|
||||
public void should_parse_movie_alternative_titles(string postTitle, string[] parsedTitles)
|
||||
{
|
||||
var movieInfo = Parser.Parser.ParseMovieTitle(postTitle, true);
|
||||
|
||||
movieInfo.MovieTitles.Count.Should().Be(parsedTitles.Length);
|
||||
|
||||
for (var i = 0; i < movieInfo.MovieTitles.Count; i += 1)
|
||||
{
|
||||
movieInfo.MovieTitles[i].Should().Be(parsedTitles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase("(1995) Movie Name", "Movie Name")]
|
||||
public void should_parse_movie_folder_name(string postTitle, string title)
|
||||
{
|
||||
Parser.Parser.ParseMovieTitle(postTitle, true).MovieTitle.Should().Be(title);
|
||||
Parser.Parser.ParseMovieTitle(postTitle, true).PrimaryMovieTitle.Should().Be(title);
|
||||
}
|
||||
|
||||
[TestCase("1776.1979.EXTENDED.720p.BluRay.X264-AMIABLE", 1979)]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Parser.Augmenters;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
@ -17,7 +18,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests
|
|||
{
|
||||
MovieInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = "A Movie",
|
||||
MovieTitles = new List<string> { "A Movie" },
|
||||
Year = 1998,
|
||||
SimpleReleaseTitle = "A Movie Title 1998 Bluray 1080p",
|
||||
Quality = new QualityModel(Quality.Bluray1080p)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Movies;
|
||||
|
@ -28,7 +29,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
Subject.GetMovie(title);
|
||||
|
||||
Mocker.GetMock<IMovieService>()
|
||||
.Verify(s => s.FindByTitle(Parser.Parser.ParseMovieTitle(title, false).MovieTitle, It.IsAny<int>(), null, null, null), Times.Once());
|
||||
.Verify(s => s.FindByTitle(Parser.Parser.ParseMovieTitle(title, false).MovieTitles, It.IsAny<int>(), It.IsAny<List<string>>(), null), Times.Once());
|
||||
}
|
||||
|
||||
/*[Test]
|
||||
|
|
|
@ -45,69 +45,69 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
|
||||
_parsedMovieInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = _movie.Title,
|
||||
MovieTitles = new List<string> { _movie.Title },
|
||||
Languages = new List<Language> { Language.English },
|
||||
Year = _movie.Year,
|
||||
};
|
||||
|
||||
_wrongYearInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = _movie.Title,
|
||||
MovieTitles = new List<string> { _movie.Title },
|
||||
Languages = new List<Language> { Language.English },
|
||||
Year = 1900,
|
||||
};
|
||||
|
||||
_wrongTitleInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = "Other Title",
|
||||
MovieTitles = new List<string> { "Other Title" },
|
||||
Languages = new List<Language> { Language.English },
|
||||
Year = 2015
|
||||
};
|
||||
|
||||
_alternativeTitleInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = _movie.AlternativeTitles.First().Title,
|
||||
MovieTitles = new List<string> { _movie.AlternativeTitles.First().Title },
|
||||
Languages = new List<Language> { Language.English },
|
||||
Year = _movie.Year,
|
||||
};
|
||||
|
||||
_translationTitleInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = _movie.Translations.First().Title,
|
||||
MovieTitles = new List<string> { _movie.Translations.First().Title },
|
||||
Languages = new List<Language> { Language.English },
|
||||
Year = _movie.Year,
|
||||
};
|
||||
|
||||
_romanTitleInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = "Fack Ju Göthe II",
|
||||
MovieTitles = new List<string> { "Fack Ju Göthe II" },
|
||||
Languages = new List<Language> { Language.English },
|
||||
Year = _movie.Year,
|
||||
};
|
||||
|
||||
_umlautInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = "Fack Ju Goethe 2",
|
||||
MovieTitles = new List<string> { "Fack Ju Goethe 2" },
|
||||
Languages = new List<Language> { Language.English },
|
||||
Year = _movie.Year
|
||||
};
|
||||
|
||||
_umlautAltInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = "Fack Ju Goethe 2: Same same",
|
||||
MovieTitles = new List<string> { "Fack Ju Goethe 2: Same same" },
|
||||
Languages = new List<Language> { Language.English },
|
||||
Year = _movie.Year
|
||||
};
|
||||
|
||||
_multiLanguageInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = _movie.Title,
|
||||
MovieTitles = { _movie.Title },
|
||||
Languages = new List<Language> { Language.Original, Language.French }
|
||||
};
|
||||
|
||||
_multiLanguageWithOriginalInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = _movie.Title,
|
||||
MovieTitles = { _movie.Title },
|
||||
Languages = new List<Language> { Language.Original, Language.French, Language.English }
|
||||
};
|
||||
|
||||
|
@ -132,7 +132,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
Subject.Map(_parsedMovieInfo, "", null);
|
||||
|
||||
Mocker.GetMock<IMovieService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>(), It.IsAny<int>(), null, null, null), Times.Once());
|
||||
.Verify(v => v.FindByTitle(It.IsAny<List<string>>(), It.IsAny<int>(), It.IsAny<List<string>>(), null), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -286,6 +286,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
[TestCase("Movie.Name.2008.BDREMUX.1080p.Bluray.AVC.DTS-HR.MA.5.1-LEGi0N")]
|
||||
[TestCase("Movie.Title.M.2008.USA.BluRay.Remux.1080p.MPEG-2.DD.5.1-TDD")]
|
||||
[TestCase("Movie.Title.2018.1080p.BluRay.REMUX.MPEG-2.DTS-HD.MA.5.1-EPSiLON")]
|
||||
[TestCase("Movie.Title.II.2003.4K.BluRay.Remux.1080p.AVC.DTS-HD.MA.5.1-BMF")]
|
||||
public void should_parse_remux1080p_quality(string title)
|
||||
{
|
||||
ParseAndVerifyQuality(title, Source.BLURAY, false, Resolution.R1080p, Modifier.REMUX);
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace NzbDrone.Core.CustomFormats
|
|||
|
||||
var info = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = movieFile.Movie.Title,
|
||||
MovieTitles = new List<string>() { movieFile.Movie.Title },
|
||||
SimpleReleaseTitle = sceneName.SimplifyReleaseTitle(),
|
||||
Quality = movieFile.Quality,
|
||||
Languages = movieFile.Languages,
|
||||
|
@ -112,7 +112,7 @@ namespace NzbDrone.Core.CustomFormats
|
|||
|
||||
var info = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = movie.Title,
|
||||
MovieTitles = new List<string>() { movie.Title },
|
||||
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? blocklist.SourceTitle.SimplifyReleaseTitle(),
|
||||
Quality = blocklist.Quality,
|
||||
Languages = blocklist.Languages,
|
||||
|
@ -140,7 +140,7 @@ namespace NzbDrone.Core.CustomFormats
|
|||
|
||||
var info = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = movie.Title,
|
||||
MovieTitles = new List<string>() { movie.Title },
|
||||
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? history.SourceTitle.SimplifyReleaseTitle(),
|
||||
Quality = history.Quality,
|
||||
Languages = history.Languages,
|
||||
|
|
|
@ -77,12 +77,12 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
|
||||
MappingResult result = null;
|
||||
|
||||
if (parsedMovieInfo == null || parsedMovieInfo.MovieTitle.IsNullOrWhiteSpace())
|
||||
if (parsedMovieInfo == null || parsedMovieInfo.PrimaryMovieTitle.IsNullOrWhiteSpace())
|
||||
{
|
||||
_logger.Debug("{0} could not be parsed :(.", report.Title);
|
||||
parsedMovieInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = report.Title,
|
||||
MovieTitles = new List<string>() { report.Title },
|
||||
SimpleReleaseTitle = report.Title.SimplifyReleaseTitle(),
|
||||
Year = 1290,
|
||||
Languages = new List<Language> { Language.Unknown },
|
||||
|
|
|
@ -227,7 +227,7 @@ namespace NzbDrone.Core.Download.Pending
|
|||
var targetItem = FindPendingRelease(queueId);
|
||||
var movieReleases = _repository.AllByMovieId(targetItem.MovieId);
|
||||
|
||||
var releasesToRemove = movieReleases.Where(c => c.ParsedMovieInfo.MovieTitle == targetItem.ParsedMovieInfo.MovieTitle);
|
||||
var releasesToRemove = movieReleases.Where(c => c.ParsedMovieInfo.PrimaryMovieTitle == targetItem.ParsedMovieInfo.PrimaryMovieTitle);
|
||||
|
||||
_repository.DeleteMany(releasesToRemove.Select(c => c.Id));
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ namespace NzbDrone.Core.ImportLists.RSSImport
|
|||
|
||||
if (result != null)
|
||||
{
|
||||
releaseInfo.Title = result.MovieTitle;
|
||||
releaseInfo.Title = result.PrimaryMovieTitle;
|
||||
releaseInfo.Year = result.Year;
|
||||
releaseInfo.ImdbId = result.ImdbId;
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
|
|||
|
||||
if (movie == null)
|
||||
{
|
||||
_parsingService.GetMovie(relativeFile.Split('\\', '/')[0]);
|
||||
movie = _parsingService.GetMovie(relativeFile.Split('\\', '/')[0]);
|
||||
}
|
||||
|
||||
if (movie == null)
|
||||
|
@ -189,7 +189,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
|
|||
|
||||
if (relativeParseInfo != null)
|
||||
{
|
||||
movie = _movieService.FindByTitle(relativeParseInfo.MovieTitle, relativeParseInfo.Year);
|
||||
movie = _movieService.FindByTitle(relativeParseInfo.PrimaryMovieTitle, relativeParseInfo.Year);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -322,10 +322,10 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
|
||||
var yearTerm = "";
|
||||
|
||||
if (parserResult != null && parserResult.MovieTitle != title)
|
||||
if (parserResult != null && parserResult.PrimaryMovieTitle != title)
|
||||
{
|
||||
//Parser found something interesting!
|
||||
parserTitle = parserResult.MovieTitle.ToLower().Replace(".", " "); //TODO Update so not every period gets replaced (e.g. R.I.P.D.)
|
||||
parserTitle = parserResult.PrimaryMovieTitle.ToLower().Replace(".", " "); //TODO Update so not every period gets replaced (e.g. R.I.P.D.)
|
||||
if (parserResult.Year > 1800)
|
||||
{
|
||||
yearTerm = parserResult.Year.ToString();
|
||||
|
|
|
@ -27,8 +27,8 @@ namespace NzbDrone.Core.Movies
|
|||
List<Movie> FindByTmdbId(List<int> tmdbids);
|
||||
Movie FindByTitle(string title);
|
||||
Movie FindByTitle(string title, int year);
|
||||
Movie FindByTitle(string title, int? year, string arabicTitle, string romanTitle, List<Movie> candidates);
|
||||
List<Movie> FindByTitleCandidates(string title, out string roman, out string arabic);
|
||||
Movie FindByTitle(List<string> titles, int? year, List<string> otherTitles, List<Movie> candidates);
|
||||
List<Movie> FindByTitleCandidates(List<string> titles, out List<string> otherTitles);
|
||||
Movie FindByTitleSlug(string slug);
|
||||
Movie FindByPath(string path);
|
||||
Dictionary<int, string> AllMoviePaths();
|
||||
|
@ -106,68 +106,74 @@ namespace NzbDrone.Core.Movies
|
|||
|
||||
public Movie FindByTitle(string title)
|
||||
{
|
||||
var candidates = FindByTitleCandidates(title, out var arabicTitle, out var romanTitle);
|
||||
var candidates = FindByTitleCandidates(new List<string> { title }, out var otherTitles);
|
||||
|
||||
return FindByTitle(title, null, arabicTitle, romanTitle, candidates);
|
||||
return FindByTitle(new List<string> { title }, null, otherTitles, candidates);
|
||||
}
|
||||
|
||||
public Movie FindByTitle(string title, int year)
|
||||
{
|
||||
var candidates = FindByTitleCandidates(title, out var arabicTitle, out var romanTitle);
|
||||
var candidates = FindByTitleCandidates(new List<string> { title }, out var otherTitles);
|
||||
|
||||
return FindByTitle(title, year, arabicTitle, romanTitle, candidates);
|
||||
return FindByTitle(new List<string> { title }, year, otherTitles, candidates);
|
||||
}
|
||||
|
||||
public Movie FindByTitle(string cleanTitle, int? year, string arabicTitle, string romanTitle, List<Movie> candidates)
|
||||
public Movie FindByTitle(List<string> cleanTitles, int? year, List<string> otherTitles, List<Movie> candidates)
|
||||
{
|
||||
var result = candidates.Where(x => x.CleanTitle == cleanTitle).FirstWithYear(year);
|
||||
var result = candidates.Where(x => cleanTitles.Contains(x.CleanTitle)).FirstWithYear(year);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
result =
|
||||
candidates.Where(movie => movie.CleanTitle == arabicTitle).FirstWithYear(year) ??
|
||||
candidates.Where(movie => movie.CleanTitle == romanTitle).FirstWithYear(year);
|
||||
candidates.Where(movie => otherTitles.Contains(movie.CleanTitle)).FirstWithYear(year);
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
result = candidates
|
||||
.Where(m => m.AlternativeTitles.Any(t => t.CleanTitle == cleanTitle ||
|
||||
t.CleanTitle == arabicTitle ||
|
||||
t.CleanTitle == romanTitle))
|
||||
.Where(m => m.AlternativeTitles.Any(t => cleanTitles.Contains(t.CleanTitle) ||
|
||||
otherTitles.Contains(t.CleanTitle)))
|
||||
.FirstWithYear(year);
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
result = candidates
|
||||
.Where(m => m.Translations.Any(t => t.CleanTitle == cleanTitle ||
|
||||
t.CleanTitle == arabicTitle ||
|
||||
t.CleanTitle == romanTitle))
|
||||
.Where(m => m.Translations.Any(t => cleanTitles.Contains(t.CleanTitle) ||
|
||||
otherTitles.Contains(t.CleanTitle)))
|
||||
.FirstWithYear(year);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Movie> FindByTitleCandidates(string title, out string arabicTitle, out string romanTitle)
|
||||
public List<Movie> FindByTitleCandidates(List<string> titles, out List<string> otherTitles)
|
||||
{
|
||||
var cleanTitle = title.CleanMovieTitle().ToLowerInvariant();
|
||||
romanTitle = cleanTitle;
|
||||
arabicTitle = cleanTitle;
|
||||
var lookupTitles = new List<string>();
|
||||
otherTitles = new List<string>();
|
||||
|
||||
foreach (var arabicRomanNumeral in RomanNumeralParser.GetArabicRomanNumeralsMapping())
|
||||
foreach (var title in titles)
|
||||
{
|
||||
var arabicNumber = arabicRomanNumeral.ArabicNumeralAsString;
|
||||
var romanNumber = arabicRomanNumeral.RomanNumeral;
|
||||
var cleanTitle = title.CleanMovieTitle().ToLowerInvariant();
|
||||
var romanTitle = cleanTitle;
|
||||
var arabicTitle = cleanTitle;
|
||||
|
||||
romanTitle = romanTitle.Replace(arabicNumber, romanNumber);
|
||||
arabicTitle = arabicTitle.Replace(romanNumber, arabicNumber);
|
||||
foreach (var arabicRomanNumeral in RomanNumeralParser.GetArabicRomanNumeralsMapping())
|
||||
{
|
||||
var arabicNumber = arabicRomanNumeral.ArabicNumeralAsString;
|
||||
var romanNumber = arabicRomanNumeral.RomanNumeral;
|
||||
|
||||
romanTitle = romanTitle.Replace(arabicNumber, romanNumber);
|
||||
arabicTitle = arabicTitle.Replace(romanNumber, arabicNumber);
|
||||
}
|
||||
|
||||
romanTitle = romanTitle.ToLowerInvariant();
|
||||
|
||||
otherTitles.AddRange(new List<string> { arabicTitle, romanTitle });
|
||||
lookupTitles.AddRange(new List<string> { cleanTitle, arabicTitle, romanTitle });
|
||||
}
|
||||
|
||||
romanTitle = romanTitle.ToLowerInvariant();
|
||||
|
||||
return _movieRepository.FindByTitles(new List<string> { cleanTitle, arabicTitle, romanTitle });
|
||||
return _movieRepository.FindByTitles(lookupTitles);
|
||||
}
|
||||
|
||||
public Movie FindByImdbId(string imdbid)
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace NzbDrone.Core.Parser.Augmenters
|
|||
} // First, let's augment the language!
|
||||
|
||||
var languageTitle = movieInfo.SimpleReleaseTitle;
|
||||
if (movieInfo.MovieTitle.IsNotNullOrWhiteSpace())
|
||||
if (movieInfo.PrimaryMovieTitle.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
if (languageTitle.ToLower().Contains("multi") && indexerSettings?.MultiLanguages?.Any() == true)
|
||||
{
|
||||
|
|
|
@ -7,12 +7,18 @@ namespace NzbDrone.Core.Parser.Model
|
|||
{
|
||||
public class ParsedMovieInfo
|
||||
{
|
||||
public string MovieTitle { get; set; }
|
||||
public ParsedMovieInfo()
|
||||
{
|
||||
MovieTitles = new List<string>();
|
||||
Languages = new List<Language>();
|
||||
}
|
||||
|
||||
public List<string> MovieTitles { get; set; }
|
||||
public string OriginalTitle { get; set; }
|
||||
public string ReleaseTitle { get; set; }
|
||||
public string SimpleReleaseTitle { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public List<Language> Languages { get; set; } = new List<Language>();
|
||||
public List<Language> Languages { get; set; }
|
||||
public string ReleaseGroup { get; set; }
|
||||
public string ReleaseHash { get; set; }
|
||||
public string Edition { get; set; }
|
||||
|
@ -22,9 +28,22 @@ namespace NzbDrone.Core.Parser.Model
|
|||
[JsonIgnore]
|
||||
public Dictionary<string, object> ExtraInfo { get; set; } = new Dictionary<string, object>();
|
||||
|
||||
public string PrimaryMovieTitle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (MovieTitles.Count > 0)
|
||||
{
|
||||
return MovieTitles[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} - {1} {2}", MovieTitle, Year, Quality);
|
||||
return string.Format("{0} - {1} {2}", PrimaryMovieTitle, Year, Quality);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,12 @@ namespace NzbDrone.Core.Parser
|
|||
//Regex to detect whether the title was reversed.
|
||||
private static readonly Regex ReversedTitleRegex = new Regex(@"(?:^|[-._ ])(p027|p0801)[-._ ]", RegexOptions.Compiled);
|
||||
|
||||
//Regex to split movie titles that contain `AKA`.
|
||||
private static readonly Regex AlternativeTitleRegex = new Regex(@"[ ]+AKA[ ]+", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
// Regex to unbracket alternative titles.
|
||||
private static readonly Regex BracketedAlternativeTitleRegex = new Regex(@"(.*) \([ ]*AKA[ ]+(.*)\)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
private static readonly Regex NormalizeRegex = new Regex(@"((?:\b|_)(?<!^|[^a-zA-Z0-9_']\w[^a-zA-Z0-9_'])(a(?!$|[^a-zA-Z0-9_']\w[^a-zA-Z0-9_'])|an|the|and|or|of)(?:\b|_))|\W|_",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
|
@ -238,7 +244,7 @@ namespace NzbDrone.Core.Parser
|
|||
//TODO: Add tests for this!
|
||||
var simpleReleaseTitle = SimpleReleaseTitleRegex.Replace(releaseTitle, string.Empty);
|
||||
|
||||
var simpleTitleReplaceString = match[0].Groups["title"].Success ? match[0].Groups["title"].Value : result.MovieTitle;
|
||||
var simpleTitleReplaceString = match[0].Groups["title"].Success ? match[0].Groups["title"].Value : result.PrimaryMovieTitle;
|
||||
|
||||
if (simpleTitleReplaceString.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
|
@ -567,7 +573,19 @@ namespace NzbDrone.Core.Parser
|
|||
result.Edition = matchCollection[0].Groups["edition"].Value.Replace(".", " ");
|
||||
}
|
||||
|
||||
result.MovieTitle = movieName;
|
||||
var movieTitles = new List<string>();
|
||||
movieTitles.Add(movieName);
|
||||
|
||||
//Delete parentheses of the form (aka ...).
|
||||
var unbracketedName = BracketedAlternativeTitleRegex.Replace(movieName, "$1 AKA $2");
|
||||
|
||||
//Split by AKA and filter out empty and duplicate names.
|
||||
movieTitles
|
||||
.AddRange(AlternativeTitleRegex
|
||||
.Split(unbracketedName)
|
||||
.Where(alternativeName => alternativeName.IsNotNullOrWhiteSpace() && alternativeName != movieName));
|
||||
|
||||
result.MovieTitles = movieTitles;
|
||||
|
||||
Logger.Debug("Movie Parsed. {0}", result);
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Languages;
|
||||
|
@ -29,17 +27,14 @@ namespace NzbDrone.Core.Parser
|
|||
private static HashSet<ArabicRomanNumeral> _arabicRomanNumeralMappings;
|
||||
|
||||
private readonly IMovieService _movieService;
|
||||
private readonly IConfigService _config;
|
||||
private readonly IEnumerable<IAugmentParsedMovieInfo> _augmenters;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public ParsingService(IMovieService movieService,
|
||||
IConfigService configService,
|
||||
IEnumerable<IAugmentParsedMovieInfo> augmenters,
|
||||
Logger logger)
|
||||
{
|
||||
_movieService = movieService;
|
||||
_config = configService;
|
||||
_augmenters = augmenters;
|
||||
_logger = logger;
|
||||
|
||||
|
@ -186,7 +181,7 @@ namespace NzbDrone.Core.Parser
|
|||
}
|
||||
|
||||
// nothing found up to here => logging that and returning null
|
||||
_logger.Debug($"No matching movie {parsedMovieInfo.MovieTitle}");
|
||||
_logger.Debug($"No matching movie for titles {string.Join(", ", parsedMovieInfo.MovieTitles)} ({parsedMovieInfo.Year})");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -215,12 +210,12 @@ namespace NzbDrone.Core.Parser
|
|||
|
||||
private bool TryGetMovieByTitleAndOrYear(ParsedMovieInfo parsedMovieInfo, out MappingResult result)
|
||||
{
|
||||
var candidates = _movieService.FindByTitleCandidates(parsedMovieInfo.MovieTitle, out var arabicTitle, out var romanTitle);
|
||||
var candidates = _movieService.FindByTitleCandidates(parsedMovieInfo.MovieTitles, out var otherTitles);
|
||||
|
||||
Movie movieByTitleAndOrYear;
|
||||
if (parsedMovieInfo.Year > 1800)
|
||||
{
|
||||
movieByTitleAndOrYear = _movieService.FindByTitle(parsedMovieInfo.MovieTitle, parsedMovieInfo.Year, arabicTitle, romanTitle, candidates);
|
||||
movieByTitleAndOrYear = _movieService.FindByTitle(parsedMovieInfo.MovieTitles, parsedMovieInfo.Year, otherTitles, candidates);
|
||||
if (movieByTitleAndOrYear != null)
|
||||
{
|
||||
result = new MappingResult { Movie = movieByTitleAndOrYear };
|
||||
|
@ -230,7 +225,7 @@ namespace NzbDrone.Core.Parser
|
|||
// Only default to not using year when one is parsed if only one movie candidate exists
|
||||
if (candidates != null && candidates.Count == 1)
|
||||
{
|
||||
movieByTitleAndOrYear = _movieService.FindByTitle(parsedMovieInfo.MovieTitle, null, arabicTitle, romanTitle, candidates);
|
||||
movieByTitleAndOrYear = _movieService.FindByTitle(parsedMovieInfo.MovieTitles, null, otherTitles, candidates);
|
||||
if (movieByTitleAndOrYear != null)
|
||||
{
|
||||
result = new MappingResult { Movie = movieByTitleAndOrYear, MappingResultType = MappingResultType.WrongYear };
|
||||
|
@ -242,7 +237,7 @@ namespace NzbDrone.Core.Parser
|
|||
return false;
|
||||
}
|
||||
|
||||
movieByTitleAndOrYear = _movieService.FindByTitle(parsedMovieInfo.MovieTitle, null, arabicTitle, romanTitle, candidates);
|
||||
movieByTitleAndOrYear = _movieService.FindByTitle(parsedMovieInfo.MovieTitles, null, otherTitles, candidates);
|
||||
if (movieByTitleAndOrYear != null)
|
||||
{
|
||||
result = new MappingResult { Movie = movieByTitleAndOrYear };
|
||||
|
@ -263,7 +258,7 @@ namespace NzbDrone.Core.Parser
|
|||
possibleTitles.AddRange(searchCriteria.Movie.AlternativeTitles.Select(t => t.CleanTitle));
|
||||
possibleTitles.AddRange(searchCriteria.Movie.Translations.Select(t => t.CleanTitle));
|
||||
|
||||
var cleanTitle = parsedMovieInfo.MovieTitle.CleanMovieTitle();
|
||||
var cleanTitle = parsedMovieInfo.PrimaryMovieTitle.CleanMovieTitle();
|
||||
|
||||
foreach (var title in possibleTitles)
|
||||
{
|
||||
|
@ -321,13 +316,13 @@ namespace NzbDrone.Core.Parser
|
|||
case MappingResultType.NotParsable:
|
||||
return $"Failed to find movie title in release name {ReleaseName}";
|
||||
case MappingResultType.TitleNotFound:
|
||||
return $"Could not find {RemoteMovie.ParsedMovieInfo.MovieTitle}";
|
||||
return $"Could not find {RemoteMovie.ParsedMovieInfo.PrimaryMovieTitle}";
|
||||
case MappingResultType.WrongYear:
|
||||
return $"Failed to map movie, expected year {RemoteMovie.Movie.Year}, but found {RemoteMovie.ParsedMovieInfo.Year}";
|
||||
case MappingResultType.WrongTitle:
|
||||
var comma = RemoteMovie.Movie.AlternativeTitles.Count > 0 ? ", " : "";
|
||||
return
|
||||
$"Failed to map movie, found title {RemoteMovie.ParsedMovieInfo.MovieTitle}, expected one of: {RemoteMovie.Movie.Title}{comma}{string.Join(", ", RemoteMovie.Movie.AlternativeTitles)}";
|
||||
$"Failed to map movie, found title(s) {string.Join(", ", RemoteMovie.ParsedMovieInfo.MovieTitles)}, expected one of: {RemoteMovie.Movie.Title}{comma}{string.Join(", ", RemoteMovie.Movie.AlternativeTitles)}";
|
||||
default:
|
||||
return $"Failed to map movie for unknown reasons";
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace NzbDrone.Core.Parser
|
||||
namespace NzbDrone.Core.Parser
|
||||
{
|
||||
public static class SceneChecker
|
||||
{
|
||||
|
@ -26,7 +26,7 @@
|
|||
if (parsedTitle == null ||
|
||||
parsedTitle.ReleaseGroup == null ||
|
||||
parsedTitle.Quality.Quality == Qualities.Quality.Unknown ||
|
||||
string.IsNullOrWhiteSpace(parsedTitle.MovieTitle) ||
|
||||
string.IsNullOrWhiteSpace(parsedTitle.PrimaryMovieTitle) ||
|
||||
string.IsNullOrWhiteSpace(parsedTitle.ReleaseTitle))
|
||||
{
|
||||
return null;
|
||||
|
|
|
@ -208,6 +208,7 @@ namespace NzbDrone.Core.Qualities
|
|||
public static readonly List<Quality> All;
|
||||
|
||||
public static readonly Quality[] AllLookup;
|
||||
|
||||
public static readonly HashSet<QualityDefinition> DefaultQualityDefinitions;
|
||||
public static Quality FindById(int id)
|
||||
{
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace NzbDrone.Integration.Test.ApiTests
|
|||
releaseResource.Age.Should().BeGreaterOrEqualTo(-1);
|
||||
releaseResource.Title.Should().NotBeNullOrWhiteSpace();
|
||||
releaseResource.DownloadUrl.Should().NotBeNullOrWhiteSpace();
|
||||
releaseResource.MovieTitle.Should().NotBeNullOrWhiteSpace();
|
||||
releaseResource.MovieTitles.First().Should().NotBeNullOrWhiteSpace();
|
||||
|
||||
//TODO: uncomment these after moving to restsharp for rss
|
||||
//releaseResource.NzbInfoUrl.Should().NotBeNullOrWhiteSpace();
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Radarr.Api.V3.Indexers
|
|||
public string ReleaseHash { get; set; }
|
||||
public string Title { get; set; }
|
||||
public bool SceneSource { get; set; }
|
||||
public string MovieTitle { get; set; }
|
||||
public List<string> MovieTitles { get; set; }
|
||||
public List<Language> Languages { get; set; }
|
||||
public bool Approved { get; set; }
|
||||
public bool TemporarilyRejected { get; set; }
|
||||
|
@ -86,7 +86,7 @@ namespace Radarr.Api.V3.Indexers
|
|||
ReleaseGroup = parsedMovieInfo.ReleaseGroup,
|
||||
ReleaseHash = parsedMovieInfo.ReleaseHash,
|
||||
Title = releaseInfo.Title,
|
||||
MovieTitle = parsedMovieInfo.MovieTitle,
|
||||
MovieTitles = parsedMovieInfo.MovieTitles,
|
||||
Languages = parsedMovieInfo.Languages,
|
||||
Approved = model.Approved,
|
||||
TemporarilyRejected = model.TemporarilyRejected,
|
||||
|
|
Loading…
Reference in New Issue