Add recursive searching for the symlink downloader.
This commit is contained in:
parent
0bfb4974d8
commit
dbb502a164
6 changed files with 49 additions and 31 deletions
|
|
@ -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/),
|
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).
|
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
|
## [2.0.73] - 2024-04-11
|
||||||
### Changed
|
### Changed
|
||||||
- Fixed another issue with the symlinker and file resolver.
|
- Fixed another issue with the symlinker and file resolver.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "rdt-client",
|
"name": "rdt-client",
|
||||||
"version": "2.0.73",
|
"version": "2.0.74",
|
||||||
"description": "This is a web interface to manage your torrents on Real-Debrid.",
|
"description": "This is a web interface to manage your torrents on Real-Debrid.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ http://127.0.0.1:6800/jsonrpc.")]
|
||||||
public String? Aria2cDownloadPath { get; set; } = null;
|
public String? Aria2cDownloadPath { get; set; } = null;
|
||||||
|
|
||||||
[DisplayName("Rclone mount path (only used for the Symlink Downloader)")]
|
[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/";
|
public String RcloneMountPath { get; set; } = "/mnt/rd/";
|
||||||
|
|
||||||
[DisplayName("Log level")]
|
[DisplayName("Log level")]
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,6 @@ public class DownloadClient(Download download, Torrent torrent, String destinati
|
||||||
|
|
||||||
var result = await Downloader.Download();
|
var result = await Downloader.Download();
|
||||||
|
|
||||||
await Task.Delay(1000);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,14 @@ public class SymlinkDownloader(String uri, String destinationPath, String path)
|
||||||
var filePath = new FileInfo(path);
|
var filePath = new FileInfo(path);
|
||||||
|
|
||||||
var rcloneMountPath = Settings.Get.DownloadClient.RcloneMountPath.TrimEnd(['\\', '/']);
|
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 fileName = filePath.Name;
|
||||||
var fileExtension = filePath.Extension;
|
var fileExtension = filePath.Extension;
|
||||||
var fileNameWithoutExtension = fileName.Replace(fileExtension, "");
|
var fileNameWithoutExtension = fileName.Replace(fileExtension, "");
|
||||||
|
|
@ -31,9 +39,9 @@ public class SymlinkDownloader(String uri, String destinationPath, String path)
|
||||||
|
|
||||||
List<String> unWantedExtensions =
|
List<String> unWantedExtensions =
|
||||||
[
|
[
|
||||||
"zip",
|
".zip",
|
||||||
"rar",
|
".rar",
|
||||||
"tar"
|
".tar"
|
||||||
];
|
];
|
||||||
|
|
||||||
if (unWantedExtensions.Any(m => fileExtension == m))
|
if (unWantedExtensions.Any(m => fileExtension == m))
|
||||||
|
|
@ -54,7 +62,7 @@ public class SymlinkDownloader(String uri, String destinationPath, String path)
|
||||||
var directoryInfo = new DirectoryInfo(searchPath);
|
var directoryInfo = new DirectoryInfo(searchPath);
|
||||||
while (directoryInfo.Parent != null)
|
while (directoryInfo.Parent != null)
|
||||||
{
|
{
|
||||||
potentialFilePaths.Add(directoryInfo.FullName);
|
potentialFilePaths.Add(directoryInfo.Name);
|
||||||
directoryInfo = directoryInfo.Parent;
|
directoryInfo = directoryInfo.Parent;
|
||||||
|
|
||||||
if (directoryInfo.FullName.TrimEnd(['\\', '/']) == rcloneMountPath)
|
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(fileName);
|
||||||
potentialFilePaths.Add(Path.Combine(rcloneMountPath, fileNameWithoutExtension));
|
potentialFilePaths.Add(fileNameWithoutExtension);
|
||||||
|
|
||||||
FileInfo? file = null;
|
potentialFilePaths = potentialFilePaths.Distinct().ToList();
|
||||||
|
|
||||||
|
String? file = null;
|
||||||
|
|
||||||
for (var retryCount = 0; retryCount < MaxRetries; retryCount++)
|
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})...");
|
_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}...");
|
foreach (var subDirectory in subDirectories)
|
||||||
|
|
||||||
if (File.Exists(potentialFilePathWithFileName))
|
|
||||||
{
|
{
|
||||||
file = new(potentialFilePathWithFileName);
|
FindFile(Path.Combine(rcloneMountPath, subDirectory), potentialFilePaths, fileName);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,9 +129,9 @@ public class SymlinkDownloader(String uri, String destinationPath, String path)
|
||||||
throw new("Could not find file from rclone mount!");
|
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)
|
if (!result)
|
||||||
{
|
{
|
||||||
|
|
@ -131,7 +140,7 @@ public class SymlinkDownloader(String uri, String destinationPath, String path)
|
||||||
|
|
||||||
DownloadComplete?.Invoke(this, new());
|
DownloadComplete?.Invoke(this, new());
|
||||||
|
|
||||||
return file.FullName;
|
return file;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -161,6 +170,23 @@ public class SymlinkDownloader(String uri, String destinationPath, String path)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String? FindFile(String rootPath, List<String> 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)
|
private Boolean TryCreateSymbolicLink(String sourcePath, String symlinkPath)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -93,16 +93,6 @@ public class TorrentRunner(ILogger<TorrentRunner> logger, Torrents torrents, Dow
|
||||||
return;
|
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();
|
var sw = new Stopwatch();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue