mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-12-16 11:37:58 +02:00
Merge branch 'regex-overhaul' into develop
This commit is contained in:
commit
e8bda2a85c
@ -120,7 +120,7 @@ public void PathParse_tests(string path, int season, int episode)
|
|||||||
ExceptionVerification.IgnoreWarns();
|
ExceptionVerification.IgnoreWarns();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("[DmonHiro] The Severing Crime Edge - Cut 02 - Portrait Of Heresy [BD, 720p] [BE36E9E0]")]
|
[TestCase("THIS SHOULD NEVER PARSE")]
|
||||||
public void unparsable_title_should_log_warn_and_return_null(string title)
|
public void unparsable_title_should_log_warn_and_return_null(string title)
|
||||||
{
|
{
|
||||||
Parser.Parser.ParseTitle(title).Should().BeNull();
|
Parser.Parser.ParseTitle(title).Should().BeNull();
|
||||||
@ -147,7 +147,9 @@ public void unparsable_title_should_log_warn_and_return_null(string title)
|
|||||||
[TestCase("Hell.on.Wheels.S02E09-E10.720p.HDTV.x264-EVOLVE", "Hell on Wheels", 2, new[] { 9, 10 })]
|
[TestCase("Hell.on.Wheels.S02E09-E10.720p.HDTV.x264-EVOLVE", "Hell on Wheels", 2, new[] { 9, 10 })]
|
||||||
[TestCase("Grey's Anatomy - 8x01_02 - Free Falling", "Grey's Anatomy", 8, new [] { 1,2 })]
|
[TestCase("Grey's Anatomy - 8x01_02 - Free Falling", "Grey's Anatomy", 8, new [] { 1,2 })]
|
||||||
[TestCase("8x01_02 - Free Falling", "", 8, new[] { 1, 2 })]
|
[TestCase("8x01_02 - Free Falling", "", 8, new[] { 1, 2 })]
|
||||||
[TestCase("Kaamelott.S01E91-E100", "Kaamelott", 1,new[] { 91, 92, 93, 94, 95, 96, 97, 98, 99, 100 })]
|
[TestCase("Kaamelott.S01E91-E100", "Kaamelott", 1, new[] { 91, 92, 93, 94, 95, 96, 97, 98, 99, 100 })]
|
||||||
|
[TestCase("Neighbours.S29E161-E165.PDTV.x264-FQM", "Neighbours", 29, new[] { 161, 162, 163, 164, 165 })]
|
||||||
|
[TestCase("Shortland.Street.S22E5363-E5366.HDTV.x264-FiHTV", "Shortland Street", 22, new[] { 5363, 5364, 5365, 5366 })]
|
||||||
public void TitleParse_multi(string postTitle, string title, int season, int[] episodes)
|
public void TitleParse_multi(string postTitle, string title, int season, int[] episodes)
|
||||||
{
|
{
|
||||||
var result = Parser.Parser.ParseTitle(postTitle);
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
@ -174,7 +176,39 @@ public void parse_daily_episodes(string postTitle, string title, int year, int m
|
|||||||
result.Should().NotBeNull();
|
result.Should().NotBeNull();
|
||||||
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
|
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
|
||||||
result.AirDate.Should().Be(airDate.ToString(Episode.AIR_DATE_FORMAT));
|
result.AirDate.Should().Be(airDate.ToString(Episode.AIR_DATE_FORMAT));
|
||||||
result.EpisodeNumbers.Should().BeNull();
|
result.EpisodeNumbers.Should().BeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("[SubDESU]_High_School_DxD_07_(1280x720_x264-AAC)_[6B7FD717]", "High School DxD", 7, 0, 0)]
|
||||||
|
[TestCase("[Chihiro]_Working!!_-_06_[848x480_H.264_AAC][859EEAFA]", "Working!!", 6, 0, 0)]
|
||||||
|
[TestCase("[Commie]_Senki_Zesshou_Symphogear_-_11_[65F220B4]", "Senki_Zesshou_Symphogear", 11, 0, 0)]
|
||||||
|
[TestCase("[Underwater]_Rinne_no_Lagrange_-_12_(720p)_[5C7BC4F9]", "Rinne_no_Lagrange", 12, 0, 0)]
|
||||||
|
[TestCase("[Commie]_Rinne_no_Lagrange_-_15_[E76552EA]", "Rinne_no_Lagrange", 15, 0, 0)]
|
||||||
|
[TestCase("[HorribleSubs]_Hunter_X_Hunter_-_33_[720p]", "Hunter_X_Hunter", 33, 0, 0)]
|
||||||
|
[TestCase("[HorribleSubs]_Fairy_Tail_-_145_[720p]", "Fairy_Tail", 145, 0, 0)]
|
||||||
|
[TestCase("[HorribleSubs] Tonari no Kaibutsu-kun - 13 [1080p].mkv", "Tonari no Kaibutsu-kun", 13, 0, 0)]
|
||||||
|
[TestCase("[Doremi].Yes.Pretty.Cure.5.Go.Go!.31.[1280x720].[C65D4B1F].mkv", "Yes.Pretty.Cure.5.Go.Go!", 31, 0, 0)]
|
||||||
|
[TestCase("[K-F] One Piece 214", "One Piece", 214, 0, 0)]
|
||||||
|
[TestCase("[K-F] One Piece S10E14 214", "One Piece", 214, 10, 14)]
|
||||||
|
[TestCase("[K-F] One Piece 10x14 214", "One Piece", 214, 10, 14)]
|
||||||
|
[TestCase("[K-F] One Piece 214 10x14", "One Piece", 214, 10, 14)]
|
||||||
|
[TestCase("One Piece S10E14 214", "One Piece", 214, 10, 14)]
|
||||||
|
[TestCase("One Piece 10x14 214", "One Piece", 214, 10, 14)]
|
||||||
|
[TestCase("One Piece 214 10x14", "One Piece", 214, 10, 14)]
|
||||||
|
[TestCase("214 One Piece 10x14", "One Piece", 214, 10, 14)]
|
||||||
|
[TestCase("Bleach - 031 - The Resolution to Kill [Lunar].avi", "Bleach", 31, 0, 0)]
|
||||||
|
[TestCase("Bleach - 031 - The Resolution to Kill [Lunar]", "Bleach", 31, 0, 0)]
|
||||||
|
[TestCase("[ACX]Hack Sign 01 Role Play [Kosaka] [9C57891E].mkv", "Hack Sign", 1, 0, 0)]
|
||||||
|
[TestCase("[SFW-sage] Bakuman S3 - 12 [720p][D07C91FC]", "Bakuman S3", 12, 0, 0)]
|
||||||
|
[TestCase("ducktales_e66_time_is_money_part_one_marking_time", "DuckTales", 66, 0, 0)]
|
||||||
|
public void parse_absolute_numbers(string postTitle, string title, int absoluteEpisodeNumber, int seasonNumber, int episodeNumber)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.AbsoluteEpisodeNumbers.First().Should().Be(absoluteEpisodeNumber);
|
||||||
|
result.SeasonNumber.Should().Be(seasonNumber);
|
||||||
|
result.EpisodeNumbers.FirstOrDefault().Should().Be(episodeNumber);
|
||||||
|
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +38,8 @@ public void Setup()
|
|||||||
{
|
{
|
||||||
SeriesTitle = _series.Title,
|
SeriesTitle = _series.Title,
|
||||||
SeasonNumber = 1,
|
SeasonNumber = 1,
|
||||||
EpisodeNumbers = new[] { 1 }
|
EpisodeNumbers = new[] { 1 },
|
||||||
|
AbsoluteEpisodeNumbers = new int[0]
|
||||||
};
|
};
|
||||||
|
|
||||||
_singleEpisodeSearchCriteria = new SingleEpisodeSearchCriteria
|
_singleEpisodeSearchCriteria = new SingleEpisodeSearchCriteria
|
||||||
@ -69,6 +70,11 @@ private void GivenSceneNumberingSeries()
|
|||||||
_series.UseSceneNumbering = true;
|
_series.UseSceneNumbering = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GivenAbsoluteNumberingSeries()
|
||||||
|
{
|
||||||
|
_parsedEpisodeInfo.AbsoluteEpisodeNumbers = new[] { 1 };
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_get_daily_episode_episode_when_search_criteria_is_null()
|
public void should_get_daily_episode_episode_when_search_criteria_is_null()
|
||||||
{
|
{
|
||||||
@ -105,6 +111,17 @@ public void should_fallback_to_daily_episode_lookup_when_search_criteria_episode
|
|||||||
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<String>()), Times.Once());
|
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<String>()), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_use_search_criteria_episode_when_it_matches_absolute()
|
||||||
|
{
|
||||||
|
GivenAbsoluteNumberingSeries();
|
||||||
|
|
||||||
|
Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||||
|
|
||||||
|
Mocker.GetMock<IEpisodeService>()
|
||||||
|
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<String>()), Times.Never());
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_use_scene_numbering_when_series_uses_scene_numbering()
|
public void should_use_scene_numbering_when_series_uses_scene_numbering()
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,7 @@ public void Setup()
|
|||||||
.With(e => e.SeasonNumber = 1)
|
.With(e => e.SeasonNumber = 1)
|
||||||
.With(e => e.SceneSeasonNumber = 2)
|
.With(e => e.SceneSeasonNumber = 2)
|
||||||
.With(e => e.EpisodeNumber = 3)
|
.With(e => e.EpisodeNumber = 3)
|
||||||
|
.With(e => e.AbsoluteEpisodeNumber = 3)
|
||||||
.With(e => e.SceneEpisodeNumber = 4)
|
.With(e => e.SceneEpisodeNumber = 4)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -51,5 +52,14 @@ public void should_not_find_episode_that_does_not_exist()
|
|||||||
.Should()
|
.Should()
|
||||||
.BeNull();
|
.BeNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_find_episode_by_absolute_numbering()
|
||||||
|
{
|
||||||
|
Subject.Find(_episode.SeriesId, _episode.AbsoluteEpisodeNumber.Value)
|
||||||
|
.Id
|
||||||
|
.Should()
|
||||||
|
.Be(_episode.Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,27 @@ public class ParsedEpisodeInfo
|
|||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public int SeasonNumber { get; set; }
|
public int SeasonNumber { get; set; }
|
||||||
public int[] EpisodeNumbers { get; set; }
|
public int[] EpisodeNumbers { get; set; }
|
||||||
|
public int[] AbsoluteEpisodeNumbers { get; set; }
|
||||||
public String AirDate { get; set; }
|
public String AirDate { get; set; }
|
||||||
public Language Language { get; set; }
|
public Language Language { get; set; }
|
||||||
|
|
||||||
public bool FullSeason { get; set; }
|
public bool FullSeason { get; set; }
|
||||||
|
|
||||||
|
public ParsedEpisodeInfo()
|
||||||
|
{
|
||||||
|
EpisodeNumbers = new int[0];
|
||||||
|
AbsoluteEpisodeNumbers = new int[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDaily()
|
||||||
|
{
|
||||||
|
return !String.IsNullOrWhiteSpace(AirDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsAbsoluteNumbering()
|
||||||
|
{
|
||||||
|
return AbsoluteEpisodeNumbers.Any();
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
string episodeString = "[Unknown Episode]";
|
string episodeString = "[Unknown Episode]";
|
||||||
@ -35,10 +51,5 @@ public override string ToString()
|
|||||||
|
|
||||||
return string.Format("{0} - {1} {2}", SeriesTitle, episodeString, Quality);
|
return string.Format("{0} - {1} {2}", SeriesTitle, episodeString, Quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsDaily()
|
|
||||||
{
|
|
||||||
return !String.IsNullOrWhiteSpace(AirDate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
@ -20,6 +21,22 @@ public static class Parser
|
|||||||
new Regex(@"^(?<title>.+?)?\W*(?<airyear>\d{4})\W+(?<airmonth>[0-1][0-9])\W+(?<airday>[0-3][0-9])(\W+|_|$)(?!\\)",
|
new Regex(@"^(?<title>.+?)?\W*(?<airyear>\d{4})\W+(?<airmonth>[0-1][0-9])\W+(?<airday>[0-3][0-9])(\W+|_|$)(?!\\)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
|
//Anime - Absolute Episode Number + Title + Season+Episode
|
||||||
|
new Regex(@"^(?:(?<absoluteepisode>\d{2,3})(?:_|-|\s|\.)+)+(?<title>.+?)(?:\W|_)+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
|
//Anime - [SubGroup] Title Absolute Episode Number + Season+Episode
|
||||||
|
new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.))?(?<title>.+?)(?:(?:\W|_)+(?<absoluteepisode>\d{2,3}))+(?:_|-|\s|\.)+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
|
//Anime - [SubGroup] Title Season+Episode + Absolute Episode Number
|
||||||
|
new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.))?(?<title>.+?)(?:\W|_)+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)(?:\s|\.)(?:(?<absoluteepisode>\d{2,3})(?:_|-|\s|\.|$)+)+",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
|
//Anime - [SubGroup] Title Absolute Episode Number
|
||||||
|
new Regex(@"^\[(?<subgroup>.+?)\](?:_|-|\s|\.)?(?<title>.+?)(?:(?:\W|_)+(?<absoluteepisode>\d{2,}))+",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
//Multi-Part episodes without a title (S01E05.S01E06)
|
//Multi-Part episodes without a title (S01E05.S01E06)
|
||||||
new Regex(@"^(?:\W*S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:[ex]){1,2}(?<episode>\d{1,3}(?!\d+)))+){2,}(\W+|_|$)(?!\\)",
|
new Regex(@"^(?:\W*S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:[ex]){1,2}(?<episode>\d{1,3}(?!\d+)))+){2,}(\W+|_|$)(?!\\)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
@ -44,6 +61,10 @@ public static class Parser
|
|||||||
new Regex(@"^(?<title>.*?)(?:\W?S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]){1,2}(?<episode>\d{1}))+)+(\W+|_|$)(?!\\)",
|
new Regex(@"^(?<title>.*?)(?:\W?S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]){1,2}(?<episode>\d{1}))+)+(\W+|_|$)(?!\\)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
|
//Anime - Title Absolute Episode Number [SubGroup]
|
||||||
|
new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+(?<absoluteepisode>\d{2,3}))+(?:.+?)\[(?<subgroup>.+?)\](?:\.|$)",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
//Supports 103/113 naming
|
//Supports 103/113 naming
|
||||||
new Regex(@"^(?<title>.+?)?(?:\W?(?<season>(?<!\d+)\d{1})(?<episode>\d{2}(?!p|i|\d+)))+(\W+|_|$)(?!\\)",
|
new Regex(@"^(?<title>.+?)?(?:\W?(?<season>(?<!\d+)\d{1})(?<episode>\d{2}(?!p|i|\d+)))+(\W+|_|$)(?!\\)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
@ -53,7 +74,7 @@ public static class Parser
|
|||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
//Supports 1103/1113 naming
|
//Supports 1103/1113 naming
|
||||||
new Regex(@"^(?<title>.+?)?(?:\W?(?<season>(?<!\d+|\(|\[)\d{2})(?<episode>\d{2}(?!p|i|\d+|\)|\]|\W\d+)))+(\W+|_|$)(?!\\)",
|
new Regex(@"^(?<title>.+?)?(?:\W?(?<season>(?<!\d+|\(|\[|e|x)\d{2})(?<episode>(?<!e|x)\d{2}(?!p|i|\d+|\)|\]|\W\d+)))+(\W+|_|$)(?!\\)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
//Supports Season 01 Episode 03
|
//Supports Season 01 Episode 03
|
||||||
@ -62,7 +83,20 @@ public static class Parser
|
|||||||
|
|
||||||
//Supports Season only releases
|
//Supports Season only releases
|
||||||
new Regex(@"^(?<title>.+?)\W(?:S|Season)\W?(?<season>\d{1,2}(?!\d+))(\W+|_|$)(?<extras>EXTRAS|SUBPACK)?(?!\\)",
|
new Regex(@"^(?<title>.+?)\W(?:S|Season)\W?(?<season>\d{1,2}(?!\d+))(\W+|_|$)(?<extras>EXTRAS|SUBPACK)?(?!\\)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled)
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
|
//4-digit episode number
|
||||||
|
//Episodes without a title, Single (S01E05, 1x05) AND Multi (S01E04E05, 1x04x05, etc)
|
||||||
|
new Regex(@"^(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{4}(?!\d+|i|p)))+)(\W+|_|$)(?!\\)",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
|
//Episodes with a title, Single episodes (S01E05, 1x05, etc) & Multi-episode (S01E05E06, S01E05-06, S01E05 E06, etc)
|
||||||
|
new Regex(@"^(?<title>.+?)(?:(\W|_)+S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{4}(?!\d+|i|p)))+)\W?(?!\\)",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
|
//Anime - Title Absolute Episode Number
|
||||||
|
new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+e(?<absoluteepisode>\d{2,3}))+",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly Regex NormalizeRegex = new Regex(@"((^|\W|_)(a|an|the|and|or|of)($|\W|_))|\W|_|(?:(?<=[^0-9]+)|\b)(?!(?:19\d{2}|20\d{2}))\d+(?=[^0-9ip]+|\b)",
|
private static readonly Regex NormalizeRegex = new Regex(@"((^|\W|_)(a|an|the|and|or|of)($|\W|_))|\W|_|(?:(?<=[^0-9]+)|\b)(?!(?:19\d{2}|20\d{2}))\d+(?=[^0-9ip]+|\b)",
|
||||||
@ -114,6 +148,7 @@ public static ParsedEpisodeInfo ParseTitle(string title)
|
|||||||
|
|
||||||
if (match.Count != 0)
|
if (match.Count != 0)
|
||||||
{
|
{
|
||||||
|
Debug.WriteLine(regex);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = ParseMatchCollection(match);
|
var result = ParseMatchCollection(match);
|
||||||
@ -226,11 +261,13 @@ private static ParsedEpisodeInfo ParseMatchCollection(MatchCollection matchColle
|
|||||||
{
|
{
|
||||||
SeasonNumber = seasons.First(),
|
SeasonNumber = seasons.First(),
|
||||||
EpisodeNumbers = new int[0],
|
EpisodeNumbers = new int[0],
|
||||||
|
AbsoluteEpisodeNumbers = new int[0]
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (Match matchGroup in matchCollection)
|
foreach (Match matchGroup in matchCollection)
|
||||||
{
|
{
|
||||||
var episodeCaptures = matchGroup.Groups["episode"].Captures.Cast<Capture>().ToList();
|
var episodeCaptures = matchGroup.Groups["episode"].Captures.Cast<Capture>().ToList();
|
||||||
|
var absoluteEpisodeCaptures = matchGroup.Groups["absoluteepisode"].Captures.Cast<Capture>().ToList();
|
||||||
|
|
||||||
//Allows use to return a list of 0 episodes (We can handle that as a full season release)
|
//Allows use to return a list of 0 episodes (We can handle that as a full season release)
|
||||||
if (episodeCaptures.Any())
|
if (episodeCaptures.Any())
|
||||||
@ -246,6 +283,20 @@ private static ParsedEpisodeInfo ParseMatchCollection(MatchCollection matchColle
|
|||||||
var count = last - first + 1;
|
var count = last - first + 1;
|
||||||
result.EpisodeNumbers = Enumerable.Range(first, count).ToArray();
|
result.EpisodeNumbers = Enumerable.Range(first, count).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (absoluteEpisodeCaptures.Any())
|
||||||
|
{
|
||||||
|
var first = Convert.ToInt32(absoluteEpisodeCaptures.First().Value);
|
||||||
|
var last = Convert.ToInt32(absoluteEpisodeCaptures.Last().Value);
|
||||||
|
|
||||||
|
if (first > last)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var count = last - first + 1;
|
||||||
|
result.AbsoluteEpisodeNumbers = Enumerable.Range(first, count).ToArray();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Check to see if this is an "Extras" or "SUBPACK" release, if it is, return NULL
|
//Check to see if this is an "Extras" or "SUBPACK" release, if it is, return NULL
|
||||||
@ -256,6 +307,10 @@ private static ParsedEpisodeInfo ParseMatchCollection(MatchCollection matchColle
|
|||||||
result.FullSeason = true;
|
result.FullSeason = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (result.AbsoluteEpisodeNumbers.Any() && !result.EpisodeNumbers.Any())
|
||||||
|
{
|
||||||
|
result.SeasonNumber = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
|
@ -129,6 +129,26 @@ public List<Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series ser
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parsedEpisodeInfo.IsAbsoluteNumbering())
|
||||||
|
{
|
||||||
|
foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers)
|
||||||
|
{
|
||||||
|
var episodeInfo = _episodeService.FindEpisode(series.Id, absoluteEpisodeNumber);
|
||||||
|
|
||||||
|
if (episodeInfo != null)
|
||||||
|
{
|
||||||
|
_logger.Info("Using absolute episode number {0} for: {1} - TVDB: {2}x{3:00}",
|
||||||
|
absoluteEpisodeNumber,
|
||||||
|
series.Title,
|
||||||
|
episodeInfo.SeasonNumber,
|
||||||
|
episodeInfo.EpisodeNumber);
|
||||||
|
result.Add(episodeInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (parsedEpisodeInfo.EpisodeNumbers == null)
|
if (parsedEpisodeInfo.EpisodeNumbers == null)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ namespace NzbDrone.Core.Tv
|
|||||||
public interface IEpisodeRepository : IBasicRepository<Episode>
|
public interface IEpisodeRepository : IBasicRepository<Episode>
|
||||||
{
|
{
|
||||||
Episode Find(int seriesId, int season, int episodeNumber);
|
Episode Find(int seriesId, int season, int episodeNumber);
|
||||||
|
Episode Find(int seriesId, int absoluteEpisodeNumber);
|
||||||
Episode Get(int seriesId, String date);
|
Episode Get(int seriesId, String date);
|
||||||
Episode Find(int seriesId, String date);
|
Episode Find(int seriesId, String date);
|
||||||
List<Episode> GetEpisodes(int seriesId);
|
List<Episode> GetEpisodes(int seriesId);
|
||||||
@ -39,6 +40,11 @@ public Episode Find(int seriesId, int season, int episodeNumber)
|
|||||||
return Query.SingleOrDefault(s => s.SeriesId == seriesId && s.SeasonNumber == season && s.EpisodeNumber == episodeNumber);
|
return Query.SingleOrDefault(s => s.SeriesId == seriesId && s.SeasonNumber == season && s.EpisodeNumber == episodeNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Episode Find(int seriesId, int absoluteEpisodeNumber)
|
||||||
|
{
|
||||||
|
return Query.SingleOrDefault(s => s.SeriesId == seriesId && s.AbsoluteEpisodeNumber == absoluteEpisodeNumber);
|
||||||
|
}
|
||||||
|
|
||||||
public Episode Get(int seriesId, String date)
|
public Episode Get(int seriesId, String date)
|
||||||
{
|
{
|
||||||
return Query.Single(s => s.SeriesId == seriesId && s.AirDate == date);
|
return Query.Single(s => s.SeriesId == seriesId && s.AirDate == date);
|
||||||
|
@ -14,6 +14,7 @@ public interface IEpisodeService
|
|||||||
{
|
{
|
||||||
Episode GetEpisode(int id);
|
Episode GetEpisode(int id);
|
||||||
Episode FindEpisode(int seriesId, int seasonNumber, int episodeNumber, bool useScene = false);
|
Episode FindEpisode(int seriesId, int seasonNumber, int episodeNumber, bool useScene = false);
|
||||||
|
Episode FindEpisode(int seriesId, int absoluteEpisodeNumber);
|
||||||
Episode GetEpisode(int seriesId, String date);
|
Episode GetEpisode(int seriesId, String date);
|
||||||
Episode FindEpisode(int seriesId, String date);
|
Episode FindEpisode(int seriesId, String date);
|
||||||
List<Episode> GetEpisodeBySeries(int seriesId);
|
List<Episode> GetEpisodeBySeries(int seriesId);
|
||||||
@ -62,6 +63,11 @@ public Episode FindEpisode(int seriesId, int seasonNumber, int episodeNumber, bo
|
|||||||
return _episodeRepository.Find(seriesId, seasonNumber, episodeNumber);
|
return _episodeRepository.Find(seriesId, seasonNumber, episodeNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Episode FindEpisode(int seriesId, int absoluteEpisodeNumber)
|
||||||
|
{
|
||||||
|
return _episodeRepository.Find(seriesId, absoluteEpisodeNumber);
|
||||||
|
}
|
||||||
|
|
||||||
public Episode GetEpisode(int seriesId, String date)
|
public Episode GetEpisode(int seriesId, String date)
|
||||||
{
|
{
|
||||||
return _episodeRepository.Get(seriesId, date);
|
return _episodeRepository.Get(seriesId, date);
|
||||||
|
Loading…
Reference in New Issue
Block a user