Fixed: Path parsing incorrectly treating series title as episode number
This commit is contained in:
parent
60ee7cc716
commit
0937ee6fef
|
@ -31,6 +31,8 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||||
[TestCase(@"C:\Test\Series\Season 1\2 Honor Thy Developer (1080p HD).m4v", 1, 2)]
|
[TestCase(@"C:\Test\Series\Season 1\2 Honor Thy Developer (1080p HD).m4v", 1, 2)]
|
||||||
[TestCase(@"C:\Test\Series\Season 2 - Total Series Action\01. Total Series Action - Episode 1 - Monster Cash.mkv", 2, 1)]
|
[TestCase(@"C:\Test\Series\Season 2 - Total Series Action\01. Total Series Action - Episode 1 - Monster Cash.mkv", 2, 1)]
|
||||||
[TestCase(@"C:\Test\Series\Season 2\01. Total Series Action - Episode 1 - Monster Cash.mkv", 2, 1)]
|
[TestCase(@"C:\Test\Series\Season 2\01. Total Series Action - Episode 1 - Monster Cash.mkv", 2, 1)]
|
||||||
|
[TestCase(@"C:\Test\Series\Season 1\02.04.24 - S01E01 - The Rabbit Hole", 1, 1)]
|
||||||
|
[TestCase(@"C:\Test\Series\Season 1\8 Series Rules - S01E01 - Pilot", 1, 1)]
|
||||||
|
|
||||||
// [TestCase(@"C:\series.state.S02E04.720p.WEB-DL.DD5.1.H.264\73696S02-04.mkv", 2, 4)] //Gets treated as S01E04 (because it gets parsed as anime); 2020-01 broken test case: Expected result.EpisodeNumbers to contain 1 item(s), but found 0
|
// [TestCase(@"C:\series.state.S02E04.720p.WEB-DL.DD5.1.H.264\73696S02-04.mkv", 2, 4)] //Gets treated as S01E04 (because it gets parsed as anime); 2020-01 broken test case: Expected result.EpisodeNumbers to contain 1 item(s), but found 0
|
||||||
public void should_parse_from_path(string path, int season, int episode)
|
public void should_parse_from_path(string path, int season, int episode)
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace NzbDrone.Core.Parser.Model
|
||||||
public bool IsMultiSeason { get; set; }
|
public bool IsMultiSeason { get; set; }
|
||||||
public bool IsSeasonExtra { get; set; }
|
public bool IsSeasonExtra { get; set; }
|
||||||
public bool IsSplitEpisode { get; set; }
|
public bool IsSplitEpisode { get; set; }
|
||||||
|
public bool IsMiniSeries { get; set; }
|
||||||
public bool Special { get; set; }
|
public bool Special { get; set; }
|
||||||
public string ReleaseGroup { get; set; }
|
public string ReleaseGroup { get; set; }
|
||||||
public string ReleaseHash { get; set; }
|
public string ReleaseHash { get; set; }
|
||||||
|
|
|
@ -555,7 +555,7 @@ namespace NzbDrone.Core.Parser
|
||||||
private static readonly Regex SpecialEpisodeWordRegex = new Regex(@"\b(part|special|edition|christmas)\b\s?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
private static readonly Regex SpecialEpisodeWordRegex = new Regex(@"\b(part|special|edition|christmas)\b\s?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
private static readonly Regex DuplicateSpacesRegex = new Regex(@"\s{2,}", RegexOptions.Compiled);
|
private static readonly Regex DuplicateSpacesRegex = new Regex(@"\s{2,}", RegexOptions.Compiled);
|
||||||
private static readonly Regex SeasonFolderRegex = new Regex(@"^(?:S|Season|Saison|Series|Stagione)[-_. ]*(?<season>(?<!\d+)\d{1,4}(?!\d+))(?:[_. ]+(?!\d+)|$)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
private static readonly Regex SeasonFolderRegex = new Regex(@"^(?:S|Season|Saison|Series|Stagione)[-_. ]*(?<season>(?<!\d+)\d{1,4}(?!\d+))(?:[_. ]+(?!\d+)|$)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
private static readonly Regex SimpleEpisodeNumberRegex = new Regex(@"^[ex]?(?<episode>(?<!\d+)\d{1,3}(?!\d+))(?:[ex-](?<episode>(?<!\d+)\d{1,3}(?!\d+)))?(?:[_. ]|$)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
private static readonly Regex SimpleEpisodeNumberRegex = new Regex(@"^[ex]?(?<episode>(?<!\d+)\d{1,3}(?!\d+))(?:[ex-](?<episode>(?<!\d+)\d{1,3}(?!\d+)))?(?:[_. ](?!\d+)(?<remaining>.+)|$)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
private static readonly Regex RequestInfoRegex = new Regex(@"^(?:\[.+?\])+", RegexOptions.Compiled);
|
private static readonly Regex RequestInfoRegex = new Regex(@"^(?:\[.+?\])+", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
@ -564,31 +564,40 @@ namespace NzbDrone.Core.Parser
|
||||||
public static ParsedEpisodeInfo ParsePath(string path)
|
public static ParsedEpisodeInfo ParsePath(string path)
|
||||||
{
|
{
|
||||||
var fileInfo = new FileInfo(path);
|
var fileInfo = new FileInfo(path);
|
||||||
|
var result = ParseTitle(fileInfo.Name);
|
||||||
|
|
||||||
// Parse using the folder and file separately, but combine if they both parse correctly.
|
// Parse using the folder and file separately, but combine if they both parse correctly.
|
||||||
var episodeNumberMatch = SimpleEpisodeNumberRegex.Matches(fileInfo.Name);
|
var episodeNumberMatch = SimpleEpisodeNumberRegex.Match(fileInfo.Name);
|
||||||
|
|
||||||
if (episodeNumberMatch.Count != 0 && fileInfo.Directory?.Name != null)
|
if (episodeNumberMatch.Success && fileInfo.Directory?.Name != null && (result == null || result.IsMiniSeries || result.AbsoluteEpisodeNumbers.Any()))
|
||||||
{
|
{
|
||||||
var parsedFileInfo = ParseMatchCollection(episodeNumberMatch, fileInfo.Name);
|
var seasonMatch = SeasonFolderRegex.Match(fileInfo.Directory.Name);
|
||||||
|
|
||||||
if (parsedFileInfo != null)
|
if (seasonMatch.Success && seasonMatch.Groups["season"].Success)
|
||||||
{
|
{
|
||||||
var seasonMatch = SeasonFolderRegex.Match(fileInfo.Directory.Name);
|
var episodeCaptures = episodeNumberMatch.Groups["episode"].Captures.Cast<Capture>().ToList();
|
||||||
|
var first = ParseNumber(episodeCaptures.First().Value);
|
||||||
|
var last = ParseNumber(episodeCaptures.Last().Value);
|
||||||
|
var pathTitle = $"S{seasonMatch.Groups["season"].Value}E{first:00}";
|
||||||
|
|
||||||
if (seasonMatch.Success && seasonMatch.Groups["season"].Success)
|
if (first != last)
|
||||||
{
|
{
|
||||||
parsedFileInfo.SeasonNumber = int.Parse(seasonMatch.Groups["season"].Value);
|
pathTitle += $"-E{last:00}";
|
||||||
|
|
||||||
Logger.Debug("Episode parsed from file and folder names. {0}", parsedFileInfo);
|
|
||||||
|
|
||||||
return parsedFileInfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (episodeNumberMatch.Groups["remaining"].Success)
|
||||||
|
{
|
||||||
|
pathTitle += $" {episodeNumberMatch.Groups["remaining"].Value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsedFileInfo = ParseTitle(pathTitle);
|
||||||
|
|
||||||
|
Logger.Debug("Episode parsed from file and folder names. {0}", parsedFileInfo);
|
||||||
|
|
||||||
|
return parsedFileInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = ParseTitle(fileInfo.Name);
|
|
||||||
|
|
||||||
if (result == null && int.TryParse(Path.GetFileNameWithoutExtension(fileInfo.Name), out var number))
|
if (result == null && int.TryParse(Path.GetFileNameWithoutExtension(fileInfo.Name), out var number))
|
||||||
{
|
{
|
||||||
Logger.Debug("Attempting to parse episode info using directory and file names. {0}", fileInfo.Directory.Name);
|
Logger.Debug("Attempting to parse episode info using directory and file names. {0}", fileInfo.Directory.Name);
|
||||||
|
@ -1107,6 +1116,7 @@ namespace NzbDrone.Core.Parser
|
||||||
{
|
{
|
||||||
// If no season was found and it's not an absolute only release it should be treated as a mini series and season 1
|
// If no season was found and it's not an absolute only release it should be treated as a mini series and season 1
|
||||||
result.SeasonNumber = 1;
|
result.SeasonNumber = 1;
|
||||||
|
result.IsMiniSeries = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue