Merge pull request #976 from ALenfant/antonin/fix_parallel_tests

fix(tests): restore parallel execution
This commit is contained in:
Roger Far 2026-05-25 20:21:39 -06:00 committed by GitHub
commit 0e00062992
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 635 additions and 443 deletions

View file

@ -21,4 +21,4 @@ jobs:
- name: Build
run: dotnet build --no-restore server
- name: Test
run: dotnet test --no-build --verbosity normal -maxcpucount:1 server
run: dotnet test --no-build --verbosity normal server

View file

@ -2,7 +2,6 @@ using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq;
using RdtClient.Data.Data;
using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.Internal;
using RdtClient.Service.BackgroundServices;
@ -17,6 +16,7 @@ public class WatchFolderCheckerTests : IDisposable
private readonly Mock<IServiceProvider> _serviceProviderMock;
private readonly Mock<IServiceScope> _serviceScopeMock;
private readonly String _testPath;
private readonly TestSettings _settings;
private readonly Mock<Torrents> _torrentsServiceMock;
public WatchFolderCheckerTests()
@ -25,7 +25,16 @@ public class WatchFolderCheckerTests : IDisposable
_serviceProviderMock = new();
_serviceScopeMock = new();
_scopeServiceProviderMock = new();
_torrentsServiceMock = new(null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!);
_settings = new(new DbSettings
{
Watch = new()
{
Interval = 0,
Default = new()
},
DownloadClient = new()
});
_torrentsServiceMock = new(null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, _settings, new TorrentRunnerState());
_serviceProviderMock
.Setup(x => x.GetService(typeof(IServiceScopeFactory)))
@ -42,10 +51,8 @@ public class WatchFolderCheckerTests : IDisposable
_testPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(_testPath);
// Reset Settings and Startup
SetStartupReady(true);
ResetSettings();
Settings.Get.Watch.Path = _testPath;
_settings.Current.Watch.Path = _testPath;
}
public void Dispose()
@ -62,22 +69,6 @@ public class WatchFolderCheckerTests : IDisposable
property?.SetValue(null, ready);
}
private static void ResetSettings()
{
var settings = new DbSettings
{
Watch = new()
{
Interval = 0,
Default = new()
},
DownloadClient = new()
};
var property = typeof(SettingData).GetProperty("Get", BindingFlags.Public | BindingFlags.Static);
property?.SetValue(null, settings);
}
private static void ResetPrevCheck(WatchFolderChecker checker)
{
var field = typeof(WatchFolderChecker).GetField("_prevCheck", BindingFlags.NonPublic | BindingFlags.Instance);
@ -92,7 +83,7 @@ public class WatchFolderCheckerTests : IDisposable
var content = "torrent content"u8.ToArray();
await File.WriteAllBytesAsync(filePath, content);
var checker = new WatchFolderChecker(_loggerMock.Object, _serviceProviderMock.Object);
var checker = new WatchFolderChecker(_loggerMock.Object, _serviceProviderMock.Object, _settings);
ResetPrevCheck(checker);
var cts = new CancellationTokenSource();
@ -131,7 +122,7 @@ public class WatchFolderCheckerTests : IDisposable
var content = "magnet:?xt=urn:btih:123";
await File.WriteAllTextAsync(filePath, content);
var checker = new WatchFolderChecker(_loggerMock.Object, _serviceProviderMock.Object);
var checker = new WatchFolderChecker(_loggerMock.Object, _serviceProviderMock.Object, _settings);
ResetPrevCheck(checker);
var cts = new CancellationTokenSource();
@ -170,7 +161,7 @@ public class WatchFolderCheckerTests : IDisposable
var content = "nzb content"u8.ToArray();
await File.WriteAllBytesAsync(filePath, content);
var checker = new WatchFolderChecker(_loggerMock.Object, _serviceProviderMock.Object);
var checker = new WatchFolderChecker(_loggerMock.Object, _serviceProviderMock.Object, _settings);
ResetPrevCheck(checker);
var cts = new CancellationTokenSource();
@ -209,7 +200,7 @@ public class WatchFolderCheckerTests : IDisposable
var filePath = Path.Combine(_testPath, "test.txt");
await File.WriteAllTextAsync(filePath, "ignore me");
var checker = new WatchFolderChecker(_loggerMock.Object, _serviceProviderMock.Object);
var checker = new WatchFolderChecker(_loggerMock.Object, _serviceProviderMock.Object, _settings);
ResetPrevCheck(checker);
var cts = new CancellationTokenSource();

View file

@ -1,3 +0,0 @@
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]

View file

@ -5,6 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<AssemblyName>RdtClient.Service.Test</AssemblyName>
<RootNamespace>RdtClient.Service.Test</RootNamespace>
</PropertyGroup>

View file

@ -3,6 +3,8 @@ using System.Text;
using Moq;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data;
using TestSettings = RdtClient.Service.Services.TestSettings;
using TorrentRunnerState = RdtClient.Service.Services.TorrentRunnerState;
using TorrentsService = RdtClient.Service.Services.Torrents;
namespace RdtClient.Service.Test.Services;
@ -28,7 +30,9 @@ public class NzbTorrentsTest
null!,
null!,
null!,
null!);
null!,
new TestSettings(),
new TorrentRunnerState());
}
[Fact]

View file

@ -1,7 +1,6 @@
using Microsoft.Extensions.Logging;
using Moq;
using System.Text.Json;
using RdtClient.Data.Data;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.DebridClient;
@ -14,15 +13,19 @@ public class QBittorrentTest
private readonly Mock<Authentication> _authenticationMock;
private readonly Mock<ILogger<QBittorrent>> _loggerMock;
private readonly QBittorrent _qBittorrent;
private readonly TestSettings _settings;
private readonly TorrentRunnerState _runnerState;
private readonly Mock<Torrents> _torrentsMock;
public QBittorrentTest()
{
_loggerMock = new();
_torrentsMock = new(null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!);
_settings = new();
_runnerState = new();
_torrentsMock = new(null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, _settings, _runnerState);
_authenticationMock = new(null!, null!, null!);
_qBittorrent = new(_loggerMock.Object, null!, _authenticationMock.Object, _torrentsMock.Object, null!);
_qBittorrent = new(_loggerMock.Object, _settings, _authenticationMock.Object, _torrentsMock.Object, null!, _runnerState);
}
[Fact]
@ -214,8 +217,8 @@ public class QBittorrentTest
public async Task TorrentInfo_ShouldUseSelectedTopLevelFileName_WhenRootFileAddsOnlyTheExtension()
{
// Arrange
var previousMappedPath = SettingData.Get.DownloadClient.MappedPath;
SettingData.Get.DownloadClient.MappedPath = "/data/downloads";
var previousMappedPath = _settings.Current.DownloadClient.MappedPath;
_settings.Current.DownloadClient.MappedPath = "/data/downloads";
try
{
@ -260,16 +263,16 @@ public class QBittorrentTest
}
finally
{
SettingData.Get.DownloadClient.MappedPath = previousMappedPath;
_settings.Current.DownloadClient.MappedPath = previousMappedPath;
}
}
[Fact]
public async Task TorrentInfo_ShouldUseExistingCompletedContentRoot_WhenSingleFileDirectoryDiffersFromRdName()
{
var previousMappedPath = SettingData.Get.DownloadClient.MappedPath;
var previousMappedPath = _settings.Current.DownloadClient.MappedPath;
var mappedPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
SettingData.Get.DownloadClient.MappedPath = mappedPath;
_settings.Current.DownloadClient.MappedPath = mappedPath;
try
{
@ -317,7 +320,7 @@ public class QBittorrentTest
}
finally
{
SettingData.Get.DownloadClient.MappedPath = previousMappedPath;
_settings.Current.DownloadClient.MappedPath = previousMappedPath;
if (Directory.Exists(mappedPath))
{
@ -329,9 +332,9 @@ public class QBittorrentTest
[Fact]
public async Task TorrentInfo_ShouldUseExistingCompletedContentRoot_WhenSelectedFileIsNestedUnderDifferentRoot()
{
var previousMappedPath = SettingData.Get.DownloadClient.MappedPath;
var previousMappedPath = _settings.Current.DownloadClient.MappedPath;
var mappedPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
SettingData.Get.DownloadClient.MappedPath = mappedPath;
_settings.Current.DownloadClient.MappedPath = mappedPath;
try
{
@ -382,7 +385,7 @@ public class QBittorrentTest
}
finally
{
SettingData.Get.DownloadClient.MappedPath = previousMappedPath;
_settings.Current.DownloadClient.MappedPath = previousMappedPath;
if (Directory.Exists(mappedPath))
{

View file

@ -1,6 +1,5 @@
using Microsoft.Extensions.Logging;
using Moq;
using RdtClient.Data.Data;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.Internal;
@ -16,11 +15,13 @@ public class SabnzbdTest
};
private readonly Mock<ILogger<Sabnzbd>> _loggerMock = new();
private readonly TestSettings _settings;
private readonly Mock<Torrents> _torrentsMock;
public SabnzbdTest()
{
_torrentsMock = new(null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!);
_settings = new();
_torrentsMock = new(null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, _settings, new TorrentRunnerState());
_torrentsMock.Setup(t => t.Get()).ReturnsAsync(new List<Torrent>());
}
@ -50,7 +51,7 @@ public class SabnzbdTest
_torrentsMock.Setup(t => t.Get()).ReturnsAsync(torrentList);
_torrentsMock.Setup(t => t.GetDownloadStats(It.IsAny<Guid>())).Returns((0, 1000, 500));
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings, _settings);
// Act
var result = await sabnzbd.GetQueue();
@ -90,7 +91,7 @@ public class SabnzbdTest
_torrentsMock.Setup(t => t.Get()).ReturnsAsync(torrentList);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings, _settings);
// Act
var result = await sabnzbd.GetQueue();
@ -134,7 +135,7 @@ public class SabnzbdTest
_torrentsMock.Setup(t => t.Get()).ReturnsAsync(torrentList);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings, _settings);
// Act
var result = await sabnzbd.GetQueue();
@ -186,7 +187,7 @@ public class SabnzbdTest
_torrentsMock.Setup(t => t.Get()).ReturnsAsync(torrentList);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings, _settings);
// Act
var result = await sabnzbd.GetQueue();
@ -224,7 +225,7 @@ public class SabnzbdTest
_torrentsMock.Setup(t => t.Get()).ReturnsAsync(torrentList);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings, _settings);
// Act
var result = await sabnzbd.GetQueue();
@ -260,7 +261,7 @@ public class SabnzbdTest
_torrentsMock.Setup(t => t.Get()).ReturnsAsync(torrentList);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings, _settings);
// Act
var result = await sabnzbd.GetHistory();
@ -275,7 +276,7 @@ public class SabnzbdTest
{
// Arrange
var savePath = @"C:\Downloads";
SettingData.Get.DownloadClient.MappedPath = savePath;
_settings.Current.DownloadClient.MappedPath = savePath;
var torrentList = new List<Torrent>
{
@ -292,7 +293,7 @@ public class SabnzbdTest
_torrentsMock.Setup(t => t.Get()).ReturnsAsync(torrentList);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings, _settings);
// Act
var result = await sabnzbd.GetHistory();
@ -308,7 +309,7 @@ public class SabnzbdTest
{
// Arrange
var savePath = @"C:\Downloads";
SettingData.Get.DownloadClient.MappedPath = savePath;
_settings.Current.DownloadClient.MappedPath = savePath;
var torrentList = new List<Torrent>
{
@ -325,7 +326,7 @@ public class SabnzbdTest
_torrentsMock.Setup(t => t.Get()).ReturnsAsync(torrentList);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings, _settings);
// Act
var result = await sabnzbd.GetHistory();
@ -355,7 +356,7 @@ public class SabnzbdTest
_torrentsMock.Setup(t => t.Get()).ReturnsAsync(torrentList);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings, _settings);
// Act
var result = await sabnzbd.GetHistory();
@ -369,7 +370,7 @@ public class SabnzbdTest
public void GetConfig_ShouldReturnCorrectConfig()
{
// Arrange
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings, _settings);
// Act
var result = sabnzbd.GetConfig();
@ -399,9 +400,9 @@ public class SabnzbdTest
_torrentsMock.Setup(t => t.Get()).ReturnsAsync(torrentList);
SettingData.Get.General.Categories = "TV, Music, *";
_settings.Current.General.Categories = "TV, Music, *";
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings);
var sabnzbd = new Sabnzbd(_loggerMock.Object, _torrentsMock.Object, _appSettings, _settings);
// Act
var result = sabnzbd.GetCategories();

View file

@ -8,30 +8,20 @@ using RdtClient.Service.Services.DebridClients;
namespace RdtClient.Service.Test.Services.TorrentClients;
[CollectionDefinition(nameof(PremiumizeSettingsCollection), DisableParallelization = true)]
public class PremiumizeSettingsCollection;
[Collection(nameof(PremiumizeSettingsCollection))]
public class PremiumizeDebridClientTest : IDisposable
public class PremiumizeDebridClientTest
{
private readonly Mock<IDownloadableFileFilter> _fileFilterMock;
private readonly Mock<IHttpClientFactory> _httpClientFactoryMock;
private readonly Mock<ILogger<PremiumizeDebridClient>> _loggerMock;
private readonly String _originalApiKey;
private readonly TestSettings _settings;
public PremiumizeDebridClientTest()
{
_loggerMock = new();
_httpClientFactoryMock = new();
_fileFilterMock = new();
_originalApiKey = Settings.Get.Provider.ApiKey ?? String.Empty;
Settings.Get.Provider.ApiKey = "test-api-key";
}
public void Dispose()
{
Settings.Get.Provider.ApiKey = _originalApiKey;
_settings = new();
_settings.Current.Provider.ApiKey = "test-api-key";
}
[Fact]
@ -208,7 +198,7 @@ public class PremiumizeDebridClientTest : IDisposable
{
_httpClientFactoryMock.Setup(m => m.CreateClient(It.IsAny<String>())).Returns(new HttpClient(handler));
return new(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object);
return new(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _settings);
}
private static HttpResponseMessage JsonResponse(String json, HttpStatusCode statusCode = HttpStatusCode.OK)

View file

@ -21,6 +21,7 @@ public class TorBoxDebridClientTest
private readonly Mock<IDownloadableFileFilter> _fileFilterMock;
private readonly Mock<IHttpClientFactory> _httpClientFactoryMock;
private readonly Mock<ILogger<TorBoxDebridClient>> _loggerMock;
private readonly TestSettings _settings;
public TorBoxDebridClientTest()
{
@ -28,12 +29,13 @@ public class TorBoxDebridClientTest
_httpClientFactoryMock = new();
_fileFilterMock = new();
_coordinatorMock = new();
_settings = new();
var httpClient = new HttpClient();
_httpClientFactoryMock.Setup(m => m.CreateClient(It.IsAny<String>())).Returns(httpClient);
Settings.Get.Provider.ApiKey = "test-api-key";
Settings.Get.Provider.Timeout = 100;
_settings.Current.Provider.ApiKey = "test-api-key";
_settings.Current.Provider.Timeout = 100;
}
[Fact]
@ -64,7 +66,7 @@ public class TorBoxDebridClientTest
}
};
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
clientMock.Protected().Setup<Task<IEnumerable<TorrentInfoResult>?>>("GetCurrentTorrents").ReturnsAsync(torrents);
clientMock.Protected().Setup<Task<IEnumerable<TorrentInfoResult>?>>("GetQueuedTorrents").ReturnsAsync(new List<TorrentInfoResult>());
clientMock.Protected().Setup<Task<IEnumerable<UsenetInfoResult>?>>("GetCurrentUsenet").ReturnsAsync(nzbs);
@ -114,7 +116,7 @@ public class TorBoxDebridClientTest
}
};
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
clientMock.Protected().Setup<Task<Response<List<AvailableTorrent?>>>>("GetTorrentAvailability", hash).ReturnsAsync(availability);
// Act
@ -157,7 +159,7 @@ public class TorBoxDebridClientTest
}
};
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
clientMock.Protected().Setup<Task<Response<List<AvailableTorrent?>>>>("GetTorrentAvailability", hash).ReturnsAsync(torrentAvailability);
clientMock.Protected().Setup<Task<Response<List<AvailableUsenet?>>>>("GetUsenetAvailability", hash).ReturnsAsync(usenetAvailability);
@ -186,7 +188,7 @@ public class TorBoxDebridClientTest
Data = new()
};
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
clientMock.Protected().Setup<Task<Response<List<AvailableTorrent?>>>>("GetTorrentAvailability", hash).ReturnsAsync(torrentAvailability);
clientMock.Protected().Setup<Task<Response<List<AvailableUsenet?>>>>("GetUsenetAvailability", hash).ReturnsAsync(usenetAvailability);
@ -208,7 +210,7 @@ public class TorBoxDebridClientTest
};
var torrentsApiMock = new Mock<ITorrentsApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
var torBoxClientMock = new Mock<ITorBoxNetClient>();
torBoxClientMock.Setup(m => m.Torrents).Returns(torrentsApiMock.Object);
@ -232,7 +234,7 @@ public class TorBoxDebridClientTest
};
var usenetApiMock = new Mock<IUsenetApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
var torBoxClientMock = new Mock<ITorBoxNetClient>();
torBoxClientMock.Setup(m => m.Usenet).Returns(usenetApiMock.Object);
@ -258,7 +260,7 @@ public class TorBoxDebridClientTest
var link = "https://torbox.app/d/123/456";
var torrentsApiMock = new Mock<ITorrentsApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
var torBoxClientMock = new Mock<ITorBoxNetClient>();
torBoxClientMock.Setup(m => m.Torrents).Returns(torrentsApiMock.Object);
@ -291,7 +293,7 @@ public class TorBoxDebridClientTest
var link = "https://torbox.app/d/123/456";
var usenetApiMock = new Mock<IUsenetApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
var torBoxClientMock = new Mock<ITorBoxNetClient>();
torBoxClientMock.Setup(m => m.Usenet).Returns(usenetApiMock.Object);
@ -323,7 +325,7 @@ public class TorBoxDebridClientTest
var name = "test-nzb";
var usenetApiMock = new Mock<IUsenetApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object)
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings)
{
CallBase = true
};
@ -377,7 +379,7 @@ public class TorBoxDebridClientTest
};
var torrentsApiMock = new Mock<ITorrentsApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
var torBoxClientMock = new Mock<ITorBoxNetClient>();
torBoxClientMock.Setup(m => m.Torrents).Returns(torrentsApiMock.Object);
@ -391,7 +393,7 @@ public class TorBoxDebridClientTest
_fileFilterMock.Setup(m => m.IsDownloadable(torrent, It.IsAny<String>(), It.IsAny<Int64>())).Returns(true);
Settings.Get.Provider.PreferZippedDownloads = false;
_settings.Current.Provider.PreferZippedDownloads = false;
// Act
var result = await clientMock.Object.GetDownloadInfos(torrent);
@ -425,10 +427,10 @@ public class TorBoxDebridClientTest
DownloadClient = DownloadClient.Aria2c
};
Settings.Get.Provider.PreferZippedDownloads = true;
_settings.Current.Provider.PreferZippedDownloads = true;
var torrentsApiMock = new Mock<ITorrentsApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
var torBoxClientMock = new Mock<ITorBoxNetClient>();
torBoxClientMock.Setup(m => m.Torrents).Returns(torrentsApiMock.Object);
@ -464,7 +466,7 @@ public class TorBoxDebridClientTest
var link = "https://torbox.app/fakedl/12345/6789";
var torrentsApiMock = new Mock<ITorrentsApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
var torBoxClientMock = new Mock<ITorBoxNetClient>();
torBoxClientMock.Setup(m => m.Torrents).Returns(torrentsApiMock.Object);
@ -496,7 +498,7 @@ public class TorBoxDebridClientTest
var link = "https://torbox.app/fakedl/12345/zip";
var torrentsApiMock = new Mock<ITorrentsApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
var torBoxClientMock = new Mock<ITorBoxNetClient>();
torBoxClientMock.Setup(m => m.Torrents).Returns(torrentsApiMock.Object);
@ -538,7 +540,7 @@ public class TorBoxDebridClientTest
};
var usenetApiMock = new Mock<IUsenetApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
var torBoxClientMock = new Mock<ITorBoxNetClient>();
torBoxClientMock.Setup(m => m.Usenet).Returns(usenetApiMock.Object);
@ -556,7 +558,7 @@ public class TorBoxDebridClientTest
_fileFilterMock.Setup(m => m.IsDownloadable(torrent, It.IsAny<String>(), It.IsAny<Int64>())).Returns(true);
Settings.Get.Provider.PreferZippedDownloads = false;
_settings.Current.Provider.PreferZippedDownloads = false;
// Act
var result = await clientMock.Object.GetDownloadInfos(torrent);
@ -579,7 +581,7 @@ public class TorBoxDebridClientTest
var link = "https://torbox.app/fakedl/98765/4321";
var usenetApiMock = new Mock<IUsenetApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
var torBoxClientMock = new Mock<ITorBoxNetClient>();
torBoxClientMock.Setup(m => m.Usenet).Returns(usenetApiMock.Object);
@ -607,7 +609,7 @@ public class TorBoxDebridClientTest
var torrentsApiMock = new Mock<ITorrentsApi>();
var userApiMock = new Mock<IUserApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object)
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings)
{
CallBase = true
};
@ -647,7 +649,7 @@ public class TorBoxDebridClientTest
var torrentsApiMock = new Mock<ITorrentsApi>();
var userApiMock = new Mock<IUserApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object)
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings)
{
CallBase = true
};
@ -685,7 +687,7 @@ public class TorBoxDebridClientTest
var torrentsApiMock = new Mock<ITorrentsApi>();
var userApiMock = new Mock<IUserApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object)
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings)
{
CallBase = true
};
@ -724,7 +726,7 @@ public class TorBoxDebridClientTest
var torrentsApiMock = new Mock<ITorrentsApi>();
var userApiMock = new Mock<IUserApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object)
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings)
{
CallBase = true
};
@ -767,7 +769,7 @@ public class TorBoxDebridClientTest
var torrentsApiMock = new Mock<ITorrentsApi>();
var userApiMock = new Mock<IUserApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object)
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings)
{
CallBase = true
};
@ -806,7 +808,7 @@ public class TorBoxDebridClientTest
var nzbLink = "https://example.com/test.nzb";
var usenetApiMock = new Mock<IUsenetApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object)
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings)
{
CallBase = true
};
@ -837,7 +839,7 @@ public class TorBoxDebridClientTest
var name = "test.nzb";
var usenetApiMock = new Mock<IUsenetApi>();
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object)
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings)
{
CallBase = true
};
@ -872,7 +874,7 @@ public class TorBoxDebridClientTest
Filename = "test-file"
};
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
// Act
var result = await clientMock.Object.UpdateData(torrent, torrentClientTorrent);
@ -898,7 +900,7 @@ public class TorBoxDebridClientTest
Filename = "test-torrent"
};
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
// Act
await clientMock.Object.UpdateData(torrent, torrentClientTorrent);
@ -929,7 +931,7 @@ public class TorBoxDebridClientTest
Filename = "test-torrent"
};
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object);
var clientMock = new Mock<TorBoxDebridClient>(_loggerMock.Object, _httpClientFactoryMock.Object, _fileFilterMock.Object, _coordinatorMock.Object, _settings);
// Act
var result = await clientMock.Object.UpdateData(torrent, torrentClientTorrent);

View file

@ -13,76 +13,63 @@ public class TorrentRunnerTest
[Fact]
public async Task Tick_ShouldNotRequeueCompletedErrorTorrent()
{
var originalApiKey = Settings.Get.Provider.ApiKey;
var originalProvider = Settings.Get.Provider.Provider;
var originalMaxParallelDownloads = Settings.Get.Provider.MaxParallelDownloads;
var originalDownloadPath = Settings.Get.DownloadClient.DownloadPath;
var testSettings = new TestSettings();
var runnerState = new TorrentRunnerState();
TorrentRunner.ActiveDownloadClients.Clear();
TorrentRunner.ActiveUnpackClients.Clear();
testSettings.Current.Provider.ApiKey = "test-api-key";
testSettings.Current.Provider.Provider = Provider.RealDebrid;
testSettings.Current.Provider.MaxParallelDownloads = 1;
testSettings.Current.DownloadClient.DownloadPath = "/downloads";
try
var erroredTorrent = new Torrent
{
Settings.Get.Provider.ApiKey = "test-api-key";
Settings.Get.Provider.Provider = Provider.RealDebrid;
Settings.Get.Provider.MaxParallelDownloads = 1;
Settings.Get.DownloadClient.DownloadPath = "/downloads";
TorrentId = Guid.NewGuid(),
Hash = "hash-1",
RdName = "Torrent 1",
FileOrMagnet = "magnet:?xt=urn:btih:hash-1",
Type = DownloadType.Torrent,
RdStatus = TorrentStatus.Queued,
DeleteOnError = 10,
Error = "Could not add to provider: Infringing file",
Completed = DateTimeOffset.UtcNow.AddMinutes(-5),
Downloads = new List<Download>()
};
var erroredTorrent = new Torrent
{
TorrentId = Guid.NewGuid(),
Hash = "hash-1",
RdName = "Torrent 1",
FileOrMagnet = "magnet:?xt=urn:btih:hash-1",
Type = DownloadType.Torrent,
RdStatus = TorrentStatus.Queued,
DeleteOnError = 10,
Error = "Could not add to provider: Infringing file",
Completed = DateTimeOffset.UtcNow.AddMinutes(-5),
Downloads = new List<Download>()
};
var torrentDataMock = new Mock<ITorrentData>(MockBehavior.Strict);
torrentDataMock.Setup(m => m.Get()).ReturnsAsync(new List<Torrent>
{
erroredTorrent
});
var torrents = new Torrents(Mock.Of<ILogger<Torrents>>(),
torrentDataMock.Object,
Mock.Of<IDownloads>(),
null!,
null!,
null!,
null!,
null!,
null!,
null!,
null!);
var torrentRunner = new TorrentRunner(Mock.Of<ILogger<TorrentRunner>>(),
torrents,
new(null!),
new(null!, torrents),
Mock.Of<IHttpClientFactory>(),
new RateLimitCoordinator());
await torrentRunner.Tick();
torrentDataMock.Verify(m => m.UpdateComplete(It.IsAny<Guid>(),
It.IsAny<String?>(),
It.IsAny<DateTimeOffset?>(),
It.IsAny<Boolean>()),
Times.Never);
}
finally
var torrentDataMock = new Mock<ITorrentData>(MockBehavior.Strict);
torrentDataMock.Setup(m => m.Get()).ReturnsAsync(new List<Torrent>
{
Settings.Get.Provider.ApiKey = originalApiKey;
Settings.Get.Provider.Provider = originalProvider;
Settings.Get.Provider.MaxParallelDownloads = originalMaxParallelDownloads;
Settings.Get.DownloadClient.DownloadPath = originalDownloadPath;
TorrentRunner.ActiveDownloadClients.Clear();
TorrentRunner.ActiveUnpackClients.Clear();
}
erroredTorrent
});
var torrents = new Torrents(Mock.Of<ILogger<Torrents>>(),
torrentDataMock.Object,
Mock.Of<IDownloads>(),
null!,
null!,
null!,
null!,
null!,
null!,
null!,
null!,
testSettings,
runnerState);
var torrentRunner = new TorrentRunner(Mock.Of<ILogger<TorrentRunner>>(),
torrents,
new(null!),
new(null!, torrents),
Mock.Of<IHttpClientFactory>(),
new RateLimitCoordinator(),
testSettings,
runnerState);
await torrentRunner.Tick();
torrentDataMock.Verify(m => m.UpdateComplete(It.IsAny<Guid>(),
It.IsAny<String?>(),
It.IsAny<DateTimeOffset?>(),
It.IsAny<Boolean>()),
Times.Never);
}
}
}

View file

@ -120,7 +120,9 @@ public class TorrentsTest
null!,
null!,
null!,
null!);
null!,
new TestSettings(),
new TorrentRunnerState());
mocks.ProcessMock.Setup(p => p.WaitForExit(It.IsAny<Int32>())).Returns(true);
@ -186,7 +188,9 @@ public class TorrentsTest
null!,
null!,
null!,
null!);
null!,
new TestSettings(),
new TorrentRunnerState());
//Act
await torrents.RunTorrentComplete(torrent.TorrentId, settings);
@ -234,7 +238,9 @@ public class TorrentsTest
null!,
null!,
null!,
null!);
null!,
new TestSettings(),
new TorrentRunnerState());
mocks.ProcessMock.Setup(p => p.WaitForExit(It.IsAny<Int32>()))
.Callback(() =>
@ -301,7 +307,9 @@ public class TorrentsTest
null!,
null!,
null!,
null!);
null!,
new TestSettings(),
new TorrentRunnerState());
mocks.ProcessMock.Setup(p => p.WaitForExit(It.IsAny<Int32>()))
.Callback(() =>
@ -364,7 +372,9 @@ public class TorrentsTest
null!,
null!,
null!,
null!);
null!,
new TestSettings(),
new TorrentRunnerState());
// Act
await torrents.AddNzbFileToDebridQueue(bytes, "filename.nzb", torrent);
@ -412,7 +422,9 @@ public class TorrentsTest
null!,
null!,
null!,
null!);
null!,
new TestSettings(),
new TorrentRunnerState());
// Act
await torrents.AddNzbLinkToDebridQueue(link, torrent);

View file

@ -0,0 +1,58 @@
using RdtClient.Data.Models.Internal;
namespace RdtClient.Service.Services;
internal sealed class TestSettings(DbSettings? settings = null) : ISettings
{
public DbSettings Current { get; } = settings ?? new();
public String DefaultSavePath
{
get
{
var downloadPath = Current.DownloadClient.MappedPath.TrimEnd('\\').TrimEnd('/');
return downloadPath + Path.DirectorySeparatorChar;
}
}
public IList<SettingProperty> GetAll()
{
return [];
}
public Task Update(IList<SettingProperty> settings)
{
return Task.CompletedTask;
}
public Task Update(String settingId, Object? value)
{
SetValue(Current, settingId.Split(':'), 0, value);
return Task.CompletedTask;
}
private static void SetValue(Object target, IReadOnlyList<String> path, Int32 index, Object? value)
{
var property = target.GetType().GetProperty(path[index]) ?? throw new($"Unknown setting {String.Join(":", path)}");
if (index < path.Count - 1)
{
SetValue(property.GetValue(target)!, path, index + 1, value);
return;
}
if (value == null)
{
property.SetValue(target, null);
return;
}
var propertyType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
var convertedValue = propertyType.IsEnum ? Enum.Parse(propertyType, value.ToString()!) : Convert.ChangeType(value, propertyType);
property.SetValue(target, convertedValue);
}
}

View file

@ -8,7 +8,7 @@ using DownloadClient = RdtClient.Data.Enums.DownloadClient;
namespace RdtClient.Service.BackgroundServices;
public class DiskSpaceMonitor(ILogger<DiskSpaceMonitor> logger, IServiceProvider serviceProvider) : BackgroundService
public class DiskSpaceMonitor(ILogger<DiskSpaceMonitor> logger, IServiceProvider serviceProvider, ISettings settings, ITorrentRunnerState runnerState) : BackgroundService
{
private static DiskSpaceStatus? _lastStatus;
private Boolean _isPausedForLowDiskSpace;
@ -34,7 +34,7 @@ public class DiskSpaceMonitor(ILogger<DiskSpaceMonitor> logger, IServiceProvider
{
try
{
var minimumFreeSpaceGB = Settings.Get.DownloadClient.MinimumFreeSpaceGB;
var minimumFreeSpaceGB = settings.Current.DownloadClient.MinimumFreeSpaceGB;
if (minimumFreeSpaceGB <= 0)
{
@ -43,14 +43,14 @@ public class DiskSpaceMonitor(ILogger<DiskSpaceMonitor> logger, IServiceProvider
continue;
}
var intervalMinutes = Settings.Get.DownloadClient.DiskSpaceCheckIntervalMinutes;
var intervalMinutes = settings.Current.DownloadClient.DiskSpaceCheckIntervalMinutes;
if (intervalMinutes < 1)
{
intervalMinutes = 1;
}
var downloadPath = Settings.Get.DownloadClient.DownloadPath;
var downloadPath = settings.Current.DownloadClient.DownloadPath;
logger.LogDebug($"Checking disk space for path: {downloadPath}");
if (!Directory.Exists(downloadPath))
@ -78,7 +78,7 @@ public class DiskSpaceMonitor(ILogger<DiskSpaceMonitor> logger, IServiceProvider
var pausedCount = 0;
foreach (var download in TorrentRunner.ActiveDownloadClients)
foreach (var download in runnerState.ActiveDownloadClients)
{
if (download.Value.Type == DownloadClient.Bezzad)
{
@ -90,7 +90,7 @@ public class DiskSpaceMonitor(ILogger<DiskSpaceMonitor> logger, IServiceProvider
logger.LogInformation($"Paused {pausedCount} active Bezzad downloads");
TorrentRunner.IsPausedForLowDiskSpace = true;
runnerState.IsPausedForLowDiskSpace = true;
_isPausedForLowDiskSpace = true;
var status = new DiskSpaceStatus
@ -125,7 +125,7 @@ public class DiskSpaceMonitor(ILogger<DiskSpaceMonitor> logger, IServiceProvider
var resumedCount = 0;
foreach (var download in TorrentRunner.ActiveDownloadClients)
foreach (var download in runnerState.ActiveDownloadClients)
{
if (download.Value.Type == DownloadClient.Bezzad)
{
@ -137,7 +137,7 @@ public class DiskSpaceMonitor(ILogger<DiskSpaceMonitor> logger, IServiceProvider
logger.LogInformation($"Resumed {resumedCount} Bezzad downloads");
TorrentRunner.IsPausedForLowDiskSpace = false;
runnerState.IsPausedForLowDiskSpace = false;
_isPausedForLowDiskSpace = false;
var status = new DiskSpaceStatus

View file

@ -7,7 +7,7 @@ using RdtClient.Service.Services;
namespace RdtClient.Service.BackgroundServices;
public class ProviderUpdater(ILogger<ProviderUpdater> logger, IServiceProvider serviceProvider) : BackgroundService
public class ProviderUpdater(ILogger<ProviderUpdater> logger, IServiceProvider serviceProvider, ISettings settings) : BackgroundService
{
private static DateTime _nextUpdate = DateTime.UtcNow;
@ -30,11 +30,11 @@ public class ProviderUpdater(ILogger<ProviderUpdater> logger, IServiceProvider s
{
var torrents = await torrentService.Get();
if (_nextUpdate < DateTime.UtcNow && (Settings.Get.Provider.AutoImport || torrents.Any(t => t.RdStatus != TorrentStatus.Finished) || RdtHub.HasConnections))
if (_nextUpdate < DateTime.UtcNow && (settings.Current.Provider.AutoImport || torrents.Any(t => t.RdStatus != TorrentStatus.Finished) || RdtHub.HasConnections))
{
logger.LogDebug($"Updating torrent info from debrid provider");
var updateTime = Settings.Get.Provider.CheckInterval * 3;
var updateTime = settings.Current.Provider.CheckInterval * 3;
if (updateTime < 30)
{
@ -43,7 +43,7 @@ public class ProviderUpdater(ILogger<ProviderUpdater> logger, IServiceProvider s
if (RdtHub.HasConnections)
{
updateTime = Settings.Get.Provider.CheckInterval;
updateTime = settings.Current.Provider.CheckInterval;
if (updateTime < 5)
{

View file

@ -8,7 +8,7 @@ using LogLevel = Microsoft.Extensions.Logging.LogLevel;
namespace RdtClient.Service.BackgroundServices;
public class WatchFolderChecker(ILogger<WatchFolderChecker> logger, IServiceProvider serviceProvider) : BackgroundService
public class WatchFolderChecker(ILogger<WatchFolderChecker> logger, IServiceProvider serviceProvider, ISettings settings) : BackgroundService
{
private DateTime _prevCheck = DateTime.MinValue;
@ -28,7 +28,7 @@ public class WatchFolderChecker(ILogger<WatchFolderChecker> logger, IServiceProv
{
try
{
var nextCheck = _prevCheck.AddSeconds(Math.Max(Settings.Get.Watch.Interval, 10));
var nextCheck = _prevCheck.AddSeconds(Math.Max(settings.Current.Watch.Interval, 10));
if (DateTime.Now < nextCheck)
{
@ -38,25 +38,25 @@ public class WatchFolderChecker(ILogger<WatchFolderChecker> logger, IServiceProv
_prevCheck = DateTime.Now;
if (String.IsNullOrWhiteSpace(Settings.Get.Watch.Path))
if (String.IsNullOrWhiteSpace(settings.Current.Watch.Path))
{
continue;
}
var processedStorePath = Path.Combine(Settings.Get.Watch.Path, "processed");
var errorStorePath = Path.Combine(Settings.Get.Watch.Path, "error");
var processedStorePath = Path.Combine(settings.Current.Watch.Path, "processed");
var errorStorePath = Path.Combine(settings.Current.Watch.Path, "error");
if (!String.IsNullOrWhiteSpace(Settings.Get.Watch.ProcessedPath))
if (!String.IsNullOrWhiteSpace(settings.Current.Watch.ProcessedPath))
{
processedStorePath = Settings.Get.Watch.ProcessedPath;
processedStorePath = settings.Current.Watch.ProcessedPath;
}
if (!String.IsNullOrWhiteSpace(Settings.Get.Watch.ErrorPath))
if (!String.IsNullOrWhiteSpace(settings.Current.Watch.ErrorPath))
{
errorStorePath = Settings.Get.Watch.ErrorPath;
errorStorePath = settings.Current.Watch.ErrorPath;
}
var torrentFiles = Directory.GetFiles(Settings.Get.Watch.Path, "*.*", SearchOption.TopDirectoryOnly);
var torrentFiles = Directory.GetFiles(settings.Current.Watch.Path, "*.*", SearchOption.TopDirectoryOnly);
foreach (var torrentFile in torrentFiles)
{
@ -78,22 +78,22 @@ public class WatchFolderChecker(ILogger<WatchFolderChecker> logger, IServiceProv
var torrent = new Torrent
{
DownloadClient = Settings.Get.DownloadClient.Client,
Category = Settings.Get.Watch.Default.Category,
HostDownloadAction = Settings.Get.Watch.Default.HostDownloadAction,
FinishedActionDelay = Settings.Get.Watch.Default.FinishedActionDelay,
DownloadAction = Settings.Get.Watch.Default.OnlyDownloadAvailableFiles
DownloadClient = settings.Current.DownloadClient.Client,
Category = settings.Current.Watch.Default.Category,
HostDownloadAction = settings.Current.Watch.Default.HostDownloadAction,
FinishedActionDelay = settings.Current.Watch.Default.FinishedActionDelay,
DownloadAction = settings.Current.Watch.Default.OnlyDownloadAvailableFiles
? TorrentDownloadAction.DownloadAvailableFiles
: TorrentDownloadAction.DownloadAll,
FinishedAction = Settings.Get.Watch.Default.FinishedAction,
DownloadMinSize = Settings.Get.Watch.Default.MinFileSize,
IncludeRegex = Settings.Get.Watch.Default.IncludeRegex,
ExcludeRegex = Settings.Get.Watch.Default.ExcludeRegex,
TorrentRetryAttempts = Settings.Get.Watch.Default.TorrentRetryAttempts,
DownloadRetryAttempts = Settings.Get.Watch.Default.DownloadRetryAttempts,
DeleteOnError = Settings.Get.Watch.Default.DeleteOnError,
Lifetime = Settings.Get.Watch.Default.TorrentLifetime,
Priority = Settings.Get.Watch.Default.Priority > 0 ? Settings.Get.Watch.Default.Priority : null
FinishedAction = settings.Current.Watch.Default.FinishedAction,
DownloadMinSize = settings.Current.Watch.Default.MinFileSize,
IncludeRegex = settings.Current.Watch.Default.IncludeRegex,
ExcludeRegex = settings.Current.Watch.Default.ExcludeRegex,
TorrentRetryAttempts = settings.Current.Watch.Default.TorrentRetryAttempts,
DownloadRetryAttempts = settings.Current.Watch.Default.DownloadRetryAttempts,
DeleteOnError = settings.Current.Watch.Default.DeleteOnError,
Lifetime = settings.Current.Watch.Default.TorrentLifetime,
Priority = settings.Current.Watch.Default.Priority > 0 ? settings.Current.Watch.Default.Priority : null
};
if (fileInfo.Extension == ".torrent")

View file

@ -30,6 +30,7 @@ public static class DiConfig
services.AddScoped<AllDebridDebridClient>();
services.AddSingleton<IRateLimitCoordinator, RateLimitCoordinator>();
services.AddSingleton<ITorrentRunnerState>(TorrentRunner.SharedState);
services.AddSingleton<IProcessFactory, ProcessFactory>();
services.AddSingleton<IFileSystem, FileSystem>();
@ -41,7 +42,8 @@ public static class DiConfig
services.AddScoped<Sabnzbd>();
services.AddScoped<RemoteService>();
services.AddScoped<RealDebridDebridClient>();
services.AddScoped<Settings>();
services.AddSingleton<Settings>();
services.AddSingleton<ISettings>(serviceProvider => serviceProvider.GetRequiredService<Settings>());
services.AddScoped<TorBoxDebridClient>();
services.AddScoped<Torrents>();
services.AddScoped<TorrentRunner>();
@ -51,7 +53,7 @@ public static class DiConfig
services.AddSingleton<ITrackerListGrabber, TrackerListGrabber>();
services.AddSingleton<IEnricher, Enricher>();
services.AddSingleton<IAuthorizationHandler, AuthSettingHandler>();
services.AddScoped<IAuthorizationHandler, AuthSettingHandler>();
services.AddScoped<IAuthorizationHandler, SabnzbdHandler>();
services.AddHostedService<DiskSpaceMonitor>();

View file

@ -8,7 +8,7 @@ public class AuthSettingRequirement : IAuthorizationRequirement
{
}
public class AuthSettingHandler : AuthorizationHandler<AuthSettingRequirement>
public class AuthSettingHandler(ISettings settings) : AuthorizationHandler<AuthSettingRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthSettingRequirement requirement)
{
@ -17,7 +17,7 @@ public class AuthSettingHandler : AuthorizationHandler<AuthSettingRequirement>
context.Succeed(requirement);
}
if (Settings.Get.General.AuthenticationType == AuthenticationType.None)
if (settings.Current.General.AuthenticationType == AuthenticationType.None)
{
context.Succeed(requirement);
}

View file

@ -9,7 +9,7 @@ public class SabnzbdRequirement : IAuthorizationRequirement
{
}
public class SabnzbdHandler(Authentication authentication, IHttpContextAccessor httpContextAccessor) : AuthorizationHandler<SabnzbdRequirement>
public class SabnzbdHandler(Authentication authentication, IHttpContextAccessor httpContextAccessor, ISettings settings) : AuthorizationHandler<SabnzbdRequirement>
{
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, SabnzbdRequirement requirement)
{
@ -22,7 +22,7 @@ public class SabnzbdHandler(Authentication authentication, IHttpContextAccessor
return;
}
if (Settings.Get.General.AuthenticationType == AuthenticationType.None)
if (settings.Current.General.AuthenticationType == AuthenticationType.None)
{
context.Succeed(requirement);

View file

@ -17,13 +17,13 @@ public interface IAllDebridNetClientFactory
public IAllDebridNETClient GetClient();
}
public class AllDebridNetClientFactory(ILogger<AllDebridNetClientFactory> logger, IHttpClientFactory httpClientFactory) : IAllDebridNetClientFactory
public class AllDebridNetClientFactory(ILogger<AllDebridNetClientFactory> logger, IHttpClientFactory httpClientFactory, ISettings settings) : IAllDebridNetClientFactory
{
public IAllDebridNETClient GetClient()
{
try
{
var apiKey = Settings.Get.Provider.ApiKey;
var apiKey = settings.Current.Provider.ApiKey;
if (String.IsNullOrWhiteSpace(apiKey))
{

View file

@ -12,7 +12,7 @@ using Torrent = DebridLinkFrNET.Models.Torrent;
namespace RdtClient.Service.Services.DebridClients;
public class DebridLinkClient(ILogger<DebridLinkClient> logger, IHttpClientFactory httpClientFactory, IDownloadableFileFilter fileFilter) : IDebridClient
public class DebridLinkClient(ILogger<DebridLinkClient> logger, IHttpClientFactory httpClientFactory, IDownloadableFileFilter fileFilter, ISettings settings) : IDebridClient
{
public async Task<IList<DebridClientTorrent>> GetDownloads()
{
@ -228,7 +228,7 @@ public class DebridLinkClient(ILogger<DebridLinkClient> logger, IHttpClientFacto
{
try
{
var apiKey = Settings.Get.Provider.ApiKey;
var apiKey = settings.Current.Provider.ApiKey;
if (String.IsNullOrWhiteSpace(apiKey))
{
@ -236,7 +236,7 @@ public class DebridLinkClient(ILogger<DebridLinkClient> logger, IHttpClientFacto
}
var httpClient = httpClientFactory.CreateClient();
httpClient.Timeout = TimeSpan.FromSeconds(Settings.Get.Provider.Timeout);
httpClient.Timeout = TimeSpan.FromSeconds(settings.Current.Provider.Timeout);
var debridLinkClient = new DebridLinkFrNETClient(apiKey, httpClient);

View file

@ -12,7 +12,7 @@ using Torrent = RdtClient.Data.Models.Data.Torrent;
namespace RdtClient.Service.Services.DebridClients;
public class PremiumizeDebridClient(ILogger<PremiumizeDebridClient> logger, IHttpClientFactory httpClientFactory, IDownloadableFileFilter fileFilter) : IDebridClient
public class PremiumizeDebridClient(ILogger<PremiumizeDebridClient> logger, IHttpClientFactory httpClientFactory, IDownloadableFileFilter fileFilter, ISettings settings) : IDebridClient
{
private const String TransferCreateUrl = "https://www.premiumize.me/api/transfer/create";
@ -216,9 +216,9 @@ public class PremiumizeDebridClient(ILogger<PremiumizeDebridClient> logger, IHtt
}
}
private static String GetApiKey()
private String GetApiKey()
{
var apiKey = Settings.Get.Provider.ApiKey;
var apiKey = settings.Current.Provider.ApiKey;
if (String.IsNullOrWhiteSpace(apiKey))
{

View file

@ -12,7 +12,7 @@ using Torrent = RDNET.Torrent;
namespace RdtClient.Service.Services.DebridClients;
public class RealDebridDebridClient(ILogger<RealDebridDebridClient> logger, IHttpClientFactory httpClientFactory, IDownloadableFileFilter fileFilter) : IDebridClient
public class RealDebridDebridClient(ILogger<RealDebridDebridClient> logger, IHttpClientFactory httpClientFactory, IDownloadableFileFilter fileFilter, ISettings settings) : IDebridClient
{
private TimeSpan? _offset;
@ -53,7 +53,7 @@ public class RealDebridDebridClient(ILogger<RealDebridDebridClient> logger, IHtt
{
try
{
var timeoutCancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(Settings.Get.Provider.Timeout));
var timeoutCancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(settings.Current.Provider.Timeout));
var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, timeoutCancellationToken.Token);
@ -70,7 +70,7 @@ public class RealDebridDebridClient(ILogger<RealDebridDebridClient> logger, IHtt
{
try
{
var timeoutCancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(Settings.Get.Provider.Timeout));
var timeoutCancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(settings.Current.Provider.Timeout));
var result = await GetClient().Torrents.AddFileAsync(bytes, timeoutCancellationToken.Token);
@ -314,7 +314,7 @@ public class RealDebridDebridClient(ILogger<RealDebridDebridClient> logger, IHtt
{
try
{
var apiKey = Settings.Get.Provider.ApiKey;
var apiKey = settings.Current.Provider.ApiKey;
if (String.IsNullOrWhiteSpace(apiKey))
{
@ -322,9 +322,9 @@ public class RealDebridDebridClient(ILogger<RealDebridDebridClient> logger, IHtt
}
var httpClient = httpClientFactory.CreateClient(DiConfig.RD_CLIENT);
httpClient.Timeout = TimeSpan.FromSeconds(Settings.Get.Provider.Timeout);
httpClient.Timeout = TimeSpan.FromSeconds(settings.Current.Provider.Timeout);
var rdtNetClient = new RdNetClient(null, httpClient, 5, Settings.Get.Provider.ApiHostname);
var rdtNetClient = new RdNetClient(null, httpClient, 5, settings.Current.Provider.ApiHostname);
rdtNetClient.UseApiAuthentication(apiKey);
// Get the server time to fix up the timezones on results

View file

@ -11,7 +11,7 @@ using Torrent = RdtClient.Data.Models.Data.Torrent;
namespace RdtClient.Service.Services.DebridClients;
public class TorBoxDebridClient(ILogger<TorBoxDebridClient> logger, IHttpClientFactory httpClientFactory, IDownloadableFileFilter fileFilter, IRateLimitCoordinator coordinator)
public class TorBoxDebridClient(ILogger<TorBoxDebridClient> logger, IHttpClientFactory httpClientFactory, IDownloadableFileFilter fileFilter, IRateLimitCoordinator coordinator, ISettings settings)
: IDebridClient
{
private const String TorBoxApiHost = "api.torbox.app";
@ -327,7 +327,7 @@ public class TorBoxDebridClient(ILogger<TorBoxDebridClient> logger, IHttpClientF
var downloadableFiles = torrent.Files.Where(file => fileFilter.IsDownloadable(torrent, file.Path, file.Bytes)).ToList();
if (downloadableFiles.Count == torrent.Files.Count && torrent.DownloadClient != Data.Enums.DownloadClient.Symlink && Settings.Get.Provider.PreferZippedDownloads)
if (downloadableFiles.Count == torrent.Files.Count && torrent.DownloadClient != Data.Enums.DownloadClient.Symlink && settings.Current.Provider.PreferZippedDownloads)
{
logger.LogDebug("Downloading files from TorBox as a zip.");
@ -364,7 +364,7 @@ public class TorBoxDebridClient(ILogger<TorBoxDebridClient> logger, IHttpClientF
{
try
{
var apiKey = Settings.Get.Provider.ApiKey;
var apiKey = settings.Current.Provider.ApiKey;
if (String.IsNullOrWhiteSpace(apiKey))
{

View file

@ -5,7 +5,7 @@ using RdtClient.Data.Models.QBittorrent;
namespace RdtClient.Service.Services;
public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authentication authentication, Torrents torrents, Downloads downloads)
public class QBittorrent(ILogger<QBittorrent> logger, ISettings settings, Authentication authentication, Torrents torrents, Downloads downloads, ITorrentRunnerState runnerState)
{
public async Task<Boolean> AuthLogin(String userName, String password)
{
@ -168,7 +168,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
WebUiUsername = ""
};
var savePath = Settings.AppDefaultSavePath;
var savePath = settings.DefaultSavePath;
preferences.SavePath = savePath;
preferences.TempPath = $"{savePath}temp{Path.DirectorySeparatorChar}";
@ -185,7 +185,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
public virtual async Task<IList<TorrentInfo>> TorrentInfo()
{
var savePath = Settings.AppDefaultSavePath;
var savePath = settings.DefaultSavePath;
var results = new List<TorrentInfo>();
@ -515,7 +515,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
public async Task<TorrentProperties?> TorrentProperties(String hash)
{
var savePath = Settings.AppDefaultSavePath;
var savePath = settings.DefaultSavePath;
var torrent = await torrents.GetByHash(hash);
@ -605,7 +605,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
return;
}
switch (Settings.Get.Integrations.Default.FinishedAction)
switch (settings.Current.Integrations.Default.FinishedAction)
{
case TorrentFinishedAction.RemoveAllTorrents:
logger.LogDebug("Removing torrents from debrid provider and RDT-Client, no files");
@ -640,19 +640,19 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
var torrent = new Torrent
{
Category = category,
DownloadClient = Settings.Get.DownloadClient.Client,
HostDownloadAction = Settings.Get.Integrations.Default.HostDownloadAction,
FinishedActionDelay = Settings.Get.Integrations.Default.FinishedActionDelay,
DownloadAction = Settings.Get.Integrations.Default.OnlyDownloadAvailableFiles ? TorrentDownloadAction.DownloadAvailableFiles : TorrentDownloadAction.DownloadAll,
DownloadClient = settings.Current.DownloadClient.Client,
HostDownloadAction = settings.Current.Integrations.Default.HostDownloadAction,
FinishedActionDelay = settings.Current.Integrations.Default.FinishedActionDelay,
DownloadAction = settings.Current.Integrations.Default.OnlyDownloadAvailableFiles ? TorrentDownloadAction.DownloadAvailableFiles : TorrentDownloadAction.DownloadAll,
FinishedAction = TorrentFinishedAction.None,
DownloadMinSize = Settings.Get.Integrations.Default.MinFileSize,
IncludeRegex = Settings.Get.Integrations.Default.IncludeRegex,
ExcludeRegex = Settings.Get.Integrations.Default.ExcludeRegex,
TorrentRetryAttempts = Settings.Get.Integrations.Default.TorrentRetryAttempts,
DownloadRetryAttempts = Settings.Get.Integrations.Default.DownloadRetryAttempts,
DeleteOnError = Settings.Get.Integrations.Default.DeleteOnError,
Lifetime = Settings.Get.Integrations.Default.TorrentLifetime,
Priority = priority ?? (Settings.Get.Integrations.Default.Priority > 0 ? Settings.Get.Integrations.Default.Priority : null)
DownloadMinSize = settings.Current.Integrations.Default.MinFileSize,
IncludeRegex = settings.Current.Integrations.Default.IncludeRegex,
ExcludeRegex = settings.Current.Integrations.Default.ExcludeRegex,
TorrentRetryAttempts = settings.Current.Integrations.Default.TorrentRetryAttempts,
DownloadRetryAttempts = settings.Current.Integrations.Default.DownloadRetryAttempts,
DeleteOnError = settings.Current.Integrations.Default.DeleteOnError,
Lifetime = settings.Current.Integrations.Default.TorrentLifetime,
Priority = priority ?? (settings.Current.Integrations.Default.Priority > 0 ? settings.Current.Integrations.Default.Priority : null)
};
await torrents.AddMagnetToDebridQueue(magnetLink, torrent);
@ -665,19 +665,19 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
var torrent = new Torrent
{
Category = category,
DownloadClient = Settings.Get.DownloadClient.Client,
HostDownloadAction = Settings.Get.Integrations.Default.HostDownloadAction,
FinishedActionDelay = Settings.Get.Integrations.Default.FinishedActionDelay,
DownloadAction = Settings.Get.Integrations.Default.OnlyDownloadAvailableFiles ? TorrentDownloadAction.DownloadAvailableFiles : TorrentDownloadAction.DownloadAll,
DownloadClient = settings.Current.DownloadClient.Client,
HostDownloadAction = settings.Current.Integrations.Default.HostDownloadAction,
FinishedActionDelay = settings.Current.Integrations.Default.FinishedActionDelay,
DownloadAction = settings.Current.Integrations.Default.OnlyDownloadAvailableFiles ? TorrentDownloadAction.DownloadAvailableFiles : TorrentDownloadAction.DownloadAll,
FinishedAction = TorrentFinishedAction.None,
DownloadMinSize = Settings.Get.Integrations.Default.MinFileSize,
IncludeRegex = Settings.Get.Integrations.Default.IncludeRegex,
ExcludeRegex = Settings.Get.Integrations.Default.ExcludeRegex,
TorrentRetryAttempts = Settings.Get.Integrations.Default.TorrentRetryAttempts,
DownloadRetryAttempts = Settings.Get.Integrations.Default.DownloadRetryAttempts,
DeleteOnError = Settings.Get.Integrations.Default.DeleteOnError,
Lifetime = Settings.Get.Integrations.Default.TorrentLifetime,
Priority = priority ?? (Settings.Get.Integrations.Default.Priority > 0 ? Settings.Get.Integrations.Default.Priority : null)
DownloadMinSize = settings.Current.Integrations.Default.MinFileSize,
IncludeRegex = settings.Current.Integrations.Default.IncludeRegex,
ExcludeRegex = settings.Current.Integrations.Default.ExcludeRegex,
TorrentRetryAttempts = settings.Current.Integrations.Default.TorrentRetryAttempts,
DownloadRetryAttempts = settings.Current.Integrations.Default.DownloadRetryAttempts,
DeleteOnError = settings.Current.Integrations.Default.DeleteOnError,
Lifetime = settings.Current.Integrations.Default.TorrentLifetime,
Priority = priority ?? (settings.Current.Integrations.Default.Priority > 0 ? settings.Current.Integrations.Default.Priority : null)
};
await torrents.AddFileToDebridQueue(fileBytes, torrent);
@ -696,7 +696,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
.Select(m => m.Category!.ToLower())
.ToList();
var categoryList = (Settings.Get.General.Categories ?? "")
var categoryList = (settings.Current.General.Categories ?? "")
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Distinct(StringComparer.CurrentCultureIgnoreCase)
.Select(m => m.Trim())
@ -713,7 +713,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
m => new TorrentCategory
{
Name = m,
SavePath = Path.Combine(Settings.AppDefaultSavePath, m)
SavePath = Path.Combine(settings.DefaultSavePath, m)
});
}
@ -729,7 +729,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
category = category.Trim();
var categoriesSetting = Settings.Get.General.Categories;
var categoriesSetting = settings.Current.General.Categories;
var categoryList = (categoriesSetting ?? "")
.Split(",", StringSplitOptions.RemoveEmptyEntries)
@ -756,7 +756,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
category = category.Trim();
var categoriesSetting = Settings.Get.General.Categories;
var categoriesSetting = settings.Current.General.Categories;
var categoryList = (categoriesSetting ?? "")
.Split(",", StringSplitOptions.RemoveEmptyEntries)
@ -796,7 +796,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
foreach (var download in downloadsForTorrent)
{
if (TorrentRunner.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient))
if (runnerState.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient))
{
await downloadClient.Pause();
}
@ -816,7 +816,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
foreach (var download in downloadsForTorrent)
{
if (TorrentRunner.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient))
if (runnerState.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient))
{
await downloadClient.Resume();
}
@ -829,7 +829,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
var categories = await TorrentsCategories();
var activeDownloads = TorrentRunner.ActiveDownloadClients.Sum(m => m.Value.Speed);
var activeDownloads = runnerState.ActiveDownloadClients.Sum(m => m.Value.Speed);
return new()
{
@ -847,16 +847,16 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
};
}
public static TransferInfo TransferInfo()
public virtual TransferInfo TransferInfo()
{
var activeDownloads = TorrentRunner.ActiveDownloadClients.Sum(m => m.Value.Speed);
var activeDownloads = runnerState.ActiveDownloadClients.Sum(m => m.Value.Speed);
return new()
{
ConnectionStatus = "connected",
DlInfoData = DownloadClient.GetTotalBytesDownloadedThisSession(),
DlInfoSpeed = activeDownloads,
DlRateLimit = Settings.Get.DownloadClient.MaxSpeed
DlRateLimit = settings.Current.DownloadClient.MaxSpeed
};
}

View file

@ -7,7 +7,7 @@ using RdtClient.Service.Helpers;
namespace RdtClient.Service.Services;
public class Sabnzbd(ILogger<Sabnzbd> logger, Torrents torrents, AppSettings appSettings)
public class Sabnzbd(ILogger<Sabnzbd> logger, Torrents torrents, AppSettings appSettings, ISettings settings)
{
public virtual async Task<SabnzbdQueue> GetQueue()
{
@ -87,7 +87,7 @@ public class Sabnzbd(ILogger<Sabnzbd> logger, Torrents torrents, AppSettings app
var allTorrents = await torrents.Get();
var completedTorrents = allTorrents.Where(t => t.Type == DownloadType.Nzb && t.Completed != null).ToList();
var savePath = Settings.AppDefaultSavePath;
var savePath = settings.DefaultSavePath;
var history = new SabnzbdHistory
{
@ -130,19 +130,19 @@ public class Sabnzbd(ILogger<Sabnzbd> logger, Torrents torrents, AppSettings app
var torrent = new Torrent
{
Category = category,
DownloadClient = Settings.Get.DownloadClient.Client,
HostDownloadAction = Settings.Get.Integrations.Default.HostDownloadAction,
FinishedActionDelay = Settings.Get.Integrations.Default.FinishedActionDelay,
DownloadAction = Settings.Get.Integrations.Default.OnlyDownloadAvailableFiles ? TorrentDownloadAction.DownloadAvailableFiles : TorrentDownloadAction.DownloadAll,
DownloadClient = settings.Current.DownloadClient.Client,
HostDownloadAction = settings.Current.Integrations.Default.HostDownloadAction,
FinishedActionDelay = settings.Current.Integrations.Default.FinishedActionDelay,
DownloadAction = settings.Current.Integrations.Default.OnlyDownloadAvailableFiles ? TorrentDownloadAction.DownloadAvailableFiles : TorrentDownloadAction.DownloadAll,
FinishedAction = TorrentFinishedAction.None,
DownloadMinSize = Settings.Get.Integrations.Default.MinFileSize,
IncludeRegex = Settings.Get.Integrations.Default.IncludeRegex,
ExcludeRegex = Settings.Get.Integrations.Default.ExcludeRegex,
TorrentRetryAttempts = Settings.Get.Integrations.Default.TorrentRetryAttempts,
DownloadRetryAttempts = Settings.Get.Integrations.Default.DownloadRetryAttempts,
DeleteOnError = Settings.Get.Integrations.Default.DeleteOnError,
Lifetime = Settings.Get.Integrations.Default.TorrentLifetime,
Priority = (priority ?? Settings.Get.Integrations.Default.Priority) > 0 ? 1 : null
DownloadMinSize = settings.Current.Integrations.Default.MinFileSize,
IncludeRegex = settings.Current.Integrations.Default.IncludeRegex,
ExcludeRegex = settings.Current.Integrations.Default.ExcludeRegex,
TorrentRetryAttempts = settings.Current.Integrations.Default.TorrentRetryAttempts,
DownloadRetryAttempts = settings.Current.Integrations.Default.DownloadRetryAttempts,
DeleteOnError = settings.Current.Integrations.Default.DeleteOnError,
Lifetime = settings.Current.Integrations.Default.TorrentLifetime,
Priority = (priority ?? settings.Current.Integrations.Default.Priority) > 0 ? 1 : null
};
var result = await torrents.AddNzbFileToDebridQueue(fileBytes, fileName, torrent);
@ -157,19 +157,19 @@ public class Sabnzbd(ILogger<Sabnzbd> logger, Torrents torrents, AppSettings app
var torrent = new Torrent
{
Category = category,
DownloadClient = Settings.Get.DownloadClient.Client,
HostDownloadAction = Settings.Get.Integrations.Default.HostDownloadAction,
FinishedActionDelay = Settings.Get.Integrations.Default.FinishedActionDelay,
DownloadAction = Settings.Get.Integrations.Default.OnlyDownloadAvailableFiles ? TorrentDownloadAction.DownloadAvailableFiles : TorrentDownloadAction.DownloadAll,
DownloadClient = settings.Current.DownloadClient.Client,
HostDownloadAction = settings.Current.Integrations.Default.HostDownloadAction,
FinishedActionDelay = settings.Current.Integrations.Default.FinishedActionDelay,
DownloadAction = settings.Current.Integrations.Default.OnlyDownloadAvailableFiles ? TorrentDownloadAction.DownloadAvailableFiles : TorrentDownloadAction.DownloadAll,
FinishedAction = TorrentFinishedAction.None,
DownloadMinSize = Settings.Get.Integrations.Default.MinFileSize,
IncludeRegex = Settings.Get.Integrations.Default.IncludeRegex,
ExcludeRegex = Settings.Get.Integrations.Default.ExcludeRegex,
TorrentRetryAttempts = Settings.Get.Integrations.Default.TorrentRetryAttempts,
DownloadRetryAttempts = Settings.Get.Integrations.Default.DownloadRetryAttempts,
DeleteOnError = Settings.Get.Integrations.Default.DeleteOnError,
Lifetime = Settings.Get.Integrations.Default.TorrentLifetime,
Priority = priority ?? (Settings.Get.Integrations.Default.Priority > 0 ? Settings.Get.Integrations.Default.Priority : null)
DownloadMinSize = settings.Current.Integrations.Default.MinFileSize,
IncludeRegex = settings.Current.Integrations.Default.IncludeRegex,
ExcludeRegex = settings.Current.Integrations.Default.ExcludeRegex,
TorrentRetryAttempts = settings.Current.Integrations.Default.TorrentRetryAttempts,
DownloadRetryAttempts = settings.Current.Integrations.Default.DownloadRetryAttempts,
DeleteOnError = settings.Current.Integrations.Default.DeleteOnError,
Lifetime = settings.Current.Integrations.Default.TorrentLifetime,
Priority = priority ?? (settings.Current.Integrations.Default.Priority > 0 ? settings.Current.Integrations.Default.Priority : null)
};
var result = await torrents.AddNzbLinkToDebridQueue(url, torrent);
@ -186,7 +186,7 @@ public class Sabnzbd(ILogger<Sabnzbd> logger, Torrents torrents, AppSettings app
return;
}
switch (Settings.Get.Integrations.Default.FinishedAction)
switch (settings.Current.Integrations.Default.FinishedAction)
{
case TorrentFinishedAction.RemoveAllTorrents:
logger.LogDebug("Removing nzb from debrid provider and RDT-Client, no files");
@ -216,7 +216,7 @@ public class Sabnzbd(ILogger<Sabnzbd> logger, Torrents torrents, AppSettings app
public virtual List<String> GetCategories()
{
var categoryList = (Settings.Get.General.Categories ?? "")
var categoryList = (settings.Current.General.Categories ?? "")
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(m => m.Trim())
.Where(m => m != "*")
@ -230,7 +230,7 @@ public class Sabnzbd(ILogger<Sabnzbd> logger, Torrents torrents, AppSettings app
public virtual SabnzbdConfig GetConfig()
{
var savePath = Settings.AppDefaultSavePath;
var savePath = settings.DefaultSavePath;
var categoryList = GetCategories();

View file

@ -1,49 +1,83 @@
using RdtClient.Data.Data;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Internal;
using Microsoft.Extensions.DependencyInjection;
using Serilog.Core;
using Serilog.Events;
namespace RdtClient.Service.Services;
public class Settings(SettingData settingData)
public interface ISettings
{
DbSettings Current { get; }
String DefaultSavePath { get; }
IList<SettingProperty> GetAll();
Task Update(IList<SettingProperty> settings);
Task Update(String settingId, Object? value);
}
public class Settings(IServiceScopeFactory serviceScopeFactory) : ISettings
{
public static readonly LoggingLevelSwitch LoggingLevelSwitch = new(LogEventLevel.Debug);
public static DbSettings Get => SettingData.Get;
public static String AppDefaultSavePath
public DbSettings Current => Get;
public static String AppDefaultSavePath => GetDefaultSavePath(Get);
public String DefaultSavePath => GetDefaultSavePath(Current);
public IList<SettingProperty> GetAll()
{
get
{
var downloadPath = Get.DownloadClient.MappedPath;
return SettingData.GetAll();
}
downloadPath = downloadPath.TrimEnd('\\')
.TrimEnd('/');
private static String GetDefaultSavePath(DbSettings settings)
{
var downloadPath = settings.DownloadClient.MappedPath;
downloadPath += Path.DirectorySeparatorChar;
downloadPath = downloadPath.TrimEnd('\\')
.TrimEnd('/');
return downloadPath;
}
downloadPath += Path.DirectorySeparatorChar;
return downloadPath;
}
public async Task Update(IList<SettingProperty> settings)
{
using var scope = serviceScopeFactory.CreateScope();
var settingData = scope.ServiceProvider.GetRequiredService<SettingData>();
await settingData.Update(settings);
}
public async Task Update(String settingId, Object? value)
{
using var scope = serviceScopeFactory.CreateScope();
var settingData = scope.ServiceProvider.GetRequiredService<SettingData>();
await settingData.Update(settingId, value);
}
public async Task Seed()
{
using var scope = serviceScopeFactory.CreateScope();
var settingData = scope.ServiceProvider.GetRequiredService<SettingData>();
await settingData.Seed();
}
public async Task ResetCache()
{
using var scope = serviceScopeFactory.CreateScope();
var settingData = scope.ServiceProvider.GetRequiredService<SettingData>();
await settingData.ResetCache();
LoggingLevelSwitch.MinimumLevel = Get.General.LogLevel switch

View file

@ -17,34 +17,34 @@ public class TorrentRunner(
Downloads downloads,
RemoteService remoteService,
IHttpClientFactory httpClientFactory,
IRateLimitCoordinator coordinator)
IRateLimitCoordinator coordinator,
ISettings settings,
ITorrentRunnerState runnerState)
{
public static readonly ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients = new();
public static readonly ConcurrentDictionary<Guid, UnpackClient> ActiveUnpackClients = new();
public static readonly ITorrentRunnerState SharedState = new TorrentRunnerState();
public static ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients => SharedState.ActiveDownloadClients;
public static ConcurrentDictionary<Guid, UnpackClient> ActiveUnpackClients => SharedState.ActiveUnpackClients;
private DateTimeOffset? _lastNextAllowedAt;
public static Boolean IsPausedForLowDiskSpace { get; set; }
public static Boolean IsPausedForLowDiskSpace
{
get => SharedState.IsPausedForLowDiskSpace;
set => SharedState.IsPausedForLowDiskSpace = value;
}
public static (Int64 Speed, Int64 BytesTotal, Int64 BytesDone) GetStats(Guid downloadId)
{
if (ActiveDownloadClients.TryGetValue(downloadId, out var downloadClient))
{
return (downloadClient.Speed, downloadClient.BytesTotal, downloadClient.BytesDone);
}
if (ActiveUnpackClients.TryGetValue(downloadId, out var unpackClient))
{
return (0, 100, unpackClient.Progess);
}
return (0, 0, 0);
return SharedState.GetStats(downloadId);
}
public async Task Initialize()
{
Log("Initializing TorrentRunner");
var settingsCopy = JsonSerializer.Deserialize<DbSettings>(JsonSerializer.Serialize(Settings.Get));
var settingsCopy = JsonSerializer.Deserialize<DbSettings>(JsonSerializer.Serialize(settings.Current));
if (settingsCopy != null)
{
@ -87,28 +87,28 @@ public class TorrentRunner(
public async Task Tick()
{
if (String.IsNullOrWhiteSpace(Settings.Get.Provider.ApiKey))
if (String.IsNullOrWhiteSpace(settings.Current.Provider.ApiKey))
{
Log($"No RealDebridApiKey set in settings");
return;
}
var settingDownloadLimit = Settings.Get.General.DownloadLimit;
var settingDownloadLimit = settings.Current.General.DownloadLimit;
if (settingDownloadLimit < 1)
{
settingDownloadLimit = 1;
}
var settingUnpackLimit = Settings.Get.General.UnpackLimit;
var settingUnpackLimit = settings.Current.General.UnpackLimit;
if (settingUnpackLimit < 0)
{
settingUnpackLimit = 0;
}
var settingDownloadPath = Settings.Get.DownloadClient.DownloadPath;
var settingDownloadPath = settings.Current.DownloadClient.DownloadPath;
if (String.IsNullOrWhiteSpace(settingDownloadPath))
{
@ -141,25 +141,25 @@ public class TorrentRunner(
_lastNextAllowedAt = currentNextAllowedAt;
}
if (!ActiveDownloadClients.IsEmpty || !ActiveUnpackClients.IsEmpty)
if (!runnerState.ActiveDownloadClients.IsEmpty || !runnerState.ActiveUnpackClients.IsEmpty)
{
Log($"TorrentRunner Tick Start, {ActiveDownloadClients.Count} active downloads, {ActiveUnpackClients.Count} active unpacks");
Log($"TorrentRunner Tick Start, {runnerState.ActiveDownloadClients.Count} active downloads, {runnerState.ActiveUnpackClients.Count} active unpacks");
}
if (ActiveDownloadClients.Any(m => m.Value.Type == Data.Enums.DownloadClient.Aria2c))
if (runnerState.ActiveDownloadClients.Any(m => m.Value.Type == Data.Enums.DownloadClient.Aria2c))
{
Log("Updating Aria2 status");
var httpClient = httpClientFactory.CreateClient();
httpClient.Timeout = TimeSpan.FromSeconds(10);
var aria2NetClient = new Aria2NetClient(Settings.Get.DownloadClient.Aria2cUrl, Settings.Get.DownloadClient.Aria2cSecret, httpClient, 1);
var aria2NetClient = new Aria2NetClient(settings.Current.DownloadClient.Aria2cUrl, settings.Current.DownloadClient.Aria2cSecret, httpClient, 1);
var allDownloads = await aria2NetClient.TellAllAsync();
Log($"Found {allDownloads.Count} Aria2 downloads");
foreach (var activeDownload in ActiveDownloadClients)
foreach (var activeDownload in runnerState.ActiveDownloadClients)
{
if (activeDownload.Value.Downloader is Aria2cDownloader aria2Downloader)
{
@ -170,11 +170,11 @@ public class TorrentRunner(
Log("Finished updating Aria2 status");
}
if (ActiveDownloadClients.Any(m => m.Value.Type == Data.Enums.DownloadClient.DownloadStation))
if (runnerState.ActiveDownloadClients.Any(m => m.Value.Type == Data.Enums.DownloadClient.DownloadStation))
{
Log("Updating DownloadStation status");
foreach (var activeDownload in ActiveDownloadClients)
foreach (var activeDownload in runnerState.ActiveDownloadClients)
{
if (activeDownload.Value.Downloader is DownloadStationDownloader downloadStationDownloader)
{
@ -184,7 +184,7 @@ public class TorrentRunner(
}
// Check if any torrents are finished downloading to the host, remove them from the active download list.
var completedActiveDownloads = ActiveDownloadClients.Where(m => m.Value.Finished).ToList();
var completedActiveDownloads = runnerState.ActiveDownloadClients.Where(m => m.Value.Finished).ToList();
if (completedActiveDownloads.Count > 0)
{
@ -196,7 +196,7 @@ public class TorrentRunner(
if (download == null)
{
ActiveDownloadClients.TryRemove(downloadId, out _);
runnerState.ActiveDownloadClients.TryRemove(downloadId, out _);
Log($"Download with ID {downloadId} not found! Removed from download queue");
@ -237,14 +237,14 @@ public class TorrentRunner(
await downloads.UpdateUnpackingQueued(downloadId, DateTimeOffset.UtcNow);
}
ActiveDownloadClients.TryRemove(downloadId, out _);
runnerState.ActiveDownloadClients.TryRemove(downloadId, out _);
Log($"Removed from ActiveDownloadClients", download, download.Torrent);
}
}
// Check if any torrents are finished unpacking, remove them from the active unpack list.
var completedUnpacks = ActiveUnpackClients.Where(m => m.Value.Finished).ToList();
var completedUnpacks = runnerState.ActiveUnpackClients.Where(m => m.Value.Finished).ToList();
if (completedUnpacks.Count > 0)
{
@ -256,7 +256,7 @@ public class TorrentRunner(
if (download == null)
{
ActiveUnpackClients.TryRemove(downloadId, out _);
runnerState.ActiveUnpackClients.TryRemove(downloadId, out _);
Log($"Download with ID {downloadId} not found! Removed from unpack queue");
@ -278,7 +278,7 @@ public class TorrentRunner(
await downloads.UpdateCompleted(downloadId, DateTimeOffset.UtcNow);
ActiveUnpackClients.TryRemove(downloadId, out _);
runnerState.ActiveUnpackClients.TryRemove(downloadId, out _);
Log($"Removed from ActiveUnpackClients", download, download.Torrent);
}
@ -288,23 +288,23 @@ public class TorrentRunner(
var downloadsById = allTorrents.SelectMany(m => m.Downloads).ToDictionary(m => m.DownloadId, m => m);
// Check for deleted torrents that are stuck in the ActiveDownloads or ActiveUnpacks
foreach (var activeDownload in ActiveDownloadClients)
foreach (var activeDownload in runnerState.ActiveDownloadClients)
{
if (!downloadsById.ContainsKey(activeDownload.Key))
{
await activeDownload.Value.Cancel();
ActiveDownloadClients.TryRemove(activeDownload.Key, out _);
runnerState.ActiveDownloadClients.TryRemove(activeDownload.Key, out _);
break;
}
}
foreach (var activeUnpacks in ActiveUnpackClients)
foreach (var activeUnpacks in runnerState.ActiveUnpackClients)
{
if (!downloadsById.ContainsKey(activeUnpacks.Key))
{
activeUnpacks.Value.Cancel();
ActiveUnpackClients.TryRemove(activeUnpacks.Key, out _);
runnerState.ActiveUnpackClients.TryRemove(activeUnpacks.Key, out _);
break;
}
@ -382,7 +382,7 @@ public class TorrentRunner(
{
var downloadingTorrentsCount = allTorrents.Count(m => m.RdStatus is not (TorrentStatus.Queued or TorrentStatus.Finished or TorrentStatus.Error));
var maxParallelDownloads = Settings.Get.Provider.MaxParallelDownloads;
var maxParallelDownloads = settings.Current.Provider.MaxParallelDownloads;
logger.LogDebug("Currently downloading {downloadingTorrentCount}/{maxParallelDownloads} torrents, {queuedCount} queued.",
downloadingTorrentsCount,
@ -481,27 +481,27 @@ public class TorrentRunner(
.OrderBy(m => m.DownloadQueued)
.ToList();
Log($"Currently {queuedDownloads.Count} queued downloads and {ActiveDownloadClients.Count} total active downloads", torrent);
Log($"Currently {queuedDownloads.Count} queued downloads and {runnerState.ActiveDownloadClients.Count} total active downloads", torrent);
foreach (var download in queuedDownloads)
{
Log($"Processing to download", download, torrent);
if (ActiveDownloadClients.Count >= settingDownloadLimit && torrent.DownloadClient != Data.Enums.DownloadClient.Symlink)
if (runnerState.ActiveDownloadClients.Count >= settingDownloadLimit && torrent.DownloadClient != Data.Enums.DownloadClient.Symlink)
{
Log($"Not starting download because there are already the max number of downloads active", download, torrent);
return;
}
if (IsPausedForLowDiskSpace && torrent.DownloadClient == Data.Enums.DownloadClient.Bezzad)
if (runnerState.IsPausedForLowDiskSpace && torrent.DownloadClient == Data.Enums.DownloadClient.Bezzad)
{
logger.LogInformation($"Not starting Bezzad download because of low disk space {download.ToLog()} {torrent.ToLog()}");
return;
}
if (ActiveDownloadClients.ContainsKey(download.DownloadId))
if (runnerState.ActiveDownloadClients.ContainsKey(download.DownloadId))
{
Log($"Not starting download because this download is already active", download, torrent);
@ -553,7 +553,7 @@ public class TorrentRunner(
// Start the download process
var downloadClient = new DownloadClient(download, torrent, downloadPath, torrent.Category);
if (ActiveDownloadClients.TryAdd(download.DownloadId, downloadClient))
if (runnerState.ActiveDownloadClients.TryAdd(download.DownloadId, downloadClient))
{
Log($"Starting download", download, torrent);
@ -573,7 +573,7 @@ public class TorrentRunner(
await downloads.UpdateRemoteId(download.DownloadId, remoteId);
}
if (IsPausedForLowDiskSpace && downloadClient.Type == Data.Enums.DownloadClient.Bezzad)
if (runnerState.IsPausedForLowDiskSpace && downloadClient.Type == Data.Enums.DownloadClient.Bezzad)
{
logger.LogInformation($"Pausing new Bezzad download due to low disk space {download.ToLog()} {torrent.ToLog()}");
await downloadClient.Pause();
@ -633,14 +633,14 @@ public class TorrentRunner(
}
// Check if we have reached the download limit, if so queue the download, but don't start it.
if (ActiveUnpackClients.Count >= settingUnpackLimit)
if (runnerState.ActiveUnpackClients.Count >= settingUnpackLimit)
{
Log($"Not starting unpack because there are already the max number of unpacks active", download, torrent);
continue;
}
if (ActiveUnpackClients.ContainsKey(download.DownloadId))
if (runnerState.ActiveUnpackClients.ContainsKey(download.DownloadId))
{
Log($"Not starting unpack because this download is already active", download, torrent);
@ -662,7 +662,7 @@ public class TorrentRunner(
// Start the unpacking process
var unpackClient = new UnpackClient(download, downloadPath);
if (ActiveUnpackClients.TryAdd(download.DownloadId, unpackClient))
if (runnerState.ActiveUnpackClients.TryAdd(download.DownloadId, unpackClient))
{
Log($"Starting unpack", download, torrent);
@ -720,8 +720,8 @@ public class TorrentRunner(
var completePerc = 0;
var totalDownloadBytes = torrent.Downloads.Sum(m => GetStats(m.DownloadId).BytesTotal);
var totalDoneBytes = torrent.Downloads.Sum(m => GetStats(m.DownloadId).BytesDone);
var totalDownloadBytes = torrent.Downloads.Sum(m => runnerState.GetStats(m.DownloadId).BytesTotal);
var totalDoneBytes = torrent.Downloads.Sum(m => runnerState.GetStats(m.DownloadId).BytesDone);
if (totalDownloadBytes > 0)
{

View file

@ -0,0 +1,47 @@
using System.Collections.Concurrent;
namespace RdtClient.Service.Services;
public interface ITorrentRunnerState
{
ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients { get; }
ConcurrentDictionary<Guid, UnpackClient> ActiveUnpackClients { get; }
Boolean IsPausedForLowDiskSpace { get; set; }
(Int64 Speed, Int64 BytesTotal, Int64 BytesDone) GetStats(Guid downloadId);
void Clear();
}
public class TorrentRunnerState : ITorrentRunnerState
{
public ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients { get; } = new();
public ConcurrentDictionary<Guid, UnpackClient> ActiveUnpackClients { get; } = new();
public Boolean IsPausedForLowDiskSpace { get; set; }
public (Int64 Speed, Int64 BytesTotal, Int64 BytesDone) GetStats(Guid downloadId)
{
if (ActiveDownloadClients.TryGetValue(downloadId, out var downloadClient))
{
return (downloadClient.Speed, downloadClient.BytesTotal, downloadClient.BytesDone);
}
if (ActiveUnpackClients.TryGetValue(downloadId, out var unpackClient))
{
return (0, 100, unpackClient.Progess);
}
return (0, 0, 0);
}
public void Clear()
{
ActiveDownloadClients.Clear();
ActiveUnpackClients.Clear();
IsPausedForLowDiskSpace = false;
}
}

View file

@ -32,7 +32,9 @@ public class Torrents(
PremiumizeDebridClient premiumizeDebridClient,
RealDebridDebridClient realDebridDebridClient,
DebridLinkClient debridLinkClient,
TorBoxDebridClient torBoxDebridClient)
TorBoxDebridClient torBoxDebridClient,
ISettings settings,
ITorrentRunnerState runnerState)
{
private static readonly SemaphoreSlim RealDebridUpdateLock = new(1, 1);
@ -47,7 +49,7 @@ public class Torrents(
{
get
{
return Settings.Get.Provider.Provider switch
return settings.Current.Provider.Provider switch
{
Provider.Premiumize => premiumizeDebridClient,
Provider.RealDebrid => realDebridDebridClient,
@ -61,7 +63,7 @@ public class Torrents(
public virtual (Int64 Speed, Int64 BytesTotal, Int64 BytesDone) GetDownloadStats(Guid downloadId)
{
return TorrentRunner.GetStats(downloadId);
return runnerState.GetStats(downloadId);
}
public virtual async Task<IList<Torrent>> Get()
@ -197,9 +199,9 @@ public class Torrents(
throw new($"{ex.Message}, trying to parse {magnetLink}");
}
if (!String.IsNullOrWhiteSpace(Settings.Get.General.BannedTrackers))
if (!String.IsNullOrWhiteSpace(settings.Current.General.BannedTrackers))
{
var bannedTrackers = Settings.Get.General.BannedTrackers.Split(',');
var bannedTrackers = settings.Current.General.BannedTrackers.Split(',');
foreach (var bannedTracker in bannedTrackers)
{
@ -264,9 +266,9 @@ public class Torrents(
throw new($"{ex.Message}, trying to parse {fileAsBase64}");
}
if (!String.IsNullOrWhiteSpace(Settings.Get.General.BannedTrackers))
if (!String.IsNullOrWhiteSpace(settings.Current.General.BannedTrackers))
{
var bannedTrackers = Settings.Get.General.BannedTrackers.Split(',');
var bannedTrackers = settings.Current.General.BannedTrackers.Split(',');
foreach (var bannedTracker in bannedTrackers)
{
@ -312,16 +314,16 @@ public class Torrents(
private async Task CopyAddedTorrent(Torrent torrent)
{
if (String.IsNullOrWhiteSpace(Settings.Get.General.CopyAddedTorrents) || String.IsNullOrWhiteSpace(torrent.FileOrMagnet) || String.IsNullOrWhiteSpace(torrent.RdName))
if (String.IsNullOrWhiteSpace(settings.Current.General.CopyAddedTorrents) || String.IsNullOrWhiteSpace(torrent.FileOrMagnet) || String.IsNullOrWhiteSpace(torrent.RdName))
{
return;
}
try
{
if (!fileSystem.Directory.Exists(Settings.Get.General.CopyAddedTorrents))
if (!fileSystem.Directory.Exists(settings.Current.General.CopyAddedTorrents))
{
fileSystem.Directory.CreateDirectory(Settings.Get.General.CopyAddedTorrents);
fileSystem.Directory.CreateDirectory(settings.Current.General.CopyAddedTorrents);
}
var extension = torrent.Type switch
@ -331,7 +333,7 @@ public class Torrents(
_ => throw new ArgumentException("Unexpected DownloadType")
};
var copyFileName = Path.Combine(Settings.Get.General.CopyAddedTorrents, FileHelper.RemoveInvalidFileNameChars(torrent.RdName));
var copyFileName = Path.Combine(settings.Current.General.CopyAddedTorrents, FileHelper.RemoveInvalidFileNameChars(torrent.RdName));
if (!copyFileName.EndsWith(extension, StringComparison.OrdinalIgnoreCase))
{
@ -355,7 +357,7 @@ public class Torrents(
}
catch (Exception ex)
{
logger.LogError(ex, $"Unable to create torrent blackhole directory: {Settings.Get.General.CopyAddedTorrents}: {ex.Message}");
logger.LogError(ex, $"Unable to create torrent blackhole directory: {settings.Current.General.CopyAddedTorrents}: {ex.Message}");
}
}
@ -511,7 +513,7 @@ public class Torrents(
{
var retry = 10;
while (TorrentRunner.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient))
while (runnerState.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient))
{
Log($"Cancelling download", download, torrent);
@ -529,7 +531,7 @@ public class Torrents(
retry = 10;
while (TorrentRunner.ActiveUnpackClients.TryGetValue(download.DownloadId, out var unpackClient))
while (runnerState.ActiveUnpackClients.TryGetValue(download.DownloadId, out var unpackClient))
{
Log($"Cancelling unpack", download, torrent);
@ -569,7 +571,7 @@ public class Torrents(
if (deleteLocalFiles && !String.IsNullOrWhiteSpace(torrent.RdName))
{
var downloadPath = DownloadPath(torrent, Settings.Get);
var downloadPath = DownloadPath(torrent, settings.Current);
downloadPath = Path.Combine(downloadPath, torrent.RdName);
Log($"Deleting local files in {downloadPath}", torrent);
@ -634,13 +636,13 @@ public class Torrents(
var profile = new Profile
{
Provider = Enum.GetName(Settings.Get.Provider.Provider),
Provider = Enum.GetName(settings.Current.Provider.Provider),
UserName = user.Username,
Expiration = user.Expiration,
CurrentVersion = UpdateChecker.CurrentVersion,
LatestVersion = UpdateChecker.LatestVersion,
IsInsecure = UpdateChecker.IsInsecure,
DisableUpdateNotification = Settings.Get.General.DisableUpdateNotifications
DisableUpdateNotification = settings.Current.General.DisableUpdateNotifications
};
return profile;
@ -663,25 +665,25 @@ public class Torrents(
torrentsByRdId.TryGetValue(rdTorrent.Id, out var torrent);
// Auto import torrents only torrents that have their files selected
if (torrent == null && Settings.Get.Provider.AutoImport)
if (torrent == null && settings.Current.Provider.AutoImport)
{
var newTorrent = new Torrent
{
Category = Settings.Get.Provider.Default.Category,
DownloadClient = Settings.Get.DownloadClient.Client,
Category = settings.Current.Provider.Default.Category,
DownloadClient = settings.Current.DownloadClient.Client,
DownloadAction =
Settings.Get.Provider.Default.OnlyDownloadAvailableFiles ? TorrentDownloadAction.DownloadAvailableFiles : TorrentDownloadAction.DownloadAll,
HostDownloadAction = Settings.Get.Provider.Default.HostDownloadAction,
FinishedActionDelay = Settings.Get.Provider.Default.FinishedActionDelay,
FinishedAction = Settings.Get.Provider.Default.FinishedAction,
DownloadMinSize = Settings.Get.Provider.Default.MinFileSize,
IncludeRegex = Settings.Get.Provider.Default.IncludeRegex,
ExcludeRegex = Settings.Get.Provider.Default.ExcludeRegex,
TorrentRetryAttempts = Settings.Get.Provider.Default.TorrentRetryAttempts,
DownloadRetryAttempts = Settings.Get.Provider.Default.DownloadRetryAttempts,
DeleteOnError = Settings.Get.Provider.Default.DeleteOnError,
Lifetime = Settings.Get.Provider.Default.TorrentLifetime,
Priority = Settings.Get.Provider.Default.Priority > 0 ? Settings.Get.Provider.Default.Priority : null,
settings.Current.Provider.Default.OnlyDownloadAvailableFiles ? TorrentDownloadAction.DownloadAvailableFiles : TorrentDownloadAction.DownloadAll,
HostDownloadAction = settings.Current.Provider.Default.HostDownloadAction,
FinishedActionDelay = settings.Current.Provider.Default.FinishedActionDelay,
FinishedAction = settings.Current.Provider.Default.FinishedAction,
DownloadMinSize = settings.Current.Provider.Default.MinFileSize,
IncludeRegex = settings.Current.Provider.Default.IncludeRegex,
ExcludeRegex = settings.Current.Provider.Default.ExcludeRegex,
TorrentRetryAttempts = settings.Current.Provider.Default.TorrentRetryAttempts,
DownloadRetryAttempts = settings.Current.Provider.Default.DownloadRetryAttempts,
DeleteOnError = settings.Current.Provider.Default.DeleteOnError,
Lifetime = settings.Current.Provider.Default.TorrentLifetime,
Priority = settings.Current.Provider.Default.Priority > 0 ? settings.Current.Provider.Default.Priority : null,
RdId = rdTorrent.Id
};
@ -690,7 +692,7 @@ public class Torrents(
continue;
}
torrent = await torrentData.Add(rdTorrent.Id, rdTorrent.Hash, null, false, DownloadType.Torrent, Settings.Get.DownloadClient.Client, newTorrent);
torrent = await torrentData.Add(rdTorrent.Id, rdTorrent.Hash, null, false, DownloadType.Torrent, settings.Current.DownloadClient.Client, newTorrent);
torrentsByRdId[rdTorrent.Id] = torrent;
torrents.Add(torrent);
@ -706,7 +708,7 @@ public class Torrents(
{
var rdTorrent = torrent.RdId != null && providerTorrentsById.TryGetValue(torrent.RdId, out var providerTorrent) ? providerTorrent : null;
if (rdTorrent == null && Settings.Get.Provider.AutoDelete && torrent.RdStatus != TorrentStatus.Queued)
if (rdTorrent == null && settings.Current.Provider.AutoDelete && torrent.RdStatus != TorrentStatus.Queued)
{
await Delete(torrent.TorrentId, true, false, true);
}
@ -744,14 +746,14 @@ public class Torrents(
foreach (var download in torrent.Downloads)
{
while (TorrentRunner.ActiveDownloadClients.TryRemove(download.DownloadId, out var downloadClient))
while (runnerState.ActiveDownloadClients.TryRemove(download.DownloadId, out var downloadClient))
{
await downloadClient.Cancel();
await Task.Delay(100);
}
while (TorrentRunner.ActiveUnpackClients.TryRemove(download.DownloadId, out var unpackClient))
while (runnerState.ActiveUnpackClients.TryRemove(download.DownloadId, out var unpackClient))
{
unpackClient.Cancel();
@ -814,21 +816,21 @@ public class Torrents(
Log($"Retrying Download", download, download.Torrent);
while (TorrentRunner.ActiveDownloadClients.TryRemove(download.DownloadId, out var downloadClient))
while (runnerState.ActiveDownloadClients.TryRemove(download.DownloadId, out var downloadClient))
{
await downloadClient.Cancel();
await Task.Delay(100);
}
while (TorrentRunner.ActiveUnpackClients.TryRemove(download.DownloadId, out var unpackClient))
while (runnerState.ActiveUnpackClients.TryRemove(download.DownloadId, out var unpackClient))
{
unpackClient.Cancel();
await Task.Delay(100);
}
var downloadPath = DownloadPath(download.Torrent!, Settings.Get);
var downloadPath = DownloadPath(download.Torrent!, settings.Current);
var filePath = DownloadHelper.GetDownloadPath(downloadPath, download.Torrent!, download);
@ -970,11 +972,11 @@ public class Torrents(
await torrentData.Update(torrent);
}
public async Task RunTorrentComplete(Guid torrentId, DbSettings? settings = null)
public async Task RunTorrentComplete(Guid torrentId, DbSettings? runSettings = null)
{
settings ??= Settings.Get;
runSettings ??= settings.Current;
if (String.IsNullOrWhiteSpace(settings.General.RunOnTorrentCompleteFileName))
if (String.IsNullOrWhiteSpace(runSettings.General.RunOnTorrentCompleteFileName))
{
return;
}
@ -983,12 +985,12 @@ public class Torrents(
var downloadsForTorrent = await downloads.GetForTorrent(torrentId);
var fileName = settings.General.RunOnTorrentCompleteFileName;
var arguments = settings.General.RunOnTorrentCompleteArguments ?? "";
var fileName = runSettings.General.RunOnTorrentCompleteFileName;
var arguments = runSettings.General.RunOnTorrentCompleteArguments ?? "";
Log($"Parsing external program {fileName} with arguments {arguments}", torrent);
var downloadPath = DownloadPath(torrent, settings);
var downloadPath = DownloadPath(torrent, runSettings);
var torrentPath = Path.Combine(downloadPath, torrent.RdName ?? "Unknown");
var filePath = torrentPath;

View file

@ -12,15 +12,18 @@ public class QBittorrentControllerTest
{
private readonly QBittorrentController _controller;
private readonly Mock<QBittorrent> _qBittorrentMock;
private readonly TestSettings _settings;
public QBittorrentControllerTest()
{
_qBittorrentMock = new(new Mock<ILogger<QBittorrent>>().Object, null!, null!, null!, null!);
_settings = new();
_qBittorrentMock = new(new Mock<ILogger<QBittorrent>>().Object, _settings, null!, null!, null!, new TorrentRunnerState());
_controller = new(
new Mock<ILogger<QBittorrentController>>().Object,
_qBittorrentMock.Object,
new Mock<IHttpClientFactory>().Object);
new Mock<IHttpClientFactory>().Object,
_settings);
_controller.ControllerContext = new()
{
@ -88,4 +91,4 @@ public class QBittorrentControllerTest
Assert.Single(payload);
Assert.Equal("hash1", payload[0].Hash);
}
}
}

View file

@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Moq;
using RdtClient.Data.Data;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Sabnzbd;
using RdtClient.Service.Services;
@ -17,15 +16,17 @@ public class SabnzbdControllerTest
private readonly Mock<Authentication> _authenticationMock;
private readonly SabnzbdController _controller;
private readonly Mock<Sabnzbd> _sabnzbdMock;
private readonly TestSettings _settings;
public SabnzbdControllerTest()
{
SettingData.Get.General.AuthenticationType = AuthenticationType.None;
SettingData.Get.Provider.ApiKey = "test-api-key";
_settings = new();
_settings.Current.General.AuthenticationType = AuthenticationType.None;
_settings.Current.Provider.ApiKey = "test-api-key";
var torrentsMock = new Mock<Torrents>(null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!);
var torrentsMock = new Mock<Torrents>(null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, _settings, new TorrentRunnerState());
var sabnzbdLoggerMock = new Mock<ILogger<Sabnzbd>>();
_sabnzbdMock = new(sabnzbdLoggerMock.Object, torrentsMock.Object, null!);
_sabnzbdMock = new(sabnzbdLoggerMock.Object, torrentsMock.Object, null!, _settings);
var loggerMock = new Mock<ILogger<SabnzbdController>>();
_authenticationMock = new(null!, null!, null!);
@ -64,7 +65,7 @@ public class SabnzbdControllerTest
public async Task GetQueue_Unauthorized_ReturnsOk_BecauseFilterIsSkippedInUnitTests()
{
// Arrange
SettingData.Get.General.AuthenticationType = AuthenticationType.UserNamePassword;
_settings.Current.General.AuthenticationType = AuthenticationType.UserNamePassword;
var queue = new SabnzbdQueue
{
@ -86,7 +87,7 @@ public class SabnzbdControllerTest
public async Task GetQueue_WithMaAuth_ReturnsOk()
{
// Arrange
SettingData.Get.General.AuthenticationType = AuthenticationType.UserNamePassword;
_settings.Current.General.AuthenticationType = AuthenticationType.UserNamePassword;
var httpContext = new DefaultHttpContext();
httpContext.Request.QueryString = new("?ma_username=user&ma_password=pass");
_controller.ControllerContext.HttpContext = httpContext;
@ -146,7 +147,7 @@ public class SabnzbdControllerTest
public void GetVersion_ReturnsOk()
{
// Arrange
SettingData.Get.General.AuthenticationType = AuthenticationType.UserNamePassword;
_settings.Current.General.AuthenticationType = AuthenticationType.UserNamePassword;
// Act
var result = _controller.Version();

View file

@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Moq;
using RdtClient.Data.Data;
using RdtClient.Data.Enums;
using RdtClient.Service.Middleware;
using RdtClient.Service.Services;
@ -15,20 +14,22 @@ public class SabnzbdHandlerTest
private readonly Mock<Authentication> _authenticationMock;
private readonly SabnzbdHandler _handler;
private readonly Mock<IHttpContextAccessor> _httpContextAccessorMock;
private readonly TestSettings _settings;
public SabnzbdHandlerTest()
{
_authenticationMock = new(null!, null!, null!);
_httpContextAccessorMock = new();
_handler = new(_authenticationMock.Object, _httpContextAccessorMock.Object);
SettingData.Get.General.AuthenticationType = AuthenticationType.UserNamePassword;
_settings = new();
_handler = new(_authenticationMock.Object, _httpContextAccessorMock.Object, _settings);
_settings.Current.General.AuthenticationType = AuthenticationType.UserNamePassword;
}
[Fact]
public async Task HandleAsync_AuthNone_Succeeds()
{
// Arrange
SettingData.Get.General.AuthenticationType = AuthenticationType.None;
_settings.Current.General.AuthenticationType = AuthenticationType.None;
var context = CreateContext();
// Act
@ -42,7 +43,7 @@ public class SabnzbdHandlerTest
public async Task HandleAsync_ValidCredentials_Succeeds()
{
// Arrange
Settings.Get.General.AuthenticationType = AuthenticationType.UserNamePassword;
_settings.Current.General.AuthenticationType = AuthenticationType.UserNamePassword;
var httpContext = new DefaultHttpContext
{
Request =
@ -67,7 +68,7 @@ public class SabnzbdHandlerTest
public async Task HandleAsync_AlreadyAuthenticated_Succeeds()
{
// Arrange
Settings.Get.General.AuthenticationType = AuthenticationType.UserNamePassword;
_settings.Current.General.AuthenticationType = AuthenticationType.UserNamePassword;
var httpContext = new DefaultHttpContext();
var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity("TestAuth"));
httpContext.User = claimsPrincipal;
@ -86,7 +87,7 @@ public class SabnzbdHandlerTest
public async Task HandleAsync_InvalidCredentials_DoesNotSucceed()
{
// Arrange
Settings.Get.General.AuthenticationType = AuthenticationType.UserNamePassword;
_settings.Current.General.AuthenticationType = AuthenticationType.UserNamePassword;
var httpContext = new DefaultHttpContext
{
Request =
@ -111,7 +112,7 @@ public class SabnzbdHandlerTest
public async Task HandleAsync_MissingCredentials_DoesNotSucceed()
{
// Arrange
Settings.Get.General.AuthenticationType = AuthenticationType.UserNamePassword;
_settings.Current.General.AuthenticationType = AuthenticationType.UserNamePassword;
var httpContext = new DefaultHttpContext();
_httpContextAccessorMock.Setup(a => a.HttpContext).Returns(httpContext);

View file

@ -17,7 +17,7 @@ public class TorrentsControllerNzbTest
public TorrentsControllerNzbTest()
{
_torrentsMock = new(null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!);
_torrentsMock = new(null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, new TestSettings(), new TorrentRunnerState());
_loggerMock = new();
_coordinatorMock = new();
_controller = new(_loggerMock.Object, _torrentsMock.Object, null!, _coordinatorMock.Object);

View file

@ -1,3 +0,0 @@
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]

View file

@ -5,6 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<AssemblyName>RdtClient.Web.Test</AssemblyName>
<RootNamespace>RdtClient.Web.Test</RootNamespace>
</PropertyGroup>

View file

@ -0,0 +1,58 @@
using RdtClient.Data.Models.Internal;
namespace RdtClient.Service.Services;
internal sealed class TestSettings(DbSettings? settings = null) : ISettings
{
public DbSettings Current { get; } = settings ?? new();
public String DefaultSavePath
{
get
{
var downloadPath = Current.DownloadClient.MappedPath.TrimEnd('\\').TrimEnd('/');
return downloadPath + Path.DirectorySeparatorChar;
}
}
public IList<SettingProperty> GetAll()
{
return [];
}
public Task Update(IList<SettingProperty> settings)
{
return Task.CompletedTask;
}
public Task Update(String settingId, Object? value)
{
SetValue(Current, settingId.Split(':'), 0, value);
return Task.CompletedTask;
}
private static void SetValue(Object target, IReadOnlyList<String> path, Int32 index, Object? value)
{
var property = target.GetType().GetProperty(path[index]) ?? throw new($"Unknown setting {String.Join(":", path)}");
if (index < path.Count - 1)
{
SetValue(property.GetValue(target)!, path, index + 1, value);
return;
}
if (value == null)
{
property.SetValue(target, null);
return;
}
var propertyType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
var convertedValue = propertyType.IsEnum ? Enum.Parse(propertyType, value.ToString()!) : Convert.ChangeType(value, propertyType);
property.SetValue(target, convertedValue);
}
}

View file

@ -6,14 +6,14 @@ using RdtClient.Service.Services;
namespace RdtClient.Web.Controllers;
[Route("Api/Authentication")]
public class AuthController(Authentication authentication, Settings settings) : Controller
public class AuthController(Authentication authentication, ISettings settings) : Controller
{
[AllowAnonymous]
[Route("IsLoggedIn")]
[HttpGet]
public async Task<ActionResult> IsLoggedIn()
{
if (Settings.Get.General.AuthenticationType == AuthenticationType.None)
if (settings.Current.General.AuthenticationType == AuthenticationType.None)
{
return Ok();
}
@ -77,7 +77,7 @@ public class AuthController(Authentication authentication, Settings settings) :
return BadRequest();
}
if (!String.IsNullOrEmpty(Settings.Get.Provider.ApiKey))
if (!String.IsNullOrEmpty(settings.Current.Provider.ApiKey))
{
return StatusCode(401);
}

View file

@ -14,7 +14,7 @@ namespace RdtClient.Web.Controllers;
[ApiController]
[Route("api/v2")]
[Route("qbittorrent/api/v2")]
public class QBittorrentController(ILogger<QBittorrentController> logger, QBittorrent qBittorrent, IHttpClientFactory httpClientFactory) : Controller
public class QBittorrentController(ILogger<QBittorrentController> logger, QBittorrent qBittorrent, IHttpClientFactory httpClientFactory, ISettings settings) : Controller
{
[AllowAnonymous]
[Route("/version/api")]
@ -33,7 +33,7 @@ public class QBittorrentController(ILogger<QBittorrentController> logger, QBitto
{
logger.LogDebug($"Auth login");
if (Settings.Get.General.AuthenticationType == AuthenticationType.None)
if (settings.Current.General.AuthenticationType == AuthenticationType.None)
{
return Content("Ok.", "text/plain");
}
@ -146,7 +146,7 @@ public class QBittorrentController(ILogger<QBittorrentController> logger, QBitto
[HttpPost]
public ActionResult<AppPreferences> AppDefaultSavePath()
{
var result = Settings.AppDefaultSavePath;
var result = settings.DefaultSavePath;
return Ok(result);
}
@ -613,7 +613,7 @@ public class QBittorrentController(ILogger<QBittorrentController> logger, QBitto
[HttpGet]
public ActionResult TransferInfo()
{
return Ok(QBittorrent.TransferInfo());
return Ok(qBittorrent.TransferInfo());
}
[Authorize(Policy = "AuthSetting")]

View file

@ -15,13 +15,13 @@ namespace RdtClient.Web.Controllers;
[Authorize(Policy = "AuthSetting")]
[Route("Api/Settings")]
public class SettingsController(Settings settings, Torrents torrents) : Controller
public class SettingsController(ISettings settings, Torrents torrents) : Controller
{
[HttpGet]
[Route("")]
public ActionResult Get()
{
var result = SettingData.GetAll();
var result = settings.GetAll();
return Ok(result);
}
@ -95,7 +95,7 @@ public class SettingsController(Settings settings, Torrents torrents) : Controll
[Route("TestDownloadSpeed")]
public async Task<ActionResult> TestDownloadSpeed(CancellationToken cancellationToken)
{
var downloadPath = Settings.Get.DownloadClient.DownloadPath;
var downloadPath = settings.Current.DownloadClient.DownloadPath;
var testFilePath = Path.Combine(downloadPath, "testDefault.rar");
@ -106,7 +106,7 @@ public class SettingsController(Settings settings, Torrents torrents) : Controll
Link = "https://34.download.real-debrid.com/speedtest/testDefault.rar",
Torrent = new()
{
DownloadClient = Settings.Get.DownloadClient.Client == DownloadClient.Symlink ? DownloadClient.Bezzad : Settings.Get.DownloadClient.Client,
DownloadClient = settings.Current.DownloadClient.Client == DownloadClient.Symlink ? DownloadClient.Bezzad : settings.Current.DownloadClient.Client,
RdName = "testDefault.rar"
}
};
@ -131,7 +131,7 @@ public class SettingsController(Settings settings, Torrents torrents) : Controll
if (downloadClient.Downloader is Aria2cDownloader aria2Downloader)
{
var aria2NetClient = new Aria2NetClient(Settings.Get.DownloadClient.Aria2cUrl, Settings.Get.DownloadClient.Aria2cSecret, httpClient, 1);
var aria2NetClient = new Aria2NetClient(settings.Current.DownloadClient.Aria2cUrl, settings.Current.DownloadClient.Aria2cSecret, httpClient, 1);
var allDownloads = await aria2NetClient.TellAllAsync(cancellationToken);
@ -155,7 +155,7 @@ public class SettingsController(Settings settings, Torrents torrents) : Controll
[Route("TestWriteSpeed")]
public async Task<ActionResult> TestWriteSpeed()
{
var downloadPath = Settings.Get.DownloadClient.DownloadPath;
var downloadPath = settings.Current.DownloadClient.DownloadPath;
var testFilePath = Path.Combine(downloadPath, "test.tmp");