Add nullable to the projects.
This commit is contained in:
parent
e65942adb7
commit
e3b38d2834
57 changed files with 945 additions and 747 deletions
|
|
@ -4,6 +4,8 @@ using RdtClient.Data.Models.Data;
|
|||
|
||||
namespace RdtClient.Data.Data;
|
||||
|
||||
#nullable disable
|
||||
|
||||
public class DataContext : IdentityDbContext
|
||||
{
|
||||
public DataContext(DbContextOptions options) : base(options)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public class DownloadData
|
|||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<Download> GetById(Guid downloadId)
|
||||
public async Task<Download?> GetById(Guid downloadId)
|
||||
{
|
||||
return await _dataContext.Downloads
|
||||
.Include(m => m.Torrent)
|
||||
|
|
@ -28,7 +28,7 @@ public class DownloadData
|
|||
.FirstOrDefaultAsync(m => m.DownloadId == downloadId);
|
||||
}
|
||||
|
||||
public async Task<Download> Get(Guid torrentId, String path)
|
||||
public async Task<Download?> Get(Guid torrentId, String path)
|
||||
{
|
||||
return await _dataContext.Downloads
|
||||
.Include(m => m.Torrent)
|
||||
|
|
@ -176,7 +176,7 @@ public class DownloadData
|
|||
await TorrentData.VoidCache();
|
||||
}
|
||||
|
||||
public async Task UpdateError(Guid downloadId, String error)
|
||||
public async Task UpdateError(Guid downloadId, String? error)
|
||||
{
|
||||
var dbDownload = await _dataContext.Downloads
|
||||
.FirstOrDefaultAsync(m => m.DownloadId == downloadId);
|
||||
|
|
@ -243,6 +243,11 @@ public class DownloadData
|
|||
var dbDownload = await _dataContext.Downloads
|
||||
.FirstOrDefaultAsync(m => m.DownloadId == downloadId);
|
||||
|
||||
if (dbDownload == null)
|
||||
{
|
||||
throw new Exception($"Cannot find download with ID {downloadId}");
|
||||
}
|
||||
|
||||
dbDownload.RetryCount = 0;
|
||||
dbDownload.Link = null;
|
||||
dbDownload.Added = DateTimeOffset.UtcNow;
|
||||
|
|
|
|||
|
|
@ -13,16 +13,16 @@ public class SettingData
|
|||
|
||||
public static DbSettings Get { get; } = new DbSettings();
|
||||
|
||||
public static IList<SettingProperty> GetAll()
|
||||
{
|
||||
return GetSettings(Get, null).ToList();
|
||||
}
|
||||
|
||||
public SettingData(DataContext dataContext)
|
||||
{
|
||||
_dataContext = dataContext;
|
||||
}
|
||||
|
||||
public IList<SettingProperty> GetAll()
|
||||
{
|
||||
return GetSettings(Get, null).ToList();
|
||||
}
|
||||
|
||||
public async Task Update(IList<SettingProperty> settings)
|
||||
{
|
||||
var dbSettings = await _dataContext.Settings.ToListAsync();
|
||||
|
|
@ -33,7 +33,7 @@ public class SettingData
|
|||
|
||||
if (setting != null)
|
||||
{
|
||||
dbSetting.Value = setting.Value.ToString();
|
||||
dbSetting.Value = setting.Value?.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ public class SettingData
|
|||
await ResetCache();
|
||||
}
|
||||
|
||||
public async Task Update(String settingId, Object value)
|
||||
public async Task Update(String settingId, Object? value)
|
||||
{
|
||||
var dbSetting = await _dataContext.Settings.FirstOrDefaultAsync(m => m.SettingId == settingId);
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ public class SettingData
|
|||
return;
|
||||
}
|
||||
|
||||
dbSetting.Value = value.ToString();
|
||||
dbSetting.Value = value?.ToString();
|
||||
|
||||
await _dataContext.SaveChangesAsync();
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ public class SettingData
|
|||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<SettingProperty> GetSettings(Object defaultSetting, String parent)
|
||||
private static IEnumerable<SettingProperty> GetSettings(Object defaultSetting, String? parent)
|
||||
{
|
||||
var result = new List<SettingProperty>();
|
||||
|
||||
|
|
@ -105,8 +105,8 @@ public class SettingData
|
|||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var displayName = (DisplayNameAttribute) Attribute.GetCustomAttribute(property, typeof(DisplayNameAttribute));
|
||||
var description = (DescriptionAttribute) Attribute.GetCustomAttribute(property, typeof(DescriptionAttribute));
|
||||
var displayName = Attribute.GetCustomAttribute(property, typeof(DisplayNameAttribute)) as DisplayNameAttribute;
|
||||
var description = Attribute.GetCustomAttribute(property, typeof(DescriptionAttribute)) as DescriptionAttribute;
|
||||
var propertyName = property.Name;
|
||||
|
||||
if (parent != null)
|
||||
|
|
@ -137,7 +137,7 @@ public class SettingData
|
|||
{
|
||||
var enumMember = property.PropertyType.GetMember(e.ToString()).First();
|
||||
var enumDescriptionAttribute = enumMember.GetCustomAttribute<DescriptionAttribute>();
|
||||
var enumName = enumDescriptionAttribute?.Description ?? Enum.GetName(property.PropertyType, e);
|
||||
var enumName = enumDescriptionAttribute?.Description ?? Enum.GetName(property.PropertyType, e) ?? "Unknown value";
|
||||
settingProperty.EnumValues.Add((Int32)(Object)e, enumName);
|
||||
}
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ public class SettingData
|
|||
settingProperty.Type = "Object";
|
||||
result.Add(settingProperty);
|
||||
|
||||
var childResults = GetSettings(property.GetValue(defaultSetting), propertyName);
|
||||
var childResults = GetSettings(property.GetValue(defaultSetting)!, propertyName);
|
||||
result.AddRange(childResults);
|
||||
}
|
||||
}
|
||||
|
|
@ -157,7 +157,7 @@ public class SettingData
|
|||
return result;
|
||||
}
|
||||
|
||||
private static void SetSettings(IList<Setting> settings, Object defaultSetting, String parent)
|
||||
private static void SetSettings(IList<Setting> settings, Object defaultSetting, String? parent)
|
||||
{
|
||||
var properties = defaultSetting.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
|
|
@ -180,14 +180,18 @@ public class SettingData
|
|||
{
|
||||
if (property.PropertyType.IsEnum)
|
||||
{
|
||||
var newValue = Enum.Parse(property.PropertyType, setting.Value);
|
||||
var newValue = Enum.Parse(property.PropertyType, setting.Value ?? "0");
|
||||
property.SetValue(defaultSetting, newValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
var converter = TypeDescriptor.GetConverter(property.PropertyType);
|
||||
|
||||
if (converter.IsValid(setting.Value))
|
||||
if (setting.Value == null)
|
||||
{
|
||||
property.SetValue(defaultSetting, null);
|
||||
}
|
||||
else if (converter.IsValid(setting.Value))
|
||||
{
|
||||
var newValue = converter.ConvertFrom(setting.Value);
|
||||
property.SetValue(defaultSetting, newValue);
|
||||
|
|
@ -201,7 +205,7 @@ public class SettingData
|
|||
}
|
||||
else
|
||||
{
|
||||
SetSettings(settings, property.GetValue(defaultSetting), propertyName);
|
||||
SetSettings(settings, property.GetValue(defaultSetting)!, propertyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ namespace RdtClient.Data.Data;
|
|||
|
||||
public class TorrentData
|
||||
{
|
||||
private static IList<Torrent> _torrentCache;
|
||||
private static IList<Torrent>? _torrentCache;
|
||||
|
||||
private static readonly SemaphoreSlim TorrentCacheLock = new(1, 1);
|
||||
|
||||
private readonly DataContext _dataContext;
|
||||
|
|
@ -34,7 +35,7 @@ public class TorrentData
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<Torrent> GetById(Guid torrentId)
|
||||
public async Task<Torrent?> GetById(Guid torrentId)
|
||||
{
|
||||
var dbTorrent = await _dataContext.Torrents
|
||||
.AsNoTracking()
|
||||
|
|
@ -54,7 +55,7 @@ public class TorrentData
|
|||
return dbTorrent;
|
||||
}
|
||||
|
||||
public async Task<Torrent> GetByHash(String hash)
|
||||
public async Task<Torrent?> GetByHash(String hash)
|
||||
{
|
||||
var dbTorrent = await _dataContext.Torrents
|
||||
.AsNoTracking()
|
||||
|
|
@ -76,7 +77,7 @@ public class TorrentData
|
|||
|
||||
public async Task<Torrent> Add(String realDebridId,
|
||||
String hash,
|
||||
String fileOrMagnetContents,
|
||||
String? fileOrMagnetContents,
|
||||
Boolean isFile,
|
||||
Torrent torrent)
|
||||
{
|
||||
|
|
@ -129,12 +130,8 @@ public class TorrentData
|
|||
dbTorrent.RdEnded = torrent.RdEnded;
|
||||
dbTorrent.RdSpeed = torrent.RdSpeed;
|
||||
dbTorrent.RdSeeders = torrent.RdSeeders;
|
||||
|
||||
if (torrent.Files != null)
|
||||
{
|
||||
dbTorrent.RdFiles = torrent.RdFiles;
|
||||
}
|
||||
|
||||
dbTorrent.RdFiles = torrent.RdFiles;
|
||||
|
||||
await _dataContext.SaveChangesAsync();
|
||||
|
||||
await VoidCache();
|
||||
|
|
@ -160,7 +157,7 @@ public class TorrentData
|
|||
await VoidCache();
|
||||
}
|
||||
|
||||
public async Task UpdateCategory(Guid torrentId, String category)
|
||||
public async Task UpdateCategory(Guid torrentId, String? category)
|
||||
{
|
||||
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
|
||||
|
||||
|
|
@ -176,7 +173,7 @@ public class TorrentData
|
|||
await VoidCache();
|
||||
}
|
||||
|
||||
public async Task UpdateComplete(Guid torrentId, String error, DateTimeOffset? datetime, Boolean retry)
|
||||
public async Task UpdateComplete(Guid torrentId, String? error, DateTimeOffset? datetime, Boolean retry)
|
||||
{
|
||||
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public class UserData
|
|||
_dataContext = dataContext;
|
||||
}
|
||||
|
||||
public async Task<IdentityUser> GetUser()
|
||||
public async Task<IdentityUser?> GetUser()
|
||||
{
|
||||
return await _dataContext.Users.FirstOrDefaultAsync();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,11 @@ public static class DiConfig
|
|||
{
|
||||
public static void Config(IServiceCollection services, AppSettings appSettings)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(appSettings.Database?.Path))
|
||||
{
|
||||
throw new Exception("Invalid database path found in appSettings");
|
||||
}
|
||||
|
||||
var connectionString = $"Data Source={appSettings.Database.Path}";
|
||||
services.AddDbContext<DataContext>(options => options.UseSqlite(connectionString));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
namespace RdtClient.Data.Enums;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace RdtClient.Data.Enums;
|
||||
|
||||
public enum DownloadClient
|
||||
{
|
||||
[Description("Simple Downloader")]
|
||||
Simple,
|
||||
|
||||
[Description("Multi-Part Downloader")]
|
||||
MultiPart,
|
||||
|
||||
[Description("Aria2c")]
|
||||
Aria2c
|
||||
}
|
||||
|
|
@ -11,10 +11,10 @@ public class Download
|
|||
public Guid TorrentId { get; set; }
|
||||
|
||||
[ForeignKey("TorrentId")]
|
||||
public Torrent Torrent { get; set; }
|
||||
public Torrent? Torrent { get; set; }
|
||||
|
||||
public String Path { get; set; }
|
||||
public String Link { get; set; }
|
||||
public String Path { get; set; } = null!;
|
||||
public String? Link { get; set; }
|
||||
|
||||
public DateTimeOffset Added { get; set; }
|
||||
public DateTimeOffset? DownloadQueued { get; set; }
|
||||
|
|
@ -27,9 +27,9 @@ public class Download
|
|||
|
||||
public Int32 RetryCount { get; set; }
|
||||
|
||||
public String Error { get; set; }
|
||||
public String? Error { get; set; }
|
||||
|
||||
public String RemoteId { get; set; }
|
||||
public String? RemoteId { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public Int64 BytesTotal { get; set; }
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace RdtClient.Data.Models.Data;
|
|||
public class Setting
|
||||
{
|
||||
[Key]
|
||||
public String SettingId { get; set; }
|
||||
public String SettingId { get; set; } = null!;
|
||||
|
||||
public String Value { get; set; }
|
||||
public String? Value { get; set; }
|
||||
}
|
||||
|
|
@ -11,21 +11,21 @@ public class Torrent
|
|||
[Key]
|
||||
public Guid TorrentId { get; set; }
|
||||
|
||||
public String Hash { get; set; }
|
||||
public String Hash { get; set; } = null!;
|
||||
|
||||
public String Category { get; set; }
|
||||
public String? Category { get; set; }
|
||||
|
||||
public TorrentDownloadAction DownloadAction { get; set; }
|
||||
public TorrentFinishedAction FinishedAction { get; set; }
|
||||
public Int32 DownloadMinSize { get; set; }
|
||||
public String DownloadManualFiles { get; set; }
|
||||
public String? DownloadManualFiles { get; set; }
|
||||
|
||||
public DateTimeOffset Added { get; set; }
|
||||
public DateTimeOffset? FilesSelected { get; set; }
|
||||
public DateTimeOffset? Completed { get; set; }
|
||||
public DateTimeOffset? Retry { get; set; }
|
||||
|
||||
public String FileOrMagnet { get; set; }
|
||||
public String? FileOrMagnet { get; set; }
|
||||
public Boolean IsFile { get; set; }
|
||||
|
||||
public Int32? Priority { get; set; }
|
||||
|
|
@ -35,24 +35,24 @@ public class Torrent
|
|||
public Int32 DeleteOnError { get; set; }
|
||||
public Int32 Lifetime { get; set; }
|
||||
|
||||
public String Error { get; set; }
|
||||
public String? Error { get; set; }
|
||||
|
||||
[InverseProperty("Torrent")]
|
||||
public IList<Download> Downloads { get; set; }
|
||||
public IList<Download> Downloads { get; set; } = new List<Download>();
|
||||
|
||||
public String RdId { get; set; }
|
||||
public String RdName { get; set; }
|
||||
public Int64 RdSize { get; set; }
|
||||
public String RdHost { get; set; }
|
||||
public Int64 RdSplit { get; set; }
|
||||
public Int64 RdProgress { get; set; }
|
||||
public TorrentStatus RdStatus { get; set; }
|
||||
public String RdStatusRaw { get; set; }
|
||||
public DateTimeOffset RdAdded { get; set; }
|
||||
public String? RdId { get; set; }
|
||||
public String? RdName { get; set; }
|
||||
public Int64? RdSize { get; set; }
|
||||
public String? RdHost { get; set; }
|
||||
public Int64? RdSplit { get; set; }
|
||||
public Int64? RdProgress { get; set; }
|
||||
public TorrentStatus? RdStatus { get; set; }
|
||||
public String? RdStatusRaw { get; set; }
|
||||
public DateTimeOffset? RdAdded { get; set; }
|
||||
public DateTimeOffset? RdEnded { get; set; }
|
||||
public Int64? RdSpeed { get; set; }
|
||||
public Int64? RdSeeders { get; set; }
|
||||
public String RdFiles { get; set; }
|
||||
public String? RdFiles { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public IList<TorrentClientFile> Files
|
||||
|
|
@ -66,7 +66,7 @@ public class Torrent
|
|||
|
||||
try
|
||||
{
|
||||
return JsonSerializer.Deserialize<List<TorrentClientFile>>(RdFiles);
|
||||
return JsonSerializer.Deserialize<List<TorrentClientFile>>(RdFiles) ?? new List<TorrentClientFile>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,25 +2,25 @@
|
|||
|
||||
public class AppSettings
|
||||
{
|
||||
public AppSettingsLogging Logging { get; set; }
|
||||
public AppSettingsDatabase Database { get; set; }
|
||||
public AppSettingsLogging? Logging { get; set; }
|
||||
public AppSettingsDatabase? Database { get; set; }
|
||||
|
||||
public Int32 Port { get; set; }
|
||||
}
|
||||
|
||||
public class AppSettingsLogging
|
||||
{
|
||||
public AppSettingsLoggingFile File { get; set; }
|
||||
public AppSettingsLoggingFile? File { get; set; }
|
||||
}
|
||||
|
||||
public class AppSettingsLoggingFile
|
||||
{
|
||||
public String Path { get; set; }
|
||||
public String? Path { get; set; }
|
||||
public Int64 FileSizeLimitBytes { get; set; }
|
||||
public Int32 MaxRollingFiles { get; set; }
|
||||
}
|
||||
|
||||
public class AppSettingsDatabase
|
||||
{
|
||||
public String Path { get; set; }
|
||||
public String? Path { get; set; }
|
||||
}
|
||||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
public class Profile
|
||||
{
|
||||
public String Provider { get; set; }
|
||||
public String UserName { get; set; }
|
||||
public String? Provider { get; set; }
|
||||
public String? UserName { get; set; }
|
||||
public DateTimeOffset? Expiration { get; set; }
|
||||
public String CurrentVersion { get; set; }
|
||||
public String LatestVersion { get; set; }
|
||||
public String? CurrentVersion { get; set; }
|
||||
public String? LatestVersion { get; set; }
|
||||
}
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
public class SettingProperty
|
||||
{
|
||||
public String Key { get; set; }
|
||||
public Object Value { get; set; }
|
||||
public String DisplayName { get; set; }
|
||||
public String Description { get; set; }
|
||||
public String Type { get; set; }
|
||||
public Dictionary<Int32, String> EnumValues { get; set; }
|
||||
public String Key { get; set; } = default!;
|
||||
public Object? Value { get; set; }
|
||||
public String? DisplayName { get; set; }
|
||||
public String? Description { get; set; }
|
||||
public String Type { get; set; } = default!;
|
||||
public Dictionary<Int32, String>? EnumValues { get; set; }
|
||||
}
|
||||
|
|
@ -5,20 +5,20 @@ namespace RdtClient.Data.Models.QBittorrent;
|
|||
public class AppBuildInfo
|
||||
{
|
||||
[JsonPropertyName("bitness")]
|
||||
public Int64 Bitness { get; set; }
|
||||
public Int64? Bitness { get; set; }
|
||||
|
||||
[JsonPropertyName("boost")]
|
||||
public String Boost { get; set; }
|
||||
public String? Boost { get; set; }
|
||||
|
||||
[JsonPropertyName("libtorrent")]
|
||||
public String Libtorrent { get; set; }
|
||||
public String? Libtorrent { get; set; }
|
||||
|
||||
[JsonPropertyName("openssl")]
|
||||
public String Openssl { get; set; }
|
||||
public String? Openssl { get; set; }
|
||||
|
||||
[JsonPropertyName("qt")]
|
||||
public String Qt { get; set; }
|
||||
public String? Qt { get; set; }
|
||||
|
||||
[JsonPropertyName("zlib")]
|
||||
public String Zlib { get; set; }
|
||||
public String? Zlib { get; set; }
|
||||
}
|
||||
|
|
@ -5,424 +5,424 @@ namespace RdtClient.Data.Models.QBittorrent;
|
|||
public class AppPreferences
|
||||
{
|
||||
[JsonPropertyName("add_trackers")]
|
||||
public String AddTrackers { get; set; }
|
||||
public String? AddTrackers { get; set; }
|
||||
|
||||
[JsonPropertyName("add_trackers_enabled")]
|
||||
public Boolean AddTrackersEnabled { get; set; }
|
||||
public Boolean? AddTrackersEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("alt_dl_limit")]
|
||||
public Int64 AltDlLimit { get; set; }
|
||||
public Int64? AltDlLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("alt_up_limit")]
|
||||
public Int64 AltUpLimit { get; set; }
|
||||
public Int64? AltUpLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("alternative_webui_enabled")]
|
||||
public Boolean AlternativeWebuiEnabled { get; set; }
|
||||
public Boolean? AlternativeWebuiEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("alternative_webui_path")]
|
||||
public String AlternativeWebuiPath { get; set; }
|
||||
public String? AlternativeWebuiPath { get; set; }
|
||||
|
||||
[JsonPropertyName("announce_ip")]
|
||||
public String AnnounceIp { get; set; }
|
||||
public String? AnnounceIp { get; set; }
|
||||
|
||||
[JsonPropertyName("announce_to_all_tiers")]
|
||||
public Boolean AnnounceToAllTiers { get; set; }
|
||||
public Boolean? AnnounceToAllTiers { get; set; }
|
||||
|
||||
[JsonPropertyName("announce_to_all_trackers")]
|
||||
public Boolean AnnounceToAllTrackers { get; set; }
|
||||
public Boolean? AnnounceToAllTrackers { get; set; }
|
||||
|
||||
[JsonPropertyName("anonymous_mode")]
|
||||
public Boolean AnonymousMode { get; set; }
|
||||
public Boolean? AnonymousMode { get; set; }
|
||||
|
||||
[JsonPropertyName("async_io_threads")]
|
||||
public Int64 AsyncIoThreads { get; set; }
|
||||
public Int64? AsyncIoThreads { get; set; }
|
||||
|
||||
[JsonPropertyName("auto_delete_mode")]
|
||||
public Int64 AutoDeleteMode { get; set; }
|
||||
public Int64? AutoDeleteMode { get; set; }
|
||||
|
||||
[JsonPropertyName("auto_tmm_enabled")]
|
||||
public Boolean AutoTmmEnabled { get; set; }
|
||||
public Boolean? AutoTmmEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("autorun_enabled")]
|
||||
public Boolean AutorunEnabled { get; set; }
|
||||
public Boolean? AutorunEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("autorun_program")]
|
||||
public String AutorunProgram { get; set; }
|
||||
public String? AutorunProgram { get; set; }
|
||||
|
||||
[JsonPropertyName("banned_IPs")]
|
||||
public String BannedIPs { get; set; }
|
||||
public String? BannedIPs { get; set; }
|
||||
|
||||
[JsonPropertyName("bittorrent_protocol")]
|
||||
public Int64 BittorrentProtocol { get; set; }
|
||||
public Int64? BittorrentProtocol { get; set; }
|
||||
|
||||
[JsonPropertyName("bypass_auth_subnet_whitelist")]
|
||||
public String BypassAuthSubnetWhitelist { get; set; }
|
||||
public String? BypassAuthSubnetWhitelist { get; set; }
|
||||
|
||||
[JsonPropertyName("bypass_auth_subnet_whitelist_enabled")]
|
||||
public Boolean BypassAuthSubnetWhitelistEnabled { get; set; }
|
||||
public Boolean? BypassAuthSubnetWhitelistEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("bypass_local_auth")]
|
||||
public Boolean BypassLocalAuth { get; set; }
|
||||
public Boolean? BypassLocalAuth { get; set; }
|
||||
|
||||
[JsonPropertyName("category_changed_tmm_enabled")]
|
||||
public Boolean CategoryChangedTmmEnabled { get; set; }
|
||||
public Boolean? CategoryChangedTmmEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("checking_memory_use")]
|
||||
public Int64 CheckingMemoryUse { get; set; }
|
||||
public Int64? CheckingMemoryUse { get; set; }
|
||||
|
||||
[JsonPropertyName("create_subfolder_enabled")]
|
||||
public Boolean CreateSubfolderEnabled { get; set; }
|
||||
public Boolean? CreateSubfolderEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("current_interface_address")]
|
||||
public String CurrentInterfaceAddress { get; set; }
|
||||
public String? CurrentInterfaceAddress { get; set; }
|
||||
|
||||
[JsonPropertyName("current_network_interface")]
|
||||
public String CurrentNetworkInterface { get; set; }
|
||||
public String? CurrentNetworkInterface { get; set; }
|
||||
|
||||
[JsonPropertyName("dht")]
|
||||
public Boolean Dht { get; set; }
|
||||
public Boolean? Dht { get; set; }
|
||||
|
||||
[JsonPropertyName("disk_cache")]
|
||||
public Int64 DiskCache { get; set; }
|
||||
public Int64? DiskCache { get; set; }
|
||||
|
||||
[JsonPropertyName("disk_cache_ttl")]
|
||||
public Int64 DiskCacheTtl { get; set; }
|
||||
public Int64? DiskCacheTtl { get; set; }
|
||||
|
||||
[JsonPropertyName("dl_limit")]
|
||||
public Int64 DlLimit { get; set; }
|
||||
public Int64? DlLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("dont_count_slow_torrents")]
|
||||
public Boolean DontCountSlowTorrents { get; set; }
|
||||
public Boolean? DontCountSlowTorrents { get; set; }
|
||||
|
||||
[JsonPropertyName("dyndns_domain")]
|
||||
public String DyndnsDomain { get; set; }
|
||||
public String? DyndnsDomain { get; set; }
|
||||
|
||||
[JsonPropertyName("dyndns_enabled")]
|
||||
public Boolean DyndnsEnabled { get; set; }
|
||||
public Boolean? DyndnsEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("dyndns_password")]
|
||||
public String DyndnsPassword { get; set; }
|
||||
public String? DyndnsPassword { get; set; }
|
||||
|
||||
[JsonPropertyName("dyndns_service")]
|
||||
public Int64 DyndnsService { get; set; }
|
||||
public Int64? DyndnsService { get; set; }
|
||||
|
||||
[JsonPropertyName("dyndns_username")]
|
||||
public String DyndnsUsername { get; set; }
|
||||
public String? DyndnsUsername { get; set; }
|
||||
|
||||
[JsonPropertyName("embedded_tracker_port")]
|
||||
public Int64 EmbeddedTrackerPort { get; set; }
|
||||
public Int64? EmbeddedTrackerPort { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_coalesce_read_write")]
|
||||
public Boolean EnableCoalesceReadWrite { get; set; }
|
||||
public Boolean? EnableCoalesceReadWrite { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_embedded_tracker")]
|
||||
public Boolean EnableEmbeddedTracker { get; set; }
|
||||
public Boolean? EnableEmbeddedTracker { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_multi_connections_from_same_ip")]
|
||||
public Boolean EnableMultiConnectionsFromSameIp { get; set; }
|
||||
public Boolean? EnableMultiConnectionsFromSameIp { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_os_cache")]
|
||||
public Boolean EnableOsCache { get; set; }
|
||||
public Boolean? EnableOsCache { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_piece_extent_affinity")]
|
||||
public Boolean EnablePieceExtentAffinity { get; set; }
|
||||
public Boolean? EnablePieceExtentAffinity { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_super_seeding")]
|
||||
public Boolean EnableSuperSeeding { get; set; }
|
||||
public Boolean? EnableSuperSeeding { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_upload_suggestions")]
|
||||
public Boolean EnableUploadSuggestions { get; set; }
|
||||
public Boolean? EnableUploadSuggestions { get; set; }
|
||||
|
||||
[JsonPropertyName("encryption")]
|
||||
public Int64 Encryption { get; set; }
|
||||
public Int64? Encryption { get; set; }
|
||||
|
||||
[JsonPropertyName("export_dir")]
|
||||
public String ExportDir { get; set; }
|
||||
public String? ExportDir { get; set; }
|
||||
|
||||
[JsonPropertyName("export_dir_fin")]
|
||||
public String ExportDirFin { get; set; }
|
||||
public String? ExportDirFin { get; set; }
|
||||
|
||||
[JsonPropertyName("file_pool_size")]
|
||||
public Int64 FilePoolSize { get; set; }
|
||||
public Int64? FilePoolSize { get; set; }
|
||||
|
||||
[JsonPropertyName("incomplete_files_ext")]
|
||||
public Boolean IncompleteFilesExt { get; set; }
|
||||
public Boolean? IncompleteFilesExt { get; set; }
|
||||
|
||||
[JsonPropertyName("ip_filter_enabled")]
|
||||
public Boolean IpFilterEnabled { get; set; }
|
||||
public Boolean? IpFilterEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("ip_filter_path")]
|
||||
public String IpFilterPath { get; set; }
|
||||
public String? IpFilterPath { get; set; }
|
||||
|
||||
[JsonPropertyName("ip_filter_trackers")]
|
||||
public Boolean IpFilterTrackers { get; set; }
|
||||
public Boolean? IpFilterTrackers { get; set; }
|
||||
|
||||
[JsonPropertyName("limit_lan_peers")]
|
||||
public Boolean LimitLanPeers { get; set; }
|
||||
public Boolean? LimitLanPeers { get; set; }
|
||||
|
||||
[JsonPropertyName("limit_tcp_overhead")]
|
||||
public Boolean LimitTcpOverhead { get; set; }
|
||||
public Boolean? LimitTcpOverhead { get; set; }
|
||||
|
||||
[JsonPropertyName("limit_utp_rate")]
|
||||
public Boolean LimitUtpRate { get; set; }
|
||||
public Boolean? LimitUtpRate { get; set; }
|
||||
|
||||
[JsonPropertyName("listen_port")]
|
||||
public Int64 ListenPort { get; set; }
|
||||
public Int64? ListenPort { get; set; }
|
||||
|
||||
[JsonPropertyName("locale")]
|
||||
public String Locale { get; set; }
|
||||
public String? Locale { get; set; }
|
||||
|
||||
[JsonPropertyName("lsd")]
|
||||
public Boolean Lsd { get; set; }
|
||||
public Boolean? Lsd { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_auth_enabled")]
|
||||
public Boolean MailNotificationAuthEnabled { get; set; }
|
||||
public Boolean? MailNotificationAuthEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_email")]
|
||||
public String MailNotificationEmail { get; set; }
|
||||
public String? MailNotificationEmail { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_enabled")]
|
||||
public Boolean MailNotificationEnabled { get; set; }
|
||||
public Boolean? MailNotificationEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_password")]
|
||||
public String MailNotificationPassword { get; set; }
|
||||
public String? MailNotificationPassword { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_sender")]
|
||||
public String MailNotificationSender { get; set; }
|
||||
public String? MailNotificationSender { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_smtp")]
|
||||
public String MailNotificationSmtp { get; set; }
|
||||
public String? MailNotificationSmtp { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_ssl_enabled")]
|
||||
public Boolean MailNotificationSslEnabled { get; set; }
|
||||
public Boolean? MailNotificationSslEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_username")]
|
||||
public String MailNotificationUsername { get; set; }
|
||||
public String? MailNotificationUsername { get; set; }
|
||||
|
||||
[JsonPropertyName("max_active_downloads")]
|
||||
public Int64 MaxActiveDownloads { get; set; }
|
||||
public Int64? MaxActiveDownloads { get; set; }
|
||||
|
||||
[JsonPropertyName("max_active_torrents")]
|
||||
public Int64 MaxActiveTorrents { get; set; }
|
||||
public Int64? MaxActiveTorrents { get; set; }
|
||||
|
||||
[JsonPropertyName("max_active_uploads")]
|
||||
public Int64 MaxActiveUploads { get; set; }
|
||||
public Int64? MaxActiveUploads { get; set; }
|
||||
|
||||
[JsonPropertyName("max_connec")]
|
||||
public Int64 MaxConnec { get; set; }
|
||||
public Int64? MaxConnec { get; set; }
|
||||
|
||||
[JsonPropertyName("max_connec_per_torrent")]
|
||||
public Int64 MaxConnecPerTorrent { get; set; }
|
||||
public Int64? MaxConnecPerTorrent { get; set; }
|
||||
|
||||
[JsonPropertyName("max_ratio")]
|
||||
public Int64 MaxRatio { get; set; }
|
||||
public Int64? MaxRatio { get; set; }
|
||||
|
||||
[JsonPropertyName("max_ratio_act")]
|
||||
public Int64 MaxRatioAct { get; set; }
|
||||
public Int64? MaxRatioAct { get; set; }
|
||||
|
||||
[JsonPropertyName("max_ratio_enabled")]
|
||||
public Boolean MaxRatioEnabled { get; set; }
|
||||
public Boolean? MaxRatioEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("max_seeding_time")]
|
||||
public Int64 MaxSeedingTime { get; set; }
|
||||
public Int64? MaxSeedingTime { get; set; }
|
||||
|
||||
[JsonPropertyName("max_seeding_time_enabled")]
|
||||
public Boolean MaxSeedingTimeEnabled { get; set; }
|
||||
public Boolean? MaxSeedingTimeEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("max_uploads")]
|
||||
public Int64 MaxUploads { get; set; }
|
||||
public Int64? MaxUploads { get; set; }
|
||||
|
||||
[JsonPropertyName("max_uploads_per_torrent")]
|
||||
public Int64 MaxUploadsPerTorrent { get; set; }
|
||||
public Int64? MaxUploadsPerTorrent { get; set; }
|
||||
|
||||
[JsonPropertyName("outgoing_ports_max")]
|
||||
public Int64 OutgoingPortsMax { get; set; }
|
||||
public Int64? OutgoingPortsMax { get; set; }
|
||||
|
||||
[JsonPropertyName("outgoing_ports_min")]
|
||||
public Int64 OutgoingPortsMin { get; set; }
|
||||
public Int64? OutgoingPortsMin { get; set; }
|
||||
|
||||
[JsonPropertyName("pex")]
|
||||
public Boolean Pex { get; set; }
|
||||
public Boolean? Pex { get; set; }
|
||||
|
||||
[JsonPropertyName("preallocate_all")]
|
||||
public Boolean PreallocateAll { get; set; }
|
||||
public Boolean? PreallocateAll { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_auth_enabled")]
|
||||
public Boolean ProxyAuthEnabled { get; set; }
|
||||
public Boolean? ProxyAuthEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_ip")]
|
||||
public String ProxyIp { get; set; }
|
||||
public String? ProxyIp { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_password")]
|
||||
public String ProxyPassword { get; set; }
|
||||
public String? ProxyPassword { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_peer_connections")]
|
||||
public Boolean ProxyPeerConnections { get; set; }
|
||||
public Boolean? ProxyPeerConnections { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_port")]
|
||||
public Int64 ProxyPort { get; set; }
|
||||
public Int64? ProxyPort { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_torrents_only")]
|
||||
public Boolean ProxyTorrentsOnly { get; set; }
|
||||
public Boolean? ProxyTorrentsOnly { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_type")]
|
||||
public Int64 ProxyType { get; set; }
|
||||
public Int64? ProxyType { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_username")]
|
||||
public String ProxyUsername { get; set; }
|
||||
public String? ProxyUsername { get; set; }
|
||||
|
||||
[JsonPropertyName("queueing_enabled")]
|
||||
public Boolean QueueingEnabled { get; set; }
|
||||
public Boolean? QueueingEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("random_port")]
|
||||
public Boolean RandomPort { get; set; }
|
||||
public Boolean? RandomPort { get; set; }
|
||||
|
||||
[JsonPropertyName("recheck_completed_torrents")]
|
||||
public Boolean RecheckCompletedTorrents { get; set; }
|
||||
public Boolean? RecheckCompletedTorrents { get; set; }
|
||||
|
||||
[JsonPropertyName("resolve_peer_countries")]
|
||||
public Boolean ResolvePeerCountries { get; set; }
|
||||
public Boolean? ResolvePeerCountries { get; set; }
|
||||
|
||||
[JsonPropertyName("rss_auto_downloading_enabled")]
|
||||
public Boolean RssAutoDownloadingEnabled { get; set; }
|
||||
public Boolean? RssAutoDownloadingEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("rss_max_articles_per_feed")]
|
||||
public Int64 RssMaxArticlesPerFeed { get; set; }
|
||||
public Int64? RssMaxArticlesPerFeed { get; set; }
|
||||
|
||||
[JsonPropertyName("rss_processing_enabled")]
|
||||
public Boolean RssProcessingEnabled { get; set; }
|
||||
public Boolean? RssProcessingEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("rss_refresh_interval")]
|
||||
public Int64 RssRefreshInterval { get; set; }
|
||||
public Int64? RssRefreshInterval { get; set; }
|
||||
|
||||
[JsonPropertyName("save_path")]
|
||||
public String SavePath { get; set; }
|
||||
public String? SavePath { get; set; }
|
||||
|
||||
[JsonPropertyName("save_path_changed_tmm_enabled")]
|
||||
public Boolean SavePathChangedTmmEnabled { get; set; }
|
||||
public Boolean? SavePathChangedTmmEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("save_resume_data_interval")]
|
||||
public Int64 SaveResumeDataInterval { get; set; }
|
||||
public Int64? SaveResumeDataInterval { get; set; }
|
||||
|
||||
[JsonPropertyName("scan_dirs")]
|
||||
public ScanDirs ScanDirs { get; set; }
|
||||
public ScanDirs? ScanDirs { get; set; }
|
||||
|
||||
[JsonPropertyName("schedule_from_hour")]
|
||||
public Int64 ScheduleFromHour { get; set; }
|
||||
public Int64? ScheduleFromHour { get; set; }
|
||||
|
||||
[JsonPropertyName("schedule_from_min")]
|
||||
public Int64 ScheduleFromMin { get; set; }
|
||||
public Int64? ScheduleFromMin { get; set; }
|
||||
|
||||
[JsonPropertyName("schedule_to_hour")]
|
||||
public Int64 ScheduleToHour { get; set; }
|
||||
public Int64? ScheduleToHour { get; set; }
|
||||
|
||||
[JsonPropertyName("schedule_to_min")]
|
||||
public Int64 ScheduleToMin { get; set; }
|
||||
public Int64? ScheduleToMin { get; set; }
|
||||
|
||||
[JsonPropertyName("scheduler_days")]
|
||||
public Int64 SchedulerDays { get; set; }
|
||||
public Int64? SchedulerDays { get; set; }
|
||||
|
||||
[JsonPropertyName("scheduler_enabled")]
|
||||
public Boolean SchedulerEnabled { get; set; }
|
||||
public Boolean? SchedulerEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("send_buffer_low_watermark")]
|
||||
public Int64 SendBufferLowWatermark { get; set; }
|
||||
public Int64? SendBufferLowWatermark { get; set; }
|
||||
|
||||
[JsonPropertyName("send_buffer_watermark")]
|
||||
public Int64 SendBufferWatermark { get; set; }
|
||||
public Int64? SendBufferWatermark { get; set; }
|
||||
|
||||
[JsonPropertyName("send_buffer_watermark_factor")]
|
||||
public Int64 SendBufferWatermarkFactor { get; set; }
|
||||
public Int64? SendBufferWatermarkFactor { get; set; }
|
||||
|
||||
[JsonPropertyName("slow_torrent_dl_rate_threshold")]
|
||||
public Int64 SlowTorrentDlRateThreshold { get; set; }
|
||||
public Int64? SlowTorrentDlRateThreshold { get; set; }
|
||||
|
||||
[JsonPropertyName("slow_torrent_inactive_timer")]
|
||||
public Int64 SlowTorrentInactiveTimer { get; set; }
|
||||
public Int64? SlowTorrentInactiveTimer { get; set; }
|
||||
|
||||
[JsonPropertyName("slow_torrent_ul_rate_threshold")]
|
||||
public Int64 SlowTorrentUlRateThreshold { get; set; }
|
||||
public Int64? SlowTorrentUlRateThreshold { get; set; }
|
||||
|
||||
[JsonPropertyName("socket_backlog_size")]
|
||||
public Int64 SocketBacklogSize { get; set; }
|
||||
public Int64? SocketBacklogSize { get; set; }
|
||||
|
||||
[JsonPropertyName("start_paused_enabled")]
|
||||
public Boolean StartPausedEnabled { get; set; }
|
||||
public Boolean? StartPausedEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("stop_tracker_timeout")]
|
||||
public Int64 StopTrackerTimeout { get; set; }
|
||||
public Int64? StopTrackerTimeout { get; set; }
|
||||
|
||||
[JsonPropertyName("temp_path")]
|
||||
public String TempPath { get; set; }
|
||||
public String? TempPath { get; set; }
|
||||
|
||||
[JsonPropertyName("temp_path_enabled")]
|
||||
public Boolean TempPathEnabled { get; set; }
|
||||
public Boolean? TempPathEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("torrent_changed_tmm_enabled")]
|
||||
public Boolean TorrentChangedTmmEnabled { get; set; }
|
||||
public Boolean? TorrentChangedTmmEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("up_limit")]
|
||||
public Int64 UpLimit { get; set; }
|
||||
public Int64? UpLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("upload_choking_algorithm")]
|
||||
public Int64 UploadChokingAlgorithm { get; set; }
|
||||
public Int64? UploadChokingAlgorithm { get; set; }
|
||||
|
||||
[JsonPropertyName("upload_slots_behavior")]
|
||||
public Int64 UploadSlotsBehavior { get; set; }
|
||||
public Int64? UploadSlotsBehavior { get; set; }
|
||||
|
||||
[JsonPropertyName("upnp")]
|
||||
public Boolean Upnp { get; set; }
|
||||
public Boolean? Upnp { get; set; }
|
||||
|
||||
[JsonPropertyName("upnp_lease_duration")]
|
||||
public Int64 UpnpLeaseDuration { get; set; }
|
||||
public Int64? UpnpLeaseDuration { get; set; }
|
||||
|
||||
[JsonPropertyName("use_https")]
|
||||
public Boolean UseHttps { get; set; }
|
||||
public Boolean? UseHttps { get; set; }
|
||||
|
||||
[JsonPropertyName("utp_tcp_mixed_mode")]
|
||||
public Int64 UtpTcpMixedMode { get; set; }
|
||||
public Int64? UtpTcpMixedMode { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_address")]
|
||||
public String WebUiAddress { get; set; }
|
||||
public String? WebUiAddress { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_ban_duration")]
|
||||
public Int64 WebUiBanDuration { get; set; }
|
||||
public Int64? WebUiBanDuration { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_clickjacking_protection_enabled")]
|
||||
public Boolean WebUiClickjackingProtectionEnabled { get; set; }
|
||||
public Boolean? WebUiClickjackingProtectionEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_csrf_protection_enabled")]
|
||||
public Boolean WebUiCsrfProtectionEnabled { get; set; }
|
||||
public Boolean? WebUiCsrfProtectionEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_domain_list")]
|
||||
public String WebUiDomainList { get; set; }
|
||||
public String? WebUiDomainList { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_host_header_validation_enabled")]
|
||||
public Boolean WebUiHostHeaderValidationEnabled { get; set; }
|
||||
public Boolean? WebUiHostHeaderValidationEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_https_cert_path")]
|
||||
public String WebUiHttpsCertPath { get; set; }
|
||||
public String? WebUiHttpsCertPath { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_https_key_path")]
|
||||
public String WebUiHttpsKeyPath { get; set; }
|
||||
public String? WebUiHttpsKeyPath { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_max_auth_fail_count")]
|
||||
public Int64 WebUiMaxAuthFailCount { get; set; }
|
||||
public Int64? WebUiMaxAuthFailCount { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_port")]
|
||||
public Int64 WebUiPort { get; set; }
|
||||
public Int64? WebUiPort { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_secure_cookie_enabled")]
|
||||
public Boolean WebUiSecureCookieEnabled { get; set; }
|
||||
public Boolean? WebUiSecureCookieEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_session_timeout")]
|
||||
public Int64 WebUiSessionTimeout { get; set; }
|
||||
public Int64? WebUiSessionTimeout { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_upnp")]
|
||||
public Boolean WebUiUpnp { get; set; }
|
||||
public Boolean? WebUiUpnp { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_username")]
|
||||
public String WebUiUsername { get; set; }
|
||||
public String? WebUiUsername { get; set; }
|
||||
}
|
||||
|
||||
public class ScanDirs
|
||||
|
|
|
|||
|
|
@ -5,98 +5,98 @@ namespace RdtClient.Data.Models.QBittorrent;
|
|||
public class SyncMetaData
|
||||
{
|
||||
[JsonPropertyName("categories")]
|
||||
public IDictionary<String, TorrentCategory> Categories { get; set; }
|
||||
public IDictionary<String, TorrentCategory>? Categories { get; set; }
|
||||
|
||||
[JsonPropertyName("full_update")]
|
||||
public Boolean FullUpdate { get; set; }
|
||||
public Boolean? FullUpdate { get; set; }
|
||||
|
||||
[JsonPropertyName("rid")]
|
||||
public Int64 Rid { get; set; }
|
||||
public Int64? Rid { get; set; }
|
||||
|
||||
[JsonPropertyName("server_state")]
|
||||
public SyncMetaDataServerState ServerState { get; set; }
|
||||
public SyncMetaDataServerState? ServerState { get; set; }
|
||||
|
||||
[JsonPropertyName("tags")]
|
||||
public IList<Object> Tags { get; set; }
|
||||
public IList<Object>? Tags { get; set; }
|
||||
|
||||
[JsonPropertyName("torrents")]
|
||||
public IDictionary<String, TorrentInfo> Torrents { get; set; }
|
||||
public IDictionary<String, TorrentInfo>? Torrents { get; set; }
|
||||
|
||||
[JsonPropertyName("trackers")]
|
||||
public IDictionary<String, List<String>> Trackers { get; set; }
|
||||
public IDictionary<String, List<String>>? Trackers { get; set; }
|
||||
}
|
||||
|
||||
public class SyncMetaDataServerState
|
||||
{
|
||||
[JsonPropertyName("alltime_dl")]
|
||||
public Int64 AlltimeDl { get; set; }
|
||||
public Int64? AlltimeDl { get; set; }
|
||||
|
||||
[JsonPropertyName("alltime_ul")]
|
||||
public Int64 AlltimeUl { get; set; }
|
||||
public Int64? AlltimeUl { get; set; }
|
||||
|
||||
[JsonPropertyName("average_time_queue")]
|
||||
public Int64 AverageTimeQueue { get; set; }
|
||||
public Int64? AverageTimeQueue { get; set; }
|
||||
|
||||
[JsonPropertyName("connection_status")]
|
||||
public String ConnectionStatus { get; set; }
|
||||
public String? ConnectionStatus { get; set; }
|
||||
|
||||
[JsonPropertyName("dht_nodes")]
|
||||
public Int64 DhtNodes { get; set; }
|
||||
public Int64? DhtNodes { get; set; }
|
||||
|
||||
[JsonPropertyName("dl_info_data")]
|
||||
public Int64 DlInfoData { get; set; }
|
||||
public Int64? DlInfoData { get; set; }
|
||||
|
||||
[JsonPropertyName("dl_info_speed")]
|
||||
public Int64 DlInfoSpeed { get; set; }
|
||||
public Int64? DlInfoSpeed { get; set; }
|
||||
|
||||
[JsonPropertyName("dl_rate_limit")]
|
||||
public Int64 DlRateLimit { get; set; }
|
||||
public Int64? DlRateLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("free_space_on_disk")]
|
||||
public Int64 FreeSpaceOnDisk { get; set; }
|
||||
public Int64? FreeSpaceOnDisk { get; set; }
|
||||
|
||||
[JsonPropertyName("global_ratio")]
|
||||
public String GlobalRatio { get; set; }
|
||||
public String? GlobalRatio { get; set; }
|
||||
|
||||
[JsonPropertyName("queued_io_jobs")]
|
||||
public Int64 QueuedIoJobs { get; set; }
|
||||
public Int64? QueuedIoJobs { get; set; }
|
||||
|
||||
[JsonPropertyName("queueing")]
|
||||
public Boolean Queueing { get; set; }
|
||||
public Boolean? Queueing { get; set; }
|
||||
|
||||
[JsonPropertyName("read_cache_hits")]
|
||||
public String ReadCacheHits { get; set; }
|
||||
public String? ReadCacheHits { get; set; }
|
||||
|
||||
[JsonPropertyName("read_cache_overload")]
|
||||
public String ReadCacheOverload { get; set; }
|
||||
public String? ReadCacheOverload { get; set; }
|
||||
|
||||
[JsonPropertyName("refresh_interval")]
|
||||
public Int64 RefreshInterval { get; set; }
|
||||
public Int64? RefreshInterval { get; set; }
|
||||
|
||||
[JsonPropertyName("total_buffers_size")]
|
||||
public Int64 TotalBuffersSize { get; set; }
|
||||
public Int64? TotalBuffersSize { get; set; }
|
||||
|
||||
[JsonPropertyName("total_peer_connections")]
|
||||
public Int64 TotalPeerConnections { get; set; }
|
||||
public Int64? TotalPeerConnections { get; set; }
|
||||
|
||||
[JsonPropertyName("total_queued_size")]
|
||||
public Int64 TotalQueuedSize { get; set; }
|
||||
public Int64? TotalQueuedSize { get; set; }
|
||||
|
||||
[JsonPropertyName("total_wasted_session")]
|
||||
public Int64 TotalWastedSession { get; set; }
|
||||
public Int64? TotalWastedSession { get; set; }
|
||||
|
||||
[JsonPropertyName("up_info_data")]
|
||||
public Int64 UpInfoData { get; set; }
|
||||
public Int64? UpInfoData { get; set; }
|
||||
|
||||
[JsonPropertyName("up_info_speed")]
|
||||
public Int64 UpInfoSpeed { get; set; }
|
||||
public Int64? UpInfoSpeed { get; set; }
|
||||
|
||||
[JsonPropertyName("up_rate_limit")]
|
||||
public Int64 UpRateLimit { get; set; }
|
||||
public Int64? UpRateLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("use_alt_speed_limits")]
|
||||
public Boolean UseAltSpeedLimits { get; set; }
|
||||
public Boolean? UseAltSpeedLimits { get; set; }
|
||||
|
||||
[JsonPropertyName("write_cache_overload")]
|
||||
public String WriteCacheOverload { get; set; }
|
||||
public String? WriteCacheOverload { get; set; }
|
||||
}
|
||||
|
|
@ -5,8 +5,8 @@ namespace RdtClient.Data.Models.QBittorrent;
|
|||
public class TorrentCategory
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public String Name { get; set; }
|
||||
public String? Name { get; set; }
|
||||
|
||||
[JsonPropertyName("savePath")]
|
||||
public String SavePath { get; set; }
|
||||
public String? SavePath { get; set; }
|
||||
}
|
||||
|
|
@ -5,5 +5,5 @@ namespace RdtClient.Data.Models.QBittorrent;
|
|||
public class TorrentFileItem
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public String Name { get; set; }
|
||||
public String? Name { get; set; }
|
||||
}
|
||||
|
|
@ -5,10 +5,10 @@ namespace RdtClient.Data.Models.QBittorrent;
|
|||
public class TorrentInfo
|
||||
{
|
||||
[JsonPropertyName("added_on")]
|
||||
public Int64 AddedOn { get; set; }
|
||||
public Int64? AddedOn { get; set; }
|
||||
|
||||
[JsonPropertyName("amount_left")]
|
||||
public Int64 AmountLeft { get; set; }
|
||||
public Int64? AmountLeft { get; set; }
|
||||
|
||||
[JsonPropertyName("auto_tmm")]
|
||||
public Boolean AutoTmm { get; set; }
|
||||
|
|
@ -17,31 +17,31 @@ public class TorrentInfo
|
|||
public Decimal Availability { get; set; }
|
||||
|
||||
[JsonPropertyName("category")]
|
||||
public String Category { get; set; }
|
||||
public String? Category { get; set; }
|
||||
|
||||
[JsonPropertyName("completed")]
|
||||
public Int64 Completed { get; set; }
|
||||
public Int64? Completed { get; set; }
|
||||
|
||||
[JsonPropertyName("completion_on")]
|
||||
public Int64? CompletionOn { get; set; }
|
||||
|
||||
[JsonPropertyName("content_path")]
|
||||
public String ContentPath { get; set; }
|
||||
public String? ContentPath { get; set; }
|
||||
|
||||
[JsonPropertyName("dl_limit")]
|
||||
public Int64 DlLimit { get; set; }
|
||||
public Int64? DlLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("dlspeed")]
|
||||
public Int64 Dlspeed { get; set; }
|
||||
public Int64? Dlspeed { get; set; }
|
||||
|
||||
[JsonPropertyName("downloaded")]
|
||||
public Int64 Downloaded { get; set; }
|
||||
public Int64? Downloaded { get; set; }
|
||||
|
||||
[JsonPropertyName("downloaded_session")]
|
||||
public Int64 DownloadedSession { get; set; }
|
||||
public Int64? DownloadedSession { get; set; }
|
||||
|
||||
[JsonPropertyName("eta")]
|
||||
public Int64 Eta { get; set; }
|
||||
public Int64? Eta { get; set; }
|
||||
|
||||
[JsonPropertyName("f_l_piece_prio")]
|
||||
public Boolean FlPiecePrio { get; set; }
|
||||
|
|
@ -50,89 +50,89 @@ public class TorrentInfo
|
|||
public Boolean ForceStart { get; set; }
|
||||
|
||||
[JsonPropertyName("hash")]
|
||||
public String Hash { get; set; }
|
||||
public String Hash { get; set; } = default!;
|
||||
|
||||
[JsonPropertyName("last_activity")]
|
||||
public Int64 LastActivity { get; set; }
|
||||
public Int64? LastActivity { get; set; }
|
||||
|
||||
[JsonPropertyName("magnet_uri")]
|
||||
public String MagnetUri { get; set; }
|
||||
public String? MagnetUri { get; set; }
|
||||
|
||||
[JsonPropertyName("max_ratio")]
|
||||
public Int64 MaxRatio { get; set; }
|
||||
public Int64? MaxRatio { get; set; }
|
||||
|
||||
[JsonPropertyName("max_seeding_time")]
|
||||
public Int64 MaxSeedingTime { get; set; }
|
||||
public Int64? MaxSeedingTime { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public String Name { get; set; }
|
||||
public String? Name { get; set; }
|
||||
|
||||
[JsonPropertyName("num_complete")]
|
||||
public Int64 NumComplete { get; set; }
|
||||
public Int64? NumComplete { get; set; }
|
||||
|
||||
[JsonPropertyName("num_incomplete")]
|
||||
public Int64 NumIncomplete { get; set; }
|
||||
public Int64? NumIncomplete { get; set; }
|
||||
|
||||
[JsonPropertyName("num_leechs")]
|
||||
public Int64 NumLeechs { get; set; }
|
||||
public Int64? NumLeechs { get; set; }
|
||||
|
||||
[JsonPropertyName("num_seeds")]
|
||||
public Int64 NumSeeds { get; set; }
|
||||
public Int64? NumSeeds { get; set; }
|
||||
|
||||
[JsonPropertyName("priority")]
|
||||
public Int64 Priority { get; set; }
|
||||
public Int64? Priority { get; set; }
|
||||
|
||||
[JsonPropertyName("progress")]
|
||||
public Single Progress { get; set; }
|
||||
|
||||
[JsonPropertyName("ratio")]
|
||||
public Int64 Ratio { get; set; }
|
||||
public Int64? Ratio { get; set; }
|
||||
|
||||
[JsonPropertyName("ratio_limit")]
|
||||
public Int64 RatioLimit { get; set; }
|
||||
public Int64? RatioLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("save_path")]
|
||||
public String SavePath { get; set; }
|
||||
public String? SavePath { get; set; }
|
||||
|
||||
[JsonPropertyName("seeding_time_limit")]
|
||||
public Int64 SeedingTimeLimit { get; set; }
|
||||
public Int64? SeedingTimeLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("seen_complete")]
|
||||
public Int64 SeenComplete { get; set; }
|
||||
public Int64? SeenComplete { get; set; }
|
||||
|
||||
[JsonPropertyName("seq_dl")]
|
||||
public Boolean SeqDl { get; set; }
|
||||
|
||||
[JsonPropertyName("size")]
|
||||
public Int64 Size { get; set; }
|
||||
public Int64? Size { get; set; }
|
||||
|
||||
[JsonPropertyName("state")]
|
||||
public String State { get; set; }
|
||||
public String? State { get; set; }
|
||||
|
||||
[JsonPropertyName("super_seeding")]
|
||||
public Boolean SuperSeeding { get; set; }
|
||||
|
||||
[JsonPropertyName("tags")]
|
||||
public String Tags { get; set; }
|
||||
public String? Tags { get; set; }
|
||||
|
||||
[JsonPropertyName("time_active")]
|
||||
public Int64 TimeActive { get; set; }
|
||||
public Int64? TimeActive { get; set; }
|
||||
|
||||
[JsonPropertyName("total_size")]
|
||||
public Int64 TotalSize { get; set; }
|
||||
public Int64? TotalSize { get; set; }
|
||||
|
||||
[JsonPropertyName("tracker")]
|
||||
public String Tracker { get; set; }
|
||||
public String? Tracker { get; set; }
|
||||
|
||||
[JsonPropertyName("up_limit")]
|
||||
public Int64 UpLimit { get; set; }
|
||||
public Int64? UpLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("uploaded")]
|
||||
public Int64 Uploaded { get; set; }
|
||||
public Int64? Uploaded { get; set; }
|
||||
|
||||
[JsonPropertyName("uploaded_session")]
|
||||
public Int64 UploadedSession { get; set; }
|
||||
public Int64? UploadedSession { get; set; }
|
||||
|
||||
[JsonPropertyName("upspeed")]
|
||||
public Int64 Upspeed { get; set; }
|
||||
public Int64? Upspeed { get; set; }
|
||||
}
|
||||
|
|
@ -5,101 +5,101 @@ namespace RdtClient.Data.Models.QBittorrent;
|
|||
public class TorrentProperties
|
||||
{
|
||||
[JsonPropertyName("addition_date")]
|
||||
public Int64 AdditionDate { get; set; }
|
||||
public Int64? AdditionDate { get; set; }
|
||||
|
||||
[JsonPropertyName("comment")]
|
||||
public String Comment { get; set; }
|
||||
public String? Comment { get; set; }
|
||||
|
||||
[JsonPropertyName("completion_date")]
|
||||
public Int64 CompletionDate { get; set; }
|
||||
public Int64? CompletionDate { get; set; }
|
||||
|
||||
[JsonPropertyName("created_by")]
|
||||
public String CreatedBy { get; set; }
|
||||
public String? CreatedBy { get; set; }
|
||||
|
||||
[JsonPropertyName("creation_date")]
|
||||
public Int64 CreationDate { get; set; }
|
||||
public Int64? CreationDate { get; set; }
|
||||
|
||||
[JsonPropertyName("dl_limit")]
|
||||
public Int64 DlLimit { get; set; }
|
||||
public Int64? DlLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("dl_speed")]
|
||||
public Int64 DlSpeed { get; set; }
|
||||
public Int64? DlSpeed { get; set; }
|
||||
|
||||
[JsonPropertyName("dl_speed_avg")]
|
||||
public Int64 DlSpeedAvg { get; set; }
|
||||
public Int64? DlSpeedAvg { get; set; }
|
||||
|
||||
[JsonPropertyName("eta")]
|
||||
public Int64 Eta { get; set; }
|
||||
public Int64? Eta { get; set; }
|
||||
|
||||
[JsonPropertyName("last_seen")]
|
||||
public Int64 LastSeen { get; set; }
|
||||
public Int64? LastSeen { get; set; }
|
||||
|
||||
[JsonPropertyName("nb_connections")]
|
||||
public Int64 NbConnections { get; set; }
|
||||
public Int64? NbConnections { get; set; }
|
||||
|
||||
[JsonPropertyName("nb_connections_limit")]
|
||||
public Int64 NbConnectionsLimit { get; set; }
|
||||
public Int64? NbConnectionsLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("peers")]
|
||||
public Int64 Peers { get; set; }
|
||||
public Int64? Peers { get; set; }
|
||||
|
||||
[JsonPropertyName("peers_total")]
|
||||
public Int64 PeersTotal { get; set; }
|
||||
public Int64? PeersTotal { get; set; }
|
||||
|
||||
[JsonPropertyName("piece_size")]
|
||||
public Int64 PieceSize { get; set; }
|
||||
public Int64? PieceSize { get; set; }
|
||||
|
||||
[JsonPropertyName("pieces_have")]
|
||||
public Int64 PiecesHave { get; set; }
|
||||
public Int64? PiecesHave { get; set; }
|
||||
|
||||
[JsonPropertyName("pieces_num")]
|
||||
public Int64 PiecesNum { get; set; }
|
||||
public Int64? PiecesNum { get; set; }
|
||||
|
||||
[JsonPropertyName("reannounce")]
|
||||
public Int64 Reannounce { get; set; }
|
||||
public Int64? Reannounce { get; set; }
|
||||
|
||||
[JsonPropertyName("save_path")]
|
||||
public String SavePath { get; set; }
|
||||
public String? SavePath { get; set; }
|
||||
|
||||
[JsonPropertyName("seeding_time")]
|
||||
public Int64 SeedingTime { get; set; }
|
||||
public Int64? SeedingTime { get; set; }
|
||||
|
||||
[JsonPropertyName("seeds")]
|
||||
public Int64 Seeds { get; set; }
|
||||
public Int64? Seeds { get; set; }
|
||||
|
||||
[JsonPropertyName("seeds_total")]
|
||||
public Int64 SeedsTotal { get; set; }
|
||||
public Int64? SeedsTotal { get; set; }
|
||||
|
||||
[JsonPropertyName("share_ratio")]
|
||||
public Int64 ShareRatio { get; set; }
|
||||
public Int64? ShareRatio { get; set; }
|
||||
|
||||
[JsonPropertyName("time_elapsed")]
|
||||
public Int64 TimeElapsed { get; set; }
|
||||
public Int64? TimeElapsed { get; set; }
|
||||
|
||||
[JsonPropertyName("total_downloaded")]
|
||||
public Int64 TotalDownloaded { get; set; }
|
||||
public Int64? TotalDownloaded { get; set; }
|
||||
|
||||
[JsonPropertyName("total_downloaded_session")]
|
||||
public Int64 TotalDownloadedSession { get; set; }
|
||||
public Int64? TotalDownloadedSession { get; set; }
|
||||
|
||||
[JsonPropertyName("total_size")]
|
||||
public Int64 TotalSize { get; set; }
|
||||
public Int64? TotalSize { get; set; }
|
||||
|
||||
[JsonPropertyName("total_uploaded")]
|
||||
public Int64 TotalUploaded { get; set; }
|
||||
public Int64? TotalUploaded { get; set; }
|
||||
|
||||
[JsonPropertyName("total_uploaded_session")]
|
||||
public Int64 TotalUploadedSession { get; set; }
|
||||
public Int64? TotalUploadedSession { get; set; }
|
||||
|
||||
[JsonPropertyName("total_wasted")]
|
||||
public Int64 TotalWasted { get; set; }
|
||||
public Int64? TotalWasted { get; set; }
|
||||
|
||||
[JsonPropertyName("up_limit")]
|
||||
public Int64 UpLimit { get; set; }
|
||||
public Int64? UpLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("up_speed")]
|
||||
public Int64 UpSpeed { get; set; }
|
||||
public Int64? UpSpeed { get; set; }
|
||||
|
||||
[JsonPropertyName("up_speed_avg")]
|
||||
public Int64 UpSpeedAvg { get; set; }
|
||||
public Int64? UpSpeedAvg { get; set; }
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
public class TorrentClientAvailableFile
|
||||
{
|
||||
public String Filename { get; set; }
|
||||
public String Filename { get; set; } = default!;
|
||||
|
||||
public Int64 Filesize { get; set; }
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
public class TorrentClientFile
|
||||
{
|
||||
public Int64 Id { get; set; }
|
||||
public String Path { get; set; }
|
||||
public String Path { get; set; } = default!;
|
||||
public Int64 Bytes { get; set; }
|
||||
public Boolean Selected { get; set; }
|
||||
}
|
||||
|
|
@ -2,20 +2,20 @@
|
|||
|
||||
public class TorrentClientTorrent
|
||||
{
|
||||
public String Id { get; set; }
|
||||
public String Filename { get; set; }
|
||||
public String OriginalFilename { get; set; }
|
||||
public String Hash { get; set; }
|
||||
public String Id { get; set; } = default!;
|
||||
public String Filename { get; set; } = default!;
|
||||
public String? OriginalFilename { get; set; } = default!;
|
||||
public String Hash { get; set; } = default!;
|
||||
public Int64 Bytes { get; set; }
|
||||
public Int64 OriginalBytes { get; set; }
|
||||
public String Host { get; set; }
|
||||
public String? Host { get; set; }
|
||||
public Int64 Split { get; set; }
|
||||
public Int64 Progress { get; set; }
|
||||
public String Status { get; set; }
|
||||
public String? Status { get; set; } = default!;
|
||||
public Int64 StatusCode { get; set; }
|
||||
public DateTimeOffset Added { get; set; }
|
||||
public List<TorrentClientFile> Files { get; set; }
|
||||
public List<String> Links { get; set; }
|
||||
public List<TorrentClientFile>? Files { get; set; }
|
||||
public List<String>? Links { get; set; }
|
||||
public DateTimeOffset? Ended { get; set; }
|
||||
public Int64? Speed { get; set; }
|
||||
public Int64? Seeders { get; set; }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
public class TorrentClientUser
|
||||
{
|
||||
public String Username { get; set; }
|
||||
public String? Username { get; set; }
|
||||
public DateTimeOffset? Expiration { get; set; }
|
||||
}
|
||||
|
|
@ -2,25 +2,21 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>disable</Nullable>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.4">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.5" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="6.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Serilog" Version="2.11.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Attributes\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public class Startup : IHostedService
|
|||
var settings = scope.ServiceProvider.GetRequiredService<Settings>();
|
||||
await settings.Seed();
|
||||
await settings.ResetCache();
|
||||
await settings.Clean();
|
||||
await Settings.Clean();
|
||||
|
||||
Ready = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ namespace RdtClient.Service.BackgroundServices;
|
|||
|
||||
public class UpdateChecker : BackgroundService
|
||||
{
|
||||
public static String CurrentVersion { get; private set; }
|
||||
public static String LatestVersion { get; private set; }
|
||||
public static String? CurrentVersion { get; private set; }
|
||||
public static String? LatestVersion { get; private set; }
|
||||
|
||||
private readonly ILogger<UpdateChecker> _logger;
|
||||
|
||||
|
|
@ -53,7 +53,13 @@ public class UpdateChecker : BackgroundService
|
|||
return;
|
||||
}
|
||||
|
||||
var latestRelease = gitHubReleases.First().Name;
|
||||
var latestRelease = gitHubReleases.FirstOrDefault(m => m.Name != null)?.Name;
|
||||
|
||||
if (latestRelease == null)
|
||||
{
|
||||
_logger.LogWarning($"Unable to find latest version on GitHub");
|
||||
return;
|
||||
}
|
||||
|
||||
if (latestRelease != CurrentVersion)
|
||||
{
|
||||
|
|
@ -77,5 +83,5 @@ public class UpdateChecker : BackgroundService
|
|||
public class GitHubReleasesResponse
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public String Name { get; set; }
|
||||
public String? Name { get; set; }
|
||||
}
|
||||
|
|
@ -23,5 +23,6 @@ public static class DiConfig
|
|||
services.AddHostedService<Startup>();
|
||||
services.AddHostedService<TaskRunner>();
|
||||
services.AddHostedService<UpdateChecker>();
|
||||
services.AddHostedService<WatchFolderChecker>();
|
||||
}
|
||||
}
|
||||
8
server/RdtClient.Service/GlobalSuppressions.cs
Normal file
8
server/RdtClient.Service/GlobalSuppressions.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// This file is used by Code Analysis to maintain SuppressMessage
|
||||
// attributes that are applied to this project.
|
||||
// Project-level suppressions either have no target or are given
|
||||
// a specific target and scoped to a namespace, type, member, etc.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
[assembly: SuppressMessage("Usage", "CA2254:Template should be a static expression", Justification = "Bug in Serilog", Scope = "NamespaceAndDescendants", Target = "N:RdtClient.Service")]
|
||||
|
|
@ -5,11 +5,11 @@ namespace RdtClient.Service.Helpers;
|
|||
|
||||
public static class DownloadHelper
|
||||
{
|
||||
public static String GetDownloadPath(String downloadPath, Torrent torrent, Download download)
|
||||
public static String? GetDownloadPath(String downloadPath, Torrent torrent, Download download)
|
||||
{
|
||||
var fileUrl = download.Link;
|
||||
|
||||
if (String.IsNullOrWhiteSpace(fileUrl))
|
||||
if (String.IsNullOrWhiteSpace(fileUrl) || torrent.RdName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public class JsonModelBinder : IModelBinder
|
|||
{
|
||||
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
|
||||
|
||||
var valueAsString = valueProviderResult.FirstValue;
|
||||
var valueAsString = valueProviderResult.FirstValue ?? "";
|
||||
var result = Newtonsoft.Json.JsonConvert.DeserializeObject(valueAsString, bindingContext.ModelType);
|
||||
if (result != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
using RdtClient.Data.Models.Data;
|
||||
|
||||
namespace RdtClient.Service.Helpers;
|
||||
|
||||
public static class SettingsHelper
|
||||
{
|
||||
public static String GetString(this IList<Setting> settings, String key)
|
||||
{
|
||||
var setting = settings.FirstOrDefault(m => m.SettingId == key);
|
||||
|
||||
if (setting == null)
|
||||
{
|
||||
throw new Exception($"Setting with key {key} not found");
|
||||
}
|
||||
|
||||
return setting.Value;
|
||||
}
|
||||
|
||||
public static Int32 GetNumber(this IList<Setting> settings, String key)
|
||||
{
|
||||
var setting = settings.FirstOrDefault(m => m.SettingId == key);
|
||||
|
||||
if (setting == null)
|
||||
{
|
||||
throw new Exception($"Setting with key {key} not found");
|
||||
}
|
||||
|
||||
return Int32.Parse(setting.Value);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,18 +2,18 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>disable</Nullable>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="AllDebrid.NET" Version="1.0.7" />
|
||||
<PackageReference Include="Aria2.NET" Version="1.0.4" />
|
||||
<PackageReference Include="Downloader" Version="2.3.3" />
|
||||
<PackageReference Include="AllDebrid.NET" Version="1.0.9" />
|
||||
<PackageReference Include="Aria2.NET" Version="1.0.5" />
|
||||
<PackageReference Include="Downloader" Version="2.3.5" />
|
||||
<PackageReference Include="MonoTorrent" Version="2.0.5" />
|
||||
<PackageReference Include="RD.NET" Version="2.1.2" />
|
||||
<PackageReference Include="RD.NET" Version="2.1.3" />
|
||||
<PackageReference Include="Serilog" Version="2.11.0" />
|
||||
<PackageReference Include="Serilog.Exceptions" Version="8.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public class Authentication
|
|||
return result;
|
||||
}
|
||||
|
||||
public async Task<IdentityUser> GetUser()
|
||||
public async Task<IdentityUser?> GetUser()
|
||||
{
|
||||
return await _userData.GetUser();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,17 @@ public class DownloadClient
|
|||
private readonly Download _download;
|
||||
private readonly Torrent _torrent;
|
||||
|
||||
public IDownloader Downloader;
|
||||
public IDownloader? Downloader;
|
||||
|
||||
public Data.Enums.DownloadClient Type { get; set; }
|
||||
|
||||
public Boolean Finished { get; private set; }
|
||||
|
||||
public String? Error { get; private set; }
|
||||
|
||||
public Int64 Speed { get; private set; }
|
||||
public Int64 BytesTotal { get; private set; }
|
||||
public Int64 BytesDone { get; private set; }
|
||||
|
||||
public DownloadClient(Download download, Torrent torrent, String destinationPath)
|
||||
{
|
||||
|
|
@ -21,17 +31,7 @@ public class DownloadClient
|
|||
_destinationPath = destinationPath;
|
||||
}
|
||||
|
||||
public Data.Enums.DownloadClient Type { get; set; }
|
||||
|
||||
public Boolean Finished { get; private set; }
|
||||
|
||||
public String Error { get; private set; }
|
||||
|
||||
public Int64 Speed { get; private set; }
|
||||
public Int64 BytesTotal { get; private set; }
|
||||
public Int64 BytesDone { get; private set; }
|
||||
|
||||
public async Task<String> Start(DbSettings settings)
|
||||
public async Task<String?> Start(DbSettings settings)
|
||||
{
|
||||
BytesDone = 0;
|
||||
BytesTotal = 0;
|
||||
|
|
@ -39,13 +39,18 @@ public class DownloadClient
|
|||
|
||||
try
|
||||
{
|
||||
if (_download.Link == null)
|
||||
{
|
||||
throw new Exception($"Invalid download link");
|
||||
}
|
||||
|
||||
var filePath = DownloadHelper.GetDownloadPath(_destinationPath, _torrent, _download);
|
||||
|
||||
if (filePath == null)
|
||||
{
|
||||
throw new Exception("Invalid download path");
|
||||
}
|
||||
|
||||
|
||||
await FileHelper.Delete(filePath);
|
||||
|
||||
Type = settings.DownloadClient.Client;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ namespace RdtClient.Service.Services.Downloaders;
|
|||
|
||||
public class Aria2cDownloader : IDownloader
|
||||
{
|
||||
public event EventHandler<DownloadCompleteEventArgs> DownloadComplete;
|
||||
public event EventHandler<DownloadProgressEventArgs> DownloadProgress;
|
||||
public event EventHandler<DownloadCompleteEventArgs>? DownloadComplete;
|
||||
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
|
||||
|
||||
private const Int32 RetryCount = 5;
|
||||
|
||||
|
|
@ -17,9 +17,9 @@ public class Aria2cDownloader : IDownloader
|
|||
private readonly String _uri;
|
||||
private readonly String _filePath;
|
||||
|
||||
private String _gid;
|
||||
private String? _gid;
|
||||
|
||||
public Aria2cDownloader(String gid, String uri, String filePath, DbSettings settings)
|
||||
public Aria2cDownloader(String? gid, String uri, String filePath, DbSettings settings)
|
||||
{
|
||||
_logger = Log.ForContext<Aria2cDownloader>();
|
||||
_gid = gid;
|
||||
|
|
@ -34,9 +34,15 @@ public class Aria2cDownloader : IDownloader
|
|||
_aria2NetClient = new Aria2NetClient(settings.DownloadClient.Aria2cUrl, settings.DownloadClient.Aria2cSecret, httpClient, 10);
|
||||
}
|
||||
|
||||
public async Task<String> Download()
|
||||
public async Task<String?> Download()
|
||||
{
|
||||
var path = Path.GetDirectoryName(_filePath);
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new Exception($"Invalid file path {_filePath}");
|
||||
}
|
||||
|
||||
var fileName = Path.GetFileName(_filePath);
|
||||
|
||||
_logger.Debug($"Starting download of {_uri}, writing to path: {path}, fileName: {fileName}");
|
||||
|
|
@ -60,7 +66,7 @@ public class Aria2cDownloader : IDownloader
|
|||
{
|
||||
try
|
||||
{
|
||||
await _aria2NetClient.TellStatus(_gid);
|
||||
await _aria2NetClient.TellStatusAsync(_gid);
|
||||
|
||||
return _gid;
|
||||
}
|
||||
|
|
@ -70,23 +76,23 @@ public class Aria2cDownloader : IDownloader
|
|||
}
|
||||
}
|
||||
|
||||
_gid ??= await _aria2NetClient.AddUri(new List<String>
|
||||
{
|
||||
_uri
|
||||
},
|
||||
new Dictionary<String, Object>
|
||||
{
|
||||
{
|
||||
"dir", path
|
||||
},
|
||||
{
|
||||
"out", fileName
|
||||
}
|
||||
});
|
||||
_gid ??= await _aria2NetClient.AddUriAsync(new List<String>
|
||||
{
|
||||
_uri
|
||||
},
|
||||
new Dictionary<String, Object>
|
||||
{
|
||||
{
|
||||
"dir", path
|
||||
},
|
||||
{
|
||||
"out", fileName
|
||||
}
|
||||
});
|
||||
|
||||
_logger.Debug($"Added download to Aria2, received ID {_gid}");
|
||||
|
||||
await _aria2NetClient.TellStatus(_gid);
|
||||
await _aria2NetClient.TellStatusAsync(_gid);
|
||||
|
||||
_logger.Debug($"Download with ID {_gid} found in Aria2");
|
||||
|
||||
|
|
@ -124,7 +130,7 @@ public class Aria2cDownloader : IDownloader
|
|||
|
||||
try
|
||||
{
|
||||
await _aria2NetClient.Pause(_gid);
|
||||
await _aria2NetClient.PauseAsync(_gid);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -143,7 +149,7 @@ public class Aria2cDownloader : IDownloader
|
|||
|
||||
try
|
||||
{
|
||||
await _aria2NetClient.Unpause(_gid);
|
||||
await _aria2NetClient.UnpauseAsync(_gid);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -228,7 +234,7 @@ public class Aria2cDownloader : IDownloader
|
|||
|
||||
try
|
||||
{
|
||||
await _aria2NetClient.ForceRemove(_gid);
|
||||
await _aria2NetClient.ForceRemoveAsync(_gid);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -237,7 +243,7 @@ public class Aria2cDownloader : IDownloader
|
|||
|
||||
try
|
||||
{
|
||||
await _aria2NetClient.RemoveDownloadResult(_gid);
|
||||
await _aria2NetClient.RemoveDownloadResultAsync(_gid);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -247,11 +253,11 @@ public class Aria2cDownloader : IDownloader
|
|||
|
||||
private async Task<Boolean> CheckIfAdded()
|
||||
{
|
||||
var allDownloads = await _aria2NetClient.TellAll();
|
||||
var allDownloads = await _aria2NetClient.TellAllAsync();
|
||||
|
||||
foreach (var download in allDownloads.Where(m => m.Files != null))
|
||||
foreach (var download in allDownloads)
|
||||
{
|
||||
foreach (var file in download.Files.Where(m => m.Uris != null))
|
||||
foreach (var file in download.Files)
|
||||
{
|
||||
if (file.Uris.Any(uri => uri.Uri == _uri))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
public class DownloadCompleteEventArgs
|
||||
{
|
||||
public String Error { get; set; }
|
||||
public String? Error { get; set; }
|
||||
}
|
||||
|
||||
public class DownloadProgressEventArgs
|
||||
|
|
@ -14,9 +14,9 @@ public class DownloadProgressEventArgs
|
|||
|
||||
public interface IDownloader
|
||||
{
|
||||
event EventHandler<DownloadCompleteEventArgs> DownloadComplete;
|
||||
event EventHandler<DownloadProgressEventArgs> DownloadProgress;
|
||||
Task<String> Download();
|
||||
event EventHandler<DownloadCompleteEventArgs>? DownloadComplete;
|
||||
event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
|
||||
Task<String?> Download();
|
||||
Task Cancel();
|
||||
Task Pause();
|
||||
Task Resume();
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ namespace RdtClient.Service.Services.Downloaders;
|
|||
|
||||
public class MultiDownloader : IDownloader
|
||||
{
|
||||
public event EventHandler<DownloadCompleteEventArgs> DownloadComplete;
|
||||
public event EventHandler<DownloadProgressEventArgs> DownloadProgress;
|
||||
public event EventHandler<DownloadCompleteEventArgs>? DownloadComplete;
|
||||
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
|
||||
|
||||
private readonly DownloadService _downloadService;
|
||||
private readonly String _filePath;
|
||||
|
|
@ -94,7 +94,7 @@ public class MultiDownloader : IDownloader
|
|||
|
||||
_downloadService.DownloadFileCompleted += (_, args) =>
|
||||
{
|
||||
String error = null;
|
||||
String? error = null;
|
||||
|
||||
if (args.Cancelled)
|
||||
{
|
||||
|
|
@ -113,7 +113,7 @@ public class MultiDownloader : IDownloader
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<String> Download()
|
||||
public async Task<String?> Download()
|
||||
{
|
||||
_logger.Debug($"Starting download of {_uri}, writing to path: {_filePath}");
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ public class SimpleDownloader : IDownloader
|
|||
{
|
||||
private const Int32 BufferSize = 8 * 1024;
|
||||
|
||||
public event EventHandler<DownloadCompleteEventArgs> DownloadComplete;
|
||||
public event EventHandler<DownloadProgressEventArgs> DownloadProgress;
|
||||
public event EventHandler<DownloadCompleteEventArgs>? DownloadComplete;
|
||||
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
|
||||
|
||||
private readonly String _uri;
|
||||
private readonly String _filePath;
|
||||
|
|
@ -30,7 +30,7 @@ public class SimpleDownloader : IDownloader
|
|||
_filePath = filePath;
|
||||
}
|
||||
|
||||
public Task<String> Download()
|
||||
public Task<String?> Download()
|
||||
{
|
||||
_logger.Debug($"Starting download of {_uri}, writing to path: {_filePath}");
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ public class SimpleDownloader : IDownloader
|
|||
await StartDownloadTask();
|
||||
});
|
||||
|
||||
return Task.FromResult<String>(null);
|
||||
return Task.FromResult<String?>(null);
|
||||
}
|
||||
|
||||
public Task Cancel()
|
||||
|
|
@ -86,6 +86,7 @@ public class SimpleDownloader : IDownloader
|
|||
while (readSize > 0 && !_cancelled)
|
||||
{
|
||||
// ReSharper disable once ConvertToUsingDeclaration
|
||||
#pragma warning disable IDE0063 // Use simple 'using' statement
|
||||
using (var innerCts = new CancellationTokenSource(1000))
|
||||
{
|
||||
readSize = await destinationStream.ReadAsync(buffer.AsMemory(0, buffer.Length), innerCts.Token).ConfigureAwait(false);
|
||||
|
|
@ -115,6 +116,7 @@ public class SimpleDownloader : IDownloader
|
|||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore IDE0063 // Use simple 'using' statement
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ public class Downloads
|
|||
return await _downloadData.GetForTorrent(torrentId);
|
||||
}
|
||||
|
||||
public async Task<Download> GetById(Guid downloadId)
|
||||
public async Task<Download?> GetById(Guid downloadId)
|
||||
{
|
||||
return await _downloadData.GetById(downloadId);
|
||||
}
|
||||
|
||||
public async Task<Download> Get(Guid torrentId, String path)
|
||||
public async Task<Download?> Get(Guid torrentId, String path)
|
||||
{
|
||||
return await _downloadData.Get(torrentId, path);
|
||||
}
|
||||
|
|
@ -67,7 +67,7 @@ public class Downloads
|
|||
await _downloadData.UpdateCompleted(downloadId, dateTime);
|
||||
}
|
||||
|
||||
public async Task UpdateError(Guid downloadId, String error)
|
||||
public async Task UpdateError(Guid downloadId, String? error)
|
||||
{
|
||||
await _downloadData.UpdateError(downloadId, error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using RdtClient.Data.Enums;
|
||||
using RdtClient.Data.Models.Data;
|
||||
using RdtClient.Data.Models.Internal;
|
||||
using RdtClient.Data.Models.QBittorrent;
|
||||
|
||||
namespace RdtClient.Service.Services;
|
||||
|
|
@ -178,7 +177,7 @@ public class QBittorrent
|
|||
WebUiUsername = ""
|
||||
};
|
||||
|
||||
var savePath = AppDefaultSavePath();
|
||||
var savePath = Settings.AppDefaultSavePath;
|
||||
|
||||
preferences.SavePath = savePath;
|
||||
preferences.TempPath = $"{savePath}temp{Path.DirectorySeparatorChar}";
|
||||
|
|
@ -193,21 +192,9 @@ public class QBittorrent
|
|||
return preferences;
|
||||
}
|
||||
|
||||
public String AppDefaultSavePath()
|
||||
{
|
||||
var downloadPath = Settings.Get.DownloadClient.MappedPath;
|
||||
|
||||
downloadPath = downloadPath.TrimEnd('\\')
|
||||
.TrimEnd('/');
|
||||
|
||||
downloadPath += Path.DirectorySeparatorChar;
|
||||
|
||||
return downloadPath;
|
||||
}
|
||||
|
||||
public async Task<IList<TorrentInfo>> TorrentInfo()
|
||||
{
|
||||
var savePath = AppDefaultSavePath();
|
||||
var savePath = Settings.AppDefaultSavePath;
|
||||
|
||||
var results = new List<TorrentInfo>();
|
||||
|
||||
|
|
@ -241,9 +228,9 @@ public class QBittorrent
|
|||
speed = (Int32) torrent.Downloads.Average(m => m.Speed);
|
||||
}
|
||||
|
||||
var progress = (bytesDone / (Single)bytesTotal);
|
||||
var progress = (bytesDone / (Single?)bytesTotal);
|
||||
|
||||
if (!Single.IsNormal(progress))
|
||||
if (progress == null || !Single.IsNormal(progress.Value))
|
||||
{
|
||||
progress = 0;
|
||||
}
|
||||
|
|
@ -276,7 +263,7 @@ public class QBittorrent
|
|||
NumLeechs = 100,
|
||||
NumSeeds = 100,
|
||||
Priority = ++prio,
|
||||
Progress = progress,
|
||||
Progress = (Single) progress,
|
||||
Ratio = 1,
|
||||
RatioLimit = 1,
|
||||
SavePath = downloadPath,
|
||||
|
|
@ -325,7 +312,7 @@ public class QBittorrent
|
|||
return results;
|
||||
}
|
||||
|
||||
public async Task<IList<TorrentFileItem>> TorrentFileContents(String hash)
|
||||
public async Task<IList<TorrentFileItem>?> TorrentFileContents(String hash)
|
||||
{
|
||||
var results = new List<TorrentFileItem>();
|
||||
|
||||
|
|
@ -349,9 +336,9 @@ public class QBittorrent
|
|||
return results;
|
||||
}
|
||||
|
||||
public async Task<TorrentProperties> TorrentProperties(String hash)
|
||||
public async Task<TorrentProperties?> TorrentProperties(String hash)
|
||||
{
|
||||
var savePath = AppDefaultSavePath();
|
||||
var savePath = Settings.AppDefaultSavePath;
|
||||
|
||||
var torrent = await _torrents.GetByHash(hash);
|
||||
|
||||
|
|
@ -428,7 +415,7 @@ public class QBittorrent
|
|||
await _torrents.Delete(torrent.TorrentId, true, true, deleteFiles);
|
||||
}
|
||||
|
||||
public async Task TorrentsAddMagnet(String magnetLink, String category, Int32? priority)
|
||||
public async Task TorrentsAddMagnet(String magnetLink, String? category, Int32? priority)
|
||||
{
|
||||
var torrent = new Torrent
|
||||
{
|
||||
|
|
@ -446,7 +433,7 @@ public class QBittorrent
|
|||
await _torrents.UploadMagnet(magnetLink, torrent);
|
||||
}
|
||||
|
||||
public async Task TorrentsAddFile(Byte[] fileBytes, String category, Int32? priority)
|
||||
public async Task TorrentsAddFile(Byte[] fileBytes, String? category, Int32? priority)
|
||||
{
|
||||
var torrent = new Torrent
|
||||
{
|
||||
|
|
@ -464,7 +451,7 @@ public class QBittorrent
|
|||
await _torrents.UploadFile(fileBytes, torrent);
|
||||
}
|
||||
|
||||
public async Task TorrentsSetCategory(String hash, String category)
|
||||
public async Task TorrentsSetCategory(String hash, String? category)
|
||||
{
|
||||
await _torrents.UpdateCategory(hash, category);
|
||||
}
|
||||
|
|
@ -474,7 +461,7 @@ public class QBittorrent
|
|||
var torrents = await _torrents.Get();
|
||||
|
||||
var torrentsToGroup = torrents.Where(m => !String.IsNullOrWhiteSpace(m.Category))
|
||||
.Select(m => m.Category.ToLower())
|
||||
.Select(m => m.Category!.ToLower())
|
||||
.ToList();
|
||||
|
||||
var categoryList = (Settings.Get.General.Categories ?? "")
|
||||
|
|
@ -494,14 +481,14 @@ public class QBittorrent
|
|||
m => new TorrentCategory
|
||||
{
|
||||
Name = m,
|
||||
SavePath = Path.Combine(AppDefaultSavePath(), m)
|
||||
SavePath = Path.Combine(Settings.AppDefaultSavePath, m)
|
||||
});
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public async Task CategoryCreate(String category)
|
||||
public async Task CategoryCreate(String? category)
|
||||
{
|
||||
if (category == null)
|
||||
{
|
||||
|
|
@ -528,7 +515,7 @@ public class QBittorrent
|
|||
await _settings.Update("General:Categories", categoriesSetting);
|
||||
}
|
||||
|
||||
public async Task CategoryRemove(String category)
|
||||
public async Task CategoryRemove(String? category)
|
||||
{
|
||||
if (category == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ public class RdtHub : Hub
|
|||
await base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception exception)
|
||||
public override async Task OnDisconnectedAsync(Exception? exception)
|
||||
{
|
||||
Users.TryRemove(Context.ConnectionId, out _);
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
using System.Diagnostics;
|
||||
using Aria2NET;
|
||||
using RdtClient.Data.Data;
|
||||
using RdtClient.Data.Data;
|
||||
using RdtClient.Data.Enums;
|
||||
using RdtClient.Data.Models.Data;
|
||||
using RdtClient.Data.Models.Internal;
|
||||
using RdtClient.Service.Helpers;
|
||||
using RdtClient.Service.Services.Downloaders;
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
|
||||
|
|
@ -24,9 +20,19 @@ public class Settings
|
|||
|
||||
public static DbSettings Get => SettingData.Get;
|
||||
|
||||
public IList<SettingProperty> GetAll()
|
||||
public static String AppDefaultSavePath
|
||||
{
|
||||
return _settingData.GetAll();
|
||||
get
|
||||
{
|
||||
var downloadPath = Get.DownloadClient.MappedPath;
|
||||
|
||||
downloadPath = downloadPath.TrimEnd('\\')
|
||||
.TrimEnd('/');
|
||||
|
||||
downloadPath += Path.DirectorySeparatorChar;
|
||||
|
||||
return downloadPath;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Update(IList<SettingProperty> settings)
|
||||
|
|
@ -34,137 +40,12 @@ public class Settings
|
|||
await _settingData.Update(settings);
|
||||
}
|
||||
|
||||
public async Task Update(String settingId, Object value)
|
||||
public async Task Update(String settingId, Object? value)
|
||||
{
|
||||
await _settingData.Update(settingId, value);
|
||||
}
|
||||
|
||||
public async Task TestPath(String path)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
throw new Exception("Path is not set");
|
||||
}
|
||||
|
||||
path = path.TrimEnd('/').TrimEnd('\\');
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
throw new Exception($"Path {path} does not exist");
|
||||
}
|
||||
|
||||
var testFile = $"{path}/test.txt";
|
||||
|
||||
await File.WriteAllTextAsync(testFile, "RealDebridClient Test File, you can remove this file.");
|
||||
|
||||
await FileHelper.Delete(testFile);
|
||||
}
|
||||
|
||||
public async Task<Double> TestDownloadSpeed(CancellationToken cancellationToken)
|
||||
{
|
||||
var downloadPath = Get.DownloadClient.DownloadPath;
|
||||
|
||||
var testFilePath = Path.Combine(downloadPath, "testDefault.rar");
|
||||
|
||||
await FileHelper.Delete(testFilePath);
|
||||
|
||||
var download = new Download
|
||||
{
|
||||
Link = "https://34.download.real-debrid.com/speedtest/testDefault.rar",
|
||||
Torrent = new Torrent
|
||||
{
|
||||
RdName = ""
|
||||
}
|
||||
};
|
||||
|
||||
var downloadClient = new DownloadClient(download, download.Torrent, downloadPath);
|
||||
|
||||
await downloadClient.Start(Get);
|
||||
|
||||
var httpClient = new HttpClient
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(10)
|
||||
};
|
||||
|
||||
while (!downloadClient.Finished)
|
||||
{
|
||||
await Task.Delay(1000, CancellationToken.None);
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
await downloadClient.Cancel();
|
||||
}
|
||||
|
||||
if (downloadClient.Downloader is Aria2cDownloader aria2Downloader)
|
||||
{
|
||||
var aria2NetClient = new Aria2NetClient(Settings.Get.DownloadClient.Aria2cUrl, Settings.Get.DownloadClient.Aria2cSecret, httpClient, 1);
|
||||
|
||||
var allDownloads = await aria2NetClient.TellAll(cancellationToken);
|
||||
|
||||
await aria2Downloader.Update(allDownloads);
|
||||
}
|
||||
|
||||
if (downloadClient.BytesDone > 1024 * 1024 * 50)
|
||||
{
|
||||
await downloadClient.Cancel();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await FileHelper.Delete(testFilePath);
|
||||
|
||||
await Clean();
|
||||
|
||||
return downloadClient.Speed;
|
||||
}
|
||||
|
||||
public async Task<Double> TestWriteSpeed()
|
||||
{
|
||||
var downloadPath = Get.DownloadClient.DownloadPath;
|
||||
|
||||
var testFilePath = Path.Combine(downloadPath, "test.tmp");
|
||||
|
||||
await FileHelper.Delete(testFilePath);
|
||||
|
||||
const Int32 testFileSize = 64 * 1024 * 1024;
|
||||
|
||||
var watch = new Stopwatch();
|
||||
|
||||
watch.Start();
|
||||
|
||||
var rnd = new Random();
|
||||
|
||||
await using var fileStream = new FileStream(testFilePath, FileMode.Create, FileAccess.Write, FileShare.Write);
|
||||
|
||||
var buffer = new Byte[64 * 1024];
|
||||
|
||||
while (fileStream.Length < testFileSize)
|
||||
{
|
||||
rnd.NextBytes(buffer);
|
||||
|
||||
await fileStream.WriteAsync(buffer.AsMemory(0, buffer.Length));
|
||||
}
|
||||
|
||||
watch.Stop();
|
||||
|
||||
var writeSpeed = fileStream.Length / watch.Elapsed.TotalSeconds;
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
await FileHelper.Delete(testFilePath);
|
||||
|
||||
return writeSpeed;
|
||||
}
|
||||
|
||||
public async Task<VersionResult> GetAria2cVersion(String url, String secret)
|
||||
{
|
||||
var client = new Aria2NetClient(url, secret);
|
||||
|
||||
return await client.GetVersion();
|
||||
}
|
||||
|
||||
public async Task Clean()
|
||||
public static async Task Clean()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
/// </summary>
|
||||
public class ThrottledStream : Stream
|
||||
{
|
||||
public Int64 Speed => (Int64)_bandwidth.AverageSpeed;
|
||||
public Int64 Speed => (Int64) (_bandwidth?.AverageSpeed ?? 0);
|
||||
|
||||
private Bandwidth _bandwidth;
|
||||
private Bandwidth? _bandwidth;
|
||||
private Int64 _bandwidthLimit;
|
||||
private readonly Stream _baseStream;
|
||||
|
||||
|
|
@ -90,7 +90,6 @@ public class ThrottledStream : Stream
|
|||
public override Int32 Read(Byte[] buffer, Int32 offset, Int32 count)
|
||||
{
|
||||
Throttle(count).Wait();
|
||||
|
||||
return _baseStream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
|
|
@ -100,8 +99,13 @@ public class ThrottledStream : Stream
|
|||
CancellationToken cancellationToken)
|
||||
{
|
||||
await Throttle(count).ConfigureAwait(false);
|
||||
return await _baseStream.ReadAsync(new Memory<Byte>(buffer, offset, count), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return await _baseStream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
|
||||
public override async ValueTask<Int32> ReadAsync(Memory<Byte> buffer, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
await Throttle(buffer.Length).ConfigureAwait(false);
|
||||
return await base.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -115,7 +119,13 @@ public class ThrottledStream : Stream
|
|||
public override async Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
|
||||
{
|
||||
await Throttle(count).ConfigureAwait(false);
|
||||
await _baseStream.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
|
||||
await _baseStream.WriteAsync(new ReadOnlyMemory<Byte>(buffer, offset, count), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public override async ValueTask WriteAsync(ReadOnlyMemory<Byte> buffer, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
await Throttle(buffer.Length).ConfigureAwait(false);
|
||||
await base.WriteAsync(buffer, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task Throttle(Int32 transmissionVolume)
|
||||
|
|
@ -124,9 +134,8 @@ public class ThrottledStream : Stream
|
|||
if (BandwidthLimit > 0 && transmissionVolume > 0)
|
||||
{
|
||||
// Calculate the time to sleep.
|
||||
_bandwidth.CalculateSpeed(transmissionVolume);
|
||||
|
||||
await Sleep(_bandwidth.PopSpeedRetrieveTime()).ConfigureAwait(false);
|
||||
_bandwidth!.CalculateSpeed(transmissionVolume);
|
||||
await Sleep(_bandwidth!.PopSpeedRetrieveTime()).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +148,7 @@ public class ThrottledStream : Stream
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override String ToString()
|
||||
public override String? ToString()
|
||||
{
|
||||
return _baseStream.ToString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,14 +70,14 @@ public class AllDebridTorrentClient : ITorrentClient
|
|||
Status = torrent.Status,
|
||||
StatusCode = torrent.StatusCode,
|
||||
Added = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(torrent.UploadDate),
|
||||
Files = (torrent.Links ?? new List<Link>()).Select((m, i) => new TorrentClientFile
|
||||
Files = torrent.Links.Select((m, i) => new TorrentClientFile
|
||||
{
|
||||
Path = m.Filename,
|
||||
Bytes = m.Size,
|
||||
Id = i,
|
||||
Selected = true,
|
||||
}).ToList(),
|
||||
Links = (torrent.Links ?? new List<Link>()).Select(m => m.LinkUrl.ToString()).ToList(),
|
||||
Links = torrent.Links.Select(m => m.LinkUrl.ToString()).ToList(),
|
||||
Ended = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(torrent.CompletionDate),
|
||||
Speed = torrent.DownloadSpeed,
|
||||
Seeders = torrent.Seeders
|
||||
|
|
@ -94,6 +94,11 @@ public class AllDebridTorrentClient : ITorrentClient
|
|||
{
|
||||
var user = await GetClient().User.GetAsync();
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
throw new Exception("Unable to get user");
|
||||
}
|
||||
|
||||
return new TorrentClientUser
|
||||
{
|
||||
Username = user.Username,
|
||||
|
|
@ -105,14 +110,38 @@ public class AllDebridTorrentClient : ITorrentClient
|
|||
{
|
||||
var result = await GetClient().Magnet.UploadMagnetAsync(magnetLink);
|
||||
|
||||
return result.Id.ToString();
|
||||
if (result?.Id == null)
|
||||
{
|
||||
throw new Exception("Unable to add magnet link");
|
||||
}
|
||||
|
||||
var resultId = result.Id.ToString();
|
||||
|
||||
if (resultId == null)
|
||||
{
|
||||
throw new Exception($"Invalid responseID {result.Id}");
|
||||
}
|
||||
|
||||
return resultId;
|
||||
}
|
||||
|
||||
public async Task<String> AddFile(Byte[] bytes)
|
||||
{
|
||||
var result = await GetClient().Magnet.UploadFileAsync(bytes);
|
||||
|
||||
return result.Id.ToString();
|
||||
if (result?.Id == null)
|
||||
{
|
||||
throw new Exception("Unable to add torrent file");
|
||||
}
|
||||
|
||||
var resultId = result.Id.ToString();
|
||||
|
||||
if (resultId == null)
|
||||
{
|
||||
throw new Exception($"Invalid responseID {result.Id}");
|
||||
}
|
||||
|
||||
return resultId;
|
||||
}
|
||||
|
||||
public async Task<IList<TorrentClientAvailableFile>> GetAvailableFiles(String hash)
|
||||
|
|
@ -143,6 +172,11 @@ public class AllDebridTorrentClient : ITorrentClient
|
|||
{
|
||||
var result = await GetClient().Magnet.StatusAsync(torrentId);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
throw new Exception($"Unable to find magnet with ID {torrentId}");
|
||||
}
|
||||
|
||||
return Map(result);
|
||||
}
|
||||
|
||||
|
|
@ -155,13 +189,23 @@ public class AllDebridTorrentClient : ITorrentClient
|
|||
{
|
||||
var result = await GetClient().Links.DownloadLinkAsync(link);
|
||||
|
||||
if (result.Link == null)
|
||||
{
|
||||
throw new Exception("Invalid result link");
|
||||
}
|
||||
|
||||
return result.Link;
|
||||
}
|
||||
|
||||
public async Task<Torrent> UpdateData(Torrent torrent, TorrentClientTorrent torrentClientTorrent)
|
||||
public async Task<Torrent> UpdateData(Torrent torrent, TorrentClientTorrent? torrentClientTorrent)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (torrent.RdId == null)
|
||||
{
|
||||
return torrent;
|
||||
}
|
||||
|
||||
torrentClientTorrent ??= await GetInfo(torrent.RdId);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(torrentClientTorrent.Filename))
|
||||
|
|
@ -231,10 +275,20 @@ public class AllDebridTorrentClient : ITorrentClient
|
|||
return torrent;
|
||||
}
|
||||
|
||||
public async Task<IList<String>> GetDownloadLinks(Torrent torrent)
|
||||
public async Task<IList<String>?> GetDownloadLinks(Torrent torrent)
|
||||
{
|
||||
if (torrent.RdId == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var magnet = await GetClient().Magnet.StatusAsync(torrent.RdId);
|
||||
|
||||
if (magnet == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var links = magnet.Links;
|
||||
|
||||
Log($"Getting download links", torrent);
|
||||
|
|
@ -262,11 +316,6 @@ public class AllDebridTorrentClient : ITorrentClient
|
|||
|
||||
foreach (var link in links)
|
||||
{
|
||||
if (link.Files == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var fileList = GetFiles(link.Files, "");
|
||||
|
||||
Log($"{link.Filename} ({link.Size}b) {link.LinkUrl}, contains files:{Environment.NewLine}{String.Join(Environment.NewLine, fileList)}");
|
||||
|
|
@ -332,7 +381,7 @@ public class AllDebridTorrentClient : ITorrentClient
|
|||
return result;
|
||||
}
|
||||
|
||||
private void Log(String message, Torrent torrent = null)
|
||||
private void Log(String message, Torrent? torrent = null)
|
||||
{
|
||||
if (torrent != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,9 +11,8 @@ public interface ITorrentClient
|
|||
Task<String> AddFile(Byte[] bytes);
|
||||
Task<IList<TorrentClientAvailableFile>> GetAvailableFiles(String hash);
|
||||
Task SelectFiles(Torrent torrent);
|
||||
Task<TorrentClientTorrent> GetInfo(String torrentId);
|
||||
Task Delete(String torrentId);
|
||||
Task<String> Unrestrict(String link);
|
||||
Task<Torrent> UpdateData(Torrent torrent, TorrentClientTorrent torrentClientTorrent);
|
||||
Task<IList<String>> GetDownloadLinks(Torrent torrent);
|
||||
Task<Torrent> UpdateData(Torrent torrent, TorrentClientTorrent? torrentClientTorrent);
|
||||
Task<IList<String>?> GetDownloadLinks(Torrent torrent);
|
||||
}
|
||||
|
|
@ -141,11 +141,11 @@ public class RealDebridTorrentClient : ITorrentClient
|
|||
|
||||
var files = result.SelectMany(m => m.Value).SelectMany(m => m.Value).SelectMany(m => m.Values);
|
||||
|
||||
var groups = files.GroupBy(m => $"{m.Filename}-{m.Filesize}");
|
||||
var groups = files.Where(m => m.Filename != null).GroupBy(m => $"{m.Filename}-{m.Filesize}");
|
||||
|
||||
var torrentClientAvailableFiles = groups.Select(m => new TorrentClientAvailableFile
|
||||
{
|
||||
Filename = m.First().Filename,
|
||||
Filename = m.First().Filename!,
|
||||
Filesize = m.First().Filesize
|
||||
} ).ToList();
|
||||
|
||||
|
|
@ -211,7 +211,7 @@ public class RealDebridTorrentClient : ITorrentClient
|
|||
|
||||
Log("", torrent);
|
||||
|
||||
await GetClient().Torrents.SelectFilesAsync(torrent.RdId, fileIds.ToArray());
|
||||
await GetClient().Torrents.SelectFilesAsync(torrent.RdId!, fileIds.ToArray());
|
||||
}
|
||||
|
||||
public async Task<TorrentClientTorrent> GetInfo(String torrentId)
|
||||
|
|
@ -230,23 +230,28 @@ public class RealDebridTorrentClient : ITorrentClient
|
|||
{
|
||||
var result = await GetClient().Unrestrict.LinkAsync(link);
|
||||
|
||||
if (result.Download == null)
|
||||
{
|
||||
throw new Exception($"Unrestrict returned an invalid download");
|
||||
}
|
||||
|
||||
return result.Download;
|
||||
}
|
||||
|
||||
public async Task<Data.Models.Data.Torrent> UpdateData(Data.Models.Data.Torrent torrent, TorrentClientTorrent torrentClientTorrent)
|
||||
public async Task<Data.Models.Data.Torrent> UpdateData(Data.Models.Data.Torrent torrent, TorrentClientTorrent? torrentClientTorrent)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (torrent == null)
|
||||
if (torrent.RdId == null)
|
||||
{
|
||||
return null;
|
||||
return torrent;
|
||||
}
|
||||
|
||||
var rdTorrent = await GetInfo(torrent.RdId);
|
||||
|
||||
if (rdTorrent == null)
|
||||
{
|
||||
return torrent;
|
||||
throw new Exception($"Resource not found");
|
||||
}
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(rdTorrent.Filename))
|
||||
|
|
@ -302,10 +307,7 @@ public class RealDebridTorrentClient : ITorrentClient
|
|||
{
|
||||
if (ex.Message == "Resource not found")
|
||||
{
|
||||
if (torrent != null)
|
||||
{
|
||||
torrent.RdStatusRaw = "deleted";
|
||||
}
|
||||
torrent.RdStatusRaw = "deleted";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -316,10 +318,20 @@ public class RealDebridTorrentClient : ITorrentClient
|
|||
return torrent;
|
||||
}
|
||||
|
||||
public async Task<IList<String>> GetDownloadLinks(Data.Models.Data.Torrent torrent)
|
||||
public async Task<IList<String>?> GetDownloadLinks(Data.Models.Data.Torrent torrent)
|
||||
{
|
||||
if (torrent.RdId == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var rdTorrent = await GetInfo(torrent.RdId);
|
||||
|
||||
if (rdTorrent.Links == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var downloadLinks = rdTorrent.Links.Where(m => !String.IsNullOrWhiteSpace(m)).ToList();
|
||||
|
||||
Log($"Found {downloadLinks.Count} links", torrent);
|
||||
|
|
@ -360,7 +372,7 @@ public class RealDebridTorrentClient : ITorrentClient
|
|||
return dateTimeOffset?.Subtract(_offset.Value).ToOffset(_offset.Value);
|
||||
}
|
||||
|
||||
private void Log(String message, Data.Models.Data.Torrent torrent = null)
|
||||
private void Log(String message, Data.Models.Data.Torrent? torrent = null)
|
||||
{
|
||||
if (torrent != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ public class TorrentRunner
|
|||
|
||||
var aria2NetClient = new Aria2NetClient(Settings.Get.DownloadClient.Aria2cUrl, Settings.Get.DownloadClient.Aria2cSecret, _httpClient, 1);
|
||||
|
||||
var allDownloads = await aria2NetClient.TellAll();
|
||||
var allDownloads = await aria2NetClient.TellAllAsync();
|
||||
|
||||
Log($"Found {allDownloads.Count} Aria2 downloads");
|
||||
|
||||
|
|
@ -162,7 +162,7 @@ public class TorrentRunner
|
|||
{
|
||||
// Retry the download if an error is encountered.
|
||||
Log($"Download reported an error: {downloadClient.Error}", download, download.Torrent);
|
||||
Log($"Download retry count {download.RetryCount}/{download.Torrent.DownloadRetryAttempts}, torrent retry count {download.Torrent.RetryCount}/{download.Torrent.TorrentRetryAttempts}", download, download.Torrent);
|
||||
Log($"Download retry count {download.RetryCount}/{download.Torrent!.DownloadRetryAttempts}, torrent retry count {download.Torrent.RetryCount}/{download.Torrent.TorrentRetryAttempts}", download, download.Torrent);
|
||||
|
||||
if (download.RetryCount < download.Torrent.DownloadRetryAttempts)
|
||||
{
|
||||
|
|
@ -570,7 +570,7 @@ public class TorrentRunner
|
|||
}
|
||||
}
|
||||
|
||||
private void Log(String message, Download download, Torrent torrent)
|
||||
private void Log(String message, Download? download, Torrent? torrent)
|
||||
{
|
||||
if (download != null)
|
||||
{
|
||||
|
|
@ -585,7 +585,7 @@ public class TorrentRunner
|
|||
_logger.LogDebug(message);
|
||||
}
|
||||
|
||||
private void Log(String message, Torrent torrent = null)
|
||||
private void Log(String message, Torrent? torrent = null)
|
||||
{
|
||||
if (torrent != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public class Torrents
|
|||
{
|
||||
Provider.RealDebrid => realDebridTorrentClient,
|
||||
Provider.AllDebrid => allDebridTorrentClient,
|
||||
_ => null
|
||||
_ => throw new Exception("Invalid Provider")
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ public class Torrents
|
|||
return torrents;
|
||||
}
|
||||
|
||||
public async Task<Torrent> GetByHash(String hash)
|
||||
public async Task<Torrent?> GetByHash(String hash)
|
||||
{
|
||||
var torrent = await _torrentData.GetByHash(hash);
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ public class Torrents
|
|||
return torrent;
|
||||
}
|
||||
|
||||
public async Task UpdateCategory(String hash, String category)
|
||||
public async Task UpdateCategory(String hash, String? category)
|
||||
{
|
||||
var torrent = await _torrentData.GetByHash(hash);
|
||||
|
||||
|
|
@ -256,7 +256,7 @@ public class Torrents
|
|||
await _torrentData.Delete(torrentId);
|
||||
}
|
||||
|
||||
if (deleteRdTorrent)
|
||||
if (deleteRdTorrent && torrent.RdId != null)
|
||||
{
|
||||
Log($"Deleting RealDebrid Torrent", torrent);
|
||||
|
||||
|
|
@ -495,14 +495,17 @@ public class Torrents
|
|||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
var downloadPath = DownloadPath(download.Torrent);
|
||||
var downloadPath = DownloadPath(download.Torrent!);
|
||||
|
||||
var filePath = DownloadHelper.GetDownloadPath(downloadPath, download.Torrent, download);
|
||||
var filePath = DownloadHelper.GetDownloadPath(downloadPath, download.Torrent!, download);
|
||||
|
||||
if (filePath != null)
|
||||
{
|
||||
Log($"Deleting {filePath}", download, download.Torrent);
|
||||
|
||||
await FileHelper.Delete(filePath);
|
||||
}
|
||||
|
||||
Log($"Deleting {filePath}", download, download.Torrent);
|
||||
|
||||
await FileHelper.Delete(filePath);
|
||||
|
||||
Log($"Resetting", download, download.Torrent);
|
||||
|
||||
await _downloads.Reset(downloadId);
|
||||
|
|
@ -510,7 +513,7 @@ public class Torrents
|
|||
await _torrentData.UpdateComplete(download.TorrentId, null, null, false);
|
||||
}
|
||||
|
||||
public async Task UpdateComplete(Guid torrentId, String error, DateTimeOffset datetime, Boolean retry)
|
||||
public async Task UpdateComplete(Guid torrentId, String? error, DateTimeOffset datetime, Boolean retry)
|
||||
{
|
||||
await _torrentData.UpdateComplete(torrentId, error, datetime, retry);
|
||||
}
|
||||
|
|
@ -542,7 +545,7 @@ public class Torrents
|
|||
await _torrentData.UpdateError(torrentId, error);
|
||||
}
|
||||
|
||||
public async Task<Torrent> GetById(Guid torrentId)
|
||||
public async Task<Torrent?> GetById(Guid torrentId)
|
||||
{
|
||||
var torrent = await _torrentData.GetById(torrentId);
|
||||
|
||||
|
|
@ -630,6 +633,12 @@ public class Torrents
|
|||
}
|
||||
|
||||
var torrent = await _torrentData.GetById(torrentId);
|
||||
|
||||
if (torrent == null)
|
||||
{
|
||||
throw new Exception($"Cannot find Torrent with ID {torrentId}");
|
||||
}
|
||||
|
||||
var downloads = await _downloads.GetForTorrent(torrentId);
|
||||
|
||||
var fileName = Settings.Get.General.RunOnTorrentCompleteFileName;
|
||||
|
|
@ -638,7 +647,7 @@ public class Torrents
|
|||
Log($"Parsing external program {fileName} with arguments {arguments}", torrent);
|
||||
|
||||
var downloadPath = DownloadPath(torrent);
|
||||
var torrentPath = Path.Combine(downloadPath, torrent.RdName);
|
||||
var torrentPath = Path.Combine(downloadPath, torrent.RdName ?? "Unknown");
|
||||
|
||||
arguments = arguments.Replace("%N", $"\"{torrent.RdName}\"");
|
||||
arguments = arguments.Replace("%L", $"\"{torrent.Category}\"");
|
||||
|
|
@ -646,7 +655,7 @@ public class Torrents
|
|||
arguments = arguments.Replace("%R", $"\"{downloadPath}\"");
|
||||
arguments = arguments.Replace("%D", $"\"{torrentPath}\"");
|
||||
arguments = arguments.Replace("%C", downloads.Count.ToString(CultureInfo.InvariantCulture).Replace(",", "").Replace(".", ""));
|
||||
arguments = arguments.Replace("%Z", torrent.RdSize.ToString(CultureInfo.InvariantCulture).Replace(",", "").Replace(".", ""));
|
||||
arguments = arguments.Replace("%Z", torrent.RdSize?.ToString(CultureInfo.InvariantCulture).Replace(",", "").Replace(".", ""));
|
||||
arguments = arguments.Replace("%I", torrent.Hash);
|
||||
|
||||
Log($"Executing external program {fileName} with arguments {arguments}", torrent);
|
||||
|
|
@ -707,7 +716,7 @@ public class Torrents
|
|||
}
|
||||
}
|
||||
|
||||
private async Task UpdateTorrentClientData(Torrent torrent, TorrentClientTorrent torrentClientTorrent = null)
|
||||
private async Task UpdateTorrentClientData(Torrent torrent, TorrentClientTorrent? torrentClientTorrent = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -736,7 +745,7 @@ public class Torrents
|
|||
}
|
||||
}
|
||||
|
||||
private void Log(String message, Data.Models.Data.Download download, Torrent torrent)
|
||||
private void Log(String message, Data.Models.Data.Download? download, Torrent? torrent)
|
||||
{
|
||||
if (download != null)
|
||||
{
|
||||
|
|
@ -751,7 +760,7 @@ public class Torrents
|
|||
_logger.LogDebug(message);
|
||||
}
|
||||
|
||||
private void Log(String message, Torrent torrent = null)
|
||||
private void Log(String message, Torrent? torrent = null)
|
||||
{
|
||||
if (torrent != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public class UnpackClient
|
|||
{
|
||||
public Boolean Finished { get; private set; }
|
||||
|
||||
public String Error { get; private set; }
|
||||
public String? Error { get; private set; }
|
||||
|
||||
public Int64 BytesTotal { get; private set; }
|
||||
public Int64 BytesDone { get; private set; }
|
||||
|
|
@ -21,14 +21,14 @@ public class UnpackClient
|
|||
|
||||
private Boolean _cancelled;
|
||||
|
||||
private RarArchiveEntry _rarCurrentEntry;
|
||||
private Dictionary<String, Int64> _rarfileStatus;
|
||||
private RarArchiveEntry? _rarCurrentEntry;
|
||||
private Dictionary<String, Int64>? _rarfileStatus;
|
||||
|
||||
public UnpackClient(Download download, String destinationPath)
|
||||
{
|
||||
_download = download;
|
||||
_destinationPath = destinationPath;
|
||||
_torrent = download.Torrent;
|
||||
_torrent = download.Torrent ?? throw new Exception($"Torrent is null");
|
||||
}
|
||||
|
||||
public void Start()
|
||||
|
|
@ -91,7 +91,7 @@ public class UnpackClient
|
|||
|
||||
if (!entries.Any(m => m.Key.StartsWith(_torrent.RdName + @"\")) && !entries.Any(m => m.Key.StartsWith(_torrent.RdName + @"/")))
|
||||
{
|
||||
extractPath = Path.Combine(_destinationPath, _torrent.RdName);
|
||||
extractPath = Path.Combine(_destinationPath, _torrent.RdName!);
|
||||
}
|
||||
|
||||
if (entries.Any(m => m.Key.Contains(".r00")))
|
||||
|
|
@ -129,14 +129,14 @@ public class UnpackClient
|
|||
}
|
||||
}
|
||||
|
||||
private void ArchiveOnCompressedBytesRead(Object sender, CompressedBytesReadEventArgs e)
|
||||
private void ArchiveOnCompressedBytesRead(Object? sender, CompressedBytesReadEventArgs e)
|
||||
{
|
||||
if (_rarCurrentEntry == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_rarfileStatus[_rarCurrentEntry.Key] = e.CompressedBytesRead;
|
||||
_rarfileStatus![_rarCurrentEntry.Key] = e.CompressedBytesRead;
|
||||
|
||||
BytesDone = _rarfileStatus.Sum(m => m.Value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using RdtClient.Data.Models.Data;
|
||||
using RdtClient.Data.Models.Internal;
|
||||
using RdtClient.Service.Services;
|
||||
|
||||
namespace RdtClient.Web.Controllers;
|
||||
|
|
@ -41,14 +39,24 @@ public class AuthController : Controller
|
|||
[AllowAnonymous]
|
||||
[Route("Create")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult> Create([FromBody] AuthControllerLoginRequest request)
|
||||
public async Task<ActionResult> Create([FromBody] AuthControllerLoginRequest? request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var user = await _authentication.GetUser();
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
return StatusCode(401);
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(request.UserName) || String.IsNullOrEmpty(request.Password))
|
||||
{
|
||||
return BadRequest("Invalid UserName or Password");
|
||||
}
|
||||
|
||||
var registerResult = await _authentication.Register(request.UserName, request.Password);
|
||||
|
||||
|
|
@ -65,8 +73,13 @@ public class AuthController : Controller
|
|||
[AllowAnonymous]
|
||||
[Route("SetupProvider")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult> SetupProvider([FromBody] AuthControllerSetupProviderRequest request)
|
||||
public async Task<ActionResult> SetupProvider([FromBody] AuthControllerSetupProviderRequest? request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(Settings.Get.Provider.ApiKey))
|
||||
{
|
||||
return StatusCode(401);
|
||||
|
|
@ -81,8 +94,13 @@ public class AuthController : Controller
|
|||
[AllowAnonymous]
|
||||
[Route("Login")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult> Login([FromBody] AuthControllerLoginRequest request)
|
||||
public async Task<ActionResult> Login([FromBody] AuthControllerLoginRequest? request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var user = await _authentication.GetUser();
|
||||
|
||||
if (user == null)
|
||||
|
|
@ -90,6 +108,11 @@ public class AuthController : Controller
|
|||
return StatusCode(402);
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(request.UserName) || String.IsNullOrEmpty(request.Password))
|
||||
{
|
||||
return BadRequest("Invalid credentials");
|
||||
}
|
||||
|
||||
var result = await _authentication.Login(request.UserName, request.Password);
|
||||
|
||||
if (!result.Succeeded)
|
||||
|
|
@ -110,8 +133,18 @@ public class AuthController : Controller
|
|||
|
||||
[Route("Update")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult> Update([FromBody] AuthControllerUpdateRequest request)
|
||||
public async Task<ActionResult> Update([FromBody] AuthControllerUpdateRequest? request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(request.UserName) || String.IsNullOrEmpty(request.Password))
|
||||
{
|
||||
return BadRequest("Invalid UserName or Password");
|
||||
}
|
||||
|
||||
var updateResult = await _authentication.Update(request.UserName, request.Password);
|
||||
|
||||
if (!updateResult.Succeeded)
|
||||
|
|
@ -125,18 +158,18 @@ public class AuthController : Controller
|
|||
|
||||
public class AuthControllerLoginRequest
|
||||
{
|
||||
public String UserName { get; set; }
|
||||
public String Password { get; set; }
|
||||
public String? UserName { get; set; }
|
||||
public String? Password { get; set; }
|
||||
}
|
||||
|
||||
public class AuthControllerSetupProviderRequest
|
||||
{
|
||||
public Int32 Provider { get; set; }
|
||||
public String Token { get; set; }
|
||||
public String? Token { get; set; }
|
||||
}
|
||||
|
||||
public class AuthControllerUpdateRequest
|
||||
{
|
||||
public String UserName { get; set; }
|
||||
public String Password { get; set; }
|
||||
public String? UserName { get; set; }
|
||||
public String? Password { get; set; }
|
||||
}
|
||||
|
|
@ -26,6 +26,11 @@ public class QBittorrentController : Controller
|
|||
[HttpGet]
|
||||
public async Task<ActionResult> AuthLogin([FromQuery] QBAuthLoginRequest request)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(request.UserName) || String.IsNullOrEmpty(request.Password))
|
||||
{
|
||||
return Ok("Fails.");
|
||||
}
|
||||
|
||||
var result = await _qBittorrent.AuthLogin(request.UserName, request.Password);
|
||||
|
||||
if (result)
|
||||
|
|
@ -121,7 +126,7 @@ public class QBittorrentController : Controller
|
|||
[HttpPost]
|
||||
public ActionResult<AppPreferences> AppDefaultSavePath()
|
||||
{
|
||||
var result = _qBittorrent.AppDefaultSavePath();
|
||||
var result = Settings.AppDefaultSavePath;
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
|
|
@ -154,6 +159,11 @@ public class QBittorrentController : Controller
|
|||
[HttpGet]
|
||||
public async Task<ActionResult<IList<TorrentFileItem>>> TorrentsFiles([FromQuery] QBTorrentsHashRequest request)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(request.Hash))
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var result = await _qBittorrent.TorrentFileContents(request.Hash);
|
||||
|
||||
if (result == null)
|
||||
|
|
@ -177,6 +187,11 @@ public class QBittorrentController : Controller
|
|||
[HttpGet]
|
||||
public async Task<ActionResult<IList<TorrentInfo>>> TorrentsProperties([FromQuery] QBTorrentsHashRequest request)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(request.Hash))
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var result = await _qBittorrent.TorrentProperties(request.Hash);
|
||||
|
||||
if (result == null)
|
||||
|
|
@ -200,6 +215,11 @@ public class QBittorrentController : Controller
|
|||
[HttpGet]
|
||||
public async Task<ActionResult> TorrentsPause([FromQuery] QBTorrentsHashesRequest request)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(request.Hashes))
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var hashes = request.Hashes.Split("|");
|
||||
|
||||
foreach (var hash in hashes)
|
||||
|
|
@ -223,6 +243,11 @@ public class QBittorrentController : Controller
|
|||
[HttpGet]
|
||||
public async Task<ActionResult> TorrentsResume([FromQuery] QBTorrentsHashesRequest request)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(request.Hashes))
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var hashes = request.Hashes.Split("|");
|
||||
|
||||
foreach (var hash in hashes)
|
||||
|
|
@ -255,6 +280,11 @@ public class QBittorrentController : Controller
|
|||
[HttpGet]
|
||||
public async Task<ActionResult> TorrentsDelete([FromQuery] QBTorrentsDeleteRequest request)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(request.Hashes))
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var hashes = request.Hashes.Split("|");
|
||||
|
||||
foreach (var hash in hashes)
|
||||
|
|
@ -278,6 +308,11 @@ public class QBittorrentController : Controller
|
|||
[HttpGet]
|
||||
public async Task<ActionResult> TorrentsAdd([FromQuery] QBTorrentsAddRequest request)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(request.Urls))
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var urls = request.Urls.Split("\n");
|
||||
|
||||
foreach (var url in urls)
|
||||
|
|
@ -294,7 +329,7 @@ public class QBittorrentController : Controller
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Invalid torrent link format {url}");
|
||||
return BadRequest($"Invalid torrent link format {url}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -332,6 +367,11 @@ public class QBittorrentController : Controller
|
|||
[HttpGet]
|
||||
public async Task<ActionResult> TorrentsSetCategory([FromQuery] QBTorrentsSetCategoryRequest request)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(request.Hashes))
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var hashes = request.Hashes.Split("|");
|
||||
|
||||
foreach (var hash in hashes)
|
||||
|
|
@ -412,6 +452,11 @@ public class QBittorrentController : Controller
|
|||
[HttpGet]
|
||||
public async Task<ActionResult> TorrentsTopPrio([FromQuery] QBTorrentsHashesRequest request)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(request.Hashes))
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var hashes = request.Hashes.Split("|");
|
||||
|
||||
foreach (var hash in hashes)
|
||||
|
|
@ -451,51 +496,50 @@ public class QBittorrentController : Controller
|
|||
|
||||
public class QBAuthLoginRequest
|
||||
{
|
||||
public String UserName { get; set; }
|
||||
public String Password { get; set; }
|
||||
public String? UserName { get; set; }
|
||||
public String? Password { get; set; }
|
||||
}
|
||||
|
||||
public class QBTorrentsInfoRequest
|
||||
{
|
||||
public String Category { get; set; }
|
||||
public String? Category { get; set; }
|
||||
}
|
||||
|
||||
public class QBTorrentsHashRequest
|
||||
{
|
||||
public String Hash { get; set; }
|
||||
public String Category { get; set; }
|
||||
public String? Hash { get; set; }
|
||||
}
|
||||
|
||||
public class QBTorrentsDeleteRequest
|
||||
{
|
||||
public String Hashes { get; set; }
|
||||
public String? Hashes { get; set; }
|
||||
public Boolean DeleteFiles { get; set; }
|
||||
}
|
||||
|
||||
public class QBTorrentsAddRequest
|
||||
{
|
||||
public String Urls { get; set; }
|
||||
public String Category { get; set; }
|
||||
public String? Urls { get; set; }
|
||||
public String? Category { get; set; }
|
||||
public Int32? Priority { get; set; }
|
||||
}
|
||||
|
||||
public class QBTorrentsSetCategoryRequest
|
||||
{
|
||||
public String Hashes { get; set; }
|
||||
public String Category { get; set; }
|
||||
public String? Hashes { get; set; }
|
||||
public String? Category { get; set; }
|
||||
}
|
||||
|
||||
public class QBTorrentsCreateCategoryRequest
|
||||
{
|
||||
public String Category { get; set; }
|
||||
public String? Category { get; set; }
|
||||
}
|
||||
|
||||
public class QBTorrentsRemoveCategoryRequest
|
||||
{
|
||||
public String Categories { get; set; }
|
||||
public String? Categories { get; set; }
|
||||
}
|
||||
|
||||
public class QBTorrentsHashesRequest
|
||||
{
|
||||
public String Hashes { get; set; }
|
||||
public String? Hashes { get; set; }
|
||||
}
|
||||
|
|
@ -1,7 +1,13 @@
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Diagnostics;
|
||||
using Aria2NET;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using RdtClient.Data.Data;
|
||||
using RdtClient.Data.Models.Data;
|
||||
using RdtClient.Data.Models.Internal;
|
||||
using RdtClient.Service.Helpers;
|
||||
using RdtClient.Service.Services;
|
||||
using RdtClient.Service.Services.Downloaders;
|
||||
|
||||
namespace RdtClient.Web.Controllers;
|
||||
|
||||
|
|
@ -22,14 +28,19 @@ public class SettingsController : Controller
|
|||
[Route("")]
|
||||
public ActionResult Get()
|
||||
{
|
||||
var result = _settings.GetAll();
|
||||
var result = SettingData.GetAll();
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Route("")]
|
||||
public async Task<ActionResult> Update([FromBody] IList<SettingProperty> settings)
|
||||
public async Task<ActionResult> Update([FromBody] IList<SettingProperty>? settings)
|
||||
{
|
||||
if (settings == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
await _settings.Update(settings);
|
||||
|
||||
return Ok();
|
||||
|
|
@ -45,9 +56,30 @@ public class SettingsController : Controller
|
|||
|
||||
[HttpPost]
|
||||
[Route("TestPath")]
|
||||
public async Task<ActionResult> TestPath([FromBody] SettingsControllerTestPathRequest request)
|
||||
public async Task<ActionResult> TestPath([FromBody] SettingsControllerTestPathRequest? request)
|
||||
{
|
||||
await _settings.TestPath(request.Path);
|
||||
if (request == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(request.Path))
|
||||
{
|
||||
return BadRequest("Invalid path");
|
||||
}
|
||||
|
||||
var path = request.Path.TrimEnd('/').TrimEnd('\\');
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
throw new Exception($"Path {path} does not exist");
|
||||
}
|
||||
|
||||
var testFile = $"{path}/test.txt";
|
||||
|
||||
await System.IO.File.WriteAllTextAsync(testFile, "RealDebridClient Test File, you can remove this file.");
|
||||
|
||||
await FileHelper.Delete(testFile);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
|
@ -56,25 +88,120 @@ public class SettingsController : Controller
|
|||
[Route("TestDownloadSpeed")]
|
||||
public async Task<ActionResult> TestDownloadSpeed(CancellationToken cancellationToken)
|
||||
{
|
||||
var downloadSpeed = await _settings.TestDownloadSpeed(cancellationToken);
|
||||
var downloadPath = Settings.Get.DownloadClient.DownloadPath;
|
||||
|
||||
return Ok(downloadSpeed);
|
||||
var testFilePath = Path.Combine(downloadPath, "testDefault.rar");
|
||||
|
||||
await FileHelper.Delete(testFilePath);
|
||||
|
||||
var download = new Download
|
||||
{
|
||||
Link = "https://34.download.real-debrid.com/speedtest/testDefault.rar",
|
||||
Torrent = new Torrent
|
||||
{
|
||||
RdName = ""
|
||||
}
|
||||
};
|
||||
|
||||
var downloadClient = new DownloadClient(download, download.Torrent, downloadPath);
|
||||
|
||||
await downloadClient.Start(Settings.Get);
|
||||
|
||||
var httpClient = new HttpClient
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(10)
|
||||
};
|
||||
|
||||
while (!downloadClient.Finished)
|
||||
{
|
||||
await Task.Delay(1000, CancellationToken.None);
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
await downloadClient.Cancel();
|
||||
}
|
||||
|
||||
if (downloadClient.Downloader is Aria2cDownloader aria2Downloader)
|
||||
{
|
||||
var aria2NetClient = new Aria2NetClient(Settings.Get.DownloadClient.Aria2cUrl, Settings.Get.DownloadClient.Aria2cSecret, httpClient, 1);
|
||||
|
||||
var allDownloads = await aria2NetClient.TellAllAsync(cancellationToken);
|
||||
|
||||
await aria2Downloader.Update(allDownloads);
|
||||
}
|
||||
|
||||
if (downloadClient.BytesDone > 1024 * 1024 * 50)
|
||||
{
|
||||
await downloadClient.Cancel();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await FileHelper.Delete(testFilePath);
|
||||
|
||||
await Settings.Clean();
|
||||
|
||||
return Ok(downloadClient.Speed);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("TestWriteSpeed")]
|
||||
public async Task<ActionResult> TestWriteSpeed()
|
||||
{
|
||||
var writeSpeed = await _settings.TestWriteSpeed();
|
||||
var downloadPath = Settings.Get.DownloadClient.DownloadPath;
|
||||
|
||||
var testFilePath = Path.Combine(downloadPath, "test.tmp");
|
||||
|
||||
await FileHelper.Delete(testFilePath);
|
||||
|
||||
const Int32 testFileSize = 64 * 1024 * 1024;
|
||||
|
||||
var watch = new Stopwatch();
|
||||
|
||||
watch.Start();
|
||||
|
||||
var rnd = new Random();
|
||||
|
||||
await using var fileStream = new FileStream(testFilePath, FileMode.Create, FileAccess.Write, FileShare.Write);
|
||||
|
||||
var buffer = new Byte[64 * 1024];
|
||||
|
||||
while (fileStream.Length < testFileSize)
|
||||
{
|
||||
rnd.NextBytes(buffer);
|
||||
|
||||
await fileStream.WriteAsync(buffer.AsMemory(0, buffer.Length));
|
||||
}
|
||||
|
||||
watch.Stop();
|
||||
|
||||
var writeSpeed = fileStream.Length / watch.Elapsed.TotalSeconds;
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
await FileHelper.Delete(testFilePath);
|
||||
|
||||
return Ok(writeSpeed);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("TestAria2cConnection")]
|
||||
public async Task<ActionResult<String>> TestAria2cConnection([FromBody] SettingsControllerTestAria2cConnectionRequest request)
|
||||
public async Task<ActionResult<String>> TestAria2cConnection([FromBody] SettingsControllerTestAria2cConnectionRequest? request)
|
||||
{
|
||||
var version = await _settings.GetAria2cVersion(request.Url, request.Secret);
|
||||
if (request == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(request.Url))
|
||||
{
|
||||
return BadRequest("Invalid Url");
|
||||
}
|
||||
|
||||
var client = new Aria2NetClient(request.Url, request.Secret);
|
||||
|
||||
var version = await client.GetVersionAsync();
|
||||
|
||||
return Ok(version);
|
||||
}
|
||||
|
|
@ -82,11 +209,11 @@ public class SettingsController : Controller
|
|||
|
||||
public class SettingsControllerTestPathRequest
|
||||
{
|
||||
public String Path { get; set; }
|
||||
public String? Path { get; set; }
|
||||
}
|
||||
|
||||
public class SettingsControllerTestAria2cConnectionRequest
|
||||
{
|
||||
public String Url { get; set; }
|
||||
public String Secret { get; set; }
|
||||
public String? Url { get; set; }
|
||||
public String? Secret { get; set; }
|
||||
}
|
||||
|
|
@ -67,22 +67,25 @@ public class TorrentsController : Controller
|
|||
|
||||
[HttpPost]
|
||||
[Route("UploadFile")]
|
||||
public async Task<ActionResult> UploadFile([FromForm] IFormFile file,
|
||||
public async Task<ActionResult> UploadFile([FromForm] IFormFile? file,
|
||||
[ModelBinder(BinderType = typeof(JsonModelBinder))]
|
||||
TorrentControllerUploadFileRequest formData)
|
||||
TorrentControllerUploadFileRequest? formData)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
var errors = ModelState.Select(x => x.Value.Errors)
|
||||
.Where(y => y.Count > 0)
|
||||
.ToList();
|
||||
|
||||
var errors = ModelState.Select(x => x.Value?.Errors.Select(m => m.ErrorMessage)).ToList();
|
||||
return BadRequest(errors);
|
||||
}
|
||||
|
||||
|
||||
if (file == null || file.Length <= 0)
|
||||
{
|
||||
throw new Exception("Invalid torrent file");
|
||||
return BadRequest("Invalid torrent file");
|
||||
}
|
||||
|
||||
if (formData?.Torrent == null)
|
||||
{
|
||||
return BadRequest("Invalid Torrent");
|
||||
}
|
||||
|
||||
var fileStream = file.OpenReadStream();
|
||||
|
|
@ -100,17 +103,29 @@ public class TorrentsController : Controller
|
|||
|
||||
[HttpPost]
|
||||
[Route("UploadMagnet")]
|
||||
public async Task<ActionResult> UploadMagnet([FromBody] TorrentControllerUploadMagnetRequest request)
|
||||
public async Task<ActionResult> UploadMagnet([FromBody] TorrentControllerUploadMagnetRequest? request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
var errors = ModelState.Select(x => x.Value.Errors)
|
||||
.Where(y => y.Count > 0)
|
||||
.ToList();
|
||||
|
||||
var errors = ModelState.Select(x => x.Value?.Errors.Select(m => m.ErrorMessage)).ToList();
|
||||
return BadRequest(errors);
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(request.MagnetLink))
|
||||
{
|
||||
return BadRequest("Invalid magnet link");
|
||||
}
|
||||
|
||||
if (request.Torrent == null)
|
||||
{
|
||||
return BadRequest("Invalid Torrent");
|
||||
}
|
||||
|
||||
await _torrents.UploadMagnet(request.MagnetLink, request.Torrent);
|
||||
|
||||
return Ok();
|
||||
|
|
@ -118,11 +133,11 @@ public class TorrentsController : Controller
|
|||
|
||||
[HttpPost]
|
||||
[Route("CheckFiles")]
|
||||
public async Task<ActionResult> CheckFiles([FromForm] IFormFile file)
|
||||
public async Task<ActionResult> CheckFiles([FromForm] IFormFile? file)
|
||||
{
|
||||
if (file == null || file.Length <= 0)
|
||||
{
|
||||
throw new Exception("Invalid torrent file");
|
||||
return BadRequest("Invalid torrent file");
|
||||
}
|
||||
|
||||
var fileStream = file.OpenReadStream();
|
||||
|
|
@ -142,8 +157,13 @@ public class TorrentsController : Controller
|
|||
|
||||
[HttpPost]
|
||||
[Route("CheckFilesMagnet")]
|
||||
public async Task<ActionResult> CheckFilesMagnet([FromBody] TorrentControllerCheckFilesRequest request)
|
||||
public async Task<ActionResult> CheckFilesMagnet([FromBody] TorrentControllerCheckFilesRequest? request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var magnet = MagnetLink.Parse(request.MagnetLink);
|
||||
|
||||
var result = await _torrents.GetAvailableFiles(magnet.InfoHash.ToHex());
|
||||
|
|
@ -153,8 +173,13 @@ public class TorrentsController : Controller
|
|||
|
||||
[HttpPost]
|
||||
[Route("Delete/{torrentId:guid}")]
|
||||
public async Task<ActionResult> Delete(Guid torrentId, [FromBody] TorrentControllerDeleteRequest request)
|
||||
public async Task<ActionResult> Delete(Guid torrentId, [FromBody] TorrentControllerDeleteRequest? request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
await _torrents.Delete(torrentId, request.DeleteData, request.DeleteRdTorrent, request.DeleteLocalFiles);
|
||||
|
||||
return Ok();
|
||||
|
|
@ -181,8 +206,13 @@ public class TorrentsController : Controller
|
|||
|
||||
[HttpPut]
|
||||
[Route("Update")]
|
||||
public async Task<ActionResult> Update([FromBody] Torrent torrent)
|
||||
public async Task<ActionResult> Update([FromBody] Torrent? torrent)
|
||||
{
|
||||
if (torrent == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
await _torrents.Update(torrent);
|
||||
|
||||
return Ok();
|
||||
|
|
@ -191,13 +221,13 @@ public class TorrentsController : Controller
|
|||
|
||||
public class TorrentControllerUploadFileRequest
|
||||
{
|
||||
public Torrent Torrent { get; set; }
|
||||
public Torrent? Torrent { get; set; }
|
||||
}
|
||||
|
||||
public class TorrentControllerUploadMagnetRequest
|
||||
{
|
||||
public String MagnetLink { get; set; }
|
||||
public Torrent Torrent { get; set; }
|
||||
public String? MagnetLink { get; set; }
|
||||
public Torrent? Torrent { get; set; }
|
||||
}
|
||||
|
||||
public class TorrentControllerDeleteRequest
|
||||
|
|
@ -209,5 +239,5 @@ public class TorrentControllerDeleteRequest
|
|||
|
||||
public class TorrentControllerCheckFilesRequest
|
||||
{
|
||||
public String MagnetLink { get; set; }
|
||||
public String? MagnetLink { get; set; }
|
||||
}
|
||||
|
|
@ -32,17 +32,20 @@ builder.WebHost.ConfigureKestrel(options =>
|
|||
options.ListenAnyIP(appSettings.Port);
|
||||
});
|
||||
|
||||
builder.Host.UseSerilog((_, lc) => lc.Enrich.FromLogContext()
|
||||
.Enrich.WithExceptionDetails()
|
||||
.WriteTo.File(appSettings.Logging.File.Path,
|
||||
rollOnFileSizeLimit: true,
|
||||
fileSizeLimitBytes: appSettings.Logging.File.FileSizeLimitBytes,
|
||||
retainedFileCountLimit: appSettings.Logging.File.MaxRollingFiles,
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {SourceContext}: {Message:lj}{NewLine}{Exception}")
|
||||
.WriteTo.Console()
|
||||
.MinimumLevel.ControlledBy(Settings.LoggingLevelSwitch)
|
||||
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
|
||||
.MinimumLevel.Override("System.Net.Http", LogEventLevel.Warning));
|
||||
if (appSettings.Logging?.File?.Path != null)
|
||||
{
|
||||
builder.Host.UseSerilog((_, lc) => lc.Enrich.FromLogContext()
|
||||
.Enrich.WithExceptionDetails()
|
||||
.WriteTo.File(appSettings.Logging.File.Path,
|
||||
rollOnFileSizeLimit: true,
|
||||
fileSizeLimitBytes: appSettings.Logging.File.FileSizeLimitBytes,
|
||||
retainedFileCountLimit: appSettings.Logging.File.MaxRollingFiles,
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {SourceContext}: {Message:lj}{NewLine}{Exception}")
|
||||
.WriteTo.Console()
|
||||
.MinimumLevel.ControlledBy(Settings.LoggingLevelSwitch)
|
||||
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
|
||||
.MinimumLevel.Override("System.Net.Http", LogEventLevel.Warning));
|
||||
}
|
||||
|
||||
Serilog.Debugging.SelfLog.Enable(msg =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<OutputType>Exe</OutputType>
|
||||
<UserSecretsId>94c24cba-f03f-4453-a671-3640b517c573</UserSecretsId>
|
||||
<Version>2.0.12</Version>
|
||||
<Nullable>disable</Nullable>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
|
@ -29,15 +29,15 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.4">
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="6.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="6.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.5" />
|
||||
<PackageReference Include="Serilog" Version="2.11.0" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@
|
|||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QB/@EntryIndexedValue">QB</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=US/@EntryIndexedValue">US</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XML/@EntryIndexedValue">XML</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XML/@EntryIndexedValue">Aria2c</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=LocalConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
|
|
|
|||
Loading…
Reference in a new issue