diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index ef0436711..4cdc02123 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -333,6 +333,7 @@ + diff --git a/src/NzbDrone.Core.Test/ParserTests/ValidateParsedEpisodeInfoFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ValidateParsedEpisodeInfoFixture.cs new file mode 100644 index 000000000..656a06b8f --- /dev/null +++ b/src/NzbDrone.Core.Test/ParserTests/ValidateParsedEpisodeInfoFixture.cs @@ -0,0 +1,73 @@ +using FizzWare.NBuilder; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Parser; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; +using NzbDrone.Test.Common; + +namespace NzbDrone.Core.Test.ParserTests +{ + [TestFixture] + public class ValidateParsedEpisodeInfoFixture : CoreTest + { + private ParsedEpisodeInfo _parsedEpisodeInfo; + private Series _series; + + [SetUp] + public void Setup() + { + _parsedEpisodeInfo = Builder.CreateNew() + .With(p => p.AirDate = null) + .Build(); + + _series = Builder.CreateNew() + .With(s => s.SeriesType = SeriesTypes.Standard) + .Build(); + } + + private void GivenDailyParsedEpisodeInfo() + { + _parsedEpisodeInfo.AirDate = "2018-05-21"; + } + + private void GivenDailySeries() + { + _series.SeriesType = SeriesTypes.Daily; + } + + [Test] + public void should_return_true_if_episode_info_is_not_daily() + { + ValidateParsedEpisodeInfo.ValidateForSeriesType(_parsedEpisodeInfo, _series).Should().BeTrue(); + } + + [Test] + public void should_return_true_if_episode_info_is_daily_for_daily_series() + { + GivenDailyParsedEpisodeInfo(); + GivenDailySeries(); + + ValidateParsedEpisodeInfo.ValidateForSeriesType(_parsedEpisodeInfo, _series).Should().BeTrue(); + } + + [Test] + public void should_return_false_if_episode_info_is_daily_for_standard_series() + { + GivenDailyParsedEpisodeInfo(); + + ValidateParsedEpisodeInfo.ValidateForSeriesType(_parsedEpisodeInfo, _series).Should().BeFalse(); + ExceptionVerification.ExpectedWarns(1); + } + + [Test] + public void should_not_log_warning_if_warnIfInvalid_is_false() + { + GivenDailyParsedEpisodeInfo(); + + ValidateParsedEpisodeInfo.ValidateForSeriesType(_parsedEpisodeInfo, _series, false); + ExceptionVerification.ExpectedWarns(0); + } + } +} diff --git a/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs b/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs index 0c83838e2..262e4102b 100644 --- a/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs +++ b/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Marr.Data; @@ -298,7 +298,14 @@ namespace NzbDrone.Core.Download.Pending } else { - episodes = _parsingService.GetEpisodes(release.ParsedEpisodeInfo, series, true); + if (ValidateParsedEpisodeInfo.ValidateForSeriesType(release.ParsedEpisodeInfo, series)) + { + episodes = _parsingService.GetEpisodes(release.ParsedEpisodeInfo, series, true); + } + else + { + episodes = new List(); + } } release.RemoteEpisode = new RemoteEpisode diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateEpisodes.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateEpisodes.cs index 24b8b0e0a..058c6e75b 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateEpisodes.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateEpisodes.cs @@ -1,6 +1,8 @@ +using System.Collections.Generic; using System.IO; using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Tv; namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators { @@ -15,9 +17,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators public LocalEpisode Aggregate(LocalEpisode localEpisode, bool otherFiles) { - var bestEpisodeInfoForEpisodes = GetBestEpisodeInfo(localEpisode, otherFiles); - - localEpisode.Episodes = _parsingService.GetEpisodes(bestEpisodeInfoForEpisodes, localEpisode.Series, localEpisode.SceneSource); + localEpisode.Episodes = GetEpisodes(localEpisode, otherFiles); return localEpisode; } @@ -50,5 +50,18 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators return parsedEpisodeInfo; } + + private List GetEpisodes(LocalEpisode localEpisode, bool otherFiles) + { + var bestEpisodeInfoForEpisodes = GetBestEpisodeInfo(localEpisode, otherFiles); + var isMediaFile = MediaFileExtensions.Extensions.Contains(Path.GetExtension(localEpisode.Path)); + + if (ValidateParsedEpisodeInfo.ValidateForSeriesType(bestEpisodeInfoForEpisodes, localEpisode.Series, isMediaFile)) + { + return _parsingService.GetEpisodes(bestEpisodeInfoForEpisodes, localEpisode.Series, localEpisode.SceneSource); + } + + return new List(); + } } } diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 789aa01ca..555710344 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -963,6 +963,7 @@ + diff --git a/src/NzbDrone.Core/Parser/ParsingService.cs b/src/NzbDrone.Core/Parser/ParsingService.cs index 66cf00e7c..33f730cd3 100644 --- a/src/NzbDrone.Core/Parser/ParsingService.cs +++ b/src/NzbDrone.Core/Parser/ParsingService.cs @@ -79,7 +79,11 @@ namespace NzbDrone.Core.Parser } remoteEpisode.Series = series; - remoteEpisode.Episodes = GetEpisodes(parsedEpisodeInfo, series, true, searchCriteria); + + if (ValidateParsedEpisodeInfo.ValidateForSeriesType(parsedEpisodeInfo, series)) + { + remoteEpisode.Episodes = GetEpisodes(parsedEpisodeInfo, series, true, searchCriteria); + } return remoteEpisode; } @@ -103,12 +107,6 @@ namespace NzbDrone.Core.Parser if (parsedEpisodeInfo.IsDaily) { - if (series.SeriesType == SeriesTypes.Standard) - { - _logger.Warn("Found daily-style episode for non-daily series: {0}.", series); - return new List(); - } - var episodeInfo = GetDailyEpisode(series, parsedEpisodeInfo.AirDate, searchCriteria); if (episodeInfo != null) diff --git a/src/NzbDrone.Core/Parser/ValidateParsedEpisodeInfo.cs b/src/NzbDrone.Core/Parser/ValidateParsedEpisodeInfo.cs new file mode 100644 index 000000000..3f3120678 --- /dev/null +++ b/src/NzbDrone.Core/Parser/ValidateParsedEpisodeInfo.cs @@ -0,0 +1,33 @@ +using NLog; +using NzbDrone.Common.Instrumentation; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Parser +{ + public static class ValidateParsedEpisodeInfo + { + private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(ValidateParsedEpisodeInfo)); + + public static bool ValidateForSeriesType(ParsedEpisodeInfo parsedEpisodeInfo, Series series, bool warnIfInvalid = true) + { + if (parsedEpisodeInfo.IsDaily && series.SeriesType == SeriesTypes.Standard) + { + var message = $"Found daily-style episode for non-daily series: {series}"; + + if (warnIfInvalid) + { + Logger.Warn(message); + } + else + { + Logger.Debug(message); + } + + return false; + } + + return true; + } + } +}