From dbb502a164c6d0509004c5f165cb0725c1c611de Mon Sep 17 00:00:00 2001 From: Roger Far Date: Sat, 20 Apr 2024 09:47:51 -0600 Subject: [PATCH] Add recursive searching for the symlink downloader. --- CHANGELOG.md | 4 ++ package.json | 2 +- .../Models/Internal/DbSettings.cs | 2 +- .../Services/DownloadClient.cs | 2 - .../Services/Downloaders/SymlinkDownloader.cs | 60 +++++++++++++------ .../Services/TorrentRunner.cs | 10 ---- 6 files changed, 49 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5cb22f..6bc8124 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.74] - 2024-04-20 +### Added +- Added support for symlink recursive searching. + ## [2.0.73] - 2024-04-11 ### Changed - Fixed another issue with the symlinker and file resolver. diff --git a/package.json b/package.json index 0e88a6b..9ecae09 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rdt-client", - "version": "2.0.73", + "version": "2.0.74", "description": "This is a web interface to manage your torrents on Real-Debrid.", "main": "index.js", "dependencies": { diff --git a/server/RdtClient.Data/Models/Internal/DbSettings.cs b/server/RdtClient.Data/Models/Internal/DbSettings.cs index 10d29b8..10381fd 100644 --- a/server/RdtClient.Data/Models/Internal/DbSettings.cs +++ b/server/RdtClient.Data/Models/Internal/DbSettings.cs @@ -129,7 +129,7 @@ http://127.0.0.1:6800/jsonrpc.")] public String? Aria2cDownloadPath { get; set; } = null; [DisplayName("Rclone mount path (only used for the Symlink Downloader)")] - [Description("Path where Rclone is mounted. Required for Symlink Downloader.")] + [Description("Path where Rclone is mounted. Required for Symlink Downloader. Suffix this path with a * to search subdirectories too.")] public String RcloneMountPath { get; set; } = "/mnt/rd/"; [DisplayName("Log level")] diff --git a/server/RdtClient.Service/Services/DownloadClient.cs b/server/RdtClient.Service/Services/DownloadClient.cs index 6b80e56..ff94b13 100644 --- a/server/RdtClient.Service/Services/DownloadClient.cs +++ b/server/RdtClient.Service/Services/DownloadClient.cs @@ -66,8 +66,6 @@ public class DownloadClient(Download download, Torrent torrent, String destinati }; var result = await Downloader.Download(); - - await Task.Delay(1000); return result; } diff --git a/server/RdtClient.Service/Services/Downloaders/SymlinkDownloader.cs b/server/RdtClient.Service/Services/Downloaders/SymlinkDownloader.cs index 65b7fd4..5353a58 100644 --- a/server/RdtClient.Service/Services/Downloaders/SymlinkDownloader.cs +++ b/server/RdtClient.Service/Services/Downloaders/SymlinkDownloader.cs @@ -23,6 +23,14 @@ public class SymlinkDownloader(String uri, String destinationPath, String path) var filePath = new FileInfo(path); var rcloneMountPath = Settings.Get.DownloadClient.RcloneMountPath.TrimEnd(['\\', '/']); + var searchSubDirectories = rcloneMountPath.EndsWith("*"); + rcloneMountPath = rcloneMountPath.TrimEnd('*').TrimEnd(['\\', '/']); + + if (!Directory.Exists(rcloneMountPath)) + { + throw new($"Mount path {rcloneMountPath} does not exist!"); + } + var fileName = filePath.Name; var fileExtension = filePath.Extension; var fileNameWithoutExtension = fileName.Replace(fileExtension, ""); @@ -31,9 +39,9 @@ public class SymlinkDownloader(String uri, String destinationPath, String path) List unWantedExtensions = [ - "zip", - "rar", - "tar" + ".zip", + ".rar", + ".tar" ]; if (unWantedExtensions.Any(m => fileExtension == m)) @@ -54,7 +62,7 @@ public class SymlinkDownloader(String uri, String destinationPath, String path) var directoryInfo = new DirectoryInfo(searchPath); while (directoryInfo.Parent != null) { - potentialFilePaths.Add(directoryInfo.FullName); + potentialFilePaths.Add(directoryInfo.Name); directoryInfo = directoryInfo.Parent; if (directoryInfo.FullName.TrimEnd(['\\', '/']) == rcloneMountPath) @@ -63,10 +71,12 @@ public class SymlinkDownloader(String uri, String destinationPath, String path) } } - potentialFilePaths.Add(Path.Combine(rcloneMountPath, fileName)); - potentialFilePaths.Add(Path.Combine(rcloneMountPath, fileNameWithoutExtension)); + potentialFilePaths.Add(fileName); + potentialFilePaths.Add(fileNameWithoutExtension); - FileInfo? file = null; + potentialFilePaths = potentialFilePaths.Distinct().ToList(); + + String? file = null; for (var retryCount = 0; retryCount < MaxRetries; retryCount++) { @@ -80,16 +90,15 @@ public class SymlinkDownloader(String uri, String destinationPath, String path) _logger.Debug($"Searching {rcloneMountPath} for {fileName} (attempt #{retryCount})..."); - foreach (var potentialFilePath in potentialFilePaths) + file = FindFile(rcloneMountPath, potentialFilePaths, fileName); + + if (file == null && searchSubDirectories) { - var potentialFilePathWithFileName = Path.Combine(potentialFilePath, fileName); + var subDirectories = Directory.GetDirectories(rcloneMountPath, "*.*", SearchOption.TopDirectoryOnly); - _logger.Debug($"Searching {potentialFilePathWithFileName}..."); - - if (File.Exists(potentialFilePathWithFileName)) + foreach (var subDirectory in subDirectories) { - file = new(potentialFilePathWithFileName); - break; + FindFile(Path.Combine(rcloneMountPath, subDirectory), potentialFilePaths, fileName); } } @@ -120,9 +129,9 @@ public class SymlinkDownloader(String uri, String destinationPath, String path) throw new("Could not find file from rclone mount!"); } - _logger.Debug($"Found {file.FullName} at {file.FullName}"); + _logger.Debug($"Creating symbolic link from {file} to {destinationPath}"); - var result = TryCreateSymbolicLink(file.FullName, destinationPath); + var result = TryCreateSymbolicLink(file, destinationPath); if (!result) { @@ -131,7 +140,7 @@ public class SymlinkDownloader(String uri, String destinationPath, String path) DownloadComplete?.Invoke(this, new()); - return file.FullName; + return file; } catch (Exception ex) { @@ -161,6 +170,23 @@ public class SymlinkDownloader(String uri, String destinationPath, String path) return Task.CompletedTask; } + private String? FindFile(String rootPath, List filePaths, String fileName) + { + foreach (var potentialFilePath in filePaths) + { + var potentialFilePathWithFileName = Path.Combine(rootPath, potentialFilePath, fileName); + + _logger.Debug($"Searching {potentialFilePathWithFileName}..."); + + if (File.Exists(potentialFilePathWithFileName)) + { + return potentialFilePathWithFileName; + } + } + + return null; + } + private Boolean TryCreateSymbolicLink(String sourcePath, String symlinkPath) { try diff --git a/server/RdtClient.Service/Services/TorrentRunner.cs b/server/RdtClient.Service/Services/TorrentRunner.cs index 11f648d..07fc8ca 100644 --- a/server/RdtClient.Service/Services/TorrentRunner.cs +++ b/server/RdtClient.Service/Services/TorrentRunner.cs @@ -93,16 +93,6 @@ public class TorrentRunner(ILogger logger, Torrents torrents, Dow return; } - if (Settings.Get.DownloadClient.Client == Data.Enums.DownloadClient.Symlink) - { - var rcloneMountPath = Settings.Get.DownloadClient.RcloneMountPath; - - if (!Directory.Exists(rcloneMountPath)) - { - throw new($"Rclone mount path ({rcloneMountPath}) was not found!"); - } - } - var sw = new Stopwatch(); sw.Start();