mirror of
https://github.com/Sonarr/Sonarr
synced 2024-12-26 01:37:07 +00:00
Parser refactoring. Now tries to parse full path if file name didn't work.
This commit is contained in:
parent
5c1f4bbf1a
commit
d0d9c44124
2 changed files with 100 additions and 91 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue