Expand enrichment to torrent files
This commit is contained in:
parent
5de0bac9d5
commit
80a8a1020c
7 changed files with 266 additions and 53 deletions
|
|
@ -75,8 +75,8 @@ Supports the following parameters:
|
||||||
[Description("When a torrent file or magnet is added, create a copy in this directory.")]
|
[Description("When a torrent file or magnet is added, create a copy in this directory.")]
|
||||||
public String? CopyAddedTorrents { get; set; } = null;
|
public String? CopyAddedTorrents { get; set; } = null;
|
||||||
|
|
||||||
[DisplayName("Magnet enrichment list")]
|
[DisplayName("Tracker enrichment list")]
|
||||||
[Description("Optional. Specify the URL of a tracker list file to be appended to magnet links.")]
|
[Description("Optional. Specify the URL of a tracker list file to be appended to magnet links and torrent files.")]
|
||||||
public String? MagnetTrackerEnrichment { get; set; } = null;
|
public String? MagnetTrackerEnrichment { get; set; } = null;
|
||||||
|
|
||||||
[DisplayName("Disable update notifications")]
|
[DisplayName("Disable update notifications")]
|
||||||
|
|
|
||||||
134
server/RdtClient.Service.Test/Services/EnricherTest.cs
Normal file
134
server/RdtClient.Service.Test/Services/EnricherTest.cs
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Moq;
|
||||||
|
using RdtClient.Service.Services;
|
||||||
|
using MonoTorrent.BEncoding;
|
||||||
|
|
||||||
|
namespace RdtClient.Service.Test.Services;
|
||||||
|
|
||||||
|
public class EnricherTest : IDisposable
|
||||||
|
{
|
||||||
|
private readonly MockRepository _mockRepository;
|
||||||
|
private readonly Mock<ILogger<Enricher>> _loggerMock;
|
||||||
|
private readonly Mock<ITrackerListGrabber> _trackerListGrabberMock;
|
||||||
|
|
||||||
|
public EnricherTest()
|
||||||
|
{
|
||||||
|
_mockRepository = new MockRepository(MockBehavior.Strict);
|
||||||
|
_loggerMock = _mockRepository.Create<ILogger<Enricher>>(MockBehavior.Loose);
|
||||||
|
_trackerListGrabberMock = _mockRepository.Create<ITrackerListGrabber>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_mockRepository.VerifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private const String TestMagnetLink = "magnet:?xt=urn:btih:1234567890123456789012345678901234567890&dn=TestFile&tr=http%3A%2F%2Ftracker1.com%2Fannounce&tr=http%3A%2F%2Ftracker2.com%2Fannounce";
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task EnrichMagnetLink_AddsNoTrackers_WhenNoTrackersFromTrackerGrabber()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
SetupTrackerListGrabber([]);
|
||||||
|
|
||||||
|
var enricher = new Enricher(_loggerMock.Object, _trackerListGrabberMock.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var enriched = await enricher.EnrichMagnetLink(TestMagnetLink);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(TestMagnetLink, enriched);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task EnrichMagnetLink_AddsTrackers_WhenTrackersFromTrackerGrabber()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
SetupTrackerListGrabber(["http://new-tracker.com/announce"]);
|
||||||
|
|
||||||
|
var Enricher = new Enricher(_loggerMock.Object, _trackerListGrabberMock.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var enriched = await Enricher.EnrichMagnetLink(TestMagnetLink);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(TestMagnetLink + $"&tr={Uri.EscapeDataString("http://new-tracker.com/announce")}", enriched);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task EnrichMagnetLink_DoesNotAddDuplicateTrackers_WhenTrackersFromTrackerGrabberAlreadyPresent()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
SetupTrackerListGrabber(["http://new-tracker.com/announce", "http://tracker1.com/announce"]);
|
||||||
|
|
||||||
|
var enricher = new Enricher(_loggerMock.Object, _trackerListGrabberMock.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var enriched = await enricher.EnrichMagnetLink(TestMagnetLink);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(TestMagnetLink + $"&tr={Uri.EscapeDataString("http://new-tracker.com/announce")}", enriched);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task EnrichMagnetLink_Throws_WhenTrackerGrabberThrows()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_trackerListGrabberMock
|
||||||
|
.Setup(t => t.GetTrackers())
|
||||||
|
.ThrowsAsync(new InvalidOperationException("Unable to fetch tracker list for enrichment."));
|
||||||
|
|
||||||
|
var enricher = new Enricher(_loggerMock.Object, _trackerListGrabberMock.Object);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
await Assert.ThrowsAsync<InvalidOperationException>(() => enricher.EnrichMagnetLink(TestMagnetLink));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task EnrichTorrentBytes_AddsTrackers_WhenTrackersFromTrackerGrabber()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var originalTracker = "http://tracker1.com/announce";
|
||||||
|
var newTracker = "http://new-tracker.com/announce";
|
||||||
|
|
||||||
|
var torrentDict = new BEncodedDictionary
|
||||||
|
{
|
||||||
|
["announce"] = new BEncodedString(originalTracker),
|
||||||
|
["announce-list"] = new BEncodedList
|
||||||
|
{
|
||||||
|
new BEncodedList { new BEncodedString(originalTracker) }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var originalTorrentBytes = torrentDict.Encode();
|
||||||
|
|
||||||
|
SetupTrackerListGrabber(new[] { newTracker });
|
||||||
|
var enricher = new Enricher(_loggerMock.Object, _trackerListGrabberMock.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var enrichedBytes = await enricher.EnrichTorrentBytes(originalTorrentBytes);
|
||||||
|
var enrichedDict = BEncodedValue.Decode<BEncodedDictionary>(enrichedBytes);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(enrichedDict.ContainsKey("announce"));
|
||||||
|
Assert.True(enrichedDict.ContainsKey("announce-list"));
|
||||||
|
|
||||||
|
var announceList = (BEncodedList)enrichedDict["announce-list"];
|
||||||
|
var flattened = announceList.Cast<BEncodedList>().SelectMany(l => l.Cast<BEncodedString>().Select(s => s.Text)).ToList();
|
||||||
|
|
||||||
|
Assert.Contains(originalTracker, flattened);
|
||||||
|
Assert.Contains(newTracker, flattened);
|
||||||
|
|
||||||
|
var announce = ((BEncodedString)enrichedDict["announce"]).Text;
|
||||||
|
Assert.Equal(flattened.First(), announce);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupTrackerListGrabber(String[] trackerList)
|
||||||
|
{
|
||||||
|
_trackerListGrabberMock
|
||||||
|
.Setup(t => t.GetTrackers())
|
||||||
|
.ReturnsAsync(trackerList)
|
||||||
|
.Verifiable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,13 +20,13 @@ class Mocks
|
||||||
public readonly Mock<ILogger<TorrentsService>> TorrentsLoggerMock;
|
public readonly Mock<ILogger<TorrentsService>> TorrentsLoggerMock;
|
||||||
public readonly Mock<IDownloads> DownloadsMock;
|
public readonly Mock<IDownloads> DownloadsMock;
|
||||||
public readonly Mock<ITorrentData> TorrentDataMock;
|
public readonly Mock<ITorrentData> TorrentDataMock;
|
||||||
public readonly Mock<ITrackerListGrabber> TrackerListGrabberMock;
|
public readonly Mock<IEnricher> EnricherMock;
|
||||||
|
|
||||||
public Mocks()
|
public Mocks()
|
||||||
{
|
{
|
||||||
TorrentDataMock = new();
|
TorrentDataMock = new();
|
||||||
DownloadsMock = new();
|
DownloadsMock = new();
|
||||||
TrackerListGrabberMock = new();
|
EnricherMock = new();
|
||||||
|
|
||||||
TorrentsLoggerMock = new();
|
TorrentsLoggerMock = new();
|
||||||
|
|
||||||
|
|
@ -104,7 +104,7 @@ public class TorrentsTest
|
||||||
mocks.DownloadsMock.Object,
|
mocks.DownloadsMock.Object,
|
||||||
mocks.ProcessFactoryMock.Object,
|
mocks.ProcessFactoryMock.Object,
|
||||||
fileSystemMock,
|
fileSystemMock,
|
||||||
mocks.TrackerListGrabberMock.Object,
|
mocks.EnricherMock.Object,
|
||||||
null!, // Torrent Clients are not used by `RunTorrentComplete`, this is fine
|
null!, // Torrent Clients are not used by `RunTorrentComplete`, this is fine
|
||||||
null!,
|
null!,
|
||||||
null!,
|
null!,
|
||||||
|
|
@ -170,7 +170,7 @@ public class TorrentsTest
|
||||||
mocks.DownloadsMock.Object,
|
mocks.DownloadsMock.Object,
|
||||||
mocks.ProcessFactoryMock.Object,
|
mocks.ProcessFactoryMock.Object,
|
||||||
fileSystemMock,
|
fileSystemMock,
|
||||||
mocks.TrackerListGrabberMock.Object,
|
mocks.EnricherMock.Object,
|
||||||
null!, // Torrent Clients are not used by `RunTorrentComplete`, this is fine
|
null!, // Torrent Clients are not used by `RunTorrentComplete`, this is fine
|
||||||
null!,
|
null!,
|
||||||
null!,
|
null!,
|
||||||
|
|
@ -218,7 +218,7 @@ public class TorrentsTest
|
||||||
mocks.DownloadsMock.Object,
|
mocks.DownloadsMock.Object,
|
||||||
mocks.ProcessFactoryMock.Object,
|
mocks.ProcessFactoryMock.Object,
|
||||||
fileSystemMock,
|
fileSystemMock,
|
||||||
mocks.TrackerListGrabberMock.Object,
|
mocks.EnricherMock.Object,
|
||||||
null!, // Torrent Clients are not used by `RunTorrentComplete`, this is fine
|
null!, // Torrent Clients are not used by `RunTorrentComplete`, this is fine
|
||||||
null!,
|
null!,
|
||||||
null!,
|
null!,
|
||||||
|
|
@ -285,7 +285,7 @@ public class TorrentsTest
|
||||||
mocks.DownloadsMock.Object,
|
mocks.DownloadsMock.Object,
|
||||||
mocks.ProcessFactoryMock.Object,
|
mocks.ProcessFactoryMock.Object,
|
||||||
fileSystemMock,
|
fileSystemMock,
|
||||||
mocks.TrackerListGrabberMock.Object,
|
mocks.EnricherMock.Object,
|
||||||
null!, // Torrent Clients are not used by `RunTorrentComplete`, this is fine
|
null!, // Torrent Clients are not used by `RunTorrentComplete`, this is fine
|
||||||
null!,
|
null!,
|
||||||
null!,
|
null!,
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ public static class DiConfig
|
||||||
|
|
||||||
services.AddSingleton<IDownloadableFileFilter, DownloadableFileFilter>();
|
services.AddSingleton<IDownloadableFileFilter, DownloadableFileFilter>();
|
||||||
services.AddSingleton<ITrackerListGrabber, TrackerListGrabber>();
|
services.AddSingleton<ITrackerListGrabber, TrackerListGrabber>();
|
||||||
|
services.AddSingleton<IEnricher, Enricher>();
|
||||||
|
|
||||||
services.AddSingleton<IAuthorizationHandler, AuthSettingHandler>();
|
services.AddSingleton<IAuthorizationHandler, AuthSettingHandler>();
|
||||||
|
|
||||||
|
|
|
||||||
111
server/RdtClient.Service/Services/Enricher.cs
Normal file
111
server/RdtClient.Service/Services/Enricher.cs
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
using System.Web;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using MonoTorrent.BEncoding;
|
||||||
|
|
||||||
|
namespace RdtClient.Service.Services;
|
||||||
|
|
||||||
|
public interface IEnricher
|
||||||
|
{
|
||||||
|
Task<String> EnrichMagnetLink(String magnetLink);
|
||||||
|
Task<Byte[]> EnrichTorrentBytes(Byte[] torrentBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enriches magnet links and torrents by adding trackers from the tracker list grabber.
|
||||||
|
/// </summary>
|
||||||
|
public class Enricher(ILogger<Enricher> logger, ITrackerListGrabber trackerListGrabber) : IEnricher
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Add trackers from the tracker list grabber to the magnet link.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="magnetLink">Magnet link to add trackres to. Is not modified</param>
|
||||||
|
/// <returns>Magnet link with additional trackers</returns>
|
||||||
|
public async Task<String> EnrichMagnetLink(String magnetLink)
|
||||||
|
{
|
||||||
|
var newTrackers = await trackerListGrabber.GetTrackers();
|
||||||
|
|
||||||
|
var uri = new Uri(magnetLink);
|
||||||
|
var query = HttpUtility.ParseQueryString(uri.Query);
|
||||||
|
|
||||||
|
var existingTrackers = query.GetValues("tr") ?? [];
|
||||||
|
var allTrackers = existingTrackers.Concat(newTrackers).Distinct(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
var trackerQuery = String.Join("&tr=", allTrackers.Select(Uri.EscapeDataString));
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(trackerQuery))
|
||||||
|
{
|
||||||
|
trackerQuery = "&tr=" + trackerQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
var baseWithoutTrackers = magnetLink.Split("&tr=")[0];
|
||||||
|
|
||||||
|
var separator = baseWithoutTrackers.Contains('?') ? "&" : "?";
|
||||||
|
|
||||||
|
var newUri = baseWithoutTrackers + separator + trackerQuery.TrimStart('&');
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_ = new Uri(newUri);
|
||||||
|
}
|
||||||
|
catch (UriFormatException ex)
|
||||||
|
{
|
||||||
|
logger.LogWarning(ex, "Failed to enrich magnet link: {newUri}", newUri);
|
||||||
|
throw new InvalidOperationException($"Failed to enrich magnet link: {newUri}", ex);
|
||||||
|
}
|
||||||
|
return newUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add trackers from the tracker list grabber to the .torrent file bytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="torrentBytes">Torrent file bytes to add trackers to. Is not modified</param>
|
||||||
|
/// <returns>Torrent file bytes with additional trackers</returns>
|
||||||
|
public async Task<Byte[]> EnrichTorrentBytes(Byte[] torrentBytes)
|
||||||
|
{
|
||||||
|
var newTrackers = await trackerListGrabber.GetTrackers();
|
||||||
|
|
||||||
|
if (torrentBytes == null) throw new ArgumentNullException(nameof(torrentBytes));
|
||||||
|
var torrentDict = BEncodedValue.Decode<BEncodedDictionary>(torrentBytes);
|
||||||
|
|
||||||
|
|
||||||
|
if (!torrentDict.TryGetValue("announce-list", out var announceListValue) || announceListValue is not BEncodedList announceList)
|
||||||
|
{
|
||||||
|
announceList = new BEncodedList();
|
||||||
|
if (torrentDict.TryGetValue("announce", out var announceValue) && announceValue is BEncodedString announceStr)
|
||||||
|
{
|
||||||
|
announceList.Add(new BEncodedList { announceStr });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var existingTrackers = new HashSet<String>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
foreach (var tier in announceList)
|
||||||
|
{
|
||||||
|
if (tier is BEncodedList tierList)
|
||||||
|
{
|
||||||
|
foreach (var tracker in tierList)
|
||||||
|
{
|
||||||
|
if (tracker is BEncodedString trackerStr)
|
||||||
|
{
|
||||||
|
existingTrackers.Add(trackerStr.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var tracker in newTrackers)
|
||||||
|
{
|
||||||
|
if (!existingTrackers.Contains(tracker))
|
||||||
|
{
|
||||||
|
announceList.Add(new BEncodedList { new BEncodedString(tracker) });
|
||||||
|
existingTrackers.Add(tracker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
torrentDict["announce-list"] = announceList;
|
||||||
|
if (announceList.Count > 0 && announceList[0] is BEncodedList firstTier && firstTier.Count > 0 && firstTier[0] is BEncodedString firstTracker)
|
||||||
|
{
|
||||||
|
torrentDict["announce"] = firstTracker;
|
||||||
|
}
|
||||||
|
|
||||||
|
return torrentDict.Encode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,7 +25,7 @@ public class Torrents(
|
||||||
IDownloads downloads,
|
IDownloads downloads,
|
||||||
IProcessFactory processFactory,
|
IProcessFactory processFactory,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ITrackerListGrabber trackerListGrabber,
|
IEnricher enricher,
|
||||||
AllDebridTorrentClient allDebridTorrentClient,
|
AllDebridTorrentClient allDebridTorrentClient,
|
||||||
PremiumizeTorrentClient premiumizeTorrentClient,
|
PremiumizeTorrentClient premiumizeTorrentClient,
|
||||||
RealDebridTorrentClient realDebridTorrentClient,
|
RealDebridTorrentClient realDebridTorrentClient,
|
||||||
|
|
@ -33,7 +33,7 @@ public class Torrents(
|
||||||
TorBoxTorrentClient torBoxTorrentClient)
|
TorBoxTorrentClient torBoxTorrentClient)
|
||||||
{
|
{
|
||||||
private static readonly SemaphoreSlim RealDebridUpdateLock = new(1, 1);
|
private static readonly SemaphoreSlim RealDebridUpdateLock = new(1, 1);
|
||||||
private readonly ITrackerListGrabber _trackerListGrabber = trackerListGrabber;
|
|
||||||
private static readonly JsonSerializerOptions JsonSerializerOptions = new()
|
private static readonly JsonSerializerOptions JsonSerializerOptions = new()
|
||||||
{
|
{
|
||||||
ReferenceHandler = ReferenceHandler.IgnoreCycles
|
ReferenceHandler = ReferenceHandler.IgnoreCycles
|
||||||
|
|
@ -109,45 +109,9 @@ public class Torrents(
|
||||||
await torrentData.UpdateCategory(torrent.TorrentId, category);
|
await torrentData.UpdateCategory(torrent.TorrentId, category);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<String> EnrichMagnetLink(String magnetLink)
|
|
||||||
{
|
|
||||||
if (String.IsNullOrWhiteSpace(Settings.Get.General.MagnetTrackerEnrichment))
|
|
||||||
{
|
|
||||||
return magnetLink;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var newTrackers = await _trackerListGrabber.GetTrackers();
|
|
||||||
|
|
||||||
var uri = new Uri(magnetLink);
|
|
||||||
var query = HttpUtility.ParseQueryString(uri.Query);
|
|
||||||
var existingTrackers = query.GetValues("tr") ?? [];
|
|
||||||
var allTrackers = existingTrackers.Concat(newTrackers).Distinct(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
var trackerQuery = String.Join("&tr=", allTrackers.Select(Uri.EscapeDataString));
|
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(trackerQuery))
|
|
||||||
{
|
|
||||||
trackerQuery = "&tr=" + trackerQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
var baseWithoutTrackers = magnetLink.Split(["&tr="], StringSplitOptions.None)[0];
|
|
||||||
var separator = baseWithoutTrackers.Contains('?') ? "&" : "?";
|
|
||||||
|
|
||||||
return baseWithoutTrackers + separator + trackerQuery.TrimStart('&');
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
logger.LogError(ex, "{Message}, trying to enrich {Magnet}", ex.Message, magnetLink);
|
|
||||||
|
|
||||||
return magnetLink;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Torrent> AddMagnetToDebridQueue(String magnetLink, Torrent torrent)
|
public async Task<Torrent> AddMagnetToDebridQueue(String magnetLink, Torrent torrent)
|
||||||
{
|
{
|
||||||
var enriched = await EnrichMagnetLink(magnetLink);
|
var enriched = await enricher.EnrichMagnetLink(magnetLink);
|
||||||
MagnetLink magnet;
|
MagnetLink magnet;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -166,7 +130,7 @@ public class Torrents(
|
||||||
var newTorrent = await AddQueued(hash, enriched, false, torrent);
|
var newTorrent = await AddQueued(hash, enriched, false, torrent);
|
||||||
|
|
||||||
Log($"Adding {hash} (magnet link) to queue", newTorrent);
|
Log($"Adding {hash} (magnet link) to queue", newTorrent);
|
||||||
await CopyAddedTorrent(magnet.Name!, enriched);
|
await CopyAddedTorrent(magnet.Name!, magnetLink);
|
||||||
|
|
||||||
return newTorrent;
|
return newTorrent;
|
||||||
}
|
}
|
||||||
|
|
@ -178,9 +142,12 @@ public class Torrents(
|
||||||
var fileAsBase64 = Convert.ToBase64String(bytes);
|
var fileAsBase64 = Convert.ToBase64String(bytes);
|
||||||
logger.LogDebug($"bytes {bytes}");
|
logger.LogDebug($"bytes {bytes}");
|
||||||
|
|
||||||
|
var enriched = await enricher.EnrichTorrentBytes(bytes);
|
||||||
|
logger.LogDebug($"enriched bytes {enriched}");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
monoTorrent = await MonoTorrent.Torrent.LoadAsync(bytes);
|
monoTorrent = await MonoTorrent.Torrent.LoadAsync(enriched);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ public class TrackerListGrabber : ITrackerListGrabber
|
||||||
public async Task<String[]> GetTrackers()
|
public async Task<String[]> GetTrackers()
|
||||||
{
|
{
|
||||||
var trackerUrlList = Settings.Get.General.MagnetTrackerEnrichment;
|
var trackerUrlList = Settings.Get.General.MagnetTrackerEnrichment;
|
||||||
if (string.IsNullOrWhiteSpace(trackerUrlList))
|
if (String.IsNullOrWhiteSpace(trackerUrlList))
|
||||||
{
|
{
|
||||||
return Array.Empty<String>();
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -26,9 +26,9 @@ public class TrackerListGrabber : ITrackerListGrabber
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return Array.Empty<String>();
|
throw new InvalidOperationException("Unable to fetch tracker list for enrichment.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue