Fixed: Specials with the season number will be handled properly

pull/6/head
Mark McDowall 10 years ago
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…
Cancel
Save