From d8ba7f4d6735aa2c9a59f6226c5a56046a1c6a71 Mon Sep 17 00:00:00 2001 From: PearsonFlyer Date: Thu, 13 Jul 2023 14:57:57 -0400 Subject: [PATCH] New: Ability to skip redownload when marking an item as failed from Activity Queue (cherry picked from commit d7025a98deb321397db9a4933cf688b68eafeba9) Closes #8861 --- frontend/src/Activity/Queue/QueueRow.js | 4 +-- .../Activity/Queue/RemoveQueueItemModal.js | 26 ++++++++++++++++--- .../Activity/Queue/RemoveQueueItemsModal.js | 26 ++++++++++++++++--- frontend/src/Store/Actions/queueActions.js | 10 ++++--- .../Download/DownloadFailedEvent.cs | 1 + .../Download/FailedDownloadService.cs | 17 ++++++------ .../RedownloadFailedDownloadService.cs | 6 +++++ src/NzbDrone.Core/Localization/Core/en.json | 2 ++ src/Radarr.Api.V3/Queue/QueueController.cs | 12 ++++----- 9 files changed, 78 insertions(+), 26 deletions(-) diff --git a/frontend/src/Activity/Queue/QueueRow.js b/frontend/src/Activity/Queue/QueueRow.js index ac1d47afe..3f53870e5 100644 --- a/frontend/src/Activity/Queue/QueueRow.js +++ b/frontend/src/Activity/Queue/QueueRow.js @@ -44,14 +44,14 @@ class QueueRow extends Component { this.setState({ isRemoveQueueItemModalOpen: true }); }; - onRemoveQueueItemModalConfirmed = (blocklist) => { + onRemoveQueueItemModalConfirmed = (blocklist, skipRedownload) => { const { onRemoveQueueItemPress, onQueueRowModalOpenOrClose } = this.props; onQueueRowModalOpenOrClose(false); - onRemoveQueueItemPress(blocklist); + onRemoveQueueItemPress(blocklist, skipRedownload); this.setState({ isRemoveQueueItemModalOpen: false }); }; diff --git a/frontend/src/Activity/Queue/RemoveQueueItemModal.js b/frontend/src/Activity/Queue/RemoveQueueItemModal.js index 58d6c1321..1c08096a9 100644 --- a/frontend/src/Activity/Queue/RemoveQueueItemModal.js +++ b/frontend/src/Activity/Queue/RemoveQueueItemModal.js @@ -22,7 +22,8 @@ class RemoveQueueItemModal extends Component { this.state = { remove: true, - blocklist: false + blocklist: false, + skipRedownload: false }; } @@ -32,7 +33,8 @@ class RemoveQueueItemModal extends Component { resetState = function() { this.setState({ remove: true, - blocklist: false + blocklist: false, + skipRedownload: false }); }; @@ -47,6 +49,10 @@ class RemoveQueueItemModal extends Component { this.setState({ blocklist: value }); }; + onSkipRedownloadChange = ({ value }) => { + this.setState({ skipRedownload: value }); + }; + onRemoveConfirmed = () => { const state = this.state; @@ -70,7 +76,7 @@ class RemoveQueueItemModal extends Component { isPending } = this.props; - const { remove, blocklist } = this.state; + const { remove, blocklist, skipRedownload } = this.state; return ( + { + blocklist ? + + {translate('SkipRedownload')} + + : + null + } diff --git a/frontend/src/Activity/Queue/RemoveQueueItemsModal.js b/frontend/src/Activity/Queue/RemoveQueueItemsModal.js index e8e983129..7f521d43d 100644 --- a/frontend/src/Activity/Queue/RemoveQueueItemsModal.js +++ b/frontend/src/Activity/Queue/RemoveQueueItemsModal.js @@ -23,7 +23,8 @@ class RemoveQueueItemsModal extends Component { this.state = { remove: true, - blocklist: false + blocklist: false, + skipRedownload: false }; } @@ -33,7 +34,8 @@ class RemoveQueueItemsModal extends Component { resetState = function() { this.setState({ remove: true, - blocklist: false + blocklist: false, + skipRedownload: false }); }; @@ -48,6 +50,10 @@ class RemoveQueueItemsModal extends Component { this.setState({ blocklist: value }); }; + onSkipRedownloadChange = ({ value }) => { + this.setState({ skipRedownload: value }); + }; + onRemoveConfirmed = () => { const state = this.state; @@ -71,7 +77,7 @@ class RemoveQueueItemsModal extends Component { allPending } = this.props; - const { remove, blocklist } = this.state; + const { remove, blocklist, skipRedownload } = this.state; return ( + { + blocklist ? + + {translate('SkipRedownload')} + + : + null + } diff --git a/frontend/src/Store/Actions/queueActions.js b/frontend/src/Store/Actions/queueActions.js index 9551d0ea8..ccbf9d519 100644 --- a/frontend/src/Store/Actions/queueActions.js +++ b/frontend/src/Store/Actions/queueActions.js @@ -371,13 +371,14 @@ export const actionHandlers = handleThunks({ const { id, remove, - blocklist + blocklist, + skipRedownload } = payload; dispatch(updateItem({ section: paged, id, isRemoving: true })); const promise = createAjaxRequest({ - url: `/queue/${id}?removeFromClient=${remove}&blocklist=${blocklist}`, + url: `/queue/${id}?removeFromClient=${remove}&blocklist=${blocklist}&skipRedownload=${skipRedownload}`, method: 'DELETE' }).request; @@ -394,7 +395,8 @@ export const actionHandlers = handleThunks({ const { ids, remove, - blocklist + blocklist, + skipRedownload } = payload; dispatch(batchActions([ @@ -410,7 +412,7 @@ export const actionHandlers = handleThunks({ ])); const promise = createAjaxRequest({ - url: `/queue/bulk?removeFromClient=${remove}&blocklist=${blocklist}`, + url: `/queue/bulk?removeFromClient=${remove}&blocklist=${blocklist}&skipRedownload=${skipRedownload}`, method: 'DELETE', dataType: 'json', contentType: 'application/json', diff --git a/src/NzbDrone.Core/Download/DownloadFailedEvent.cs b/src/NzbDrone.Core/Download/DownloadFailedEvent.cs index 494d8eb56..019adb08c 100644 --- a/src/NzbDrone.Core/Download/DownloadFailedEvent.cs +++ b/src/NzbDrone.Core/Download/DownloadFailedEvent.cs @@ -22,5 +22,6 @@ namespace NzbDrone.Core.Download public Dictionary Data { get; set; } public TrackedDownload TrackedDownload { get; set; } public List Languages { get; set; } + public bool SkipRedownload { get; set; } } } diff --git a/src/NzbDrone.Core/Download/FailedDownloadService.cs b/src/NzbDrone.Core/Download/FailedDownloadService.cs index ccacf426b..9b2ac04b2 100644 --- a/src/NzbDrone.Core/Download/FailedDownloadService.cs +++ b/src/NzbDrone.Core/Download/FailedDownloadService.cs @@ -9,8 +9,8 @@ namespace NzbDrone.Core.Download { public interface IFailedDownloadService { - void MarkAsFailed(int historyId); - void MarkAsFailed(string downloadId); + void MarkAsFailed(int historyId, bool skipRedownload = false); + void MarkAsFailed(string downloadId, bool skipRedownload = false); void Check(TrackedDownload trackedDownload); void ProcessFailed(TrackedDownload trackedDownload); } @@ -30,14 +30,14 @@ namespace NzbDrone.Core.Download _eventAggregator = eventAggregator; } - public void MarkAsFailed(int historyId) + public void MarkAsFailed(int historyId, bool skipRedownload = false) { var history = _historyService.Get(historyId); var downloadId = history.DownloadId; if (downloadId.IsNullOrWhiteSpace()) { - PublishDownloadFailedEvent(new List { history }, "Manually marked as failed"); + PublishDownloadFailedEvent(new List { history }, "Manually marked as failed", skipRedownload: skipRedownload); return; } @@ -57,7 +57,7 @@ namespace NzbDrone.Core.Download PublishDownloadFailedEvent(grabbedHistory, "Manually marked as failed"); } - public void MarkAsFailed(string downloadId) + public void MarkAsFailed(string downloadId, bool skipRedownload = false) { var history = _historyService.Find(downloadId, MovieHistoryEventType.Grabbed); @@ -65,7 +65,7 @@ namespace NzbDrone.Core.Download { var trackedDownload = _trackedDownloadService.Find(downloadId); - PublishDownloadFailedEvent(history, "Manually marked as failed", trackedDownload); + PublishDownloadFailedEvent(history, "Manually marked as failed", trackedDownload, skipRedownload: skipRedownload); } } @@ -125,7 +125,7 @@ namespace NzbDrone.Core.Download PublishDownloadFailedEvent(grabbedItems, failure, trackedDownload); } - private void PublishDownloadFailedEvent(List historyItems, string message, TrackedDownload trackedDownload = null) + private void PublishDownloadFailedEvent(List historyItems, string message, TrackedDownload trackedDownload = null, bool skipRedownload = false) { var historyItem = historyItems.First(); @@ -139,7 +139,8 @@ namespace NzbDrone.Core.Download Message = message, Data = historyItem.Data, TrackedDownload = trackedDownload, - Languages = historyItem.Languages + Languages = historyItem.Languages, + SkipRedownload = skipRedownload }; _eventAggregator.PublishEvent(downloadFailedEvent); diff --git a/src/NzbDrone.Core/Download/RedownloadFailedDownloadService.cs b/src/NzbDrone.Core/Download/RedownloadFailedDownloadService.cs index a36def4b4..18b7cb2aa 100644 --- a/src/NzbDrone.Core/Download/RedownloadFailedDownloadService.cs +++ b/src/NzbDrone.Core/Download/RedownloadFailedDownloadService.cs @@ -26,6 +26,12 @@ namespace NzbDrone.Core.Download [EventHandleOrder(EventHandleOrder.Last)] public void Handle(DownloadFailedEvent message) { + if (message.SkipRedownload) + { + _logger.Debug("Skip redownloading requested by user"); + return; + } + if (!_configService.AutoRedownloadFailed) { _logger.Debug("Auto redownloading failed movies is disabled"); diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index b1fb3be9e..5c012ee29 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -1031,6 +1031,8 @@ "SizeOnDisk": "Size on Disk", "SkipFreeSpaceCheck": "Skip Free Space Check", "SkipFreeSpaceCheckWhenImportingHelpText": "Use when Radarr is unable to detect free space from your movie root folder", + "SkipRedownload": "Skip Redownload", + "SkipRedownloadHelpText": "Prevents Radarr from trying to download an alternative release for this item", "Small": "Small", "Socks4": "Socks4", "Socks5": "Socks5 (Support TOR)", diff --git a/src/Radarr.Api.V3/Queue/QueueController.cs b/src/Radarr.Api.V3/Queue/QueueController.cs index f69d8cb72..e4c765d81 100644 --- a/src/Radarr.Api.V3/Queue/QueueController.cs +++ b/src/Radarr.Api.V3/Queue/QueueController.cs @@ -65,7 +65,7 @@ namespace Radarr.Api.V3.Queue } [RestDeleteById] - public void RemoveAction(int id, bool removeFromClient = true, bool blocklist = false) + public void RemoveAction(int id, bool removeFromClient = true, bool blocklist = false, bool skipRedownload = false) { var pendingRelease = _pendingReleaseService.FindPendingQueueItem(id); @@ -83,12 +83,12 @@ namespace Radarr.Api.V3.Queue throw new NotFoundException(); } - Remove(trackedDownload, removeFromClient, blocklist); + Remove(trackedDownload, removeFromClient, blocklist, skipRedownload); _trackedDownloadService.StopTracking(trackedDownload.DownloadItem.DownloadId); } [HttpDelete("bulk")] - public object RemoveMany([FromBody] QueueBulkResource resource, [FromQuery] bool removeFromClient = true, [FromQuery] bool blocklist = false) + public object RemoveMany([FromBody] QueueBulkResource resource, [FromQuery] bool removeFromClient = true, [FromQuery] bool blocklist = false, [FromQuery] bool skipRedownload = false) { var trackedDownloadIds = new List(); var pendingToRemove = new List(); @@ -119,7 +119,7 @@ namespace Radarr.Api.V3.Queue foreach (var trackedDownload in trackedToRemove.DistinctBy(t => t.DownloadItem.DownloadId)) { - Remove(trackedDownload, removeFromClient, blocklist); + Remove(trackedDownload, removeFromClient, blocklist, skipRedownload); trackedDownloadIds.Add(trackedDownload.DownloadItem.DownloadId); } @@ -242,7 +242,7 @@ namespace Radarr.Api.V3.Queue _pendingReleaseService.RemovePendingQueueItems(pendingRelease.Id); } - private TrackedDownload Remove(TrackedDownload trackedDownload, bool removeFromClient, bool blocklist) + private TrackedDownload Remove(TrackedDownload trackedDownload, bool removeFromClient, bool blocklist, bool skipRedownload) { if (removeFromClient) { @@ -258,7 +258,7 @@ namespace Radarr.Api.V3.Queue if (blocklist) { - _failedDownloadService.MarkAsFailed(trackedDownload.DownloadItem.DownloadId); + _failedDownloadService.MarkAsFailed(trackedDownload.DownloadItem.DownloadId, skipRedownload); } if (!removeFromClient && !blocklist)