Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f770473e5 | |||
| 5fe0f5750a |
@@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
public enum DeleteReason
|
public enum DeleteReason
|
||||||
{
|
{
|
||||||
|
None,
|
||||||
Stalled,
|
Stalled,
|
||||||
ImportFailed,
|
ImportFailed,
|
||||||
AllFilesBlocked
|
DownloadingMetadata,
|
||||||
|
AllFilesSkipped,
|
||||||
|
AllFilesSkippedByQBit,
|
||||||
|
AllFilesBlocked,
|
||||||
}
|
}
|
||||||
@@ -3,5 +3,6 @@
|
|||||||
public enum StrikeType
|
public enum StrikeType
|
||||||
{
|
{
|
||||||
Stalled,
|
Stalled,
|
||||||
|
DownloadingMetadata,
|
||||||
ImportFailed
|
ImportFailed
|
||||||
}
|
}
|
||||||
@@ -105,13 +105,14 @@ public class DownloadServiceTests : IClassFixture<DownloadServiceFixture>
|
|||||||
// Arrange
|
// Arrange
|
||||||
const string hash = "test-hash";
|
const string hash = "test-hash";
|
||||||
const string itemName = "test-item";
|
const string itemName = "test-item";
|
||||||
_fixture.Striker.StrikeAndCheckLimit(hash, itemName, 3, StrikeType.Stalled)
|
StrikeType strikeType = StrikeType.Stalled;
|
||||||
|
_fixture.Striker.StrikeAndCheckLimit(hash, itemName, 3, strikeType)
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
|
|
||||||
TestDownloadService sut = _fixture.CreateSut();
|
TestDownloadService sut = _fixture.CreateSut();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
bool result = await sut.StrikeAndCheckLimit(hash, itemName);
|
bool result = await sut.StrikeAndCheckLimit(hash, itemName, strikeType);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.ShouldBeTrue();
|
result.ShouldBeTrue();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Text.RegularExpressions;
|
|||||||
using Common.Configuration.ContentBlocker;
|
using Common.Configuration.ContentBlocker;
|
||||||
using Common.Configuration.DownloadCleaner;
|
using Common.Configuration.DownloadCleaner;
|
||||||
using Common.Configuration.QueueCleaner;
|
using Common.Configuration.QueueCleaner;
|
||||||
|
using Domain.Enums;
|
||||||
using Infrastructure.Interceptors;
|
using Infrastructure.Interceptors;
|
||||||
using Infrastructure.Verticals.ContentBlocker;
|
using Infrastructure.Verticals.ContentBlocker;
|
||||||
using Infrastructure.Verticals.DownloadClient;
|
using Infrastructure.Verticals.DownloadClient;
|
||||||
@@ -45,6 +46,6 @@ public class TestDownloadService : DownloadService
|
|||||||
|
|
||||||
// Expose protected methods for testing
|
// Expose protected methods for testing
|
||||||
public new void ResetStrikesOnProgress(string hash, long downloaded) => base.ResetStrikesOnProgress(hash, downloaded);
|
public new void ResetStrikesOnProgress(string hash, long downloaded) => base.ResetStrikesOnProgress(hash, downloaded);
|
||||||
public new Task<bool> StrikeAndCheckLimit(string hash, string itemName) => base.StrikeAndCheckLimit(hash, itemName);
|
public new Task<bool> StrikeAndCheckLimit(string hash, string itemName, StrikeType strikeType) => base.StrikeAndCheckLimit(hash, itemName, strikeType);
|
||||||
public new SeedingCheckResult ShouldCleanDownload(double ratio, TimeSpan seedingTime, Category category) => base.ShouldCleanDownload(ratio, seedingTime, category);
|
public new SeedingCheckResult ShouldCleanDownload(double ratio, TimeSpan seedingTime, Category category) => base.ShouldCleanDownload(ratio, seedingTime, category);
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FLM.QBittorrent" Version="1.0.0" />
|
<PackageReference Include="FLM.QBittorrent" Version="1.0.0" />
|
||||||
<PackageReference Include="FLM.Transmission" Version="1.0.2" />
|
<PackageReference Include="FLM.Transmission" Version="1.0.3" />
|
||||||
<PackageReference Include="Mapster" Version="7.4.0" />
|
<PackageReference Include="Mapster" Version="7.4.0" />
|
||||||
<PackageReference Include="MassTransit" Version="8.3.6" />
|
<PackageReference Include="MassTransit" Version="8.3.6" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" />
|
||||||
|
|||||||
@@ -114,7 +114,12 @@ public abstract class ArrClient : IArrClient
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task DeleteQueueItemAsync(ArrInstance arrInstance, QueueRecord record, bool removeFromClient)
|
public virtual async Task DeleteQueueItemAsync(
|
||||||
|
ArrInstance arrInstance,
|
||||||
|
QueueRecord record,
|
||||||
|
bool removeFromClient,
|
||||||
|
DeleteReason deleteReason
|
||||||
|
)
|
||||||
{
|
{
|
||||||
UriBuilder uriBuilder = new(arrInstance.Url);
|
UriBuilder uriBuilder = new(arrInstance.Url);
|
||||||
uriBuilder.Path = $"{uriBuilder.Path.TrimEnd('/')}/{GetQueueDeleteUrlPath(record.Id).TrimStart('/')}";
|
uriBuilder.Path = $"{uriBuilder.Path.TrimEnd('/')}/{GetQueueDeleteUrlPath(record.Id).TrimStart('/')}";
|
||||||
@@ -130,8 +135,9 @@ public abstract class ArrClient : IArrClient
|
|||||||
|
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
removeFromClient
|
removeFromClient
|
||||||
? "queue item deleted | {url} | {title}"
|
? "queue item deleted with reason {reason} | {url} | {title}"
|
||||||
: "queue item removed from arr | {url} | {title}",
|
: "queue item removed from arr with reason {reason} | {url} | {title}",
|
||||||
|
deleteReason.ToString(),
|
||||||
arrInstance.Url,
|
arrInstance.Url,
|
||||||
record.Title
|
record.Title
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public interface IArrClient
|
|||||||
|
|
||||||
Task<bool> ShouldRemoveFromQueue(InstanceType instanceType, QueueRecord record, bool isPrivateDownload);
|
Task<bool> ShouldRemoveFromQueue(InstanceType instanceType, QueueRecord record, bool isPrivateDownload);
|
||||||
|
|
||||||
Task DeleteQueueItemAsync(ArrInstance arrInstance, QueueRecord record, bool removeFromClient);
|
Task DeleteQueueItemAsync(ArrInstance arrInstance, QueueRecord record, bool removeFromClient, DeleteReason deleteReason);
|
||||||
|
|
||||||
Task RefreshItemsAsync(ArrInstance arrInstance, HashSet<SearchItem>? items);
|
Task RefreshItemsAsync(ArrInstance arrInstance, HashSet<SearchItem>? items);
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ public sealed class ContentBlocker : GenericHandler
|
|||||||
removeFromClient = false;
|
removeFromClient = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await arrClient.DeleteQueueItemAsync(instance, record, removeFromClient);
|
await arrClient.DeleteQueueItemAsync(instance, record, removeFromClient, DeleteReason.AllFilesBlocked);
|
||||||
await _notifier.NotifyQueueItemDeleted(removeFromClient, DeleteReason.AllFilesBlocked);
|
await _notifier.NotifyQueueItemDeleted(removeFromClient, DeleteReason.AllFilesBlocked);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ public class DelugeService : DownloadService, IDelugeService
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.IsPrivate = download.Private;
|
||||||
|
|
||||||
if (ignoredDownloads.Count > 0 && download.ShouldIgnore(ignoredDownloads))
|
if (ignoredDownloads.Count > 0 && download.ShouldIgnore(ignoredDownloads))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("skip | download is ignored | {name}", download.Name);
|
_logger.LogInformation("skip | download is ignored | {name}", download.Name);
|
||||||
@@ -79,6 +81,7 @@ public class DelugeService : DownloadService, IDelugeService
|
|||||||
{
|
{
|
||||||
_logger.LogDebug(exception, "failed to find torrent {hash} in the download client", hash);
|
_logger.LogDebug(exception, "failed to find torrent {hash} in the download client", hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool shouldRemove = contents?.Contents?.Count > 0;
|
bool shouldRemove = contents?.Contents?.Count > 0;
|
||||||
|
|
||||||
@@ -92,17 +95,15 @@ public class DelugeService : DownloadService, IDelugeService
|
|||||||
|
|
||||||
if (shouldRemove)
|
if (shouldRemove)
|
||||||
{
|
{
|
||||||
result.DeleteReason = DeleteReason.AllFilesBlocked;
|
// remove if all files are unwanted
|
||||||
|
result.ShouldRemove = true;
|
||||||
|
result.DeleteReason = DeleteReason.AllFilesSkipped;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.ShouldRemove = shouldRemove || await IsItemStuckAndShouldRemove(download);
|
// remove if download is stuck
|
||||||
result.IsPrivate = download.Private;
|
(result.ShouldRemove, result.DeleteReason) = await IsItemStuckAndShouldRemove(download);
|
||||||
|
|
||||||
if (!shouldRemove && result.ShouldRemove)
|
|
||||||
{
|
|
||||||
result.DeleteReason = DeleteReason.Stalled;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,33 +296,33 @@ public class DelugeService : DownloadService, IDelugeService
|
|||||||
await _client.ChangeFilesPriority(hash, sortedPriorities);
|
await _client.ChangeFilesPriority(hash, sortedPriorities);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> IsItemStuckAndShouldRemove(TorrentStatus status)
|
private async Task<(bool, DeleteReason)> IsItemStuckAndShouldRemove(TorrentStatus status)
|
||||||
{
|
{
|
||||||
if (_queueCleanerConfig.StalledMaxStrikes is 0)
|
if (_queueCleanerConfig.StalledMaxStrikes is 0)
|
||||||
{
|
{
|
||||||
return false;
|
return (false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_queueCleanerConfig.StalledIgnorePrivate && status.Private)
|
if (_queueCleanerConfig.StalledIgnorePrivate && status.Private)
|
||||||
{
|
{
|
||||||
// ignore private trackers
|
// ignore private trackers
|
||||||
_logger.LogDebug("skip stalled check | download is private | {name}", status.Name);
|
_logger.LogDebug("skip stalled check | download is private | {name}", status.Name);
|
||||||
return false;
|
return (false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.State is null || !status.State.Equals("Downloading", StringComparison.InvariantCultureIgnoreCase))
|
if (status.State is null || !status.State.Equals("Downloading", StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
return (false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.Eta > 0)
|
if (status.Eta > 0)
|
||||||
{
|
{
|
||||||
return false;
|
return (false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetStrikesOnProgress(status.Hash!, status.TotalDone);
|
ResetStrikesOnProgress(status.Hash!, status.TotalDone);
|
||||||
|
|
||||||
return await StrikeAndCheckLimit(status.Hash!, status.Name!);
|
return (await StrikeAndCheckLimit(status.Hash!, status.Name!, StrikeType.Stalled), DeleteReason.Stalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ProcessFiles(Dictionary<string, DelugeFileOrDirectory>? contents, Action<string, DelugeFileOrDirectory> processFile)
|
private static void ProcessFiles(Dictionary<string, DelugeFileOrDirectory>? contents, Action<string, DelugeFileOrDirectory> processFile)
|
||||||
|
|||||||
@@ -100,10 +100,11 @@ public abstract class DownloadService : IDownloadService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hash">The torrent hash.</param>
|
/// <param name="hash">The torrent hash.</param>
|
||||||
/// <param name="itemName">The name or title of the item.</param>
|
/// <param name="itemName">The name or title of the item.</param>
|
||||||
|
/// <param name="strikeType"></param>
|
||||||
/// <returns>True if the limit has been reached; otherwise, false.</returns>
|
/// <returns>True if the limit has been reached; otherwise, false.</returns>
|
||||||
protected async Task<bool> StrikeAndCheckLimit(string hash, string itemName)
|
protected async Task<bool> StrikeAndCheckLimit(string hash, string itemName, StrikeType strikeType)
|
||||||
{
|
{
|
||||||
return await _striker.StrikeAndCheckLimit(hash, itemName, _queueCleanerConfig.StalledMaxStrikes, StrikeType.Stalled);
|
return await _striker.StrikeAndCheckLimit(hash, itemName, _queueCleanerConfig.StalledMaxStrikes, strikeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SeedingCheckResult ShouldCleanDownload(double ratio, TimeSpan seedingTime, Category category)
|
protected SeedingCheckResult ShouldCleanDownload(double ratio, TimeSpan seedingTime, Category category)
|
||||||
|
|||||||
@@ -96,30 +96,26 @@ public class QBitService : DownloadService, IQBitService
|
|||||||
bool.TryParse(dictValue?.ToString(), out bool boolValue)
|
bool.TryParse(dictValue?.ToString(), out bool boolValue)
|
||||||
&& boolValue;
|
&& boolValue;
|
||||||
|
|
||||||
// if all files were blocked by qBittorrent
|
|
||||||
if (download is { CompletionOn: not null, Downloaded: null or 0 })
|
|
||||||
{
|
|
||||||
result.ShouldRemove = true;
|
|
||||||
result.DeleteReason = DeleteReason.AllFilesBlocked;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
IReadOnlyList<TorrentContent>? files = await _client.GetTorrentContentsAsync(hash);
|
IReadOnlyList<TorrentContent>? files = await _client.GetTorrentContentsAsync(hash);
|
||||||
|
|
||||||
// if all files are marked as skip
|
|
||||||
if (files?.Count is > 0 && files.All(x => x.Priority is TorrentContentPriority.Skip))
|
if (files?.Count is > 0 && files.All(x => x.Priority is TorrentContentPriority.Skip))
|
||||||
{
|
{
|
||||||
result.ShouldRemove = true;
|
result.ShouldRemove = true;
|
||||||
result.DeleteReason = DeleteReason.AllFilesBlocked;
|
|
||||||
|
// if all files were blocked by qBittorrent
|
||||||
|
if (download is { CompletionOn: not null, Downloaded: null or 0 })
|
||||||
|
{
|
||||||
|
result.DeleteReason = DeleteReason.AllFilesSkippedByQBit;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove if all files are unwanted
|
||||||
|
result.DeleteReason = DeleteReason.AllFilesSkipped;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.ShouldRemove = await IsItemStuckAndShouldRemove(download, result.IsPrivate);
|
// remove if download is stuck
|
||||||
|
(result.ShouldRemove, result.DeleteReason) = await IsItemStuckAndShouldRemove(download, result.IsPrivate);
|
||||||
if (result.ShouldRemove)
|
|
||||||
{
|
|
||||||
result.DeleteReason = DeleteReason.Stalled;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -337,30 +333,35 @@ public class QBitService : DownloadService, IQBitService
|
|||||||
_client.Dispose();
|
_client.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> IsItemStuckAndShouldRemove(TorrentInfo torrent, bool isPrivate)
|
private async Task<(bool, DeleteReason)> IsItemStuckAndShouldRemove(TorrentInfo torrent, bool isPrivate)
|
||||||
{
|
{
|
||||||
if (_queueCleanerConfig.StalledMaxStrikes is 0)
|
if (_queueCleanerConfig.StalledMaxStrikes is 0)
|
||||||
{
|
{
|
||||||
return false;
|
return (false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_queueCleanerConfig.StalledIgnorePrivate && isPrivate)
|
if (_queueCleanerConfig.StalledIgnorePrivate && isPrivate)
|
||||||
{
|
{
|
||||||
// ignore private trackers
|
// ignore private trackers
|
||||||
_logger.LogDebug("skip stalled check | download is private | {name}", torrent.Name);
|
_logger.LogDebug("skip stalled check | download is private | {name}", torrent.Name);
|
||||||
return false;
|
return (false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (torrent.State is not TorrentState.StalledDownload and not TorrentState.FetchingMetadata
|
if (torrent.State is not TorrentState.StalledDownload and not TorrentState.FetchingMetadata
|
||||||
and not TorrentState.ForcedFetchingMetadata)
|
and not TorrentState.ForcedFetchingMetadata)
|
||||||
{
|
{
|
||||||
// ignore other states
|
// ignore other states
|
||||||
return false;
|
return (false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetStrikesOnProgress(torrent.Hash, torrent.Downloaded ?? 0);
|
ResetStrikesOnProgress(torrent.Hash, torrent.Downloaded ?? 0);
|
||||||
|
|
||||||
return await StrikeAndCheckLimit(torrent.Hash, torrent.Name);
|
if (torrent.State is TorrentState.StalledDownload)
|
||||||
|
{
|
||||||
|
return (await StrikeAndCheckLimit(torrent.Hash, torrent.Name, StrikeType.Stalled), DeleteReason.Stalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (await StrikeAndCheckLimit(torrent.Hash, torrent.Name, StrikeType.DownloadingMetadata), DeleteReason.DownloadingMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IReadOnlyList<TorrentTracker>> GetTrackersAsync(string hash)
|
private async Task<IReadOnlyList<TorrentTracker>> GetTrackersAsync(string hash)
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ public class TransmissionService : DownloadService, ITransmissionService
|
|||||||
{
|
{
|
||||||
private readonly TransmissionConfig _config;
|
private readonly TransmissionConfig _config;
|
||||||
private readonly Client _client;
|
private readonly Client _client;
|
||||||
private TorrentInfo[]? _torrentsCache;
|
|
||||||
|
|
||||||
private static readonly string[] Fields =
|
private static readonly string[] Fields =
|
||||||
[
|
[
|
||||||
@@ -119,17 +118,15 @@ public class TransmissionService : DownloadService, ITransmissionService
|
|||||||
|
|
||||||
if (shouldRemove)
|
if (shouldRemove)
|
||||||
{
|
{
|
||||||
|
// remove if all files are unwanted
|
||||||
|
result.ShouldRemove = true;
|
||||||
result.DeleteReason = DeleteReason.AllFilesBlocked;
|
result.DeleteReason = DeleteReason.AllFilesBlocked;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove if all files are unwanted or download is stuck
|
// remove if download is stuck
|
||||||
result.ShouldRemove = shouldRemove || await IsItemStuckAndShouldRemove(download);
|
(result.ShouldRemove, result.DeleteReason) = await IsItemStuckAndShouldRemove(download);
|
||||||
|
|
||||||
if (!shouldRemove && result.ShouldRemove)
|
|
||||||
{
|
|
||||||
result.DeleteReason = DeleteReason.Stalled;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,60 +335,38 @@ public class TransmissionService : DownloadService, ITransmissionService
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> IsItemStuckAndShouldRemove(TorrentInfo torrent)
|
private async Task<(bool, DeleteReason)> IsItemStuckAndShouldRemove(TorrentInfo torrent)
|
||||||
{
|
{
|
||||||
if (_queueCleanerConfig.StalledMaxStrikes is 0)
|
if (_queueCleanerConfig.StalledMaxStrikes is 0)
|
||||||
{
|
{
|
||||||
return false;
|
return (false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_queueCleanerConfig.StalledIgnorePrivate && (torrent.IsPrivate ?? false))
|
if (_queueCleanerConfig.StalledIgnorePrivate && (torrent.IsPrivate ?? false))
|
||||||
{
|
{
|
||||||
// ignore private trackers
|
// ignore private trackers
|
||||||
_logger.LogDebug("skip stalled check | download is private | {name}", torrent.Name);
|
_logger.LogDebug("skip stalled check | download is private | {name}", torrent.Name);
|
||||||
return false;
|
return (false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (torrent.Status is not 4)
|
if (torrent.Status is not 4)
|
||||||
{
|
{
|
||||||
// not in downloading state
|
// not in downloading state
|
||||||
return false;
|
return (false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (torrent.Eta > 0)
|
if (torrent.Eta > 0)
|
||||||
{
|
{
|
||||||
return false;
|
return (false, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetStrikesOnProgress(torrent.HashString!, torrent.DownloadedEver ?? 0);
|
ResetStrikesOnProgress(torrent.HashString!, torrent.DownloadedEver ?? 0);
|
||||||
|
|
||||||
return await StrikeAndCheckLimit(torrent.HashString!, torrent.Name!);
|
return (await StrikeAndCheckLimit(torrent.HashString!, torrent.Name!, StrikeType.Stalled), DeleteReason.Stalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<TorrentInfo?> GetTorrentAsync(string hash)
|
private async Task<TorrentInfo?> GetTorrentAsync(string hash) =>
|
||||||
{
|
(await _client.TorrentGetAsync(Fields, hash))
|
||||||
TorrentInfo? torrent = _torrentsCache?
|
?.Torrents
|
||||||
.FirstOrDefault(x => x.HashString.Equals(hash, StringComparison.InvariantCultureIgnoreCase));
|
?.FirstOrDefault();
|
||||||
|
|
||||||
if (_torrentsCache is null || torrent is null)
|
|
||||||
{
|
|
||||||
// refresh cache
|
|
||||||
_torrentsCache = (await _client.TorrentGetAsync(Fields))
|
|
||||||
?.Torrents;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_torrentsCache?.Length is null or 0)
|
|
||||||
{
|
|
||||||
_logger.LogDebug("could not list torrents | {url}", _config.Url);
|
|
||||||
}
|
|
||||||
|
|
||||||
torrent = _torrentsCache?.FirstOrDefault(x => x.HashString.Equals(hash, StringComparison.InvariantCultureIgnoreCase));
|
|
||||||
|
|
||||||
if (torrent is null)
|
|
||||||
{
|
|
||||||
_logger.LogDebug("could not find torrent | {hash} | {url}", hash, _config.Url);
|
|
||||||
}
|
|
||||||
|
|
||||||
return torrent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ public sealed class QueueCleaner : GenericHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await arrClient.DeleteQueueItemAsync(instance, record, removeFromClient);
|
await arrClient.DeleteQueueItemAsync(instance, record, removeFromClient, deleteReason);
|
||||||
await _notifier.NotifyQueueItemDeleted(removeFromClient, deleteReason);
|
await _notifier.NotifyQueueItemDeleted(removeFromClient, deleteReason);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user