Fixed: Specials with the season number will be handled properly
This commit is contained in:
parent
5e68ed7aac
commit
9a92815cbf
|
@ -14,7 +14,7 @@ using NzbDrone.Core.Tv;
|
||||||
namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class DownloadApprovedReportsFixture : CoreTest<DownloadApprovedReports>
|
public class GetQualifiedReportsFixture : CoreTest<DownloadApprovedReports>
|
||||||
{
|
{
|
||||||
private Episode GetEpisode(int id)
|
private Episode GetEpisode(int id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||||
SeriesTitle = ""
|
SeriesTitle = ""
|
||||||
};
|
};
|
||||||
|
|
||||||
parsedEpisodeInfo.IsPossibleSpecialEpisode().Should().BeFalse();
|
parsedEpisodeInfo.IsPossibleSpecialEpisode.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -33,7 +33,15 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||||
SeriesTitle = ""
|
SeriesTitle = ""
|
||||||
};
|
};
|
||||||
|
|
||||||
parsedEpisodeInfo.IsPossibleSpecialEpisode().Should().BeTrue();
|
parsedEpisodeInfo.IsPossibleSpecialEpisode.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Under.the.Dome.S02.Special-Inside.Chesters.Mill.HDTV.x264-BAJSKORV")]
|
||||||
|
[TestCase("Under.the.Dome.S02.Special-Inside.Chesters.Mill.720p.HDTV.x264-BAJSKORV")]
|
||||||
|
[TestCase("Rookie.Blue.Behind.the.Badge.S05.Special.HDTV.x264-2HD")]
|
||||||
|
public void IsPossibleSpecialEpisode_should_be_true(string title)
|
||||||
|
{
|
||||||
|
Parser.Parser.ParseTitle(title).IsPossibleSpecialEpisode.Should().BeTrue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||||
[TestCase("Eureka S 01 720p WEB DL DD 5 1 h264 TjHD", "Eureka", 1)]
|
[TestCase("Eureka S 01 720p WEB DL DD 5 1 h264 TjHD", "Eureka", 1)]
|
||||||
[TestCase("Doctor Who Confidential Season 3", "Doctor Who Confidential", 3)]
|
[TestCase("Doctor Who Confidential Season 3", "Doctor Who Confidential", 3)]
|
||||||
[TestCase("Fleming.S01.720p.WEBDL.DD5.1.H.264-NTb", "Fleming", 1)]
|
[TestCase("Fleming.S01.720p.WEBDL.DD5.1.H.264-NTb", "Fleming", 1)]
|
||||||
public void should_parsefull_season_release(string postTitle, string title, int season)
|
public void should_parse_full_season_release(string postTitle, string title, int season)
|
||||||
{
|
{
|
||||||
var result = Parser.Parser.ParseTitle(postTitle);
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
result.SeasonNumber.Should().Be(season);
|
result.SeasonNumber.Should().Be(season);
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Instrumentation.Extensions;
|
using NzbDrone.Core.Instrumentation.Extensions;
|
||||||
|
@ -63,16 +64,17 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
var parsedEpisodeInfo = Parser.Parser.ParseTitle(report.Title);
|
var parsedEpisodeInfo = Parser.Parser.ParseTitle(report.Title);
|
||||||
|
|
||||||
if (parsedEpisodeInfo == null || parsedEpisodeInfo.IsPossibleSpecialEpisode())
|
if (parsedEpisodeInfo == null || parsedEpisodeInfo.IsPossibleSpecialEpisode)
|
||||||
{
|
{
|
||||||
var specialEpisodeInfo = _parsingService.ParseSpecialEpisodeTitle(report.Title, report.TvRageId, searchCriteria);
|
var specialEpisodeInfo = _parsingService.ParseSpecialEpisodeTitle(report.Title, report.TvRageId, searchCriteria);
|
||||||
|
|
||||||
if (specialEpisodeInfo != null)
|
if (specialEpisodeInfo != null)
|
||||||
{
|
{
|
||||||
parsedEpisodeInfo = specialEpisodeInfo;
|
parsedEpisodeInfo = specialEpisodeInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsedEpisodeInfo != null && !string.IsNullOrWhiteSpace(parsedEpisodeInfo.SeriesTitle))
|
if (parsedEpisodeInfo != null && !parsedEpisodeInfo.SeriesTitle.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, report.TvRageId, searchCriteria);
|
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, report.TvRageId, searchCriteria);
|
||||||
remoteEpisode.Release = report;
|
remoteEpisode.Release = report;
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
|
|
||||||
var episode = _episodeService.GetEpisode(dailySearchSpec.Series.Id, dailySearchSpec.AirDate.ToString(Episode.AIR_DATE_FORMAT));
|
var episode = _episodeService.GetEpisode(dailySearchSpec.Series.Id, dailySearchSpec.AirDate.ToString(Episode.AIR_DATE_FORMAT));
|
||||||
|
|
||||||
if (!remoteEpisode.ParsedEpisodeInfo.IsDaily() || remoteEpisode.ParsedEpisodeInfo.AirDate != episode.AirDate)
|
if (!remoteEpisode.ParsedEpisodeInfo.IsDaily || remoteEpisode.ParsedEpisodeInfo.AirDate != episode.AirDate)
|
||||||
{
|
{
|
||||||
_logger.Debug("Episode AirDate does not match searched episode number, skipping.");
|
_logger.Debug("Episode AirDate does not match searched episode number, skipping.");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
return validationFailure;
|
return validationFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsedEpisodeInfo.IsDaily())
|
if (parsedEpisodeInfo.IsDaily)
|
||||||
{
|
{
|
||||||
if (!parsedEpisodeInfo.AirDate.Equals(sampleResult.Episodes.Single().AirDate))
|
if (!parsedEpisodeInfo.AirDate.Equals(sampleResult.Episodes.Single().AirDate))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,23 +1,24 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Parser.Model
|
namespace NzbDrone.Core.Parser.Model
|
||||||
{
|
{
|
||||||
public class ParsedEpisodeInfo
|
public class ParsedEpisodeInfo
|
||||||
{
|
{
|
||||||
public string SeriesTitle { get; set; }
|
public String SeriesTitle { get; set; }
|
||||||
public SeriesTitleInfo SeriesTitleInfo { get; set; }
|
public SeriesTitleInfo SeriesTitleInfo { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public int SeasonNumber { get; set; }
|
public Int32 SeasonNumber { get; set; }
|
||||||
public int[] EpisodeNumbers { get; set; }
|
public Int32[] EpisodeNumbers { get; set; }
|
||||||
public int[] AbsoluteEpisodeNumbers { get; set; }
|
public Int32[] 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 Boolean FullSeason { get; set; }
|
||||||
public string ReleaseGroup { get; set; }
|
public Boolean Special { get; set; }
|
||||||
public string ReleaseHash { get; set; }
|
public String ReleaseGroup { get; set; }
|
||||||
|
public String ReleaseHash { get; set; }
|
||||||
|
|
||||||
public ParsedEpisodeInfo()
|
public ParsedEpisodeInfo()
|
||||||
{
|
{
|
||||||
|
@ -25,46 +26,56 @@ namespace NzbDrone.Core.Parser.Model
|
||||||
AbsoluteEpisodeNumbers = new int[0];
|
AbsoluteEpisodeNumbers = new int[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsDaily()
|
public bool IsDaily
|
||||||
{
|
{
|
||||||
return !String.IsNullOrWhiteSpace(AirDate);
|
get
|
||||||
|
{
|
||||||
|
return !String.IsNullOrWhiteSpace(AirDate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsAbsoluteNumbering()
|
public bool IsAbsoluteNumbering
|
||||||
{
|
{
|
||||||
return AbsoluteEpisodeNumbers.Any();
|
get
|
||||||
|
{
|
||||||
|
return AbsoluteEpisodeNumbers.Any();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsPossibleSpecialEpisode()
|
public bool IsPossibleSpecialEpisode
|
||||||
{
|
{
|
||||||
// if we dont have eny episode numbers we are likely a special episode and need to do a search by episode title
|
get
|
||||||
return String.IsNullOrWhiteSpace(AirDate) &&
|
{
|
||||||
(EpisodeNumbers.Length == 0 || SeasonNumber == 0) &&
|
// if we don't have eny episode numbers we are likely a special episode and need to do a search by episode title
|
||||||
String.IsNullOrWhiteSpace(SeriesTitle);
|
return (AirDate.IsNullOrWhiteSpace() &&
|
||||||
|
SeriesTitle.IsNullOrWhiteSpace() &&
|
||||||
|
(EpisodeNumbers.Length == 0 || SeasonNumber == 0) ||
|
||||||
|
!SeriesTitle.IsNullOrWhiteSpace() && Special);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
string episodeString = "[Unknown Episode]";
|
string episodeString = "[Unknown Episode]";
|
||||||
|
|
||||||
if (IsDaily() && EpisodeNumbers == null)
|
if (IsDaily && EpisodeNumbers == null)
|
||||||
{
|
{
|
||||||
episodeString = string.Format("{0}", AirDate);
|
episodeString = String.Format("{0}", AirDate);
|
||||||
}
|
}
|
||||||
else if (FullSeason)
|
else if (FullSeason)
|
||||||
{
|
{
|
||||||
episodeString = string.Format("Season {0:00}", SeasonNumber);
|
episodeString = String.Format("Season {0:00}", SeasonNumber);
|
||||||
}
|
}
|
||||||
else if (EpisodeNumbers != null && EpisodeNumbers.Any())
|
else if (EpisodeNumbers != null && EpisodeNumbers.Any())
|
||||||
{
|
{
|
||||||
episodeString = string.Format("S{0:00}E{1}", SeasonNumber, String.Join("-", EpisodeNumbers.Select(c => c.ToString("00"))));
|
episodeString = String.Format("S{0:00}E{1}", SeasonNumber, String.Join("-", EpisodeNumbers.Select(c => c.ToString("00"))));
|
||||||
}
|
}
|
||||||
else if (AbsoluteEpisodeNumbers != null && AbsoluteEpisodeNumbers.Any())
|
else if (AbsoluteEpisodeNumbers != null && AbsoluteEpisodeNumbers.Any())
|
||||||
{
|
{
|
||||||
episodeString = string.Format("{0}", String.Join("-", AbsoluteEpisodeNumbers.Select(c => c.ToString("000"))));
|
episodeString = String.Format("{0}", String.Join("-", AbsoluteEpisodeNumbers.Select(c => c.ToString("000"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Format("{0} - {1} {2}", SeriesTitle, episodeString, Quality);
|
return String.Format("{0} - {1} {2}", SeriesTitle, episodeString, Quality);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -190,7 +190,7 @@ namespace NzbDrone.Core.Parser
|
||||||
var titleWithoutExtension = RemoveFileExtension(title).ToCharArray();
|
var titleWithoutExtension = RemoveFileExtension(title).ToCharArray();
|
||||||
Array.Reverse(titleWithoutExtension);
|
Array.Reverse(titleWithoutExtension);
|
||||||
|
|
||||||
title = new string(titleWithoutExtension) + title.Substring(titleWithoutExtension.Length);
|
title = new String(titleWithoutExtension) + title.Substring(titleWithoutExtension.Length);
|
||||||
|
|
||||||
Logger.Debug("Reversed name detected. Converted to '{0}'", title);
|
Logger.Debug("Reversed name detected. Converted to '{0}'", title);
|
||||||
}
|
}
|
||||||
|
@ -213,8 +213,15 @@ namespace NzbDrone.Core.Parser
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = ParseMatchCollection(match);
|
var result = ParseMatchCollection(match);
|
||||||
|
|
||||||
if (result != null)
|
if (result != null)
|
||||||
{
|
{
|
||||||
|
if (result.FullSeason && title.ContainsIgnoreCase("Special"))
|
||||||
|
{
|
||||||
|
result.FullSeason = false;
|
||||||
|
result.Special = true;
|
||||||
|
}
|
||||||
|
|
||||||
result.Language = ParseLanguage(title);
|
result.Language = ParseLanguage(title);
|
||||||
Logger.Debug("Language parsed: {0}", result.Language);
|
Logger.Debug("Language parsed: {0}", result.Language);
|
||||||
|
|
||||||
|
@ -379,12 +386,10 @@ namespace NzbDrone.Core.Parser
|
||||||
}
|
}
|
||||||
|
|
||||||
//If no season was found it should be treated as a mini series and season 1
|
//If no season was found it should be treated as a mini series and season 1
|
||||||
if (seasons.Count == 0)
|
if (seasons.Count == 0) seasons.Add(1);
|
||||||
seasons.Add(1);
|
|
||||||
|
|
||||||
//If more than 1 season was parsed go to the next REGEX (A multi-season release is unlikely)
|
//If more than 1 season was parsed go to the next REGEX (A multi-season release is unlikely)
|
||||||
if (seasons.Distinct().Count() > 1)
|
if (seasons.Distinct().Count() > 1) return null;
|
||||||
return null;
|
|
||||||
|
|
||||||
result = new ParsedEpisodeInfo
|
result = new ParsedEpisodeInfo
|
||||||
{
|
{
|
||||||
|
@ -431,12 +436,12 @@ namespace NzbDrone.Core.Parser
|
||||||
{
|
{
|
||||||
//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
|
||||||
//Todo: Set a "Extras" flag in EpisodeParseResult if we want to download them ever
|
//Todo: Set a "Extras" flag in EpisodeParseResult if we want to download them ever
|
||||||
if (!String.IsNullOrWhiteSpace(matchCollection[0].Groups["extras"].Value))
|
if (!matchCollection[0].Groups["extras"].Value.IsNullOrWhiteSpace()) return null;
|
||||||
return null;
|
|
||||||
|
|
||||||
result.FullSeason = true;
|
result.FullSeason = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.AbsoluteEpisodeNumbers.Any() && !result.EpisodeNumbers.Any())
|
if (result.AbsoluteEpisodeNumbers.Any() && !result.EpisodeNumbers.Any())
|
||||||
{
|
{
|
||||||
result.SeasonNumber = 0;
|
result.SeasonNumber = 0;
|
||||||
|
|
|
@ -44,15 +44,13 @@ namespace NzbDrone.Core.Parser
|
||||||
{
|
{
|
||||||
var parsedEpisodeInfo = Parser.ParsePath(filename);
|
var parsedEpisodeInfo = Parser.ParsePath(filename);
|
||||||
|
|
||||||
// do we have a possible special episode?
|
if (parsedEpisodeInfo == null || parsedEpisodeInfo.IsPossibleSpecialEpisode)
|
||||||
if (parsedEpisodeInfo == null || parsedEpisodeInfo.IsPossibleSpecialEpisode())
|
|
||||||
{
|
{
|
||||||
// try to parse as a special episode
|
|
||||||
var title = Path.GetFileNameWithoutExtension(filename);
|
var title = Path.GetFileNameWithoutExtension(filename);
|
||||||
var specialEpisodeInfo = ParseSpecialEpisodeTitle(title, series);
|
var specialEpisodeInfo = ParseSpecialEpisodeTitle(title, series);
|
||||||
|
|
||||||
if (specialEpisodeInfo != null)
|
if (specialEpisodeInfo != null)
|
||||||
{
|
{
|
||||||
// use special episode
|
|
||||||
parsedEpisodeInfo = specialEpisodeInfo;
|
parsedEpisodeInfo = specialEpisodeInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +129,7 @@ namespace NzbDrone.Core.Parser
|
||||||
return _episodeService.GetEpisodesBySeason(series.Id, parsedEpisodeInfo.SeasonNumber);
|
return _episodeService.GetEpisodesBySeason(series.Id, parsedEpisodeInfo.SeasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsedEpisodeInfo.IsDaily())
|
if (parsedEpisodeInfo.IsDaily)
|
||||||
{
|
{
|
||||||
if (series.SeriesType == SeriesTypes.Standard)
|
if (series.SeriesType == SeriesTypes.Standard)
|
||||||
{
|
{
|
||||||
|
@ -149,7 +147,7 @@ namespace NzbDrone.Core.Parser
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsedEpisodeInfo.IsAbsoluteNumbering())
|
if (parsedEpisodeInfo.IsAbsoluteNumbering)
|
||||||
{
|
{
|
||||||
var sceneSeasonNumber = _sceneMappingService.GetSeasonNumber(parsedEpisodeInfo.SeriesTitle);
|
var sceneSeasonNumber = _sceneMappingService.GetSeasonNumber(parsedEpisodeInfo.SeriesTitle);
|
||||||
|
|
||||||
|
@ -299,6 +297,7 @@ namespace NzbDrone.Core.Parser
|
||||||
{
|
{
|
||||||
// find special episode in series season 0
|
// find special episode in series season 0
|
||||||
var episode = _episodeService.FindEpisodeByName(series.Id, 0, title);
|
var episode = _episodeService.FindEpisodeByName(series.Id, 0, title);
|
||||||
|
|
||||||
if (episode != null)
|
if (episode != null)
|
||||||
{
|
{
|
||||||
// create parsed info from tv episode
|
// create parsed info from tv episode
|
||||||
|
|
Loading…
Reference in New Issue