diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/HistorySpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/HistorySpecification.cs index a8ce354f7..025fd89e2 100644 --- a/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/HistorySpecification.cs +++ b/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/HistorySpecification.cs @@ -1,4 +1,7 @@ using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Core.Configuration; @@ -51,7 +54,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync _logger.Debug("Checking current status of episode [{0}] in history", episode.Id); var mostRecent = _historyService.MostRecentForEpisode(episode.Id); - if (mostRecent != null && mostRecent.EventType == EpisodeHistoryEventType.Grabbed) + if (mostRecent == null) + { + continue; + } + + if (mostRecent.EventType == EpisodeHistoryEventType.Grabbed) { var recent = mostRecent.Date.After(DateTime.UtcNow.AddHours(-12)); @@ -116,6 +124,41 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync return DownloadSpecDecision.Reject(DownloadRejectionReason.HistoryUpgradesNotAllowed, "{0} grab event in history and Quality Profile '{1}' does not allow upgrades", rejectionSubject, qualityProfile.Name); } } + + if (subject.Episodes.FirstOrDefault(x => x.Id == episode.Id) is { HasFile: true }) + { + EpisodeHistory availableUsableEpisodeHistoryForCustomFormatScore; + + var episodeHistoryEventTypeForHistoryComparison = new List + { + EpisodeHistoryEventType.Grabbed, + EpisodeHistoryEventType.SeriesFolderImported, + }; + + if (episodeHistoryEventTypeForHistoryComparison.Contains(mostRecent.EventType)) + { + availableUsableEpisodeHistoryForCustomFormatScore = mostRecent; + } + else + { + availableUsableEpisodeHistoryForCustomFormatScore = _historyService.MostRecentForEpisodeInEventCollection( + episode.Id, + new ReadOnlyCollection(episodeHistoryEventTypeForHistoryComparison)); + } + + if (availableUsableEpisodeHistoryForCustomFormatScore == null) + { + continue; + } + + var mostRecentCustomFormat = _formatService.ParseCustomFormat(availableUsableEpisodeHistoryForCustomFormatScore, subject.Series); + var mostRecentCustomFormatScore = qualityProfile.CalculateCustomFormatScore(mostRecentCustomFormat); + + if (mostRecentCustomFormatScore > subject.CustomFormatScore) + { + return DownloadSpecDecision.Reject(DownloadRejectionReason.HistoryCustomFormatScore, "Quality Profile '{0}' has a higher Custom Format score than the report: {1}", qualityProfile.Name, subject.CustomFormatScore); + } + } } return DownloadSpecDecision.Accept(); diff --git a/src/NzbDrone.Core/History/HistoryRepository.cs b/src/NzbDrone.Core/History/HistoryRepository.cs index e51ef5eed..4d564187d 100644 --- a/src/NzbDrone.Core/History/HistoryRepository.cs +++ b/src/NzbDrone.Core/History/HistoryRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using NzbDrone.Core.Datastore; using NzbDrone.Core.Messaging.Events; @@ -20,6 +21,7 @@ namespace NzbDrone.Core.History void DeleteForSeries(List seriesIds); List Since(DateTime date, EpisodeHistoryEventType? eventType); PagingSpec GetPaged(PagingSpec pagingSpec, int[] languages, int[] qualities); + EpisodeHistory MostRecentForEpisodeInEventCollection(int id, ReadOnlyCollection episodeHistoryEventTypes); } public class HistoryRepository : BasicRepository, IHistoryRepository @@ -132,6 +134,11 @@ namespace NzbDrone.Core.History return pagingSpec; } + public EpisodeHistory MostRecentForEpisodeInEventCollection(int id, ReadOnlyCollection episodeHistoryEventTypes) + { + return Query(x => x.EpisodeId == id).Where(x => episodeHistoryEventTypes.Contains(x.EventType)).MaxBy(h => h.Date); + } + private SqlBuilder PagedBuilder(int[] languages, int[] qualities) { var builder = Builder() diff --git a/src/NzbDrone.Core/History/HistoryService.cs b/src/NzbDrone.Core/History/HistoryService.cs index 6a8ff6520..e827062f2 100644 --- a/src/NzbDrone.Core/History/HistoryService.cs +++ b/src/NzbDrone.Core/History/HistoryService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; using System.Linq; using NLog; @@ -27,6 +28,7 @@ namespace NzbDrone.Core.History List FindByDownloadId(string downloadId); string FindDownloadId(EpisodeImportedEvent trackedDownload); List Since(DateTime date, EpisodeHistoryEventType? eventType); + EpisodeHistory MostRecentForEpisodeInEventCollection(int id, ReadOnlyCollection episodeHistoryEventTypes); } public class HistoryService : IHistoryService, @@ -365,5 +367,10 @@ namespace NzbDrone.Core.History { return _historyRepository.Since(date, eventType); } + + public EpisodeHistory MostRecentForEpisodeInEventCollection(int id, ReadOnlyCollection episodeHistoryEventTypes) + { + return _historyRepository.MostRecentForEpisodeInEventCollection(id, episodeHistoryEventTypes); + } } }