1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-12-25 02:30:20 +02:00
Sonarr/src/NzbDrone.Core/Parser/ParsingService.cs

336 lines
12 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Parser
{
public interface IParsingService
{
ParsedEpisodeInfo ParseSpecialEpisodeTitle(string title, Series series);
2013-07-23 08:50:32 +03:00
LocalEpisode GetEpisodes(string filename, Series series, bool sceneSource);
Series GetSeries(string title);
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvRageId, SearchCriteriaBase searchCriteria = null);
2013-09-15 11:23:54 +03:00
List<Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series series, bool sceneSource, SearchCriteriaBase searchCriteria = null);
}
public class ParsingService : IParsingService
{
private readonly IEpisodeService _episodeService;
private readonly ISeriesService _seriesService;
private readonly IDiskProvider _diskProvider;
private readonly ISceneMappingService _sceneMappingService;
private readonly Logger _logger;
public ParsingService(IEpisodeService episodeService,
ISeriesService seriesService,
IDiskProvider diskProvider,
ISceneMappingService sceneMappingService,
Logger logger)
{
_episodeService = episodeService;
_seriesService = seriesService;
_diskProvider = diskProvider;
_sceneMappingService = sceneMappingService;
_logger = logger;
}
public ParsedEpisodeInfo ParseSpecialEpisodeTitle(string title, Series series)
{
try
{
if (series == null)
{
// find series if we dont have it already
// we use an inexact match here since the series name is often mangled with the episode title
series = _seriesService.FindByTitleInexact(title);
if (series == null)
{
// no series matched
return null;
}
}
// find special episode in series season 0
Episode episode = _episodeService.FindEpisodeByName(series.Id, 0, title);
if (episode != null)
{
// created parsed info from tv episode that we found
var info = new ParsedEpisodeInfo();
info.SeriesTitle = series.Title;
info.SeriesTitleInfo = new SeriesTitleInfo();
info.SeriesTitleInfo.Title = info.SeriesTitle;
info.SeasonNumber = episode.SeasonNumber;
info.EpisodeNumbers = new int[1] { episode.EpisodeNumber };
info.FullSeason = false;
info.Quality = QualityParser.ParseQuality(title);
info.ReleaseGroup = Parser.ParseReleaseGroup(title);
_logger.Info("Found special episode {0} for title '{1}'", info, title);
return info;
}
}
catch (Exception e)
{
_logger.ErrorException("An error has occurred while trying to parse special episode " + title, e);
}
return null;
}
2013-07-23 08:50:32 +03:00
public LocalEpisode GetEpisodes(string filename, Series series, bool sceneSource)
{
var parsedEpisodeInfo = Parser.ParsePath(filename);
// do we have a possible special episode?
if (parsedEpisodeInfo == null || parsedEpisodeInfo.IsPossibleSpecialEpisode())
{
// try to parse as a special episode
var title = System.IO.Path.GetFileNameWithoutExtension(filename);
var specialEpisodeInfo = ParseSpecialEpisodeTitle(title, series);
if (specialEpisodeInfo != null)
{
// use special episode
parsedEpisodeInfo = specialEpisodeInfo;
}
}
if (parsedEpisodeInfo == null)
{
return null;
}
2013-07-23 08:50:32 +03:00
var episodes = GetEpisodes(parsedEpisodeInfo, series, sceneSource);
if (!episodes.Any())
{
_logger.Trace("No matching episodes found for: {0}", parsedEpisodeInfo);
return null;
}
return new LocalEpisode
2013-07-23 08:50:32 +03:00
{
Series = series,
Quality = parsedEpisodeInfo.Quality,
Episodes = episodes,
Path = filename,
ParsedEpisodeInfo = parsedEpisodeInfo,
ExistingFile = _diskProvider.IsParent(series.Path, filename)
2013-07-23 08:50:32 +03:00
};
}
public Series GetSeries(string title)
{
var parsedEpisodeInfo = Parser.ParseTitle(title);
2013-04-18 02:32:53 +03:00
if (parsedEpisodeInfo == null)
{
return _seriesService.FindByTitle(title);
}
var series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
if (series == null)
2013-04-18 02:32:53 +03:00
{
series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear,
parsedEpisodeInfo.SeriesTitleInfo.Year);
2013-04-18 02:32:53 +03:00
}
return series;
}
public RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvRageId, SearchCriteriaBase searchCriteria = null)
{
var remoteEpisode = new RemoteEpisode
{
ParsedEpisodeInfo = parsedEpisodeInfo,
};
var series = searchCriteria == null ? GetSeries(parsedEpisodeInfo, tvRageId) :
GetSeries(parsedEpisodeInfo, tvRageId, searchCriteria);
if (series == null)
{
return remoteEpisode;
}
remoteEpisode.Series = series;
remoteEpisode.Episodes = GetEpisodes(parsedEpisodeInfo, series, true, searchCriteria);
return remoteEpisode;
}
2013-09-15 11:23:54 +03:00
public List<Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series series, bool sceneSource, SearchCriteriaBase searchCriteria = null)
{
var result = new List<Episode>();
if (parsedEpisodeInfo.FullSeason)
{
return _episodeService.GetEpisodesBySeason(series.Id, parsedEpisodeInfo.SeasonNumber);
}
if (parsedEpisodeInfo.IsDaily())
{
if (series.SeriesType == SeriesTypes.Standard)
{
2013-07-05 08:17:25 +03:00
_logger.Warn("Found daily-style episode for non-daily series: {0}.", series);
2013-11-27 10:48:57 +03:00
return result;
}
var episodeInfo = GetDailyEpisode(series, parsedEpisodeInfo.AirDate, searchCriteria);
if (episodeInfo != null)
{
result.Add(episodeInfo);
}
return result;
}
if (parsedEpisodeInfo.IsAbsoluteNumbering())
{
foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers)
{
var episodeInfo = _episodeService.FindEpisode(series.Id, absoluteEpisodeNumber);
if (episodeInfo != null)
{
_logger.Info("Using absolute episode number {0} for: {1} - TVDB: {2}x{3:00}",
absoluteEpisodeNumber,
series.Title,
episodeInfo.SeasonNumber,
episodeInfo.EpisodeNumber);
result.Add(episodeInfo);
}
}
return result;
}
if (parsedEpisodeInfo.EpisodeNumbers == null)
return result;
foreach (var episodeNumber in parsedEpisodeInfo.EpisodeNumbers)
{
Episode episodeInfo = null;
2013-07-23 08:50:32 +03:00
if (series.UseSceneNumbering && sceneSource)
{
if (searchCriteria != null)
{
episodeInfo = searchCriteria.Episodes.SingleOrDefault(e => e.SceneSeasonNumber == parsedEpisodeInfo.SeasonNumber &&
e.SceneEpisodeNumber == episodeNumber);
}
if (episodeInfo == null)
{
episodeInfo = _episodeService.FindEpisode(series.Id, parsedEpisodeInfo.SeasonNumber, episodeNumber, true);
}
2013-07-23 08:50:32 +03:00
if (episodeInfo != null)
{
_logger.Info("Using Scene to TVDB Mapping for: {0} - Scene: {1}x{2:00} - TVDB: {3}x{4:00}",
series.Title,
episodeInfo.SceneSeasonNumber,
episodeInfo.SceneEpisodeNumber,
episodeInfo.SeasonNumber,
episodeInfo.EpisodeNumber);
}
}
if (episodeInfo == null && searchCriteria != null)
{
episodeInfo = searchCriteria.Episodes.SingleOrDefault(e => e.SeasonNumber == parsedEpisodeInfo.SeasonNumber &&
e.EpisodeNumber == episodeNumber);
}
if (episodeInfo == null)
{
2013-09-15 11:23:54 +03:00
episodeInfo = _episodeService.FindEpisode(series.Id, parsedEpisodeInfo.SeasonNumber, episodeNumber);
}
if (episodeInfo != null)
{
result.Add(episodeInfo);
}
else
{
_logger.Debug("Unable to find {0}", parsedEpisodeInfo);
}
}
return result;
}
2013-09-15 11:23:54 +03:00
private Series GetSeries(ParsedEpisodeInfo parsedEpisodeInfo, int tvRageId, SearchCriteriaBase searchCriteria)
2013-11-27 10:48:57 +03:00
{
2013-09-15 11:23:54 +03:00
var tvdbId = _sceneMappingService.GetTvDbId(parsedEpisodeInfo.SeriesTitle);
if (tvdbId.HasValue)
{
if (searchCriteria.Series.TvdbId == tvdbId)
{
return searchCriteria.Series;
}
}
if (parsedEpisodeInfo.SeriesTitle.CleanSeriesTitle() == searchCriteria.Series.CleanTitle)
{
return searchCriteria.Series;
}
if (tvRageId == searchCriteria.Series.TvRageId)
{
//TODO: If series is found by TvRageId, we should report it as a scene naming exception, since it will fail to import
return searchCriteria.Series;
}
return GetSeries(parsedEpisodeInfo, tvRageId);
}
private Series GetSeries(ParsedEpisodeInfo parsedEpisodeInfo, int tvRageId)
{
var series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
if (series == null && tvRageId > 0)
{
//TODO: If series is found by TvRageId, we should report it as a scene naming exception, since it will fail to import
series = _seriesService.FindByTvRageId(tvRageId);
}
if (series == null)
{
_logger.Trace("No matching series {0}", parsedEpisodeInfo.SeriesTitle);
return null;
}
return series;
}
private Episode GetDailyEpisode(Series series, String airDate, SearchCriteriaBase searchCriteria)
{
Episode episodeInfo = null;
if (searchCriteria != null)
{
episodeInfo = searchCriteria.Episodes.SingleOrDefault(
e => e.AirDate == airDate);
}
if (episodeInfo == null)
{
2013-09-15 11:23:54 +03:00
episodeInfo = _episodeService.FindEpisode(series.Id, airDate);
}
return episodeInfo;
}
}
}