You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Radarr/src/NzbDrone.Core/Parser/ParsingService.cs

252 lines
9.0 KiB

using System.Collections.Generic;
using System.IO;
using System.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Parser.RomanNumerals;
namespace NzbDrone.Core.Parser
{
public interface IParsingService
{
Movie GetMovie(string title);
RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, string imdbId, int tmdbId, SearchCriteriaBase searchCriteria = null);
RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, int movieId);
ParsedMovieInfo ParseMinimalPathMovieInfo(string path);
}
public class ParsingService : IParsingService
{
private static HashSet<ArabicRomanNumeral> _arabicRomanNumeralMappings;
private readonly IMovieService _movieService;
private readonly Logger _logger;
public ParsingService(IMovieService movieService,
Logger logger)
{
_movieService = movieService;
_logger = logger;
if (_arabicRomanNumeralMappings == null)
{
_arabicRomanNumeralMappings = RomanNumeralParser.GetArabicRomanNumeralsMapping();
}
}
public ParsedMovieInfo ParseMinimalPathMovieInfo(string path)
{
var fileInfo = new FileInfo(path);
var result = Parser.ParseMovieTitle(fileInfo.Name, true);
if (result == null)
{
_logger.Debug("Attempting to parse movie info using directory and file names. '{0}'", fileInfo.Directory.Name);
result = Parser.ParseMovieTitle(fileInfo.Directory.Name + " " + fileInfo.Name);
}
if (result == null)
{
_logger.Debug("Attempting to parse movie info using directory name. '{0}'", fileInfo.Directory.Name);
result = Parser.ParseMovieTitle(fileInfo.Directory.Name + fileInfo.Extension);
}
return result;
}
public Movie GetMovie(string title)
{
var parsedMovieInfo = Parser.ParseMovieTitle(title);
if (parsedMovieInfo == null)
{
return _movieService.FindByTitle(title);
}
var result = TryGetMovieByTitleAndOrYear(parsedMovieInfo);
if (result != null)
{
return result.Movie;
}
return null;
}
public RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, string imdbId, int tmdbId, SearchCriteriaBase searchCriteria = null)
{
return Map(parsedMovieInfo, imdbId, tmdbId, null, searchCriteria);
}
public RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, int movieId)
{
return new RemoteMovie
{
ParsedMovieInfo = parsedMovieInfo,
Movie = _movieService.GetMovie(movieId)
};
}
public RemoteMovie Map(ParsedMovieInfo parsedMovieInfo, string imdbId, int tmdbId, Movie movie, SearchCriteriaBase searchCriteria)
{
var remoteMovie = new RemoteMovie
{
ParsedMovieInfo = parsedMovieInfo
};
if (movie == null)
{
var movieMatch = FindMovie(parsedMovieInfo, imdbId, tmdbId, searchCriteria);
if (movieMatch != null)
{
movie = movieMatch.Movie;
remoteMovie.MovieMatchType = movieMatch.MatchType;
}
}
if (movie != null)
{
remoteMovie.Movie = movie;
}
remoteMovie.Languages = parsedMovieInfo.Languages;
return remoteMovie;
}
private FindMovieResult FindMovie(ParsedMovieInfo parsedMovieInfo, string imdbId, int tmdbId, SearchCriteriaBase searchCriteria)
{
FindMovieResult result = null;
if (!string.IsNullOrWhiteSpace(imdbId) && imdbId != "0")
{
result = TryGetMovieByImDbId(parsedMovieInfo, imdbId);
}
if (result == null && tmdbId > 0)
{
result = TryGetMovieByTmdbId(parsedMovieInfo, tmdbId);
}
if (result == null)
{
if (searchCriteria != null)
{
result = TryGetMovieBySearchCriteria(parsedMovieInfo, imdbId, tmdbId, searchCriteria);
}
else
{
result = TryGetMovieByTitleAndOrYear(parsedMovieInfo);
}
}
if (result == null)
{
_logger.Debug($"No matching movie for titles '{string.Join(", ", parsedMovieInfo.MovieTitles)} ({parsedMovieInfo.Year})"');
}
return 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 || movie.MovieMetadata.Value.Year == parsedMovieInfo.Year || movie.MovieMetadata.Value.SecondaryYear == parsedMovieInfo.Year))
{
return new FindMovieResult(movie, MovieMatchType.Id);
}
return null;
}
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);
Movie movieByTitleAndOrYear;
if (parsedMovieInfo.Year > 1800)
{
movieByTitleAndOrYear = _movieService.FindByTitle(parsedMovieInfo.MovieTitles, parsedMovieInfo.Year, otherTitles, candidates);
if (movieByTitleAndOrYear != null)
{
return new FindMovieResult(movieByTitleAndOrYear, MovieMatchType.Title);
}
return null;
}
movieByTitleAndOrYear = _movieService.FindByTitle(parsedMovieInfo.MovieTitles, null, otherTitles, candidates);
if (movieByTitleAndOrYear != null)
{
return new FindMovieResult(movieByTitleAndOrYear, MovieMatchType.Title);
}
return null;
}
private FindMovieResult TryGetMovieBySearchCriteria(ParsedMovieInfo parsedMovieInfo, string imdbId, int tmdbId, SearchCriteriaBase searchCriteria)
{
Movie possibleMovie = null;
var possibleTitles = new List<string>
{
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));
var cleanTitles = parsedMovieInfo.MovieTitles.Select(t => t.CleanMovieTitle()).ToArray();
if (possibleTitles.Any(pt =>
cleanTitles.Contains(pt)
|| _arabicRomanNumeralMappings.Any(mn =>
cleanTitles.Contains(pt.Replace(mn.ArabicNumeralAsString, mn.RomanNumeralLowerCase))
|| cleanTitles.Any(t => t.Replace(mn.ArabicNumeralAsString, mn.RomanNumeralLowerCase) == pt))))
{
possibleMovie = searchCriteria.Movie;
}
if (possibleMovie != null)
{
if (parsedMovieInfo.Year < 1800 || possibleMovie.MovieMetadata.Value.Year == parsedMovieInfo.Year || possibleMovie.MovieMetadata.Value.SecondaryYear == parsedMovieInfo.Year)
{
return new FindMovieResult(possibleMovie, MovieMatchType.Title);
}
}
if (tmdbId > 0 && tmdbId == searchCriteria.Movie.TmdbId)
{
return new FindMovieResult(searchCriteria.Movie, MovieMatchType.Id);
}
if (imdbId.IsNotNullOrWhiteSpace() && imdbId == searchCriteria.Movie.ImdbId)
{
return new FindMovieResult(searchCriteria.Movie, MovieMatchType.Id);
}
return null;
}
}
}