From 9454ea1bd17054d1b9a33e2d0aebf058b798255b Mon Sep 17 00:00:00 2001 From: omgbeez <251408589+omgbeez@users.noreply.github.com> Date: Sat, 17 Jan 2026 12:23:16 -0500 Subject: [PATCH] Refactored torrent and download models with DTOs to simplify serialization and API responses. --- .../Models/Internal/TorrentDto.cs | 67 ++++++++ .../Services/RemoteService.cs | 67 +++++++- .../Controllers/TorrentsController.cs | 143 ++++++++++++++++-- 3 files changed, 258 insertions(+), 19 deletions(-) create mode 100644 server/RdtClient.Data/Models/Internal/TorrentDto.cs diff --git a/server/RdtClient.Data/Models/Internal/TorrentDto.cs b/server/RdtClient.Data/Models/Internal/TorrentDto.cs new file mode 100644 index 0000000..d04f64e --- /dev/null +++ b/server/RdtClient.Data/Models/Internal/TorrentDto.cs @@ -0,0 +1,67 @@ +using RdtClient.Data.Enums; +using RdtClient.Data.Models.Data; +using RdtClient.Data.Models.TorrentClient; + +namespace RdtClient.Data.Models.Internal; + +public class TorrentDto +{ + public Guid TorrentId { get; set; } + public String Hash { get; set; } = null!; + public String? Category { get; set; } + public TorrentDownloadAction DownloadAction { get; set; } + public TorrentFinishedAction FinishedAction { get; set; } + public Int32 FinishedActionDelay { get; set; } + public TorrentHostDownloadAction HostDownloadAction { get; set; } + public Int32 DownloadMinSize { get; set; } + public String? IncludeRegex { get; set; } + public String? ExcludeRegex { get; set; } + public String? DownloadManualFiles { get; set; } + public DownloadClient DownloadClient { get; set; } + public DateTimeOffset Added { get; set; } + public DateTimeOffset? FilesSelected { get; set; } + public DateTimeOffset? Completed { get; set; } + public Boolean IsFile { get; set; } + public Int32? Priority { get; set; } + public Int32 RetryCount { get; set; } + public Int32 DownloadRetryAttempts { get; set; } + public Int32 TorrentRetryAttempts { get; set; } + public Int32 DeleteOnError { get; set; } + public Int32 Lifetime { get; set; } + public String? Error { get; set; } + public String? RdId { get; set; } + public String? RdName { get; set; } + public Int64? RdSize { get; set; } + public String? RdHost { get; set; } + public Int64? RdSplit { get; set; } + public Int64? RdProgress { get; set; } + public TorrentStatus? RdStatus { get; set; } + public String? RdStatusRaw { get; set; } + public DateTimeOffset? RdAdded { get; set; } + public DateTimeOffset? RdEnded { get; set; } + public Int64? RdSpeed { get; set; } + public Int64? RdSeeders { get; set; } + public IList Files { get; set; } = []; + public IList Downloads { get; set; } = []; +} + +public class DownloadDto +{ + public Guid DownloadId { get; set; } + public Guid TorrentId { get; set; } + public String Path { get; set; } = null!; + public String? Link { get; set; } + public DateTimeOffset Added { get; set; } + public DateTimeOffset? DownloadQueued { get; set; } + public DateTimeOffset? DownloadStarted { get; set; } + public DateTimeOffset? DownloadFinished { get; set; } + public DateTimeOffset? UnpackingQueued { get; set; } + public DateTimeOffset? UnpackingStarted { get; set; } + public DateTimeOffset? UnpackingFinished { get; set; } + public DateTimeOffset? Completed { get; set; } + public Int32 RetryCount { get; set; } + public String? Error { get; set; } + public Int64 BytesTotal { get; set; } + public Int64 BytesDone { get; set; } + public Int64 Speed { get; set; } +} diff --git a/server/RdtClient.Service/Services/RemoteService.cs b/server/RdtClient.Service/Services/RemoteService.cs index 8eea62c..7ce8d77 100644 --- a/server/RdtClient.Service/Services/RemoteService.cs +++ b/server/RdtClient.Service/Services/RemoteService.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.SignalR; +using RdtClient.Data.Models.Internal; namespace RdtClient.Service.Services; @@ -7,16 +8,70 @@ public class RemoteService(IHubContext hub, Torrents torrents) public async Task Update() { var allTorrents = await torrents.Get(); - - // Prevent infinite recursion when serializing - foreach (var file in allTorrents.SelectMany(torrent => torrent.Downloads)) + + var torrentDtos = allTorrents.Select(torrent => new TorrentDto { - file.Torrent = null; - } + TorrentId = torrent.TorrentId, + Hash = torrent.Hash, + Category = torrent.Category, + DownloadAction = torrent.DownloadAction, + FinishedAction = torrent.FinishedAction, + FinishedActionDelay = torrent.FinishedActionDelay, + HostDownloadAction = torrent.HostDownloadAction, + DownloadMinSize = torrent.DownloadMinSize, + IncludeRegex = torrent.IncludeRegex, + ExcludeRegex = torrent.ExcludeRegex, + DownloadManualFiles = torrent.DownloadManualFiles, + DownloadClient = torrent.DownloadClient, + Added = torrent.Added, + FilesSelected = torrent.FilesSelected, + Completed = torrent.Completed, + IsFile = torrent.IsFile, + Priority = torrent.Priority, + RetryCount = torrent.RetryCount, + DownloadRetryAttempts = torrent.DownloadRetryAttempts, + TorrentRetryAttempts = torrent.TorrentRetryAttempts, + DeleteOnError = torrent.DeleteOnError, + Lifetime = torrent.Lifetime, + Error = torrent.Error, + RdId = torrent.RdId, + RdName = torrent.RdName, + RdSize = torrent.RdSize, + RdHost = torrent.RdHost, + RdSplit = torrent.RdSplit, + RdProgress = torrent.RdProgress, + RdStatus = torrent.RdStatus, + RdStatusRaw = torrent.RdStatusRaw, + RdAdded = torrent.RdAdded, + RdEnded = torrent.RdEnded, + RdSpeed = torrent.RdSpeed, + RdSeeders = torrent.RdSeeders, + Files = torrent.Files, + Downloads = torrent.Downloads.Select(download => new DownloadDto + { + DownloadId = download.DownloadId, + TorrentId = download.TorrentId, + Path = download.Path, + Link = download.Link, + Added = download.Added, + DownloadQueued = download.DownloadQueued, + DownloadStarted = download.DownloadStarted, + DownloadFinished = download.DownloadFinished, + UnpackingQueued = download.UnpackingQueued, + UnpackingStarted = download.UnpackingStarted, + UnpackingFinished = download.UnpackingFinished, + Completed = download.Completed, + RetryCount = download.RetryCount, + Error = download.Error, + BytesTotal = download.BytesTotal, + BytesDone = download.BytesDone, + Speed = download.Speed + }).ToList() + }).ToList(); await hub.Clients.All.SendCoreAsync("update", [ - allTorrents + torrentDtos ]); } diff --git a/server/RdtClient.Web/Controllers/TorrentsController.cs b/server/RdtClient.Web/Controllers/TorrentsController.cs index fd3a0dc..71f152f 100644 --- a/server/RdtClient.Web/Controllers/TorrentsController.cs +++ b/server/RdtClient.Web/Controllers/TorrentsController.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using MonoTorrent; +using RdtClient.Data.Models.Internal; using RdtClient.Data.Models.TorrentClient; using RdtClient.Service.Helpers; using RdtClient.Service.Services; @@ -15,34 +16,150 @@ public class TorrentsController(ILogger logger, Torrents tor { [HttpGet] [Route("")] - public async Task>> GetAll() + public async Task>> GetAll() { var results = await torrents.Get(); - // Prevent infinite recursion when serializing - foreach (var file in results.SelectMany(torrent => torrent.Downloads)) + var torrentDtos = results.Select(torrent => new TorrentDto { - file.Torrent = null; - } + TorrentId = torrent.TorrentId, + Hash = torrent.Hash, + Category = torrent.Category, + DownloadAction = torrent.DownloadAction, + FinishedAction = torrent.FinishedAction, + FinishedActionDelay = torrent.FinishedActionDelay, + HostDownloadAction = torrent.HostDownloadAction, + DownloadMinSize = torrent.DownloadMinSize, + IncludeRegex = torrent.IncludeRegex, + ExcludeRegex = torrent.ExcludeRegex, + DownloadManualFiles = torrent.DownloadManualFiles, + DownloadClient = torrent.DownloadClient, + Added = torrent.Added, + FilesSelected = torrent.FilesSelected, + Completed = torrent.Completed, + IsFile = torrent.IsFile, + Priority = torrent.Priority, + RetryCount = torrent.RetryCount, + DownloadRetryAttempts = torrent.DownloadRetryAttempts, + TorrentRetryAttempts = torrent.TorrentRetryAttempts, + DeleteOnError = torrent.DeleteOnError, + Lifetime = torrent.Lifetime, + Error = torrent.Error, + RdId = torrent.RdId, + RdName = torrent.RdName, + RdSize = torrent.RdSize, + RdHost = torrent.RdHost, + RdSplit = torrent.RdSplit, + RdProgress = torrent.RdProgress, + RdStatus = torrent.RdStatus, + RdStatusRaw = torrent.RdStatusRaw, + RdAdded = torrent.RdAdded, + RdEnded = torrent.RdEnded, + RdSpeed = torrent.RdSpeed, + RdSeeders = torrent.RdSeeders, + Files = torrent.Files, + Downloads = torrent.Downloads.Select(download => new DownloadDto + { + DownloadId = download.DownloadId, + TorrentId = download.TorrentId, + Path = download.Path, + Link = download.Link, + Added = download.Added, + DownloadQueued = download.DownloadQueued, + DownloadStarted = download.DownloadStarted, + DownloadFinished = download.DownloadFinished, + UnpackingQueued = download.UnpackingQueued, + UnpackingStarted = download.UnpackingStarted, + UnpackingFinished = download.UnpackingFinished, + Completed = download.Completed, + RetryCount = download.RetryCount, + Error = download.Error, + BytesTotal = download.BytesTotal, + BytesDone = download.BytesDone, + Speed = download.Speed + }).ToList() + }).ToList(); - return Ok(results); + return Ok(torrentDtos); } [HttpGet] [Route("Get/{torrentId:guid}")] - public async Task> GetById(Guid torrentId) + public async Task> GetById(Guid torrentId) { var torrent = await torrents.GetById(torrentId); - if (torrent?.Downloads != null) + if (torrent == null) { - foreach (var file in torrent.Downloads) - { - file.Torrent = null; - } + return NotFound(); } - return Ok(torrent); + foreach (var file in torrent.Downloads) + { + file.Torrent = null; + } + + var torrentDto = new TorrentDto + { + TorrentId = torrent!.TorrentId, + Hash = torrent.Hash, + Category = torrent.Category, + DownloadAction = torrent.DownloadAction, + FinishedAction = torrent.FinishedAction, + FinishedActionDelay = torrent.FinishedActionDelay, + HostDownloadAction = torrent.HostDownloadAction, + DownloadMinSize = torrent.DownloadMinSize, + IncludeRegex = torrent.IncludeRegex, + ExcludeRegex = torrent.ExcludeRegex, + DownloadManualFiles = torrent.DownloadManualFiles, + DownloadClient = torrent.DownloadClient, + Added = torrent.Added, + FilesSelected = torrent.FilesSelected, + Completed = torrent.Completed, + IsFile = torrent.IsFile, + Priority = torrent.Priority, + RetryCount = torrent.RetryCount, + DownloadRetryAttempts = torrent.DownloadRetryAttempts, + TorrentRetryAttempts = torrent.TorrentRetryAttempts, + DeleteOnError = torrent.DeleteOnError, + Lifetime = torrent.Lifetime, + Error = torrent.Error, + RdId = torrent.RdId, + RdName = torrent.RdName, + RdSize = torrent.RdSize, + RdHost = torrent.RdHost, + RdSplit = torrent.RdSplit, + RdProgress = torrent.RdProgress, + RdStatus = torrent.RdStatus, + RdStatusRaw = torrent.RdStatusRaw, + RdAdded = torrent.RdAdded, + RdEnded = torrent.RdEnded, + RdSpeed = torrent.RdSpeed, + RdSeeders = torrent.RdSeeders, + Files = torrent.Files, + Downloads = (torrent.Downloads).Select(download => new DownloadDto + { + DownloadId = download.DownloadId, + TorrentId = download.TorrentId, + Path = download.Path, + Link = download.Link, + Added = download.Added, + DownloadQueued = download.DownloadQueued, + DownloadStarted = download.DownloadStarted, + DownloadFinished = download.DownloadFinished, + UnpackingQueued = download.UnpackingQueued, + UnpackingStarted = download.UnpackingStarted, + UnpackingFinished = download.UnpackingFinished, + Completed = download.Completed, + RetryCount = download.RetryCount, + Error = download.Error, + BytesTotal = download.BytesTotal, + BytesDone = download.BytesDone, + Speed = download.Speed + }).ToList() + }; + + return Ok(torrentDto); } [HttpGet]