rdt-client/server/RdtClient.Data/Data/TorrentData.cs
2026-05-27 22:04:30 -06:00

310 lines
9.4 KiB
C#

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data;
namespace RdtClient.Data.Data;
public class TorrentData(DataContext dataContext, ILogger<TorrentData>? logger = null) : ITorrentData
{
public async Task<IList<Torrent>> Get()
{
var torrents = await dataContext.Torrents
.AsNoTracking()
.AsSplitQuery()
.Include(m => m.Downloads)
.OrderBy(m => m.Priority ?? 9999)
.ToListAsync();
return torrents.OrderBy(m => m.Priority ?? 9999)
.ThenBy(m => m.Added)
.ToList();
}
public async Task<Torrent?> GetById(Guid torrentId)
{
var dbTorrent = await dataContext.Torrents
.AsNoTracking()
.Include(m => m.Downloads)
.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null)
{
return null;
}
foreach (var file in dbTorrent.Downloads)
{
file.Torrent = null;
}
return dbTorrent;
}
public async Task<Torrent?> GetByHash(String hash)
{
hash = hash.ToLower();
var dbTorrent = await dataContext.Torrents
.AsNoTracking()
.Include(m => m.Downloads)
.FirstOrDefaultAsync(m => m.Hash == hash);
if (dbTorrent == null)
{
return null;
}
foreach (var file in dbTorrent.Downloads)
{
file.Torrent = null;
}
return dbTorrent;
}
public async Task<Torrent> Add(String? rdId,
String hash,
String? fileOrMagnetContents,
Boolean isFile,
DownloadType downloadType,
DownloadClient downloadClient,
Torrent torrent)
{
var newTorrent = new Torrent
{
TorrentId = Guid.NewGuid(),
Added = DateTimeOffset.UtcNow,
RdId = rdId,
Hash = hash.ToLower(),
Category = torrent.Category,
HostDownloadAction = torrent.HostDownloadAction,
FinishedActionDelay = torrent.FinishedActionDelay,
DownloadAction = torrent.DownloadAction,
FinishedAction = torrent.FinishedAction,
DownloadMinSize = torrent.DownloadMinSize,
IncludeRegex = torrent.IncludeRegex,
ExcludeRegex = torrent.ExcludeRegex,
DownloadManualFiles = torrent.DownloadManualFiles,
DownloadClient = downloadClient,
Type = downloadType,
FileOrMagnet = fileOrMagnetContents,
IsFile = isFile,
Priority = torrent.Priority,
TorrentRetryAttempts = torrent.TorrentRetryAttempts,
DownloadRetryAttempts = torrent.DownloadRetryAttempts,
DeleteOnError = torrent.DeleteOnError,
Lifetime = torrent.Lifetime,
RdStatus = torrent.RdStatus,
RdName = torrent.RdName
};
await dataContext.Torrents.AddAsync(newTorrent);
await dataContext.SaveChangesAsync();
return newTorrent;
}
public async Task UpdateRdData(Torrent torrent)
{
var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrent.TorrentId);
if (dbTorrent == null)
{
return;
}
dbTorrent.RdName = torrent.RdName;
dbTorrent.RdSize = torrent.RdSize;
dbTorrent.RdHost = torrent.RdHost;
dbTorrent.RdSplit = torrent.RdSplit;
dbTorrent.RdProgress = torrent.RdProgress;
dbTorrent.RdStatus = torrent.RdStatus;
dbTorrent.RdStatusRaw = torrent.RdStatusRaw;
dbTorrent.RdAdded = torrent.RdAdded;
dbTorrent.RdEnded = torrent.RdEnded;
dbTorrent.RdSpeed = torrent.RdSpeed;
dbTorrent.RdSeeders = torrent.RdSeeders;
dbTorrent.RdFiles = torrent.RdFiles;
await dataContext.SaveChangesAsync();
}
public async Task UpdateRdId(Torrent torrent, String rdId)
{
var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrent.TorrentId);
if (dbTorrent == null)
{
return;
}
dbTorrent.RdId = rdId;
await dataContext.SaveChangesAsync();
}
public async Task UpdateHash(Torrent torrent, String hash)
{
var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrent.TorrentId);
if (dbTorrent == null)
{
return;
}
dbTorrent.Hash = hash.ToLower();
await dataContext.SaveChangesAsync();
}
public async Task Update(Torrent torrent)
{
var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrent.TorrentId);
if (dbTorrent == null)
{
return;
}
dbTorrent.DownloadClient = torrent.DownloadClient;
dbTorrent.HostDownloadAction = torrent.HostDownloadAction;
dbTorrent.Category = torrent.Category;
dbTorrent.Priority = torrent.Priority;
dbTorrent.DownloadRetryAttempts = torrent.DownloadRetryAttempts;
dbTorrent.TorrentRetryAttempts = torrent.TorrentRetryAttempts;
dbTorrent.DeleteOnError = torrent.DeleteOnError;
dbTorrent.Lifetime = torrent.Lifetime;
await dataContext.SaveChangesAsync();
}
public async Task UpdateCategory(Guid torrentId, String? category)
{
var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null)
{
return;
}
dbTorrent.Category = category;
await dataContext.SaveChangesAsync();
}
public async Task UpdateComplete(Guid torrentId, String? error, DateTimeOffset? datetime, Boolean retry)
{
var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null)
{
return;
}
if (String.IsNullOrWhiteSpace(error))
{
var downloads = await dataContext.Downloads.AsNoTracking().Where(m => m.TorrentId == torrentId).ToListAsync();
var downloadWithErrors = downloads.Where(m => !String.IsNullOrWhiteSpace(m.Error)).ToList();
if (downloadWithErrors.Count > 0)
{
error = $"{downloadWithErrors.Count}/{downloads.Count} downloads failed with errors";
}
}
if (!String.IsNullOrWhiteSpace(error) && retry)
{
if (dbTorrent.RetryCount < dbTorrent.TorrentRetryAttempts)
{
dbTorrent.RetryCount += 1;
dbTorrent.Retry = DateTime.UtcNow;
}
}
dbTorrent.Completed = datetime;
dbTorrent.Error = error;
await dataContext.SaveChangesAsync();
}
public async Task UpdateFilesSelected(Guid torrentId, DateTimeOffset datetime)
{
var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null)
{
return;
}
dbTorrent.FilesSelected = datetime;
await dataContext.SaveChangesAsync();
}
public async Task UpdatePriority(Guid torrentId, Int32? priority)
{
var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null)
{
return;
}
dbTorrent.Priority = priority;
await dataContext.SaveChangesAsync();
}
public async Task UpdateRetry(Guid torrentId, DateTimeOffset? dateTime, Int32 retryCount)
{
var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null)
{
return;
}
dbTorrent.RetryCount = retryCount;
dbTorrent.Retry = dateTime;
await dataContext.SaveChangesAsync();
}
public async Task UpdateError(Guid torrentId, String error)
{
var dbTorrent = await dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
if (dbTorrent == null)
{
return;
}
dbTorrent.Error = error;
await dataContext.SaveChangesAsync();
}
public async Task Delete(Guid torrentId)
{
await using var transaction = await dataContext.Database.BeginTransactionAsync();
await dataContext.Downloads
.Where(m => m.TorrentId == torrentId)
.ExecuteDeleteAsync();
var deletedTorrents = await dataContext.Torrents
.Where(m => m.TorrentId == torrentId)
.ExecuteDeleteAsync();
await transaction.CommitAsync();
if (deletedTorrents == 0)
{
logger?.LogDebug("Skipped torrent graph deletion because the torrent was not found. TorrentId: {torrentId}", torrentId);
return;
}
}
}