Fixed: Blocklisting torrents from indexers that do not provide torrent hash

Closes #6108
This commit is contained in:
Mark McDowall 2023-10-29 11:23:23 -07:00 committed by Mark McDowall
parent 5d86329c18
commit 3541cd7ba8
29 changed files with 176 additions and 53 deletions

View File

@ -15,6 +15,7 @@ namespace NzbDrone.Core.Blocklisting
public interface IBlocklistService public interface IBlocklistService
{ {
bool Blocklisted(int seriesId, ReleaseInfo release); bool Blocklisted(int seriesId, ReleaseInfo release);
bool BlocklistedTorrentHash(int seriesId, string hash);
PagingSpec<Blocklist> Paged(PagingSpec<Blocklist> pagingSpec); PagingSpec<Blocklist> Paged(PagingSpec<Blocklist> pagingSpec);
void Block(RemoteEpisode remoteEpisode, string message); void Block(RemoteEpisode remoteEpisode, string message);
void Delete(int id); void Delete(int id);
@ -61,6 +62,12 @@ namespace NzbDrone.Core.Blocklisting
.Any(b => SameNzb(b, release)); .Any(b => SameNzb(b, release));
} }
public bool BlocklistedTorrentHash(int seriesId, string hash)
{
return _blocklistRepository.BlocklistedByTorrentInfoHash(seriesId, hash).Any(b =>
b.TorrentInfoHash.Equals(hash, StringComparison.InvariantCultureIgnoreCase));
}
public PagingSpec<Blocklist> Paged(PagingSpec<Blocklist> pagingSpec) public PagingSpec<Blocklist> Paged(PagingSpec<Blocklist> pagingSpec)
{ {
return _blocklistRepository.GetPaged(pagingSpec); return _blocklistRepository.GetPaged(pagingSpec);

View File

@ -7,6 +7,7 @@ using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.MediaFiles.TorrentInfo;
@ -28,9 +29,10 @@ namespace NzbDrone.Core.Download.Clients.Aria2
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
_proxy = proxy; _proxy = proxy;
} }

View File

@ -7,6 +7,7 @@ using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.MediaFiles.TorrentInfo;
@ -30,9 +31,10 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
_scanWatchFolder = scanWatchFolder; _scanWatchFolder = scanWatchFolder;

View File

@ -7,6 +7,7 @@ using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.MediaFiles.TorrentInfo;
@ -26,9 +27,10 @@ namespace NzbDrone.Core.Download.Clients.Deluge
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
_proxy = proxy; _proxy = proxy;
} }

View File

@ -8,6 +8,7 @@ using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download.Clients.DownloadStation.Proxies; using NzbDrone.Core.Download.Clients.DownloadStation.Proxies;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
@ -37,9 +38,10 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
_dsInfoProxy = dsInfoProxy; _dsInfoProxy = dsInfoProxy;
_dsTaskProxySelector = dsTaskProxySelector; _dsTaskProxySelector = dsTaskProxySelector;

View File

@ -7,6 +7,7 @@ using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download.Clients.Flood.Models; using NzbDrone.Core.Download.Clients.Flood.Models;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
@ -29,9 +30,10 @@ namespace NzbDrone.Core.Download.Clients.Flood
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
_proxy = proxy; _proxy = proxy;
_downloadSeedConfigProvider = downloadSeedConfigProvider; _downloadSeedConfigProvider = downloadSeedConfigProvider;

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using FluentValidation.Results; using FluentValidation.Results;
@ -6,6 +6,7 @@ using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download.Clients.FreeboxDownload.Responses; using NzbDrone.Core.Download.Clients.FreeboxDownload.Responses;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
@ -25,9 +26,10 @@ namespace NzbDrone.Core.Download.Clients.FreeboxDownload
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
_proxy = proxy; _proxy = proxy;
} }

View File

@ -5,6 +5,7 @@ using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download.Clients.Hadouken.Models; using NzbDrone.Core.Download.Clients.Hadouken.Models;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
@ -25,9 +26,10 @@ namespace NzbDrone.Core.Download.Clients.Hadouken
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
_proxy = proxy; _proxy = proxy;
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using Newtonsoft.Json; using Newtonsoft.Json;

View File

@ -8,6 +8,7 @@ using NzbDrone.Common.Cache;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.MediaFiles.TorrentInfo;
@ -35,9 +36,10 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
ICacheManager cacheManager, ICacheManager cacheManager,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
_proxySelector = proxySelector; _proxySelector = proxySelector;

View File

@ -1,10 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using FluentValidation.Results; using FluentValidation.Results;
using NLog; using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.MediaFiles.TorrentInfo;
@ -20,9 +21,10 @@ namespace NzbDrone.Core.Download.Clients.Transmission
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(proxy, torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(proxy, torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
} }

View File

@ -6,6 +6,7 @@ using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.MediaFiles.TorrentInfo;
@ -25,9 +26,10 @@ namespace NzbDrone.Core.Download.Clients.Transmission
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
_proxy = proxy; _proxy = proxy;
} }

View File

@ -2,6 +2,7 @@ using FluentValidation.Results;
using NLog; using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download.Clients.Transmission; using NzbDrone.Core.Download.Clients.Transmission;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
@ -20,9 +21,10 @@ namespace NzbDrone.Core.Download.Clients.Vuze
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(proxy, torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(proxy, torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
} }

View File

@ -8,6 +8,7 @@ using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download.Clients.rTorrent; using NzbDrone.Core.Download.Clients.rTorrent;
using NzbDrone.Core.Exceptions; using NzbDrone.Core.Exceptions;
@ -35,9 +36,10 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
IDownloadSeedConfigProvider downloadSeedConfigProvider, IDownloadSeedConfigProvider downloadSeedConfigProvider,
IRTorrentDirectoryValidator rTorrentDirectoryValidator, IRTorrentDirectoryValidator rTorrentDirectoryValidator,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
_proxy = proxy; _proxy = proxy;
_rTorrentDirectoryValidator = rTorrentDirectoryValidator; _rTorrentDirectoryValidator = rTorrentDirectoryValidator;

View File

@ -8,6 +8,7 @@ using NzbDrone.Common.Cache;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization; using NzbDrone.Core.Localization;
using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.MediaFiles.TorrentInfo;
@ -29,9 +30,10 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger, localizationService) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{ {
_proxy = proxy; _proxy = proxy;

View File

@ -104,6 +104,11 @@ namespace NzbDrone.Core.Download
_logger.Trace("Release {0} no longer available on indexer.", remoteEpisode); _logger.Trace("Release {0} no longer available on indexer.", remoteEpisode);
throw; throw;
} }
catch (ReleaseBlockedException)
{
_logger.Trace("Release {0} previously added to blocklist, not sending to download client again.", remoteEpisode);
throw;
}
catch (DownloadClientRejectedReleaseException) catch (DownloadClientRejectedReleaseException)
{ {
_logger.Trace("Release {0} rejected by download client, possible duplicate.", remoteEpisode); _logger.Trace("Release {0} rejected by download client, possible duplicate.", remoteEpisode);
@ -128,7 +133,7 @@ namespace NzbDrone.Core.Download
episodeGrabbedEvent.DownloadClientId = downloadClient.Definition.Id; episodeGrabbedEvent.DownloadClientId = downloadClient.Definition.Id;
episodeGrabbedEvent.DownloadClientName = downloadClient.Definition.Name; episodeGrabbedEvent.DownloadClientName = downloadClient.Definition.Name;
if (!string.IsNullOrWhiteSpace(downloadClientId)) if (downloadClientId.IsNotNullOrWhiteSpace())
{ {
episodeGrabbedEvent.DownloadId = downloadClientId; episodeGrabbedEvent.DownloadId = downloadClientId;
} }

View File

@ -129,7 +129,7 @@ namespace NzbDrone.Core.Download
private void PublishDownloadFailedEvent(List<EpisodeHistory> historyItems, string message, TrackedDownload trackedDownload = null, bool skipRedownload = false) private void PublishDownloadFailedEvent(List<EpisodeHistory> historyItems, string message, TrackedDownload trackedDownload = null, bool skipRedownload = false)
{ {
var historyItem = historyItems.First(); var historyItem = historyItems.Last();
Enum.TryParse(historyItem.Data.GetValueOrDefault(EpisodeHistory.RELEASE_SOURCE, ReleaseSourceType.Unknown.ToString()), out ReleaseSourceType releaseSource); Enum.TryParse(historyItem.Data.GetValueOrDefault(EpisodeHistory.RELEASE_SOURCE, ReleaseSourceType.Unknown.ToString()), out ReleaseSourceType releaseSource);
var downloadFailedEvent = new DownloadFailedEvent var downloadFailedEvent = new DownloadFailedEvent

View File

@ -6,6 +6,7 @@ using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Exceptions; using NzbDrone.Core.Exceptions;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
@ -22,6 +23,7 @@ namespace NzbDrone.Core.Download
where TSettings : IProviderConfig, new() where TSettings : IProviderConfig, new()
{ {
protected readonly IHttpClient _httpClient; protected readonly IHttpClient _httpClient;
private readonly IBlocklistService _blocklistService;
protected readonly ITorrentFileInfoReader _torrentFileInfoReader; protected readonly ITorrentFileInfoReader _torrentFileInfoReader;
protected TorrentClientBase(ITorrentFileInfoReader torrentFileInfoReader, protected TorrentClientBase(ITorrentFileInfoReader torrentFileInfoReader,
@ -29,11 +31,13 @@ namespace NzbDrone.Core.Download
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService, IRemotePathMappingService remotePathMappingService,
Logger logger, ILocalizationService localizationService,
ILocalizationService localizationService) IBlocklistService blocklistService,
Logger logger)
: base(configService, diskProvider, remotePathMappingService, logger, localizationService) : base(configService, diskProvider, remotePathMappingService, logger, localizationService)
{ {
_httpClient = httpClient; _httpClient = httpClient;
_blocklistService = blocklistService;
_torrentFileInfoReader = torrentFileInfoReader; _torrentFileInfoReader = torrentFileInfoReader;
} }
@ -88,7 +92,7 @@ namespace NzbDrone.Core.Download
{ {
try try
{ {
return DownloadFromMagnetUrl(remoteEpisode, magnetUrl); return DownloadFromMagnetUrl(remoteEpisode, indexer, magnetUrl);
} }
catch (NotSupportedException ex) catch (NotSupportedException ex)
{ {
@ -102,7 +106,7 @@ namespace NzbDrone.Core.Download
{ {
try try
{ {
return DownloadFromMagnetUrl(remoteEpisode, magnetUrl); return DownloadFromMagnetUrl(remoteEpisode, indexer, magnetUrl);
} }
catch (NotSupportedException ex) catch (NotSupportedException ex)
{ {
@ -149,7 +153,7 @@ namespace NzbDrone.Core.Download
{ {
if (locationHeader.StartsWith("magnet:")) if (locationHeader.StartsWith("magnet:"))
{ {
return DownloadFromMagnetUrl(remoteEpisode, locationHeader); return DownloadFromMagnetUrl(remoteEpisode, indexer, locationHeader);
} }
request.Url += new HttpUri(locationHeader); request.Url += new HttpUri(locationHeader);
@ -192,6 +196,9 @@ namespace NzbDrone.Core.Download
var filename = string.Format("{0}.torrent", FileNameBuilder.CleanFileName(remoteEpisode.Release.Title)); var filename = string.Format("{0}.torrent", FileNameBuilder.CleanFileName(remoteEpisode.Release.Title));
var hash = _torrentFileInfoReader.GetHashFromTorrentFile(torrentFile); var hash = _torrentFileInfoReader.GetHashFromTorrentFile(torrentFile);
EnsureReleaseIsNotBlocklisted(remoteEpisode, indexer, hash);
var actualHash = AddFromTorrentFile(remoteEpisode, hash, filename, torrentFile); var actualHash = AddFromTorrentFile(remoteEpisode, hash, filename, torrentFile);
if (actualHash.IsNotNullOrWhiteSpace() && hash != actualHash) if (actualHash.IsNotNullOrWhiteSpace() && hash != actualHash)
@ -205,7 +212,7 @@ namespace NzbDrone.Core.Download
return actualHash; return actualHash;
} }
private string DownloadFromMagnetUrl(RemoteEpisode remoteEpisode, string magnetUrl) private string DownloadFromMagnetUrl(RemoteEpisode remoteEpisode, IIndexer indexer, string magnetUrl)
{ {
string hash = null; string hash = null;
string actualHash = null; string actualHash = null;
@ -223,6 +230,8 @@ namespace NzbDrone.Core.Download
if (hash != null) if (hash != null)
{ {
EnsureReleaseIsNotBlocklisted(remoteEpisode, indexer, hash);
actualHash = AddFromMagnetLink(remoteEpisode, hash, magnetUrl); actualHash = AddFromMagnetLink(remoteEpisode, hash, magnetUrl);
} }
@ -236,5 +245,30 @@ namespace NzbDrone.Core.Download
return actualHash; return actualHash;
} }
private void EnsureReleaseIsNotBlocklisted(RemoteEpisode remoteEpisode, IIndexer indexer, string hash)
{
var indexerSettings = indexer?.Definition?.Settings as ITorrentIndexerSettings;
var torrentInfo = remoteEpisode.Release as TorrentInfo;
var torrentInfoHash = torrentInfo?.InfoHash;
// If the release didn't come from an interactive search,
// the hash wasn't known during processing and the
// indexer is configured to reject blocklisted releases
// during grab check if it's already been blocklisted.
if (torrentInfo != null && torrentInfoHash.IsNullOrWhiteSpace())
{
// If the hash isn't known from parsing we set it here so it can be used for blocklisting.
torrentInfo.InfoHash = hash;
if (remoteEpisode.ReleaseSource != ReleaseSourceType.InteractiveSearch &&
indexerSettings?.RejectBlocklistedTorrentHashesWhileGrabbing == true &&
_blocklistService.BlocklistedTorrentHash(remoteEpisode.Series.Id, hash))
{
throw new ReleaseBlockedException(remoteEpisode.Release, "Release previously added to blocklist");
}
}
}
} }
} }

View File

@ -0,0 +1,28 @@
using System;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Exceptions
{
public class ReleaseBlockedException : ReleaseDownloadException
{
public ReleaseBlockedException(ReleaseInfo release, string message, params object[] args)
: base(release, message, args)
{
}
public ReleaseBlockedException(ReleaseInfo release, string message)
: base(release, message)
{
}
public ReleaseBlockedException(ReleaseInfo release, string message, Exception innerException, params object[] args)
: base(release, message, innerException, args)
{
}
public ReleaseBlockedException(ReleaseInfo release, string message, Exception innerException)
: base(release, message, innerException)
{
}
}
}

View File

@ -175,9 +175,7 @@ namespace NzbDrone.Core.History
history.Data.Add("ReleaseHash", message.Episode.ParsedEpisodeInfo.ReleaseHash); history.Data.Add("ReleaseHash", message.Episode.ParsedEpisodeInfo.ReleaseHash);
} }
var torrentRelease = message.Episode.Release as TorrentInfo; if (message.Episode.Release is TorrentInfo torrentRelease)
if (torrentRelease != null)
{ {
history.Data.Add("TorrentInfoHash", torrentRelease.InfoHash); history.Data.Add("TorrentInfoHash", torrentRelease.InfoHash);
} }

View File

@ -37,6 +37,9 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
[FieldDefinition(3)] [FieldDefinition(3)]
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
[FieldDefinition(4, Type = FieldType.Checkbox, Label = "Reject Blocklisted Torrent Hashes While Grabbing", HelpText = "If a torrent is blocked by hash it may not properly be rejected during RSS/Search for some indexers, enabling this will allow it to be rejected after the torrent is grabbed, but before it is sent to the client.", Advanced = true)]
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));

View File

@ -58,6 +58,9 @@ namespace NzbDrone.Core.Indexers.FileList
[FieldDefinition(7)] [FieldDefinition(7)]
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
[FieldDefinition(8, Type = FieldType.Checkbox, Label = "Reject Blocklisted Torrent Hashes While Grabbing", HelpText = "If a torrent is blocked by hash it may not properly be rejected during RSS/Search for some indexers, enabling this will allow it to be rejected after the torrent is grabbed, but before it is sent to the client.", Advanced = true)]
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));

View File

@ -55,6 +55,9 @@ namespace NzbDrone.Core.Indexers.HDBits
[FieldDefinition(7)] [FieldDefinition(7)]
public SeedCriteriaSettings SeedCriteria { get; set; } = new (); public SeedCriteriaSettings SeedCriteria { get; set; } = new ();
[FieldDefinition(8, Type = FieldType.Checkbox, Label = "Reject Blocklisted Torrent Hashes While Grabbing", HelpText = "If a torrent is blocked by hash it may not properly be rejected during RSS/Search for some indexers, enabling this will allow it to be rejected after the torrent is grabbed, but before it is sent to the client.", Advanced = true)]
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));

View File

@ -40,6 +40,9 @@ namespace NzbDrone.Core.Indexers.IPTorrents
[FieldDefinition(2)] [FieldDefinition(2)]
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
[FieldDefinition(3, Type = FieldType.Checkbox, Label = "Reject Blocklisted Torrent Hashes While Grabbing", HelpText = "If a torrent is blocked by hash it may not properly be rejected during RSS/Search for some indexers, enabling this will allow it to be rejected after the torrent is grabbed, but before it is sent to the client.", Advanced = true)]
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));

View File

@ -6,5 +6,6 @@ namespace NzbDrone.Core.Indexers
// TODO: System.Text.Json requires setter be public for sub-object deserialization in 3.0. https://github.com/dotnet/corefx/issues/42515 // TODO: System.Text.Json requires setter be public for sub-object deserialization in 3.0. https://github.com/dotnet/corefx/issues/42515
SeedCriteriaSettings SeedCriteria { get; set; } SeedCriteriaSettings SeedCriteria { get; set; }
bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
} }
} }

View File

@ -42,6 +42,9 @@ namespace NzbDrone.Core.Indexers.Nyaa
[FieldDefinition(4)] [FieldDefinition(4)]
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
[FieldDefinition(5, Type = FieldType.Checkbox, Label = "Reject Blocklisted Torrent Hashes While Grabbing", HelpText = "If a torrent is blocked by hash it may not properly be rejected during RSS/Search for some indexers, enabling this will allow it to be rejected after the torrent is grabbed, but before it is sent to the client.", Advanced = true)]
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));

View File

@ -40,6 +40,9 @@ namespace NzbDrone.Core.Indexers.TorrentRss
[FieldDefinition(4)] [FieldDefinition(4)]
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
[FieldDefinition(5, Type = FieldType.Checkbox, Label = "Reject Blocklisted Torrent Hashes While Grabbing", HelpText = "If a torrent is blocked by hash it may not properly be rejected during RSS/Search for some indexers, enabling this will allow it to be rejected after the torrent is grabbed, but before it is sent to the client.", Advanced = true)]
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));

View File

@ -37,6 +37,9 @@ namespace NzbDrone.Core.Indexers.Torrentleech
[FieldDefinition(3)] [FieldDefinition(3)]
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
[FieldDefinition(4, Type = FieldType.Checkbox, Label = "Reject Blocklisted Torrent Hashes While Grabbing", HelpText = "If a torrent is blocked by hash it may not properly be rejected during RSS/Search for some indexers, enabling this will allow it to be rejected after the torrent is grabbed, but before it is sent to the client.", Advanced = true)]
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));

View File

@ -57,6 +57,9 @@ namespace NzbDrone.Core.Indexers.Torznab
[FieldDefinition(8)] [FieldDefinition(8)]
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
[FieldDefinition(9, Type = FieldType.Checkbox, Label = "Reject Blocklisted Torrent Hashes While Grabbing", HelpText = "If a torrent is blocked by hash it may not properly be rejected during RSS/Search for some indexers, enabling this will allow it to be rejected after the torrent is grabbed, but before it is sent to the client.", Advanced = true)]
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
public override NzbDroneValidationResult Validate() public override NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));