mirror of
https://github.com/Sonarr/Sonarr
synced 2025-12-06 08:28:37 +01:00
New: Indexer option for Season Pack Seed Ratio
This commit is contained in:
parent
71553ad67b
commit
bd20ebfad7
6 changed files with 174 additions and 5 deletions
|
|
@ -59,6 +59,7 @@ public void should_not_return_config_for_invalid_indexer()
|
||||||
public void should_return_season_time_for_season_packs()
|
public void should_return_season_time_for_season_packs()
|
||||||
{
|
{
|
||||||
var settings = new TorznabSettings();
|
var settings = new TorznabSettings();
|
||||||
|
settings.SeedCriteria.SeasonPackSeedGoal = (int)SeasonPackSeedGoal.UseSeasonPackSeedGoal;
|
||||||
settings.SeedCriteria.SeasonPackSeedTime = 10;
|
settings.SeedCriteria.SeasonPackSeedTime = 10;
|
||||||
|
|
||||||
Mocker.GetMock<ICachedIndexerSettingsProvider>()
|
Mocker.GetMock<ICachedIndexerSettingsProvider>()
|
||||||
|
|
@ -85,5 +86,71 @@ public void should_return_season_time_for_season_packs()
|
||||||
result.Should().NotBeNull();
|
result.Should().NotBeNull();
|
||||||
result.SeedTime.Should().Be(TimeSpan.FromMinutes(10));
|
result.SeedTime.Should().Be(TimeSpan.FromMinutes(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_season_ratio_for_season_packs_when_set()
|
||||||
|
{
|
||||||
|
var settings = new TorznabSettings();
|
||||||
|
settings.SeedCriteria.SeasonPackSeedGoal = (int)SeasonPackSeedGoal.UseSeasonPackSeedGoal;
|
||||||
|
settings.SeedCriteria.SeedRatio = 1.0;
|
||||||
|
settings.SeedCriteria.SeasonPackSeedRatio = 10.0;
|
||||||
|
|
||||||
|
Mocker.GetMock<ICachedIndexerSettingsProvider>()
|
||||||
|
.Setup(v => v.GetSettings(It.IsAny<int>()))
|
||||||
|
.Returns(new CachedIndexerSettings
|
||||||
|
{
|
||||||
|
FailDownloads = new HashSet<FailDownloads> { FailDownloads.Executables },
|
||||||
|
SeedCriteriaSettings = settings.SeedCriteria
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = Subject.GetSeedConfiguration(new RemoteEpisode
|
||||||
|
{
|
||||||
|
Release = new ReleaseInfo
|
||||||
|
{
|
||||||
|
DownloadProtocol = DownloadProtocol.Torrent,
|
||||||
|
IndexerId = 1
|
||||||
|
},
|
||||||
|
ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
|
{
|
||||||
|
FullSeason = true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.Ratio.Should().Be(10.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_standard_ratio_for_season_packs_when_not_set()
|
||||||
|
{
|
||||||
|
var settings = new TorznabSettings();
|
||||||
|
settings.SeedCriteria.SeasonPackSeedGoal = (int)SeasonPackSeedGoal.UseStandardSeedGoal;
|
||||||
|
settings.SeedCriteria.SeedRatio = 1.0;
|
||||||
|
settings.SeedCriteria.SeasonPackSeedRatio = 10.0;
|
||||||
|
|
||||||
|
Mocker.GetMock<ICachedIndexerSettingsProvider>()
|
||||||
|
.Setup(v => v.GetSettings(It.IsAny<int>()))
|
||||||
|
.Returns(new CachedIndexerSettings
|
||||||
|
{
|
||||||
|
FailDownloads = new HashSet<FailDownloads> { FailDownloads.Executables },
|
||||||
|
SeedCriteriaSettings = settings.SeedCriteria
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = Subject.GetSeedConfiguration(new RemoteEpisode
|
||||||
|
{
|
||||||
|
Release = new ReleaseInfo
|
||||||
|
{
|
||||||
|
DownloadProtocol = DownloadProtocol.Torrent,
|
||||||
|
IndexerId = 1
|
||||||
|
},
|
||||||
|
ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
|
{
|
||||||
|
FullSeason = true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.Ratio.Should().Be(1.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using Dapper;
|
||||||
|
using FluentMigrator;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(229)]
|
||||||
|
public class enable_season_pack_seeding_goal : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Execute.WithConnection(SetSeasonPackSeedingGoal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetSeasonPackSeedingGoal(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
var updatedIndexers = new List<object>();
|
||||||
|
|
||||||
|
using var selectCommand = conn.CreateCommand();
|
||||||
|
|
||||||
|
selectCommand.Transaction = tran;
|
||||||
|
selectCommand.CommandText = "SELECT * FROM \"Indexers\"";
|
||||||
|
|
||||||
|
using var reader = selectCommand.ExecuteReader();
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
var idIndex = reader.GetOrdinal("Id");
|
||||||
|
var settingsIndex = reader.GetOrdinal("Settings");
|
||||||
|
|
||||||
|
var id = reader.GetInt32(idIndex);
|
||||||
|
var settings = Json.Deserialize<Dictionary<string, object>>(reader.GetString(settingsIndex));
|
||||||
|
|
||||||
|
if (settings.TryGetValue("seedCriteria", out var seedCriteriaToken) && seedCriteriaToken is JObject seedCriteria)
|
||||||
|
{
|
||||||
|
if (seedCriteria?["seasonPackSeedTime"] != null)
|
||||||
|
{
|
||||||
|
seedCriteria["seasonPackSeedGoal"] = 1;
|
||||||
|
|
||||||
|
if (seedCriteria["seedRatio"] != null)
|
||||||
|
{
|
||||||
|
seedCriteria["seasonPackSeedRatio"] = seedCriteria["seedRatio"];
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedIndexers.Add(new
|
||||||
|
{
|
||||||
|
Settings = settings.ToJson(),
|
||||||
|
Id = id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedIndexers.Any())
|
||||||
|
{
|
||||||
|
var updateSql = "UPDATE \"Indexers\" SET \"Settings\" = @Settings WHERE \"Id\" = @Id";
|
||||||
|
conn.Execute(updateSql, updatedIndexers, transaction: tran);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/NzbDrone.Core/Indexers/SeasonPackSeedGoal.cs
Normal file
11
src/NzbDrone.Core/Indexers/SeasonPackSeedGoal.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
using NzbDrone.Core.Annotations;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Indexers;
|
||||||
|
|
||||||
|
public enum SeasonPackSeedGoal
|
||||||
|
{
|
||||||
|
[FieldOption(Label = "IndexerSettingsSeasonPackSeedGoalUseStandardGoals")]
|
||||||
|
UseStandardSeedGoal = 0,
|
||||||
|
[FieldOption(Label = "IndexerSettingsSeasonPackSeedGoalUseSeasonPackGoals")]
|
||||||
|
UseSeasonPackSeedGoal = 1
|
||||||
|
}
|
||||||
|
|
@ -49,12 +49,16 @@ public TorrentSeedConfiguration GetSeedConfiguration(int indexerId, bool fullSea
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var useSeasonPackSeedGoal = (SeasonPackSeedGoal)seedCriteria.SeasonPackSeedGoal == SeasonPackSeedGoal.UseSeasonPackSeedGoal;
|
||||||
|
|
||||||
var seedConfig = new TorrentSeedConfiguration
|
var seedConfig = new TorrentSeedConfiguration
|
||||||
{
|
{
|
||||||
Ratio = seedCriteria.SeedRatio
|
Ratio = (fullSeason && useSeasonPackSeedGoal)
|
||||||
|
? seedCriteria.SeasonPackSeedRatio
|
||||||
|
: seedCriteria.SeedRatio
|
||||||
};
|
};
|
||||||
|
|
||||||
var seedTime = fullSeason ? seedCriteria.SeasonPackSeedTime : seedCriteria.SeedTime;
|
var seedTime = (fullSeason && useSeasonPackSeedGoal) ? seedCriteria.SeasonPackSeedTime : seedCriteria.SeedTime;
|
||||||
if (seedTime.HasValue)
|
if (seedTime.HasValue)
|
||||||
{
|
{
|
||||||
seedConfig.SeedTime = TimeSpan.FromMinutes(seedTime.Value);
|
seedConfig.SeedTime = TimeSpan.FromMinutes(seedTime.Value);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,10 @@ public SeedCriteriaSettingsValidator(double seedRatioMinimum = 0.0, int seedTime
|
||||||
.When(c => c.SeedTime.HasValue)
|
.When(c => c.SeedTime.HasValue)
|
||||||
.AsWarning().WithMessage("Should be greater than zero");
|
.AsWarning().WithMessage("Should be greater than zero");
|
||||||
|
|
||||||
|
RuleFor(c => c.SeasonPackSeedRatio).GreaterThan(0.0)
|
||||||
|
.When(c => c.SeasonPackSeedRatio.HasValue)
|
||||||
|
.AsWarning().WithMessage("Should be greater than zero");
|
||||||
|
|
||||||
RuleFor(c => c.SeasonPackSeedTime).GreaterThan(0)
|
RuleFor(c => c.SeasonPackSeedTime).GreaterThan(0)
|
||||||
.When(c => c.SeasonPackSeedTime.HasValue)
|
.When(c => c.SeasonPackSeedTime.HasValue)
|
||||||
.AsWarning().WithMessage("Should be greater than zero");
|
.AsWarning().WithMessage("Should be greater than zero");
|
||||||
|
|
@ -27,6 +31,11 @@ public SeedCriteriaSettingsValidator(double seedRatioMinimum = 0.0, int seedTime
|
||||||
.When(c => c.SeedRatio > 0.0)
|
.When(c => c.SeedRatio > 0.0)
|
||||||
.AsWarning()
|
.AsWarning()
|
||||||
.WithMessage($"Under {seedRatioMinimum} leads to H&R");
|
.WithMessage($"Under {seedRatioMinimum} leads to H&R");
|
||||||
|
|
||||||
|
RuleFor(c => c.SeasonPackSeedRatio).GreaterThanOrEqualTo(seedRatioMinimum)
|
||||||
|
.When(c => c.SeasonPackSeedRatio > 0.0)
|
||||||
|
.AsWarning()
|
||||||
|
.WithMessage($"Under {seedRatioMinimum} leads to H&R");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seedTimeMinimum != 0)
|
if (seedTimeMinimum != 0)
|
||||||
|
|
@ -55,7 +64,13 @@ public class SeedCriteriaSettings : PropertywiseEquatable<SeedCriteriaSettings>
|
||||||
[FieldDefinition(1, Type = FieldType.Number, Label = "IndexerSettingsSeedTime", Unit = "minutes", HelpText = "IndexerSettingsSeedTimeHelpText", Advanced = true)]
|
[FieldDefinition(1, Type = FieldType.Number, Label = "IndexerSettingsSeedTime", Unit = "minutes", HelpText = "IndexerSettingsSeedTimeHelpText", Advanced = true)]
|
||||||
public int? SeedTime { get; set; }
|
public int? SeedTime { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(2, Type = FieldType.Number, Label = "Season-Pack Seed Time", Unit = "minutes", HelpText = "IndexerSettingsSeasonPackSeedTimeHelpText", Advanced = true)]
|
[FieldDefinition(2, Type = FieldType.Select, Label = "IndexerSettingsSeasonPackSeedGoal", SelectOptions = typeof(SeasonPackSeedGoal), HelpText = "IndexerSettingsSeasonPackSeedGoalHelpText", Advanced = true)]
|
||||||
|
public int SeasonPackSeedGoal { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(3, Type = FieldType.Number, Label = "IndexerSettingsSeasonPackSeedRatio", HelpText = "IndexerSettingsSeasonPackSeedRatioHelpText", Advanced = true)]
|
||||||
|
public double? SeasonPackSeedRatio { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(4, Type = FieldType.Number, Label = "IndexerSettingsSeasonPackSeedTime", Unit = "minutes", HelpText = "IndexerSettingsSeasonPackSeedTimeHelpText", Advanced = true)]
|
||||||
public int? SeasonPackSeedTime { get; set; }
|
public int? SeasonPackSeedTime { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1025,8 +1025,14 @@
|
||||||
"IndexerSettingsRejectBlocklistedTorrentHashesHelpText": "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.",
|
"IndexerSettingsRejectBlocklistedTorrentHashesHelpText": "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.",
|
||||||
"IndexerSettingsRssUrl": "RSS URL",
|
"IndexerSettingsRssUrl": "RSS URL",
|
||||||
"IndexerSettingsRssUrlHelpText": "Enter to URL to an {indexer} compatible RSS feed",
|
"IndexerSettingsRssUrlHelpText": "Enter to URL to an {indexer} compatible RSS feed",
|
||||||
"IndexerSettingsSeasonPackSeedTime": "Season-Pack Seed Time",
|
"IndexerSettingsSeasonPackSeedGoal": "Seeding Goal for Season Packs",
|
||||||
"IndexerSettingsSeasonPackSeedTimeHelpText": "The time a season-pack torrent should be seeded before stopping, empty uses the download client's default",
|
"IndexerSettingsSeasonPackSeedGoalHelpText": "Choose whether to use different seeding goals for season packs",
|
||||||
|
"IndexerSettingsSeasonPackSeedGoalUseStandardGoals": "Use Standard Goals",
|
||||||
|
"IndexerSettingsSeasonPackSeedGoalUseSeasonPackGoals": "Use Season Pack Goals",
|
||||||
|
"IndexerSettingsSeasonPackSeedRatio": "Season Pack Seed Ratio",
|
||||||
|
"IndexerSettingsSeasonPackSeedRatioHelpText": "The ratio a season pack torrent should reach before stopping, empty uses the download client's default. Ratio should be at least 1.0 and follow the indexers rules",
|
||||||
|
"IndexerSettingsSeasonPackSeedTime": "Season Pack Seed Time",
|
||||||
|
"IndexerSettingsSeasonPackSeedTimeHelpText": "The time a season pack torrent should be seeded before stopping, empty uses the download client's default",
|
||||||
"IndexerSettingsSeedRatio": "Seed Ratio",
|
"IndexerSettingsSeedRatio": "Seed Ratio",
|
||||||
"IndexerSettingsSeedRatioHelpText": "The ratio a torrent should reach before stopping, empty uses the download client's default. Ratio should be at least 1.0 and follow the indexers rules",
|
"IndexerSettingsSeedRatioHelpText": "The ratio a torrent should reach before stopping, empty uses the download client's default. Ratio should be at least 1.0 and follow the indexers rules",
|
||||||
"IndexerSettingsSeedTime": "Seed Time",
|
"IndexerSettingsSeedTime": "Seed Time",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue