Fix QBit Import Path for Single File Torrents

This commit is contained in:
jwmann 2026-04-25 13:04:40 -04:00
parent 7f60f9de5a
commit 7c1169d0dd
No known key found for this signature in database
GPG key ID: FEAF88A73A68BD1B
2 changed files with 89 additions and 1 deletions

View file

@ -1,5 +1,7 @@
using Microsoft.Extensions.Logging;
using Moq;
using System.Text.Json;
using RdtClient.Data.Data;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.DebridClient;
@ -208,4 +210,58 @@ public class QBittorrentTest
Assert.NotNull(result);
Assert.False(result!.IsPrivate);
}
[Fact]
public async Task TorrentInfo_ShouldUseSelectedTopLevelFileName_WhenRootFileAddsOnlyTheExtension()
{
// Arrange
var previousMappedPath = SettingData.Get.DownloadClient.MappedPath;
SettingData.Get.DownloadClient.MappedPath = "/data/downloads";
try
{
var torrentRootName = "Example.Series.S01E01.1080p.WEB-DL-GROUP";
var selectedFileName = $"{torrentRootName}.mkv";
var torrent = new Torrent
{
Hash = "hash1",
Category = "tv",
Completed = DateTimeOffset.UtcNow,
RdName = torrentRootName,
RdFiles = JsonSerializer.Serialize(new List<DebridClientFile>
{
new()
{
Id = 1,
Path = $"/{selectedFileName}",
Bytes = 1000,
Selected = true
},
new()
{
Id = 2,
Path = $"/{torrentRootName}.nfo",
Bytes = 10,
Selected = false
}
}),
Type = DownloadType.Torrent
};
_torrentsMock.Setup(m => m.Get()).ReturnsAsync(new List<Torrent> { torrent });
// Act
var result = await _qBittorrent.TorrentInfo();
// Assert
Assert.Single(result);
Assert.Equal(Path.Combine("/data/downloads", "tv", selectedFileName) + Path.DirectorySeparatorChar, result[0].ContentPath);
Assert.Equal(torrentRootName, result[0].Name);
}
finally
{
SettingData.Get.DownloadClient.MappedPath = previousMappedPath;
}
}
}

View file

@ -204,6 +204,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
}
var torrentPath = downloadPath;
var contentPathName = GetContentPathName(torrent);
if (!String.IsNullOrWhiteSpace(torrent.RdName))
{
@ -214,7 +215,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
}
else
{
torrentPath = Path.Combine(downloadPath, torrent.RdName) + Path.DirectorySeparatorChar;
torrentPath = Path.Combine(downloadPath, contentPathName) + Path.DirectorySeparatorChar;
}
}
@ -328,6 +329,37 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
return results;
}
private static String GetContentPathName(Torrent torrent)
{
if (String.IsNullOrWhiteSpace(torrent.RdName))
{
return torrent.RdName ?? String.Empty;
}
var topLevelSelectedFiles = torrent.Files
.Where(m => m.Selected && !String.IsNullOrWhiteSpace(m.Path))
.Select(m => m.Path.Trim('/').Trim('\\'))
.Where(m => m.IndexOfAny(['/', '\\']) < 0)
.Select(Path.GetFileName)
.Where(m => !String.IsNullOrWhiteSpace(m))
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
if (topLevelSelectedFiles.Count == 1)
{
var selectedFileName = topLevelSelectedFiles[0]!;
var selectedFileBaseName = Path.GetFileNameWithoutExtension(selectedFileName);
if (!String.IsNullOrWhiteSpace(selectedFileBaseName) &&
selectedFileBaseName.Equals(torrent.RdName, StringComparison.OrdinalIgnoreCase))
{
return selectedFileName;
}
}
return torrent.RdName;
}
public async Task<IList<TorrentFileItem>?> TorrentFileContents(String hash)
{
var torrent = await torrents.GetByHash(hash);