Parser refactoring. Now tries to parse full path if file name didn't work.

This commit is contained in:
kay.one 2011-11-23 23:35:37 -08:00
parent 5c1f4bbf1a
commit d0d9c44124
2 changed files with 100 additions and 91 deletions

View File

@ -1,10 +1,12 @@
// ReSharper disable RedundantUsingDirective // ReSharper disable RedundantUsingDirective
using System; using System;
using System.Linq;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Model; using NzbDrone.Core.Model;
using NzbDrone.Core.Repository.Quality; using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test namespace NzbDrone.Core.Test
{ {
@ -52,10 +54,10 @@ namespace NzbDrone.Core.Test
public void ParseTitle_single(string postTitle, string title, int seasonNumber, int episodeNumber) public void ParseTitle_single(string postTitle, string title, int seasonNumber, int episodeNumber)
{ {
var result = Parser.ParseTitle(postTitle); var result = Parser.ParseTitle(postTitle);
result.EpisodeNumbers.Should().HaveCount(1);
result.SeasonNumber.Should().Be(seasonNumber); result.SeasonNumber.Should().Be(seasonNumber);
result.EpisodeNumbers[0].Should().Be(episodeNumber); result.EpisodeNumbers.First().Should().Be(episodeNumber);
result.CleanTitle.Should().Be(Parser.NormalizeTitle(title)); result.CleanTitle.Should().Be(Parser.NormalizeTitle(title));
result.EpisodeNumbers.Count.Should().Be(1);
} }
[Test] [Test]
@ -68,12 +70,15 @@ namespace NzbDrone.Core.Test
[TestCase(@"P:\TV Shows\House\Season 6\S06E13 - 5 to 9 - 720p BluRay.mkv", 6, 13)] [TestCase(@"P:\TV Shows\House\Season 6\S06E13 - 5 to 9 - 720p BluRay.mkv", 6, 13)]
[TestCase(@"S:\TV Drop\House - 10x11 - Title [SDTV]\1011 - Title.avi", 10, 11)] [TestCase(@"S:\TV Drop\House - 10x11 - Title [SDTV]\1011 - Title.avi", 10, 11)]
[TestCase(@"S:\TV Drop\King of the Hill - 10x12 - 24 Hour Propane People [SDTV]\1012 - 24 Hour Propane People.avi", 10, 12)] [TestCase(@"S:\TV Drop\King of the Hill - 10x12 - 24 Hour Propane People [SDTV]\1012 - 24 Hour Propane People.avi", 10, 12)]
[TestCase(@"S:\TV Drop\King of the Hill - 10x12 - 24 Hour Propane People [SDTV]\Hour Propane People.avi", 10, 12)]
public void PathParse_tests(string path, int season, int episode) public void PathParse_tests(string path, int season, int episode)
{ {
var result = Parser.ParsePath(path); var result = Parser.ParsePath(path);
result.EpisodeNumbers.Should().HaveCount(1); result.EpisodeNumbers.Should().HaveCount(1);
result.SeasonNumber.Should().Be(season); result.SeasonNumber.Should().Be(season);
result.EpisodeNumbers[0].Should().Be(episode); result.EpisodeNumbers[0].Should().Be(episode);
ExceptionVerification.IgnoreWarns();
} }
[TestCase("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.DVD)] [TestCase("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.DVD)]
@ -345,6 +350,7 @@ namespace NzbDrone.Core.Test
var result = Parser.ParseTitle(postTitle); var result = Parser.ParseTitle(postTitle);
result.Should().BeNull(); result.Should().BeNull();
ExceptionVerification.ExcpectedWarns(1);
} }
[TestCase("Lie.to.Me.S03.SUBPACK.DVDRip.XviD-REWARD")] [TestCase("Lie.to.Me.S03.SUBPACK.DVDRip.XviD-REWARD")]
@ -355,6 +361,8 @@ namespace NzbDrone.Core.Test
var result = Parser.ParseTitle(postTitle); var result = Parser.ParseTitle(postTitle);
result.Should().BeNull(); result.Should().BeNull();
ExceptionVerification.ExcpectedWarns(1);
} }
} }
} }

View File

@ -62,22 +62,22 @@ namespace NzbDrone.Core
RegexOptions.IgnoreCase | RegexOptions.Compiled); RegexOptions.IgnoreCase | RegexOptions.Compiled);
/// <summary>
/// Parses a file path into list of episodes it contains
/// </summary>
/// <param name = "path">Path of the file to parse</param>
/// <returns>List of episodes contained in the file</returns>
internal static EpisodeParseResult ParsePath(string path) internal static EpisodeParseResult ParsePath(string path)
{ {
var fileInfo = new FileInfo(path); var fileInfo = new FileInfo(path);
return ParseTitle(fileInfo.Name);
var result = ParseTitle(fileInfo.Name);
if (result == null)
{
Logger.Trace("Attempting to parse episode info using full path. {0}", fileInfo.FullName);
result = ParseTitle(fileInfo.FullName);
}
return result;
} }
/// <summary>
/// Parses a post title into list of episodes it contains
/// </summary>
/// <param name = "title">Title of the report</param>
/// <returns>List of episodes contained in the post</returns>
internal static EpisodeParseResult ParseTitle(string title) internal static EpisodeParseResult ParseTitle(string title)
{ {
Logger.Trace("Parsing string '{0}'", title); Logger.Trace("Parsing string '{0}'", title);
@ -85,95 +85,96 @@ namespace NzbDrone.Core
foreach (var regex in ReportTitleRegex) foreach (var regex in ReportTitleRegex)
{ {
//Use only the filename, not the entire path
var match = regex.Matches(simpleTitle); var match = regex.Matches(simpleTitle);
if (match.Count != 0) if (match.Count != 0)
{ {
var seriesName = NormalizeTitle(match[0].Groups["title"].Value); var result = ParseMatchCollection(match);
if (result != null)
int airyear;
Int32.TryParse(match[0].Groups["airyear"].Value, out airyear);
EpisodeParseResult parsedEpisode;
if (airyear < 1)
{ {
var seasons = new List<int>(); result.Language = ParseLanguage(title);
result.Quality = ParseQuality(title);
foreach (Capture seasonCapture in match[0].Groups["season"].Captures) return result;
{
int s;
if (Int32.TryParse(seasonCapture.Value, out s))
seasons.Add(s);
}
//If more than 1 season was parsed go to the next REGEX (A multi-season release is unlikely)
if (seasons.Distinct().Count() != 1)
continue;
var season = seasons[0];
parsedEpisode = new EpisodeParseResult
{
CleanTitle = seriesName,
SeasonNumber = season,
EpisodeNumbers = new List<int>()
};
foreach (Match matchGroup in match)
{
var count = matchGroup.Groups["episode"].Captures.Count;
//Allows use to return a list of 0 episodes (We can handle that as a full season release)
if (count > 0)
{
var first = Convert.ToInt32(matchGroup.Groups["episode"].Captures[0].Value);
var last = Convert.ToInt32(matchGroup.Groups["episode"].Captures[count - 1].Value);
for (int i = first; i <= last; i++)
{
parsedEpisode.EpisodeNumbers.Add(i);
}
}
else
{
//Check to see if this is an "Extras" or "SUBPACK" release, if it is, return NULL
//Todo: Set a "Extras" flag in EpisodeParseResult if we want to download them ever
if (!String.IsNullOrEmpty(match[0].Groups["extras"].Value))
return null;
parsedEpisode.FullSeason = true;
}
}
} }
else
{
//Try to Parse as a daily show
var airmonth = Convert.ToInt32(match[0].Groups["airmonth"].Value);
var airday = Convert.ToInt32(match[0].Groups["airday"].Value);
parsedEpisode = new EpisodeParseResult
{
CleanTitle = seriesName,
AirDate = new DateTime(airyear, airmonth, airday),
Language = ParseLanguage(simpleTitle)
};
}
parsedEpisode.Quality = ParseQuality(title);
Logger.Trace("Episode Parsed. {0}", parsedEpisode);
return parsedEpisode;
} }
} }
Logger.Warn("Unable to parse episode info. {0}", title); Logger.Warn("Unable to parse episode info. {0}", title);
return null; return null;
} }
private static EpisodeParseResult ParseMatchCollection(MatchCollection matchCollection)
{
var seriesName = NormalizeTitle(matchCollection[0].Groups["title"].Value);
int airyear;
Int32.TryParse(matchCollection[0].Groups["airyear"].Value, out airyear);
EpisodeParseResult parsedEpisode;
if (airyear < 1900)
{
var seasons = new List<int>();
foreach (Capture seasonCapture in matchCollection[0].Groups["season"].Captures)
{
int parsedSeason;
if (Int32.TryParse(seasonCapture.Value, out parsedSeason))
seasons.Add(parsedSeason);
}
//If more than 1 season was parsed go to the next REGEX (A multi-season release is unlikely)
if (seasons.Distinct().Count() != 1)
return null;
parsedEpisode = new EpisodeParseResult
{
SeasonNumber = seasons.First(),
EpisodeNumbers = new List<int>()
};
foreach (Match matchGroup in matchCollection)
{
var episodeCaptures = matchGroup.Groups["episode"].Captures.Cast<Capture>().ToList();
//Allows use to return a list of 0 episodes (We can handle that as a full season release)
if (episodeCaptures.Any())
{
var first = Convert.ToInt32(episodeCaptures.First().Value);
var last = Convert.ToInt32(episodeCaptures.Last().Value);
parsedEpisode.EpisodeNumbers = Enumerable.Range(first, last - first + 1).ToList();
}
else
{
//Check to see if this is an "Extras" or "SUBPACK" release, if it is, return NULL
//Todo: Set a "Extras" flag in EpisodeParseResult if we want to download them ever
if (!String.IsNullOrWhiteSpace(matchCollection[0].Groups["extras"].Value))
return null;
parsedEpisode.FullSeason = true;
}
}
}
else
{
//Try to Parse as a daily show
var airmonth = Convert.ToInt32(matchCollection[0].Groups["airmonth"].Value);
var airday = Convert.ToInt32(matchCollection[0].Groups["airday"].Value);
parsedEpisode = new EpisodeParseResult
{
AirDate = new DateTime(airyear, airmonth, airday),
};
}
parsedEpisode.CleanTitle = seriesName;
Logger.Trace("Episode Parsed. {0}", parsedEpisode);
return parsedEpisode;
}
/// <summary> /// <summary>
/// Parses a post title to find the series that relates to it /// Parses a post title to find the series that relates to it
/// </summary> /// </summary>
@ -294,7 +295,7 @@ namespace NzbDrone.Core
return result; return result;
} }
public static LanguageType ParseLanguage(string title) internal static LanguageType ParseLanguage(string title)
{ {
var lowerTitle = title.ToLower(); var lowerTitle = title.ToLower();