Add quick fix to reject torrents that error out as soon as they are added.

This commit is contained in:
Roger Far 2026-05-27 21:50:21 -06:00
parent 157fc8b2f2
commit d6f747c8d8
8 changed files with 66 additions and 43 deletions

View file

@ -1,3 +1 @@
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]

View file

@ -11,17 +11,17 @@
<ItemGroup>
<PackageReference Include="AllDebrid.NET" Version="1.0.18" />
<PackageReference Include="coverlet.collector" Version="10.0.0">
<PackageReference Include="coverlet.collector" Version="10.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="SharpCompress" Version="[0.42.1]" />
<PackageReference Include="TestableIO.System.IO.Abstractions" Version="22.1.1" />
<PackageReference Include="TestableIO.System.IO.Abstractions.TestingHelpers" Version="22.1.1" />
<PackageReference Include="TestableIO.System.IO.Abstractions.Wrappers" Version="22.1.1" />
<PackageReference Include="TorBox.NET" Version="1.8.1" />
<PackageReference Include="TorBox.NET" Version="2.0.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>

View file

@ -26,7 +26,7 @@
<PackageReference Include="Synology.Api.Client" Version="[0.3.93]" />
<PackageReference Include="TestableIO.System.IO.Abstractions" Version="22.1.1" />
<PackageReference Include="TestableIO.System.IO.Abstractions.Wrappers" Version="22.1.1" />
<PackageReference Include="TorBox.NET" Version="1.8.1" />
<PackageReference Include="TorBox.NET" Version="2.0.0" />
</ItemGroup>
<ItemGroup>

View file

@ -633,7 +633,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
}
}
public async Task TorrentsAddMagnet(String magnetLink, String? category, Int32? priority)
public async Task<Torrent> TorrentsAddMagnet(String magnetLink, String? category, Int32? priority)
{
logger.LogDebug($"Add magnet {category}");
@ -655,10 +655,10 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
Priority = priority ?? (Settings.Get.Integrations.Default.Priority > 0 ? Settings.Get.Integrations.Default.Priority : null)
};
await torrents.AddMagnetToDebridQueue(magnetLink, torrent);
return await torrents.AddMagnetToDebridQueue(magnetLink, torrent);
}
public async Task TorrentsAddFile(Byte[] fileBytes, String? category, Int32? priority)
public async Task<Torrent> TorrentsAddFile(Byte[] fileBytes, String? category, Int32? priority)
{
logger.LogDebug($"Add file {category}");
@ -680,7 +680,7 @@ public class QBittorrent(ILogger<QBittorrent> logger, Settings settings, Authent
Priority = priority ?? (Settings.Get.Integrations.Default.Priority > 0 ? Settings.Get.Integrations.Default.Priority : null)
};
await torrents.AddFileToDebridQueue(fileBytes, torrent);
return await torrents.AddFileToDebridQueue(fileBytes, torrent);
}
public async Task TorrentsSetCategory(String hash, String? category)

View file

@ -12,16 +12,14 @@ public class QBittorrentControllerTest
{
private readonly QBittorrentController _controller;
private readonly Mock<QBittorrent> _qBittorrentMock;
private readonly Mock<Torrents> _torrentsMock;
public QBittorrentControllerTest()
{
_qBittorrentMock = new(new Mock<ILogger<QBittorrent>>().Object, null!, null!, null!, null!);
_torrentsMock = new(null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!);
_controller = new(
new Mock<ILogger<QBittorrentController>>().Object,
_qBittorrentMock.Object,
new Mock<IHttpClientFactory>().Object);
_controller = new(new Mock<ILogger<QBittorrentController>>().Object, _qBittorrentMock.Object, new Mock<IHttpClientFactory>().Object, _torrentsMock.Object);
_controller.ControllerContext = new()
{
HttpContext = new DefaultHttpContext()

View file

@ -1,3 +1 @@
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]

View file

@ -10,7 +10,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="SharpCompress" Version="[0.42.1]" />
<PackageReference Include="xunit" Version="2.9.3" />

View file

@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Mvc;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.QBittorrent;
using RdtClient.Service.Services;
using RealDebridException = RDNET.RealDebridException;
using Torrent = RdtClient.Data.Models.Data.Torrent;
namespace RdtClient.Web.Controllers;
@ -14,7 +14,7 @@ namespace RdtClient.Web.Controllers;
[ApiController]
[Route("api/v2")]
[Route("qbittorrent/api/v2")]
public class QBittorrentController(ILogger<QBittorrentController> logger, QBittorrent qBittorrent, IHttpClientFactory httpClientFactory) : Controller
public class QBittorrentController(ILogger<QBittorrentController> logger, QBittorrent qBittorrent, IHttpClientFactory httpClientFactory, Torrents torrents) : Controller
{
[AllowAnonymous]
[Route("/version/api")]
@ -368,36 +368,33 @@ public class QBittorrentController(ILogger<QBittorrentController> logger, QBitto
foreach (var url in urls)
{
try
Torrent? torrent;
if (url.StartsWith("magnet"))
{
if (url.StartsWith("magnet"))
{
await qBittorrent.TorrentsAddMagnet(url.Trim(), request.Category, null);
}
else if (url.StartsWith("http"))
{
var httpClient = httpClientFactory.CreateClient();
var result = await httpClient.GetByteArrayAsync(url);
await qBittorrent.TorrentsAddFile(result, request.Category, null);
}
else
{
return BadRequest($"Invalid torrent link format {url}");
}
torrent = await qBittorrent.TorrentsAddMagnet(url.Trim(), request.Category, null);
}
catch (RealDebridException ex)
else if (url.StartsWith("http"))
{
// Infringing file.
if (ex.ErrorCode == 35)
{
return Ok("Fails.");
}
var httpClient = httpClientFactory.CreateClient();
var result = await httpClient.GetByteArrayAsync(url);
torrent = await qBittorrent.TorrentsAddFile(result, request.Category, null);
}
else
{
return BadRequest($"Invalid torrent link format {url}");
}
var addResult = await WaitForTorrent(torrent.TorrentId);
if (!addResult)
{
return Ok("Fails.");
}
}
return Ok();
}
[Authorize(Policy = "AuthSetting")]
[Route("torrents/add")]
[HttpPost]
@ -412,7 +409,14 @@ public class QBittorrentController(ILogger<QBittorrentController> logger, QBitto
await file.CopyToAsync(target);
var fileBytes = target.ToArray();
await qBittorrent.TorrentsAddFile(fileBytes, request.Category, request.Priority);
var torrent = await qBittorrent.TorrentsAddFile(fileBytes, request.Category, request.Priority);
var addResult = await WaitForTorrent(torrent.TorrentId);
if (!addResult)
{
return Ok("Fails.");
}
}
}
@ -671,6 +675,31 @@ public class QBittorrentController(ILogger<QBittorrentController> logger, QBitto
_ => String.Equals(torrent.State, filter, StringComparison.OrdinalIgnoreCase)
};
}
private async Task<Boolean> WaitForTorrent(Guid torrentId)
{
while (true)
{
var torrent = await torrents.GetById(torrentId);
if (torrent == null)
{
throw new($"Failed to add torrent: Not Found");
}
if (torrent.RdStatus == TorrentStatus.Error || torrent.Error != null)
{
return false;
}
if (torrent.RdStatus != TorrentStatus.Queued)
{
return true;
}
await Task.Delay(1000);
}
}
}
public class QBAuthLoginRequest