From 780d0e51188e56e2f55f99bcac001ed91ffba175 Mon Sep 17 00:00:00 2001 From: Roger Far Date: Wed, 12 Feb 2025 19:48:48 -0700 Subject: [PATCH 1/2] Add fixes for AllDebrid and their new API. --- .../Models/TorrentClient/TorrentClientFile.cs | 1 + server/RdtClient.Data/RdtClient.Data.csproj | 10 +- .../RdtClient.Service.csproj | 10 +- .../TorrentClients/AllDebridTorrentClient.cs | 199 ++++++++---------- server/RdtClient.Web/RdtClient.Web.csproj | 12 +- 5 files changed, 107 insertions(+), 125 deletions(-) diff --git a/server/RdtClient.Data/Models/TorrentClient/TorrentClientFile.cs b/server/RdtClient.Data/Models/TorrentClient/TorrentClientFile.cs index 62bf096..7f5ccbd 100644 --- a/server/RdtClient.Data/Models/TorrentClient/TorrentClientFile.cs +++ b/server/RdtClient.Data/Models/TorrentClient/TorrentClientFile.cs @@ -6,4 +6,5 @@ public class TorrentClientFile public String Path { get; set; } = default!; public Int64 Bytes { get; set; } public Boolean Selected { get; set; } + public String? DownloadLink { get; set; } } \ No newline at end of file diff --git a/server/RdtClient.Data/RdtClient.Data.csproj b/server/RdtClient.Data/RdtClient.Data.csproj index f21d4fd..37af83e 100644 --- a/server/RdtClient.Data/RdtClient.Data.csproj +++ b/server/RdtClient.Data/RdtClient.Data.csproj @@ -8,11 +8,11 @@ - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index 90ad249..ac3645f 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -9,21 +9,21 @@ - + - - + + - + - + diff --git a/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs index 9ab8875..306da68 100644 --- a/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs @@ -8,13 +8,16 @@ using RdtClient.Service.Helpers; using System.Web; using RdtClient.Data.Models.Data; using File = AllDebridNET.File; -using LogLevel = Microsoft.Extensions.Logging.LogLevel; using Torrent = RdtClient.Data.Models.Data.Torrent; namespace RdtClient.Service.Services.TorrentClients; public class AllDebridTorrentClient(ILogger logger, IHttpClientFactory httpClientFactory) : ITorrentClient { + private static readonly Int64 SessionId = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + private static List _cache = []; + private static Int64 _sessionCounter = 0; + private AllDebridNETClient GetClient() { try @@ -49,30 +52,24 @@ public class AllDebridTorrentClient(ILogger logger, IHtt private static TorrentClientTorrent Map(Magnet torrent) { + var files = GetFiles(torrent.Files); return new() { Id = torrent.Id.ToString(), - Filename = torrent.Filename, + Filename = torrent.Filename ?? "", OriginalFilename = torrent.Filename, - Hash = torrent.Hash, - Bytes = torrent.Size, - OriginalBytes = torrent.Size, + Hash = torrent.Hash ?? "", + Bytes = torrent.Size ?? 0, + OriginalBytes = torrent.Size ?? 0, Host = null, Split = 0, - Progress = (Int64)Math.Round(torrent.Downloaded * 100.0 / torrent.Size), + Progress = (Int64)Math.Round((torrent.Downloaded ?? 0) * 100.0 / (torrent.Size ?? 1)), Status = torrent.Status, - StatusCode = torrent.StatusCode, - Added = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(torrent.UploadDate), - Files = torrent.Links.Select((m, i) => new TorrentClientFile - { - Path = GetFiles(m.Files), - Bytes = m.Size, - Id = i, - Selected = true, - }) - .ToList(), - Links = torrent.Links.Select(m => m.LinkUrl.ToString()).ToList(), - Ended = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(torrent.CompletionDate), + StatusCode = torrent.StatusCode ?? 0, + Added = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(torrent.UploadDate ?? 0), + Files = files, + Links = [], + Ended = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(torrent.CompletionDate ?? 0), Speed = torrent.DownloadSpeed, Seeders = torrent.Seeders }; @@ -80,9 +77,31 @@ public class AllDebridTorrentClient(ILogger logger, IHtt public async Task> GetTorrents() { - var results = await GetClient().Magnet.StatusAllAsync(); + var results = await GetClient().Magnet.StatusLiveAsync(SessionId, _sessionCounter); - return results.Select(Map).ToList(); + _sessionCounter = results.Counter; + + if (results.Fullsync == true) + { + _cache = (results.Magnets ?? []).Select(Map).ToList(); + } + else + { + // Replace the existing items in the cache with the new ones based on the ID + foreach (var result in results.Magnets ?? []) + { + var existing = _cache.FirstOrDefault(m => m.Id == result.Id.ToString()); + if (existing != null) + { + _cache.Remove(existing); + } + _cache.Add(Map(result)); + } + } + + _cache = _cache.Where(m => m.Status != null).ToList(); + + return _cache; } public async Task GetUser() @@ -226,14 +245,9 @@ public class AllDebridTorrentClient(ILogger logger, IHtt return null; } - var magnet = await GetClient().Magnet.StatusAsync(torrent.RdId); + var allFiles = await GetClient().Magnet.FilesAsync(Int64.Parse(torrent.RdId)); - if (magnet == null) - { - return null; - } - - var links = magnet.Links; + var files = GetFiles(allFiles); Log($"Getting download links", torrent); @@ -243,83 +257,74 @@ public class AllDebridTorrentClient(ILogger logger, IHtt Log($"Determining which files are over {minFileSize} bytes", torrent); - links = links.Where(m => m.Size > minFileSize) + files = files.Where(m => m.Bytes > minFileSize) .ToList(); - Log($"Found {links.Count} files that match the minimum file size criterea", torrent); + Log($"Found {files.Count} files that match the minimum file size criterea", torrent); } if (!String.IsNullOrWhiteSpace(torrent.IncludeRegex)) { Log($"Using regular expression {torrent.IncludeRegex} to include only files matching this regex", torrent); - var newLinks = new List(); + var newFiles = new List(); - foreach (var link in links) + foreach (var file in files) { - var path = GetFiles(link.Files); - - if (Regex.IsMatch(path, torrent.IncludeRegex)) + if (Regex.IsMatch(file.Path, torrent.IncludeRegex)) { - Log($"* Including {path}", torrent); - newLinks.Add(link); + Log($"* Including {file.Path}", torrent); + newFiles.Add(file); } else { - Log($"* Excluding {path}", torrent); + Log($"* Excluding {file.Path}", torrent); } } - links = newLinks; + files = newFiles; - Log($"Found {newLinks.Count} files that match the regex", torrent); + Log($"Found {newFiles.Count} files that match the regex", torrent); } else if (!String.IsNullOrWhiteSpace(torrent.ExcludeRegex)) { Log($"Using regular expression {torrent.IncludeRegex} to ignore files matching this regex", torrent); - var newLinks = new List(); + var newLinks = new List(); - foreach (var link in links) + foreach (var link in files) { - var path = GetFiles(link.Files); - - if (!Regex.IsMatch(path, torrent.ExcludeRegex)) + if (!Regex.IsMatch(link.Path, torrent.ExcludeRegex)) { - Log($"* Including {path}", torrent); + Log($"* Including {link.Path}", torrent); newLinks.Add(link); } else { - Log($"* Excluding {path}", torrent); + Log($"* Excluding {link.Path}", torrent); } } - links = newLinks; + files = newLinks; Log($"Found {newLinks.Count} files that match the regex", torrent); } - if (links.Count == 0) + if (files.Count == 0) { Log($"Filtered all files out! Downloading ALL files instead!", torrent); - links = magnet.Links; + files = GetFiles(allFiles); } - if (logger.IsEnabled(LogLevel.Debug)) + Log($"Selecting links:"); + + foreach (var file in files) { - Log($"Selecting links:"); - - foreach (var link in links) - { - Log($"{GetFiles(link.Files)} ({link.Size}b) {link.LinkUrl}"); - } + Log($"{file.Path} ({file.Bytes}b) {file.DownloadLink}"); } - - Log("", torrent); - - return links.Select(m => m.LinkUrl.ToString()).ToList(); + + return files.Where(m => m.DownloadLink != null).Select(m => m.DownloadLink!.ToString()).ToList(); } public Task GetFileName(String downloadUrl) @@ -340,65 +345,41 @@ public class AllDebridTorrentClient(ILogger logger, IHtt return Map(result); } - - private static String GetFiles(IList files) + + private static List GetFiles(List? files, String parentPath = "") { - var result = new List(); - - foreach (var file in files) + if (files == null) { - if (!String.IsNullOrWhiteSpace(file.N)) - { - result.Add(file.N); - } + return []; + } - if (file.E != null && file.E.Value.PurpleEArray != null && file.E.Value.PurpleEArray.Count > 0) + return files.SelectMany(file => + { + var currentPath = String.IsNullOrEmpty(parentPath) + ? file.FolderOrFileName + : Path.Combine(parentPath, file.FolderOrFileName); + + var result = new List(); + + // If it's a file (has size) + if (file.Size.HasValue) { - if (file.E.Value.PurpleEArray.Count != 1) + result.Add(new() { - throw new("Unexpected number of nested files"); - } - - result.AddRange(GetFiles(file.E.Value.PurpleEArray)); + Path = currentPath, + Bytes = file.Size.Value, + DownloadLink = file.DownloadLink + }); } - } - return String.Join("/", result); - } - - private static List GetFiles(IList files) - { - var result = new List(); - - foreach (var file in files) - { - if (!String.IsNullOrWhiteSpace(file.N)) + // Process sub-nodes if they exist + if (file.SubNodes != null) { - result.Add(file.N); + result.AddRange(GetFiles(file.SubNodes, currentPath)); } - if (file.E != null && file.E.Count > 0) - { - result.AddRange(GetFiles(file.E)); - } - } - - return result; - } - - private static List GetFiles(IList files) - { - var result = new List(); - - foreach (var file in files) - { - if (!String.IsNullOrWhiteSpace(file.N)) - { - result.Add(file.N); - } - } - - return result; + return result; + }).ToList(); } private void Log(String message, Torrent? torrent = null) diff --git a/server/RdtClient.Web/RdtClient.Web.csproj b/server/RdtClient.Web/RdtClient.Web.csproj index f64d20b..383e53f 100644 --- a/server/RdtClient.Web/RdtClient.Web.csproj +++ b/server/RdtClient.Web/RdtClient.Web.csproj @@ -29,15 +29,15 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + From f58b7d3e7237fda939202929ef4f6a2cf1c5ea8f Mon Sep 17 00:00:00 2001 From: Roger Far Date: Wed, 12 Feb 2025 20:24:22 -0700 Subject: [PATCH 2/2] Refactored TorrentClientKind to Provider. Upgrade Downloader.NET --- server/RdtClient.Data/Models/Data/Torrent.cs | 10 +--------- server/RdtClient.Service/RdtClient.Service.csproj | 2 +- server/RdtClient.Service/Services/DownloadClient.cs | 5 +++-- .../Services/Downloaders/SymlinkDownloader.cs | 6 +++--- server/RdtClient.Service/Services/QBittorrent.cs | 2 +- .../Services/TorrentClients/AllDebridTorrentClient.cs | 2 +- .../Services/TorrentClients/PremiumizeTorrentClient.cs | 2 +- .../Services/TorrentClients/RealDebridTorrentClient.cs | 2 +- .../Services/TorrentClients/TorBoxTorrentClient.cs | 2 +- 9 files changed, 13 insertions(+), 20 deletions(-) diff --git a/server/RdtClient.Data/Models/Data/Torrent.cs b/server/RdtClient.Data/Models/Data/Torrent.cs index f928e3e..57efdbf 100644 --- a/server/RdtClient.Data/Models/Data/Torrent.cs +++ b/server/RdtClient.Data/Models/Data/Torrent.cs @@ -44,7 +44,7 @@ public class Torrent [InverseProperty("Torrent")] public IList Downloads { get; set; } = []; - public TorrentClientKind? ClientKind { get; set; } + public Provider? ClientKind { get; set; } public String? RdId { get; set; } public String? RdName { get; set; } public Int64? RdSize { get; set; } @@ -93,12 +93,4 @@ public class Torrent return DownloadManualFiles.Split(","); } } - - public enum TorrentClientKind - { - AllDebrid, - Premiumize, - RealDebrid, - TorBox - } } \ No newline at end of file diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index ac3645f..8f2c179 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -12,7 +12,7 @@ - + diff --git a/server/RdtClient.Service/Services/DownloadClient.cs b/server/RdtClient.Service/Services/DownloadClient.cs index 23d0f1e..07cdbec 100644 --- a/server/RdtClient.Service/Services/DownloadClient.cs +++ b/server/RdtClient.Service/Services/DownloadClient.cs @@ -1,4 +1,5 @@ -using RdtClient.Data.Models.Data; +using RdtClient.Data.Enums; +using RdtClient.Data.Models.Data; using RdtClient.Service.Helpers; using RdtClient.Service.Services.Downloaders; using RdtClient.Service.Services.TorrentClients; @@ -40,7 +41,7 @@ public class DownloadClient(Download download, Torrent torrent, String destinati var filePath = DownloadHelper.GetDownloadPath(destinationPath, torrent, download); var downloadPath = DownloadHelper.GetDownloadPath(torrent, download); - if (torrent.ClientKind == Torrent.TorrentClientKind.AllDebrid && Type == Data.Enums.DownloadClient.Symlink) + if (torrent.ClientKind == Provider.AllDebrid && Type == Data.Enums.DownloadClient.Symlink) { downloadPath = AllDebridTorrentClient.GetSymlinkPath(torrent, download); } diff --git a/server/RdtClient.Service/Services/Downloaders/SymlinkDownloader.cs b/server/RdtClient.Service/Services/Downloaders/SymlinkDownloader.cs index 74db7c0..4ea8f79 100644 --- a/server/RdtClient.Service/Services/Downloaders/SymlinkDownloader.cs +++ b/server/RdtClient.Service/Services/Downloaders/SymlinkDownloader.cs @@ -1,10 +1,10 @@ -using RdtClient.Data.Models.Data; +using RdtClient.Data.Enums; using RdtClient.Service.Helpers; using Serilog; namespace RdtClient.Service.Services.Downloaders; -public class SymlinkDownloader(String uri, String destinationPath, String path, Torrent.TorrentClientKind? clientKind) : IDownloader +public class SymlinkDownloader(String uri, String destinationPath, String path, Provider? clientKind) : IDownloader { public event EventHandler? DownloadComplete; public event EventHandler? DownloadProgress; @@ -62,7 +62,7 @@ public class SymlinkDownloader(String uri, String destinationPath, String path, var shouldSearch = true; // When resolving symlinks for AllDebrid, we know the exact file path, so we can skip the search. - if (clientKind == Torrent.TorrentClientKind.AllDebrid) + if (clientKind == Provider.AllDebrid) { var potentialFilePath = Path.Combine(rcloneMountPath, path); diff --git a/server/RdtClient.Service/Services/QBittorrent.cs b/server/RdtClient.Service/Services/QBittorrent.cs index d066fab..3c12685 100644 --- a/server/RdtClient.Service/Services/QBittorrent.cs +++ b/server/RdtClient.Service/Services/QBittorrent.cs @@ -209,7 +209,7 @@ public class QBittorrent(ILogger logger, Settings settings, Authent if (!String.IsNullOrWhiteSpace(torrent.RdName)) { // Alldebrid stores single file torrents at the root folder. - if (torrent.ClientKind == Torrent.TorrentClientKind.AllDebrid && torrent.Files.Count == 1) + if (torrent.ClientKind == Provider.AllDebrid && torrent.Files.Count == 1) { torrentPath = Path.Combine(downloadPath, torrent.Files[0].Path); } else diff --git a/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs index 306da68..ed8249a 100644 --- a/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs @@ -196,7 +196,7 @@ public class AllDebridTorrentClient(ILogger logger, IHtt torrent.RdFiles = JsonConvert.SerializeObject(torrentClientTorrent.Files); } - torrent.ClientKind = Torrent.TorrentClientKind.AllDebrid; + torrent.ClientKind = Provider.AllDebrid; torrent.RdHost = torrentClientTorrent.Host; torrent.RdSplit = torrentClientTorrent.Split; torrent.RdProgress = torrentClientTorrent.Progress; diff --git a/server/RdtClient.Service/Services/TorrentClients/PremiumizeTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/PremiumizeTorrentClient.cs index 438fe29..59da932 100644 --- a/server/RdtClient.Service/Services/TorrentClients/PremiumizeTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/PremiumizeTorrentClient.cs @@ -162,7 +162,7 @@ public class PremiumizeTorrentClient(ILogger logger, IH torrent.RdFiles = JsonConvert.SerializeObject(torrentClientTorrent.Files); } - torrent.ClientKind = Torrent.TorrentClientKind.Premiumize; + torrent.ClientKind = Provider.Premiumize; torrent.RdHost = torrentClientTorrent.Host; torrent.RdSplit = torrentClientTorrent.Split; torrent.RdProgress = torrentClientTorrent.Progress; diff --git a/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs index 29493fd..368e733 100644 --- a/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs @@ -295,7 +295,7 @@ public class RealDebridTorrentClient(ILogger logger, IH torrent.RdFiles = JsonConvert.SerializeObject(torrentClientTorrent.Files); } - torrent.ClientKind = Data.Models.Data.Torrent.TorrentClientKind.RealDebrid; + torrent.ClientKind = Provider.RealDebrid; torrent.RdHost = torrentClientTorrent.Host; torrent.RdSplit = torrentClientTorrent.Split; torrent.RdProgress = torrentClientTorrent.Progress; diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 45f562b..1a542f4 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -230,7 +230,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien torrent.RdFiles = JsonConvert.SerializeObject(rdTorrent.Files); } - torrent.ClientKind = Torrent.TorrentClientKind.TorBox; + torrent.ClientKind = Provider.TorBox; torrent.RdHost = rdTorrent.Host; torrent.RdSplit = rdTorrent.Split; torrent.RdProgress = rdTorrent.Progress;