Skip to content

Commit

Permalink
New: Remove qBitorrent torrents that reach inactive seeding time
Browse files Browse the repository at this point in the history
(cherry picked from commit d738035fed859eb475051f3df494b9c975a42e82)
  • Loading branch information
c4181 authored and mynameisbogdan committed Apr 28, 2024
1 parent a735ecc commit 5f248aa
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ protected void GivenHighPriority()
Subject.Definition.Settings.As<QBittorrentSettings>().RecentMusicPriority = (int)QBittorrentPriority.First;
}

protected void GivenGlobalSeedLimits(float maxRatio, int maxSeedingTime = -1, QBittorrentMaxRatioAction maxRatioAction = QBittorrentMaxRatioAction.Pause)
protected void GivenGlobalSeedLimits(float maxRatio, int maxSeedingTime = -1, int maxInactiveSeedingTime = -1, QBittorrentMaxRatioAction maxRatioAction = QBittorrentMaxRatioAction.Pause)
{
Mocker.GetMock<IQBittorrentProxy>()
.Setup(s => s.GetConfig(It.IsAny<QBittorrentSettings>()))
Expand All @@ -118,7 +118,9 @@ protected void GivenGlobalSeedLimits(float maxRatio, int maxSeedingTime = -1, QB
MaxRatio = maxRatio,
MaxRatioEnabled = maxRatio >= 0,
MaxSeedingTime = maxSeedingTime,
MaxSeedingTimeEnabled = maxSeedingTime >= 0
MaxSeedingTimeEnabled = maxSeedingTime >= 0,
MaxInactiveSeedingTime = maxInactiveSeedingTime,
MaxInactiveSeedingTimeEnabled = maxInactiveSeedingTime >= 0
});
}

Expand Down Expand Up @@ -609,7 +611,9 @@ public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio
float ratio = 0.1f,
float ratioLimit = -2,
int seedingTime = 1,
int seedingTimeLimit = -2)
int seedingTimeLimit = -2,
int inactiveSeedingTimeLimit = -2,
long lastActivity = -1)
{
var torrent = new QBittorrentTorrent
{
Expand All @@ -623,7 +627,9 @@ public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio
SavePath = "",
Ratio = ratio,
RatioLimit = ratioLimit,
SeedingTimeLimit = seedingTimeLimit
SeedingTimeLimit = seedingTimeLimit,
InactiveSeedingTimeLimit = inactiveSeedingTimeLimit,
LastActivity = lastActivity == -1 ? DateTimeOffset.UtcNow.ToUnixTimeSeconds() : lastActivity
};

GivenTorrents(new List<QBittorrentTorrent>() { torrent });
Expand Down Expand Up @@ -737,6 +743,50 @@ public void should_not_be_removable_if_overridden_max_seedingtime_not_reached_an
item.CanMoveFiles.Should().BeFalse();
}

[Test]
public void should_not_be_removable_and_should_not_allow_move_files_if_max_inactive_seedingtime_reached_and_not_paused()
{
GivenGlobalSeedLimits(-1, maxInactiveSeedingTime: 20);
GivenCompletedTorrent("uploading", ratio: 2.0f, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(25)).ToUnixTimeSeconds());

var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}

[Test]
public void should_be_removable_and_should_allow_move_files_if_max_inactive_seedingtime_reached_and_paused()
{
GivenGlobalSeedLimits(-1, maxInactiveSeedingTime: 20);
GivenCompletedTorrent("pausedUP", ratio: 2.0f, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(25)).ToUnixTimeSeconds());

var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}

[Test]
public void should_be_removable_and_should_allow_move_files_if_overridden_max_inactive_seedingtime_reached_and_paused()
{
GivenGlobalSeedLimits(-1, maxInactiveSeedingTime: 40);
GivenCompletedTorrent("pausedUP", ratio: 2.0f, seedingTime: 20, inactiveSeedingTimeLimit: 10, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(15)).ToUnixTimeSeconds());

var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}

[Test]
public void should_not_be_removable_if_overridden_max_inactive_seedingtime_not_reached_and_paused()
{
GivenGlobalSeedLimits(-1, maxInactiveSeedingTime: 20);
GivenCompletedTorrent("pausedUP", ratio: 2.0f, seedingTime: 30, inactiveSeedingTimeLimit: 40, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(30)).ToUnixTimeSeconds());

var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}

[Test]
public void should_be_removable_and_should_allow_move_files_if_max_seedingtime_reached_but_ratio_not_and_paused()
{
Expand All @@ -748,6 +798,17 @@ public void should_be_removable_and_should_allow_move_files_if_max_seedingtime_r
item.CanMoveFiles.Should().BeTrue();
}

[Test]
public void should_be_removable_and_should_allow_move_files_if_max_inactive_seedingtime_reached_but_ratio_not_and_paused()
{
GivenGlobalSeedLimits(2.0f, maxInactiveSeedingTime: 20);
GivenCompletedTorrent("pausedUP", ratio: 1.0f, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(25)).ToUnixTimeSeconds());

var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}

[Test]
public void should_not_fetch_details_twice()
{
Expand Down
22 changes: 21 additions & 1 deletion src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ protected bool HasReachedSeedLimit(QBittorrentTorrent torrent, QBittorrentPrefer
}
}

if (HasReachedSeedingTimeLimit(torrent, config))
if (HasReachedSeedingTimeLimit(torrent, config) || HasReachedInactiveSeedingTimeLimit(torrent, config))
{
return true;
}
Expand Down Expand Up @@ -693,6 +693,26 @@ protected bool HasReachedSeedingTimeLimit(QBittorrentTorrent torrent, QBittorren
return false;
}

protected bool HasReachedInactiveSeedingTimeLimit(QBittorrentTorrent torrent, QBittorrentPreferences config)
{
long inactiveSeedingTimeLimit;

if (torrent.InactiveSeedingTimeLimit >= 0)
{
inactiveSeedingTimeLimit = torrent.InactiveSeedingTimeLimit * 60;
}
else if (torrent.InactiveSeedingTimeLimit == -2 && config.MaxInactiveSeedingTimeEnabled)
{
inactiveSeedingTimeLimit = config.MaxInactiveSeedingTime * 60;
}
else
{
return false;
}

return DateTimeOffset.UtcNow.ToUnixTimeSeconds() - torrent.LastActivity > inactiveSeedingTimeLimit;
}

protected void FetchTorrentDetails(QBittorrentTorrent torrent)
{
var torrentProperties = Proxy.GetTorrentProperties(torrent.Hash, Settings);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ public class QBittorrentPreferences
[JsonProperty(PropertyName = "max_seeding_time")]
public long MaxSeedingTime { get; set; } // Get the global share time limit in minutes

[JsonProperty(PropertyName = "max_inactive_seeding_time_enabled")]
public bool MaxInactiveSeedingTimeEnabled { get; set; } // True if share inactive time limit is enabled

[JsonProperty(PropertyName = "max_inactive_seeding_time")]
public long MaxInactiveSeedingTime { get; set; } // Get the global share inactive time limit in minutes

[JsonProperty(PropertyName = "max_ratio_act")]
public QBittorrentMaxRatioAction MaxRatioAction { get; set; } // Action performed when a torrent reaches the maximum share ratio.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ public class QBittorrentTorrent

[JsonProperty(PropertyName = "seeding_time_limit")] // Per torrent seeding time limit (-2 = use global, -1 = unlimited)
public long SeedingTimeLimit { get; set; } = -2;

[JsonProperty(PropertyName = "inactive_seeding_time_limit")] // Per torrent inactive seeding time limit (-2 = use global, -1 = unlimited)
public long InactiveSeedingTimeLimit { get; set; } = -2;

[JsonProperty(PropertyName = "last_activity")] // Timestamp in unix seconds when a chunk was last downloaded/uploaded
public long LastActivity { get; set; }
}

public class QBittorrentTorrentProperties
Expand Down

0 comments on commit 5f248aa

Please sign in to comment.