diff --git a/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs b/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs index 902985371..cdf869695 100644 --- a/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs +++ b/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs @@ -31,7 +31,7 @@ namespace NzbDrone.Core.Download.Clients.Aria2 _proxy = proxy; } - protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink) + protected override string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink) { var gid = _proxy.AddUri(Settings, magnetLink); @@ -50,7 +50,7 @@ namespace NzbDrone.Core.Download.Clients.Aria2 return hash; } - protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent) + protected override string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent) { var gid = _proxy.AddTorrent(Settings, fileContent); @@ -120,7 +120,7 @@ namespace NzbDrone.Core.Download.Clients.Aria2 return null; } - protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) + protected override string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink) { var gid = _proxy.AddUri(Settings, torrentLink); diff --git a/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs b/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs index 5f6dd7a9d..5505233e5 100644 --- a/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs +++ b/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs @@ -25,12 +25,12 @@ namespace NzbDrone.Core.Download.Clients.Blackhole { } - protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) + protected override string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink) { throw new NotImplementedException("Blackhole does not support redirected indexers."); } - protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink) + protected override string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink) { if (!Settings.SaveMagnetFiles) { @@ -54,7 +54,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole return null; } - protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent) + protected override string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent) { var title = release.Title; diff --git a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs index 9ea829e6a..caa83fbdc 100644 --- a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs +++ b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs @@ -29,7 +29,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge _proxy = proxy; } - protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink) + protected override string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink) { var actualHash = _proxy.AddTorrentFromMagnet(magnetLink, Settings); @@ -53,7 +53,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge return actualHash.ToUpper(); } - protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent) + protected override string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent) { var actualHash = _proxy.AddTorrentFromFile(filename, fileContent, Settings); @@ -211,7 +211,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge return null; } - protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) + protected override string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink) { throw new NotImplementedException(); } diff --git a/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs b/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs index ebe52b722..b2d89a0c7 100644 --- a/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs +++ b/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs @@ -53,7 +53,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation return _dsTaskProxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.BT.ToString().ToLower()); } - protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink) + protected override string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink) { var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings); @@ -72,7 +72,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation throw new DownloadClientException("Failed to add magnet task to Download Station"); } - protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent) + protected override string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent) { var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings); @@ -315,7 +315,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation return null; } - protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) + protected override string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink) { throw new NotImplementedException(); } diff --git a/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs b/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs index f292eaf53..5506edeac 100644 --- a/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs +++ b/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs @@ -63,14 +63,14 @@ namespace NzbDrone.Core.Download.Clients.Flood public override bool SupportsCategories => true; public override ProviderMessage Message => new ProviderMessage("Prowlarr is unable to remove torrents that have finished seeding when using Flood", ProviderMessageType.Warning); - protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent) + protected override string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent) { _proxy.AddTorrentByFile(Convert.ToBase64String(fileContent), HandleTags(release, Settings, GetCategoryForRelease(release)), Settings); return hash; } - protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink) + protected override string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink) { _proxy.AddTorrentByUrl(magnetLink, HandleTags(release, Settings, GetCategoryForRelease(release)), Settings); @@ -93,7 +93,7 @@ namespace NzbDrone.Core.Download.Clients.Flood } } - protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) + protected override string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink) { throw new NotImplementedException(); } diff --git a/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs b/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs index a7f3ace5e..13c992443 100644 --- a/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs +++ b/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs @@ -36,7 +36,7 @@ namespace NzbDrone.Core.Download.Clients.FreeboxDownload return _proxy.GetTasks(Settings).Where(v => v.Type.ToLower() == FreeboxDownloadTaskType.Bt.ToString().ToLower()); } - protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink) + protected override string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink) { return _proxy.AddTaskFromUrl(magnetLink, GetDownloadDirectory(release).EncodeBase64(), @@ -45,7 +45,7 @@ namespace NzbDrone.Core.Download.Clients.FreeboxDownload Settings); } - protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent) + protected override string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent) { return _proxy.AddTaskFromFile(filename, fileContent, @@ -55,7 +55,7 @@ namespace NzbDrone.Core.Download.Clients.FreeboxDownload Settings); } - protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) + protected override string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink) { return _proxy.AddTaskFromUrl(torrentLink, GetDownloadDirectory(release).EncodeBase64(), diff --git a/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs b/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs index a5ca2e4fc..f3aa2c93b 100644 --- a/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs +++ b/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs @@ -40,14 +40,14 @@ namespace NzbDrone.Core.Download.Clients.Hadouken failures.AddIfNotNull(TestGetTorrents()); } - protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink) + protected override string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink) { _proxy.AddTorrentUri(Settings, magnetLink, GetCategoryForRelease(release) ?? Settings.Category); return hash.ToUpper(); } - protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent) + protected override string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent) { return _proxy.AddTorrentFile(Settings, fileContent, GetCategoryForRelease(release) ?? Settings.Category).ToUpper(); } @@ -97,7 +97,7 @@ namespace NzbDrone.Core.Download.Clients.Hadouken return null; } - protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) + protected override string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink) { throw new NotImplementedException(); } diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs index edc9b2fd4..1cca3d3ba 100644 --- a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs @@ -41,7 +41,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent private IQBittorrentProxy Proxy => _proxySelector.GetProxy(Settings); private Version ProxyApiVersion => _proxySelector.GetApiVersion(Settings); - protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink) + protected override string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink) { if (!Proxy.GetConfig(Settings).DhtEnabled && !magnetLink.Contains("&tr=")) { @@ -95,7 +95,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent return hash; } - protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent) + protected override string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent) { //var setShareLimits = release.SeedConfiguration != null && (release.SeedConfiguration.Ratio.HasValue || release.SeedConfiguration.SeedTime.HasValue); //var addHasSetShareLimits = setShareLimits && ProxyApiVersion >= new Version(2, 8, 1); @@ -450,7 +450,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent torrent.SeedingTime = torrentProperties.SeedingTime; } - protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) + protected override string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink) { throw new NotImplementedException(); } diff --git a/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs b/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs index a4e4d90ae..51af63ee9 100644 --- a/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs +++ b/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs @@ -66,7 +66,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission return false; } - protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink) + protected override string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink) { _proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings); @@ -79,7 +79,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission return hash; } - protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent) + protected override string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent) { _proxy.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings); @@ -92,7 +92,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission return hash; } - protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) + protected override string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink) { throw new NotImplementedException(); } diff --git a/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs b/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs index 9f7505cfd..e4ae67767 100644 --- a/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs @@ -34,7 +34,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent _rTorrentDirectoryValidator = rTorrentDirectoryValidator; } - protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink) + protected override string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink) { var priority = (RTorrentPriority)Settings.Priority; @@ -54,7 +54,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent return hash; } - protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent) + protected override string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent) { var priority = (RTorrentPriority)Settings.Priority; @@ -157,7 +157,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent return false; } - protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) + protected override string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink) { throw new NotImplementedException(); } diff --git a/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs b/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs index 7d8da7b1c..6ab0635c5 100644 --- a/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs @@ -32,7 +32,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent _torrentCache = cacheManager.GetCache(GetType(), "differentialTorrents"); } - protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink) + protected override string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink) { _proxy.AddTorrentFromUrl(magnetLink, Settings); @@ -53,7 +53,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent return hash; } - protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent) + protected override string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent) { _proxy.AddTorrentFromFile(filename, fileContent, Settings); @@ -148,7 +148,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent return null; } - protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) + protected override string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink) { throw new NotImplementedException(); } diff --git a/src/NzbDrone.Core/Download/DownloadService.cs b/src/NzbDrone.Core/Download/DownloadService.cs index 49085b6e4..e4d10f1eb 100644 --- a/src/NzbDrone.Core/Download/DownloadService.cs +++ b/src/NzbDrone.Core/Download/DownloadService.cs @@ -29,6 +29,7 @@ namespace NzbDrone.Core.Download private readonly IIndexerStatusService _indexerStatusService; private readonly IRateLimitService _rateLimitService; private readonly IEventAggregator _eventAggregator; + private readonly ISeedConfigProvider _seedConfigProvider; private readonly Logger _logger; public DownloadService(IProvideDownloadClient downloadClientProvider, @@ -37,6 +38,7 @@ namespace NzbDrone.Core.Download IIndexerStatusService indexerStatusService, IRateLimitService rateLimitService, IEventAggregator eventAggregator, + ISeedConfigProvider seedConfigProvider, Logger logger) { _downloadClientProvider = downloadClientProvider; @@ -45,6 +47,7 @@ namespace NzbDrone.Core.Download _indexerStatusService = indexerStatusService; _rateLimitService = rateLimitService; _eventAggregator = eventAggregator; + _seedConfigProvider = seedConfigProvider; _logger = logger; } @@ -59,7 +62,8 @@ namespace NzbDrone.Core.Download } // Get the seed configuration for this release. - // remoteMovie.SeedConfiguration = _seedConfigProvider.GetSeedConfiguration(remoteMovie); + ((TorrentInfo)release).SeedConfiguration = _seedConfigProvider.GetSeedConfiguration(release); + var indexer = _indexerFactory.GetInstance(_indexerFactory.Get(release.IndexerId)); var grabEvent = new IndexerDownloadEvent(release, true, source, host, release.Title, release.DownloadUrl) diff --git a/src/NzbDrone.Core/Download/TorrentClientBase.cs b/src/NzbDrone.Core/Download/TorrentClientBase.cs index 9a5787e0a..2bcc4382e 100644 --- a/src/NzbDrone.Core/Download/TorrentClientBase.cs +++ b/src/NzbDrone.Core/Download/TorrentClientBase.cs @@ -36,9 +36,9 @@ namespace NzbDrone.Core.Download public virtual bool PreferTorrentFile => false; - protected abstract string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink); - protected abstract string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent); - protected abstract string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink); + protected abstract string AddFromMagnetLink(TorrentInfo release, string hash, string magnetLink); + protected abstract string AddFromTorrentFile(TorrentInfo release, string hash, string filename, byte[] fileContent); + protected abstract string AddFromTorrentLink(TorrentInfo release, string hash, string torrentLink); public override async Task Download(ReleaseInfo release, bool redirect, IIndexer indexer) { @@ -142,7 +142,7 @@ namespace NzbDrone.Core.Download var filename = string.Format("{0}.torrent", StringUtil.CleanFileName(release.Title)); var hash = _torrentFileInfoReader.GetHashFromTorrentFile(torrentFile); - var actualHash = AddFromTorrentFile(release, hash, filename, torrentFile); + var actualHash = AddFromTorrentFile((TorrentInfo)release, hash, filename, torrentFile); if (actualHash.IsNotNullOrWhiteSpace() && hash != actualHash) { @@ -173,7 +173,7 @@ namespace NzbDrone.Core.Download if (hash != null) { - actualHash = AddFromMagnetLink(release, hash, magnetUrl); + actualHash = AddFromMagnetLink((TorrentInfo)release, hash, magnetUrl); } if (actualHash.IsNotNullOrWhiteSpace() && hash != actualHash) diff --git a/src/NzbDrone.Core/Indexers/SeedConfigProvider.cs b/src/NzbDrone.Core/Indexers/SeedConfigProvider.cs new file mode 100644 index 000000000..88d8e8e9a --- /dev/null +++ b/src/NzbDrone.Core/Indexers/SeedConfigProvider.cs @@ -0,0 +1,91 @@ +using System; +using NzbDrone.Common.Cache; +using NzbDrone.Core.Datastore; +using NzbDrone.Core.Download.Clients; +using NzbDrone.Core.Messaging.Events; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.ThingiProvider.Events; + +namespace NzbDrone.Core.Indexers +{ + public interface ISeedConfigProvider + { + TorrentSeedConfiguration GetSeedConfiguration(ReleaseInfo release); + TorrentSeedConfiguration GetSeedConfiguration(int indexerId); + } + + public class SeedConfigProvider : ISeedConfigProvider, IHandle> + { + private readonly IIndexerFactory _indexerFactory; + private readonly ICached _cache; + + public SeedConfigProvider(IIndexerFactory indexerFactory, ICacheManager cacheManager) + { + _indexerFactory = indexerFactory; + _cache = cacheManager.GetRollingCache(GetType(), "criteriaByIndexer", TimeSpan.FromHours(1)); + } + + public TorrentSeedConfiguration GetSeedConfiguration(ReleaseInfo release) + { + if (release.DownloadProtocol != DownloadProtocol.Torrent) + { + return null; + } + + if (release.IndexerId == 0) + { + return null; + } + + return GetSeedConfiguration(release.IndexerId); + } + + public TorrentSeedConfiguration GetSeedConfiguration(int indexerId) + { + if (indexerId == 0) + { + return null; + } + + var seedCriteria = _cache.Get(indexerId.ToString(), () => FetchSeedCriteria(indexerId)); + + if (seedCriteria == null) + { + return null; + } + + var seedConfig = new TorrentSeedConfiguration + { + Ratio = seedCriteria.SeedRatio + }; + + var seedTime = seedCriteria.SeedTime; + if (seedTime.HasValue) + { + seedConfig.SeedTime = TimeSpan.FromMinutes(seedTime.Value); + } + + return seedConfig; + } + + private IndexerTorrentBaseSettings FetchSeedCriteria(int indexerId) + { + try + { + var indexer = _indexerFactory.Get(indexerId); + var torrentIndexerSettings = indexer.Settings as ITorrentIndexerSettings; + + return torrentIndexerSettings?.TorrentBaseSettings; + } + catch (ModelNotFoundException) + { + return null; + } + } + + public void Handle(ProviderUpdatedEvent message) + { + _cache.Clear(); + } + } +} diff --git a/src/NzbDrone.Core/Parser/Model/TorrentInfo.cs b/src/NzbDrone.Core/Parser/Model/TorrentInfo.cs index a5ae1d26e..b8081f73b 100644 --- a/src/NzbDrone.Core/Parser/Model/TorrentInfo.cs +++ b/src/NzbDrone.Core/Parser/Model/TorrentInfo.cs @@ -1,4 +1,5 @@ using System.Text; +using NzbDrone.Core.Download.Clients; namespace NzbDrone.Core.Parser.Model { @@ -13,6 +14,8 @@ namespace NzbDrone.Core.Parser.Model public double? DownloadVolumeFactor { get; set; } public double? UploadVolumeFactor { get; set; } + public TorrentSeedConfiguration SeedConfiguration { get; set; } + public static int? GetSeeders(ReleaseInfo release) { var torrentInfo = release as TorrentInfo;