mirror of
https://github.com/Sonarr/Sonarr.git
synced 2025-01-25 11:13:39 +02:00
New: Ability to skip redownload when marking an item as failed from Activity Queue
This commit is contained in:
parent
38f263931f
commit
d7025a98de
@ -45,14 +45,14 @@ class QueueRow extends Component {
|
|||||||
this.setState({ isRemoveQueueItemModalOpen: true });
|
this.setState({ isRemoveQueueItemModalOpen: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
onRemoveQueueItemModalConfirmed = (blocklist) => {
|
onRemoveQueueItemModalConfirmed = (blocklist, skipRedownload) => {
|
||||||
const {
|
const {
|
||||||
onRemoveQueueItemPress,
|
onRemoveQueueItemPress,
|
||||||
onQueueRowModalOpenOrClose
|
onQueueRowModalOpenOrClose
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
onQueueRowModalOpenOrClose(false);
|
onQueueRowModalOpenOrClose(false);
|
||||||
onRemoveQueueItemPress(blocklist);
|
onRemoveQueueItemPress(blocklist, skipRedownload);
|
||||||
|
|
||||||
this.setState({ isRemoveQueueItemModalOpen: false });
|
this.setState({ isRemoveQueueItemModalOpen: false });
|
||||||
};
|
};
|
||||||
|
@ -10,6 +10,7 @@ import ModalContent from 'Components/Modal/ModalContent';
|
|||||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
|
|
||||||
class RemoveQueueItemModal extends Component {
|
class RemoveQueueItemModal extends Component {
|
||||||
|
|
||||||
@ -21,7 +22,8 @@ class RemoveQueueItemModal extends Component {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
remove: true,
|
remove: true,
|
||||||
blocklist: false
|
blocklist: false,
|
||||||
|
skipRedownload: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +33,8 @@ class RemoveQueueItemModal extends Component {
|
|||||||
resetState = function() {
|
resetState = function() {
|
||||||
this.setState({
|
this.setState({
|
||||||
remove: true,
|
remove: true,
|
||||||
blocklist: false
|
blocklist: false,
|
||||||
|
skipRedownload: false
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -46,6 +49,10 @@ class RemoveQueueItemModal extends Component {
|
|||||||
this.setState({ blocklist: value });
|
this.setState({ blocklist: value });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onSkipRedownloadChange = ({ value }) => {
|
||||||
|
this.setState({ skipRedownload: value });
|
||||||
|
};
|
||||||
|
|
||||||
onRemoveConfirmed = () => {
|
onRemoveConfirmed = () => {
|
||||||
const state = this.state;
|
const state = this.state;
|
||||||
|
|
||||||
@ -69,7 +76,7 @@ class RemoveQueueItemModal extends Component {
|
|||||||
isPending
|
isPending
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { remove, blocklist } = this.state;
|
const { remove, blocklist, skipRedownload } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@ -118,6 +125,20 @@ class RemoveQueueItemModal extends Component {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
{
|
||||||
|
blocklist ?
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('SkipRedownload')}</FormLabel>
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.CHECK}
|
||||||
|
name="skipRedownload"
|
||||||
|
value={skipRedownload}
|
||||||
|
helpText={translate('SkipRedownloadHelpText')}
|
||||||
|
onChange={this.onSkipRedownloadChange}
|
||||||
|
/>
|
||||||
|
</FormGroup> :
|
||||||
|
null
|
||||||
|
}
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
|
@ -23,7 +23,8 @@ class RemoveQueueItemsModal extends Component {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
remove: true,
|
remove: true,
|
||||||
blocklist: false
|
blocklist: false,
|
||||||
|
skipRedownload: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +34,8 @@ class RemoveQueueItemsModal extends Component {
|
|||||||
resetState = function() {
|
resetState = function() {
|
||||||
this.setState({
|
this.setState({
|
||||||
remove: true,
|
remove: true,
|
||||||
blocklist: false
|
blocklist: false,
|
||||||
|
skipRedownload: false
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -48,6 +50,10 @@ class RemoveQueueItemsModal extends Component {
|
|||||||
this.setState({ blocklist: value });
|
this.setState({ blocklist: value });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onSkipRedownloadChange = ({ value }) => {
|
||||||
|
this.setState({ skipRedownload: value });
|
||||||
|
};
|
||||||
|
|
||||||
onRemoveConfirmed = () => {
|
onRemoveConfirmed = () => {
|
||||||
const state = this.state;
|
const state = this.state;
|
||||||
|
|
||||||
@ -71,7 +77,7 @@ class RemoveQueueItemsModal extends Component {
|
|||||||
allPending
|
allPending
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { remove, blocklist } = this.state;
|
const { remove, blocklist, skipRedownload } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@ -122,6 +128,20 @@ class RemoveQueueItemsModal extends Component {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
{
|
||||||
|
blocklist ?
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('SkipRedownload')}</FormLabel>
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.CHECK}
|
||||||
|
name="skipRedownload"
|
||||||
|
value={skipRedownload}
|
||||||
|
helpText={translate('SkipRedownloadHelpText')}
|
||||||
|
onChange={this.onSkipRedownloadChange}
|
||||||
|
/>
|
||||||
|
</FormGroup> :
|
||||||
|
null
|
||||||
|
}
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
|
@ -381,13 +381,14 @@ export const actionHandlers = handleThunks({
|
|||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
remove,
|
remove,
|
||||||
blocklist
|
blocklist,
|
||||||
|
skipRedownload
|
||||||
} = payload;
|
} = payload;
|
||||||
|
|
||||||
dispatch(updateItem({ section: paged, id, isRemoving: true }));
|
dispatch(updateItem({ section: paged, id, isRemoving: true }));
|
||||||
|
|
||||||
const promise = createAjaxRequest({
|
const promise = createAjaxRequest({
|
||||||
url: `/queue/${id}?removeFromClient=${remove}&blocklist=${blocklist}`,
|
url: `/queue/${id}?removeFromClient=${remove}&blocklist=${blocklist}&skipRedownload=${skipRedownload}`,
|
||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
}).request;
|
}).request;
|
||||||
|
|
||||||
@ -404,7 +405,8 @@ export const actionHandlers = handleThunks({
|
|||||||
const {
|
const {
|
||||||
ids,
|
ids,
|
||||||
remove,
|
remove,
|
||||||
blocklist
|
blocklist,
|
||||||
|
skipRedownload
|
||||||
} = payload;
|
} = payload;
|
||||||
|
|
||||||
dispatch(batchActions([
|
dispatch(batchActions([
|
||||||
@ -420,7 +422,7 @@ export const actionHandlers = handleThunks({
|
|||||||
]));
|
]));
|
||||||
|
|
||||||
const promise = createAjaxRequest({
|
const promise = createAjaxRequest({
|
||||||
url: `/queue/bulk?removeFromClient=${remove}&blocklist=${blocklist}`,
|
url: `/queue/bulk?removeFromClient=${remove}&blocklist=${blocklist}&skipRedownload=${skipRedownload}`,
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
|
@ -23,5 +23,6 @@ namespace NzbDrone.Core.Download
|
|||||||
public Dictionary<string, string> Data { get; set; }
|
public Dictionary<string, string> Data { get; set; }
|
||||||
public TrackedDownload TrackedDownload { get; set; }
|
public TrackedDownload TrackedDownload { get; set; }
|
||||||
public List<Language> Languages { get; set; }
|
public List<Language> Languages { get; set; }
|
||||||
|
public bool SkipRedownload { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@ namespace NzbDrone.Core.Download
|
|||||||
{
|
{
|
||||||
public interface IFailedDownloadService
|
public interface IFailedDownloadService
|
||||||
{
|
{
|
||||||
void MarkAsFailed(int historyId);
|
void MarkAsFailed(int historyId, bool skipRedownload = false);
|
||||||
void MarkAsFailed(string downloadId);
|
void MarkAsFailed(string downloadId, bool skipRedownload = false);
|
||||||
void Check(TrackedDownload trackedDownload);
|
void Check(TrackedDownload trackedDownload);
|
||||||
void ProcessFailed(TrackedDownload trackedDownload);
|
void ProcessFailed(TrackedDownload trackedDownload);
|
||||||
}
|
}
|
||||||
@ -30,14 +30,14 @@ namespace NzbDrone.Core.Download
|
|||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MarkAsFailed(int historyId)
|
public void MarkAsFailed(int historyId, bool skipRedownload = false)
|
||||||
{
|
{
|
||||||
var history = _historyService.Get(historyId);
|
var history = _historyService.Get(historyId);
|
||||||
|
|
||||||
var downloadId = history.DownloadId;
|
var downloadId = history.DownloadId;
|
||||||
if (downloadId.IsNullOrWhiteSpace())
|
if (downloadId.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
PublishDownloadFailedEvent(new List<EpisodeHistory> { history }, "Manually marked as failed");
|
PublishDownloadFailedEvent(new List<EpisodeHistory> { history }, "Manually marked as failed", skipRedownload: skipRedownload);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ namespace NzbDrone.Core.Download
|
|||||||
PublishDownloadFailedEvent(grabbedHistory, "Manually marked as failed");
|
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);
|
var history = _historyService.Find(downloadId, EpisodeHistoryEventType.Grabbed);
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ namespace NzbDrone.Core.Download
|
|||||||
{
|
{
|
||||||
var trackedDownload = _trackedDownloadService.Find(downloadId);
|
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);
|
PublishDownloadFailedEvent(grabbedItems, failure, trackedDownload);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PublishDownloadFailedEvent(List<EpisodeHistory> historyItems, string message, TrackedDownload trackedDownload = null)
|
private void PublishDownloadFailedEvent(List<EpisodeHistory> historyItems, string message, TrackedDownload trackedDownload = null, bool skipRedownload = false)
|
||||||
{
|
{
|
||||||
var historyItem = historyItems.First();
|
var historyItem = historyItems.First();
|
||||||
|
|
||||||
@ -140,7 +140,8 @@ namespace NzbDrone.Core.Download
|
|||||||
Message = message,
|
Message = message,
|
||||||
Data = historyItem.Data,
|
Data = historyItem.Data,
|
||||||
TrackedDownload = trackedDownload,
|
TrackedDownload = trackedDownload,
|
||||||
Languages = historyItem.Languages
|
Languages = historyItem.Languages,
|
||||||
|
SkipRedownload = skipRedownload
|
||||||
};
|
};
|
||||||
|
|
||||||
_eventAggregator.PublishEvent(downloadFailedEvent);
|
_eventAggregator.PublishEvent(downloadFailedEvent);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.IndexerSearch;
|
using NzbDrone.Core.IndexerSearch;
|
||||||
@ -30,6 +30,12 @@ namespace NzbDrone.Core.Download
|
|||||||
[EventHandleOrder(EventHandleOrder.Last)]
|
[EventHandleOrder(EventHandleOrder.Last)]
|
||||||
public void Handle(DownloadFailedEvent message)
|
public void Handle(DownloadFailedEvent message)
|
||||||
{
|
{
|
||||||
|
if (message.SkipRedownload)
|
||||||
|
{
|
||||||
|
_logger.Debug("Skip redownloading requested by user");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_configService.AutoRedownloadFailed)
|
if (!_configService.AutoRedownloadFailed)
|
||||||
{
|
{
|
||||||
_logger.Debug("Auto redownloading failed episodes is disabled");
|
_logger.Debug("Auto redownloading failed episodes is disabled");
|
||||||
|
@ -276,6 +276,8 @@
|
|||||||
"ShownClickToHide": "Shown, click to hide",
|
"ShownClickToHide": "Shown, click to hide",
|
||||||
"Size": "Size",
|
"Size": "Size",
|
||||||
"SizeOnDisk": "Size on disk",
|
"SizeOnDisk": "Size on disk",
|
||||||
|
"SkipRedownloadHelpText": "Prevents Sonarr from trying to download an alternative release for this item",
|
||||||
|
"SkipRedownload": "Skip Redownload",
|
||||||
"Source": "Source",
|
"Source": "Source",
|
||||||
"Special": "Special",
|
"Special": "Special",
|
||||||
"Started": "Started",
|
"Started": "Started",
|
||||||
|
@ -70,7 +70,7 @@ namespace Sonarr.Api.V3.Queue
|
|||||||
}
|
}
|
||||||
|
|
||||||
[RestDeleteById]
|
[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);
|
var pendingRelease = _pendingReleaseService.FindPendingQueueItem(id);
|
||||||
|
|
||||||
@ -88,12 +88,12 @@ namespace Sonarr.Api.V3.Queue
|
|||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
Remove(trackedDownload, removeFromClient, blocklist);
|
Remove(trackedDownload, removeFromClient, blocklist, skipRedownload);
|
||||||
_trackedDownloadService.StopTracking(trackedDownload.DownloadItem.DownloadId);
|
_trackedDownloadService.StopTracking(trackedDownload.DownloadItem.DownloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("bulk")]
|
[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<string>();
|
var trackedDownloadIds = new List<string>();
|
||||||
var pendingToRemove = new List<NzbDrone.Core.Queue.Queue>();
|
var pendingToRemove = new List<NzbDrone.Core.Queue.Queue>();
|
||||||
@ -124,7 +124,7 @@ namespace Sonarr.Api.V3.Queue
|
|||||||
|
|
||||||
foreach (var trackedDownload in trackedToRemove.DistinctBy(t => t.DownloadItem.DownloadId))
|
foreach (var trackedDownload in trackedToRemove.DistinctBy(t => t.DownloadItem.DownloadId))
|
||||||
{
|
{
|
||||||
Remove(trackedDownload, removeFromClient, blocklist);
|
Remove(trackedDownload, removeFromClient, blocklist, skipRedownload);
|
||||||
trackedDownloadIds.Add(trackedDownload.DownloadItem.DownloadId);
|
trackedDownloadIds.Add(trackedDownload.DownloadItem.DownloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ namespace Sonarr.Api.V3.Queue
|
|||||||
_pendingReleaseService.RemovePendingQueueItems(pendingRelease.Id);
|
_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)
|
if (removeFromClient)
|
||||||
{
|
{
|
||||||
@ -271,7 +271,7 @@ namespace Sonarr.Api.V3.Queue
|
|||||||
|
|
||||||
if (blocklist)
|
if (blocklist)
|
||||||
{
|
{
|
||||||
_failedDownloadService.MarkAsFailed(trackedDownload.DownloadItem.DownloadId);
|
_failedDownloadService.MarkAsFailed(trackedDownload.DownloadItem.DownloadId, skipRedownload);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!removeFromClient && !blocklist)
|
if (!removeFromClient && !blocklist)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user