From 772631d47f534260a0745c92e1a9f4b237d9f386 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Thu, 18 Jul 2024 20:14:35 +1000 Subject: [PATCH 01/31] partially complete about 1/4 of the TorBoxClient Up to available files --- .../RdtClient.Service.csproj | 1 + .../TorrentClients/TorBoxTorrentClient.cs | 429 ++++++++++++++++++ 2 files changed, 430 insertions(+) create mode 100644 server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index c736d2e..2c5daa6 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -22,6 +22,7 @@ + diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs new file mode 100644 index 0000000..02c1d21 --- /dev/null +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -0,0 +1,429 @@ +using System.Text.RegularExpressions; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using TorBoxNET; +using RdtClient.Data.Enums; +using RdtClient.Data.Models.TorrentClient; +using RdtClient.Service.Helpers; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace RdtClient.Service.Services.TorrentClients; + +public class TorBoxTorrentClient(ILogger logger, IHttpClientFactory httpClientFactory) : ITorrentClient +{ + private TimeSpan? _offset; + + private TorBoxNetClient GetClient() + { + try + { + var apiKey = Settings.Get.Provider.ApiKey; + + if (String.IsNullOrWhiteSpace(apiKey)) + { + throw new("TorBox API Key not set in the settings"); + } + + var httpClient = httpClientFactory.CreateClient(); + httpClient.Timeout = TimeSpan.FromSeconds(Settings.Get.Provider.Timeout); + + var rdtNetClient = new TorBoxNetClient(null, httpClient, 5); + rdtNetClient.UseApiAuthentication(apiKey); + + // Get the server time to fix up the timezones on results + if (_offset == null) + { + var serverTime = rdtNetClient.Api.GetIsoTimeAsync(); + _offset = serverTime.Offset; + } + + return rdtNetClient; + } + catch (AggregateException ae) + { + foreach (var inner in ae.InnerExceptions) + { + logger.LogError(inner, $"The connection to RealDebrid has failed: {inner.Message}"); + } + + throw; + } + catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) + { + logger.LogError(ex, $"The connection to RealDebrid has timed out: {ex.Message}"); + + throw; + } + catch (TaskCanceledException ex) + { + logger.LogError(ex, $"The connection to RealDebrid has timed out: {ex.Message}"); + + throw; + } + } + + private TorrentClientTorrent Map(Torrent torrent) + { + return new() + { + Id = torrent.Id.ToString(), + Filename = torrent.Name, + OriginalFilename = torrent.Name, + Hash = torrent.Hash, + Bytes = torrent.Size, + OriginalBytes = torrent.Size, + Host = null, + Split = 0, + Progress = (Int64)((torrent.Progress) * 100.0), + Status = torrent.DownloadState, + Added = ChangeTimeZone(torrent.CreatedAt)!.Value, + Files = (torrent.Files ?? []).Select(m => new TorrentClientFile + { + Path = m.S3Path.Replace(m.Hash + "/", string.Empty), + Bytes = m.Size, + Id = m.Id, + Selected = true + }).ToList(), + Links = [], + Ended = ChangeTimeZone(torrent.UpdatedAt), + Speed = torrent.DownloadSpeed, + Seeders = torrent.Seeds, + }; + } + + public async Task> GetTorrents() + { + var results = await GetClient().Torrents.GetAsync(true); + + return results!.Select(Map).ToList(); + } + + public async Task GetUser() + { + var user = await GetClient().User.GetAsync(false); + + return new() + { + Username = user.Data!.Email, + Expiration = user.Data!.Plan != 0 ? user.Data!.PremiumExpiresAt.Value : null + }; + } + + public async Task AddMagnet(String magnetLink) + { + var result = await GetClient().Torrents.AddMagnetAsync(magnetLink); + + return result.Data?.Torrent_ID.ToString()!; + } + + public async Task AddFile(Byte[] bytes) + { + var result = await GetClient().Torrents.AddFileAsync(bytes); + + return result.Data?.Torrent_ID.ToString()!; + } + + public async Task> GetAvailableFiles(String hash) + { + var result = await GetClient().Torrents.GetAvailableFiles(hash); + + var files = result.SelectMany(m => m.Value).SelectMany(m => m.Value).SelectMany(m => m.Values); + + var groups = files.Where(m => m.Filename != null).GroupBy(m => $"{m.Filename}-{m.Filesize}"); + + var torrentClientAvailableFiles = groups.Select(m => new TorrentClientAvailableFile + { + Filename = m.First().Filename!, + Filesize = m.First().Filesize + }).ToList(); + + return torrentClientAvailableFiles; + } + + public async Task SelectFiles(Data.Models.Data.Torrent torrent) + { + var files = torrent.Files; + + Log("Seleting files", torrent); + + if (torrent.DownloadAction == TorrentDownloadAction.DownloadAvailableFiles) + { + Log($"Determining which files are already available on RealDebrid", torrent); + + var availableFiles = await GetAvailableFiles(torrent.Hash); + + Log($"Found {files.Count}/{torrent.Files.Count} available files on RealDebrid", torrent); + + files = torrent.Files.Where(m => availableFiles.Any(f => m.Path.EndsWith(f.Filename))).ToList(); + } + else if (torrent.DownloadAction == TorrentDownloadAction.DownloadAll) + { + Log("Selecting all files", torrent); + files = [.. torrent.Files]; + } + else if (torrent.DownloadAction == TorrentDownloadAction.DownloadManual) + { + Log("Selecting manual selected files", torrent); + files = torrent.Files.Where(m => torrent.ManualFiles.Any(f => m.Path.EndsWith(f))).ToList(); + } + + Log($"Selecting {files.Count}/{torrent.Files.Count} files", torrent); + + if (torrent.DownloadAction != TorrentDownloadAction.DownloadManual && torrent.DownloadMinSize > 0) + { + var minFileSize = torrent.DownloadMinSize * 1024 * 1024; + + Log($"Determining which files are over {minFileSize} bytes", torrent); + + files = files.Where(m => m.Bytes > minFileSize) + .ToList(); + + 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 newFiles = new List(); + foreach (var file in files) + { + if (Regex.IsMatch(file.Path, torrent.IncludeRegex)) + { + Log($"* Including {file.Path}", torrent); + newFiles.Add(file); + } + else + { + Log($"* Excluding {file.Path}", torrent); + } + } + + files = newFiles; + + Log($"Found {files.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 newFiles = new List(); + foreach (var file in files) + { + if (!Regex.IsMatch(file.Path, torrent.ExcludeRegex)) + { + Log($"* Including {file.Path}", torrent); + newFiles.Add(file); + } + else + { + Log($"* Excluding {file.Path}", torrent); + } + } + + files = newFiles; + + Log($"Found {files.Count} files that match the regex", torrent); + } + + if (files.Count == 0) + { + Log($"Filtered all files out! Downloading ALL files instead!", torrent); + + files = torrent.Files; + } + + var fileIds = files.Select(m => m.Id.ToString()).ToArray(); + + Log($"Selecting files:"); + + foreach (var file in files) + { + Log($"{file.Id}: {file.Path} ({file.Bytes}b)"); + } + + Log("", torrent); + + await GetClient().Torrents.SelectFilesAsync(torrent.RdId!, [.. fileIds]); + } + + public async Task Delete(String torrentId) + { + await GetClient().Torrents.DeleteAsync(torrentId); + } + + public async Task Unrestrict(String link) + { + var result = await GetClient().Unrestrict.LinkAsync(link); + + if (result.Download == null) + { + throw new($"Unrestrict returned an invalid download"); + } + + return result.Download; + } + + public async Task UpdateData(Data.Models.Data.Torrent torrent, TorrentClientTorrent? torrentClientTorrent) + { + try + { + if (torrent.RdId == null) + { + return torrent; + } + + var rdTorrent = await GetInfo(torrent.RdId) ?? throw new($"Resource not found"); + + if (!String.IsNullOrWhiteSpace(rdTorrent.Filename)) + { + torrent.RdName = rdTorrent.Filename; + } + + if (!String.IsNullOrWhiteSpace(rdTorrent.OriginalFilename)) + { + torrent.RdName = rdTorrent.OriginalFilename; + } + + if (rdTorrent.Bytes > 0) + { + torrent.RdSize = rdTorrent.Bytes; + } + else if (rdTorrent.OriginalBytes > 0) + { + torrent.RdSize = rdTorrent.OriginalBytes; + } + + if (rdTorrent.Files != null) + { + torrent.RdFiles = JsonConvert.SerializeObject(rdTorrent.Files); + } + + torrent.RdHost = rdTorrent.Host; + torrent.RdSplit = rdTorrent.Split; + torrent.RdProgress = rdTorrent.Progress; + torrent.RdAdded = rdTorrent.Added; + torrent.RdEnded = rdTorrent.Ended; + torrent.RdSpeed = rdTorrent.Speed; + torrent.RdSeeders = rdTorrent.Seeders; + torrent.RdStatusRaw = rdTorrent.Status; + + torrent.RdStatus = rdTorrent.Status switch + { + "magnet_error" => TorrentStatus.Error, + "magnet_conversion" => TorrentStatus.Processing, + "waiting_files_selection" => TorrentStatus.WaitingForFileSelection, + "queued" => TorrentStatus.Downloading, + "downloading" => TorrentStatus.Downloading, + "downloaded" => TorrentStatus.Finished, + "error" => TorrentStatus.Error, + "virus" => TorrentStatus.Error, + "compressing" => TorrentStatus.Downloading, + "uploading" => TorrentStatus.Uploading, + "dead" => TorrentStatus.Error, + _ => TorrentStatus.Error + }; + } + catch (Exception ex) + { + if (ex.Message == "Resource not found") + { + torrent.RdStatusRaw = "deleted"; + } + else + { + throw; + } + } + + return torrent; + } + + public async Task?> GetDownloadLinks(Data.Models.Data.Torrent torrent) + { + if (torrent.RdId == null) + { + return null; + } + + var rdTorrent = await GetInfo(torrent.RdId); + + if (rdTorrent.Links == null) + { + return null; + } + + var downloadLinks = rdTorrent.Links.Where(m => !String.IsNullOrWhiteSpace(m)).ToList(); + + Log($"Found {downloadLinks.Count} links", torrent); + + foreach (var link in downloadLinks) + { + Log($"{link}", torrent); + } + + Log($"Torrent has {torrent.Files.Count(m => m.Selected)} selected files out of {torrent.Files.Count} files, found {downloadLinks.Count} links, torrent ended: {torrent.RdEnded}", torrent); + + // Check if all the links are set that have been selected + if (torrent.Files.Count(m => m.Selected) == downloadLinks.Count) + { + Log($"Matched {torrent.Files.Count(m => m.Selected)} selected files expected files to {downloadLinks.Count} found files", torrent); + + return downloadLinks; + } + + // Check if all all the links are set for manual selection + if (torrent.ManualFiles.Count == downloadLinks.Count) + { + Log($"Matched {torrent.ManualFiles.Count} manual files expected files to {downloadLinks.Count} found files", torrent); + + return downloadLinks; + } + + // If there is only 1 link, delay for 1 minute to see if more links pop up. + if (downloadLinks.Count == 1 && torrent.RdEnded.HasValue) + { + var expired = DateTime.UtcNow - torrent.RdEnded.Value.ToUniversalTime(); + + Log($"Waiting to see if more links appear, checked for {expired.TotalSeconds} seconds", torrent); + + if (expired.TotalSeconds > 60.0) + { + Log($"Waited long enough", torrent); + + return downloadLinks; + } + } + + Log($"Did not find any suiteable download links", torrent); + + return null; + } + + private DateTimeOffset? ChangeTimeZone(DateTimeOffset? dateTimeOffset) + { + if (_offset == null) + { + return dateTimeOffset; + } + + return dateTimeOffset?.Subtract(_offset.Value).ToOffset(_offset.Value); + } + + private async Task GetInfo(String torrentId) + { + var result = await GetClient().Torrents.GetInfoAsync(torrentId); + + return Map(result); + } + + private void Log(String message, Data.Models.Data.Torrent? torrent = null) + { + if (torrent != null) + { + message = $"{message} {torrent.ToLog()}"; + } + + logger.LogDebug(message); + } +} \ No newline at end of file From fc9ea4c29af274b640b65614a5bee4a2479b0677 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Tue, 27 Aug 2024 11:06:33 +1000 Subject: [PATCH 02/31] Implement queudtorrents, selecting files, hash rather than id --- client/package-lock.json | 338 ++++++++++++++++-- client/package.json | 4 +- .../TorrentClients/TorBoxTorrentClient.cs | 197 +++------- 3 files changed, 360 insertions(+), 179 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index b6d1ede..7b63b6f 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -35,7 +35,7 @@ "@angular-eslint/eslint-plugin-template": "16.1.1", "@angular-eslint/schematics": "16.1.1", "@angular-eslint/template-parser": "16.1.1", - "@angular/cli": "^16.2.1", + "@angular/cli": "^16.2.14", "@angular/compiler-cli": "^16.2.3", "@angular/language-service": "^16.2.3", "@types/file-saver": "^2.0.5", @@ -352,12 +352,12 @@ "dev": true }, "node_modules/@angular-devkit/schematics": { - "version": "16.2.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.1.tgz", - "integrity": "sha512-rXXO5zSI/iN6JtU3oU+vKfOB1N8n1iCH9aLudtJfO5zT9r29FIvV4YMmHO0iu78i4IhQAeJdr42cvrGPp8Y41A==", + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.14.tgz", + "integrity": "sha512-B6LQKInCT8w5zx5Pbroext5eFFRTCJdTwHN8GhcVS8IeKCnkeqVTQLjB4lBUg7LEm8Y7UHXwzrVxmk+f+MBXhw==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.1", + "@angular-devkit/core": "16.2.14", "jsonc-parser": "3.2.0", "magic-string": "0.30.1", "ora": "5.4.1", @@ -369,6 +369,55 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", + "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/@angular-eslint/builder": { "version": "16.1.1", "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.1.1.tgz", @@ -544,15 +593,15 @@ } }, "node_modules/@angular/cli": { - "version": "16.2.1", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.1.tgz", - "integrity": "sha512-nuCc0VOGjuUFQo1Pu9CyFQ4VTy7OuwTiwxOG9qbut4FSGz2CO9NeqoamPUuy6rpKVu5JxVe+L6Y4OFaNKv2n3Q==", + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.14.tgz", + "integrity": "sha512-0y71jtitigVolm4Rim1b8xPQ+B22cGp4Spef2Wunpqj67UowN6tsZaVuWBEQh4u5xauX8LAHKqsvy37ZPWCc4A==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1602.1", - "@angular-devkit/core": "16.2.1", - "@angular-devkit/schematics": "16.2.1", - "@schematics/angular": "16.2.1", + "@angular-devkit/architect": "0.1602.14", + "@angular-devkit/core": "16.2.14", + "@angular-devkit/schematics": "16.2.14", + "@schematics/angular": "16.2.14", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.1", @@ -577,6 +626,70 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { + "version": "0.1602.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.14.tgz", + "integrity": "sha512-eSdONEV5dbtLNiOMBy9Ue9DdJ1ct6dH9RdZfYiedq6VZn0lejePAjY36MYVXgq2jTE+v/uIiaNy7caea5pt55A==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.2.14", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/core": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", + "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular/cli/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular/cli/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/@angular/cli/node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -3665,13 +3778,13 @@ } }, "node_modules/@schematics/angular": { - "version": "16.2.1", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.1.tgz", - "integrity": "sha512-e3ckgvSv+OA+4xUBpOqVOvNM8FqY/yXaWqs/Ob0uQ/zPL1iVa/MCAoB25KqYQPnq21hEwE4zqIIQFKasKBIqMA==", + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.14.tgz", + "integrity": "sha512-YqIv727l9Qze8/OL6H9mBHc2jVXzAGRNBYnxYWqWhLbfvuVbbldo6NNIIjgv6lrl2LJSdPAAMNOD5m/f6210ug==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.1", - "@angular-devkit/schematics": "16.2.1", + "@angular-devkit/core": "16.2.14", + "@angular-devkit/schematics": "16.2.14", "jsonc-parser": "3.2.0" }, "engines": { @@ -3680,6 +3793,55 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", + "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@schematics/angular/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@schematics/angular/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/@sigstore/bundle": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", @@ -14563,16 +14725,50 @@ } }, "@angular-devkit/schematics": { - "version": "16.2.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.1.tgz", - "integrity": "sha512-rXXO5zSI/iN6JtU3oU+vKfOB1N8n1iCH9aLudtJfO5zT9r29FIvV4YMmHO0iu78i4IhQAeJdr42cvrGPp8Y41A==", + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.14.tgz", + "integrity": "sha512-B6LQKInCT8w5zx5Pbroext5eFFRTCJdTwHN8GhcVS8IeKCnkeqVTQLjB4lBUg7LEm8Y7UHXwzrVxmk+f+MBXhw==", "dev": true, "requires": { - "@angular-devkit/core": "16.2.1", + "@angular-devkit/core": "16.2.14", "jsonc-parser": "3.2.0", "magic-string": "0.30.1", "ora": "5.4.1", "rxjs": "7.8.1" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", + "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", + "dev": true, + "requires": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + } + }, + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } } }, "@angular-eslint/builder": { @@ -14708,15 +14904,15 @@ } }, "@angular/cli": { - "version": "16.2.1", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.1.tgz", - "integrity": "sha512-nuCc0VOGjuUFQo1Pu9CyFQ4VTy7OuwTiwxOG9qbut4FSGz2CO9NeqoamPUuy6rpKVu5JxVe+L6Y4OFaNKv2n3Q==", + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.14.tgz", + "integrity": "sha512-0y71jtitigVolm4Rim1b8xPQ+B22cGp4Spef2Wunpqj67UowN6tsZaVuWBEQh4u5xauX8LAHKqsvy37ZPWCc4A==", "dev": true, "requires": { - "@angular-devkit/architect": "0.1602.1", - "@angular-devkit/core": "16.2.1", - "@angular-devkit/schematics": "16.2.1", - "@schematics/angular": "16.2.1", + "@angular-devkit/architect": "0.1602.14", + "@angular-devkit/core": "16.2.14", + "@angular-devkit/schematics": "16.2.14", + "@schematics/angular": "16.2.14", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.1", @@ -14733,6 +14929,48 @@ "yargs": "17.7.2" }, "dependencies": { + "@angular-devkit/architect": { + "version": "0.1602.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.14.tgz", + "integrity": "sha512-eSdONEV5dbtLNiOMBy9Ue9DdJ1ct6dH9RdZfYiedq6VZn0lejePAjY36MYVXgq2jTE+v/uIiaNy7caea5pt55A==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.2.14", + "rxjs": "7.8.1" + } + }, + "@angular-devkit/core": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", + "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", + "dev": true, + "requires": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + } + }, + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -16747,14 +16985,48 @@ "optional": true }, "@schematics/angular": { - "version": "16.2.1", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.1.tgz", - "integrity": "sha512-e3ckgvSv+OA+4xUBpOqVOvNM8FqY/yXaWqs/Ob0uQ/zPL1iVa/MCAoB25KqYQPnq21hEwE4zqIIQFKasKBIqMA==", + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.14.tgz", + "integrity": "sha512-YqIv727l9Qze8/OL6H9mBHc2jVXzAGRNBYnxYWqWhLbfvuVbbldo6NNIIjgv6lrl2LJSdPAAMNOD5m/f6210ug==", "dev": true, "requires": { - "@angular-devkit/core": "16.2.1", - "@angular-devkit/schematics": "16.2.1", + "@angular-devkit/core": "16.2.14", + "@angular-devkit/schematics": "16.2.14", "jsonc-parser": "3.2.0" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", + "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", + "dev": true, + "requires": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + } + }, + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } } }, "@sigstore/bundle": { diff --git a/client/package.json b/client/package.json index 4fea071..9f2d19e 100644 --- a/client/package.json +++ b/client/package.json @@ -39,7 +39,7 @@ "@angular-eslint/eslint-plugin-template": "16.1.1", "@angular-eslint/schematics": "16.1.1", "@angular-eslint/template-parser": "16.1.1", - "@angular/cli": "^16.2.1", + "@angular/cli": "^16.2.14", "@angular/compiler-cli": "^16.2.3", "@angular/language-service": "^16.2.3", "@types/file-saver": "^2.0.5", @@ -51,4 +51,4 @@ "prettier": "^3.0.3", "typescript": "5.1.6" } -} \ No newline at end of file +} diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 02c1d21..81935a7 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -6,6 +6,7 @@ using RdtClient.Data.Enums; using RdtClient.Data.Models.TorrentClient; using RdtClient.Service.Helpers; using Microsoft.AspNetCore.Mvc.RazorPages; +using System.Diagnostics.Eventing.Reader; namespace RdtClient.Service.Services.TorrentClients; @@ -58,7 +59,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien { logger.LogError(ex, $"The connection to RealDebrid has timed out: {ex.Message}"); - throw; + throw; } } @@ -72,7 +73,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien Hash = torrent.Hash, Bytes = torrent.Size, OriginalBytes = torrent.Size, - Host = null, + Host = torrent.DownloadPresent.ToString(), Split = 0, Progress = (Int64)((torrent.Progress) * 100.0), Status = torrent.DownloadState, @@ -93,9 +94,22 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task> GetTorrents() { - var results = await GetClient().Torrents.GetAsync(true); + var torrents = new List(); - return results!.Select(Map).ToList(); + var currentTorrents = await GetClient().Torrents.GetCurrentAsync(true); + if (currentTorrents != null) + { + torrents.AddRange(currentTorrents); + } + + var queuedTorrents = await GetClient().Torrents.GetQueuedAsync(true); + if (queuedTorrents != null) + { + torrents.AddRange(queuedTorrents); + + } + + return torrents!.Select(Map).ToList(); } public async Task GetUser() @@ -105,7 +119,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien return new() { Username = user.Data!.Email, - Expiration = user.Data!.Plan != 0 ? user.Data!.PremiumExpiresAt.Value : null + Expiration = user.Data!.Plan != 0 ? user.Data!.PremiumExpiresAt!.Value : null }; } @@ -123,133 +137,20 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien return result.Data?.Torrent_ID.ToString()!; } - public async Task> GetAvailableFiles(String hash) + public Task> GetAvailableFiles(String hash) { - var result = await GetClient().Torrents.GetAvailableFiles(hash); - - var files = result.SelectMany(m => m.Value).SelectMany(m => m.Value).SelectMany(m => m.Values); - - var groups = files.Where(m => m.Filename != null).GroupBy(m => $"{m.Filename}-{m.Filesize}"); - - var torrentClientAvailableFiles = groups.Select(m => new TorrentClientAvailableFile - { - Filename = m.First().Filename!, - Filesize = m.First().Filesize - }).ToList(); - - return torrentClientAvailableFiles; + var result = new List(); + return Task.FromResult>(result); } - public async Task SelectFiles(Data.Models.Data.Torrent torrent) + public Task SelectFiles(Data.Models.Data.Torrent torrent) { - var files = torrent.Files; - - Log("Seleting files", torrent); - - if (torrent.DownloadAction == TorrentDownloadAction.DownloadAvailableFiles) - { - Log($"Determining which files are already available on RealDebrid", torrent); - - var availableFiles = await GetAvailableFiles(torrent.Hash); - - Log($"Found {files.Count}/{torrent.Files.Count} available files on RealDebrid", torrent); - - files = torrent.Files.Where(m => availableFiles.Any(f => m.Path.EndsWith(f.Filename))).ToList(); - } - else if (torrent.DownloadAction == TorrentDownloadAction.DownloadAll) - { - Log("Selecting all files", torrent); - files = [.. torrent.Files]; - } - else if (torrent.DownloadAction == TorrentDownloadAction.DownloadManual) - { - Log("Selecting manual selected files", torrent); - files = torrent.Files.Where(m => torrent.ManualFiles.Any(f => m.Path.EndsWith(f))).ToList(); - } - - Log($"Selecting {files.Count}/{torrent.Files.Count} files", torrent); - - if (torrent.DownloadAction != TorrentDownloadAction.DownloadManual && torrent.DownloadMinSize > 0) - { - var minFileSize = torrent.DownloadMinSize * 1024 * 1024; - - Log($"Determining which files are over {minFileSize} bytes", torrent); - - files = files.Where(m => m.Bytes > minFileSize) - .ToList(); - - 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 newFiles = new List(); - foreach (var file in files) - { - if (Regex.IsMatch(file.Path, torrent.IncludeRegex)) - { - Log($"* Including {file.Path}", torrent); - newFiles.Add(file); - } - else - { - Log($"* Excluding {file.Path}", torrent); - } - } - - files = newFiles; - - Log($"Found {files.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 newFiles = new List(); - foreach (var file in files) - { - if (!Regex.IsMatch(file.Path, torrent.ExcludeRegex)) - { - Log($"* Including {file.Path}", torrent); - newFiles.Add(file); - } - else - { - Log($"* Excluding {file.Path}", torrent); - } - } - - files = newFiles; - - Log($"Found {files.Count} files that match the regex", torrent); - } - - if (files.Count == 0) - { - Log($"Filtered all files out! Downloading ALL files instead!", torrent); - - files = torrent.Files; - } - - var fileIds = files.Select(m => m.Id.ToString()).ToArray(); - - Log($"Selecting files:"); - - foreach (var file in files) - { - Log($"{file.Id}: {file.Path} ({file.Bytes}b)"); - } - - Log("", torrent); - - await GetClient().Torrents.SelectFilesAsync(torrent.RdId!, [.. fileIds]); + return Task.CompletedTask; } public async Task Delete(String torrentId) { - await GetClient().Torrents.DeleteAsync(torrentId); + await GetClient().Torrents.ControlAsync(Convert.ToInt32(torrentId), "delete"); } public async Task Unrestrict(String link) @@ -273,7 +174,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien return torrent; } - var rdTorrent = await GetInfo(torrent.RdId) ?? throw new($"Resource not found"); + var rdTorrent = await GetInfo(torrent.Hash) ?? throw new($"Resource not found"); if (!String.IsNullOrWhiteSpace(rdTorrent.Filename)) { @@ -308,21 +209,29 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien torrent.RdSeeders = rdTorrent.Seeders; torrent.RdStatusRaw = rdTorrent.Status; - torrent.RdStatus = rdTorrent.Status switch + if (rdTorrent.Host == "true") { - "magnet_error" => TorrentStatus.Error, - "magnet_conversion" => TorrentStatus.Processing, - "waiting_files_selection" => TorrentStatus.WaitingForFileSelection, - "queued" => TorrentStatus.Downloading, - "downloading" => TorrentStatus.Downloading, - "downloaded" => TorrentStatus.Finished, - "error" => TorrentStatus.Error, - "virus" => TorrentStatus.Error, - "compressing" => TorrentStatus.Downloading, - "uploading" => TorrentStatus.Uploading, - "dead" => TorrentStatus.Error, - _ => TorrentStatus.Error - }; + torrent.RdStatus = TorrentStatus.Finished; + } + else + { + torrent.RdStatus = rdTorrent.Status switch + { + "queued" => TorrentStatus.Processing, + "metaDL" => TorrentStatus.Processing, + "checkingResumeData" => TorrentStatus.Processing, + "paused" => TorrentStatus.Downloading, + "downloading" => TorrentStatus.Downloading, + "completed" => TorrentStatus.Downloading, + "uploading" => TorrentStatus.Downloading, + "uploading (no peers)" => TorrentStatus.Downloading, + "stalled" => TorrentStatus.Downloading, + "stalled (no seeds)" => TorrentStatus.Downloading, + "cached" => TorrentStatus.Finished, + _ => TorrentStatus.Error + }; + } + } catch (Exception ex) { @@ -363,7 +272,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien } Log($"Torrent has {torrent.Files.Count(m => m.Selected)} selected files out of {torrent.Files.Count} files, found {downloadLinks.Count} links, torrent ended: {torrent.RdEnded}", torrent); - + // Check if all the links are set that have been selected if (torrent.Files.Count(m => m.Selected) == downloadLinks.Count) { @@ -396,7 +305,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien } Log($"Did not find any suiteable download links", torrent); - + return null; } @@ -410,11 +319,11 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien return dateTimeOffset?.Subtract(_offset.Value).ToOffset(_offset.Value); } - private async Task GetInfo(String torrentId) + private async Task GetInfo(String torrentHash) { - var result = await GetClient().Torrents.GetInfoAsync(torrentId); + var result = await GetClient().Torrents.GetInfoAsync(torrentHash); - return Map(result); + return Map(result!); } private void Log(String message, Data.Models.Data.Torrent? torrent = null) From 395f83847e0badaa7e1d3e34e5d458f07a7ec29f Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Tue, 27 Aug 2024 19:11:24 +1000 Subject: [PATCH 03/31] Add Getting DL link, tracking via hash --- .../TorrentClients/TorBoxTorrentClient.cs | 64 ++++--------------- 1 file changed, 13 insertions(+), 51 deletions(-) diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 81935a7..fb65098 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -127,14 +127,14 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien { var result = await GetClient().Torrents.AddMagnetAsync(magnetLink); - return result.Data?.Torrent_ID.ToString()!; + return result.Data?.Hash?.ToString()!; } public async Task AddFile(Byte[] bytes) { var result = await GetClient().Torrents.AddFileAsync(bytes); - return result.Data?.Torrent_ID.ToString()!; + return result.Data?.Hash?.ToString()!; } public Task> GetAvailableFiles(String hash) @@ -157,12 +157,12 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien { var result = await GetClient().Unrestrict.LinkAsync(link); - if (result.Download == null) + if (result.Error != null) { throw new($"Unrestrict returned an invalid download"); } - return result.Download; + return result.Data!; } public async Task UpdateData(Data.Models.Data.Torrent torrent, TorrentClientTorrent? torrentClientTorrent) @@ -250,63 +250,25 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task?> GetDownloadLinks(Data.Models.Data.Torrent torrent) { - if (torrent.RdId == null) + if (torrent.Hash == null) { return null; } - var rdTorrent = await GetInfo(torrent.RdId); + var rdTorrent = await GetInfo(torrent.Hash); - if (rdTorrent.Links == null) + var files = new List(); + + if (rdTorrent.Files?.Count != 0) { - return null; - } - - var downloadLinks = rdTorrent.Links.Where(m => !String.IsNullOrWhiteSpace(m)).ToList(); - - Log($"Found {downloadLinks.Count} links", torrent); - - foreach (var link in downloadLinks) - { - Log($"{link}", torrent); - } - - Log($"Torrent has {torrent.Files.Count(m => m.Selected)} selected files out of {torrent.Files.Count} files, found {downloadLinks.Count} links, torrent ended: {torrent.RdEnded}", torrent); - - // Check if all the links are set that have been selected - if (torrent.Files.Count(m => m.Selected) == downloadLinks.Count) - { - Log($"Matched {torrent.Files.Count(m => m.Selected)} selected files expected files to {downloadLinks.Count} found files", torrent); - - return downloadLinks; - } - - // Check if all all the links are set for manual selection - if (torrent.ManualFiles.Count == downloadLinks.Count) - { - Log($"Matched {torrent.ManualFiles.Count} manual files expected files to {downloadLinks.Count} found files", torrent); - - return downloadLinks; - } - - // If there is only 1 link, delay for 1 minute to see if more links pop up. - if (downloadLinks.Count == 1 && torrent.RdEnded.HasValue) - { - var expired = DateTime.UtcNow - torrent.RdEnded.Value.ToUniversalTime(); - - Log($"Waiting to see if more links appear, checked for {expired.TotalSeconds} seconds", torrent); - - if (expired.TotalSeconds > 60.0) + foreach (var file in rdTorrent.Files!) { - Log($"Waited long enough", torrent); - - return downloadLinks; + var newFile = new List { rdTorrent.Id, file.Id.ToString() }; + files.Add(newFile.ToString()!); } } - Log($"Did not find any suiteable download links", torrent); - - return null; + return files; } private DateTimeOffset? ChangeTimeZone(DateTimeOffset? dateTimeOffset) From c34f91fc2777a30ea3f96ca2e3a2c156f23a88db Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:05:56 +1000 Subject: [PATCH 04/31] Add UI elements for TorBox, fix downloads. --- .../add-new-torrent.component.html | 7 +++- client/src/app/navbar/navbar.component.ts | 11 +++++- client/src/app/setup/setup.component.html | 8 +++- server/RdtClient.Data/Enums/Provider.cs | 5 ++- .../Models/Internal/DbSettings.cs | 7 +++- server/RdtClient.Service/DiConfig.cs | 1 + .../Helpers/DownloadHelper.cs | 39 +++++++++++++++++-- .../RdtClient.Service.csproj | 2 +- .../Services/DownloadClient.cs | 10 ++--- .../TorrentClients/TorBoxTorrentClient.cs | 26 +++++++------ server/RdtClient.Service/Services/Torrents.cs | 6 ++- .../Services/UnpackClient.cs | 2 +- 12 files changed, 92 insertions(+), 32 deletions(-) diff --git a/client/src/app/add-new-torrent/add-new-torrent.component.html b/client/src/app/add-new-torrent/add-new-torrent.component.html index ed6a853..a083d1d 100644 --- a/client/src/app/add-new-torrent/add-new-torrent.component.html +++ b/client/src/app/add-new-torrent/add-new-torrent.component.html @@ -74,7 +74,10 @@
- @@ -82,7 +85,7 @@

When a torrent is fully downloaded on the provider, perform this action.

- This option is only available for RealDebrid. AllDebrid and Premiumize will always download the full torrent. + This option is only available for RealDebrid. AllDebrid, Premiumize, and Torbox will always download the full torrent.

diff --git a/client/src/app/navbar/navbar.component.ts b/client/src/app/navbar/navbar.component.ts index c47e2b9..95c8067 100644 --- a/client/src/app/navbar/navbar.component.ts +++ b/client/src/app/navbar/navbar.component.ts @@ -15,7 +15,11 @@ export class NavbarComponent implements OnInit { public profile: Profile; public providerLink: string; - constructor(private settingsService: SettingsService, private authService: AuthService, private router: Router) {} + constructor( + private settingsService: SettingsService, + private authService: AuthService, + private router: Router, + ) {} ngOnInit(): void { this.settingsService.getProfile().subscribe((result) => { @@ -31,6 +35,9 @@ export class NavbarComponent implements OnInit { case 'Premiumize': this.providerLink = 'https://www.premiumize.me/'; break; + case 'TorBox': + this.providerLink = 'https://torbox.app/'; + break; } }); } @@ -40,7 +47,7 @@ export class NavbarComponent implements OnInit { () => { this.router.navigate(['/login']); }, - (err) => {} + (err) => {}, ); } } diff --git a/client/src/app/setup/setup.component.html b/client/src/app/setup/setup.component.html index 3de49e5..c794ba9 100644 --- a/client/src/app/setup/setup.component.html +++ b/client/src/app/setup/setup.component.html @@ -42,7 +42,7 @@
To be able to use the Real-Debrid Client you need a premium subscription to download torrents.

- Not premium yet? You have the choice of 2 providers: + Not premium yet? You have the choice of 4 providers:
Use this link to sign up to Real-Debrid.Use this link to sign up to Premiumize. + Use this link to sign up to Premiumize.
(Referal links)
@@ -65,6 +66,7 @@ + @@ -91,6 +93,10 @@ >https://www.premiumize.me/account.

+

+ You can find your API key here: + https://torbox.app/settings. +

diff --git a/server/RdtClient.Data/Enums/Provider.cs b/server/RdtClient.Data/Enums/Provider.cs index 7422663..ff372dc 100644 --- a/server/RdtClient.Data/Enums/Provider.cs +++ b/server/RdtClient.Data/Enums/Provider.cs @@ -11,5 +11,8 @@ public enum Provider AllDebrid, [Description("Premiumize")] - Premiumize + Premiumize, + + [Description("TorBox")] + TorBox } \ No newline at end of file diff --git a/server/RdtClient.Data/Models/Internal/DbSettings.cs b/server/RdtClient.Data/Models/Internal/DbSettings.cs index 10381fd..ee58bb5 100644 --- a/server/RdtClient.Data/Models/Internal/DbSettings.cs +++ b/server/RdtClient.Data/Models/Internal/DbSettings.cs @@ -140,10 +140,11 @@ http://127.0.0.1:6800/jsonrpc.")] public class DbSettingsProvider { [DisplayName("Provider")] - [Description(@"The following 3 providers are supported: + [Description(@"The following 4 providers are supported: https://real-debrid.com https://alldebrid.com https://www.premiumize.me/ +https://torbox.app/ At this point only 1 provider can be used at the time.")] public Provider Provider { get; set; } = Provider.RealDebrid; @@ -153,7 +154,9 @@ At this point only 1 provider can be used at the time.")] or https://alldebrid.com/apikeys/ or -https://www.premiumize.me/account/")] +https://www.premiumize.me/account/ +or +https://torbox.app/settings/")] public String ApiKey { get; set; } = ""; [DisplayName("Automatically import and process torrents added to provider")] diff --git a/server/RdtClient.Service/DiConfig.cs b/server/RdtClient.Service/DiConfig.cs index e5f7aa2..695443f 100644 --- a/server/RdtClient.Service/DiConfig.cs +++ b/server/RdtClient.Service/DiConfig.cs @@ -24,6 +24,7 @@ public static class DiConfig services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/server/RdtClient.Service/Helpers/DownloadHelper.cs b/server/RdtClient.Service/Helpers/DownloadHelper.cs index 0c9a1c4..aaa04c0 100644 --- a/server/RdtClient.Service/Helpers/DownloadHelper.cs +++ b/server/RdtClient.Service/Helpers/DownloadHelper.cs @@ -1,11 +1,14 @@ -using System.Web; +using System; +using System.Web; +using RdtClient.Data.Enums; using RdtClient.Data.Models.Data; +using RdtClient.Service.Services; namespace RdtClient.Service.Helpers; public static class DownloadHelper { - public static String? GetDownloadPath(String downloadPath, Torrent torrent, Download download) + public static async Task GetDownloadPath(String downloadPath, Torrent torrent, Download download) { var fileUrl = download.Link; @@ -21,6 +24,20 @@ public static class DownloadHelper var fileName = uri.Segments.Last(); + if (Settings.Get.Provider.Provider == Provider.TorBox) + { + using (HttpClient client = new HttpClient()) + { + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Head, uri); + HttpResponseMessage response = await client.SendAsync(request); + + if (response.Content.Headers.ContentDisposition != null) + { + fileName = response.Content.Headers.ContentDisposition.FileName!.Trim('"'); + } + } + } + fileName = HttpUtility.UrlDecode(fileName); fileName = FileHelper.RemoveInvalidFileNameChars(fileName); @@ -48,10 +65,12 @@ public static class DownloadHelper var filePath = Path.Combine(torrentPath, fileName); + Console.WriteLine($"FILEPATH HERE {filePath}"); + return filePath; } - public static String? GetDownloadPath(Torrent torrent, Download download) + public static async Task GetDownloadPath(Torrent torrent, Download download) { var fileUrl = download.Link; @@ -65,6 +84,20 @@ public static class DownloadHelper var fileName = uri.Segments.Last(); + if (Settings.Get.Provider.Provider == Provider.TorBox) + { + using (HttpClient client = new HttpClient()) + { + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Head, uri); + HttpResponseMessage response = await client.SendAsync(request); + + if (response.Content.Headers.ContentDisposition != null) + { + fileName = response.Content.Headers.ContentDisposition.FileName!.Trim('"'); + } + } + } + fileName = HttpUtility.UrlDecode(fileName); fileName = FileHelper.RemoveInvalidFileNameChars(fileName); diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index 2c5daa6..6d43ec2 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -22,7 +22,7 @@ - + diff --git a/server/RdtClient.Service/Services/DownloadClient.cs b/server/RdtClient.Service/Services/DownloadClient.cs index b8a268d..51220cf 100644 --- a/server/RdtClient.Service/Services/DownloadClient.cs +++ b/server/RdtClient.Service/Services/DownloadClient.cs @@ -39,16 +39,16 @@ public class DownloadClient(Download download, Torrent torrent, String destinati throw new("Invalid download path"); } - await FileHelper.Delete(filePath); + await FileHelper.Delete(filePath.Result!); Type = torrent.DownloadClient; Downloader = Type switch { - Data.Enums.DownloadClient.Internal => new InternalDownloader(download.Link, filePath), - Data.Enums.DownloadClient.Bezzad => new BezzadDownloader(download.Link, filePath), - Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(download.RemoteId, download.Link, filePath, downloadPath, category), - Data.Enums.DownloadClient.Symlink => new SymlinkDownloader(download.Link, filePath, downloadPath), + Data.Enums.DownloadClient.Internal => new InternalDownloader(download.Link, filePath.Result!), + Data.Enums.DownloadClient.Bezzad => new BezzadDownloader(download.Link, filePath.Result!), + Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(download.RemoteId, download.Link, filePath.Result!, downloadPath.Result!, category), + Data.Enums.DownloadClient.Symlink => new SymlinkDownloader(download.Link, filePath.Result!, downloadPath.Result!), _ => throw new($"Unknown download client {Type}") }; diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index fb65098..1d031f0 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -1,12 +1,10 @@ -using System.Text.RegularExpressions; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using TorBoxNET; using RdtClient.Data.Enums; using RdtClient.Data.Models.TorrentClient; using RdtClient.Service.Helpers; -using Microsoft.AspNetCore.Mvc.RazorPages; -using System.Diagnostics.Eventing.Reader; +using Microsoft.AspNetCore.Routing.Constraints; namespace RdtClient.Service.Services.TorrentClients; @@ -80,7 +78,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien Added = ChangeTimeZone(torrent.CreatedAt)!.Value, Files = (torrent.Files ?? []).Select(m => new TorrentClientFile { - Path = m.S3Path.Replace(m.Hash + "/", string.Empty), + Path = string.Join("/", m.Name.Split('/').Skip(1)), Bytes = m.Size, Id = m.Id, Selected = true @@ -125,14 +123,14 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task AddMagnet(String magnetLink) { - var result = await GetClient().Torrents.AddMagnetAsync(magnetLink); + var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, seeding: 3); return result.Data?.Hash?.ToString()!; } public async Task AddFile(Byte[] bytes) { - var result = await GetClient().Torrents.AddFileAsync(bytes); + var result = await GetClient().Torrents.AddFileAsync(bytes, seeding: 3); return result.Data?.Hash?.ToString()!; } @@ -155,7 +153,10 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task Unrestrict(String link) { - var result = await GetClient().Unrestrict.LinkAsync(link); + var torrentFile = new List(link.Split('/')); + var torrentID = torrentFile[4]; + var fileID = torrentFile[5]; + var result = await GetClient().Unrestrict.LinkAsync(torrentID, fileID); if (result.Error != null) { @@ -219,12 +220,13 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien { "queued" => TorrentStatus.Processing, "metaDL" => TorrentStatus.Processing, + "checking" => TorrentStatus.Processing, "checkingResumeData" => TorrentStatus.Processing, "paused" => TorrentStatus.Downloading, "downloading" => TorrentStatus.Downloading, "completed" => TorrentStatus.Downloading, - "uploading" => TorrentStatus.Downloading, - "uploading (no peers)" => TorrentStatus.Downloading, + "uploading" => TorrentStatus.Finished, + "uploading (no peers)" => TorrentStatus.Finished, "stalled" => TorrentStatus.Downloading, "stalled (no seeds)" => TorrentStatus.Downloading, "cached" => TorrentStatus.Finished, @@ -263,8 +265,8 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien { foreach (var file in rdTorrent.Files!) { - var newFile = new List { rdTorrent.Id, file.Id.ToString() }; - files.Add(newFile.ToString()!); + var newFile = $"https://torbox.app/fakedl/{rdTorrent.Id}/{file.Id}"; + files.Add(newFile); } } @@ -283,7 +285,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien private async Task GetInfo(String torrentHash) { - var result = await GetClient().Torrents.GetInfoAsync(torrentHash); + var result = await GetClient().Torrents.GetInfoAsync(torrentHash, skipCache: true); return Map(result!); } diff --git a/server/RdtClient.Service/Services/Torrents.cs b/server/RdtClient.Service/Services/Torrents.cs index cc39252..3053891 100644 --- a/server/RdtClient.Service/Services/Torrents.cs +++ b/server/RdtClient.Service/Services/Torrents.cs @@ -22,7 +22,8 @@ public class Torrents( Downloads downloads, AllDebridTorrentClient allDebridTorrentClient, PremiumizeTorrentClient premiumizeTorrentClient, - RealDebridTorrentClient realDebridTorrentClient) + RealDebridTorrentClient realDebridTorrentClient, + TorBoxTorrentClient torBoxTorrentClient) { private static readonly SemaphoreSlim RealDebridUpdateLock = new(1, 1); @@ -40,6 +41,7 @@ public class Torrents( Provider.Premiumize => premiumizeTorrentClient, Provider.RealDebrid => realDebridTorrentClient, Provider.AllDebrid => allDebridTorrentClient, + Provider.TorBox => torBoxTorrentClient, _ => throw new("Invalid Provider") }; } @@ -551,7 +553,7 @@ public class Torrents( { Log($"Deleting {filePath}", download, download.Torrent); - await FileHelper.Delete(filePath); + await FileHelper.Delete(filePath.Result!); } Log($"Resetting", download, download.Torrent); diff --git a/server/RdtClient.Service/Services/UnpackClient.cs b/server/RdtClient.Service/Services/UnpackClient.cs index 2724f43..c702d71 100644 --- a/server/RdtClient.Service/Services/UnpackClient.cs +++ b/server/RdtClient.Service/Services/UnpackClient.cs @@ -31,7 +31,7 @@ public class UnpackClient(Download download, String destinationPath) { if (!_cancellationTokenSource.IsCancellationRequested) { - await Unpack(filePath, _cancellationTokenSource.Token); + await Unpack(filePath.Result!, _cancellationTokenSource.Token); } }); } From 754588091d44c59d13dddf9f07b64dde8abd817a Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Thu, 29 Aug 2024 07:16:54 +1000 Subject: [PATCH 05/31] Fix seeding --- .../Services/TorrentClients/TorBoxTorrentClient.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 1d031f0..30dd54d 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -123,14 +123,14 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task AddMagnet(String magnetLink) { - var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, seeding: 3); + var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, seeding: 2); return result.Data?.Hash?.ToString()!; } public async Task AddFile(Byte[] bytes) { - var result = await GetClient().Torrents.AddFileAsync(bytes, seeding: 3); + var result = await GetClient().Torrents.AddFileAsync(bytes, seeding: 2); return result.Data?.Hash?.ToString()!; } @@ -210,7 +210,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien torrent.RdSeeders = rdTorrent.Seeders; torrent.RdStatusRaw = rdTorrent.Status; - if (rdTorrent.Host == "true") + if (rdTorrent.Host == "True") { torrent.RdStatus = TorrentStatus.Finished; } @@ -225,8 +225,8 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien "paused" => TorrentStatus.Downloading, "downloading" => TorrentStatus.Downloading, "completed" => TorrentStatus.Downloading, - "uploading" => TorrentStatus.Finished, - "uploading (no peers)" => TorrentStatus.Finished, + "uploading" => TorrentStatus.Downloading, + "uploading (no peers)" => TorrentStatus.Downloading, "stalled" => TorrentStatus.Downloading, "stalled (no seeds)" => TorrentStatus.Downloading, "cached" => TorrentStatus.Finished, From 183798db2d79b4cb00deb8daa6b4e44bed850344 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Fri, 30 Aug 2024 17:26:53 +1000 Subject: [PATCH 06/31] Fix TorBox GetAvailability Won't display anything in the UI though as its set to only show available files for RD --- .../RdtClient.Service.csproj | 2 +- .../TorrentClients/TorBoxTorrentClient.cs | 30 +++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index 6d43ec2..71d18a9 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -22,7 +22,7 @@ - + diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 30dd54d..6cf14d8 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -135,10 +135,30 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien return result.Data?.Hash?.ToString()!; } - public Task> GetAvailableFiles(String hash) + public async Task> GetAvailableFiles(String hash) { - var result = new List(); - return Task.FromResult>(result); + var availability = await GetClient().Torrents.GetAvailabilityAsync(hash, listFiles: true); + + if (availability.Data != null) + { + var availableFiles = new List(); + foreach (var file in availability.Data[0]?.Files!) + { + availableFiles.Add( + new TorrentClientAvailableFile + { + Filename = file!.Name, + Filesize = file.Size + }); + } + return availableFiles; + } + else + { + return []; + } + + } public Task SelectFiles(Data.Models.Data.Torrent torrent) @@ -213,7 +233,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien if (rdTorrent.Host == "True") { torrent.RdStatus = TorrentStatus.Finished; - } + } else { torrent.RdStatus = rdTorrent.Status switch @@ -233,7 +253,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien _ => TorrentStatus.Error }; } - + } catch (Exception ex) { From e60059a5bd38a3e0c6409906a7a473b2ad988dc3 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Sat, 31 Aug 2024 10:17:27 +1000 Subject: [PATCH 07/31] Fix deleting torrents from provider --- server/RdtClient.Service/RdtClient.Service.csproj | 2 +- .../Services/TorrentClients/TorBoxTorrentClient.cs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index 71d18a9..16c826c 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -22,7 +22,7 @@ - + diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 6cf14d8..9d8a57b 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -168,15 +168,13 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task Delete(String torrentId) { - await GetClient().Torrents.ControlAsync(Convert.ToInt32(torrentId), "delete"); + await GetClient().Torrents.ControlAsync(torrentId, "delete"); } public async Task Unrestrict(String link) { var torrentFile = new List(link.Split('/')); - var torrentID = torrentFile[4]; - var fileID = torrentFile[5]; - var result = await GetClient().Unrestrict.LinkAsync(torrentID, fileID); + var result = await GetClient().Unrestrict.LinkAsync(torrentID: torrentFile[4], fileID: torrentFile[5]); if (result.Error != null) { From e20dd84e1d4352edf033a34319bbdb3b9d514d72 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Sat, 31 Aug 2024 19:27:20 +1000 Subject: [PATCH 08/31] Fix adding torrent via file it was a reference conflict between System.Io.File and TorBoxNet.File, but committing anyways to make sure i don't forget that i fixed it --- server/RdtClient.Service/RdtClient.Service.csproj | 2 +- .../Services/TorrentClients/TorBoxTorrentClient.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index 16c826c..97a68fc 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -22,7 +22,7 @@ - + diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 9d8a57b..c5529b8 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -104,7 +104,6 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien if (queuedTorrents != null) { torrents.AddRange(queuedTorrents); - } return torrents!.Select(Map).ToList(); From 91dcdb9d7c4f2cdf475f30180845b04a382f60fd Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Sun, 1 Sep 2024 16:25:36 +1000 Subject: [PATCH 09/31] Fix importing from TorBox, adding queued torrents --- .../RdtClient.Service.csproj | 2 +- .../TorrentClients/TorBoxTorrentClient.cs | 36 ++++++++++++++----- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index 97a68fc..fba85e6 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -22,7 +22,7 @@ - + diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index c5529b8..3671be3 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -4,7 +4,7 @@ using TorBoxNET; using RdtClient.Data.Enums; using RdtClient.Data.Models.TorrentClient; using RdtClient.Service.Helpers; -using Microsoft.AspNetCore.Routing.Constraints; +using MonoTorrent; namespace RdtClient.Service.Services.TorrentClients; @@ -61,11 +61,11 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien } } - private TorrentClientTorrent Map(Torrent torrent) + private TorrentClientTorrent Map(TorrentInfoResult torrent) { return new() { - Id = torrent.Id.ToString(), + Id = torrent.Hash, Filename = torrent.Name, OriginalFilename = torrent.Name, Hash = torrent.Hash, @@ -92,7 +92,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task> GetTorrents() { - var torrents = new List(); + var torrents = new List(); var currentTorrents = await GetClient().Torrents.GetCurrentAsync(true); if (currentTorrents != null) @@ -124,14 +124,31 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien { var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, seeding: 2); - return result.Data?.Hash?.ToString()!; + if (result.Error == "ACTIVE_LIMIT") + { + var magnetLinkInfo = MonoTorrent.MagnetLink.Parse(magnetLink); + return magnetLinkInfo.InfoHash.ToHex().ToLowerInvariant(); + } + else + { + return result.Data!.Hash!; + } } public async Task AddFile(Byte[] bytes) { var result = await GetClient().Torrents.AddFileAsync(bytes, seeding: 2); - - return result.Data?.Hash?.ToString()!; + if (result.Error == "ACTIVE_LIMIT") + { + using (var stream = new MemoryStream(bytes)) + { + var torrent = MonoTorrent.Torrent.Load(stream); + return torrent!.InfoHash.ToHex()!.ToLowerInvariant(); + } + } else + { + return result.Data!.Hash!; + } } public async Task> GetAvailableFiles(String hash) @@ -275,14 +292,15 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien } var rdTorrent = await GetInfo(torrent.Hash); - var files = new List(); + var torrentId = await GetClient().Torrents.GetInfoAsync(torrent.Hash, skipCache: true); + if (rdTorrent.Files?.Count != 0) { foreach (var file in rdTorrent.Files!) { - var newFile = $"https://torbox.app/fakedl/{rdTorrent.Id}/{file.Id}"; + var newFile = $"https://torbox.app/fakedl/{torrentId?.Id}/{file.Id}"; files.Add(newFile); } } From 70584d1acb49d32227142482624d8f6b2758a379 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Sun, 1 Sep 2024 19:46:05 +1000 Subject: [PATCH 10/31] Add DB values for seeding and zipped, pass to addtorrent --- client/src/app/setup/setup.component.html | 3 ++- server/RdtClient.Data/Models/Internal/DbSettings.cs | 8 ++++++++ .../Services/TorrentClients/TorBoxTorrentClient.cs | 12 +++++++----- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/client/src/app/setup/setup.component.html b/client/src/app/setup/setup.component.html index c794ba9..643e618 100644 --- a/client/src/app/setup/setup.component.html +++ b/client/src/app/setup/setup.component.html @@ -55,7 +55,8 @@ Use this link to sign up to Premiumize. - Use this link to sign up to Premiumize. + Use this link to sign up to TorBox.
(Referal links)
diff --git a/server/RdtClient.Data/Models/Internal/DbSettings.cs b/server/RdtClient.Data/Models/Internal/DbSettings.cs index ee58bb5..1f014ad 100644 --- a/server/RdtClient.Data/Models/Internal/DbSettings.cs +++ b/server/RdtClient.Data/Models/Internal/DbSettings.cs @@ -263,4 +263,12 @@ public class DbSettingsDefaults [DisplayName("Priority")] [Description("Set the priority of a torrent, 1 = highest, 0 = disabled.")] public Int32 Priority { get; set; } = 0; + + [DisplayName("Seeding")] + [Description("Set the priority of a torrent, 1 = Auto, 2 = Seed, 3 = disabled. [TorBox Only]")] + public Int32 Seeding { get; set; } = 3; + + [DisplayName("Download as Zip")] + [Description("Whether to download the files individually or zipped. [TorBox Only]")] + public bool Zipped { get; set; } = true; } \ No newline at end of file diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 3671be3..5879ef4 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -4,14 +4,14 @@ using TorBoxNET; using RdtClient.Data.Enums; using RdtClient.Data.Models.TorrentClient; using RdtClient.Service.Helpers; -using MonoTorrent; +using RdtClient.Data.Models.Internal; namespace RdtClient.Service.Services.TorrentClients; public class TorBoxTorrentClient(ILogger logger, IHttpClientFactory httpClientFactory) : ITorrentClient { private TimeSpan? _offset; - + private DbSettingsDefaults _dbSettings = new DbSettingsDefaults(); private TorBoxNetClient GetClient() { try @@ -122,7 +122,8 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task AddMagnet(String magnetLink) { - var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, seeding: 2); + + var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, _dbSettings.Seeding, _dbSettings.Zipped); if (result.Error == "ACTIVE_LIMIT") { @@ -137,7 +138,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task AddFile(Byte[] bytes) { - var result = await GetClient().Torrents.AddFileAsync(bytes, seeding: 2); + var result = await GetClient().Torrents.AddFileAsync(bytes, _dbSettings.Seeding, _dbSettings.Zipped); if (result.Error == "ACTIVE_LIMIT") { using (var stream = new MemoryStream(bytes)) @@ -145,7 +146,8 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien var torrent = MonoTorrent.Torrent.Load(stream); return torrent!.InfoHash.ToHex()!.ToLowerInvariant(); } - } else + } + else { return result.Data!.Hash!; } From 320c52c4bea9b844dbbefd59b9d298955a6cd765 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Wed, 4 Sep 2024 17:14:36 +1000 Subject: [PATCH 11/31] Handle zipped DL only w/ file count > 100 --- .../Models/Internal/DbSettings.cs | 16 ++++----- .../RdtClient.Service.csproj | 2 +- .../TorrentClients/TorBoxTorrentClient.cs | 35 ++++++++++++------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/server/RdtClient.Data/Models/Internal/DbSettings.cs b/server/RdtClient.Data/Models/Internal/DbSettings.cs index 1f014ad..c7d4cf1 100644 --- a/server/RdtClient.Data/Models/Internal/DbSettings.cs +++ b/server/RdtClient.Data/Models/Internal/DbSettings.cs @@ -177,6 +177,14 @@ or [DisplayName("Auto Import Defaults")] public DbSettingsDefaultsWithCategory Default { get; set; } = new(); + + [DisplayName("Seeding")] + [Description("Set the priority of a torrent, 1 = Auto, 2 = Seed, 3 = disabled. [TorBox Only]")] + public Int32 Seeding { get; set; } = 3; + + [DisplayName("Download as Zip")] + [Description("Whether to download the files individually or zipped. [TorBox Only]")] + public bool Zipped { get; set; } = true; } public class DbSettingsIntegrations @@ -263,12 +271,4 @@ public class DbSettingsDefaults [DisplayName("Priority")] [Description("Set the priority of a torrent, 1 = highest, 0 = disabled.")] public Int32 Priority { get; set; } = 0; - - [DisplayName("Seeding")] - [Description("Set the priority of a torrent, 1 = Auto, 2 = Seed, 3 = disabled. [TorBox Only]")] - public Int32 Seeding { get; set; } = 3; - - [DisplayName("Download as Zip")] - [Description("Whether to download the files individually or zipped. [TorBox Only]")] - public bool Zipped { get; set; } = true; } \ No newline at end of file diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index fba85e6..ed3e98b 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -22,7 +22,7 @@ - +
diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 5879ef4..830842b 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -4,14 +4,12 @@ using TorBoxNET; using RdtClient.Data.Enums; using RdtClient.Data.Models.TorrentClient; using RdtClient.Service.Helpers; -using RdtClient.Data.Models.Internal; namespace RdtClient.Service.Services.TorrentClients; public class TorBoxTorrentClient(ILogger logger, IHttpClientFactory httpClientFactory) : ITorrentClient { private TimeSpan? _offset; - private DbSettingsDefaults _dbSettings = new DbSettingsDefaults(); private TorBoxNetClient GetClient() { try @@ -122,8 +120,9 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task AddMagnet(String magnetLink) { - - var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, _dbSettings.Seeding, _dbSettings.Zipped); + var seeding = Settings.Get.Provider.Seeding; + var zipped = Settings.Get.Provider.Zipped; + var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, seeding, zipped); if (result.Error == "ACTIVE_LIMIT") { @@ -138,7 +137,9 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task AddFile(Byte[] bytes) { - var result = await GetClient().Torrents.AddFileAsync(bytes, _dbSettings.Seeding, _dbSettings.Zipped); + var seeding = Settings.Get.Provider.Seeding; + var zipped = Settings.Get.Provider.Zipped; + var result = await GetClient().Torrents.AddFileAsync(bytes, seeding, zipped); if (result.Error == "ACTIVE_LIMIT") { using (var stream = new MemoryStream(bytes)) @@ -189,17 +190,21 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien await GetClient().Torrents.ControlAsync(torrentId, "delete"); } - public async Task Unrestrict(String link) + public async Task Unrestrict(string link) { - var torrentFile = new List(link.Split('/')); - var result = await GetClient().Unrestrict.LinkAsync(torrentID: torrentFile[4], fileID: torrentFile[5]); + var segments = link.Split('/'); - if (result.Error != null) + bool zipped = segments[5] == "zip"; + string fileId = zipped ? "0" : segments[5]; + + var result = await GetClient().Unrestrict.LinkAsync(torrentID: segments[4], fileID: fileId, zipped: zipped); + + if (result?.Error != null) { - throw new($"Unrestrict returned an invalid download"); + throw new("Unrestrict returned an invalid download"); } - return result.Data!; + return result!.Data!; } public async Task UpdateData(Data.Models.Data.Torrent torrent, TorrentClientTorrent? torrentClientTorrent) @@ -297,8 +302,12 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien var files = new List(); var torrentId = await GetClient().Torrents.GetInfoAsync(torrent.Hash, skipCache: true); - - if (rdTorrent.Files?.Count != 0) + if (Settings.Get.Provider.Zipped == true && rdTorrent.Files!.Count() > 100 && torrentId!.AllowZipped == true) + { + var newFile = $"https://torbox.app/fakedl/{torrentId?.Id}/zip"; + files.Add(newFile); + } + else if (rdTorrent.Files?.Count != 0) { foreach (var file in rdTorrent.Files!) { From 6bac21b4264ffd0394bbf82de3cd9208cce79160 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Mon, 9 Sep 2024 22:07:18 +1000 Subject: [PATCH 12/31] Update for TorBoxNET v1.0.0.42 changes --- .../Services/TorrentClients/TorBoxTorrentClient.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 830842b..72868fb 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -30,7 +30,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien // Get the server time to fix up the timezones on results if (_offset == null) { - var serverTime = rdtNetClient.Api.GetIsoTimeAsync(); + var serverTime = DateTimeOffset.UtcNow; _offset = serverTime.Offset; } @@ -127,7 +127,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien if (result.Error == "ACTIVE_LIMIT") { var magnetLinkInfo = MonoTorrent.MagnetLink.Parse(magnetLink); - return magnetLinkInfo.InfoHash.ToHex().ToLowerInvariant(); + return magnetLinkInfo.InfoHashes.V1!.ToHex().ToLowerInvariant(); } else { @@ -145,7 +145,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien using (var stream = new MemoryStream(bytes)) { var torrent = MonoTorrent.Torrent.Load(stream); - return torrent!.InfoHash.ToHex()!.ToLowerInvariant(); + return torrent!.InfoHashes.V1!.ToHex().ToLowerInvariant(); } } else @@ -197,7 +197,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien bool zipped = segments[5] == "zip"; string fileId = zipped ? "0" : segments[5]; - var result = await GetClient().Unrestrict.LinkAsync(torrentID: segments[4], fileID: fileId, zipped: zipped); + var result = await GetClient().Torrents.RequestDownloadAsync(Convert.ToInt32(segments[4]), Convert.ToInt32(fileId), zipped); if (result?.Error != null) { @@ -302,7 +302,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien var files = new List(); var torrentId = await GetClient().Torrents.GetInfoAsync(torrent.Hash, skipCache: true); - if (Settings.Get.Provider.Zipped == true && rdTorrent.Files!.Count() > 100 && torrentId!.AllowZipped == true) + if (Settings.Get.Provider.Zipped == true) { var newFile = $"https://torbox.app/fakedl/{torrentId?.Id}/zip"; files.Add(newFile); From 446b1c0180c43373c23a90f39d183ea8dada1ea4 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Mon, 9 Sep 2024 22:41:20 +1000 Subject: [PATCH 13/31] Fix error from merge from upstream, fix error on processing --- server/RdtClient.Data/Models/Internal/DbSettings.cs | 2 +- server/RdtClient.Service/Helpers/DownloadHelper.cs | 2 -- server/RdtClient.Service/RdtClient.Service.csproj | 2 +- server/RdtClient.Service/Services/DownloadClient.cs | 2 +- .../Services/TorrentClients/TorBoxTorrentClient.cs | 1 + 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/server/RdtClient.Data/Models/Internal/DbSettings.cs b/server/RdtClient.Data/Models/Internal/DbSettings.cs index c7d4cf1..2c45ec8 100644 --- a/server/RdtClient.Data/Models/Internal/DbSettings.cs +++ b/server/RdtClient.Data/Models/Internal/DbSettings.cs @@ -123,7 +123,7 @@ http://127.0.0.1:6800/jsonrpc.")] [DisplayName("Aria2c Secret (only used for the Aria2c Downloader)")] [Description("The secret of your Aria2c instance. Optional.")] public String Aria2cSecret { get; set; } = "mysecret123"; - + [DisplayName("Aria2c Download Path")] [Description("The root path to download the file to on the Aria2c host, if empty use the Download path setting.")] public String? Aria2cDownloadPath { get; set; } = null; diff --git a/server/RdtClient.Service/Helpers/DownloadHelper.cs b/server/RdtClient.Service/Helpers/DownloadHelper.cs index 84e81c2..c427ac1 100644 --- a/server/RdtClient.Service/Helpers/DownloadHelper.cs +++ b/server/RdtClient.Service/Helpers/DownloadHelper.cs @@ -65,8 +65,6 @@ public static class DownloadHelper var filePath = Path.Combine(torrentPath, fileName); - Console.WriteLine($"FILEPATH HERE {filePath}"); - return filePath; } diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index 51824c1..d7e692e 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -22,7 +22,7 @@ - + diff --git a/server/RdtClient.Service/Services/DownloadClient.cs b/server/RdtClient.Service/Services/DownloadClient.cs index 0d33bab..d5faf3d 100644 --- a/server/RdtClient.Service/Services/DownloadClient.cs +++ b/server/RdtClient.Service/Services/DownloadClient.cs @@ -43,7 +43,7 @@ public class DownloadClient(Download download, Torrent torrent, String destinati if (Type != Data.Enums.DownloadClient.Symlink) { - await FileHelper.Delete(filePath); + await FileHelper.Delete(filePath.Result!); } Downloader = Type switch diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 72868fb..985a5be 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -270,6 +270,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien "uploading (no peers)" => TorrentStatus.Downloading, "stalled" => TorrentStatus.Downloading, "stalled (no seeds)" => TorrentStatus.Downloading, + "processing" => TorrentStatus.Downloading, "cached" => TorrentStatus.Finished, _ => TorrentStatus.Error }; From 194b9fd2a3e0b120aefb3da8cdbefdaa23407d8d Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Fri, 13 Sep 2024 15:54:03 +1000 Subject: [PATCH 14/31] Update TorBox.NET to 1.0.1 --- client/package-lock.json | 338 ++---------------- client/package.json | 4 +- .../RdtClient.Service.csproj | 2 +- 3 files changed, 36 insertions(+), 308 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 7b63b6f..b6d1ede 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -35,7 +35,7 @@ "@angular-eslint/eslint-plugin-template": "16.1.1", "@angular-eslint/schematics": "16.1.1", "@angular-eslint/template-parser": "16.1.1", - "@angular/cli": "^16.2.14", + "@angular/cli": "^16.2.1", "@angular/compiler-cli": "^16.2.3", "@angular/language-service": "^16.2.3", "@types/file-saver": "^2.0.5", @@ -352,12 +352,12 @@ "dev": true }, "node_modules/@angular-devkit/schematics": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.14.tgz", - "integrity": "sha512-B6LQKInCT8w5zx5Pbroext5eFFRTCJdTwHN8GhcVS8IeKCnkeqVTQLjB4lBUg7LEm8Y7UHXwzrVxmk+f+MBXhw==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.1.tgz", + "integrity": "sha512-rXXO5zSI/iN6JtU3oU+vKfOB1N8n1iCH9aLudtJfO5zT9r29FIvV4YMmHO0iu78i4IhQAeJdr42cvrGPp8Y41A==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.14", + "@angular-devkit/core": "16.2.1", "jsonc-parser": "3.2.0", "magic-string": "0.30.1", "ora": "5.4.1", @@ -369,55 +369,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", - "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", - "dev": true, - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "picomatch": "2.3.1", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/schematics/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/@angular-eslint/builder": { "version": "16.1.1", "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.1.1.tgz", @@ -593,15 +544,15 @@ } }, "node_modules/@angular/cli": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.14.tgz", - "integrity": "sha512-0y71jtitigVolm4Rim1b8xPQ+B22cGp4Spef2Wunpqj67UowN6tsZaVuWBEQh4u5xauX8LAHKqsvy37ZPWCc4A==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.1.tgz", + "integrity": "sha512-nuCc0VOGjuUFQo1Pu9CyFQ4VTy7OuwTiwxOG9qbut4FSGz2CO9NeqoamPUuy6rpKVu5JxVe+L6Y4OFaNKv2n3Q==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1602.14", - "@angular-devkit/core": "16.2.14", - "@angular-devkit/schematics": "16.2.14", - "@schematics/angular": "16.2.14", + "@angular-devkit/architect": "0.1602.1", + "@angular-devkit/core": "16.2.1", + "@angular-devkit/schematics": "16.2.1", + "@schematics/angular": "16.2.1", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.1", @@ -626,70 +577,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { - "version": "0.1602.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.14.tgz", - "integrity": "sha512-eSdONEV5dbtLNiOMBy9Ue9DdJ1ct6dH9RdZfYiedq6VZn0lejePAjY36MYVXgq2jTE+v/uIiaNy7caea5pt55A==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "16.2.14", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/cli/node_modules/@angular-devkit/core": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", - "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", - "dev": true, - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "picomatch": "2.3.1", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular/cli/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@angular/cli/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/@angular/cli/node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -3778,13 +3665,13 @@ } }, "node_modules/@schematics/angular": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.14.tgz", - "integrity": "sha512-YqIv727l9Qze8/OL6H9mBHc2jVXzAGRNBYnxYWqWhLbfvuVbbldo6NNIIjgv6lrl2LJSdPAAMNOD5m/f6210ug==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.1.tgz", + "integrity": "sha512-e3ckgvSv+OA+4xUBpOqVOvNM8FqY/yXaWqs/Ob0uQ/zPL1iVa/MCAoB25KqYQPnq21hEwE4zqIIQFKasKBIqMA==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.14", - "@angular-devkit/schematics": "16.2.14", + "@angular-devkit/core": "16.2.1", + "@angular-devkit/schematics": "16.2.1", "jsonc-parser": "3.2.0" }, "engines": { @@ -3793,55 +3680,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", - "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", - "dev": true, - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "picomatch": "2.3.1", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@schematics/angular/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@schematics/angular/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/@sigstore/bundle": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", @@ -14725,50 +14563,16 @@ } }, "@angular-devkit/schematics": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.14.tgz", - "integrity": "sha512-B6LQKInCT8w5zx5Pbroext5eFFRTCJdTwHN8GhcVS8IeKCnkeqVTQLjB4lBUg7LEm8Y7UHXwzrVxmk+f+MBXhw==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.1.tgz", + "integrity": "sha512-rXXO5zSI/iN6JtU3oU+vKfOB1N8n1iCH9aLudtJfO5zT9r29FIvV4YMmHO0iu78i4IhQAeJdr42cvrGPp8Y41A==", "dev": true, "requires": { - "@angular-devkit/core": "16.2.14", + "@angular-devkit/core": "16.2.1", "jsonc-parser": "3.2.0", "magic-string": "0.30.1", "ora": "5.4.1", "rxjs": "7.8.1" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", - "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", - "dev": true, - "requires": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "picomatch": "2.3.1", - "rxjs": "7.8.1", - "source-map": "0.7.4" - } - }, - "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } } }, "@angular-eslint/builder": { @@ -14904,15 +14708,15 @@ } }, "@angular/cli": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.14.tgz", - "integrity": "sha512-0y71jtitigVolm4Rim1b8xPQ+B22cGp4Spef2Wunpqj67UowN6tsZaVuWBEQh4u5xauX8LAHKqsvy37ZPWCc4A==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.1.tgz", + "integrity": "sha512-nuCc0VOGjuUFQo1Pu9CyFQ4VTy7OuwTiwxOG9qbut4FSGz2CO9NeqoamPUuy6rpKVu5JxVe+L6Y4OFaNKv2n3Q==", "dev": true, "requires": { - "@angular-devkit/architect": "0.1602.14", - "@angular-devkit/core": "16.2.14", - "@angular-devkit/schematics": "16.2.14", - "@schematics/angular": "16.2.14", + "@angular-devkit/architect": "0.1602.1", + "@angular-devkit/core": "16.2.1", + "@angular-devkit/schematics": "16.2.1", + "@schematics/angular": "16.2.1", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.1", @@ -14929,48 +14733,6 @@ "yargs": "17.7.2" }, "dependencies": { - "@angular-devkit/architect": { - "version": "0.1602.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.14.tgz", - "integrity": "sha512-eSdONEV5dbtLNiOMBy9Ue9DdJ1ct6dH9RdZfYiedq6VZn0lejePAjY36MYVXgq2jTE+v/uIiaNy7caea5pt55A==", - "dev": true, - "requires": { - "@angular-devkit/core": "16.2.14", - "rxjs": "7.8.1" - } - }, - "@angular-devkit/core": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", - "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", - "dev": true, - "requires": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "picomatch": "2.3.1", - "rxjs": "7.8.1", - "source-map": "0.7.4" - } - }, - "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -16985,48 +16747,14 @@ "optional": true }, "@schematics/angular": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.14.tgz", - "integrity": "sha512-YqIv727l9Qze8/OL6H9mBHc2jVXzAGRNBYnxYWqWhLbfvuVbbldo6NNIIjgv6lrl2LJSdPAAMNOD5m/f6210ug==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.1.tgz", + "integrity": "sha512-e3ckgvSv+OA+4xUBpOqVOvNM8FqY/yXaWqs/Ob0uQ/zPL1iVa/MCAoB25KqYQPnq21hEwE4zqIIQFKasKBIqMA==", "dev": true, "requires": { - "@angular-devkit/core": "16.2.14", - "@angular-devkit/schematics": "16.2.14", + "@angular-devkit/core": "16.2.1", + "@angular-devkit/schematics": "16.2.1", "jsonc-parser": "3.2.0" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz", - "integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==", - "dev": true, - "requires": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "picomatch": "2.3.1", - "rxjs": "7.8.1", - "source-map": "0.7.4" - } - }, - "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } } }, "@sigstore/bundle": { diff --git a/client/package.json b/client/package.json index 9f2d19e..4fea071 100644 --- a/client/package.json +++ b/client/package.json @@ -39,7 +39,7 @@ "@angular-eslint/eslint-plugin-template": "16.1.1", "@angular-eslint/schematics": "16.1.1", "@angular-eslint/template-parser": "16.1.1", - "@angular/cli": "^16.2.14", + "@angular/cli": "^16.2.1", "@angular/compiler-cli": "^16.2.3", "@angular/language-service": "^16.2.3", "@types/file-saver": "^2.0.5", @@ -51,4 +51,4 @@ "prettier": "^3.0.3", "typescript": "5.1.6" } -} +} \ No newline at end of file diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index d7e692e..4fc239a 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -22,7 +22,7 @@ - + From df084bcebe83333c6587318ec2531007ca202338 Mon Sep 17 00:00:00 2001 From: GabbeHags <38500419+GabbeHags@users.noreply.github.com> Date: Sun, 15 Sep 2024 21:04:55 +0200 Subject: [PATCH 15/31] download limit now takes in to consideration total active downloads --- .../Services/Downloaders/InternalDownloader.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/RdtClient.Service/Services/Downloaders/InternalDownloader.cs b/server/RdtClient.Service/Services/Downloaders/InternalDownloader.cs index 98cc1ba..74408b5 100644 --- a/server/RdtClient.Service/Services/Downloaders/InternalDownloader.cs +++ b/server/RdtClient.Service/Services/Downloaders/InternalDownloader.cs @@ -26,7 +26,7 @@ public class InternalDownloader : IDownloader _uri = uri; _filePath = filePath; - + _downloadConfiguration = new(); SetSettings(); @@ -131,14 +131,14 @@ public class InternalDownloader : IDownloader { settingDownloadParallelCount = 1; } - + var settingDownloadMaxSpeed = Settings.Get.DownloadClient.MaxSpeed; if (settingDownloadMaxSpeed <= 0) { settingDownloadMaxSpeed = 0; } - + settingDownloadMaxSpeed = settingDownloadMaxSpeed / Math.Max(TorrentRunner.ActiveDownloadClients.Count, 1); settingDownloadMaxSpeed = settingDownloadMaxSpeed * 1024 * 1024; var settingDownloadTimeout = Settings.Get.DownloadClient.Timeout; From 910419700021b7dfe0c7f9e0230df6f43a1ec488 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Wed, 25 Sep 2024 14:53:54 +1000 Subject: [PATCH 16/31] Update TorBox.NET to v1.1.2 fixes GetInfoAsync rename to GetHashInfoAsync --- .../RdtClient.Service.csproj | 2 +- .../TorrentClients/TorBoxTorrentClient.cs | 20 +++++-------------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index 4fc239a..fdc2c13 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -22,7 +22,7 @@ - + diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 985a5be..c5ec039 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -24,8 +24,8 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien var httpClient = httpClientFactory.CreateClient(); httpClient.Timeout = TimeSpan.FromSeconds(Settings.Get.Provider.Timeout); - var rdtNetClient = new TorBoxNetClient(null, httpClient, 5); - rdtNetClient.UseApiAuthentication(apiKey); + var torBoxNetClient = new TorBoxNetClient(null, httpClient, 5); + torBoxNetClient.UseApiAuthentication(apiKey); // Get the server time to fix up the timezones on results if (_offset == null) @@ -34,7 +34,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien _offset = serverTime.Offset; } - return rdtNetClient; + return torBoxNetClient; } catch (AggregateException ae) { @@ -302,7 +302,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien var rdTorrent = await GetInfo(torrent.Hash); var files = new List(); - var torrentId = await GetClient().Torrents.GetInfoAsync(torrent.Hash, skipCache: true); + var torrentId = await GetClient().Torrents.GetHashInfoAsync(torrent.Hash, skipCache: true); if (Settings.Get.Provider.Zipped == true) { var newFile = $"https://torbox.app/fakedl/{torrentId?.Id}/zip"; @@ -332,18 +332,8 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien private async Task GetInfo(String torrentHash) { - var result = await GetClient().Torrents.GetInfoAsync(torrentHash, skipCache: true); + var result = await GetClient().Torrents.GetHashInfoAsync(torrentHash, skipCache: true); return Map(result!); } - - private void Log(String message, Data.Models.Data.Torrent? torrent = null) - { - if (torrent != null) - { - message = $"{message} {torrent.ToLog()}"; - } - - logger.LogDebug(message); - } } \ No newline at end of file From 3bae4501a519086224bfc489f203b545ba54de69 Mon Sep 17 00:00:00 2001 From: Ruakij Date: Sun, 27 Oct 2024 18:02:32 +0100 Subject: [PATCH 17/31] Accept login via qbittorrent-api when AuthType is none --- server/RdtClient.Web/Controllers/QBittorrentController.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/RdtClient.Web/Controllers/QBittorrentController.cs b/server/RdtClient.Web/Controllers/QBittorrentController.cs index 4fdfd77..a527f7b 100644 --- a/server/RdtClient.Web/Controllers/QBittorrentController.cs +++ b/server/RdtClient.Web/Controllers/QBittorrentController.cs @@ -21,6 +21,11 @@ public class QBittorrentController(ILogger logger, QBitto { logger.LogDebug($"Auth login"); + if (Settings.Get.General.AuthenticationType == AuthenticationType.None) + { + return Ok("Ok."); + } + if (String.IsNullOrWhiteSpace(request.UserName) || String.IsNullOrEmpty(request.Password)) { return Ok("Fails."); From b78f0cdd956507f7ce24b17137c1def513384dfa Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:59:00 +1000 Subject: [PATCH 18/31] Remove zipped --- .../TorrentClients/TorBoxTorrentClient.cs | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index c5ec039..ffe0f76 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -121,8 +121,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task AddMagnet(String magnetLink) { var seeding = Settings.Get.Provider.Seeding; - var zipped = Settings.Get.Provider.Zipped; - var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, seeding, zipped); + var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, seeding, false); if (result.Error == "ACTIVE_LIMIT") { @@ -138,8 +137,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task AddFile(Byte[] bytes) { var seeding = Settings.Get.Provider.Seeding; - var zipped = Settings.Get.Provider.Zipped; - var result = await GetClient().Torrents.AddFileAsync(bytes, seeding, zipped); + var result = await GetClient().Torrents.AddFileAsync(bytes, seeding, false); if (result.Error == "ACTIVE_LIMIT") { using (var stream = new MemoryStream(bytes)) @@ -303,19 +301,9 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien var files = new List(); var torrentId = await GetClient().Torrents.GetHashInfoAsync(torrent.Hash, skipCache: true); - if (Settings.Get.Provider.Zipped == true) - { - var newFile = $"https://torbox.app/fakedl/{torrentId?.Id}/zip"; - files.Add(newFile); - } - else if (rdTorrent.Files?.Count != 0) - { - foreach (var file in rdTorrent.Files!) - { - var newFile = $"https://torbox.app/fakedl/{torrentId?.Id}/{file.Id}"; - files.Add(newFile); - } - } + + var newFile = $"https://torbox.app/fakedl/{torrentId?.Id}/zip"; + files.Add(newFile); return files; } @@ -336,4 +324,4 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien return Map(result!); } -} \ No newline at end of file +} From ec4e1602882c9783b7f7e887fc189900944bdb34 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Tue, 12 Nov 2024 14:29:47 +1000 Subject: [PATCH 19/31] disable seeding Would rather have seeding disabled and Torbox support be merged then fix it in December when I have time again. --- .../Models/Internal/DbSettings.cs | 8 -------- .../TorrentClients/TorBoxTorrentClient.cs | 19 +++++++++++++++---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/server/RdtClient.Data/Models/Internal/DbSettings.cs b/server/RdtClient.Data/Models/Internal/DbSettings.cs index 2c45ec8..9402b33 100644 --- a/server/RdtClient.Data/Models/Internal/DbSettings.cs +++ b/server/RdtClient.Data/Models/Internal/DbSettings.cs @@ -177,14 +177,6 @@ or [DisplayName("Auto Import Defaults")] public DbSettingsDefaultsWithCategory Default { get; set; } = new(); - - [DisplayName("Seeding")] - [Description("Set the priority of a torrent, 1 = Auto, 2 = Seed, 3 = disabled. [TorBox Only]")] - public Int32 Seeding { get; set; } = 3; - - [DisplayName("Download as Zip")] - [Description("Whether to download the files individually or zipped. [TorBox Only]")] - public bool Zipped { get; set; } = true; } public class DbSettingsIntegrations diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index ffe0f76..8ed91e9 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -120,8 +120,13 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task AddMagnet(String magnetLink) { - var seeding = Settings.Get.Provider.Seeding; - var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, seeding, false); + // var seeding = Settings.Get.Integrations.Default.FinishedAction; + + // Line is not working right now, will disable seeding and fix in december when I have time again. + // var seed = (seeding == TorrentFinishedAction.RemoveAllTorrents || seeding == TorrentFinishedAction.RemoveRealDebrid) ? 3 : 2; + + var seed = 3; + var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, seed, false); if (result.Error == "ACTIVE_LIMIT") { @@ -136,8 +141,14 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task AddFile(Byte[] bytes) { - var seeding = Settings.Get.Provider.Seeding; - var result = await GetClient().Torrents.AddFileAsync(bytes, seeding, false); + var seeding = Settings.Get.Integrations.Default.FinishedAction; + + // Line is not working right now, will disable seeding and fix in december when I have time again. + // var seed = (seeding == TorrentFinishedAction.RemoveAllTorrents || seeding == TorrentFinishedAction.RemoveRealDebrid) ? 3 : 2; + + var seed = 3; + + var result = await GetClient().Torrents.AddFileAsync(bytes, seed, false); if (result.Error == "ACTIVE_LIMIT") { using (var stream = new MemoryStream(bytes)) From b12f6812cfb7986d60daee4d91660115d0c73f64 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Tue, 12 Nov 2024 15:16:03 +1000 Subject: [PATCH 20/31] update torbox.net to 1.2.1 --- server/RdtClient.Service/RdtClient.Service.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index fdc2c13..ae30459 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -22,7 +22,7 @@ - + From ee5b5f8dc3ea5a864faa81297e196d55f11fb1ff Mon Sep 17 00:00:00 2001 From: Roger Versluis Date: Mon, 18 Nov 2024 03:39:12 -0700 Subject: [PATCH 21/31] Upgrade to .NET 9, code cleanup. --- server/RdtClient.Data/Data/TorrentData.cs | 6 +- server/RdtClient.Data/RdtClient.Data.csproj | 14 ++-- .../Helpers/DownloadHelper.cs | 37 +--------- .../RdtClient.Service.csproj | 12 ++-- .../Services/DownloadClient.cs | 10 +-- .../Downloaders/InternalDownloader.cs | 2 +- .../TorrentClients/TorBoxTorrentClient.cs | 68 +++++++------------ server/RdtClient.Service/Services/Torrents.cs | 2 +- .../Services/UnpackClient.cs | 2 +- .../Controllers/QBittorrentController.cs | 1 + server/RdtClient.Web/Program.cs | 3 - server/RdtClient.Web/RdtClient.Web.csproj | 18 ++--- server/RdtClient.sln.DotSettings | 2 + 13 files changed, 62 insertions(+), 115 deletions(-) diff --git a/server/RdtClient.Data/Data/TorrentData.cs b/server/RdtClient.Data/Data/TorrentData.cs index 63d6cf6..34f43a3 100644 --- a/server/RdtClient.Data/Data/TorrentData.cs +++ b/server/RdtClient.Data/Data/TorrentData.cs @@ -51,12 +51,12 @@ public class TorrentData(DataContext dataContext) public async Task GetByHash(String hash) { -#pragma warning disable CA1862 // Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + hash = hash.ToLower(); + var dbTorrent = await dataContext.Torrents .AsNoTracking() .Include(m => m.Downloads) - .FirstOrDefaultAsync(m => m.Hash.ToLower() == hash.ToLower()); -#pragma warning restore CA1862 // Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + .FirstOrDefaultAsync(m => m.Hash == hash); if (dbTorrent == null) { diff --git a/server/RdtClient.Data/RdtClient.Data.csproj b/server/RdtClient.Data/RdtClient.Data.csproj index 81e9430..ff4da08 100644 --- a/server/RdtClient.Data/RdtClient.Data.csproj +++ b/server/RdtClient.Data/RdtClient.Data.csproj @@ -1,22 +1,22 @@ - net8.0 + net9.0 enable enable latest - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/server/RdtClient.Service/Helpers/DownloadHelper.cs b/server/RdtClient.Service/Helpers/DownloadHelper.cs index c427ac1..bbb1775 100644 --- a/server/RdtClient.Service/Helpers/DownloadHelper.cs +++ b/server/RdtClient.Service/Helpers/DownloadHelper.cs @@ -1,14 +1,11 @@ -using System; -using System.Web; -using RdtClient.Data.Enums; +using System.Web; using RdtClient.Data.Models.Data; -using RdtClient.Service.Services; namespace RdtClient.Service.Helpers; public static class DownloadHelper { - public static async Task GetDownloadPath(String downloadPath, Torrent torrent, Download download) + public static String? GetDownloadPath(String downloadPath, Torrent torrent, Download download) { var fileUrl = download.Link; @@ -24,20 +21,6 @@ public static class DownloadHelper var fileName = uri.Segments.Last(); - if (Settings.Get.Provider.Provider == Provider.TorBox) - { - using (HttpClient client = new HttpClient()) - { - HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Head, uri); - HttpResponseMessage response = await client.SendAsync(request); - - if (response.Content.Headers.ContentDisposition != null) - { - fileName = response.Content.Headers.ContentDisposition.FileName!.Trim('"'); - } - } - } - fileName = HttpUtility.UrlDecode(fileName); fileName = FileHelper.RemoveInvalidFileNameChars(fileName); @@ -68,7 +51,7 @@ public static class DownloadHelper return filePath; } - public static async Task GetDownloadPath(Torrent torrent, Download download) + public static String? GetDownloadPath(Torrent torrent, Download download) { var fileUrl = download.Link; @@ -82,20 +65,6 @@ public static class DownloadHelper var fileName = uri.Segments.Last(); - if (Settings.Get.Provider.Provider == Provider.TorBox) - { - using (HttpClient client = new HttpClient()) - { - HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Head, uri); - HttpResponseMessage response = await client.SendAsync(request); - - if (response.Content.Headers.ContentDisposition != null) - { - fileName = response.Content.Headers.ContentDisposition.FileName!.Trim('"'); - } - } - } - fileName = HttpUtility.UrlDecode(fileName); fileName = FileHelper.RemoveInvalidFileNameChars(fileName); diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index ae30459..46e3a0f 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable latest @@ -11,15 +11,15 @@ - + - - + + - + - + diff --git a/server/RdtClient.Service/Services/DownloadClient.cs b/server/RdtClient.Service/Services/DownloadClient.cs index d5faf3d..3ab400b 100644 --- a/server/RdtClient.Service/Services/DownloadClient.cs +++ b/server/RdtClient.Service/Services/DownloadClient.cs @@ -43,15 +43,15 @@ public class DownloadClient(Download download, Torrent torrent, String destinati if (Type != Data.Enums.DownloadClient.Symlink) { - await FileHelper.Delete(filePath.Result!); + await FileHelper.Delete(filePath); } Downloader = Type switch { - Data.Enums.DownloadClient.Internal => new InternalDownloader(download.Link, filePath.Result!), - Data.Enums.DownloadClient.Bezzad => new BezzadDownloader(download.Link, filePath.Result!), - Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(download.RemoteId, download.Link, filePath.Result!, downloadPath.Result!, category), - Data.Enums.DownloadClient.Symlink => new SymlinkDownloader(download.Link, filePath.Result!, downloadPath.Result!), + Data.Enums.DownloadClient.Internal => new InternalDownloader(download.Link, filePath), + Data.Enums.DownloadClient.Bezzad => new BezzadDownloader(download.Link, filePath), + Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(download.RemoteId, download.Link, filePath, downloadPath, category), + Data.Enums.DownloadClient.Symlink => new SymlinkDownloader(download.Link, filePath, downloadPath), _ => throw new($"Unknown download client {Type}") }; diff --git a/server/RdtClient.Service/Services/Downloaders/InternalDownloader.cs b/server/RdtClient.Service/Services/Downloaders/InternalDownloader.cs index 74408b5..11e02da 100644 --- a/server/RdtClient.Service/Services/Downloaders/InternalDownloader.cs +++ b/server/RdtClient.Service/Services/Downloaders/InternalDownloader.cs @@ -138,7 +138,7 @@ public class InternalDownloader : IDownloader { settingDownloadMaxSpeed = 0; } - settingDownloadMaxSpeed = settingDownloadMaxSpeed / Math.Max(TorrentRunner.ActiveDownloadClients.Count, 1); + settingDownloadMaxSpeed /= Math.Max(TorrentRunner.ActiveDownloadClients.Count, 1); settingDownloadMaxSpeed = settingDownloadMaxSpeed * 1024 * 1024; var settingDownloadTimeout = Settings.Get.DownloadClient.Timeout; diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 8ed91e9..b7a9407 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -3,7 +3,6 @@ using Newtonsoft.Json; using TorBoxNET; using RdtClient.Data.Enums; using RdtClient.Data.Models.TorrentClient; -using RdtClient.Service.Helpers; namespace RdtClient.Service.Services.TorrentClients; @@ -74,9 +73,9 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien Progress = (Int64)((torrent.Progress) * 100.0), Status = torrent.DownloadState, Added = ChangeTimeZone(torrent.CreatedAt)!.Value, - Files = (torrent.Files ?? []).Select(m => new TorrentClientFile + Files = torrent.Files.Select(m => new TorrentClientFile { - Path = string.Join("/", m.Name.Split('/').Skip(1)), + Path = String.Join("/", m.Name.Split('/').Skip(1)), Bytes = m.Size, Id = m.Id, Selected = true @@ -104,7 +103,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien torrents.AddRange(queuedTorrents); } - return torrents!.Select(Map).ToList(); + return torrents.Select(Map).ToList(); } public async Task GetUser() @@ -141,26 +140,20 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task AddFile(Byte[] bytes) { - var seeding = Settings.Get.Integrations.Default.FinishedAction; - // Line is not working right now, will disable seeding and fix in december when I have time again. // var seed = (seeding == TorrentFinishedAction.RemoveAllTorrents || seeding == TorrentFinishedAction.RemoveRealDebrid) ? 3 : 2; + const Int32 seed = 3; - var seed = 3; - - var result = await GetClient().Torrents.AddFileAsync(bytes, seed, false); + var result = await GetClient().Torrents.AddFileAsync(bytes, seed); if (result.Error == "ACTIVE_LIMIT") { - using (var stream = new MemoryStream(bytes)) - { - var torrent = MonoTorrent.Torrent.Load(stream); - return torrent!.InfoHashes.V1!.ToHex().ToLowerInvariant(); - } - } - else - { - return result.Data!.Hash!; + using var stream = new MemoryStream(bytes); + + var torrent = await MonoTorrent.Torrent.LoadAsync(stream); + return torrent.InfoHashes.V1!.ToHex().ToLowerInvariant(); } + + return result.Data!.Hash!; } public async Task> GetAvailableFiles(String hash) @@ -169,24 +162,15 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien if (availability.Data != null) { - var availableFiles = new List(); - foreach (var file in availability.Data[0]?.Files!) - { - availableFiles.Add( - new TorrentClientAvailableFile - { - Filename = file!.Name, - Filesize = file.Size - }); - } - return availableFiles; - } - else - { - return []; + return (availability.Data[0]?.Files ?? []).Select(file => new TorrentClientAvailableFile() + { + Filename = file.Name, + Filesize = file.Size + }) + .ToList(); } - + return []; } public Task SelectFiles(Data.Models.Data.Torrent torrent) @@ -199,21 +183,21 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien await GetClient().Torrents.ControlAsync(torrentId, "delete"); } - public async Task Unrestrict(string link) + public async Task Unrestrict(String link) { var segments = link.Split('/'); - bool zipped = segments[5] == "zip"; - string fileId = zipped ? "0" : segments[5]; + var zipped = segments[5] == "zip"; + var fileId = zipped ? "0" : segments[5]; var result = await GetClient().Torrents.RequestDownloadAsync(Convert.ToInt32(segments[4]), Convert.ToInt32(fileId), zipped); - if (result?.Error != null) + if (result.Error != null) { throw new("Unrestrict returned an invalid download"); } - return result!.Data!; + return result.Data!; } public async Task UpdateData(Data.Models.Data.Torrent torrent, TorrentClientTorrent? torrentClientTorrent) @@ -303,12 +287,6 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien public async Task?> GetDownloadLinks(Data.Models.Data.Torrent torrent) { - if (torrent.Hash == null) - { - return null; - } - - var rdTorrent = await GetInfo(torrent.Hash); var files = new List(); var torrentId = await GetClient().Torrents.GetHashInfoAsync(torrent.Hash, skipCache: true); diff --git a/server/RdtClient.Service/Services/Torrents.cs b/server/RdtClient.Service/Services/Torrents.cs index 4885e1b..25817cf 100644 --- a/server/RdtClient.Service/Services/Torrents.cs +++ b/server/RdtClient.Service/Services/Torrents.cs @@ -553,7 +553,7 @@ public class Torrents( { Log($"Deleting {filePath}", download, download.Torrent); - await FileHelper.Delete(filePath.Result!); + await FileHelper.Delete(filePath); } Log($"Resetting", download, download.Torrent); diff --git a/server/RdtClient.Service/Services/UnpackClient.cs b/server/RdtClient.Service/Services/UnpackClient.cs index c702d71..2724f43 100644 --- a/server/RdtClient.Service/Services/UnpackClient.cs +++ b/server/RdtClient.Service/Services/UnpackClient.cs @@ -31,7 +31,7 @@ public class UnpackClient(Download download, String destinationPath) { if (!_cancellationTokenSource.IsCancellationRequested) { - await Unpack(filePath.Result!, _cancellationTokenSource.Token); + await Unpack(filePath, _cancellationTokenSource.Token); } }); } diff --git a/server/RdtClient.Web/Controllers/QBittorrentController.cs b/server/RdtClient.Web/Controllers/QBittorrentController.cs index a527f7b..fe162b2 100644 --- a/server/RdtClient.Web/Controllers/QBittorrentController.cs +++ b/server/RdtClient.Web/Controllers/QBittorrentController.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using RdtClient.Data.Enums; using RdtClient.Data.Models.QBittorrent; using RdtClient.Service.Services; diff --git a/server/RdtClient.Web/Program.cs b/server/RdtClient.Web/Program.cs index e65ad0c..d1d676a 100644 --- a/server/RdtClient.Web/Program.cs +++ b/server/RdtClient.Web/Program.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using System.Net; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Hosting.WindowsServices; @@ -136,8 +135,6 @@ builder.Host.UseWindowsService(); RdtClient.Data.DiConfig.Config(builder.Services, appSettings); builder.Services.RegisterRdtServices(); -ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; - try { // Build the app diff --git a/server/RdtClient.Web/RdtClient.Web.csproj b/server/RdtClient.Web/RdtClient.Web.csproj index 9de70e8..032a8b0 100644 --- a/server/RdtClient.Web/RdtClient.Web.csproj +++ b/server/RdtClient.Web/RdtClient.Web.csproj @@ -1,7 +1,7 @@ - net8.0 + net9.0 Exe 94c24cba-f03f-4453-a671-3640b517c573 2.0.86 @@ -29,17 +29,17 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + diff --git a/server/RdtClient.sln.DotSettings b/server/RdtClient.sln.DotSettings index b248b47..46b2271 100644 --- a/server/RdtClient.sln.DotSettings +++ b/server/RdtClient.sln.DotSettings @@ -199,10 +199,12 @@ <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True True True True True True True + True \ No newline at end of file From f33380e77b9e0b75f5c49687bb27e792541cd32f Mon Sep 17 00:00:00 2001 From: Roger Versluis Date: Mon, 18 Nov 2024 03:58:53 -0700 Subject: [PATCH 22/31] Changed dockerfile to use .NET 9 --- CHANGELOG.md | 8 ++++++++ Dockerfile | 14 +++++++------- README.md | 8 ++++---- client/src/app/navbar/navbar.component.html | 2 +- package.json | 2 +- server/RdtClient.Web/RdtClient.Web.csproj | 2 +- 6 files changed, 22 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88b2cc2..d250e51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.87] - 2024-11-18 +### Added +- Torbox support. +- qBittorrent API authentication when no authentication is used. +### Changed +- .NET version changed to .NET 9. +- Changed download limit to be split by active torrents. + ## [2.0.86] - 2024-09-03 ### Changed - Add potential fix for BASE_PATH. diff --git a/Dockerfile b/Dockerfile index 9bc6a22..e210c88 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ RUN \ RUN ls -FCla /appclient/root # Stage 2 - Build the backend -FROM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim-amd64 AS dotnet-build-env +FROM mcr.microsoft.com/dotnet/sdk:9.0-bookworm-slim-amd64 AS dotnet-build-env ARG TARGETPLATFORM ENV TARGETPLATFORM=${TARGETPLATFORM:-linux/amd64} ARG BUILDPLATFORM @@ -66,14 +66,14 @@ RUN \ RUN \ if [ "$TARGETPLATFORM" = "linux/arm/v7" ] ; then \ - wget https://download.visualstudio.microsoft.com/download/pr/c3bf3103-efdb-42e0-af55-bbf861a4215b/dc22eda8877933b8c6569e3823f18d21/aspnetcore-runtime-8.0.0-linux-musl-arm64.tar.gz && \ - tar zxf aspnetcore-runtime-8.0.0-linux-musl-arm64.tar.gz -C /usr/share/dotnet ; \ + wget https://download.visualstudio.microsoft.com/download/pr/59a041e1-921e-405e-8092-95333f80f9ca/63e83e3feb70e05ca05ed5db3c579be2/aspnetcore-runtime-9.0.0-linux-musl-arm.tar.gz && \ + tar zxf aspnetcore-runtime-9.0.0-linux-musl-arm.tar.gz -C /usr/share/dotnet ; \ elif [ "$TARGETPLATFORM" = "linux/arm64" ] ; then \ - wget https://download.visualstudio.microsoft.com/download/pr/c3bf3103-efdb-42e0-af55-bbf861a4215b/dc22eda8877933b8c6569e3823f18d21/aspnetcore-runtime-8.0.0-linux-musl-arm64.tar.gz && \ - tar zxf aspnetcore-runtime-8.0.0-linux-musl-arm64.tar.gz -C /usr/share/dotnet ; \ + wget https://download.visualstudio.microsoft.com/download/pr/e137f557-83cb-4f55-b1c8-e5f59ccd3cba/b8ba6f2ab96d0961757b71b00c201f31/aspnetcore-runtime-9.0.0-linux-musl-arm64.tar.gz && \ + tar zxf aspnetcore-runtime-9.0.0-linux-musl-arm64.tar.gz -C /usr/share/dotnet ; \ else \ - wget https://download.visualstudio.microsoft.com/download/pr/7aa33fc7-07fe-48c2-8e44-a4bfb4928535/3b96ec50970eee414895ef3a5b188bcd/aspnetcore-runtime-8.0.0-linux-musl-x64.tar.gz && \ - tar zxf aspnetcore-runtime-8.0.0-linux-musl-x64.tar.gz -C /usr/share/dotnet ; \ + wget https://download.visualstudio.microsoft.com/download/pr/86d7a513-fe71-4f37-b9ec-fdcf5566cce8/e72574fc82d7496c73a61f411d967d8e/aspnetcore-runtime-9.0.0-linux-musl-x64.tar.gz && \ + tar zxf aspnetcore-runtime-9.0.0-linux-musl-x64.tar.gz -C /usr/share/dotnet ; \ fi RUN \ diff --git a/README.md b/README.md index 402b587..e157e61 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This is a web interface to manage your torrents on Real-Debrid, AllDebrid or Pre - Download all files from Real-Debrid, AllDebrid or Premiumize to your local machine automatically - Unpack all files when finished downloading - Implements a fake qBittorrent API so you can hook up other applications like Sonarr, Radarr or Couchpotato. -- Built with Angular 15 and .NET 8 +- Built with Angular 15 and .NET 9 **You will need a Premium service at Real-Debrid, AllDebrid or Premiumize!** @@ -30,7 +30,7 @@ Instead of running in Docker you can install it as a service in Windows or Linux ## Windows Service -1. Make sure you have the ASP.NET Core Runtime 8 installed: [https://dotnet.microsoft.com/download/dotnet/8.0](https://dotnet.microsoft.com/download/dotnet/8.0) +1. Make sure you have the .NET 9 Runtime installed: [https://dotnet.microsoft.com/download/dotnet/9.0](https://dotnet.microsoft.com/download/dotnet/9.0) 2. Get the latest zip file from the Releases page and extract it to your host. 3. Open the `appsettings.json` file and replace the `LogLevel` `Path` to a path on your host. 4. In `appsettings.json` replace the `Database` `Path` to a path on your host. @@ -52,7 +52,7 @@ Instead of running in Docker you can install it as a service in Linux. ```rm packages-microsoft-prod.deb``` - ```sudo apt-get update && sudo apt-get install -y dotnet-sdk-8.0``` + ```sudo apt-get update && sudo apt-get install -y dotnet-sdk-9.0``` 2. Get latest archive from [releases](https://github.com/rogerfar/rdt-client/releases): ```wget ``` @@ -188,7 +188,7 @@ By default the application runs in the root of your hosted address (i.e. https:/ - NodeJS - NPM - Angular CLI -- .NET 8 +- .NET 9 - Visual Studio 2022 - (optional) Resharper diff --git a/client/src/app/navbar/navbar.component.html b/client/src/app/navbar/navbar.component.html index 8395feb..46c2aa6 100644 --- a/client/src/app/navbar/navbar.component.html +++ b/client/src/app/navbar/navbar.component.html @@ -55,7 +55,7 @@ Profile Logout - Version 2.0.86 + Version 2.0.87 diff --git a/package.json b/package.json index 4ea720f..3ce220b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rdt-client", - "version": "2.0.86", + "version": "2.0.87", "description": "This is a web interface to manage your torrents on Real-Debrid.", "main": "index.js", "dependencies": { diff --git a/server/RdtClient.Web/RdtClient.Web.csproj b/server/RdtClient.Web/RdtClient.Web.csproj index 032a8b0..d5a14ee 100644 --- a/server/RdtClient.Web/RdtClient.Web.csproj +++ b/server/RdtClient.Web/RdtClient.Web.csproj @@ -4,7 +4,7 @@ net9.0 Exe 94c24cba-f03f-4453-a671-3640b517c573 - 2.0.86 + 2.0.87 enable enable latest From d932089b90a0ac3ddc5901df2f51c411cb79b21b Mon Sep 17 00:00:00 2001 From: Roger Far Date: Sun, 24 Nov 2024 05:45:22 -0700 Subject: [PATCH 23/31] Catch disabled instant availability endpoint from Real Debrid. --- CHANGELOG.md | 4 +++ client/src/app/navbar/navbar.component.html | 2 +- package.json | 2 +- .../TorrentClients/RealDebridTorrentClient.cs | 35 +++++++++++++------ server/RdtClient.Web/RdtClient.Web.csproj | 2 +- 5 files changed, 31 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d250e51..4a25e53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.88] - 2024-11-24 +### Changed +- Catch disabled instant availability endpoint from Real Debrid. + ## [2.0.87] - 2024-11-18 ### Added - Torbox support. diff --git a/client/src/app/navbar/navbar.component.html b/client/src/app/navbar/navbar.component.html index 46c2aa6..84888ab 100644 --- a/client/src/app/navbar/navbar.component.html +++ b/client/src/app/navbar/navbar.component.html @@ -55,7 +55,7 @@ Profile Logout - Version 2.0.87 + Version 2.0.88 diff --git a/package.json b/package.json index 3ce220b..9c61cea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rdt-client", - "version": "2.0.87", + "version": "2.0.88", "description": "This is a web interface to manage your torrents on Real-Debrid.", "main": "index.js", "dependencies": { diff --git a/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs index 2b09057..ccfb781 100644 --- a/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs @@ -139,19 +139,32 @@ public class RealDebridTorrentClient(ILogger logger, IH public async Task> GetAvailableFiles(String hash) { - var result = await GetClient().Torrents.GetAvailableFiles(hash); - - var files = result.SelectMany(m => m.Value).SelectMany(m => m.Value).SelectMany(m => m.Values); - - var groups = files.Where(m => m.Filename != null).GroupBy(m => $"{m.Filename}-{m.Filesize}"); - - var torrentClientAvailableFiles = groups.Select(m => new TorrentClientAvailableFile + try { - Filename = m.First().Filename!, - Filesize = m.First().Filesize - }).ToList(); + var result = await GetClient().Torrents.GetAvailableFiles(hash); - return torrentClientAvailableFiles; + var files = result.SelectMany(m => m.Value).SelectMany(m => m.Value).SelectMany(m => m.Values); + + var groups = files.Where(m => m.Filename != null).GroupBy(m => $"{m.Filename}-{m.Filesize}"); + + var torrentClientAvailableFiles = groups.Select(m => new TorrentClientAvailableFile + { + Filename = m.First().Filename!, + Filesize = m.First().Filesize + }) + .ToList(); + + return torrentClientAvailableFiles; + } + catch (RealDebridException exception) + { + if (exception.ErrorCode == 36) + { + return []; + } + + throw; + } } public async Task SelectFiles(Data.Models.Data.Torrent torrent) diff --git a/server/RdtClient.Web/RdtClient.Web.csproj b/server/RdtClient.Web/RdtClient.Web.csproj index d5a14ee..cb460b3 100644 --- a/server/RdtClient.Web/RdtClient.Web.csproj +++ b/server/RdtClient.Web/RdtClient.Web.csproj @@ -4,7 +4,7 @@ net9.0 Exe 94c24cba-f03f-4453-a671-3640b517c573 - 2.0.87 + 2.0.88 enable enable latest From 116ca29131592ae8e22770a1002741024b135c2f Mon Sep 17 00:00:00 2001 From: Roger Far Date: Sun, 24 Nov 2024 06:05:23 -0700 Subject: [PATCH 24/31] Ignore the "Only download available files on debrid provider" for real-debrid and disable the instant availability completely for Real Debrid. --- .../add-new-torrent.component.html | 51 ------------------ .../TorrentClients/PremiumizeTorrentClient.cs | 3 +- .../TorrentClients/RealDebridTorrentClient.cs | 53 ++++--------------- 3 files changed, 10 insertions(+), 97 deletions(-) diff --git a/client/src/app/add-new-torrent/add-new-torrent.component.html b/client/src/app/add-new-torrent/add-new-torrent.component.html index a083d1d..a519870 100644 --- a/client/src/app/add-new-torrent/add-new-torrent.component.html +++ b/client/src/app/add-new-torrent/add-new-torrent.component.html @@ -71,24 +71,6 @@

-
- -
- -
-

When a torrent is fully downloaded on the provider, perform this action.

-

- This option is only available for RealDebrid. AllDebrid, Premiumize, and Torbox will always download the full torrent. -

-
-
-
-
- -

- These files are available for immediate download from your debrid provider.
- It is possible that there are more files in the torrent, which are not shown here.
-

-
-
- -
-
- -
-
- -
-
-
-
diff --git a/server/RdtClient.Service/Services/TorrentClients/PremiumizeTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/PremiumizeTorrentClient.cs index b7e8382..cb170c2 100644 --- a/server/RdtClient.Service/Services/TorrentClients/PremiumizeTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/PremiumizeTorrentClient.cs @@ -117,8 +117,7 @@ public class PremiumizeTorrentClient(ILogger logger, IH public Task> GetAvailableFiles(String hash) { - var result = new List(); - return Task.FromResult>(result); + return Task.FromResult>([]); } public Task SelectFiles(Torrent torrent) diff --git a/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs index ccfb781..9cc8ad0 100644 --- a/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs @@ -137,62 +137,27 @@ public class RealDebridTorrentClient(ILogger logger, IH return result.Id; } - public async Task> GetAvailableFiles(String hash) + public Task> GetAvailableFiles(String hash) { - try - { - var result = await GetClient().Torrents.GetAvailableFiles(hash); - - var files = result.SelectMany(m => m.Value).SelectMany(m => m.Value).SelectMany(m => m.Values); - - var groups = files.Where(m => m.Filename != null).GroupBy(m => $"{m.Filename}-{m.Filesize}"); - - var torrentClientAvailableFiles = groups.Select(m => new TorrentClientAvailableFile - { - Filename = m.First().Filename!, - Filesize = m.First().Filesize - }) - .ToList(); - - return torrentClientAvailableFiles; - } - catch (RealDebridException exception) - { - if (exception.ErrorCode == 36) - { - return []; - } - - throw; - } + return Task.FromResult>([]); } public async Task SelectFiles(Data.Models.Data.Torrent torrent) { - var files = torrent.Files; + IList files; Log("Seleting files", torrent); - if (torrent.DownloadAction == TorrentDownloadAction.DownloadAvailableFiles) - { - Log($"Determining which files are already available on RealDebrid", torrent); - - var availableFiles = await GetAvailableFiles(torrent.Hash); - - Log($"Found {files.Count}/{torrent.Files.Count} available files on RealDebrid", torrent); - - files = torrent.Files.Where(m => availableFiles.Any(f => m.Path.EndsWith(f.Filename))).ToList(); - } - else if (torrent.DownloadAction == TorrentDownloadAction.DownloadAll) - { - Log("Selecting all files", torrent); - files = [.. torrent.Files]; - } - else if (torrent.DownloadAction == TorrentDownloadAction.DownloadManual) + if (torrent.DownloadAction == TorrentDownloadAction.DownloadManual) { Log("Selecting manual selected files", torrent); files = torrent.Files.Where(m => torrent.ManualFiles.Any(f => m.Path.EndsWith(f))).ToList(); } + else + { + Log("Selecting all files", torrent); + files = [.. torrent.Files]; + } Log($"Selecting {files.Count}/{torrent.Files.Count} files", torrent); From 8bd83dffbf83482b289bbf415e6dc4ef461acefc Mon Sep 17 00:00:00 2001 From: Roger Far Date: Sun, 24 Nov 2024 06:06:28 -0700 Subject: [PATCH 25/31] no message --- CHANGELOG.md | 4 ++++ client/src/app/navbar/navbar.component.html | 2 +- package.json | 2 +- server/RdtClient.Web/RdtClient.Web.csproj | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a25e53..fbb1bf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.89] - 2024-11-24 +### Changed +- Disabled selecting of files as Real-Debrid was the only provider that supported that. + ## [2.0.88] - 2024-11-24 ### Changed - Catch disabled instant availability endpoint from Real Debrid. diff --git a/client/src/app/navbar/navbar.component.html b/client/src/app/navbar/navbar.component.html index 84888ab..dea8adc 100644 --- a/client/src/app/navbar/navbar.component.html +++ b/client/src/app/navbar/navbar.component.html @@ -55,7 +55,7 @@ Profile Logout - Version 2.0.88 + Version 2.0.89
diff --git a/package.json b/package.json index 9c61cea..4966673 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rdt-client", - "version": "2.0.88", + "version": "2.0.89", "description": "This is a web interface to manage your torrents on Real-Debrid.", "main": "index.js", "dependencies": { diff --git a/server/RdtClient.Web/RdtClient.Web.csproj b/server/RdtClient.Web/RdtClient.Web.csproj index cb460b3..4b3cac8 100644 --- a/server/RdtClient.Web/RdtClient.Web.csproj +++ b/server/RdtClient.Web/RdtClient.Web.csproj @@ -4,7 +4,7 @@ net9.0 Exe 94c24cba-f03f-4453-a671-3640b517c573 - 2.0.88 + 2.0.89 enable enable latest From 8b16bd8ee26834b39c0d0568a932c924fab8e1c2 Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Wed, 27 Nov 2024 05:01:55 +1000 Subject: [PATCH 26/31] [TB] Download files individually rather than via zip --- .../Services/TorrentClients/TorBoxTorrentClient.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index b7a9407..94fe710 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -291,8 +291,11 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien var torrentId = await GetClient().Torrents.GetHashInfoAsync(torrent.Hash, skipCache: true); - var newFile = $"https://torbox.app/fakedl/{torrentId?.Id}/zip"; - files.Add(newFile); + foreach (var file in torrent.Files!) + { + var newFile = $"https://torbox.app/fakedl/{torrentId?.Id}/{file.Id}"; + files.Add(newFile); + } return files; } From 99c30bbc4fe21969295357bba765f82681d7258d Mon Sep 17 00:00:00 2001 From: Sam Heinz <54530346+asylumexp@users.noreply.github.com> Date: Wed, 27 Nov 2024 05:44:20 +1000 Subject: [PATCH 27/31] [TB] Fix source parameter null error --- .../Services/TorrentClients/TorBoxTorrentClient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 94fe710..505ed22 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -73,7 +73,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien Progress = (Int64)((torrent.Progress) * 100.0), Status = torrent.DownloadState, Added = ChangeTimeZone(torrent.CreatedAt)!.Value, - Files = torrent.Files.Select(m => new TorrentClientFile + Files = (torrent.Files ?? []).Select(m => new TorrentClientFile { Path = String.Join("/", m.Name.Split('/').Skip(1)), Bytes = m.Size, @@ -291,7 +291,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien var torrentId = await GetClient().Torrents.GetHashInfoAsync(torrent.Hash, skipCache: true); - foreach (var file in torrent.Files!) + foreach (var file in torrent.Files) { var newFile = $"https://torbox.app/fakedl/{torrentId?.Id}/{file.Id}"; files.Add(newFile); From 165d83361b456fa021cccca97f358866b8883077 Mon Sep 17 00:00:00 2001 From: Roger Far Date: Fri, 6 Dec 2024 18:11:24 -0700 Subject: [PATCH 28/31] Removed InstantAvailability endpoint from AllDebrid. --- .../add-new-torrent.component.html | 14 -------------- server/RdtClient.Data/RdtClient.Data.csproj | 2 +- .../RdtClient.Service/RdtClient.Service.csproj | 4 ++-- .../TorrentClients/AllDebridTorrentClient.cs | 18 ++---------------- .../TorrentClients/TorBoxTorrentClient.cs | 2 +- server/RdtClient.Web/RdtClient.Web.csproj | 2 +- 6 files changed, 7 insertions(+), 35 deletions(-) diff --git a/client/src/app/add-new-torrent/add-new-torrent.component.html b/client/src/app/add-new-torrent/add-new-torrent.component.html index a519870..6986959 100644 --- a/client/src/app/add-new-torrent/add-new-torrent.component.html +++ b/client/src/app/add-new-torrent/add-new-torrent.component.html @@ -71,20 +71,6 @@

-
- This torrent is available for immediate download. -
- -
- This torrent is not available for immediate download. -
-
diff --git a/server/RdtClient.Data/RdtClient.Data.csproj b/server/RdtClient.Data/RdtClient.Data.csproj index ff4da08..aebafe5 100644 --- a/server/RdtClient.Data/RdtClient.Data.csproj +++ b/server/RdtClient.Data/RdtClient.Data.csproj @@ -16,7 +16,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj index 46e3a0f..0ab2013 100644 --- a/server/RdtClient.Service/RdtClient.Service.csproj +++ b/server/RdtClient.Service/RdtClient.Service.csproj @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs index a46e3fe..bc0102c 100644 --- a/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs @@ -118,23 +118,9 @@ public class AllDebridTorrentClient(ILogger logger, IHtt return resultId; } - public async Task> GetAvailableFiles(String hash) + public Task> GetAvailableFiles(String hash) { - var isAvailable = await GetClient().Magnet.InstantAvailabilityAsync(hash); - - if (isAvailable) - { - return - [ - new() - { - Filename = "All files", - Filesize = 0 - } - ]; - } - - return []; + return Task.FromResult>([]); } public Task SelectFiles(Torrent torrent) diff --git a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs index 505ed22..088c928 100644 --- a/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs +++ b/server/RdtClient.Service/Services/TorrentClients/TorBoxTorrentClient.cs @@ -162,7 +162,7 @@ public class TorBoxTorrentClient(ILogger logger, IHttpClien if (availability.Data != null) { - return (availability.Data[0]?.Files ?? []).Select(file => new TorrentClientAvailableFile() + return (availability.Data[0]?.Files ?? []).Select(file => new TorrentClientAvailableFile { Filename = file.Name, Filesize = file.Size diff --git a/server/RdtClient.Web/RdtClient.Web.csproj b/server/RdtClient.Web/RdtClient.Web.csproj index 4b3cac8..a8fc753 100644 --- a/server/RdtClient.Web/RdtClient.Web.csproj +++ b/server/RdtClient.Web/RdtClient.Web.csproj @@ -38,7 +38,7 @@ - + From a91ea71dcbc29f0e34e7174d6d09c47d44374ed0 Mon Sep 17 00:00:00 2001 From: Roger Far Date: Fri, 6 Dec 2024 18:13:06 -0700 Subject: [PATCH 29/31] no message --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbb1bf3..da04f8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.90] - 2024-12-06 +### Changed +- Download individual files from Torbox instead of a zip file. + +### Removed +- Removed ability to select instant files from AllDebrid. + ## [2.0.89] - 2024-11-24 ### Changed - Disabled selecting of files as Real-Debrid was the only provider that supported that. diff --git a/package.json b/package.json index 4966673..8c177b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rdt-client", - "version": "2.0.89", + "version": "2.0.90", "description": "This is a web interface to manage your torrents on Real-Debrid.", "main": "index.js", "dependencies": { From 4351c7541c2d9d7e379ea1cf0a9574c96318ccb5 Mon Sep 17 00:00:00 2001 From: Roger Far Date: Fri, 6 Dec 2024 18:13:24 -0700 Subject: [PATCH 30/31] no message --- client/src/app/navbar/navbar.component.html | 2 +- server/RdtClient.Web/RdtClient.Web.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/app/navbar/navbar.component.html b/client/src/app/navbar/navbar.component.html index dea8adc..55ee2b7 100644 --- a/client/src/app/navbar/navbar.component.html +++ b/client/src/app/navbar/navbar.component.html @@ -55,7 +55,7 @@ Profile Logout - Version 2.0.89 + Version 2.0.90
diff --git a/server/RdtClient.Web/RdtClient.Web.csproj b/server/RdtClient.Web/RdtClient.Web.csproj index a8fc753..adfbda3 100644 --- a/server/RdtClient.Web/RdtClient.Web.csproj +++ b/server/RdtClient.Web/RdtClient.Web.csproj @@ -4,7 +4,7 @@ net9.0 Exe 94c24cba-f03f-4453-a671-3640b517c573 - 2.0.89 + 2.0.90 enable enable latest From 1a9a0ddf3c35153fbba2dbe2c500cbd3eda7e18b Mon Sep 17 00:00:00 2001 From: Roger Far Date: Fri, 6 Dec 2024 18:18:04 -0700 Subject: [PATCH 31/31] Update README to include the ASP.NET Core Runtime. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e157e61..52f83ac 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Instead of running in Docker you can install it as a service in Windows or Linux ## Windows Service -1. Make sure you have the .NET 9 Runtime installed: [https://dotnet.microsoft.com/download/dotnet/9.0](https://dotnet.microsoft.com/download/dotnet/9.0) +1. Make sure you have the **ASP.NET Core Runtime 9.0.0** installed: [https://dotnet.microsoft.com/download/dotnet/9.0](https://dotnet.microsoft.com/download/dotnet/9.0) 2. Get the latest zip file from the Releases page and extract it to your host. 3. Open the `appsettings.json` file and replace the `LogLevel` `Path` to a path on your host. 4. In `appsettings.json` replace the `Database` `Path` to a path on your host.