Added bit of logging to debug downloader issues, upgraded packages, cleaned up C# code.

This commit is contained in:
Roger Far 2024-04-06 13:54:58 -06:00
parent 74b988effa
commit 3b72463663
35 changed files with 407 additions and 666 deletions

View file

@ -6,12 +6,8 @@ namespace RdtClient.Data.Data;
#nullable disable #nullable disable
public class DataContext : IdentityDbContext public class DataContext(DbContextOptions options) : IdentityDbContext(options)
{ {
public DataContext(DbContextOptions options) : base(options)
{
}
public DbSet<Download> Downloads { get; set; } public DbSet<Download> Downloads { get; set; }
public DbSet<Setting> Settings { get; set; } public DbSet<Setting> Settings { get; set; }
public DbSet<Torrent> Torrents { get; set; } public DbSet<Torrent> Torrents { get; set; }

View file

@ -3,18 +3,11 @@ using Download = RdtClient.Data.Models.Data.Download;
namespace RdtClient.Data.Data; namespace RdtClient.Data.Data;
public class DownloadData public class DownloadData(DataContext dataContext)
{ {
private readonly DataContext _dataContext;
public DownloadData(DataContext dataContext)
{
_dataContext = dataContext;
}
public async Task<List<Download>> GetForTorrent(Guid torrentId) public async Task<List<Download>> GetForTorrent(Guid torrentId)
{ {
return await _dataContext.Downloads return await dataContext.Downloads
.AsNoTracking() .AsNoTracking()
.Where(m => m.TorrentId == torrentId) .Where(m => m.TorrentId == torrentId)
.ToListAsync(); .ToListAsync();
@ -22,7 +15,7 @@ public class DownloadData
public async Task<Download?> GetById(Guid downloadId) public async Task<Download?> GetById(Guid downloadId)
{ {
return await _dataContext.Downloads return await dataContext.Downloads
.Include(m => m.Torrent) .Include(m => m.Torrent)
.AsNoTracking() .AsNoTracking()
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
@ -30,7 +23,7 @@ public class DownloadData
public async Task<Download?> Get(Guid torrentId, String path) public async Task<Download?> Get(Guid torrentId, String path)
{ {
return await _dataContext.Downloads return await dataContext.Downloads
.Include(m => m.Torrent) .Include(m => m.Torrent)
.AsNoTracking() .AsNoTracking()
.FirstOrDefaultAsync(m => m.TorrentId == torrentId && m.Path == path); .FirstOrDefaultAsync(m => m.TorrentId == torrentId && m.Path == path);
@ -48,9 +41,9 @@ public class DownloadData
RetryCount = 0 RetryCount = 0
}; };
await _dataContext.Downloads.AddAsync(download); await dataContext.Downloads.AddAsync(download);
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
@ -59,7 +52,7 @@ public class DownloadData
public async Task UpdateUnrestrictedLink(Guid downloadId, String unrestrictedLink) public async Task UpdateUnrestrictedLink(Guid downloadId, String unrestrictedLink)
{ {
var dbDownload = await _dataContext.Downloads var dbDownload = await dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null) if (dbDownload == null)
@ -69,14 +62,14 @@ public class DownloadData
dbDownload.Link = unrestrictedLink; dbDownload.Link = unrestrictedLink;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }
public async Task UpdateDownloadStarted(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateDownloadStarted(Guid downloadId, DateTimeOffset? dateTime)
{ {
var dbDownload = await _dataContext.Downloads var dbDownload = await dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null) if (dbDownload == null)
@ -86,14 +79,14 @@ public class DownloadData
dbDownload.DownloadStarted = dateTime; dbDownload.DownloadStarted = dateTime;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }
public async Task UpdateDownloadFinished(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateDownloadFinished(Guid downloadId, DateTimeOffset? dateTime)
{ {
var dbDownload = await _dataContext.Downloads var dbDownload = await dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null) if (dbDownload == null)
@ -103,14 +96,14 @@ public class DownloadData
dbDownload.DownloadFinished = dateTime; dbDownload.DownloadFinished = dateTime;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }
public async Task UpdateUnpackingQueued(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateUnpackingQueued(Guid downloadId, DateTimeOffset? dateTime)
{ {
var dbDownload = await _dataContext.Downloads var dbDownload = await dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null) if (dbDownload == null)
@ -120,14 +113,14 @@ public class DownloadData
dbDownload.UnpackingQueued = dateTime; dbDownload.UnpackingQueued = dateTime;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }
public async Task UpdateUnpackingStarted(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateUnpackingStarted(Guid downloadId, DateTimeOffset? dateTime)
{ {
var dbDownload = await _dataContext.Downloads var dbDownload = await dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null) if (dbDownload == null)
@ -137,14 +130,14 @@ public class DownloadData
dbDownload.UnpackingStarted = dateTime; dbDownload.UnpackingStarted = dateTime;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }
public async Task UpdateUnpackingFinished(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateUnpackingFinished(Guid downloadId, DateTimeOffset? dateTime)
{ {
var dbDownload = await _dataContext.Downloads var dbDownload = await dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null) if (dbDownload == null)
@ -154,14 +147,14 @@ public class DownloadData
dbDownload.UnpackingFinished = dateTime; dbDownload.UnpackingFinished = dateTime;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }
public async Task UpdateCompleted(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateCompleted(Guid downloadId, DateTimeOffset? dateTime)
{ {
var dbDownload = await _dataContext.Downloads var dbDownload = await dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null) if (dbDownload == null)
@ -171,14 +164,14 @@ public class DownloadData
dbDownload.Completed = dateTime; dbDownload.Completed = dateTime;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }
public async Task UpdateError(Guid downloadId, String? error) public async Task UpdateError(Guid downloadId, String? error)
{ {
var dbDownload = await _dataContext.Downloads var dbDownload = await dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null) if (dbDownload == null)
@ -188,14 +181,14 @@ public class DownloadData
dbDownload.Error = error; dbDownload.Error = error;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }
public async Task UpdateRetryCount(Guid downloadId, Int32 retryCount) public async Task UpdateRetryCount(Guid downloadId, Int32 retryCount)
{ {
var dbDownload = await _dataContext.Downloads var dbDownload = await dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null) if (dbDownload == null)
@ -205,14 +198,14 @@ public class DownloadData
dbDownload.RetryCount = retryCount; dbDownload.RetryCount = retryCount;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }
public async Task UpdateRemoteId(Guid downloadId, String remoteId) public async Task UpdateRemoteId(Guid downloadId, String remoteId)
{ {
var dbDownload = await _dataContext.Downloads var dbDownload = await dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null) if (dbDownload == null)
@ -222,25 +215,25 @@ public class DownloadData
dbDownload.RemoteId = remoteId; dbDownload.RemoteId = remoteId;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
} }
public async Task DeleteForTorrent(Guid torrentId) public async Task DeleteForTorrent(Guid torrentId)
{ {
var downloads = await _dataContext.Downloads var downloads = await dataContext.Downloads
.Where(m => m.TorrentId == torrentId) .Where(m => m.TorrentId == torrentId)
.ToListAsync(); .ToListAsync();
_dataContext.Downloads.RemoveRange(downloads); dataContext.Downloads.RemoveRange(downloads);
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }
public async Task Reset(Guid downloadId) public async Task Reset(Guid downloadId)
{ {
var dbDownload = await _dataContext.Downloads var dbDownload = await dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null) if (dbDownload == null)
@ -260,7 +253,7 @@ public class DownloadData
dbDownload.Completed = null; dbDownload.Completed = null;
dbDownload.Error = null; dbDownload.Error = null;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }

View file

@ -7,11 +7,8 @@ using RdtClient.Data.Models.Internal;
namespace RdtClient.Data.Data; namespace RdtClient.Data.Data;
public class SettingData public class SettingData(DataContext dataContext, ILogger<SettingData> logger)
{ {
private readonly DataContext _dataContext;
private readonly ILogger<SettingData> _logger;
public static DbSettings Get { get; } = new DbSettings(); public static DbSettings Get { get; } = new DbSettings();
public static IList<SettingProperty> GetAll() public static IList<SettingProperty> GetAll()
@ -19,15 +16,9 @@ public class SettingData
return GetSettings(Get, null).ToList(); return GetSettings(Get, null).ToList();
} }
public SettingData(DataContext dataContext, ILogger<SettingData> logger)
{
_dataContext = dataContext;
_logger = logger;
}
public async Task Update(IList<SettingProperty> settings) public async Task Update(IList<SettingProperty> settings)
{ {
var dbSettings = await _dataContext.Settings.ToListAsync(); var dbSettings = await dataContext.Settings.ToListAsync();
foreach (var dbSetting in dbSettings) foreach (var dbSetting in dbSettings)
{ {
@ -39,14 +30,14 @@ public class SettingData
} }
} }
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await ResetCache(); 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); var dbSetting = await dataContext.Settings.FirstOrDefaultAsync(m => m.SettingId == settingId);
if (dbSetting == null) if (dbSetting == null)
{ {
@ -55,14 +46,14 @@ public class SettingData
dbSetting.Value = value?.ToString(); dbSetting.Value = value?.ToString();
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await ResetCache(); await ResetCache();
} }
public async Task ResetCache() public async Task ResetCache()
{ {
var settings = await _dataContext.Settings.AsNoTracking().ToListAsync(); var settings = await dataContext.Settings.AsNoTracking().ToListAsync();
if (settings.Count == 0) if (settings.Count == 0)
{ {
@ -74,7 +65,7 @@ public class SettingData
public async Task Seed() public async Task Seed()
{ {
var dbSettings = await _dataContext.Settings.AsNoTracking().ToListAsync(); var dbSettings = await dataContext.Settings.AsNoTracking().ToListAsync();
var expectedSettings = GetSettings(Get, null).Where(m => m.Type != "Object").Select(m => new Setting var expectedSettings = GetSettings(Get, null).Where(m => m.Type != "Object").Select(m => new Setting
{ {
@ -86,16 +77,16 @@ public class SettingData
if (newSettings.Any()) if (newSettings.Any())
{ {
await _dataContext.Settings.AddRangeAsync(newSettings); await dataContext.Settings.AddRangeAsync(newSettings);
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
} }
var oldSettings = dbSettings.Where(m => expectedSettings.All(p => p.SettingId != m.SettingId)).ToList(); var oldSettings = dbSettings.Where(m => expectedSettings.All(p => p.SettingId != m.SettingId)).ToList();
if (oldSettings.Any()) if (oldSettings.Any())
{ {
_dataContext.Settings.RemoveRange(oldSettings); dataContext.Settings.RemoveRange(oldSettings);
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
} }
} }
@ -200,7 +191,7 @@ public class SettingData
} }
else else
{ {
_logger.LogWarning($"Invalid value for setting {propertyName}: {setting.Value}"); logger.LogWarning($"Invalid value for setting {propertyName}: {setting.Value}");
} }
} }
} }

View file

@ -4,26 +4,19 @@ using RdtClient.Data.Models.Data;
namespace RdtClient.Data.Data; namespace RdtClient.Data.Data;
public class TorrentData public class TorrentData(DataContext dataContext)
{ {
private static IList<Torrent>? _torrentCache; private static IList<Torrent>? _torrentCache;
private static readonly SemaphoreSlim TorrentCacheLock = new(1, 1); private static readonly SemaphoreSlim TorrentCacheLock = new(1, 1);
private readonly DataContext _dataContext;
public TorrentData(DataContext dataContext)
{
_dataContext = dataContext;
}
public async Task<IList<Torrent>> Get() public async Task<IList<Torrent>> Get()
{ {
await TorrentCacheLock.WaitAsync(); await TorrentCacheLock.WaitAsync();
try try
{ {
_torrentCache ??= await _dataContext.Torrents _torrentCache ??= await dataContext.Torrents
.AsNoTracking() .AsNoTracking()
.Include(m => m.Downloads) .Include(m => m.Downloads)
.ToListAsync(); .ToListAsync();
@ -38,7 +31,7 @@ public class TorrentData
public async Task<Torrent?> GetById(Guid torrentId) public async Task<Torrent?> GetById(Guid torrentId)
{ {
var dbTorrent = await _dataContext.Torrents var dbTorrent = await dataContext.Torrents
.AsNoTracking() .AsNoTracking()
.Include(m => m.Downloads) .Include(m => m.Downloads)
.FirstOrDefaultAsync(m => m.TorrentId == torrentId); .FirstOrDefaultAsync(m => m.TorrentId == torrentId);
@ -58,7 +51,7 @@ public class TorrentData
public async Task<Torrent?> GetByHash(String hash) public async Task<Torrent?> GetByHash(String hash)
{ {
var dbTorrent = await _dataContext.Torrents var dbTorrent = await dataContext.Torrents
.AsNoTracking() .AsNoTracking()
.Include(m => m.Downloads) .Include(m => m.Downloads)
.FirstOrDefaultAsync(m => m.Hash.ToLower() == hash.ToLower()); .FirstOrDefaultAsync(m => m.Hash.ToLower() == hash.ToLower());
@ -107,9 +100,9 @@ public class TorrentData
Lifetime = torrent.Lifetime Lifetime = torrent.Lifetime
}; };
await _dataContext.Torrents.AddAsync(newTorrent); await dataContext.Torrents.AddAsync(newTorrent);
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await VoidCache(); await VoidCache();
@ -118,7 +111,7 @@ public class TorrentData
public async Task UpdateRdData(Torrent torrent) public async Task UpdateRdData(Torrent torrent)
{ {
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrent.TorrentId); var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrent.TorrentId);
if (dbTorrent == null) if (dbTorrent == null)
{ {
@ -138,14 +131,14 @@ public class TorrentData
dbTorrent.RdSeeders = torrent.RdSeeders; dbTorrent.RdSeeders = torrent.RdSeeders;
dbTorrent.RdFiles = torrent.RdFiles; dbTorrent.RdFiles = torrent.RdFiles;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await VoidCache(); await VoidCache();
} }
public async Task Update(Torrent torrent) public async Task Update(Torrent torrent)
{ {
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrent.TorrentId); var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrent.TorrentId);
if (dbTorrent == null) if (dbTorrent == null)
{ {
@ -161,14 +154,14 @@ public class TorrentData
dbTorrent.DeleteOnError = torrent.DeleteOnError; dbTorrent.DeleteOnError = torrent.DeleteOnError;
dbTorrent.Lifetime = torrent.Lifetime; dbTorrent.Lifetime = torrent.Lifetime;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await VoidCache(); 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); var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null) if (dbTorrent == null)
{ {
@ -177,14 +170,14 @@ public class TorrentData
dbTorrent.Category = category; dbTorrent.Category = category;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await VoidCache(); 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); var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null) if (dbTorrent == null)
{ {
@ -193,7 +186,7 @@ public class TorrentData
if (String.IsNullOrWhiteSpace(error)) if (String.IsNullOrWhiteSpace(error))
{ {
var downloads = await _dataContext.Downloads.AsNoTracking().Where(m => m.TorrentId == torrentId).ToListAsync(); var downloads = await dataContext.Downloads.AsNoTracking().Where(m => m.TorrentId == torrentId).ToListAsync();
var downloadWithErrors = downloads.Where(m => !String.IsNullOrWhiteSpace(m.Error)).ToList(); var downloadWithErrors = downloads.Where(m => !String.IsNullOrWhiteSpace(m.Error)).ToList();
if (downloadWithErrors.Any()) if (downloadWithErrors.Any())
@ -214,14 +207,14 @@ public class TorrentData
dbTorrent.Completed = datetime; dbTorrent.Completed = datetime;
dbTorrent.Error = error; dbTorrent.Error = error;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await VoidCache(); await VoidCache();
} }
public async Task UpdateFilesSelected(Guid torrentId, DateTimeOffset datetime) public async Task UpdateFilesSelected(Guid torrentId, DateTimeOffset datetime)
{ {
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId); var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null) if (dbTorrent == null)
{ {
@ -230,14 +223,14 @@ public class TorrentData
dbTorrent.FilesSelected = datetime; dbTorrent.FilesSelected = datetime;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await VoidCache(); await VoidCache();
} }
public async Task UpdatePriority(Guid torrentId, Int32? priority) public async Task UpdatePriority(Guid torrentId, Int32? priority)
{ {
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId); var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null) if (dbTorrent == null)
{ {
@ -246,14 +239,14 @@ public class TorrentData
dbTorrent.Priority = priority; dbTorrent.Priority = priority;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await VoidCache(); await VoidCache();
} }
public async Task UpdateRetry(Guid torrentId, DateTimeOffset? dateTime, Int32 retryCount) public async Task UpdateRetry(Guid torrentId, DateTimeOffset? dateTime, Int32 retryCount)
{ {
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId); var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null) if (dbTorrent == null)
{ {
@ -263,14 +256,14 @@ public class TorrentData
dbTorrent.RetryCount = retryCount; dbTorrent.RetryCount = retryCount;
dbTorrent.Retry = dateTime; dbTorrent.Retry = dateTime;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await VoidCache(); await VoidCache();
} }
public async Task UpdateError(Guid torrentId, String error) public async Task UpdateError(Guid torrentId, String error)
{ {
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId); var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null) if (dbTorrent == null)
{ {
@ -279,23 +272,23 @@ public class TorrentData
dbTorrent.Error = error; dbTorrent.Error = error;
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await VoidCache(); await VoidCache();
} }
public async Task Delete(Guid torrentId) public async Task Delete(Guid torrentId)
{ {
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId); var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null) if (dbTorrent == null)
{ {
return; return;
} }
_dataContext.Torrents.Remove(dbTorrent); dataContext.Torrents.Remove(dbTorrent);
await _dataContext.SaveChangesAsync(); await dataContext.SaveChangesAsync();
await VoidCache(); await VoidCache();
} }

View file

@ -3,17 +3,10 @@ using Microsoft.EntityFrameworkCore;
namespace RdtClient.Data.Data; namespace RdtClient.Data.Data;
public class UserData public class UserData(DataContext dataContext)
{ {
private readonly DataContext _dataContext;
public UserData(DataContext dataContext)
{
_dataContext = dataContext;
}
public async Task<IdentityUser?> GetUser() public async Task<IdentityUser?> GetUser()
{ {
return await _dataContext.Users.OrderBy(m => m.Id).FirstOrDefaultAsync(); return await dataContext.Users.OrderBy(m => m.Id).FirstOrDefaultAsync();
} }
} }

View file

@ -8,11 +8,11 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.1" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.1" /> <PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="8.0.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.3">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>

View file

@ -5,18 +5,9 @@ using RdtClient.Service.Services;
namespace RdtClient.Service.BackgroundServices; namespace RdtClient.Service.BackgroundServices;
public class ProviderUpdater : BackgroundService public class ProviderUpdater(ILogger<TaskRunner> logger, IServiceProvider serviceProvider) : BackgroundService
{ {
private readonly ILogger<TaskRunner> _logger;
private readonly IServiceProvider _serviceProvider;
private static DateTime _nextUpdate = DateTime.UtcNow; private static DateTime _nextUpdate = DateTime.UtcNow;
public ProviderUpdater(ILogger<TaskRunner> logger, IServiceProvider serviceProvider)
{
_logger = logger;
_serviceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
@ -25,10 +16,10 @@ public class ProviderUpdater : BackgroundService
await Task.Delay(1000, stoppingToken); await Task.Delay(1000, stoppingToken);
} }
using var scope = _serviceProvider.CreateScope(); using var scope = serviceProvider.CreateScope();
var torrentService = scope.ServiceProvider.GetRequiredService<Torrents>(); var torrentService = scope.ServiceProvider.GetRequiredService<Torrents>();
_logger.LogInformation("ProviderUpdater started."); logger.LogInformation("ProviderUpdater started.");
while (!stoppingToken.IsCancellationRequested) while (!stoppingToken.IsCancellationRequested)
{ {
@ -38,7 +29,7 @@ public class ProviderUpdater : BackgroundService
if (_nextUpdate < DateTime.UtcNow && ((torrents.Count > 0 && !Settings.Get.Provider.AutoImport) || Settings.Get.Provider.AutoImport)) if (_nextUpdate < DateTime.UtcNow && ((torrents.Count > 0 && !Settings.Get.Provider.AutoImport) || Settings.Get.Provider.AutoImport))
{ {
_logger.LogDebug($"Updating torrent info from debrid provider"); logger.LogDebug($"Updating torrent info from debrid provider");
var updateTime = Settings.Get.Provider.CheckInterval * 3; var updateTime = Settings.Get.Provider.CheckInterval * 3;
@ -61,17 +52,17 @@ public class ProviderUpdater : BackgroundService
await torrentService.UpdateRdData(); await torrentService.UpdateRdData();
_logger.LogDebug($"Finished updating torrent info from debrid provider, next update in {updateTime} seconds"); logger.LogDebug($"Finished updating torrent info from debrid provider, next update in {updateTime} seconds");
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, $"Unexpected error occurred in ProviderUpdater: {ex.Message}"); logger.LogError(ex, $"Unexpected error occurred in ProviderUpdater: {ex.Message}");
} }
await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken); await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken);
} }
_logger.LogInformation("ProviderUpdater stopped."); logger.LogInformation("ProviderUpdater stopped.");
} }
} }

View file

@ -9,22 +9,15 @@ using RdtClient.Service.Services;
namespace RdtClient.Service.BackgroundServices; namespace RdtClient.Service.BackgroundServices;
public class Startup : IHostedService public class Startup(IServiceProvider serviceProvider) : IHostedService
{ {
public static Boolean Ready { get; private set; } public static Boolean Ready { get; private set; }
private readonly IServiceProvider _serviceProvider;
public Startup(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task StartAsync(CancellationToken cancellationToken) public async Task StartAsync(CancellationToken cancellationToken)
{ {
var version = Assembly.GetEntryAssembly()?.GetName().Version; var version = Assembly.GetEntryAssembly()?.GetName().Version;
using var scope = _serviceProvider.CreateScope(); using var scope = serviceProvider.CreateScope();
var logger = scope.ServiceProvider.GetRequiredService<ILogger<Startup>>(); var logger = scope.ServiceProvider.GetRequiredService<ILogger<Startup>>();
logger.LogWarning($"Starting host on version {version}"); logger.LogWarning($"Starting host on version {version}");

View file

@ -7,17 +7,8 @@ using RdtClient.Service.Services;
namespace RdtClient.Service.BackgroundServices; namespace RdtClient.Service.BackgroundServices;
public class TaskRunner : BackgroundService public class TaskRunner(ILogger<TaskRunner> logger, IServiceProvider serviceProvider) : BackgroundService
{ {
private readonly ILogger<TaskRunner> _logger;
private readonly IServiceProvider _serviceProvider;
public TaskRunner(ILogger<TaskRunner> logger, IServiceProvider serviceProvider)
{
_logger = logger;
_serviceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
while (!Startup.Ready) while (!Startup.Ready)
@ -25,10 +16,10 @@ public class TaskRunner : BackgroundService
await Task.Delay(1000, stoppingToken); await Task.Delay(1000, stoppingToken);
} }
using var scope = _serviceProvider.CreateScope(); using var scope = serviceProvider.CreateScope();
var torrentRunner = scope.ServiceProvider.GetRequiredService<TorrentRunner>(); var torrentRunner = scope.ServiceProvider.GetRequiredService<TorrentRunner>();
_logger.LogInformation("TaskRunner started."); logger.LogInformation("TaskRunner started.");
await torrentRunner.Initialize(); await torrentRunner.Initialize();
@ -45,21 +36,21 @@ public class TaskRunner : BackgroundService
var proposedValues = entry.CurrentValues; var proposedValues = entry.CurrentValues;
var databaseValues = await entry.GetDatabaseValuesAsync(stoppingToken); var databaseValues = await entry.GetDatabaseValuesAsync(stoppingToken);
_logger.LogWarning("DbUpdateConcurrencyException occurred:"); logger.LogWarning("DbUpdateConcurrencyException occurred:");
_logger.LogWarning("Proposed Values:"); logger.LogWarning("Proposed Values:");
_logger.LogWarning(JsonSerializer.Serialize(proposedValues)); logger.LogWarning(JsonSerializer.Serialize(proposedValues));
_logger.LogWarning("Database Values:"); logger.LogWarning("Database Values:");
_logger.LogWarning(JsonSerializer.Serialize(databaseValues)); logger.LogWarning(JsonSerializer.Serialize(databaseValues));
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, $"Unexpected error occurred in TorrentDownloadManager.Tick: {ex.Message}"); logger.LogError(ex, $"Unexpected error occurred in TorrentDownloadManager.Tick: {ex.Message}");
} }
await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken); await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken);
} }
_logger.LogInformation("TaskRunner stopped."); logger.LogInformation("TaskRunner stopped.");
} }
} }

View file

@ -6,18 +6,11 @@ using Newtonsoft.Json;
namespace RdtClient.Service.BackgroundServices; namespace RdtClient.Service.BackgroundServices;
public class UpdateChecker : BackgroundService public class UpdateChecker(ILogger<UpdateChecker> logger) : BackgroundService
{ {
public static String? CurrentVersion { get; private set; } public static String? CurrentVersion { get; private set; }
public static String? LatestVersion { get; private set; } public static String? LatestVersion { get; private set; }
private readonly ILogger<UpdateChecker> _logger;
public UpdateChecker(ILogger<UpdateChecker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
while (!Startup.Ready) while (!Startup.Ready)
@ -36,7 +29,7 @@ public class UpdateChecker : BackgroundService
CurrentVersion = $"v{version[..version.LastIndexOf(".", StringComparison.Ordinal)]}"; CurrentVersion = $"v{version[..version.LastIndexOf(".", StringComparison.Ordinal)]}";
_logger.LogInformation("UpdateChecker started, currently on version {CurrentVersion}.", CurrentVersion); logger.LogInformation("UpdateChecker started, currently on version {CurrentVersion}.", CurrentVersion);
while (!stoppingToken.IsCancellationRequested) while (!stoppingToken.IsCancellationRequested)
{ {
@ -57,26 +50,26 @@ public class UpdateChecker : BackgroundService
if (latestRelease == null) if (latestRelease == null)
{ {
_logger.LogWarning($"Unable to find latest version on GitHub"); logger.LogWarning($"Unable to find latest version on GitHub");
return; return;
} }
if (latestRelease != CurrentVersion) if (latestRelease != CurrentVersion)
{ {
_logger.LogInformation("New version found on GitHub: {latestRelease}", latestRelease); logger.LogInformation("New version found on GitHub: {latestRelease}", latestRelease);
} }
LatestVersion = latestRelease; LatestVersion = latestRelease;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogDebug(ex, "Unexpected error occurred while checking for updates. This error is safe to ignore."); logger.LogDebug(ex, "Unexpected error occurred while checking for updates. This error is safe to ignore.");
} }
await Task.Delay(TimeSpan.FromHours(1), stoppingToken); await Task.Delay(TimeSpan.FromHours(1), stoppingToken);
} }
_logger.LogInformation("UpdateChecker stopped."); logger.LogInformation("UpdateChecker stopped.");
} }
} }

View file

@ -8,19 +8,10 @@ using LogLevel = Microsoft.Extensions.Logging.LogLevel;
namespace RdtClient.Service.BackgroundServices; namespace RdtClient.Service.BackgroundServices;
public class WatchFolderChecker : BackgroundService public class WatchFolderChecker(ILogger<WatchFolderChecker> logger, IServiceProvider serviceProvider) : BackgroundService
{ {
private readonly ILogger<WatchFolderChecker> _logger;
private readonly IServiceProvider _serviceProvider;
private DateTime _prevCheck = DateTime.MinValue; private DateTime _prevCheck = DateTime.MinValue;
public WatchFolderChecker(ILogger<WatchFolderChecker> logger, IServiceProvider serviceProvider)
{
_logger = logger;
_serviceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
while (!Startup.Ready) while (!Startup.Ready)
@ -28,10 +19,10 @@ public class WatchFolderChecker : BackgroundService
await Task.Delay(1000, stoppingToken); await Task.Delay(1000, stoppingToken);
} }
using var scope = _serviceProvider.CreateScope(); using var scope = serviceProvider.CreateScope();
var torrentService = scope.ServiceProvider.GetRequiredService<Torrents>(); var torrentService = scope.ServiceProvider.GetRequiredService<Torrents>();
_logger.LogInformation("WatchFolderChecker started."); logger.LogInformation("WatchFolderChecker started.");
while (!stoppingToken.IsCancellationRequested) while (!stoppingToken.IsCancellationRequested)
{ {
@ -84,7 +75,7 @@ public class WatchFolderChecker : BackgroundService
try try
{ {
_logger.Log(LogLevel.Debug, "Processing {torrentFile}", torrentFile); logger.Log(LogLevel.Debug, "Processing {torrentFile}", torrentFile);
var torrent = new Torrent var torrent = new Torrent
{ {
@ -125,7 +116,7 @@ public class WatchFolderChecker : BackgroundService
File.Move(torrentFile, processedPath); File.Move(torrentFile, processedPath);
_logger.Log(LogLevel.Debug, "Moved {torrentFile} to {processedPath}", torrentFile, processedPath); logger.Log(LogLevel.Debug, "Moved {torrentFile} to {processedPath}", torrentFile, processedPath);
} }
catch catch
{ {
@ -141,7 +132,7 @@ public class WatchFolderChecker : BackgroundService
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, $"Unexpected error occurred in ProviderUpdater: {ex.Message}"); logger.LogError(ex, $"Unexpected error occurred in ProviderUpdater: {ex.Message}");
} }
} }
} }

View file

@ -3,15 +3,8 @@ using Microsoft.AspNetCore.Http;
namespace RdtClient.Service.Middleware; namespace RdtClient.Service.Middleware;
public class AuthorizeMiddleware public class AuthorizeMiddleware(RequestDelegate next)
{ {
private readonly RequestDelegate _next;
public AuthorizeMiddleware(RequestDelegate next)
{
_next = next;
}
/// <summary> /// <summary>
/// Return a 403 instead of a 401, it's quirk that QBittorrent has. /// Return a 403 instead of a 401, it's quirk that QBittorrent has.
/// </summary> /// </summary>
@ -19,7 +12,7 @@ public class AuthorizeMiddleware
/// <returns></returns> /// <returns></returns>
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
await _next(context); await next(context);
if (context.Response.StatusCode == (Int32) HttpStatusCode.Unauthorized) if (context.Response.StatusCode == (Int32) HttpStatusCode.Unauthorized)
{ {

View file

@ -3,16 +3,9 @@ using Microsoft.AspNetCore.Http;
namespace RdtClient.Service.Middleware; namespace RdtClient.Service.Middleware;
public class BaseHrefMiddleware public class BaseHrefMiddleware(RequestDelegate next, String basePath)
{ {
private readonly RequestDelegate _next; private readonly String _basePath = $"/{basePath.TrimStart('/').TrimEnd('/')}/";
private readonly String _basePath;
public BaseHrefMiddleware(RequestDelegate next, String basePath)
{
_next = next;
_basePath = $"/{basePath.TrimStart('/').TrimEnd('/')}/";
}
public async Task InvokeAsync(HttpContext context) public async Task InvokeAsync(HttpContext context)
{ {
@ -24,7 +17,7 @@ public class BaseHrefMiddleware
context.Response.Body = newBody; context.Response.Body = newBody;
await _next(context); await next(context);
context.Response.Body = originalBody; context.Response.Body = originalBody;
newBody.Seek(0, SeekOrigin.Begin); newBody.Seek(0, SeekOrigin.Begin);

View file

@ -4,22 +4,15 @@ using System.Text;
namespace RdtClient.Service.Middleware; namespace RdtClient.Service.Middleware;
public class RequestLoggingMiddleware public class RequestLoggingMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{ {
private readonly RequestDelegate _next; private readonly ILogger _logger = loggerFactory.CreateLogger<RequestLoggingMiddleware>();
private readonly ILogger _logger;
public RequestLoggingMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
_next = next;
_logger = loggerFactory.CreateLogger<RequestLoggingMiddleware>();
}
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
if (!_logger.IsEnabled(LogLevel.Debug) || (!context.Request.Path.StartsWithSegments("/api/v2") && !context.Request.Path.StartsWithSegments("/api/torrents"))) if (!_logger.IsEnabled(LogLevel.Debug) || (!context.Request.Path.StartsWithSegments("/api/v2") && !context.Request.Path.StartsWithSegments("/api/torrents")))
{ {
await _next(context); await next(context);
return; return;
} }
@ -43,7 +36,7 @@ public class RequestLoggingMiddleware
_logger.LogDebug(requestLog); _logger.LogDebug(requestLog);
await _next(context); await next(context);
} }
private static async Task<String> ReadRequestBodyAsync(HttpRequest request) private static async Task<String> ReadRequestBodyAsync(HttpRequest request)

View file

@ -3,24 +3,13 @@ using RdtClient.Data.Data;
namespace RdtClient.Service.Services; namespace RdtClient.Service.Services;
public class Authentication public class Authentication(SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager, UserData userData)
{ {
private readonly SignInManager<IdentityUser> _signInManager;
private readonly UserManager<IdentityUser> _userManager;
private readonly UserData _userData;
public Authentication(SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager, UserData userData)
{
_signInManager = signInManager;
_userManager = userManager;
_userData = userData;
}
public async Task<IdentityResult> Register(String userName, String password) public async Task<IdentityResult> Register(String userName, String password)
{ {
var user = new IdentityUser(userName); var user = new IdentityUser(userName);
var result = await _userManager.CreateAsync(user, password); var result = await userManager.CreateAsync(user, password);
return result; return result;
} }
@ -32,41 +21,36 @@ public class Authentication
return SignInResult.Failed; return SignInResult.Failed;
} }
var result = await _signInManager.PasswordSignInAsync(userName, password, true, false); var result = await signInManager.PasswordSignInAsync(userName, password, true, false);
return result; return result;
} }
public async Task<IdentityUser?> GetUser() public async Task<IdentityUser?> GetUser()
{ {
return await _userData.GetUser(); return await userData.GetUser();
} }
public async Task Logout() public async Task Logout()
{ {
await _signInManager.SignOutAsync(); await signInManager.SignOutAsync();
} }
public async Task<IdentityResult> Update(String newUserName, String newPassword) public async Task<IdentityResult> Update(String newUserName, String newPassword)
{ {
var user = await GetUser(); var user = await GetUser() ?? throw new Exception("No logged in user found");
if (user == null)
{
throw new Exception("No logged in user found");
}
if (!String.IsNullOrWhiteSpace(newUserName)) if (!String.IsNullOrWhiteSpace(newUserName))
{ {
user.UserName = newUserName; user.UserName = newUserName;
} }
await _userManager.UpdateAsync(user); await userManager.UpdateAsync(user);
if (!String.IsNullOrWhiteSpace(newPassword)) if (!String.IsNullOrWhiteSpace(newPassword))
{ {
var token = await _userManager.GeneratePasswordResetTokenAsync(user); var token = await userManager.GeneratePasswordResetTokenAsync(user);
var result = await _userManager.ResetPasswordAsync(user, token, newPassword); var result = await userManager.ResetPasswordAsync(user, token, newPassword);
return result; return result;
} }

View file

@ -4,12 +4,12 @@ using RdtClient.Service.Services.Downloaders;
namespace RdtClient.Service.Services; namespace RdtClient.Service.Services;
public class DownloadClient public class DownloadClient(Download download, Torrent torrent, String destinationPath)
{ {
private readonly String _destinationPath; private readonly String _destinationPath = destinationPath;
private readonly Download _download; private readonly Download _download = download;
private readonly Torrent _torrent; private readonly Torrent _torrent = torrent;
public IDownloader? Downloader; public IDownloader? Downloader;
@ -23,13 +23,6 @@ public class DownloadClient
public Int64 BytesTotal { get; private set; } public Int64 BytesTotal { get; private set; }
public Int64 BytesDone { get; private set; } public Int64 BytesDone { get; private set; }
public DownloadClient(Download download, Torrent torrent, String destinationPath)
{
_download = download;
_torrent = torrent;
_destinationPath = destinationPath;
}
public async Task<String?> Start() public async Task<String?> Start()
{ {
BytesDone = 0; BytesDone = 0;

View file

@ -22,6 +22,8 @@ public class Aria2cDownloader : IDownloader
public Aria2cDownloader(String? gid, String uri, String filePath, String downloadPath) public Aria2cDownloader(String? gid, String uri, String filePath, String downloadPath)
{ {
_logger = Log.ForContext<Aria2cDownloader>(); _logger = Log.ForContext<Aria2cDownloader>();
_logger.Debug($"Instantiated new Aria2c Downloader for URI {uri} to filePath {filePath} and downloadPath {downloadPath} and GID {gid}");
_gid = gid; _gid = gid;
_uri = uri; _uri = uri;
_filePath = filePath; _filePath = filePath;
@ -45,13 +47,7 @@ public class Aria2cDownloader : IDownloader
public async Task<String?> Download() public async Task<String?> Download()
{ {
var path = Path.GetDirectoryName(_remotePath); var path = Path.GetDirectoryName(_remotePath) ?? throw new Exception($"Invalid file path {_filePath}");
if (path == null)
{
throw new Exception($"Invalid file path {_filePath}");
}
var fileName = Path.GetFileName(_filePath); var fileName = Path.GetFileName(_filePath);
_logger.Debug($"Starting download of {_uri}, writing to path: {_filePath} (on aria2: {_remotePath}), fileName: {fileName}"); _logger.Debug($"Starting download of {_uri}, writing to path: {_filePath} (on aria2: {_remotePath}), fileName: {fileName}");
@ -85,10 +81,9 @@ public class Aria2cDownloader : IDownloader
} }
} }
_gid ??= await _aria2NetClient.AddUriAsync(new List<String> _gid ??= await _aria2NetClient.AddUriAsync([
{
_uri _uri
}, ],
new Dictionary<String, Object> new Dictionary<String, Object>
{ {
{ {

View file

@ -22,6 +22,7 @@ public class BezzadDownloader : IDownloader
public BezzadDownloader(String uri, String filePath) public BezzadDownloader(String uri, String filePath)
{ {
_logger = Log.ForContext<BezzadDownloader>(); _logger = Log.ForContext<BezzadDownloader>();
_logger.Debug($"Instantiated new Bezzad Downloader for URI {uri} to filePath {filePath}");
_uri = uri; _uri = uri;
_filePath = filePath; _filePath = filePath;

View file

@ -22,6 +22,7 @@ public class InternalDownloader : IDownloader
public InternalDownloader(String uri, String filePath) public InternalDownloader(String uri, String filePath)
{ {
_logger = Log.ForContext<InternalDownloader>(); _logger = Log.ForContext<InternalDownloader>();
_logger.Debug($"Instantiated new Internal Downloader for URI {uri} to filePath {filePath}");
_uri = uri; _uri = uri;
_filePath = filePath; _filePath = filePath;

View file

@ -17,6 +17,7 @@ public class SymlinkDownloader : IDownloader
public SymlinkDownloader(String uri, String filePath) public SymlinkDownloader(String uri, String filePath)
{ {
_logger = Log.ForContext<SymlinkDownloader>(); _logger = Log.ForContext<SymlinkDownloader>();
_logger.Debug($"Instantiated new Symlink Downloader for URI {uri} to filePath {filePath}");
_uri = uri; _uri = uri;
_filePath = filePath; _filePath = filePath;
@ -38,13 +39,13 @@ public class SymlinkDownloader : IDownloader
_logger.Debug($"Searching {Settings.Get.DownloadClient.RcloneMountPath} for {fileName}"); _logger.Debug($"Searching {Settings.Get.DownloadClient.RcloneMountPath} for {fileName}");
// Recursively search for the fileName in the rclone mount location. // Recursively search for the fileName in the rclone mount location.
var foundFiles = Directory.GetFiles(Settings.Get.DownloadClient.RcloneMountPath, fileName, SearchOption.AllDirectories); var foundFiles = Directory.GetFiles(Settings.Get.DownloadClient.RcloneMountPath, fileName, SearchOption.AllDirectories).ToList();
if (foundFiles.Any()) if (foundFiles.Count > 0)
{ {
if (foundFiles.Length > 1) if (foundFiles.Count > 1)
{ {
_logger.Warning($"Found {foundFiles.Length} files named {fileName}"); _logger.Warning($"Found {foundFiles.Count} files named {fileName}");
} }
// Assume first matching filename is the one we want. // Assume first matching filename is the one we want.

View file

@ -3,92 +3,85 @@ using Download = RdtClient.Data.Models.Data.Download;
namespace RdtClient.Service.Services; namespace RdtClient.Service.Services;
public class Downloads public class Downloads(DownloadData downloadData)
{ {
private readonly DownloadData _downloadData;
public Downloads(DownloadData downloadData)
{
_downloadData = downloadData;
}
public async Task<List<Download>> GetForTorrent(Guid torrentId) public async Task<List<Download>> GetForTorrent(Guid torrentId)
{ {
return await _downloadData.GetForTorrent(torrentId); return await downloadData.GetForTorrent(torrentId);
} }
public async Task<Download?> GetById(Guid downloadId) public async Task<Download?> GetById(Guid downloadId)
{ {
return await _downloadData.GetById(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); return await downloadData.Get(torrentId, path);
} }
public async Task<Download> Add(Guid torrentId, String path) public async Task<Download> Add(Guid torrentId, String path)
{ {
return await _downloadData.Add(torrentId, path); return await downloadData.Add(torrentId, path);
} }
public async Task UpdateUnrestrictedLink(Guid downloadId, String unrestrictedLink) public async Task UpdateUnrestrictedLink(Guid downloadId, String unrestrictedLink)
{ {
await _downloadData.UpdateUnrestrictedLink(downloadId, unrestrictedLink); await downloadData.UpdateUnrestrictedLink(downloadId, unrestrictedLink);
} }
public async Task UpdateDownloadStarted(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateDownloadStarted(Guid downloadId, DateTimeOffset? dateTime)
{ {
await _downloadData.UpdateDownloadStarted(downloadId, dateTime); await downloadData.UpdateDownloadStarted(downloadId, dateTime);
} }
public async Task UpdateDownloadFinished(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateDownloadFinished(Guid downloadId, DateTimeOffset? dateTime)
{ {
await _downloadData.UpdateDownloadFinished(downloadId, dateTime); await downloadData.UpdateDownloadFinished(downloadId, dateTime);
} }
public async Task UpdateUnpackingQueued(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateUnpackingQueued(Guid downloadId, DateTimeOffset? dateTime)
{ {
await _downloadData.UpdateUnpackingQueued(downloadId, dateTime); await downloadData.UpdateUnpackingQueued(downloadId, dateTime);
} }
public async Task UpdateUnpackingStarted(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateUnpackingStarted(Guid downloadId, DateTimeOffset? dateTime)
{ {
await _downloadData.UpdateUnpackingStarted(downloadId, dateTime); await downloadData.UpdateUnpackingStarted(downloadId, dateTime);
} }
public async Task UpdateUnpackingFinished(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateUnpackingFinished(Guid downloadId, DateTimeOffset? dateTime)
{ {
await _downloadData.UpdateUnpackingFinished(downloadId, dateTime); await downloadData.UpdateUnpackingFinished(downloadId, dateTime);
} }
public async Task UpdateCompleted(Guid downloadId, DateTimeOffset? dateTime) public async Task UpdateCompleted(Guid downloadId, DateTimeOffset? dateTime)
{ {
await _downloadData.UpdateCompleted(downloadId, dateTime); 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); await downloadData.UpdateError(downloadId, error);
} }
public async Task UpdateRetryCount(Guid downloadId, Int32 retryCount) public async Task UpdateRetryCount(Guid downloadId, Int32 retryCount)
{ {
await _downloadData.UpdateRetryCount(downloadId, retryCount); await downloadData.UpdateRetryCount(downloadId, retryCount);
} }
public async Task UpdateRemoteId(Guid downloadId, String remoteId) public async Task UpdateRemoteId(Guid downloadId, String remoteId)
{ {
await _downloadData.UpdateRemoteId(downloadId, remoteId); await downloadData.UpdateRemoteId(downloadId, remoteId);
} }
public async Task DeleteForTorrent(Guid torrentId) public async Task DeleteForTorrent(Guid torrentId)
{ {
await _downloadData.DeleteForTorrent(torrentId); await downloadData.DeleteForTorrent(torrentId);
} }
public async Task Reset(Guid downloadId) public async Task Reset(Guid downloadId)
{ {
await _downloadData.Reset(downloadId); await downloadData.Reset(downloadId);
} }
} }

View file

@ -5,37 +5,22 @@ using RdtClient.Data.Models.QBittorrent;
namespace RdtClient.Service.Services; namespace RdtClient.Service.Services;
public class QBittorrent public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authentication authentication, Torrents torrents, Downloads downloads)
{ {
private readonly Authentication _authentication;
private readonly ILogger<QBittorrent> _logger;
private readonly Settings _settings;
private readonly Torrents _torrents;
private readonly Downloads _downloads;
public QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authentication authentication, Torrents torrents, Downloads downloads)
{
_logger = logger;
_settings = settings;
_authentication = authentication;
_torrents = torrents;
_downloads = downloads;
}
public async Task<Boolean> AuthLogin(String userName, String password) public async Task<Boolean> AuthLogin(String userName, String password)
{ {
_logger.LogDebug("Auth login"); logger.LogDebug("Auth login");
var login = await _authentication.Login(userName, password); var login = await authentication.Login(userName, password);
return login.Succeeded; return login.Succeeded;
} }
public async Task AuthLogout() public async Task AuthLogout()
{ {
_logger.LogDebug("Auth logout"); logger.LogDebug("Auth logout");
await _authentication.Logout(); await authentication.Logout();
} }
public async Task<AppPreferences> AppPreferences() public async Task<AppPreferences> AppPreferences()
@ -189,7 +174,7 @@ public class QBittorrent
preferences.SavePath = savePath; preferences.SavePath = savePath;
preferences.TempPath = $"{savePath}temp{Path.DirectorySeparatorChar}"; preferences.TempPath = $"{savePath}temp{Path.DirectorySeparatorChar}";
var user = await _authentication.GetUser(); var user = await authentication.GetUser();
if (user != null) if (user != null)
{ {
@ -205,13 +190,13 @@ public class QBittorrent
var results = new List<TorrentInfo>(); var results = new List<TorrentInfo>();
var torrents = await _torrents.Get(); var torrents1 = await torrents.Get();
var prio = 0; var prio = 0;
Decimal? downloadProgress = 0; Decimal? downloadProgress = 0;
foreach (var torrent in torrents) foreach (var torrent in torrents1)
{ {
var downloadPath = savePath; var downloadPath = savePath;
@ -312,7 +297,7 @@ public class QBittorrent
{ {
var results = new List<TorrentFileItem>(); var results = new List<TorrentFileItem>();
var torrent = await _torrents.GetByHash(hash); var torrent = await torrents.GetByHash(hash);
if (torrent == null) if (torrent == null)
{ {
@ -336,7 +321,7 @@ public class QBittorrent
{ {
var savePath = Settings.AppDefaultSavePath; var savePath = Settings.AppDefaultSavePath;
var torrent = await _torrents.GetByHash(hash); var torrent = await torrents.GetByHash(hash);
if (torrent == null) if (torrent == null)
{ {
@ -403,14 +388,14 @@ public class QBittorrent
{ {
if (deleteFiles) if (deleteFiles)
{ {
_logger.LogDebug($"Delete {hash}, with files"); logger.LogDebug($"Delete {hash}, with files");
} }
else else
{ {
_logger.LogDebug($"Delete {hash}, no files"); logger.LogDebug($"Delete {hash}, no files");
} }
var torrent = await _torrents.GetByHash(hash); var torrent = await torrents.GetByHash(hash);
if (torrent == null) if (torrent == null)
{ {
@ -420,26 +405,26 @@ public class QBittorrent
switch (Settings.Get.Integrations.Default.FinishedAction) switch (Settings.Get.Integrations.Default.FinishedAction)
{ {
case TorrentFinishedAction.RemoveAllTorrents: case TorrentFinishedAction.RemoveAllTorrents:
_logger.LogDebug("Removing torrents from debrid provider and RDT-Client, no files"); logger.LogDebug("Removing torrents from debrid provider and RDT-Client, no files");
await _torrents.Delete(torrent.TorrentId, true, true, deleteFiles); await torrents.Delete(torrent.TorrentId, true, true, deleteFiles);
break; break;
case TorrentFinishedAction.RemoveRealDebrid: case TorrentFinishedAction.RemoveRealDebrid:
_logger.LogDebug("Removing torrents from debrid provider, no files"); logger.LogDebug("Removing torrents from debrid provider, no files");
await _torrents.Delete(torrent.TorrentId, false, true, deleteFiles); await torrents.Delete(torrent.TorrentId, false, true, deleteFiles);
break; break;
case TorrentFinishedAction.RemoveClient: case TorrentFinishedAction.RemoveClient:
_logger.LogDebug("Removing torrents from client, no files"); logger.LogDebug("Removing torrents from client, no files");
await _torrents.Delete(torrent.TorrentId, true, false, deleteFiles); await torrents.Delete(torrent.TorrentId, true, false, deleteFiles);
break; break;
case TorrentFinishedAction.None: case TorrentFinishedAction.None:
_logger.LogDebug("Not removing torrents or files"); logger.LogDebug("Not removing torrents or files");
break; break;
default: default:
_logger.LogDebug($"Invalid torrent FinishedAction {torrent.FinishedAction}", torrent); logger.LogDebug($"Invalid torrent FinishedAction {torrent.FinishedAction}", torrent);
break; break;
} }
@ -447,7 +432,7 @@ public class QBittorrent
public async Task TorrentsAddMagnet(String magnetLink, String? category, Int32? priority) public async Task TorrentsAddMagnet(String magnetLink, String? category, Int32? priority)
{ {
_logger.LogDebug($"Add magnet {category}"); logger.LogDebug($"Add magnet {category}");
var torrent = new Torrent var torrent = new Torrent
{ {
@ -466,12 +451,12 @@ public class QBittorrent
Priority = priority ?? (Settings.Get.Integrations.Default.Priority > 0 ? Settings.Get.Integrations.Default.Priority : null) Priority = priority ?? (Settings.Get.Integrations.Default.Priority > 0 ? Settings.Get.Integrations.Default.Priority : null)
}; };
await _torrents.UploadMagnet(magnetLink, torrent); 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)
{ {
_logger.LogDebug($"Add file {category}"); logger.LogDebug($"Add file {category}");
var torrent = new Torrent var torrent = new Torrent
{ {
@ -490,19 +475,19 @@ public class QBittorrent
Priority = priority ?? (Settings.Get.Integrations.Default.Priority > 0 ? Settings.Get.Integrations.Default.Priority : null) Priority = priority ?? (Settings.Get.Integrations.Default.Priority > 0 ? Settings.Get.Integrations.Default.Priority : null)
}; };
await _torrents.UploadFile(fileBytes, torrent); 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); await torrents.UpdateCategory(hash, category);
} }
public async Task<IDictionary<String, TorrentCategory>> TorrentsCategories() public async Task<IDictionary<String, TorrentCategory>> TorrentsCategories()
{ {
var torrents = await _torrents.Get(); var torrents1 = await torrents.Get();
var torrentsToGroup = torrents.Where(m => !String.IsNullOrWhiteSpace(m.Category)) var torrentsToGroup = torrents1.Where(m => !String.IsNullOrWhiteSpace(m.Category))
.Select(m => m.Category!.ToLower()) .Select(m => m.Category!.ToLower())
.ToList(); .ToList();
@ -554,7 +539,7 @@ public class QBittorrent
categoriesSetting = String.Join(",", categoryList); categoriesSetting = String.Join(",", categoryList);
await _settings.Update("General:Categories", categoriesSetting); await settings.Update("General:Categories", categoriesSetting);
} }
public async Task CategoryRemove(String? category) public async Task CategoryRemove(String? category)
@ -578,26 +563,26 @@ public class QBittorrent
categoriesSetting = String.Join(",", categoryList); categoriesSetting = String.Join(",", categoryList);
await _settings.Update("General:Categories", categoriesSetting); await settings.Update("General:Categories", categoriesSetting);
} }
public async Task TorrentsTopPrio(String hash) public async Task TorrentsTopPrio(String hash)
{ {
await _torrents.UpdatePriority(hash, 1); await torrents.UpdatePriority(hash, 1);
} }
public async Task TorrentPause(String hash) public async Task TorrentPause(String hash)
{ {
var torrent = await _torrents.GetByHash(hash); var torrent = await torrents.GetByHash(hash);
if (torrent == null) if (torrent == null)
{ {
return; return;
} }
var downloads = await _downloads.GetForTorrent(torrent.TorrentId); var downloads1 = await downloads.GetForTorrent(torrent.TorrentId);
foreach (var download in downloads) foreach (var download in downloads1)
{ {
if (TorrentRunner.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient)) if (TorrentRunner.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient))
{ {
@ -608,16 +593,16 @@ public class QBittorrent
public async Task TorrentResume(String hash) public async Task TorrentResume(String hash)
{ {
var torrent = await _torrents.GetByHash(hash); var torrent = await torrents.GetByHash(hash);
if (torrent == null) if (torrent == null)
{ {
return; return;
} }
var downloads = await _downloads.GetForTorrent(torrent.TorrentId); var downloads1 = await downloads.GetForTorrent(torrent.TorrentId);
foreach (var download in downloads) foreach (var download in downloads1)
{ {
if (TorrentRunner.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient)) if (TorrentRunner.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient))
{ {

View file

@ -2,31 +2,22 @@
namespace RdtClient.Service.Services; namespace RdtClient.Service.Services;
public class RemoteService public class RemoteService(IHubContext<RdtHub> hub, Torrents torrents)
{ {
private readonly IHubContext<RdtHub> _hub;
private readonly Torrents _torrents;
public RemoteService(IHubContext<RdtHub> hub, Torrents torrents)
{
_hub = hub;
_torrents = torrents;
}
public async Task Update() public async Task Update()
{ {
var torrents = await _torrents.Get(); var torrents1 = await torrents.Get();
// Prevent infinite recursion when serializing // Prevent infinite recursion when serializing
foreach (var file in torrents.SelectMany(torrent => torrent.Downloads)) foreach (var file in torrents1.SelectMany(torrent => torrent.Downloads))
{ {
file.Torrent = null; file.Torrent = null;
} }
await _hub.Clients.All.SendCoreAsync("update", await hub.Clients.All.SendCoreAsync("update",
new Object[] new Object[]
{ {
torrents torrents1
}); });
} }
} }

View file

@ -6,17 +6,10 @@ using Serilog.Events;
namespace RdtClient.Service.Services; namespace RdtClient.Service.Services;
public class Settings public class Settings(SettingData settingData)
{ {
public static readonly LoggingLevelSwitch LoggingLevelSwitch = new(LogEventLevel.Debug); public static readonly LoggingLevelSwitch LoggingLevelSwitch = new(LogEventLevel.Debug);
private readonly SettingData _settingData;
public Settings(SettingData settingData)
{
_settingData = settingData;
}
public static DbSettings Get => SettingData.Get; public static DbSettings Get => SettingData.Get;
public static String AppDefaultSavePath public static String AppDefaultSavePath
@ -36,22 +29,22 @@ public class Settings
public async Task Update(IList<SettingProperty> settings) public async Task Update(IList<SettingProperty> settings)
{ {
await _settingData.Update(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); await settingData.Update(settingId, value);
} }
public async Task Seed() public async Task Seed()
{ {
await _settingData.Seed(); await settingData.Seed();
} }
public async Task ResetCache() public async Task ResetCache()
{ {
await _settingData.ResetCache(); await settingData.ResetCache();
LoggingLevelSwitch.MinimumLevel = Settings.Get.General.LogLevel switch LoggingLevelSwitch.MinimumLevel = Settings.Get.General.LogLevel switch
{ {

View file

@ -9,17 +9,8 @@ using Torrent = RdtClient.Data.Models.Data.Torrent;
namespace RdtClient.Service.Services.TorrentClients; namespace RdtClient.Service.Services.TorrentClients;
public class AllDebridTorrentClient : ITorrentClient public class AllDebridTorrentClient(ILogger<AllDebridTorrentClient> logger, IHttpClientFactory httpClientFactory) : ITorrentClient
{ {
private readonly ILogger<AllDebridTorrentClient> _logger;
private readonly IHttpClientFactory _httpClientFactory;
public AllDebridTorrentClient(ILogger<AllDebridTorrentClient> logger, IHttpClientFactory httpClientFactory)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
}
private AllDebridNETClient GetClient() private AllDebridNETClient GetClient()
{ {
try try
@ -31,7 +22,7 @@ public class AllDebridTorrentClient : ITorrentClient
throw new Exception("All-Debrid API Key not set in the settings"); throw new Exception("All-Debrid API Key not set in the settings");
} }
var httpClient = _httpClientFactory.CreateClient(); var httpClient = httpClientFactory.CreateClient();
httpClient.Timeout = TimeSpan.FromSeconds(10); httpClient.Timeout = TimeSpan.FromSeconds(10);
var allDebridNetClient = new AllDebridNETClient("RealDebridClient", apiKey, httpClient); var allDebridNetClient = new AllDebridNETClient("RealDebridClient", apiKey, httpClient);
@ -40,13 +31,13 @@ public class AllDebridTorrentClient : ITorrentClient
} }
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
{ {
_logger.LogError(ex, $"The connection to AllDebrid has timed out: {ex.Message}"); logger.LogError(ex, $"The connection to AllDebrid has timed out: {ex.Message}");
throw; throw;
} }
catch (TaskCanceledException ex) catch (TaskCanceledException ex)
{ {
_logger.LogError(ex, $"The connection to AllDebrid has timed out: {ex.Message}"); logger.LogError(ex, $"The connection to AllDebrid has timed out: {ex.Message}");
throw; throw;
} }
@ -375,6 +366,6 @@ public class AllDebridTorrentClient : ITorrentClient
message = $"{message} {torrent.ToLog()}"; message = $"{message} {torrent.ToLog()}";
} }
_logger.LogDebug(message); logger.LogDebug(message);
} }
} }

View file

@ -8,17 +8,8 @@ using Torrent = RdtClient.Data.Models.Data.Torrent;
namespace RdtClient.Service.Services.TorrentClients; namespace RdtClient.Service.Services.TorrentClients;
public class PremiumizeTorrentClient : ITorrentClient public class PremiumizeTorrentClient(ILogger<PremiumizeTorrentClient> logger, IHttpClientFactory httpClientFactory) : ITorrentClient
{ {
private readonly ILogger<PremiumizeTorrentClient> _logger;
private readonly IHttpClientFactory _httpClientFactory;
public PremiumizeTorrentClient(ILogger<PremiumizeTorrentClient> logger, IHttpClientFactory httpClientFactory)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
}
private PremiumizeNETClient GetClient() private PremiumizeNETClient GetClient()
{ {
try try
@ -30,7 +21,7 @@ public class PremiumizeTorrentClient : ITorrentClient
throw new Exception("Premiumize API Key not set in the settings"); throw new Exception("Premiumize API Key not set in the settings");
} }
var httpClient = _httpClientFactory.CreateClient(); var httpClient = httpClientFactory.CreateClient();
httpClient.Timeout = TimeSpan.FromSeconds(10); httpClient.Timeout = TimeSpan.FromSeconds(10);
var premiumizeNetClient = new PremiumizeNETClient(apiKey, httpClient); var premiumizeNetClient = new PremiumizeNETClient(apiKey, httpClient);
@ -39,13 +30,13 @@ public class PremiumizeTorrentClient : ITorrentClient
} }
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
{ {
_logger.LogError(ex, $"The connection to Premiumize has timed out: {ex.Message}"); logger.LogError(ex, $"The connection to Premiumize has timed out: {ex.Message}");
throw; throw;
} }
catch (TaskCanceledException ex) catch (TaskCanceledException ex)
{ {
_logger.LogError(ex, $"The connection to Premiumize has timed out: {ex.Message}"); logger.LogError(ex, $"The connection to Premiumize has timed out: {ex.Message}");
throw; throw;
} }
@ -329,6 +320,6 @@ public class PremiumizeTorrentClient : ITorrentClient
message = $"{message} {torrent.ToLog()}"; message = $"{message} {torrent.ToLog()}";
} }
_logger.LogDebug(message); logger.LogDebug(message);
} }
} }

View file

@ -8,18 +8,10 @@ using RdtClient.Service.Helpers;
namespace RdtClient.Service.Services.TorrentClients; namespace RdtClient.Service.Services.TorrentClients;
public class RealDebridTorrentClient : ITorrentClient public class RealDebridTorrentClient(ILogger<RealDebridTorrentClient> logger, IHttpClientFactory httpClientFactory) : ITorrentClient
{ {
private readonly ILogger<RealDebridTorrentClient> _logger;
private readonly IHttpClientFactory _httpClientFactory;
private TimeSpan? _offset; private TimeSpan? _offset;
public RealDebridTorrentClient(ILogger<RealDebridTorrentClient> logger, IHttpClientFactory httpClientFactory)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
}
private RdNetClient GetClient() private RdNetClient GetClient()
{ {
try try
@ -31,7 +23,7 @@ public class RealDebridTorrentClient : ITorrentClient
throw new Exception("Real-Debrid API Key not set in the settings"); throw new Exception("Real-Debrid API Key not set in the settings");
} }
var httpClient = _httpClientFactory.CreateClient(); var httpClient = httpClientFactory.CreateClient();
httpClient.Timeout = TimeSpan.FromSeconds(Settings.Get.Provider.Timeout); httpClient.Timeout = TimeSpan.FromSeconds(Settings.Get.Provider.Timeout);
var rdtNetClient = new RdNetClient(null, httpClient, 5); var rdtNetClient = new RdNetClient(null, httpClient, 5);
@ -50,20 +42,20 @@ public class RealDebridTorrentClient : ITorrentClient
{ {
foreach (var inner in ae.InnerExceptions) foreach (var inner in ae.InnerExceptions)
{ {
_logger.LogError(inner, $"The connection to RealDebrid has failed: {inner.Message}"); logger.LogError(inner, $"The connection to RealDebrid has failed: {inner.Message}");
} }
throw; throw;
} }
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
{ {
_logger.LogError(ex, $"The connection to RealDebrid has timed out: {ex.Message}"); logger.LogError(ex, $"The connection to RealDebrid has timed out: {ex.Message}");
throw; throw;
} }
catch (TaskCanceledException ex) catch (TaskCanceledException ex)
{ {
_logger.LogError(ex, $"The connection to RealDebrid has timed out: {ex.Message}"); logger.LogError(ex, $"The connection to RealDebrid has timed out: {ex.Message}");
throw; throw;
} }
@ -451,6 +443,6 @@ public class RealDebridTorrentClient : ITorrentClient
message = $"{message} {torrent.ToLog()}"; message = $"{message} {torrent.ToLog()}";
} }
_logger.LogDebug(message); logger.LogDebug(message);
} }
} }

View file

@ -12,29 +12,15 @@ using RdtClient.Service.Services.Downloaders;
namespace RdtClient.Service.Services; namespace RdtClient.Service.Services;
public class TorrentRunner public class TorrentRunner(ILogger<TorrentRunner> logger, Torrents torrents, Downloads downloads, RemoteService remoteService)
{ {
public static readonly ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients = new(); public static readonly ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients = new();
public static readonly ConcurrentDictionary<Guid, UnpackClient> ActiveUnpackClients = new(); public static readonly ConcurrentDictionary<Guid, UnpackClient> ActiveUnpackClients = new();
private readonly ILogger<TorrentRunner> _logger; private readonly HttpClient _httpClient = new()
private readonly Torrents _torrents;
private readonly Downloads _downloads;
private readonly RemoteService _remoteService;
private readonly HttpClient _httpClient;
public TorrentRunner(ILogger<TorrentRunner> logger, Torrents torrents, Downloads downloads, RemoteService remoteService)
{ {
_logger = logger; Timeout = TimeSpan.FromSeconds(10)
_torrents = torrents; };
_downloads = downloads;
_remoteService = remoteService;
_httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(10)
};
}
public async Task Initialize() public async Task Initialize()
{ {
@ -51,13 +37,13 @@ public class TorrentRunner
} }
// When starting up reset any pending downloads or unpackings so that they are restarted. // When starting up reset any pending downloads or unpackings so that they are restarted.
var torrents = await _torrents.Get(); var torrents1 = await torrents.Get();
torrents = torrents.Where(m => m.Completed == null).ToList(); torrents1 = torrents1.Where(m => m.Completed == null).ToList();
Log($"Found {torrents.Count} not completed torrents"); Log($"Found {torrents1.Count} not completed torrents");
foreach (var torrent in torrents) foreach (var torrent in torrents1)
{ {
foreach (var download in torrent.Downloads) foreach (var download in torrent.Downloads)
{ {
@ -65,14 +51,14 @@ public class TorrentRunner
{ {
Log("Resetting download status", download, torrent); Log("Resetting download status", download, torrent);
await _downloads.UpdateDownloadStarted(download.DownloadId, null); await downloads.UpdateDownloadStarted(download.DownloadId, null);
} }
if (download.UnpackingQueued != null && download.UnpackingStarted != null && download.UnpackingFinished == null && download.Error == null) if (download.UnpackingQueued != null && download.UnpackingStarted != null && download.UnpackingFinished == null && download.Error == null)
{ {
Log("Resetting unpack status", download, torrent); Log("Resetting unpack status", download, torrent);
await _downloads.UpdateUnpackingStarted(download.DownloadId, null); await downloads.UpdateUnpackingStarted(download.DownloadId, null);
} }
} }
} }
@ -103,7 +89,7 @@ public class TorrentRunner
var settingDownloadPath = Settings.Get.DownloadClient.DownloadPath; var settingDownloadPath = Settings.Get.DownloadClient.DownloadPath;
if (String.IsNullOrWhiteSpace(settingDownloadPath)) if (String.IsNullOrWhiteSpace(settingDownloadPath))
{ {
_logger.LogError("No DownloadPath set in settings"); logger.LogError("No DownloadPath set in settings");
return; return;
} }
@ -145,7 +131,7 @@ public class TorrentRunner
foreach (var (downloadId, downloadClient) in completedActiveDownloads) foreach (var (downloadId, downloadClient) in completedActiveDownloads)
{ {
var download = await _downloads.GetById(downloadId); var download = await downloads.GetById(downloadId);
if (download == null) if (download == null)
{ {
@ -168,23 +154,23 @@ public class TorrentRunner
{ {
Log($"Retrying download", download, download.Torrent); Log($"Retrying download", download, download.Torrent);
await _downloads.Reset(downloadId); await downloads.Reset(downloadId);
await _downloads.UpdateRetryCount(downloadId, download.RetryCount + 1); await downloads.UpdateRetryCount(downloadId, download.RetryCount + 1);
} }
else else
{ {
Log($"Not retrying download", download, download.Torrent); Log($"Not retrying download", download, download.Torrent);
await _downloads.UpdateError(downloadId, downloadClient.Error); await downloads.UpdateError(downloadId, downloadClient.Error);
await _downloads.UpdateCompleted(downloadId, DateTimeOffset.UtcNow); await downloads.UpdateCompleted(downloadId, DateTimeOffset.UtcNow);
} }
} }
else else
{ {
Log($"Download finished successfully", download, download.Torrent); Log($"Download finished successfully", download, download.Torrent);
await _downloads.UpdateDownloadFinished(downloadId, DateTimeOffset.UtcNow); await downloads.UpdateDownloadFinished(downloadId, DateTimeOffset.UtcNow);
await _downloads.UpdateUnpackingQueued(downloadId, DateTimeOffset.UtcNow); await downloads.UpdateUnpackingQueued(downloadId, DateTimeOffset.UtcNow);
} }
ActiveDownloadClients.TryRemove(downloadId, out _); ActiveDownloadClients.TryRemove(downloadId, out _);
@ -202,7 +188,7 @@ public class TorrentRunner
foreach (var (downloadId, unpackClient) in completedUnpacks) foreach (var (downloadId, unpackClient) in completedUnpacks)
{ {
var download = await _downloads.GetById(downloadId); var download = await downloads.GetById(downloadId);
if (download == null) if (download == null)
{ {
@ -217,15 +203,15 @@ public class TorrentRunner
{ {
Log($"Unpack reported an error: {unpackClient.Error}", download, download.Torrent); Log($"Unpack reported an error: {unpackClient.Error}", download, download.Torrent);
await _downloads.UpdateError(downloadId, unpackClient.Error); await downloads.UpdateError(downloadId, unpackClient.Error);
await _downloads.UpdateCompleted(downloadId, DateTimeOffset.UtcNow); await downloads.UpdateCompleted(downloadId, DateTimeOffset.UtcNow);
} }
else else
{ {
Log($"Unpack finished successfully", download, download.Torrent); Log($"Unpack finished successfully", download, download.Torrent);
await _downloads.UpdateUnpackingFinished(downloadId, DateTimeOffset.UtcNow); await downloads.UpdateUnpackingFinished(downloadId, DateTimeOffset.UtcNow);
await _downloads.UpdateCompleted(downloadId, DateTimeOffset.UtcNow); await downloads.UpdateCompleted(downloadId, DateTimeOffset.UtcNow);
} }
ActiveUnpackClients.TryRemove(downloadId, out _); ActiveUnpackClients.TryRemove(downloadId, out _);
@ -234,12 +220,12 @@ public class TorrentRunner
} }
} }
var torrents = await _torrents.Get(); var torrents1 = await torrents.Get();
// Check for deleted torrents that are stuck in the ActiveDownloads or ActiveUnpacks // Check for deleted torrents that are stuck in the ActiveDownloads or ActiveUnpacks
foreach (var activeDownload in ActiveDownloadClients) foreach (var activeDownload in ActiveDownloadClients)
{ {
var download = torrents.SelectMany(m => m.Downloads).FirstOrDefault(m => m.DownloadId == activeDownload.Key); var download = torrents1.SelectMany(m => m.Downloads).FirstOrDefault(m => m.DownloadId == activeDownload.Key);
if (download == null) if (download == null)
{ {
@ -251,7 +237,7 @@ public class TorrentRunner
foreach (var activeUnpacks in ActiveUnpackClients) foreach (var activeUnpacks in ActiveUnpackClients)
{ {
var download = torrents.SelectMany(m => m.Downloads).FirstOrDefault(m => m.DownloadId == activeUnpacks.Key); var download = torrents1.SelectMany(m => m.Downloads).FirstOrDefault(m => m.DownloadId == activeUnpacks.Key);
if (download == null) if (download == null)
{ {
@ -262,7 +248,7 @@ public class TorrentRunner
} }
// Process torrent retries // Process torrent retries
foreach (var torrent in torrents.Where(m => m.Retry != null)) foreach (var torrent in torrents1.Where(m => m.Retry != null))
{ {
try try
{ {
@ -270,22 +256,22 @@ public class TorrentRunner
if (torrent.RetryCount > torrent.TorrentRetryAttempts) if (torrent.RetryCount > torrent.TorrentRetryAttempts)
{ {
await _torrents.UpdateRetry(torrent.TorrentId, null, torrent.RetryCount); await torrents.UpdateRetry(torrent.TorrentId, null, torrent.RetryCount);
Log($"Torrent reach max retry count"); Log($"Torrent reach max retry count");
continue; continue;
} }
await _torrents.RetryTorrent(torrent.TorrentId, torrent.RetryCount); await torrents.RetryTorrent(torrent.TorrentId, torrent.RetryCount);
} }
catch (Exception ex) catch (Exception ex)
{ {
await _torrents.UpdateRetry(torrent.TorrentId, null, torrent.RetryCount); await torrents.UpdateRetry(torrent.TorrentId, null, torrent.RetryCount);
await _torrents.UpdateError(torrent.TorrentId, ex.Message); await torrents.UpdateError(torrent.TorrentId, ex.Message);
} }
} }
// Process torrent errors // Process torrent errors
foreach (var torrent in torrents.Where(m => m.Error != null && m.DeleteOnError > 0)) foreach (var torrent in torrents1.Where(m => m.Error != null && m.DeleteOnError > 0))
{ {
if (torrent.Completed == null) if (torrent.Completed == null)
{ {
@ -299,11 +285,11 @@ public class TorrentRunner
Log($"Removing torrent because it has been {torrent.DeleteOnError} minutes in the error state", torrent); Log($"Removing torrent because it has been {torrent.DeleteOnError} minutes in the error state", torrent);
await _torrents.Delete(torrent.TorrentId, true, true, true); await torrents.Delete(torrent.TorrentId, true, true, true);
} }
// Process torrent lifetime // Process torrent lifetime
foreach (var torrent in torrents.Where(m => m.Downloads.Count == 0 && m.Completed == null && m.Lifetime > 0)) foreach (var torrent in torrents1.Where(m => m.Downloads.Count == 0 && m.Completed == null && m.Lifetime > 0))
{ {
if (torrent.Added.AddMinutes(torrent.Lifetime) > DateTime.UtcNow) if (torrent.Added.AddMinutes(torrent.Lifetime) > DateTime.UtcNow)
{ {
@ -312,20 +298,20 @@ public class TorrentRunner
Log($"Torrent has reached its {torrent.Lifetime} minutes lifetime, marking as error", torrent); Log($"Torrent has reached its {torrent.Lifetime} minutes lifetime, marking as error", torrent);
await _torrents.UpdateRetry(torrent.TorrentId, null, torrent.TorrentRetryAttempts); await torrents.UpdateRetry(torrent.TorrentId, null, torrent.TorrentRetryAttempts);
await _torrents.UpdateComplete(torrent.TorrentId, $"Torrent lifetime of {torrent.Lifetime} minutes reached", DateTimeOffset.UtcNow, false); await torrents.UpdateComplete(torrent.TorrentId, $"Torrent lifetime of {torrent.Lifetime} minutes reached", DateTimeOffset.UtcNow, false);
} }
torrents = await _torrents.Get(); torrents1 = await torrents.Get();
torrents = torrents.Where(m => m.Completed == null).ToList(); torrents1 = torrents1.Where(m => m.Completed == null).ToList();
if (torrents.Count > 0) if (torrents1.Count > 0)
{ {
Log($"Processing {torrents.Count} torrents"); Log($"Processing {torrents1.Count} torrents");
} }
foreach (var torrent in torrents) foreach (var torrent in torrents1)
{ {
try try
{ {
@ -359,15 +345,15 @@ public class TorrentRunner
{ {
Log($"Unrestricting links", download, torrent); Log($"Unrestricting links", download, torrent);
var downloadLink = await _torrents.UnrestrictLink(download.DownloadId); var downloadLink = await torrents.UnrestrictLink(download.DownloadId);
download.Link = downloadLink; download.Link = downloadLink;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Cannot unrestrict link: {ex.Message}", ex.Message); logger.LogError(ex, "Cannot unrestrict link: {ex.Message}", ex.Message);
await _downloads.UpdateError(download.DownloadId, ex.Message); await downloads.UpdateError(download.DownloadId, ex.Message);
await _downloads.UpdateCompleted(download.DownloadId, DateTimeOffset.UtcNow); await downloads.UpdateCompleted(download.DownloadId, DateTimeOffset.UtcNow);
download.Error = ex.Message; download.Error = ex.Message;
download.Completed = DateTimeOffset.UtcNow; download.Completed = DateTimeOffset.UtcNow;
@ -399,12 +385,12 @@ public class TorrentRunner
Log($"Received ID {remoteId}", download, torrent); Log($"Received ID {remoteId}", download, torrent);
download.RemoteId = remoteId; download.RemoteId = remoteId;
await _downloads.UpdateRemoteId(download.DownloadId, remoteId); await downloads.UpdateRemoteId(download.DownloadId, remoteId);
Log($"Marking download as started", download, torrent); Log($"Marking download as started", download, torrent);
download.DownloadStarted = DateTime.UtcNow; download.DownloadStarted = DateTime.UtcNow;
await _downloads.UpdateDownloadStarted(download.DownloadId, download.DownloadStarted); await downloads.UpdateDownloadStarted(download.DownloadId, download.DownloadStarted);
ActiveDownloadClients.TryAdd(download.DownloadId, downloadClient); ActiveDownloadClients.TryAdd(download.DownloadId, downloadClient);
} }
@ -423,8 +409,8 @@ public class TorrentRunner
{ {
Log($"No download link found", download, torrent); Log($"No download link found", download, torrent);
await _downloads.UpdateError(download.DownloadId, "Download Link cannot be null"); await downloads.UpdateError(download.DownloadId, "Download Link cannot be null");
await _downloads.UpdateCompleted(download.DownloadId, DateTimeOffset.UtcNow); await downloads.UpdateCompleted(download.DownloadId, DateTimeOffset.UtcNow);
continue; continue;
} }
@ -447,9 +433,9 @@ public class TorrentRunner
download.UnpackingFinished = DateTimeOffset.UtcNow; download.UnpackingFinished = DateTimeOffset.UtcNow;
download.Completed = DateTimeOffset.UtcNow; download.Completed = DateTimeOffset.UtcNow;
await _downloads.UpdateUnpackingStarted(download.DownloadId, download.UnpackingStarted); await downloads.UpdateUnpackingStarted(download.DownloadId, download.UnpackingStarted);
await _downloads.UpdateUnpackingFinished(download.DownloadId, download.UnpackingFinished); await downloads.UpdateUnpackingFinished(download.DownloadId, download.UnpackingFinished);
await _downloads.UpdateCompleted(download.DownloadId, download.Completed); await downloads.UpdateCompleted(download.DownloadId, download.Completed);
continue; continue;
} }
@ -470,7 +456,7 @@ public class TorrentRunner
} }
download.UnpackingStarted = DateTimeOffset.UtcNow; download.UnpackingStarted = DateTimeOffset.UtcNow;
await _downloads.UpdateUnpackingStarted(download.DownloadId, download.UnpackingStarted); await downloads.UpdateUnpackingStarted(download.DownloadId, download.UnpackingStarted);
var downloadPath = settingDownloadPath; var downloadPath = settingDownloadPath;
@ -502,7 +488,7 @@ public class TorrentRunner
Log($"Received RealDebrid error: {torrent.RdStatusRaw}, not processing further", torrent); Log($"Received RealDebrid error: {torrent.RdStatusRaw}, not processing further", torrent);
await _torrents.UpdateComplete(torrent.TorrentId, $"Received RealDebrid error: {torrent.RdStatusRaw}.", DateTimeOffset.UtcNow, true); await torrents.UpdateComplete(torrent.TorrentId, $"Received RealDebrid error: {torrent.RdStatusRaw}.", DateTimeOffset.UtcNow, true);
continue; continue;
} }
@ -514,9 +500,9 @@ public class TorrentRunner
{ {
Log($"Selecting files", torrent); Log($"Selecting files", torrent);
await _torrents.SelectFiles(torrent.TorrentId); await torrents.SelectFiles(torrent.TorrentId);
await _torrents.UpdateFilesSelected(torrent.TorrentId, DateTime.UtcNow); await torrents.UpdateFilesSelected(torrent.TorrentId, DateTime.UtcNow);
} }
// Debrid provider finished downloading the torrent, process the file to host. // Debrid provider finished downloading the torrent, process the file to host.
@ -529,7 +515,7 @@ public class TorrentRunner
if (torrent.HostDownloadAction == TorrentHostDownloadAction.DownloadAll) if (torrent.HostDownloadAction == TorrentHostDownloadAction.DownloadAll)
{ {
await _torrents.CreateDownloads(torrent.TorrentId); await torrents.CreateDownloads(torrent.TorrentId);
} }
} }
} }
@ -554,15 +540,15 @@ public class TorrentRunner
{ {
Log($"All downloads complete, marking torrent as complete", torrent); Log($"All downloads complete, marking torrent as complete", torrent);
await _torrents.UpdateComplete(torrent.TorrentId, null, DateTimeOffset.UtcNow, true); await torrents.UpdateComplete(torrent.TorrentId, null, DateTimeOffset.UtcNow, true);
try try
{ {
await _torrents.RunTorrentComplete(torrent.TorrentId); await torrents.RunTorrentComplete(torrent.TorrentId);
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message, "Unable to run post process: {Message}", ex.Message); logger.LogError(ex.Message, "Unable to run post process: {Message}", ex.Message);
} }
if (torrent.DownloadClient == Data.Enums.DownloadClient.Symlink) if (torrent.DownloadClient == Data.Enums.DownloadClient.Symlink)
@ -586,17 +572,17 @@ public class TorrentRunner
{ {
case TorrentFinishedAction.RemoveAllTorrents: case TorrentFinishedAction.RemoveAllTorrents:
Log($"Removing torrents from debrid provider and RDT-Client, no files", torrent); Log($"Removing torrents from debrid provider and RDT-Client, no files", torrent);
await _torrents.Delete(torrent.TorrentId, true, true, false); await torrents.Delete(torrent.TorrentId, true, true, false);
break; break;
case TorrentFinishedAction.RemoveRealDebrid: case TorrentFinishedAction.RemoveRealDebrid:
Log($"Removing torrents from debrid provider, no files", torrent); Log($"Removing torrents from debrid provider, no files", torrent);
await _torrents.Delete(torrent.TorrentId, false, true, false); await torrents.Delete(torrent.TorrentId, false, true, false);
break; break;
case TorrentFinishedAction.RemoveClient: case TorrentFinishedAction.RemoveClient:
Log($"Removing torrents from client, no files", torrent); Log($"Removing torrents from client, no files", torrent);
await _torrents.Delete(torrent.TorrentId, true, false, false); await torrents.Delete(torrent.TorrentId, true, false, false);
break; break;
case TorrentFinishedAction.None: case TorrentFinishedAction.None:
@ -617,12 +603,12 @@ public class TorrentRunner
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message, "Torrent processing result in an unexpected exception: {Message}", ex.Message); logger.LogError(ex.Message, "Torrent processing result in an unexpected exception: {Message}", ex.Message);
await _torrents.UpdateComplete(torrent.TorrentId, ex.Message, DateTimeOffset.UtcNow, true); await torrents.UpdateComplete(torrent.TorrentId, ex.Message, DateTimeOffset.UtcNow, true);
} }
} }
await _remoteService.Update(); await remoteService.Update();
sw.Stop(); sw.Stop();
@ -644,7 +630,7 @@ public class TorrentRunner
message = $"{message} {torrent.ToLog()}"; message = $"{message} {torrent.ToLog()}";
} }
_logger.LogDebug(message); logger.LogDebug(message);
} }
private void Log(String message, Torrent? torrent = null) private void Log(String message, Torrent? torrent = null)
@ -654,7 +640,7 @@ public class TorrentRunner
message = $"{message} {torrent.ToLog()}"; message = $"{message} {torrent.ToLog()}";
} }
_logger.LogDebug(message); logger.LogDebug(message);
} }
private void LogError(String message, Download? download, Torrent? torrent) private void LogError(String message, Download? download, Torrent? torrent)
@ -669,6 +655,6 @@ public class TorrentRunner
message = $"{message} {torrent.ToLog()}"; message = $"{message} {torrent.ToLog()}";
} }
_logger.LogError(message); logger.LogError(message);
} }
} }

View file

@ -16,27 +16,25 @@ using Torrent = RdtClient.Data.Models.Data.Torrent;
namespace RdtClient.Service.Services; namespace RdtClient.Service.Services;
public class Torrents public class Torrents(
ILogger<Torrents> logger,
TorrentData torrentData,
Downloads downloads,
AllDebridTorrentClient allDebridTorrentClient,
PremiumizeTorrentClient premiumizeTorrentClient,
RealDebridTorrentClient realDebridTorrentClient)
{ {
private static readonly SemaphoreSlim RealDebridUpdateLock = new(1, 1); private static readonly SemaphoreSlim RealDebridUpdateLock = new(1, 1);
private readonly ILogger<Torrents> _logger;
private readonly TorrentData _torrentData;
private readonly Downloads _downloads;
private readonly AllDebridTorrentClient _allDebridTorrentClient;
private readonly PremiumizeTorrentClient _premiumizeTorrentClient;
private readonly RealDebridTorrentClient _realDebridTorrentClient;
private ITorrentClient TorrentClient private ITorrentClient TorrentClient
{ {
get get
{ {
return Settings.Get.Provider.Provider switch return Settings.Get.Provider.Provider switch
{ {
Provider.Premiumize => _premiumizeTorrentClient, Provider.Premiumize => premiumizeTorrentClient,
Provider.RealDebrid => _realDebridTorrentClient, Provider.RealDebrid => realDebridTorrentClient,
Provider.AllDebrid => _allDebridTorrentClient, Provider.AllDebrid => allDebridTorrentClient,
_ => throw new Exception("Invalid Provider") _ => throw new Exception("Invalid Provider")
}; };
} }
@ -44,24 +42,9 @@ public class Torrents
private static readonly SemaphoreSlim TorrentResetLock = new(1, 1); private static readonly SemaphoreSlim TorrentResetLock = new(1, 1);
public Torrents(ILogger<Torrents> logger,
TorrentData torrentData,
Downloads downloads,
AllDebridTorrentClient allDebridTorrentClient,
PremiumizeTorrentClient premiumizeTorrentClient,
RealDebridTorrentClient realDebridTorrentClient)
{
_logger = logger;
_torrentData = torrentData;
_downloads = downloads;
_allDebridTorrentClient = allDebridTorrentClient;
_premiumizeTorrentClient = premiumizeTorrentClient;
_realDebridTorrentClient = realDebridTorrentClient;
}
public async Task<IList<Torrent>> Get() public async Task<IList<Torrent>> Get()
{ {
var torrents = await _torrentData.Get(); var torrents = await torrentData.Get();
foreach (var torrent in torrents) foreach (var torrent in torrents)
{ {
@ -87,7 +70,7 @@ public class Torrents
public async Task<Torrent?> GetByHash(String hash) public async Task<Torrent?> GetByHash(String hash)
{ {
var torrent = await _torrentData.GetByHash(hash); var torrent = await torrentData.GetByHash(hash);
if (torrent != null) if (torrent != null)
{ {
@ -99,7 +82,7 @@ public class Torrents
public async Task UpdateCategory(String hash, String? category) public async Task UpdateCategory(String hash, String? category)
{ {
var torrent = await _torrentData.GetByHash(hash); var torrent = await torrentData.GetByHash(hash);
if (torrent == null) if (torrent == null)
{ {
@ -108,7 +91,7 @@ public class Torrents
Log($"Update category to {category}", torrent); Log($"Update category to {category}", torrent);
await _torrentData.UpdateCategory(torrent.TorrentId, category); await torrentData.UpdateCategory(torrent.TorrentId, category);
} }
public async Task<Torrent> UploadMagnet(String magnetLink, Torrent torrent) public async Task<Torrent> UploadMagnet(String magnetLink, Torrent torrent)
@ -121,7 +104,7 @@ public class Torrents
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "{ex.Message}, trying to parse {magnetLink}", ex.Message, magnetLink); logger.LogError(ex, "{ex.Message}, trying to parse {magnetLink}", ex.Message, magnetLink);
throw new Exception($"{ex.Message}, trying to parse {magnetLink}"); throw new Exception($"{ex.Message}, trying to parse {magnetLink}");
} }
@ -153,7 +136,7 @@ public class Torrents
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, $"Unable to create torrent blackhole directory: {Settings.Get.General.CopyAddedTorrents}: {ex.Message}"); logger.LogError(ex, $"Unable to create torrent blackhole directory: {Settings.Get.General.CopyAddedTorrents}: {ex.Message}");
} }
} }
@ -165,7 +148,7 @@ public class Torrents
MonoTorrent.Torrent monoTorrent; MonoTorrent.Torrent monoTorrent;
var fileAsBase64 = Convert.ToBase64String(bytes); var fileAsBase64 = Convert.ToBase64String(bytes);
_logger.LogDebug($"bytes {bytes}"); logger.LogDebug($"bytes {bytes}");
try try
{ {
@ -204,7 +187,7 @@ public class Torrents
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, $"Unable to create torrent blackhole directory: {Settings.Get.General.CopyAddedTorrents}: {ex.Message}"); logger.LogError(ex, $"Unable to create torrent blackhole directory: {Settings.Get.General.CopyAddedTorrents}: {ex.Message}");
} }
} }
@ -249,11 +232,11 @@ public class Torrents
foreach (var downloadLink in downloadLinks) foreach (var downloadLink in downloadLinks)
{ {
// Make sure downloads don't get added multiple times // Make sure downloads don't get added multiple times
var downloadExists = await _downloads.Get(torrent.TorrentId, downloadLink); var downloadExists = await downloads.Get(torrent.TorrentId, downloadLink);
if (downloadExists == null && !String.IsNullOrWhiteSpace(downloadLink)) if (downloadExists == null && !String.IsNullOrWhiteSpace(downloadLink))
{ {
await _downloads.Add(torrent.TorrentId, downloadLink); await downloads.Add(torrent.TorrentId, downloadLink);
} }
} }
} }
@ -314,8 +297,8 @@ public class Torrents
{ {
Log($"Deleting RdtClient data", torrent); Log($"Deleting RdtClient data", torrent);
await _downloads.DeleteForTorrent(torrent.TorrentId); await downloads.DeleteForTorrent(torrent.TorrentId);
await _torrentData.Delete(torrentId); await torrentData.Delete(torrentId);
} }
if (deleteRdTorrent && torrent.RdId != null) if (deleteRdTorrent && torrent.RdId != null)
@ -369,7 +352,7 @@ public class Torrents
public async Task<String> UnrestrictLink(Guid downloadId) public async Task<String> UnrestrictLink(Guid downloadId)
{ {
var download = await _downloads.GetById(downloadId); var download = await downloads.GetById(downloadId);
if (download == null) if (download == null)
{ {
@ -380,7 +363,7 @@ public class Torrents
var unrestrictedLink = await TorrentClient.Unrestrict(download.Path); var unrestrictedLink = await TorrentClient.Unrestrict(download.Path);
await _downloads.UpdateUnrestrictedLink(downloadId, unrestrictedLink); await downloads.UpdateUnrestrictedLink(downloadId, unrestrictedLink);
return unrestrictedLink; return unrestrictedLink;
} }
@ -440,7 +423,7 @@ public class Torrents
continue; continue;
} }
torrent = await _torrentData.Add(rdTorrent.Id, rdTorrent.Hash, null, false, Settings.Get.DownloadClient.Client, newTorrent); torrent = await torrentData.Add(rdTorrent.Id, rdTorrent.Hash, null, false, Settings.Get.DownloadClient.Client, newTorrent);
await UpdateTorrentClientData(torrent, rdTorrent); await UpdateTorrentClientData(torrent, rdTorrent);
} }
@ -472,7 +455,7 @@ public class Torrents
try try
{ {
var torrent = await _torrentData.GetById(torrentId); var torrent = await torrentData.GetById(torrentId);
if (torrent?.Retry == null) if (torrent?.Retry == null)
{ {
@ -486,8 +469,8 @@ public class Torrents
foreach (var download in torrent.Downloads) foreach (var download in torrent.Downloads)
{ {
await _downloads.UpdateError(download.DownloadId, null); await downloads.UpdateError(download.DownloadId, null);
await _downloads.UpdateCompleted(download.DownloadId, DateTimeOffset.UtcNow); await downloads.UpdateCompleted(download.DownloadId, DateTimeOffset.UtcNow);
} }
foreach (var download in torrent.Downloads) foreach (var download in torrent.Downloads)
@ -527,7 +510,7 @@ public class Torrents
newTorrent = await UploadMagnet(torrent.FileOrMagnet, torrent); newTorrent = await UploadMagnet(torrent.FileOrMagnet, torrent);
} }
await _torrentData.UpdateRetry(newTorrent.TorrentId, null, retryCount); await torrentData.UpdateRetry(newTorrent.TorrentId, null, retryCount);
} }
finally finally
{ {
@ -537,7 +520,7 @@ public class Torrents
public async Task RetryDownload(Guid downloadId) public async Task RetryDownload(Guid downloadId)
{ {
var download = await _downloads.GetById(downloadId); var download = await downloads.GetById(downloadId);
if (download == null) if (download == null)
{ {
@ -573,46 +556,46 @@ public class Torrents
Log($"Resetting", download, download.Torrent); Log($"Resetting", download, download.Torrent);
await _downloads.Reset(downloadId); await downloads.Reset(downloadId);
await _torrentData.UpdateComplete(download.TorrentId, null, null, false); 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); await torrentData.UpdateComplete(torrentId, error, datetime, retry);
} }
public async Task UpdateFilesSelected(Guid torrentId, DateTimeOffset datetime) public async Task UpdateFilesSelected(Guid torrentId, DateTimeOffset datetime)
{ {
await _torrentData.UpdateFilesSelected(torrentId, datetime); await torrentData.UpdateFilesSelected(torrentId, datetime);
} }
public async Task UpdatePriority(String hash, Int32 priority) public async Task UpdatePriority(String hash, Int32 priority)
{ {
var torrent = await _torrentData.GetByHash(hash); var torrent = await torrentData.GetByHash(hash);
if (torrent == null) if (torrent == null)
{ {
return; return;
} }
await _torrentData.UpdatePriority(torrent.TorrentId, priority); await torrentData.UpdatePriority(torrent.TorrentId, priority);
} }
public async Task UpdateRetry(Guid torrentId, DateTimeOffset? datetime, Int32 retry) public async Task UpdateRetry(Guid torrentId, DateTimeOffset? datetime, Int32 retry)
{ {
await _torrentData.UpdateRetry(torrentId, datetime, retry); await torrentData.UpdateRetry(torrentId, datetime, retry);
} }
public async Task UpdateError(Guid torrentId, String error) public async Task UpdateError(Guid torrentId, String error)
{ {
await _torrentData.UpdateError(torrentId, error); 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); var torrent = await torrentData.GetById(torrentId);
if (torrent == null) if (torrent == null)
{ {
@ -662,14 +645,14 @@ public class Torrents
try try
{ {
var existingTorrent = await _torrentData.GetByHash(infoHash); var existingTorrent = await torrentData.GetByHash(infoHash);
if (existingTorrent != null) if (existingTorrent != null)
{ {
return existingTorrent; return existingTorrent;
} }
var newTorrent = await _torrentData.Add(rdTorrentId, var newTorrent = await torrentData.Add(rdTorrentId,
infoHash, infoHash,
fileOrMagnetContents, fileOrMagnetContents,
isFile, isFile,
@ -688,7 +671,7 @@ public class Torrents
public async Task Update(Torrent torrent) public async Task Update(Torrent torrent)
{ {
await _torrentData.Update(torrent); await torrentData.Update(torrent);
} }
public async Task RunTorrentComplete(Guid torrentId) public async Task RunTorrentComplete(Guid torrentId)
@ -698,14 +681,14 @@ public class Torrents
return; return;
} }
var torrent = await _torrentData.GetById(torrentId); var torrent = await torrentData.GetById(torrentId);
if (torrent == null) if (torrent == null)
{ {
throw new Exception($"Cannot find Torrent with ID {torrentId}"); throw new Exception($"Cannot find Torrent with ID {torrentId}");
} }
var downloads = await _downloads.GetForTorrent(torrentId); var downloads1 = await downloads.GetForTorrent(torrentId);
var fileName = Settings.Get.General.RunOnTorrentCompleteFileName; var fileName = Settings.Get.General.RunOnTorrentCompleteFileName;
var arguments = Settings.Get.General.RunOnTorrentCompleteArguments ?? ""; var arguments = Settings.Get.General.RunOnTorrentCompleteArguments ?? "";
@ -729,7 +712,7 @@ public class Torrents
arguments = arguments.Replace("%F", $"\"{filePath}\""); arguments = arguments.Replace("%F", $"\"{filePath}\"");
arguments = arguments.Replace("%R", $"\"{downloadPath}\""); arguments = arguments.Replace("%R", $"\"{downloadPath}\"");
arguments = arguments.Replace("%D", $"\"{torrentPath}\""); arguments = arguments.Replace("%D", $"\"{torrentPath}\"");
arguments = arguments.Replace("%C", downloads.Count.ToString(CultureInfo.InvariantCulture).Replace(",", "").Replace(".", "")); arguments = arguments.Replace("%C", downloads1.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); arguments = arguments.Replace("%I", torrent.Hash);
@ -811,7 +794,7 @@ public class Torrents
if (originalTorrent != newTorrent) if (originalTorrent != newTorrent)
{ {
await _torrentData.UpdateRdData(torrent); await torrentData.UpdateRdData(torrent);
} }
} }
catch catch
@ -832,7 +815,7 @@ public class Torrents
message = $"{message} {torrent.ToLog()}"; message = $"{message} {torrent.ToLog()}";
} }
_logger.LogDebug(message); logger.LogDebug(message);
} }
private void Log(String message, Torrent? torrent = null) private void Log(String message, Torrent? torrent = null)
@ -842,6 +825,6 @@ public class Torrents
message = $"{message} {torrent.ToLog()}"; message = $"{message} {torrent.ToLog()}";
} }
_logger.LogDebug(message); logger.LogDebug(message);
} }
} }

View file

@ -7,34 +7,25 @@ using SharpCompress.Archives.Zip;
namespace RdtClient.Service.Services; namespace RdtClient.Service.Services;
public class UnpackClient public class UnpackClient(Download download, String destinationPath)
{ {
public Boolean Finished { get; private set; } public Boolean Finished { get; private set; }
public String? Error { get; private set; } public String? Error { get; private set; }
public Int32 Progess { get; private set; } public Int32 Progess { get; private set; }
private readonly Download _download; private readonly Torrent _torrent = download.Torrent ?? throw new Exception($"Torrent is null");
private readonly String _destinationPath;
private readonly Torrent _torrent;
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
public UnpackClient(Download download, String destinationPath)
{
_download = download;
_destinationPath = destinationPath;
_torrent = download.Torrent ?? throw new Exception($"Torrent is null");
}
public void Start() public void Start()
{ {
Progess = 0; Progess = 0;
try try
{ {
var filePath = DownloadHelper.GetDownloadPath(_destinationPath, _torrent, _download); var filePath = DownloadHelper.GetDownloadPath(destinationPath, _torrent, download);
if (filePath == null) if (filePath == null)
{ {
@ -51,7 +42,7 @@ public class UnpackClient
} }
catch (Exception ex) catch (Exception ex)
{ {
Error = $"An unexpected error occurred preparing download {_download.Link} for torrent {_torrent.RdName}: {ex.Message}"; Error = $"An unexpected error occurred preparing download {download.Link} for torrent {_torrent.RdName}: {ex.Message}";
Finished = true; Finished = true;
} }
} }
@ -70,14 +61,14 @@ public class UnpackClient
return; return;
} }
var extractPath = _destinationPath; var extractPath = destinationPath;
String? extractPathTemp = null; String? extractPathTemp = null;
var archiveEntries = await GetArchiveFiles(filePath); var archiveEntries = await GetArchiveFiles(filePath);
if (!archiveEntries.Any(m => m.StartsWith(_torrent.RdName + @"\")) && !archiveEntries.Any(m => m.StartsWith(_torrent.RdName + "/"))) if (!archiveEntries.Any(m => m.StartsWith(_torrent.RdName + @"\")) && !archiveEntries.Any(m => m.StartsWith(_torrent.RdName + "/")))
{ {
extractPath = Path.Combine(_destinationPath, _torrent.RdName!); extractPath = Path.Combine(destinationPath, _torrent.RdName!);
} }
if (archiveEntries.Any(m => m.Contains(".r00"))) if (archiveEntries.Any(m => m.Contains(".r00")))
@ -119,7 +110,7 @@ public class UnpackClient
} }
catch (Exception ex) catch (Exception ex)
{ {
Error = $"An unexpected error occurred unpacking {_download.Link} for torrent {_torrent.RdName}: {ex.Message}"; Error = $"An unexpected error occurred unpacking {download.Link} for torrent {_torrent.RdName}: {ex.Message}";
} }
finally finally
{ {

View file

@ -12,30 +12,21 @@ namespace RdtClient.Web.Controllers;
/// </summary> /// </summary>
[ApiController] [ApiController]
[Route("api/v2")] [Route("api/v2")]
public class QBittorrentController : Controller public class QBittorrentController(ILogger<QBittorrentController> logger, QBittorrent qBittorrent) : Controller
{ {
private readonly ILogger<QBittorrentController> _logger;
private readonly QBittorrent _qBittorrent;
public QBittorrentController(ILogger<QBittorrentController> logger, QBittorrent qBittorrent)
{
_logger = logger;
_qBittorrent = qBittorrent;
}
[AllowAnonymous] [AllowAnonymous]
[Route("auth/login")] [Route("auth/login")]
[HttpGet] [HttpGet]
public async Task<ActionResult> AuthLogin([FromQuery] QBAuthLoginRequest request) public async Task<ActionResult> AuthLogin([FromQuery] QBAuthLoginRequest request)
{ {
_logger.LogDebug($"Auth login"); logger.LogDebug($"Auth login");
if (String.IsNullOrWhiteSpace(request.UserName) || String.IsNullOrEmpty(request.Password)) if (String.IsNullOrWhiteSpace(request.UserName) || String.IsNullOrEmpty(request.Password))
{ {
return Ok("Fails."); return Ok("Fails.");
} }
var result = await _qBittorrent.AuthLogin(request.UserName, request.Password); var result = await qBittorrent.AuthLogin(request.UserName, request.Password);
if (result) if (result)
{ {
@ -59,9 +50,9 @@ public class QBittorrentController : Controller
[HttpPost] [HttpPost]
public async Task<ActionResult> AuthLogout() public async Task<ActionResult> AuthLogout()
{ {
_logger.LogDebug($"Auth logout"); logger.LogDebug($"Auth logout");
await _qBittorrent.AuthLogout(); await qBittorrent.AuthLogout();
return Ok(); return Ok();
} }
@ -113,7 +104,7 @@ public class QBittorrentController : Controller
[HttpPost] [HttpPost]
public async Task<ActionResult<AppPreferences>> AppPreferences() public async Task<ActionResult<AppPreferences>> AppPreferences()
{ {
var result = await _qBittorrent.AppPreferences(); var result = await qBittorrent.AppPreferences();
return Ok(result); return Ok(result);
} }
@ -142,7 +133,7 @@ public class QBittorrentController : Controller
[HttpPost] [HttpPost]
public async Task<ActionResult<IList<TorrentInfo>>> TorrentsInfo([FromQuery] QBTorrentsInfoRequest request) public async Task<ActionResult<IList<TorrentInfo>>> TorrentsInfo([FromQuery] QBTorrentsInfoRequest request)
{ {
var results = await _qBittorrent.TorrentInfo(); var results = await qBittorrent.TorrentInfo();
if (!String.IsNullOrWhiteSpace(request.Category)) if (!String.IsNullOrWhiteSpace(request.Category))
{ {
@ -170,7 +161,7 @@ public class QBittorrentController : Controller
return BadRequest(); return BadRequest();
} }
var result = await _qBittorrent.TorrentFileContents(request.Hash); var result = await qBittorrent.TorrentFileContents(request.Hash);
if (result == null) if (result == null)
{ {
@ -198,7 +189,7 @@ public class QBittorrentController : Controller
return BadRequest(); return BadRequest();
} }
var result = await _qBittorrent.TorrentProperties(request.Hash); var result = await qBittorrent.TorrentProperties(request.Hash);
if (result == null) if (result == null)
{ {
@ -230,7 +221,7 @@ public class QBittorrentController : Controller
foreach (var hash in hashes) foreach (var hash in hashes)
{ {
await _qBittorrent.TorrentPause(hash); await qBittorrent.TorrentPause(hash);
} }
return Ok(); return Ok();
@ -258,7 +249,7 @@ public class QBittorrentController : Controller
foreach (var hash in hashes) foreach (var hash in hashes)
{ {
await _qBittorrent.TorrentResume(hash); await qBittorrent.TorrentResume(hash);
} }
return Ok(); return Ok();
@ -291,13 +282,13 @@ public class QBittorrentController : Controller
return BadRequest(); return BadRequest();
} }
_logger.LogDebug($"Delete {request.Hashes}"); logger.LogDebug($"Delete {request.Hashes}");
var hashes = request.Hashes.Split("|"); var hashes = request.Hashes.Split("|");
foreach (var hash in hashes) foreach (var hash in hashes)
{ {
await _qBittorrent.TorrentsDelete(hash, request.DeleteFiles); await qBittorrent.TorrentsDelete(hash, request.DeleteFiles);
} }
return Ok(); return Ok();
@ -327,13 +318,13 @@ public class QBittorrentController : Controller
{ {
if (url.StartsWith("magnet")) if (url.StartsWith("magnet"))
{ {
await _qBittorrent.TorrentsAddMagnet(url.Trim(), request.Category, null); await qBittorrent.TorrentsAddMagnet(url.Trim(), request.Category, null);
} }
else if (url.StartsWith("http")) else if (url.StartsWith("http"))
{ {
var httpClient = new HttpClient(); var httpClient = new HttpClient();
var result = await httpClient.GetByteArrayAsync(url); var result = await httpClient.GetByteArrayAsync(url);
await _qBittorrent.TorrentsAddFile(result, request.Category, null); await qBittorrent.TorrentsAddFile(result, request.Category, null);
} }
else else
{ {
@ -358,7 +349,7 @@ public class QBittorrentController : Controller
await file.CopyToAsync(target); await file.CopyToAsync(target);
var fileBytes = target.ToArray(); var fileBytes = target.ToArray();
await _qBittorrent.TorrentsAddFile(fileBytes, request.Category, request.Priority); await qBittorrent.TorrentsAddFile(fileBytes, request.Category, request.Priority);
} }
} }
@ -384,7 +375,7 @@ public class QBittorrentController : Controller
foreach (var hash in hashes) foreach (var hash in hashes)
{ {
await _qBittorrent.TorrentsSetCategory(hash, request.Category); await qBittorrent.TorrentsSetCategory(hash, request.Category);
} }
return Ok(); return Ok();
@ -404,7 +395,7 @@ public class QBittorrentController : Controller
[HttpPost] [HttpPost]
public async Task<ActionResult<IDictionary<String, TorrentCategory>>> TorrentsCategories() public async Task<ActionResult<IDictionary<String, TorrentCategory>>> TorrentsCategories()
{ {
var categories = await _qBittorrent.TorrentsCategories(); var categories = await qBittorrent.TorrentsCategories();
return Ok(categories); return Ok(categories);
} }
@ -420,7 +411,7 @@ public class QBittorrentController : Controller
return BadRequest("category name is empty"); return BadRequest("category name is empty");
} }
await _qBittorrent.CategoryCreate(request.Category.Trim()); await qBittorrent.CategoryCreate(request.Category.Trim());
return Ok(); return Ok();
} }
@ -440,7 +431,7 @@ public class QBittorrentController : Controller
foreach (var category in categories) foreach (var category in categories)
{ {
await _qBittorrent.CategoryRemove(category.Trim()); await qBittorrent.CategoryRemove(category.Trim());
} }
return Ok(); return Ok();
@ -469,7 +460,7 @@ public class QBittorrentController : Controller
foreach (var hash in hashes) foreach (var hash in hashes)
{ {
await _qBittorrent.TorrentsTopPrio(hash); await qBittorrent.TorrentsTopPrio(hash);
} }
return Ok(); return Ok();
@ -488,7 +479,7 @@ public class QBittorrentController : Controller
[HttpGet] [HttpGet]
public async Task<ActionResult> SyncMainData() public async Task<ActionResult> SyncMainData()
{ {
var result = await _qBittorrent.SyncMainData(); var result = await qBittorrent.SyncMainData();
return Ok(result); return Ok(result);
} }

View file

@ -13,17 +13,8 @@ namespace RdtClient.Web.Controllers;
[Authorize(Policy = "AuthSetting")] [Authorize(Policy = "AuthSetting")]
[Route("Api/Settings")] [Route("Api/Settings")]
public class SettingsController : Controller public class SettingsController(Settings settings, Torrents torrents) : Controller
{ {
private readonly Settings _settings;
private readonly Torrents _torrents;
public SettingsController(Settings settings, Torrents torrents)
{
_settings = settings;
_torrents = torrents;
}
[HttpGet] [HttpGet]
[Route("")] [Route("")]
public ActionResult Get() public ActionResult Get()
@ -34,14 +25,14 @@ public class SettingsController : Controller
[HttpPut] [HttpPut]
[Route("")] [Route("")]
public async Task<ActionResult> Update([FromBody] IList<SettingProperty>? settings) public async Task<ActionResult> Update([FromBody] IList<SettingProperty>? settings1)
{ {
if (settings == null) if (settings1 == null)
{ {
return BadRequest(); return BadRequest();
} }
await _settings.Update(settings); await settings.Update(settings1);
return Ok(); return Ok();
} }
@ -50,7 +41,7 @@ public class SettingsController : Controller
[Route("Profile")] [Route("Profile")]
public async Task<ActionResult<Profile>> Profile() public async Task<ActionResult<Profile>> Profile()
{ {
var profile = await _torrents.GetProfile(); var profile = await torrents.GetProfile();
return Ok(profile); return Ok(profile);
} }

View file

@ -11,24 +11,13 @@ namespace RdtClient.Web.Controllers;
[Authorize(Policy = "AuthSetting")] [Authorize(Policy = "AuthSetting")]
[Route("Api/Torrents")] [Route("Api/Torrents")]
public class TorrentsController : Controller public class TorrentsController(ILogger<TorrentsController> logger, Torrents torrents, TorrentRunner torrentRunner) : Controller
{ {
private readonly TorrentRunner _torrentRunner;
private readonly ILogger<TorrentsController> _logger;
private readonly Torrents _torrents;
public TorrentsController(ILogger<TorrentsController> logger, Torrents torrents, TorrentRunner torrentRunner)
{
_logger = logger;
_torrents = torrents;
_torrentRunner = torrentRunner;
}
[HttpGet] [HttpGet]
[Route("")] [Route("")]
public async Task<ActionResult<IList<Torrent>>> GetAll() public async Task<ActionResult<IList<Torrent>>> GetAll()
{ {
var results = await _torrents.Get(); var results = await torrents.Get();
// Prevent infinite recursion when serializing // Prevent infinite recursion when serializing
foreach (var file in results.SelectMany(torrent => torrent.Downloads)) foreach (var file in results.SelectMany(torrent => torrent.Downloads))
@ -43,7 +32,7 @@ public class TorrentsController : Controller
[Route("Get/{torrentId:guid}")] [Route("Get/{torrentId:guid}")]
public async Task<ActionResult<Torrent>> GetById(Guid torrentId) public async Task<ActionResult<Torrent>> GetById(Guid torrentId)
{ {
var torrent = await _torrents.GetById(torrentId); var torrent = await torrents.GetById(torrentId);
if (torrent?.Downloads != null) if (torrent?.Downloads != null)
{ {
@ -64,7 +53,7 @@ public class TorrentsController : Controller
[Route("Tick")] [Route("Tick")]
public async Task<ActionResult> Tick() public async Task<ActionResult> Tick()
{ {
await _torrentRunner.Tick(); await torrentRunner.Tick();
return Ok(); return Ok();
} }
@ -85,7 +74,7 @@ public class TorrentsController : Controller
return BadRequest("Invalid Torrent"); return BadRequest("Invalid Torrent");
} }
_logger.LogDebug($"Add file"); logger.LogDebug($"Add file");
var fileStream = file.OpenReadStream(); var fileStream = file.OpenReadStream();
@ -95,7 +84,7 @@ public class TorrentsController : Controller
var bytes = memoryStream.ToArray(); var bytes = memoryStream.ToArray();
await _torrents.UploadFile(bytes, formData.Torrent); await torrents.UploadFile(bytes, formData.Torrent);
return Ok(); return Ok();
} }
@ -119,9 +108,9 @@ public class TorrentsController : Controller
return BadRequest("Invalid Torrent"); return BadRequest("Invalid Torrent");
} }
_logger.LogDebug($"Add magnet"); logger.LogDebug($"Add magnet");
await _torrents.UploadMagnet(request.MagnetLink, request.Torrent); await torrents.UploadMagnet(request.MagnetLink, request.Torrent);
return Ok(); return Ok();
} }
@ -145,7 +134,7 @@ public class TorrentsController : Controller
var torrent = await MonoTorrent.Torrent.LoadAsync(bytes); var torrent = await MonoTorrent.Torrent.LoadAsync(bytes);
var result = await _torrents.GetAvailableFiles(torrent.InfoHash.ToHex()); var result = await torrents.GetAvailableFiles(torrent.InfoHash.ToHex());
return Ok(result); return Ok(result);
} }
@ -161,7 +150,7 @@ public class TorrentsController : Controller
var magnet = MagnetLink.Parse(request.MagnetLink); var magnet = MagnetLink.Parse(request.MagnetLink);
var result = await _torrents.GetAvailableFiles(magnet.InfoHash.ToHex()); var result = await torrents.GetAvailableFiles(magnet.InfoHash.ToHex());
return Ok(result); return Ok(result);
} }
@ -175,9 +164,9 @@ public class TorrentsController : Controller
return BadRequest(); return BadRequest();
} }
_logger.LogDebug($"Delete {torrentId}"); logger.LogDebug($"Delete {torrentId}");
await _torrents.Delete(torrentId, request.DeleteData, request.DeleteRdTorrent, request.DeleteLocalFiles); await torrents.Delete(torrentId, request.DeleteData, request.DeleteRdTorrent, request.DeleteLocalFiles);
return Ok(); return Ok();
} }
@ -186,10 +175,10 @@ public class TorrentsController : Controller
[Route("Retry/{torrentId:guid}")] [Route("Retry/{torrentId:guid}")]
public async Task<ActionResult> Retry(Guid torrentId) public async Task<ActionResult> Retry(Guid torrentId)
{ {
_logger.LogDebug($"Retry {torrentId}"); logger.LogDebug($"Retry {torrentId}");
await _torrents.UpdateRetry(torrentId, DateTimeOffset.UtcNow, 0); await torrents.UpdateRetry(torrentId, DateTimeOffset.UtcNow, 0);
await _torrents.RetryTorrent(torrentId, 0); await torrents.RetryTorrent(torrentId, 0);
return Ok(); return Ok();
} }
@ -198,9 +187,9 @@ public class TorrentsController : Controller
[Route("RetryDownload/{downloadId:guid}")] [Route("RetryDownload/{downloadId:guid}")]
public async Task<ActionResult> RetryDownload(Guid downloadId) public async Task<ActionResult> RetryDownload(Guid downloadId)
{ {
_logger.LogDebug($"Retry download {downloadId}"); logger.LogDebug($"Retry download {downloadId}");
await _torrents.RetryDownload(downloadId); await torrents.RetryDownload(downloadId);
return Ok(); return Ok();
} }
@ -214,7 +203,7 @@ public class TorrentsController : Controller
return BadRequest(); return BadRequest();
} }
await _torrents.Update(torrent); await torrents.Update(torrent);
return Ok(); return Ok();
} }
@ -237,7 +226,7 @@ public class TorrentsController : Controller
{ {
var magnet = MagnetLink.Parse(request.MagnetLink); var magnet = MagnetLink.Parse(request.MagnetLink);
availableFiles = await _torrents.GetAvailableFiles(magnet.InfoHash.ToHex()); availableFiles = await torrents.GetAvailableFiles(magnet.InfoHash.ToHex());
} }
else if (file != null) else if (file != null)
{ {
@ -251,7 +240,7 @@ public class TorrentsController : Controller
var torrent = await MonoTorrent.Torrent.LoadAsync(bytes); var torrent = await MonoTorrent.Torrent.LoadAsync(bytes);
availableFiles = await _torrents.GetAvailableFiles(torrent.InfoHash.ToHex()); availableFiles = await torrents.GetAvailableFiles(torrent.InfoHash.ToHex());
} }
else else
{ {

View file

@ -68,13 +68,10 @@ builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationSc
options.SlidingExpiration = true; options.SlidingExpiration = true;
}); });
builder.Services.AddAuthorization( options =>
{ builder.Services.AddAuthorizationBuilder().AddPolicy("AuthSetting", policyCorrectUser =>
options.AddPolicy("AuthSetting", {
policyCorrectUser => policyCorrectUser.Requirements.Add(new AuthSettingRequirement());
{
policyCorrectUser.Requirements.Add(new AuthSettingRequirement());
});
}); });
@ -178,12 +175,10 @@ try
app.UseAuthentication(); app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
app.UseEndpoints(endpoints => app.MapHub<RdtHub>("/hub");
{
endpoints.MapHub<RdtHub>("/hub"); app.MapControllers();
endpoints.MapControllers();
});
app.MapWhen(x => !x.Request.Path.StartsWithSegments("/api"), routeBuilder => app.MapWhen(x => !x.Request.Path.StartsWithSegments("/api"), routeBuilder =>
{ {

View file

@ -29,15 +29,15 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="8.0.1" /> <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="8.0.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.3">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.3" />
<PackageReference Include="Serilog" Version="3.1.1" /> <PackageReference Include="Serilog" Version="3.1.1" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" /> <PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />