Fixes in response to code review
ParseSpecialEpisode now follows similar pattern to Map() method and accepts TvRageId and SearchCriteria Fixed normalize episode title to handle punctuation separately from spaces and removed special episode words Removed comments
This commit is contained in:
parent
6ee08af111
commit
c459cdf168
|
@ -52,13 +52,6 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
_logger.ProgressInfo("No reports found");
|
_logger.ProgressInfo("No reports found");
|
||||||
}
|
}
|
||||||
|
|
||||||
// get series from search criteria
|
|
||||||
Tv.Series series = null;
|
|
||||||
if (searchCriteria != null)
|
|
||||||
{
|
|
||||||
series = searchCriteria.Series;
|
|
||||||
}
|
|
||||||
|
|
||||||
var reportNumber = 1;
|
var reportNumber = 1;
|
||||||
|
|
||||||
foreach (var report in reports)
|
foreach (var report in reports)
|
||||||
|
@ -68,17 +61,13 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// use parsing service to parse episode info (this allows us to do episode title searches against the episode repository)
|
|
||||||
var parsedEpisodeInfo = Parser.Parser.ParseTitle(report.Title);
|
var parsedEpisodeInfo = Parser.Parser.ParseTitle(report.Title);
|
||||||
|
|
||||||
// do we have a possible special episode?
|
|
||||||
if (parsedEpisodeInfo == null || parsedEpisodeInfo.IsPossibleSpecialEpisode())
|
if (parsedEpisodeInfo == null || parsedEpisodeInfo.IsPossibleSpecialEpisode())
|
||||||
{
|
{
|
||||||
// try to parse as a special episode
|
var specialEpisodeInfo = _parsingService.ParseSpecialEpisodeTitle(report.Title, report.TvRageId, searchCriteria);
|
||||||
var specialEpisodeInfo = _parsingService.ParseSpecialEpisodeTitle(report.Title, series);
|
|
||||||
if (specialEpisodeInfo != null)
|
if (specialEpisodeInfo != null)
|
||||||
{
|
{
|
||||||
// use special episode
|
|
||||||
parsedEpisodeInfo = specialEpisodeInfo;
|
parsedEpisodeInfo = specialEpisodeInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,8 +114,11 @@ namespace NzbDrone.Core.Parser
|
||||||
private static readonly Regex YearInTitleRegex = new Regex(@"^(?<title>.+?)(?:\W|_)?(?<year>\d{4})",
|
private static readonly Regex YearInTitleRegex = new Regex(@"^(?<title>.+?)(?:\W|_)?(?<year>\d{4})",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
private static readonly Regex NonWordRegex = new Regex(@"\W+", RegexOptions.Compiled);
|
private static readonly Regex WordDelimiterRegex = new Regex(@"(\s|\.|,|_|-|=|\|)+", RegexOptions.Compiled);
|
||||||
private static readonly Regex CommonWordRegex = new Regex(@"\b(a|an|the|and|or|of|part)\b\s?",
|
private static readonly Regex PunctuationRegex = new Regex(@"[^\w\s]", RegexOptions.Compiled);
|
||||||
|
private static readonly Regex CommonWordRegex = new Regex(@"\b(a|an|the|and|or|of)\b\s?",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
private static readonly Regex SpecialEpisodeWordRegex = new Regex(@"\b(part|special|edition)\b\s?",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
|
|
||||||
|
@ -227,11 +230,11 @@ namespace NzbDrone.Core.Parser
|
||||||
|
|
||||||
public static string NormalizeEpisodeTitle(string title)
|
public static string NormalizeEpisodeTitle(string title)
|
||||||
{
|
{
|
||||||
// convert any non-word characters to a single space
|
string singleSpaces = WordDelimiterRegex.Replace(title, " ");
|
||||||
string normalizedSpaces = NonWordRegex.Replace(title, " ").ToLower();
|
string noPunctuation = PunctuationRegex.Replace(singleSpaces, String.Empty);
|
||||||
// remove common words
|
string noCommonWords = CommonWordRegex.Replace(noPunctuation, String.Empty);
|
||||||
string normalized = CommonWordRegex.Replace(normalizedSpaces, String.Empty);
|
string normalized = SpecialEpisodeWordRegex.Replace(noCommonWords, String.Empty);
|
||||||
return normalized;
|
return normalized.Trim().ToLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ParseReleaseGroup(string title)
|
public static string ParseReleaseGroup(string title)
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace NzbDrone.Core.Parser
|
||||||
{
|
{
|
||||||
public interface IParsingService
|
public interface IParsingService
|
||||||
{
|
{
|
||||||
|
ParsedEpisodeInfo ParseSpecialEpisodeTitle(string title, int tvRageId, SearchCriteriaBase searchCriteria = null);
|
||||||
ParsedEpisodeInfo ParseSpecialEpisodeTitle(string title, Series series);
|
ParsedEpisodeInfo ParseSpecialEpisodeTitle(string title, Series series);
|
||||||
LocalEpisode GetEpisodes(string filename, Series series, bool sceneSource);
|
LocalEpisode GetEpisodes(string filename, Series series, bool sceneSource);
|
||||||
Series GetSeries(string title);
|
Series GetSeries(string title);
|
||||||
|
@ -40,27 +41,47 @@ namespace NzbDrone.Core.Parser
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParsedEpisodeInfo ParseSpecialEpisodeTitle(string title, Series series)
|
public ParsedEpisodeInfo ParseSpecialEpisodeTitle(string title, int tvRageId, SearchCriteriaBase searchCriteria = null)
|
||||||
{
|
{
|
||||||
try
|
if (searchCriteria != null)
|
||||||
{
|
{
|
||||||
if (series == null)
|
var tvdbId = _sceneMappingService.GetTvDbId(title);
|
||||||
|
if (tvdbId.HasValue)
|
||||||
{
|
{
|
||||||
// find series if we dont have it already
|
if (searchCriteria.Series.TvdbId == tvdbId)
|
||||||
// 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 ParseSpecialEpisodeTitle(title, searchCriteria.Series);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tvRageId == searchCriteria.Series.TvRageId)
|
||||||
|
{
|
||||||
|
return ParseSpecialEpisodeTitle(title, searchCriteria.Series);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var series = _seriesService.FindByTitleInexact(title);
|
||||||
|
if (series == null && tvRageId > 0)
|
||||||
|
{
|
||||||
|
series = _seriesService.FindByTvRageId(tvRageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (series == null)
|
||||||
|
{
|
||||||
|
_logger.Trace("No matching series {0}", title);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParseSpecialEpisodeTitle(title, series);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParsedEpisodeInfo ParseSpecialEpisodeTitle(string title, Series series)
|
||||||
|
{
|
||||||
// find special episode in series season 0
|
// find special episode in series season 0
|
||||||
Episode episode = _episodeService.FindEpisodeByName(series.Id, 0, title);
|
var episode = _episodeService.FindEpisodeByName(series.Id, 0, title);
|
||||||
if (episode != null)
|
if (episode != null)
|
||||||
{
|
{
|
||||||
// created parsed info from tv episode that we found
|
// create parsed info from tv episode
|
||||||
var info = new ParsedEpisodeInfo();
|
var info = new ParsedEpisodeInfo();
|
||||||
info.SeriesTitle = series.Title;
|
info.SeriesTitle = series.Title;
|
||||||
info.SeriesTitleInfo = new SeriesTitleInfo();
|
info.SeriesTitleInfo = new SeriesTitleInfo();
|
||||||
|
@ -74,17 +95,11 @@ namespace NzbDrone.Core.Parser
|
||||||
_logger.Info("Found special episode {0} for title '{1}'", info, title);
|
_logger.Info("Found special episode {0} for title '{1}'", info, title);
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("An error has occurred while trying to parse special episode " + title, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public LocalEpisode GetEpisodes(string filename, Series series, bool sceneSource)
|
public LocalEpisode GetEpisodes(string filename, Series series, bool sceneSource)
|
||||||
{
|
{
|
||||||
var parsedEpisodeInfo = Parser.ParsePath(filename);
|
var parsedEpisodeInfo = Parser.ParsePath(filename);
|
||||||
|
|
|
@ -103,9 +103,6 @@ namespace NzbDrone.Core.Tv
|
||||||
|
|
||||||
public Series FindByTitleInexact(string title)
|
public Series FindByTitleInexact(string title)
|
||||||
{
|
{
|
||||||
// perform fuzzy matching of series name
|
|
||||||
// TODO: can replace this search mechanism with something smarter/faster/better
|
|
||||||
|
|
||||||
// find any series clean title within the provided release title
|
// find any series clean title within the provided release title
|
||||||
string cleanTitle = Parser.Parser.CleanSeriesTitle(title);
|
string cleanTitle = Parser.Parser.CleanSeriesTitle(title);
|
||||||
var list = _seriesRepository.All().Where(s => cleanTitle.Contains(s.CleanTitle)).ToList();
|
var list = _seriesRepository.All().Where(s => cleanTitle.Contains(s.CleanTitle)).ToList();
|
||||||
|
@ -137,7 +134,6 @@ namespace NzbDrone.Core.Tv
|
||||||
|
|
||||||
// get the leftmost series that is the longest
|
// get the leftmost series that is the longest
|
||||||
// series are usually the first thing in release title, so we select the leftmost and longest match
|
// series are usually the first thing in release title, so we select the leftmost and longest match
|
||||||
// we could have multiple matches for series which have a common prefix like "Love it", "Love it Too" so we pick the longest one
|
|
||||||
var match = query.First().series;
|
var match = query.First().series;
|
||||||
|
|
||||||
_logger.Trace("Multiple series matched {0} from title {1}", match.Title, title);
|
_logger.Trace("Multiple series matched {0} from title {1}", match.Title, title);
|
||||||
|
|
Loading…
Reference in New Issue