diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportService.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportService.cs index ea794ea92..032497670 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportService.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -205,10 +205,23 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual item.Series = decision.LocalEpisode.Series; } - if (decision.LocalEpisode.Episodes.Any()) + if (decision.LocalEpisode.Episodes.Any() && decision.LocalEpisode.Episodes.Select(c => c.SeasonNumber).Distinct().Count() == 1) { - item.SeasonNumber = decision.LocalEpisode.SeasonNumber; - item.Episodes = decision.LocalEpisode.Episodes; + var seasons = decision.LocalEpisode.Episodes.Select(c => c.SeasonNumber).Distinct().ToList(); + + if (seasons.Empty()) + { + _logger.Warn("Expected one season, but found none for: {0}", decision.LocalEpisode.Path); + } + else if (seasons.Count > 1) + { + _logger.Warn("Expected one season, but found {0} ({1}) for: {2}", seasons.Count, string.Join(", ", seasons), decision.LocalEpisode.Path); + } + else + { + item.SeasonNumber = decision.LocalEpisode.SeasonNumber; + item.Episodes = decision.LocalEpisode.Episodes; + } } item.Quality = decision.LocalEpisode.Quality; diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotSampleSpecification.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotSampleSpecification.cs index ea3848d39..731f69f9c 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotSampleSpecification.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotSampleSpecification.cs @@ -1,6 +1,8 @@ -using NLog; +using System; +using NLog; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Download; +using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications @@ -25,18 +27,23 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications return Decision.Accept(); } - var sample = _detectSample.IsSample(localEpisode.Series, - localEpisode.Path, - localEpisode.IsSpecial); - - if (sample == DetectSampleResult.Sample) + try { - return Decision.Reject("Sample"); + var sample = _detectSample.IsSample(localEpisode.Series, localEpisode.Path, localEpisode.IsSpecial); + + if (sample == DetectSampleResult.Sample) + { + return Decision.Reject("Sample"); + } + + else if (sample == DetectSampleResult.Indeterminate) + { + return Decision.Reject("Unable to determine if file is a sample"); + } } - - else if (sample == DetectSampleResult.Indeterminate) + catch (InvalidSeasonException e) { - return Decision.Reject("Unable to determine if file is a sample"); + _logger.Warn(e, "Invalid season detected during sample check"); } return Decision.Accept(); diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 0aa6fef7c..ebad14f1e 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -936,6 +936,7 @@ + diff --git a/src/NzbDrone.Core/Parser/InvalidSeasonException.cs b/src/NzbDrone.Core/Parser/InvalidSeasonException.cs new file mode 100644 index 000000000..23ce77954 --- /dev/null +++ b/src/NzbDrone.Core/Parser/InvalidSeasonException.cs @@ -0,0 +1,15 @@ +using NzbDrone.Common.Exceptions; + +namespace NzbDrone.Core.Parser +{ + public class InvalidSeasonException : NzbDroneException + { + public InvalidSeasonException(string message, params object[] args) : base(message, args) + { + } + + public InvalidSeasonException(string message) : base(message) + { + } + } +} diff --git a/src/NzbDrone.Core/Parser/Model/LocalEpisode.cs b/src/NzbDrone.Core/Parser/Model/LocalEpisode.cs index 67ec2d873..d59e55958 100644 --- a/src/NzbDrone.Core/Parser/Model/LocalEpisode.cs +++ b/src/NzbDrone.Core/Parser/Model/LocalEpisode.cs @@ -1,5 +1,6 @@ using System.Linq; using System.Collections.Generic; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Qualities; using NzbDrone.Core.Tv; using NzbDrone.Core.MediaFiles.MediaInfo; @@ -26,7 +27,19 @@ namespace NzbDrone.Core.Parser.Model { get { - return Episodes.Select(c => c.SeasonNumber).Distinct().Single(); + var seasons = Episodes.Select(c => c.SeasonNumber).Distinct().ToList(); + + if (seasons.Empty()) + { + throw new InvalidSeasonException("Expected one season, but found none"); + } + + if (seasons.Count > 1) + { + throw new InvalidSeasonException("Expected one season, but found {0} ({1})", seasons.Count, string.Join(", ", seasons)); + } + + return seasons.Single(); } } @@ -37,4 +50,4 @@ namespace NzbDrone.Core.Parser.Model return Path; } } -} \ No newline at end of file +}