Added bit of logging to debug downloader issues, upgraded packages, cleaned up C# code.
This commit is contained in:
parent
74b988effa
commit
3b72463663
35 changed files with 407 additions and 666 deletions
|
|
@ -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; }
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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}");
|
||||||
|
|
|
||||||
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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 =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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" />
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue