New: Added advanced setting per indexer to override seed ratio limit for supported clients.

Kevin Richter 7 years ago committed by Taloth Saldono
parent 69f8fc4d5e
commit 2d86e44c63

@ -0,0 +1,10 @@
using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Configuration
{
public interface ISeedConfigProvider
{
TorrentSeedConfiguration GetSeedConfiguration(ReleaseInfo release);
}
}

@ -0,0 +1,33 @@
using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Configuration
{
public class SeedConfigProvider: ISeedConfigProvider
{
private readonly IIndexerFactory _indexerFactory;
public SeedConfigProvider(IIndexerFactory indexerFactory)
{
_indexerFactory = indexerFactory;
}
public TorrentSeedConfiguration GetSeedConfiguration(ReleaseInfo release)
{
if (release.DownloadProtocol != DownloadProtocol.Torrent) return null;
var indexer = _indexerFactory.Get(release.IndexerId);
if (indexer.Settings is ITorrentIndexerSettings torrentIndexerSettings)
{
return new TorrentSeedConfiguration
{
Ratio = torrentIndexerSettings.SeedRatio
};
}
return null;
}
}
}

@ -45,6 +45,8 @@ namespace NzbDrone.Core.Download.Clients.Deluge
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
}
_proxy.SetTorrentSeedingConfiguration(actualHash, remoteEpisode.SeedConfiguration, Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
@ -65,6 +67,8 @@ namespace NzbDrone.Core.Download.Clients.Deluge
throw new DownloadClientException("Deluge failed to add torrent " + filename);
}
_proxy.SetTorrentSeedingConfiguration(actualHash, remoteEpisode.SeedConfiguration, Settings);
if (!Settings.TvCategory.IsNullOrWhiteSpace())
{
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
@ -110,6 +114,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
var outputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(torrent.DownloadPath));
item.OutputPath = outputPath + torrent.Name;
item.RemainingSize = torrent.Size - torrent.BytesDownloaded;
item.SeedRatio = torrent.Ratio;
try
{
@ -145,8 +150,13 @@ namespace NzbDrone.Core.Download.Clients.Deluge
item.Status = DownloadItemStatus.Downloading;
}
// Here we detect if Deluge is managing the torrent and whether the seed criteria has been met. This allows drone to delete the torrent as appropriate.
item.CanMoveFiles = item.CanBeRemoved = (torrent.IsAutoManaged && torrent.StopAtRatio && torrent.Ratio >= torrent.StopRatio && torrent.State == DelugeTorrentStatus.Paused);
// Here we detect if Deluge is managing the torrent and whether the seed criteria has been met.
// This allows drone to delete the torrent as appropriate.
item.CanMoveFiles = item.CanBeRemoved =
torrent.IsAutoManaged &&
torrent.StopAtRatio &&
torrent.Ratio >= torrent.StopRatio &&
torrent.State == DelugeTorrentStatus.Paused;
items.Add(item);
}

@ -151,13 +151,16 @@ namespace NzbDrone.Core.Download.Clients.Deluge
public void SetTorrentSeedingConfiguration(string hash, TorrentSeedConfiguration seedConfiguration, DelugeSettings settings)
{
if (seedConfiguration == null) return;
var ratioArguments = new Dictionary<string, object>();
if (seedConfiguration.Ratio != null)
{
var ratioArguments = new Dictionary<string, object>();
ratioArguments.Add("stop_ratio", seedConfiguration.Ratio.Value);
ProcessRequest<object>(settings, "core.set_torrent_options", new string[] { hash }, ratioArguments);
}
ProcessRequest<object>(settings, "core.set_torrent_options", new[] { hash }, ratioArguments);
}
public void AddLabel(string label, DelugeSettings settings)
@ -176,7 +179,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
var requestBuilder = new JsonRpcRequestBuilder(url);
requestBuilder.LogResponseContent = true;
requestBuilder.Resource("json");
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);

@ -13,7 +13,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
[JsonProperty(PropertyName = "is_finished")]
public bool IsFinished { get; set; }
// Other paths: What is the difference between 'move_completed_path' and 'move_on_completed_path'?
/*
[JsonProperty(PropertyName = "move_completed_path")]
@ -22,7 +22,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
public String DownloadPathMoveOnCompleted { get; set; }
*/
[JsonProperty(PropertyName = "save_path")]
[JsonProperty(PropertyName = "save_path")]
public string DownloadPath { get; set; }
[JsonProperty(PropertyName = "total_size")]

@ -88,6 +88,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
TotalSize = torrent.Size,
RemainingSize = GetRemainingSize(torrent),
RemainingTime = GetRemainingTime(torrent),
SeedRatio = GetSeedRatio(torrent),
Status = GetStatus(torrent),
Message = GetMessage(torrent),
CanMoveFiles = IsCompleted(torrent),
@ -121,7 +122,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
{
_logger.Debug(e, "Failed to get config from Download Station");
throw e;
throw;
}
}
@ -278,6 +279,19 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
return TimeSpan.FromSeconds(remainingSize / downloadSpeed);
}
protected double? GetSeedRatio(DownloadStationTask torrent)
{
var couldConvertDownloaded = long.TryParse(torrent.Additional.Transfer["size_downloaded"], out var downloaded);
var couldConvertUploaded = long.TryParse(torrent.Additional.Transfer["size_uploaded"], out var uploaded);
if (!couldConvertDownloaded || !couldConvertUploaded)
{
return new Nullable<double>();
}
return downloaded <= 0 ? 0 : (double) uploaded / downloaded;
}
protected ValidationFailure TestOutputPath()
{
try

@ -147,7 +147,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
{
_logger.Debug(e, "Failed to get config from Download Station");
throw e;
throw;
}
}

@ -62,7 +62,9 @@ namespace NzbDrone.Core.Download.Clients.Hadouken
RemainingSize = torrent.TotalSize - torrent.DownloadedBytes,
RemainingTime = eta,
Title = torrent.Name,
TotalSize = torrent.TotalSize
TotalSize = torrent.TotalSize,
SeedRatio = torrent.DownloadedBytes <= 0 ? 0 :
(double) torrent.UploadedBytes / torrent.DownloadedBytes
};
if (!string.IsNullOrEmpty(torrent.Error))

@ -138,6 +138,7 @@ namespace NzbDrone.Core.Download.Clients.Hadouken
TotalSize = Convert.ToInt64(item[3]),
Progress = Convert.ToDouble(item[4]),
DownloadedBytes = Convert.ToInt64(item[5]),
UploadedBytes = Convert.ToInt64(item[6]),
DownloadRate = Convert.ToInt64(item[9]),
Label = Convert.ToString(item[11]),
Error = Convert.ToString(item[21]),

@ -13,6 +13,7 @@
public bool IsSeeding { get; set; }
public long TotalSize { get; set; }
public long DownloadedBytes { get; set; }
public long UploadedBytes { get; set; }
public long DownloadRate { get; set; }
public string Error { get; set; }
}

@ -108,6 +108,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
item.DownloadClient = Definition.Name;
item.RemainingSize = (long)(torrent.Size * (1.0 - torrent.Progress));
item.RemainingTime = GetRemainingTime(torrent);
item.SeedRatio = torrent.Ratio;
item.OutputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(torrent.SavePath));

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common.Disk;
@ -66,6 +65,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission
item.OutputPath = GetOutputPath(outputPath, torrent);
item.TotalSize = torrent.TotalSize;
item.RemainingSize = torrent.LeftUntilDone;
item.SeedRatio = torrent.DownloadedEver <= 0 ? 0 :
(double) torrent.UploadedEver / torrent.DownloadedEver;
if (torrent.Eta >= 0)
{
item.RemainingTime = TimeSpan.FromSeconds(torrent.Eta);
@ -96,7 +98,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission
item.Status = DownloadItemStatus.Downloading;
}
item.CanMoveFiles = item.CanBeRemoved = torrent.Status == TransmissionTorrentStatus.Stopped;
item.CanMoveFiles = item.CanBeRemoved =
torrent.Status == TransmissionTorrentStatus.Stopped &&
item.SeedRatio >= torrent.SeedRatioLimit;
items.Add(item);
}
@ -129,6 +133,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings);
_proxy.SetTorrentSeedingConfiguration(hash, remoteEpisode.SeedConfiguration, Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
@ -144,6 +149,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings);
_proxy.SetTorrentSeedingConfiguration(hash, remoteEpisode.SeedConfiguration, Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
@ -174,17 +180,13 @@ namespace NzbDrone.Core.Download.Clients.Transmission
{
return Settings.TvDirectory;
}
else if (Settings.TvCategory.IsNotNullOrWhiteSpace())
{
var config = _proxy.GetConfig(Settings);
var destDir = (string)config.GetValueOrDefault("download-dir");
return string.Format("{0}/{1}", destDir.TrimEnd('/'), Settings.TvCategory);
}
else
{
return null;
}
if (!Settings.TvCategory.IsNotNullOrWhiteSpace()) return null;
var config = _proxy.GetConfig(Settings);
var destDir = (string)config.GetValueOrDefault("download-dir");
return $"{destDir.TrimEnd('/')}/{Settings.TvCategory}";
}
protected ValidationFailure TestConnection()

@ -37,7 +37,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
_authSessionIDCache = cacheManager.GetCache<string>(GetType(), "authSessionID");
}
public List<TransmissionTorrent> GetTorrents(TransmissionSettings settings)
{
var result = GetTorrentStatus(settings);
@ -77,8 +77,10 @@ namespace NzbDrone.Core.Download.Clients.Transmission
public void SetTorrentSeedingConfiguration(string hash, TorrentSeedConfiguration seedConfiguration, TransmissionSettings settings)
{
if (seedConfiguration == null) return;
var arguments = new Dictionary<string, object>();
arguments.Add("ids", new string[] { hash });
arguments.Add("ids", new[] { hash });
if (seedConfiguration.Ratio != null)
{
@ -167,9 +169,12 @@ namespace NzbDrone.Core.Download.Clients.Transmission
"leftUntilDone",
"isFinished",
"eta",
"errorString"
"errorString",
"uploadedEver",
"downloadedEver",
"seedRatioLimit"
};
var arguments = new Dictionary<string, object>();
arguments.Add("fields", fields);
@ -237,7 +242,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
requestBuilder.SetHeader("X-Transmission-Session-Id", sessionId);
}
public TransmissionResponse ProcessRequest(string action, object arguments, TransmissionSettings settings)
{
try

@ -23,5 +23,11 @@
public int SecondsDownloading { get; set; }
public string ErrorString { get; set; }
public long DownloadedEver { get; set; }
public long UploadedEver { get; set; }
public long SeedRatioLimit { get; set; }
}
}

@ -104,6 +104,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
item.TotalSize = torrent.TotalSize;
item.RemainingSize = torrent.RemainingSize;
item.Category = torrent.Category;
item.SeedRatio = torrent.Ratio;
if (torrent.DownRate > 0)
{

@ -40,6 +40,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
_proxy.SetTorrentSeedingConfiguration(hash, remoteEpisode.SeedConfiguration, Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
@ -58,6 +59,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
_proxy.SetTorrentSeedingConfiguration(hash, remoteEpisode.SeedConfiguration, Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
@ -94,6 +96,8 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
item.Category = torrent.Label;
item.DownloadClient = Definition.Name;
item.RemainingSize = torrent.Remaining;
item.SeedRatio = torrent.Ratio;
if (torrent.Eta != -1)
{
item.RemainingTime = TimeSpan.FromSeconds(torrent.Eta);
@ -101,7 +105,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
var outputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(torrent.RootDownloadPath));
if (outputPath == null || outputPath.FileName == torrent.Name)
if (outputPath.FileName == torrent.Name)
{
item.OutputPath = outputPath;
}
@ -134,7 +138,9 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
}
// 'Started' without 'Queued' is when the torrent is 'forced seeding'
item.CanMoveFiles = item.CanBeRemoved = (!torrent.Status.HasFlag(UTorrentTorrentStatus.Queued) && !torrent.Status.HasFlag(UTorrentTorrentStatus.Started));
item.CanMoveFiles = item.CanBeRemoved =
!torrent.Status.HasFlag(UTorrentTorrentStatus.Queued) &&
!torrent.Status.HasFlag(UTorrentTorrentStatus.Started);
queueItems.Add(item);
}

@ -69,14 +69,14 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
return configuration;
}
public UTorrentResponse GetTorrents(string cacheID, UTorrentSettings settings)
public UTorrentResponse GetTorrents(string cacheId, UTorrentSettings settings)
{
var requestBuilder = BuildRequest(settings)
.AddQueryParam("list", 1);
if (cacheID.IsNotNullOrWhiteSpace())
if (cacheId.IsNotNullOrWhiteSpace())
{
requestBuilder.AddQueryParam("cid", cacheID);
requestBuilder.AddQueryParam("cid", cacheId);
}
var result = ProcessRequest(requestBuilder, settings);
@ -99,17 +99,19 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
.Post()
.AddQueryParam("action", "add-file")
.AddQueryParam("path", string.Empty)
.AddFormUpload("torrent_file", fileName, fileContent, @"application/octet-stream");
.AddFormUpload("torrent_file", fileName, fileContent);
ProcessRequest(requestBuilder, settings);
}
public void SetTorrentSeedingConfiguration(string hash, TorrentSeedConfiguration seedConfiguration, UTorrentSettings settings)
{
if (seedConfiguration == null) return;
var requestBuilder = BuildRequest(settings)
.AddQueryParam("action", "setprops")
.AddQueryParam("hash", hash);
requestBuilder.AddQueryParam("s", "seed_override")
.AddQueryParam("v", 1);

@ -15,6 +15,7 @@ namespace NzbDrone.Core.Download
public long TotalSize { get; set; }
public long RemainingSize { get; set; }
public TimeSpan? RemainingTime { get; set; }
public double? SeedRatio { get; set; }
public OsPath OutputPath { get; set; }
public string Message { get; set; }

@ -5,6 +5,7 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Common.Instrumentation.Extensions;
using NzbDrone.Common.TPL;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.Indexers;
@ -26,6 +27,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,
@ -33,6 +35,7 @@ namespace NzbDrone.Core.Download
IIndexerStatusService indexerStatusService,
IRateLimitService rateLimitService,
IEventAggregator eventAggregator,
ISeedConfigProvider seedConfigProvider,
Logger logger)
{
_downloadClientProvider = downloadClientProvider;
@ -40,6 +43,7 @@ namespace NzbDrone.Core.Download
_indexerStatusService = indexerStatusService;
_rateLimitService = rateLimitService;
_eventAggregator = eventAggregator;
_seedConfigProvider = seedConfigProvider;
_logger = logger;
}
@ -56,6 +60,9 @@ namespace NzbDrone.Core.Download
throw new DownloadClientUnavailableException($"{remoteEpisode.Release.DownloadProtocol} Download client isn't configured yet");
}
// Get the seed configuration for this release.
remoteEpisode.SeedConfiguration = _seedConfigProvider.GetSeedConfiguration(remoteEpisode.Release);
// Limit grabs to 2 per second.
if (remoteEpisode.Release.DownloadUrl.IsNotNullOrWhiteSpace() && !remoteEpisode.Release.DownloadUrl.StartsWith("magnet:"))
{

@ -47,6 +47,9 @@ namespace NzbDrone.Core.Indexers.BitMeTv
[FieldDefinition(4, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
public int MinimumSeeders { get; set; }
[FieldDefinition(5, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default", Advanced = true)]
public double? SeedRatio { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

@ -32,6 +32,9 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
[FieldDefinition(2, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
public int MinimumSeeders { get; set; }
[FieldDefinition(3, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default", Advanced = true)]
public double? SeedRatio { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

@ -35,6 +35,9 @@ namespace NzbDrone.Core.Indexers.HDBits
[FieldDefinition(3, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
public int MinimumSeeders { get; set; }
[FieldDefinition(4, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default", Advanced = true)]
public double? SeedRatio { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

@ -2,7 +2,6 @@
using FluentValidation;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.IPTorrents
@ -36,6 +35,9 @@ namespace NzbDrone.Core.Indexers.IPTorrents
[FieldDefinition(1, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
public int MinimumSeeders { get; set; }
[FieldDefinition(2, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default", Advanced = true)]
public double? SeedRatio { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

@ -3,5 +3,7 @@
public interface ITorrentIndexerSettings : IIndexerSettings
{
int MinimumSeeders { get; set; }
double? SeedRatio { get; set; }
}
}

@ -2,6 +2,7 @@
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Validation;
using System.Text.RegularExpressions;
namespace NzbDrone.Core.Indexers.Nyaa
{
public class NyaaSettingsValidator : AbstractValidator<NyaaSettings>
@ -33,6 +34,9 @@ namespace NzbDrone.Core.Indexers.Nyaa
[FieldDefinition(2, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
public int MinimumSeeders { get; set; }
[FieldDefinition(3, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default", Advanced = true)]
public double? SeedRatio { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

@ -35,6 +35,9 @@ namespace NzbDrone.Core.Indexers.Rarbg
[FieldDefinition(3, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
public int MinimumSeeders { get; set; }
[FieldDefinition(4, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default", Advanced = true)]
public double? SeedRatio { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

@ -35,6 +35,9 @@ namespace NzbDrone.Core.Indexers.TorrentRss
[FieldDefinition(3, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
public int MinimumSeeders { get; set; }
[FieldDefinition(4, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default", Advanced = true)]
public double? SeedRatio { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(validator.Validate(this));

@ -32,6 +32,9 @@ namespace NzbDrone.Core.Indexers.Torrentleech
[FieldDefinition(2, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
public int MinimumSeeders { get; set; }
[FieldDefinition(3, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default", Advanced = true)]
public double? SeedRatio { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

@ -60,6 +60,9 @@ namespace NzbDrone.Core.Indexers.Torznab
[FieldDefinition(6, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
public int MinimumSeeders { get; set; }
[FieldDefinition(7, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default", Advanced = true)]
public double? SeedRatio { get; set; }
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

@ -142,7 +142,9 @@
<Compile Include="Configuration\Events\ConfigSavedEvent.cs" />
<Compile Include="Configuration\IConfigService.cs" />
<Compile Include="Configuration\InvalidConfigFileException.cs" />
<Compile Include="Configuration\ISeedConfigProvider.cs" />
<Compile Include="Configuration\ResetApiKeyCommand.cs" />
<Compile Include="Configuration\SeedConfigProvider.cs" />
<Compile Include="DataAugmentation\DailySeries\DailySeries.cs" />
<Compile Include="DataAugmentation\DailySeries\DailySeriesDataProxy.cs" />
<Compile Include="DataAugmentation\DailySeries\DailySeriesService.cs" />

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Parser.Model
@ -12,6 +13,7 @@ namespace NzbDrone.Core.Parser.Model
public Series Series { get; set; }
public List<Episode> Episodes { get; set; }
public bool DownloadAllowed { get; set; }
public TorrentSeedConfiguration SeedConfiguration { get; set; }
public bool IsRecentEpisode()
{
@ -23,4 +25,4 @@ namespace NzbDrone.Core.Parser.Model
return Release.Title;
}
}
}
}

Loading…
Cancel
Save