diff --git a/frontend/src/Activity/Queue/QueueRow.js b/frontend/src/Activity/Queue/QueueRow.js
index 708f960bb..0f66fbfa4 100644
--- a/frontend/src/Activity/Queue/QueueRow.js
+++ b/frontend/src/Activity/Queue/QueueRow.js
@@ -45,14 +45,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 f1a152734..8260d4362 100644
--- a/frontend/src/Activity/Queue/RemoveQueueItemModal.js
+++ b/frontend/src/Activity/Queue/RemoveQueueItemModal.js
@@ -10,6 +10,7 @@ import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds, sizes } from 'Helpers/Props';
+import translate from 'Utilities/String/translate';
class RemoveQueueItemModal extends Component {
@@ -21,7 +22,8 @@ class RemoveQueueItemModal extends Component {
this.state = {
remove: true,
- blocklist: false
+ blocklist: false,
+ skipRedownload: false
};
}
@@ -31,7 +33,8 @@ class RemoveQueueItemModal extends Component {
resetState = function() {
this.setState({
remove: true,
- blocklist: false
+ blocklist: false,
+ skipRedownload: false
});
};
@@ -46,6 +49,10 @@ class RemoveQueueItemModal extends Component {
this.setState({ blocklist: value });
};
+ onSkipRedownloadChange = ({ value }) => {
+ this.setState({ skipRedownload: value });
+ };
+
onRemoveConfirmed = () => {
const state = this.state;
@@ -69,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 738559ed5..9ee6fef87 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 ef0466466..e4fbb3d90 100644
--- a/frontend/src/Store/Actions/queueActions.js
+++ b/frontend/src/Store/Actions/queueActions.js
@@ -381,13 +381,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;
@@ -404,7 +405,8 @@ export const actionHandlers = handleThunks({
const {
ids,
remove,
- blocklist
+ blocklist,
+ skipRedownload
} = payload;
dispatch(batchActions([
@@ -420,7 +422,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 143eba14e..757e5da97 100644
--- a/src/NzbDrone.Core/Download/DownloadFailedEvent.cs
+++ b/src/NzbDrone.Core/Download/DownloadFailedEvent.cs
@@ -23,5 +23,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 f26741ca8..8e07b23fd 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, EpisodeHistoryEventType.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();
@@ -140,7 +140,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 ed23f021b..20c19e15d 100644
--- a/src/NzbDrone.Core/Download/RedownloadFailedDownloadService.cs
+++ b/src/NzbDrone.Core/Download/RedownloadFailedDownloadService.cs
@@ -1,4 +1,4 @@
-using System.Linq;
+using System.Linq;
using NLog;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch;
@@ -30,6 +30,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 episodes is disabled");
diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json
index 31d7cfe44..b5320ab95 100644
--- a/src/NzbDrone.Core/Localization/Core/en.json
+++ b/src/NzbDrone.Core/Localization/Core/en.json
@@ -276,6 +276,8 @@
"ShownClickToHide": "Shown, click to hide",
"Size": "Size",
"SizeOnDisk": "Size on disk",
+ "SkipRedownloadHelpText": "Prevents Sonarr from trying to download an alternative release for this item",
+ "SkipRedownload": "Skip Redownload",
"Source": "Source",
"Special": "Special",
"Started": "Started",
diff --git a/src/Sonarr.Api.V3/Queue/QueueController.cs b/src/Sonarr.Api.V3/Queue/QueueController.cs
index 605bc9db9..6259956c3 100644
--- a/src/Sonarr.Api.V3/Queue/QueueController.cs
+++ b/src/Sonarr.Api.V3/Queue/QueueController.cs
@@ -70,7 +70,7 @@ namespace Sonarr.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);
@@ -88,12 +88,12 @@ namespace Sonarr.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();
@@ -124,7 +124,7 @@ namespace Sonarr.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);
}
@@ -255,7 +255,7 @@ namespace Sonarr.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)
{
@@ -271,7 +271,7 @@ namespace Sonarr.Api.V3.Queue
if (blocklist)
{
- _failedDownloadService.MarkAsFailed(trackedDownload.DownloadItem.DownloadId);
+ _failedDownloadService.MarkAsFailed(trackedDownload.DownloadItem.DownloadId, skipRedownload);
}
if (!removeFromClient && !blocklist)