diff --git a/NzbDrone.Core.Test/ParserTest.cs b/NzbDrone.Core.Test/ParserTest.cs
index 3704a7263..8f6c6075d 100644
--- a/NzbDrone.Core.Test/ParserTest.cs
+++ b/NzbDrone.Core.Test/ParserTest.cs
@@ -1,10 +1,12 @@
// ReSharper disable RedundantUsingDirective
using System;
+using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Model;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework;
+using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test
{
@@ -52,10 +54,10 @@ public class ParserTest : CoreTest
public void ParseTitle_single(string postTitle, string title, int seasonNumber, int episodeNumber)
{
var result = Parser.ParseTitle(postTitle);
+ result.EpisodeNumbers.Should().HaveCount(1);
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.EpisodeNumbers.Count.Should().Be(1);
}
[Test]
@@ -68,12 +70,15 @@ public void ParseTitle_single(string postTitle, string title, int seasonNumber,
[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\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)
{
var result = Parser.ParsePath(path);
result.EpisodeNumbers.Should().HaveCount(1);
result.SeasonNumber.Should().Be(season);
result.EpisodeNumbers[0].Should().Be(episode);
+
+ ExceptionVerification.IgnoreWarns();
}
[TestCase("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.DVD)]
@@ -345,6 +350,7 @@ public void parse_season_extras(string postTitle)
var result = Parser.ParseTitle(postTitle);
result.Should().BeNull();
+ ExceptionVerification.ExcpectedWarns(1);
}
[TestCase("Lie.to.Me.S03.SUBPACK.DVDRip.XviD-REWARD")]
@@ -355,6 +361,8 @@ public void parse_season_subpack(string postTitle)
var result = Parser.ParseTitle(postTitle);
result.Should().BeNull();
+
+ ExceptionVerification.ExcpectedWarns(1);
}
}
}
diff --git a/NzbDrone.Core/Parser.cs b/NzbDrone.Core/Parser.cs
index 126784e38..fece6bf26 100644
--- a/NzbDrone.Core/Parser.cs
+++ b/NzbDrone.Core/Parser.cs
@@ -62,22 +62,22 @@ public static class Parser
RegexOptions.IgnoreCase | RegexOptions.Compiled);
- ///
- /// Parses a file path into list of episodes it contains
- ///
- /// Path of the file to parse
- /// List of episodes contained in the file
internal static EpisodeParseResult ParsePath(string 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;
}
- ///
- /// Parses a post title into list of episodes it contains
- ///
- /// Title of the report
- /// List of episodes contained in the post
+
internal static EpisodeParseResult ParseTitle(string title)
{
Logger.Trace("Parsing string '{0}'", title);
@@ -85,95 +85,96 @@ internal static EpisodeParseResult ParseTitle(string title)
foreach (var regex in ReportTitleRegex)
{
- //Use only the filename, not the entire path
var match = regex.Matches(simpleTitle);
if (match.Count != 0)
{
- var seriesName = NormalizeTitle(match[0].Groups["title"].Value);
-
- int airyear;
- Int32.TryParse(match[0].Groups["airyear"].Value, out airyear);
-
- EpisodeParseResult parsedEpisode;
-
- if (airyear < 1)
+ var result = ParseMatchCollection(match);
+ if (result != null)
{
- var seasons = new List();
-
- foreach (Capture seasonCapture in match[0].Groups["season"].Captures)
- {
- 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()
- };
-
- 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;
- }
- }
+ result.Language = ParseLanguage(title);
+ result.Quality = ParseQuality(title);
+ return result;
}
-
- 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);
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();
+
+ 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()
+ };
+
+ foreach (Match matchGroup in matchCollection)
+ {
+ var episodeCaptures = matchGroup.Groups["episode"].Captures.Cast().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;
+ }
+
///
/// Parses a post title to find the series that relates to it
///
@@ -294,7 +295,7 @@ internal static Quality ParseQuality(string name)
return result;
}
- public static LanguageType ParseLanguage(string title)
+ internal static LanguageType ParseLanguage(string title)
{
var lowerTitle = title.ToLower();