Skip to content

Commit

Permalink
Added support for inactive seeding time limit.
Browse files Browse the repository at this point in the history
  • Loading branch information
fedarovich committed Dec 15, 2023
1 parent 4e969f3 commit 5fb3d6a
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -509,8 +509,16 @@ public class Seeding : SettingsCommand<SeedingViewModel>
[Range(-1, int.MaxValue)]
public int? MaxSeedingTime { get; set; }

[Option("-a|--action <ACTION>", "Action to perform when maximal ratio or seeding time limit is reached (Pause|Remove)",
CommandOptionType.SingleValue)]
[Option("-I|--max-inactive-seeding-time-enabled <BOOL>", "Enable/disable maximal inactive seeding time limit", CommandOptionType.SingleValue)]
[MinApiVersion("2.9.2", "\"max-inactive-seeding-time-enabled\" option requires qBittorrent 4.6.0 or later.")]
public bool? MaxInactiveSeedingTimeEnabled { get; set; }

[Option("-i|--max-inactive-seeding-time <MINUTES>", "Maximal inactive seeding time in minutes", CommandOptionType.SingleValue)]
[Range(-1, int.MaxValue)]
[MinApiVersion("2.9.2", "\"max-inactive-seeding-time-enabled\" option requires qBittorrent 4.6.0 or later.")]
public int? MaxInactiveSeedingTime { get; set; }

[Option("-a|--action <ACTION>", "Action to perform when maximal ratio or seeding time limit is reached (Pause|Remove)", CommandOptionType.SingleValue)]
public MaxRatioAction? MaxRatioAction { get; set; }
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Threading.Tasks;
using McMaster.Extensions.CommandLineUtils;
Expand All @@ -27,6 +26,10 @@ public class Share : TorrentSpecificFormattableCommandBase<TorrentShareViewModel
[ShareSeedingTimeLimitValidation]
public string SeedingTimeLimit { get; set; }

[Option("-i|--inactive-seeding-time-limit <VALUE>", "Set the inactive seeding time limit ([d.]HH:mm[:ss]|GLOBAL|NONE). Requires qBittorrent 4.6.0 or later.", CommandOptionType.SingleValue)]
[ShareSeedingTimeLimitValidation]
public string InactiveSeedingTimeLimit { get; set; }

protected override async Task<int> OnExecuteTorrentSpecificAsync(QBittorrentClient client, CommandLineApplication app, IConsole console)
{
var partialData = await client.GetPartialDataAsync();
Expand All @@ -38,12 +41,31 @@ protected override async Task<int> OnExecuteTorrentSpecificAsync(QBittorrentClie

var ratioLimit = GetRatioLimit();
var seedingTimeLimit = GetSeedingTimeLimit();
var inactiveSeedingTimeLimit = GetInactiveSeedingTimeLimit();

if (ratioLimit != null || seedingTimeLimit != null)
var apiVersion = await client.GetApiVersionAsync();

if (ratioLimit != null || seedingTimeLimit != null || inactiveSeedingTimeLimit != null)
{
await client.SetShareLimitsAsync(Hash,
ratioLimit ?? info.RatioLimit ?? ShareLimits.Ratio.Global,
seedingTimeLimit ?? info.SeedingTimeLimit ?? ShareLimits.SeedingTime.Global);
if (apiVersion < new ApiVersion(2, 9, 2))
{
if (inactiveSeedingTimeLimit != null)
{
console.WriteLineColored("The option --inactive-seeding-time-limit requires qBittorrent 4.6.0 or later.", ColorScheme.Current.Warning);
}

await client.SetShareLimitsAsync(Hash,
ratioLimit ?? info.RatioLimit ?? ShareLimits.Ratio.Global,
seedingTimeLimit ?? info.SeedingTimeLimit ?? ShareLimits.SeedingTime.Global);
}
else
{
await client.SetShareLimitsAsync(Hash,
ratioLimit ?? info.RatioLimit ?? ShareLimits.Ratio.Global,
seedingTimeLimit ?? info.SeedingTimeLimit ?? ShareLimits.SeedingTime.Global,
inactiveSeedingTimeLimit ?? info.InactiveSeedingTimeLimit ?? ShareLimits.SeedingTime.Global);
}

return ExitCodes.Success;
}

Expand All @@ -55,7 +77,8 @@ await client.SetShareLimitsAsync(Hash,
_customFormatters = new Dictionary<string, Func<object, object>>
{
[nameof(viewModel.RatioLimit)] = FormatRatioLimit,
[nameof(viewModel.SeedingTimeLimit)] = FormatSeedingTimeLimit
[nameof(viewModel.SeedingTimeLimit)] = FormatSeedingTimeLimit,
[nameof(viewModel.InactiveSeedingTimeLimit)] = FormatInactiveSeedingTimeLimit
};
Print(viewModel);

Expand All @@ -82,7 +105,19 @@ object FormatSeedingTimeLimit(object arg)
var time = arg as TimeSpan?;
if (time == ShareLimits.SeedingTime.Global)
{
var globalValue = global.MaxSeedingTime >= 0 ? global.MaxSeedingTime.Value.ToString() : "None";
var globalValue = global.MaxSeedingTime >= 0 ? TimeSpan.FromMinutes(global.MaxSeedingTime.Value).ToString() : "None";
return $"Global ({globalValue})";
}

return time == ShareLimits.SeedingTime.Unlimited ? "None" : time?.ToString();
}

object FormatInactiveSeedingTimeLimit(object arg)
{
var time = arg as TimeSpan?;
if (time == ShareLimits.SeedingTime.Global)
{
var globalValue = global.MaxInactiveSeedingTime >= 0 ? TimeSpan.FromMinutes(global.MaxInactiveSeedingTime.Value).ToString() : "None";
return $"Global ({globalValue})";
}

Expand All @@ -103,7 +138,7 @@ object FormatSeedingTimeLimit(object arg)
if (double.TryParse(RatioLimit, NumberStyles.Float, CultureInfo.InvariantCulture, out var ratioLimit))
return ratioLimit;

return double.TryParse(RatioLimit, out ratioLimit) ? ratioLimit : (double?) null;
return double.TryParse(RatioLimit, out ratioLimit) ? ratioLimit : null;
}

private TimeSpan? GetSeedingTimeLimit()
Expand All @@ -114,7 +149,18 @@ object FormatSeedingTimeLimit(object arg)
if ("NONE".Equals(SeedingTimeLimit, StringComparison.OrdinalIgnoreCase))
return ShareLimits.SeedingTime.Unlimited;

return TimeSpan.TryParse(SeedingTimeLimit, out var seedingTimeLimit) ? seedingTimeLimit : (TimeSpan?)null;
return TimeSpan.TryParse(SeedingTimeLimit, out var seedingTimeLimit) ? seedingTimeLimit : null;
}

private TimeSpan? GetInactiveSeedingTimeLimit()
{
if ("GLOBAL".Equals(InactiveSeedingTimeLimit, StringComparison.OrdinalIgnoreCase))
return ShareLimits.SeedingTime.Global;

if ("NONE".Equals(InactiveSeedingTimeLimit, StringComparison.OrdinalIgnoreCase))
return ShareLimits.SeedingTime.Unlimited;

return TimeSpan.TryParse(InactiveSeedingTimeLimit, out var inactiveSeedingTimeLimit) ? inactiveSeedingTimeLimit : null;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NJsonSchema" Version="9.14.1" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.8" />
<PackageReference Include="QBittorrent.Client" Version="1.9.23348.2" />
<PackageReference Include="QBittorrent.Client" Version="1.9.23349.1" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="5.0.0" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
using System.ComponentModel.DataAnnotations;
using QBittorrent.Client;

namespace QBittorrent.CommandLineInterface.ViewModels.ServerPreferences
Expand Down Expand Up @@ -29,6 +26,13 @@ public SeedingViewModel(Preferences wrappedObject)
[DisplayFormat(DataFormatString = "{0:0 minutes;None;None}")]
public int? MaxSeedingTime => _wrappedObject.MaxSeedingTime;

[Display(Name = "Maximal inactive seeding time enabled")]
public bool? MaxInactiveSeedingTimeEnabled => _wrappedObject.MaxInactiveSeedingTimeEnabled;

[Display(Name = "Maximal inactive seeding time")]
[DisplayFormat(DataFormatString = "{0:0 minutes;None;None}")]
public int? MaxInactiveSeedingTime => _wrappedObject.MaxInactiveSeedingTime;

[Display(Name = "Action on limit reached")]
public MaxRatioAction? MaxRatioAction => _wrappedObject.MaxRatioAction;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
using BencodeNET.Torrents;
using QBittorrent.Client;

namespace QBittorrent.CommandLineInterface.ViewModels
Expand Down Expand Up @@ -32,5 +29,9 @@ public TorrentShareViewModel(TorrentProperties properties, TorrentPartialInfo wr
[Display(Name = "Seeding time limit")]
[DisplayFormat(NullDisplayText = "n/a")]
public TimeSpan? SeedingTimeLimit => _partialInfo.SeedingTimeLimit;

[Display(Name = "Inactive seeding time limit")]
[DisplayFormat(NullDisplayText = "n/a")]
public TimeSpan? InactiveSeedingTimeLimit => _partialInfo.InactiveSeedingTimeLimit;
}
}

0 comments on commit 5fb3d6a

Please sign in to comment.