mirror of
https://github.com/Cleanuparr/Cleanuparr.git
synced 2026-05-08 23:03:13 -04:00
Add paused and queued Deluge states for Download Cleaner (#596)
This commit is contained in:
@@ -1,27 +1,31 @@
|
||||
using Newtonsoft.Json;
|
||||
using Cleanuparr.Domain.Enums;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Cleanuparr.Domain.Entities.Deluge.Response;
|
||||
|
||||
public sealed record DownloadStatus
|
||||
{
|
||||
public string? Hash { get; init; }
|
||||
|
||||
public string? State { get; init; }
|
||||
|
||||
|
||||
public DelugeState State { get; init; }
|
||||
|
||||
public string? Name { get; init; }
|
||||
|
||||
|
||||
public ulong Eta { get; init; }
|
||||
|
||||
|
||||
[JsonProperty("download_payload_rate")]
|
||||
public long DownloadSpeed { get; init; }
|
||||
|
||||
|
||||
public bool Private { get; init; }
|
||||
|
||||
|
||||
[JsonProperty("total_size")]
|
||||
public long Size { get; init; }
|
||||
|
||||
|
||||
[JsonProperty("total_done")]
|
||||
public long TotalDone { get; init; }
|
||||
|
||||
[JsonProperty("is_finished")]
|
||||
public bool IsFinished { get; init; }
|
||||
|
||||
public string? Label { get; set; }
|
||||
|
||||
|
||||
20
code/backend/Cleanuparr.Domain/Enums/DelugeState.cs
Normal file
20
code/backend/Cleanuparr.Domain/Enums/DelugeState.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Cleanuparr.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Torrent state values reported by Deluge
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(DelugeStateConverter))]
|
||||
public enum DelugeState
|
||||
{
|
||||
Unknown = 0,
|
||||
Allocating,
|
||||
Checking,
|
||||
Downloading,
|
||||
Seeding,
|
||||
Paused,
|
||||
Error,
|
||||
Queued,
|
||||
Moving,
|
||||
}
|
||||
26
code/backend/Cleanuparr.Domain/Enums/DelugeStateConverter.cs
Normal file
26
code/backend/Cleanuparr.Domain/Enums/DelugeStateConverter.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Cleanuparr.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Maps Deluge wire state strings to <see cref="DelugeState"/>, falling back to <see cref="DelugeState.Unknown"/> for any value not present in the enum
|
||||
/// </summary>
|
||||
public sealed class DelugeStateConverter : JsonConverter<DelugeState>
|
||||
{
|
||||
public override DelugeState ReadJson(JsonReader reader, Type objectType, DelugeState existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType != JsonToken.String || reader.Value is not string raw)
|
||||
{
|
||||
return DelugeState.Unknown;
|
||||
}
|
||||
|
||||
return Enum.TryParse<DelugeState>(raw, ignoreCase: true, out var parsed)
|
||||
? parsed
|
||||
: DelugeState.Unknown;
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, DelugeState value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteValue(value.ToString());
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Cleanuparr.Domain.Entities.Deluge.Response;
|
||||
using Cleanuparr.Domain.Enums;
|
||||
using Cleanuparr.Infrastructure.Features.DownloadClient.Deluge;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
@@ -399,13 +400,11 @@ public class DelugeItemWrapperTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Downloading", true)]
|
||||
[InlineData("downloading", true)]
|
||||
[InlineData("DOWNLOADING", true)]
|
||||
[InlineData("Seeding", false)]
|
||||
[InlineData("Paused", false)]
|
||||
[InlineData(null, false)]
|
||||
public void IsDownloading_ReturnsCorrectValue(string? state, bool expected)
|
||||
[InlineData(DelugeState.Downloading, true)]
|
||||
[InlineData(DelugeState.Seeding, false)]
|
||||
[InlineData(DelugeState.Paused, false)]
|
||||
[InlineData(DelugeState.Unknown, false)]
|
||||
public void IsDownloading_ReturnsCorrectValue(DelugeState state, bool expected)
|
||||
{
|
||||
// Arrange
|
||||
var downloadStatus = new DownloadStatus
|
||||
@@ -424,14 +423,14 @@ public class DelugeItemWrapperTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Downloading", 0, 0UL, true)] // Downloading with no speed and no ETA = stalled
|
||||
[InlineData("Downloading", 1000, 0UL, false)] // Has download speed = not stalled
|
||||
[InlineData("Downloading", 0, 100UL, false)] // Has ETA = not stalled
|
||||
[InlineData("Downloading", 1000, 100UL, false)] // Has both = not stalled
|
||||
[InlineData("Seeding", 0, 0UL, false)] // Not downloading state = not stalled
|
||||
[InlineData("Paused", 0, 0UL, false)] // Not downloading state = not stalled
|
||||
[InlineData(null, 0, 0UL, false)] // Null state = not stalled
|
||||
public void IsStalled_ReturnsCorrectValue(string? state, long downloadSpeed, ulong eta, bool expected)
|
||||
[InlineData(DelugeState.Downloading, 0, 0UL, true)]
|
||||
[InlineData(DelugeState.Downloading, 1000, 0UL, false)]
|
||||
[InlineData(DelugeState.Downloading, 0, 100UL, false)]
|
||||
[InlineData(DelugeState.Downloading, 1000, 100UL, false)]
|
||||
[InlineData(DelugeState.Seeding, 0, 0UL, false)]
|
||||
[InlineData(DelugeState.Paused, 0, 0UL, false)]
|
||||
[InlineData(DelugeState.Unknown, 0, 0UL, false)]
|
||||
public void IsStalled_ReturnsCorrectValue(DelugeState state, long downloadSpeed, ulong eta, bool expected)
|
||||
{
|
||||
// Arrange
|
||||
var downloadStatus = new DownloadStatus
|
||||
|
||||
@@ -34,9 +34,9 @@ public class DelugeServiceDCTests : IClassFixture<DelugeServiceFixture>
|
||||
|
||||
var downloads = new List<DownloadStatus>
|
||||
{
|
||||
new DownloadStatus { Hash = "hash1", Name = "Torrent 1", State = "Seeding", Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" },
|
||||
new DownloadStatus { Hash = "hash2", Name = "Torrent 2", State = "Downloading", Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" },
|
||||
new DownloadStatus { Hash = "hash3", Name = "Torrent 3", State = "Seeding", Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" }
|
||||
new DownloadStatus { Hash = "hash1", Name = "Torrent 1", State = DelugeState.Seeding, Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" },
|
||||
new DownloadStatus { Hash = "hash2", Name = "Torrent 2", State = DelugeState.Downloading, Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" },
|
||||
new DownloadStatus { Hash = "hash3", Name = "Torrent 3", State = DelugeState.Seeding, Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" }
|
||||
};
|
||||
|
||||
_fixture.ClientWrapper
|
||||
@@ -51,29 +51,6 @@ public class DelugeServiceDCTests : IClassFixture<DelugeServiceFixture>
|
||||
foreach (var item in result) { item.Hash.ShouldNotBeNull(); }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IsCaseInsensitive()
|
||||
{
|
||||
// Arrange
|
||||
var sut = _fixture.CreateSut();
|
||||
|
||||
var downloads = new List<DownloadStatus>
|
||||
{
|
||||
new DownloadStatus { Hash = "hash1", Name = "Torrent 1", State = "SEEDING", Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" },
|
||||
new DownloadStatus { Hash = "hash2", Name = "Torrent 2", State = "seeding", Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" }
|
||||
};
|
||||
|
||||
_fixture.ClientWrapper
|
||||
.GetStatusForAllTorrents()
|
||||
.Returns(downloads);
|
||||
|
||||
// Act
|
||||
var result = await sut.GetSeedingDownloads();
|
||||
|
||||
// Assert
|
||||
result.Count.ShouldBe(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReturnsEmptyList_WhenNull()
|
||||
{
|
||||
@@ -99,8 +76,121 @@ public class DelugeServiceDCTests : IClassFixture<DelugeServiceFixture>
|
||||
|
||||
var downloads = new List<DownloadStatus>
|
||||
{
|
||||
new DownloadStatus { Hash = "", Name = "No Hash", State = "Seeding", Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" },
|
||||
new DownloadStatus { Hash = "hash1", Name = "Valid Hash", State = "Seeding", Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" }
|
||||
new DownloadStatus { Hash = "", Name = "No Hash", State = DelugeState.Seeding, Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" },
|
||||
new DownloadStatus { Hash = "hash1", Name = "Valid Hash", State = DelugeState.Seeding, Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" }
|
||||
};
|
||||
|
||||
_fixture.ClientWrapper
|
||||
.GetStatusForAllTorrents()
|
||||
.Returns(downloads);
|
||||
|
||||
// Act
|
||||
var result = await sut.GetSeedingDownloads();
|
||||
|
||||
// Assert
|
||||
result.ShouldHaveSingleItem();
|
||||
result[0].Hash.ShouldBe("hash1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IncludesPausedFinishedTorrents()
|
||||
{
|
||||
// Arrange
|
||||
var sut = _fixture.CreateSut();
|
||||
|
||||
var downloads = new List<DownloadStatus>
|
||||
{
|
||||
new DownloadStatus { Hash = "hash1", Name = "Paused finished", State = DelugeState.Paused, IsFinished = true, Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" }
|
||||
};
|
||||
|
||||
_fixture.ClientWrapper
|
||||
.GetStatusForAllTorrents()
|
||||
.Returns(downloads);
|
||||
|
||||
// Act
|
||||
var result = await sut.GetSeedingDownloads();
|
||||
|
||||
// Assert
|
||||
result.ShouldHaveSingleItem();
|
||||
result[0].Hash.ShouldBe("hash1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IncludesQueuedFinishedTorrents()
|
||||
{
|
||||
// Arrange
|
||||
var sut = _fixture.CreateSut();
|
||||
|
||||
var downloads = new List<DownloadStatus>
|
||||
{
|
||||
new DownloadStatus { Hash = "hash1", Name = "Queued finished", State = DelugeState.Queued, IsFinished = true, Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" }
|
||||
};
|
||||
|
||||
_fixture.ClientWrapper
|
||||
.GetStatusForAllTorrents()
|
||||
.Returns(downloads);
|
||||
|
||||
// Act
|
||||
var result = await sut.GetSeedingDownloads();
|
||||
|
||||
// Assert
|
||||
result.ShouldHaveSingleItem();
|
||||
result[0].Hash.ShouldBe("hash1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExcludesPausedNotFinished()
|
||||
{
|
||||
// Arrange
|
||||
var sut = _fixture.CreateSut();
|
||||
|
||||
var downloads = new List<DownloadStatus>
|
||||
{
|
||||
new DownloadStatus { Hash = "hash1", Name = "Paused mid-download", State = DelugeState.Paused, IsFinished = false, Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" }
|
||||
};
|
||||
|
||||
_fixture.ClientWrapper
|
||||
.GetStatusForAllTorrents()
|
||||
.Returns(downloads);
|
||||
|
||||
// Act
|
||||
var result = await sut.GetSeedingDownloads();
|
||||
|
||||
// Assert
|
||||
result.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExcludesQueuedNotFinished()
|
||||
{
|
||||
// Arrange
|
||||
var sut = _fixture.CreateSut();
|
||||
|
||||
var downloads = new List<DownloadStatus>
|
||||
{
|
||||
new DownloadStatus { Hash = "hash1", Name = "Queued mid-download", State = DelugeState.Queued, IsFinished = false, Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" }
|
||||
};
|
||||
|
||||
_fixture.ClientWrapper
|
||||
.GetStatusForAllTorrents()
|
||||
.Returns(downloads);
|
||||
|
||||
// Act
|
||||
var result = await sut.GetSeedingDownloads();
|
||||
|
||||
// Assert
|
||||
result.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IncludesSeedingRegardlessOfIsFinished()
|
||||
{
|
||||
// Arrange
|
||||
var sut = _fixture.CreateSut();
|
||||
|
||||
var downloads = new List<DownloadStatus>
|
||||
{
|
||||
new DownloadStatus { Hash = "hash1", Name = "Seeding without IsFinished flag", State = DelugeState.Seeding, IsFinished = false, Private = false, Trackers = new List<Tracker>(), DownloadLocation = "/downloads" }
|
||||
};
|
||||
|
||||
_fixture.ClientWrapper
|
||||
|
||||
@@ -51,7 +51,7 @@ public class DelugeServiceTests : IClassFixture<DelugeServiceFixture>
|
||||
{
|
||||
Hash = hash,
|
||||
Name = "Test Torrent",
|
||||
State = "Downloading",
|
||||
State = DelugeState.Downloading,
|
||||
Private = true,
|
||||
DownloadSpeed = 1000,
|
||||
Trackers = new List<Tracker>(),
|
||||
@@ -96,7 +96,7 @@ public class DelugeServiceTests : IClassFixture<DelugeServiceFixture>
|
||||
{
|
||||
Hash = hash,
|
||||
Name = "Test Torrent",
|
||||
State = "Downloading",
|
||||
State = DelugeState.Downloading,
|
||||
Private = false,
|
||||
DownloadSpeed = 1000,
|
||||
Trackers = new List<Tracker>(),
|
||||
@@ -148,7 +148,7 @@ public class DelugeServiceTests : IClassFixture<DelugeServiceFixture>
|
||||
{
|
||||
Hash = hash,
|
||||
Name = "Test Torrent",
|
||||
State = "Downloading",
|
||||
State = DelugeState.Downloading,
|
||||
Private = false,
|
||||
DownloadSpeed = 1000,
|
||||
Trackers = new List<Tracker>(),
|
||||
@@ -187,7 +187,7 @@ public class DelugeServiceTests : IClassFixture<DelugeServiceFixture>
|
||||
{
|
||||
Hash = hash,
|
||||
Name = "Test Torrent",
|
||||
State = "Downloading",
|
||||
State = DelugeState.Downloading,
|
||||
Private = false,
|
||||
DownloadSpeed = 1000,
|
||||
Trackers = new List<Tracker>(),
|
||||
@@ -239,7 +239,7 @@ public class DelugeServiceTests : IClassFixture<DelugeServiceFixture>
|
||||
{
|
||||
Hash = hash,
|
||||
Name = "Test Torrent",
|
||||
State = "Downloading",
|
||||
State = DelugeState.Downloading,
|
||||
Private = false,
|
||||
DownloadSpeed = 1000,
|
||||
Trackers = new List<Tracker>(),
|
||||
@@ -267,7 +267,7 @@ public class DelugeServiceTests : IClassFixture<DelugeServiceFixture>
|
||||
{
|
||||
Hash = hash,
|
||||
Name = "Test Torrent",
|
||||
State = "Downloading",
|
||||
State = DelugeState.Downloading,
|
||||
Private = false,
|
||||
DownloadSpeed = 1000,
|
||||
Label = category,
|
||||
@@ -296,7 +296,7 @@ public class DelugeServiceTests : IClassFixture<DelugeServiceFixture>
|
||||
{
|
||||
Hash = hash,
|
||||
Name = "Test Torrent",
|
||||
State = "Downloading",
|
||||
State = DelugeState.Downloading,
|
||||
Private = false,
|
||||
DownloadSpeed = 1000,
|
||||
Trackers = new List<Tracker>
|
||||
@@ -333,7 +333,7 @@ public class DelugeServiceTests : IClassFixture<DelugeServiceFixture>
|
||||
{
|
||||
Hash = hash,
|
||||
Name = "Test Torrent",
|
||||
State = "Seeding",
|
||||
State = DelugeState.Seeding,
|
||||
Private = false,
|
||||
DownloadSpeed = 0,
|
||||
Trackers = new List<Tracker>(),
|
||||
@@ -374,7 +374,7 @@ public class DelugeServiceTests : IClassFixture<DelugeServiceFixture>
|
||||
{
|
||||
Hash = hash,
|
||||
Name = "Test Torrent",
|
||||
State = "Downloading",
|
||||
State = DelugeState.Downloading,
|
||||
Private = false,
|
||||
DownloadSpeed = 0,
|
||||
Trackers = new List<Tracker>(),
|
||||
@@ -422,7 +422,7 @@ public class DelugeServiceTests : IClassFixture<DelugeServiceFixture>
|
||||
{
|
||||
Hash = hash,
|
||||
Name = "Test Torrent",
|
||||
State = "Downloading",
|
||||
State = DelugeState.Downloading,
|
||||
Private = false,
|
||||
DownloadSpeed = 1000,
|
||||
Trackers = new List<Tracker>(),
|
||||
@@ -464,7 +464,7 @@ public class DelugeServiceTests : IClassFixture<DelugeServiceFixture>
|
||||
{
|
||||
Hash = hash,
|
||||
Name = "Test Torrent",
|
||||
State = "Downloading",
|
||||
State = DelugeState.Downloading,
|
||||
DownloadSpeed = 0,
|
||||
Eta = 0,
|
||||
Private = false,
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
using Cleanuparr.Domain.Entities.Deluge.Response;
|
||||
using Cleanuparr.Domain.Enums;
|
||||
using Newtonsoft.Json;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace Cleanuparr.Infrastructure.Tests.Features.DownloadClient;
|
||||
|
||||
public class DownloadStatusDeserializationTests
|
||||
{
|
||||
private const string BaseDelugePayload = """
|
||||
{
|
||||
"hash": "abc123",
|
||||
"name": "Some Torrent",
|
||||
"eta": 0,
|
||||
"private": false,
|
||||
"total_size": 1024,
|
||||
"total_done": 1024,
|
||||
"is_finished": true,
|
||||
"label": "movies",
|
||||
"seeding_time": 0,
|
||||
"ratio": 1.0,
|
||||
"trackers": [],
|
||||
"download_payload_rate": 0,
|
||||
"download_location": "/downloads"
|
||||
}
|
||||
""";
|
||||
|
||||
[Fact]
|
||||
public void UnknownStateValue_DeserializesToUnknown_AndPreservesOtherFields()
|
||||
{
|
||||
var json = BaseDelugePayload.Replace("\"hash\": \"abc123\",", "\"hash\": \"abc123\", \"state\": \"FutureNewState\",");
|
||||
|
||||
var result = JsonConvert.DeserializeObject<DownloadStatus>(json);
|
||||
|
||||
result.ShouldNotBeNull();
|
||||
result.State.ShouldBe(DelugeState.Unknown);
|
||||
result.Hash.ShouldBe("abc123");
|
||||
result.IsFinished.ShouldBeTrue();
|
||||
result.Size.ShouldBe(1024L);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Seeding")]
|
||||
[InlineData("seeding")]
|
||||
[InlineData("SEEDING")]
|
||||
public void KnownState_DeserializesCaseInsensitively(string wireValue)
|
||||
{
|
||||
var json = BaseDelugePayload.Replace("\"hash\": \"abc123\",", $"\"hash\": \"abc123\", \"state\": \"{wireValue}\",");
|
||||
|
||||
var result = JsonConvert.DeserializeObject<DownloadStatus>(json);
|
||||
|
||||
result.ShouldNotBeNull();
|
||||
result.State.ShouldBe(DelugeState.Seeding);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MissingStateField_DeserializesToUnknown()
|
||||
{
|
||||
var result = JsonConvert.DeserializeObject<DownloadStatus>(BaseDelugePayload);
|
||||
|
||||
result.ShouldNotBeNull();
|
||||
result.State.ShouldBe(DelugeState.Unknown);
|
||||
result.Hash.ShouldBe("abc123");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NullStateField_DeserializesToUnknown()
|
||||
{
|
||||
var json = BaseDelugePayload.Replace("\"hash\": \"abc123\",", "\"hash\": \"abc123\", \"state\": null,");
|
||||
|
||||
var result = JsonConvert.DeserializeObject<DownloadStatus>(json);
|
||||
|
||||
result.ShouldNotBeNull();
|
||||
result.State.ShouldBe(DelugeState.Unknown);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public sealed class DelugeClient
|
||||
"eta",
|
||||
"private",
|
||||
"total_done",
|
||||
"is_finished",
|
||||
"label",
|
||||
"seeding_time",
|
||||
"ratio",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Cleanuparr.Domain.Entities;
|
||||
using Cleanuparr.Domain.Entities.Deluge.Response;
|
||||
using Cleanuparr.Domain.Enums;
|
||||
using Cleanuparr.Infrastructure.Services;
|
||||
|
||||
namespace Cleanuparr.Infrastructure.Features.DownloadClient.Deluge;
|
||||
@@ -58,9 +59,9 @@ public sealed class DelugeItemWrapper : ITorrentItemWrapper
|
||||
|
||||
public IReadOnlyList<string> Tags => Array.Empty<string>();
|
||||
|
||||
public bool IsDownloading() => Info.State?.Equals("Downloading", StringComparison.InvariantCultureIgnoreCase) == true;
|
||||
|
||||
public bool IsStalled() => Info.State?.Equals("Downloading", StringComparison.InvariantCultureIgnoreCase) == true && Info is { DownloadSpeed: <= 0, Eta: <= 0 };
|
||||
public bool IsDownloading() => Info is { State: DelugeState.Downloading };
|
||||
|
||||
public bool IsStalled() => Info is { State: DelugeState.Downloading, DownloadSpeed: <= 0, Eta: <= 0 };
|
||||
|
||||
public bool IsIgnored(IReadOnlyList<string> ignoredDownloads)
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ public partial class DelugeService
|
||||
|
||||
return downloads
|
||||
.Where(x => !string.IsNullOrEmpty(x.Hash))
|
||||
.Where(x => x.State?.Equals("seeding", StringComparison.InvariantCultureIgnoreCase) is true)
|
||||
.Where(x => x.State is DelugeState.Seeding || x is { IsFinished: true, State: DelugeState.Paused or DelugeState.Queued })
|
||||
.Select(ITorrentItemWrapper (x) => new DelugeItemWrapper(x))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user