parent
ead1371846
commit
3f60e28c42
|
@ -279,6 +279,17 @@ class Queue extends Component {
|
||||||
return !!(item && item.seriesId && item.episodeId);
|
return !!(item && item.seriesId && item.episodeId);
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
|
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}
|
onRemovePress={this.onRemoveSelectedConfirmed}
|
||||||
onModalClose={this.onConfirmRemoveModalClose}
|
onModalClose={this.onConfirmRemoveModalClose}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -377,6 +377,7 @@ class QueueRow extends Component {
|
||||||
isOpen={isRemoveQueueItemModalOpen}
|
isOpen={isRemoveQueueItemModalOpen}
|
||||||
sourceTitle={title}
|
sourceTitle={title}
|
||||||
canIgnore={!!series}
|
canIgnore={!!series}
|
||||||
|
isPending={isPending}
|
||||||
onRemovePress={this.onRemoveQueueItemModalConfirmed}
|
onRemovePress={this.onRemoveQueueItemModalConfirmed}
|
||||||
onModalClose={this.onRemoveQueueItemModalClose}
|
onModalClose={this.onRemoveQueueItemModalClose}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -65,7 +65,8 @@ class RemoveQueueItemModal extends Component {
|
||||||
const {
|
const {
|
||||||
isOpen,
|
isOpen,
|
||||||
sourceTitle,
|
sourceTitle,
|
||||||
canIgnore
|
canIgnore,
|
||||||
|
isPending
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { remove, blocklist } = this.state;
|
const { remove, blocklist } = this.state;
|
||||||
|
@ -88,18 +89,22 @@ class RemoveQueueItemModal extends Component {
|
||||||
Are you sure you want to remove '{sourceTitle}' from the queue?
|
Are you sure you want to remove '{sourceTitle}' from the queue?
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FormGroup>
|
{
|
||||||
<FormLabel>Remove From Download Client</FormLabel>
|
isPending ?
|
||||||
|
null :
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>Remove From Download Client</FormLabel>
|
||||||
|
|
||||||
<FormInputGroup
|
<FormInputGroup
|
||||||
type={inputTypes.CHECK}
|
type={inputTypes.CHECK}
|
||||||
name="remove"
|
name="remove"
|
||||||
value={remove}
|
value={remove}
|
||||||
helpTextWarning="Removing will remove the download and the file(s) from the download client."
|
helpTextWarning="Removing will remove the download and the file(s) from the download client."
|
||||||
isDisabled={!canIgnore}
|
isDisabled={!canIgnore}
|
||||||
onChange={this.onRemoveChange}
|
onChange={this.onRemoveChange}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
}
|
||||||
|
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormLabel>Add Release To Blocklist</FormLabel>
|
<FormLabel>Add Release To Blocklist</FormLabel>
|
||||||
|
@ -137,6 +142,7 @@ RemoveQueueItemModal.propTypes = {
|
||||||
isOpen: PropTypes.bool.isRequired,
|
isOpen: PropTypes.bool.isRequired,
|
||||||
sourceTitle: PropTypes.string.isRequired,
|
sourceTitle: PropTypes.string.isRequired,
|
||||||
canIgnore: PropTypes.bool.isRequired,
|
canIgnore: PropTypes.bool.isRequired,
|
||||||
|
isPending: PropTypes.bool.isRequired,
|
||||||
onRemovePress: PropTypes.func.isRequired,
|
onRemovePress: PropTypes.func.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,7 +66,8 @@ class RemoveQueueItemsModal extends Component {
|
||||||
const {
|
const {
|
||||||
isOpen,
|
isOpen,
|
||||||
selectedCount,
|
selectedCount,
|
||||||
canIgnore
|
canIgnore,
|
||||||
|
allPending
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { remove, blocklist } = this.state;
|
const { remove, blocklist } = this.state;
|
||||||
|
@ -89,18 +90,22 @@ class RemoveQueueItemsModal extends Component {
|
||||||
Are you sure you want to remove {selectedCount} item{selectedCount > 1 ? 's' : ''} from the queue?
|
Are you sure you want to remove {selectedCount} item{selectedCount > 1 ? 's' : ''} from the queue?
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FormGroup>
|
{
|
||||||
<FormLabel>Remove From Download Client</FormLabel>
|
allPending ?
|
||||||
|
null :
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>Remove From Download Client</FormLabel>
|
||||||
|
|
||||||
<FormInputGroup
|
<FormInputGroup
|
||||||
type={inputTypes.CHECK}
|
type={inputTypes.CHECK}
|
||||||
name="remove"
|
name="remove"
|
||||||
value={remove}
|
value={remove}
|
||||||
helpTextWarning="Removing will remove the download and the file(s) from the download client."
|
helpTextWarning="Removing will remove the download and the file(s) from the download client."
|
||||||
isDisabled={!canIgnore}
|
isDisabled={!canIgnore}
|
||||||
onChange={this.onRemoveChange}
|
onChange={this.onRemoveChange}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
}
|
||||||
|
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
|
@ -140,6 +145,7 @@ RemoveQueueItemsModal.propTypes = {
|
||||||
isOpen: PropTypes.bool.isRequired,
|
isOpen: PropTypes.bool.isRequired,
|
||||||
selectedCount: PropTypes.number.isRequired,
|
selectedCount: PropTypes.number.isRequired,
|
||||||
canIgnore: PropTypes.bool.isRequired,
|
canIgnore: PropTypes.bool.isRequired,
|
||||||
|
allPending: PropTypes.bool.isRequired,
|
||||||
onRemovePress: PropTypes.func.isRequired,
|
onRemovePress: PropTypes.func.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.Blocklisting
|
||||||
{
|
{
|
||||||
bool Blocklisted(int seriesId, ReleaseInfo release);
|
bool Blocklisted(int seriesId, ReleaseInfo release);
|
||||||
PagingSpec<Blocklist> Paged(PagingSpec<Blocklist> pagingSpec);
|
PagingSpec<Blocklist> Paged(PagingSpec<Blocklist> pagingSpec);
|
||||||
|
void Block(RemoteEpisode remoteEpisode, string message);
|
||||||
void Delete(int id);
|
void Delete(int id);
|
||||||
void Delete(List<int> ids);
|
void Delete(List<int> ids);
|
||||||
}
|
}
|
||||||
|
@ -61,6 +62,32 @@ namespace NzbDrone.Core.Blocklisting
|
||||||
return _blocklistRepository.GetPaged(pagingSpec);
|
return _blocklistRepository.GetPaged(pagingSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Block(RemoteEpisode remoteEpisode, string message)
|
||||||
|
{
|
||||||
|
var blocklist = new Blocklist
|
||||||
|
{
|
||||||
|
SeriesId = remoteEpisode.Series.Id,
|
||||||
|
EpisodeIds = remoteEpisode.Episodes.Select(e => e.Id).ToList(),
|
||||||
|
SourceTitle = remoteEpisode.Release.Title,
|
||||||
|
Quality = remoteEpisode.ParsedEpisodeInfo.Quality,
|
||||||
|
Date = DateTime.UtcNow,
|
||||||
|
PublishedDate = remoteEpisode.Release.PublishDate,
|
||||||
|
Size = remoteEpisode.Release.Size,
|
||||||
|
Indexer = remoteEpisode.Release.Indexer,
|
||||||
|
Protocol = remoteEpisode.Release.DownloadProtocol,
|
||||||
|
Message = message,
|
||||||
|
Language = remoteEpisode.ParsedEpisodeInfo.Language
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (remoteEpisode.Release is TorrentInfo torrentRelease)
|
||||||
|
{
|
||||||
|
blocklist.TorrentInfoHash = torrentRelease.InfoHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
_blocklistRepository.Insert(blocklist);
|
||||||
|
}
|
||||||
|
|
||||||
public void Delete(int id)
|
public void Delete(int id)
|
||||||
{
|
{
|
||||||
_blocklistRepository.Delete(id);
|
_blocklistRepository.Delete(id);
|
||||||
|
|
|
@ -130,13 +130,6 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ILookup<int, PendingRelease> CreateEpisodeLookup(IEnumerable<PendingRelease> alreadyPending)
|
|
||||||
{
|
|
||||||
return alreadyPending.SelectMany(v => v.RemoteEpisode.Episodes
|
|
||||||
.Select(d => new { Episode = d, PendingRelease = v }))
|
|
||||||
.ToLookup(v => v.Episode.Id, v => v.PendingRelease);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ReleaseInfo> GetPending()
|
public List<ReleaseInfo> GetPending()
|
||||||
{
|
{
|
||||||
var releases = _repository.All().Select(p => p.Release).ToList();
|
var releases = _repository.All().Select(p => p.Release).ToList();
|
||||||
|
@ -149,13 +142,6 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
return releases;
|
return releases;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ReleaseInfo> FilterBlockedIndexers(List<ReleaseInfo> releases)
|
|
||||||
{
|
|
||||||
var blockedIndexers = new HashSet<int>(_indexerStatusService.GetBlockedProviders().Select(v => v.ProviderId));
|
|
||||||
|
|
||||||
return releases.Where(release => !blockedIndexers.Contains(release.IndexerId)).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<RemoteEpisode> GetPendingRemoteEpisodes(int seriesId)
|
public List<RemoteEpisode> GetPendingRemoteEpisodes(int seriesId)
|
||||||
{
|
{
|
||||||
return IncludeRemoteEpisodes(_repository.AllBySeriesId(seriesId)).Select(v => v.RemoteEpisode).ToList();
|
return IncludeRemoteEpisodes(_repository.AllBySeriesId(seriesId)).Select(v => v.RemoteEpisode).ToList();
|
||||||
|
@ -252,6 +238,20 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ILookup<int, PendingRelease> CreateEpisodeLookup(IEnumerable<PendingRelease> alreadyPending)
|
||||||
|
{
|
||||||
|
return alreadyPending.SelectMany(v => v.RemoteEpisode.Episodes
|
||||||
|
.Select(d => new { Episode = d, PendingRelease = v }))
|
||||||
|
.ToLookup(v => v.Episode.Id, v => v.PendingRelease);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ReleaseInfo> FilterBlockedIndexers(List<ReleaseInfo> releases)
|
||||||
|
{
|
||||||
|
var blockedIndexers = new HashSet<int>(_indexerStatusService.GetBlockedProviders().Select(v => v.ProviderId));
|
||||||
|
|
||||||
|
return releases.Where(release => !blockedIndexers.Contains(release.IndexerId)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
private List<PendingRelease> GetPendingReleases()
|
private List<PendingRelease> GetPendingReleases()
|
||||||
{
|
{
|
||||||
return IncludeRemoteEpisodes(_repository.All().ToList());
|
return IncludeRemoteEpisodes(_repository.All().ToList());
|
||||||
|
@ -345,13 +345,6 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
_eventAggregator.PublishEvent(new PendingReleasesUpdatedEvent());
|
_eventAggregator.PublishEvent(new PendingReleasesUpdatedEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Func<PendingRelease, bool> MatchingReleasePredicate(ReleaseInfo release)
|
|
||||||
{
|
|
||||||
return p => p.Title == release.Title &&
|
|
||||||
p.Release.PublishDate == release.PublishDate &&
|
|
||||||
p.Release.Indexer == release.Indexer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetDelay(RemoteEpisode remoteEpisode)
|
private int GetDelay(RemoteEpisode remoteEpisode)
|
||||||
{
|
{
|
||||||
var delayProfile = _delayProfileService.AllForTags(remoteEpisode.Series.Tags).OrderBy(d => d.Order).First();
|
var delayProfile = _delayProfileService.AllForTags(remoteEpisode.Series.Tags).OrderBy(d => d.Order).First();
|
||||||
|
@ -446,5 +439,12 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
{
|
{
|
||||||
RemoveRejected(message.ProcessedDecisions.Rejected);
|
RemoveRejected(message.ProcessedDecisions.Rejected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Func<PendingRelease, bool> MatchingReleasePredicate(ReleaseInfo release)
|
||||||
|
{
|
||||||
|
return p => p.Title == release.Title &&
|
||||||
|
p.Release.PublishDate == release.PublishDate &&
|
||||||
|
p.Release.Indexer == release.Indexer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
|
using NzbDrone.Core.Blocklisting;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Download.Pending;
|
using NzbDrone.Core.Download.Pending;
|
||||||
using NzbDrone.Core.Download.TrackedDownloads;
|
using NzbDrone.Core.Download.TrackedDownloads;
|
||||||
|
@ -21,6 +22,7 @@ namespace Sonarr.Api.V3.Queue
|
||||||
private readonly IProvideDownloadClient _downloadClientProvider;
|
private readonly IProvideDownloadClient _downloadClientProvider;
|
||||||
private readonly IPendingReleaseService _pendingReleaseService;
|
private readonly IPendingReleaseService _pendingReleaseService;
|
||||||
private readonly IDownloadService _downloadService;
|
private readonly IDownloadService _downloadService;
|
||||||
|
private readonly IBlocklistService _blocklistService;
|
||||||
|
|
||||||
public QueueActionModule(IQueueService queueService,
|
public QueueActionModule(IQueueService queueService,
|
||||||
ITrackedDownloadService trackedDownloadService,
|
ITrackedDownloadService trackedDownloadService,
|
||||||
|
@ -28,7 +30,8 @@ namespace Sonarr.Api.V3.Queue
|
||||||
IIgnoredDownloadService ignoredDownloadService,
|
IIgnoredDownloadService ignoredDownloadService,
|
||||||
IProvideDownloadClient downloadClientProvider,
|
IProvideDownloadClient downloadClientProvider,
|
||||||
IPendingReleaseService pendingReleaseService,
|
IPendingReleaseService pendingReleaseService,
|
||||||
IDownloadService downloadService)
|
IDownloadService downloadService,
|
||||||
|
IBlocklistService blocklistService)
|
||||||
{
|
{
|
||||||
_queueService = queueService;
|
_queueService = queueService;
|
||||||
_trackedDownloadService = trackedDownloadService;
|
_trackedDownloadService = trackedDownloadService;
|
||||||
|
@ -37,6 +40,7 @@ namespace Sonarr.Api.V3.Queue
|
||||||
_downloadClientProvider = downloadClientProvider;
|
_downloadClientProvider = downloadClientProvider;
|
||||||
_pendingReleaseService = pendingReleaseService;
|
_pendingReleaseService = pendingReleaseService;
|
||||||
_downloadService = downloadService;
|
_downloadService = downloadService;
|
||||||
|
_blocklistService = blocklistService;
|
||||||
|
|
||||||
Post(@"/grab/(?<id>[\d]{1,10})", x => Grab((int)x.Id));
|
Post(@"/grab/(?<id>[\d]{1,10})", x => Grab((int)x.Id));
|
||||||
Post("/grab/bulk", x => Grab());
|
Post("/grab/bulk", x => Grab());
|
||||||
|
@ -126,6 +130,7 @@ namespace Sonarr.Api.V3.Queue
|
||||||
|
|
||||||
if (pendingRelease != null)
|
if (pendingRelease != null)
|
||||||
{
|
{
|
||||||
|
_blocklistService.Block(pendingRelease.RemoteEpisode, "Pending release manually blocklisted");
|
||||||
_pendingReleaseService.RemovePendingQueueItems(pendingRelease.Id);
|
_pendingReleaseService.RemovePendingQueueItems(pendingRelease.Id);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Reference in New Issue