From e2745c5956e6f443b7483d066aa4266af1c41384 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 1 Aug 2021 14:36:16 -0700 Subject: [PATCH] Fixed: Blocklisting pending releases --- frontend/src/Activity/Queue/Queue.js | 11 +++++ frontend/src/Activity/Queue/QueueRow.js | 1 + .../Activity/Queue/RemoveQueueItemModal.js | 34 ++++++++------- .../Activity/Queue/RemoveQueueItemsModal.js | 34 ++++++++------- .../Blocklisting/BlocklistService.cs | 25 +++++++++++ .../Download/Pending/PendingReleaseService.cs | 42 +++++++++---------- src/Readarr.Api.V1/Queue/QueueController.cs | 7 +++- 7 files changed, 104 insertions(+), 50 deletions(-) diff --git a/frontend/src/Activity/Queue/Queue.js b/frontend/src/Activity/Queue/Queue.js index ba03f002c..23abcb914 100644 --- a/frontend/src/Activity/Queue/Queue.js +++ b/frontend/src/Activity/Queue/Queue.js @@ -284,6 +284,17 @@ class Queue extends Component { return !!(item && item.authorId && item.bookId); }) )} + allPending={isConfirmRemoveModalOpen && ( + selectedIds.every((id) => { + const item = items.find((i) => i.id === id); + + if (!item) { + return false; + } + + return item.status === 'delay' || item.status === 'downloadClientUnavailable'; + }) + )} onRemovePress={this.onRemoveSelectedConfirmed} onModalClose={this.onConfirmRemoveModalClose} /> diff --git a/frontend/src/Activity/Queue/QueueRow.js b/frontend/src/Activity/Queue/QueueRow.js index d6dc0b075..e42ca594b 100644 --- a/frontend/src/Activity/Queue/QueueRow.js +++ b/frontend/src/Activity/Queue/QueueRow.js @@ -357,6 +357,7 @@ class QueueRow extends Component { isOpen={isRemoveQueueItemModalOpen} sourceTitle={title} canIgnore={!!author} + isPending={isPending} onRemovePress={this.onRemoveQueueItemModalConfirmed} onModalClose={this.onRemoveQueueItemModalClose} /> diff --git a/frontend/src/Activity/Queue/RemoveQueueItemModal.js b/frontend/src/Activity/Queue/RemoveQueueItemModal.js index a69e4dbde..352951e86 100644 --- a/frontend/src/Activity/Queue/RemoveQueueItemModal.js +++ b/frontend/src/Activity/Queue/RemoveQueueItemModal.js @@ -72,7 +72,8 @@ class RemoveQueueItemModal extends Component { const { isOpen, sourceTitle, - canIgnore + canIgnore, + isPending } = this.props; const { remove, blocklist, skipredownload } = this.state; @@ -95,20 +96,24 @@ class RemoveQueueItemModal extends Component { Are you sure you want to remove '{sourceTitle}' from the queue? - - - {translate('RemoveFromDownloadClient')} - + { + isPending ? + null : + + + {translate('RemoveFromDownloadClient')} + - - + + + } @@ -164,6 +169,7 @@ RemoveQueueItemModal.propTypes = { isOpen: PropTypes.bool.isRequired, sourceTitle: PropTypes.string.isRequired, canIgnore: PropTypes.bool.isRequired, + isPending: PropTypes.bool.isRequired, onRemovePress: PropTypes.func.isRequired, onModalClose: PropTypes.func.isRequired }; diff --git a/frontend/src/Activity/Queue/RemoveQueueItemsModal.js b/frontend/src/Activity/Queue/RemoveQueueItemsModal.js index 3825a7ac7..13bbe1c15 100644 --- a/frontend/src/Activity/Queue/RemoveQueueItemsModal.js +++ b/frontend/src/Activity/Queue/RemoveQueueItemsModal.js @@ -73,7 +73,8 @@ class RemoveQueueItemsModal extends Component { const { isOpen, selectedCount, - canIgnore + canIgnore, + allPending } = this.props; const { remove, blocklist, skipredownload } = this.state; @@ -96,20 +97,24 @@ class RemoveQueueItemsModal extends Component { Are you sure you want to remove {selectedCount} item{selectedCount > 1 ? 's' : ''} from the queue? - - - {translate('RemoveFromDownloadClient')} - + { + allPending ? + null : + + + {translate('RemoveFromDownloadClient')} + - - + + + } @@ -165,6 +170,7 @@ RemoveQueueItemsModal.propTypes = { isOpen: PropTypes.bool.isRequired, selectedCount: PropTypes.number.isRequired, canIgnore: PropTypes.bool.isRequired, + allPending: PropTypes.bool.isRequired, onRemovePress: PropTypes.func.isRequired, onModalClose: PropTypes.func.isRequired }; diff --git a/src/NzbDrone.Core/Blocklisting/BlocklistService.cs b/src/NzbDrone.Core/Blocklisting/BlocklistService.cs index 49f39af3b..c61996af8 100644 --- a/src/NzbDrone.Core/Blocklisting/BlocklistService.cs +++ b/src/NzbDrone.Core/Blocklisting/BlocklistService.cs @@ -16,6 +16,7 @@ namespace NzbDrone.Core.Blocklisting { bool Blocklisted(int authorId, ReleaseInfo release); PagingSpec Paged(PagingSpec pagingSpec); + void Block(RemoteBook remoteEpisode, string message); void Delete(int id); void Delete(List ids); } @@ -66,6 +67,30 @@ namespace NzbDrone.Core.Blocklisting return _blocklistRepository.GetPaged(pagingSpec); } + public void Block(RemoteBook remoteEpisode, string message) + { + var blocklist = new Blocklist + { + AuthorId = remoteEpisode.Author.Id, + BookIds = remoteEpisode.Books.Select(e => e.Id).ToList(), + SourceTitle = remoteEpisode.Release.Title, + Quality = remoteEpisode.ParsedBookInfo.Quality, + Date = DateTime.UtcNow, + PublishedDate = remoteEpisode.Release.PublishDate, + Size = remoteEpisode.Release.Size, + Indexer = remoteEpisode.Release.Indexer, + Protocol = remoteEpisode.Release.DownloadProtocol, + Message = message + }; + + if (remoteEpisode.Release is TorrentInfo torrentRelease) + { + blocklist.TorrentInfoHash = torrentRelease.InfoHash; + } + + _blocklistRepository.Insert(blocklist); + } + public void Delete(int id) { _blocklistRepository.Delete(id); diff --git a/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs b/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs index c2c2f7619..fd35cf7ea 100644 --- a/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs +++ b/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs @@ -129,13 +129,6 @@ namespace NzbDrone.Core.Download.Pending } } - private ILookup CreateBookLookup(IEnumerable alreadyPending) - { - return alreadyPending.SelectMany(v => v.RemoteBook.Books - .Select(d => new { Book = d, PendingRelease = v })) - .ToLookup(v => v.Book.Id, v => v.PendingRelease); - } - public List GetPending() { var releases = _repository.All().Select(p => p.Release).ToList(); @@ -148,13 +141,6 @@ namespace NzbDrone.Core.Download.Pending return releases; } - private List FilterBlockedIndexers(List releases) - { - var blockedIndexers = new HashSet(_indexerStatusService.GetBlockedProviders().Select(v => v.ProviderId)); - - return releases.Where(release => !blockedIndexers.Contains(release.IndexerId)).ToList(); - } - public List GetPendingRemoteBooks(int authorId) { return IncludeRemoteBooks(_repository.AllByAuthorId(authorId)).Select(v => v.RemoteBook).ToList(); @@ -249,6 +235,20 @@ namespace NzbDrone.Core.Download.Pending .FirstOrDefault(); } + private ILookup CreateBookLookup(IEnumerable alreadyPending) + { + return alreadyPending.SelectMany(v => v.RemoteBook.Books + .Select(d => new { Book = d, PendingRelease = v })) + .ToLookup(v => v.Book.Id, v => v.PendingRelease); + } + + private List FilterBlockedIndexers(List releases) + { + var blockedIndexers = new HashSet(_indexerStatusService.GetBlockedProviders().Select(v => v.ProviderId)); + + return releases.Where(release => !blockedIndexers.Contains(release.IndexerId)).ToList(); + } + private List GetPendingReleases() { return IncludeRemoteBooks(_repository.All().ToList()); @@ -338,13 +338,6 @@ namespace NzbDrone.Core.Download.Pending _eventAggregator.PublishEvent(new PendingReleasesUpdatedEvent()); } - private static Func MatchingReleasePredicate(ReleaseInfo release) - { - return p => p.Title == release.Title && - p.Release.PublishDate == release.PublishDate && - p.Release.Indexer == release.Indexer; - } - private int GetDelay(RemoteBook remoteBook) { var delayProfile = _delayProfileService.AllForTags(remoteBook.Author.Tags).OrderBy(d => d.Order).First(); @@ -439,5 +432,12 @@ namespace NzbDrone.Core.Download.Pending { RemoveRejected(message.ProcessedDecisions.Rejected); } + + private static Func MatchingReleasePredicate(ReleaseInfo release) + { + return p => p.Title == release.Title && + p.Release.PublishDate == release.PublishDate && + p.Release.Indexer == release.Indexer; + } } } diff --git a/src/Readarr.Api.V1/Queue/QueueController.cs b/src/Readarr.Api.V1/Queue/QueueController.cs index 87e7d750a..2e8c29f55 100644 --- a/src/Readarr.Api.V1/Queue/QueueController.cs +++ b/src/Readarr.Api.V1/Queue/QueueController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore.Events; using NzbDrone.Core.Download; @@ -32,6 +33,7 @@ namespace Readarr.Api.V1.Queue private readonly IFailedDownloadService _failedDownloadService; private readonly IIgnoredDownloadService _ignoredDownloadService; private readonly IProvideDownloadClient _downloadClientProvider; + private readonly IBlocklistService _blocklistService; public QueueController(IBroadcastSignalRMessage broadcastSignalRMessage, IQueueService queueService, @@ -40,7 +42,8 @@ namespace Readarr.Api.V1.Queue ITrackedDownloadService trackedDownloadService, IFailedDownloadService failedDownloadService, IIgnoredDownloadService ignoredDownloadService, - IProvideDownloadClient downloadClientProvider) + IProvideDownloadClient downloadClientProvider, + IBlocklistService blocklistService) : base(broadcastSignalRMessage) { _queueService = queueService; @@ -49,6 +52,7 @@ namespace Readarr.Api.V1.Queue _failedDownloadService = failedDownloadService; _ignoredDownloadService = ignoredDownloadService; _downloadClientProvider = downloadClientProvider; + _blocklistService = blocklistService; _qualityComparer = new QualityModelComparer(qualityProfileService.GetDefaultProfile(string.Empty)); } @@ -199,6 +203,7 @@ namespace Readarr.Api.V1.Queue if (pendingRelease != null) { + _blocklistService.Block(pendingRelease.RemoteBook, "Pending book manually blocklisted"); _pendingReleaseService.RemovePendingQueueItems(pendingRelease.Id); return null;