mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-17 21:25:39 -04:00
Fixed: Blocklisting pending releases
This commit is contained in:
@@ -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}
|
||||
/>
|
||||
|
||||
@@ -357,6 +357,7 @@ class QueueRow extends Component {
|
||||
isOpen={isRemoveQueueItemModalOpen}
|
||||
sourceTitle={title}
|
||||
canIgnore={!!author}
|
||||
isPending={isPending}
|
||||
onRemovePress={this.onRemoveQueueItemModalConfirmed}
|
||||
onModalClose={this.onRemoveQueueItemModalClose}
|
||||
/>
|
||||
|
||||
@@ -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?
|
||||
</div>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
{translate('RemoveFromDownloadClient')}
|
||||
</FormLabel>
|
||||
{
|
||||
isPending ?
|
||||
null :
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
{translate('RemoveFromDownloadClient')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="remove"
|
||||
value={remove}
|
||||
helpTextWarning={translate('RemoveHelpTextWarning')}
|
||||
isDisabled={!canIgnore}
|
||||
onChange={this.onRemoveChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="remove"
|
||||
value={remove}
|
||||
helpTextWarning={translate('RemoveHelpTextWarning')}
|
||||
isDisabled={!canIgnore}
|
||||
onChange={this.onRemoveChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
}
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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?
|
||||
</div>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
{translate('RemoveFromDownloadClient')}
|
||||
</FormLabel>
|
||||
{
|
||||
allPending ?
|
||||
null :
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
{translate('RemoveFromDownloadClient')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="remove"
|
||||
value={remove}
|
||||
helpTextWarning={translate('RemoveHelpTextWarning')}
|
||||
isDisabled={!canIgnore}
|
||||
onChange={this.onRemoveChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="remove"
|
||||
value={remove}
|
||||
helpTextWarning={translate('RemoveHelpTextWarning')}
|
||||
isDisabled={!canIgnore}
|
||||
onChange={this.onRemoveChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
}
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace NzbDrone.Core.Blocklisting
|
||||
{
|
||||
bool Blocklisted(int authorId, ReleaseInfo release);
|
||||
PagingSpec<Blocklist> Paged(PagingSpec<Blocklist> pagingSpec);
|
||||
void Block(RemoteBook remoteEpisode, string message);
|
||||
void Delete(int id);
|
||||
void Delete(List<int> 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);
|
||||
|
||||
@@ -129,13 +129,6 @@ namespace NzbDrone.Core.Download.Pending
|
||||
}
|
||||
}
|
||||
|
||||
private ILookup<int, PendingRelease> CreateBookLookup(IEnumerable<PendingRelease> 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<ReleaseInfo> GetPending()
|
||||
{
|
||||
var releases = _repository.All().Select(p => p.Release).ToList();
|
||||
@@ -148,13 +141,6 @@ namespace NzbDrone.Core.Download.Pending
|
||||
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<RemoteBook> 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<int, PendingRelease> CreateBookLookup(IEnumerable<PendingRelease> 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<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()
|
||||
{
|
||||
return IncludeRemoteBooks(_repository.All().ToList());
|
||||
@@ -338,13 +338,6 @@ namespace NzbDrone.Core.Download.Pending
|
||||
_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(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<PendingRelease, bool> MatchingReleasePredicate(ReleaseInfo release)
|
||||
{
|
||||
return p => p.Title == release.Title &&
|
||||
p.Release.PublishDate == release.PublishDate &&
|
||||
p.Release.Indexer == release.Indexer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user