Improve stalled and failed imports (#37)
This commit is contained in:
@@ -30,18 +30,19 @@ public sealed class DelugeService : DownloadServiceBase
|
||||
await _client.LoginAsync();
|
||||
}
|
||||
|
||||
public override async Task<bool> ShouldRemoveFromArrQueueAsync(string hash)
|
||||
public override async Task<RemoveResult> ShouldRemoveFromArrQueueAsync(string hash)
|
||||
{
|
||||
hash = hash.ToLowerInvariant();
|
||||
|
||||
DelugeContents? contents = null;
|
||||
RemoveResult result = new();
|
||||
|
||||
TorrentStatus? status = await GetTorrentStatus(hash);
|
||||
|
||||
if (status?.Hash is null)
|
||||
{
|
||||
_logger.LogDebug("failed to find torrent {hash} in the download client", hash);
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -63,7 +64,10 @@ public sealed class DelugeService : DownloadServiceBase
|
||||
}
|
||||
});
|
||||
|
||||
return shouldRemove || IsItemStuckAndShouldRemove(status);
|
||||
result.ShouldRemove = shouldRemove || IsItemStuckAndShouldRemove(status);
|
||||
result.IsPrivate = status.Private;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task BlockUnwantedFilesAsync(string hash)
|
||||
@@ -128,6 +132,18 @@ public sealed class DelugeService : DownloadServiceBase
|
||||
|
||||
private bool IsItemStuckAndShouldRemove(TorrentStatus status)
|
||||
{
|
||||
if (_queueCleanerConfig.StalledMaxStrikes is 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_queueCleanerConfig.StalledIgnorePrivate && status.Private)
|
||||
{
|
||||
// ignore private trackers
|
||||
_logger.LogDebug("skip stalled check | download is private | {name}", status.Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (status.State is null || !status.State.Equals("Downloading", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
@@ -146,7 +162,7 @@ public sealed class DelugeService : DownloadServiceBase
|
||||
return await _client.SendRequest<TorrentStatus?>(
|
||||
"web.get_torrent_status",
|
||||
hash,
|
||||
new[] { "hash", "state", "name", "eta" }
|
||||
new[] { "hash", "state", "name", "eta", "private" }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public abstract class DownloadServiceBase : IDownloadService
|
||||
|
||||
public abstract Task LoginAsync();
|
||||
|
||||
public abstract Task<bool> ShouldRemoveFromArrQueueAsync(string hash);
|
||||
public abstract Task<RemoveResult> ShouldRemoveFromArrQueueAsync(string hash);
|
||||
|
||||
public abstract Task BlockUnwantedFilesAsync(string hash);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public sealed class DummyDownloadService : DownloadServiceBase
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task<bool> ShouldRemoveFromArrQueueAsync(string hash)
|
||||
public override Task<RemoveResult> ShouldRemoveFromArrQueueAsync(string hash)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ public interface IDownloadService : IDisposable
|
||||
{
|
||||
public Task LoginAsync();
|
||||
|
||||
public Task<bool> ShouldRemoveFromArrQueueAsync(string hash);
|
||||
public Task<RemoveResult> ShouldRemoveFromArrQueueAsync(string hash);
|
||||
|
||||
public Task BlockUnwantedFilesAsync(string hash);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using Common.Configuration.DownloadClient;
|
||||
using Common.Configuration.DownloadClient;
|
||||
using Common.Configuration.QueueCleaner;
|
||||
using Infrastructure.Verticals.ContentBlocker;
|
||||
using Infrastructure.Verticals.ItemStriker;
|
||||
@@ -36,21 +36,35 @@ public sealed class QBitService : DownloadServiceBase
|
||||
await _client.LoginAsync(_config.Username, _config.Password);
|
||||
}
|
||||
|
||||
public override async Task<bool> ShouldRemoveFromArrQueueAsync(string hash)
|
||||
public override async Task<RemoveResult> ShouldRemoveFromArrQueueAsync(string hash)
|
||||
{
|
||||
RemoveResult result = new();
|
||||
TorrentInfo? torrent = (await _client.GetTorrentListAsync(new TorrentListQuery { Hashes = [hash] }))
|
||||
.FirstOrDefault();
|
||||
|
||||
if (torrent is null)
|
||||
{
|
||||
_logger.LogDebug("failed to find torrent {hash} in the download client", hash);
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
|
||||
TorrentProperties? torrentProperties = await _client.GetTorrentPropertiesAsync(hash);
|
||||
|
||||
if (torrentProperties is null)
|
||||
{
|
||||
_logger.LogDebug("failed to find torrent properties {hash} in the download client", hash);
|
||||
return result;
|
||||
}
|
||||
|
||||
result.IsPrivate = torrentProperties.AdditionalData.TryGetValue("is_private", out var dictValue) &&
|
||||
bool.TryParse(dictValue?.ToString(), out bool boolValue)
|
||||
&& boolValue;
|
||||
|
||||
// if all files were blocked by qBittorrent
|
||||
if (torrent is { CompletionOn: not null, Downloaded: null or 0 })
|
||||
{
|
||||
return true;
|
||||
result.ShouldRemove = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
IReadOnlyList<TorrentContent>? files = await _client.GetTorrentContentsAsync(hash);
|
||||
@@ -58,10 +72,13 @@ public sealed class QBitService : DownloadServiceBase
|
||||
// if all files are marked as skip
|
||||
if (files?.Count is > 0 && files.All(x => x.Priority is TorrentContentPriority.Skip))
|
||||
{
|
||||
return true;
|
||||
result.ShouldRemove = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
return IsItemStuckAndShouldRemove(torrent);
|
||||
result.ShouldRemove = IsItemStuckAndShouldRemove(torrent, result.IsPrivate);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task BlockUnwantedFilesAsync(string hash)
|
||||
@@ -95,8 +112,20 @@ public sealed class QBitService : DownloadServiceBase
|
||||
_client.Dispose();
|
||||
}
|
||||
|
||||
private bool IsItemStuckAndShouldRemove(TorrentInfo torrent)
|
||||
private bool IsItemStuckAndShouldRemove(TorrentInfo torrent, bool isPrivate)
|
||||
{
|
||||
if (_queueCleanerConfig.StalledMaxStrikes is 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_queueCleanerConfig.StalledIgnorePrivate && isPrivate)
|
||||
{
|
||||
// ignore private trackers
|
||||
_logger.LogDebug("skip stalled check | download is private | {name}", torrent.Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (torrent.State is not TorrentState.StalledDownload and not TorrentState.FetchingMetadata
|
||||
and not TorrentState.ForcedFetchingMetadata)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Infrastructure.Verticals.DownloadClient;
|
||||
|
||||
public sealed record RemoveResult
|
||||
{
|
||||
/// <summary>
|
||||
/// True if the download should be removed; otherwise false.
|
||||
/// </summary>
|
||||
public bool ShouldRemove { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the download is private; otherwise false.
|
||||
/// </summary>
|
||||
public bool IsPrivate { get; set; }
|
||||
}
|
||||
@@ -38,17 +38,19 @@ public sealed class TransmissionService : DownloadServiceBase
|
||||
await _client.GetSessionInformationAsync();
|
||||
}
|
||||
|
||||
public override async Task<bool> ShouldRemoveFromArrQueueAsync(string hash)
|
||||
public override async Task<RemoveResult> ShouldRemoveFromArrQueueAsync(string hash)
|
||||
{
|
||||
RemoveResult result = new();
|
||||
TorrentInfo? torrent = await GetTorrentAsync(hash);
|
||||
|
||||
if (torrent is null)
|
||||
{
|
||||
_logger.LogDebug("failed to find torrent {hash} in the download client", hash);
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool shouldRemove = torrent.FileStats?.Length > 0;
|
||||
result.IsPrivate = torrent.IsPrivate ?? false;
|
||||
|
||||
foreach (TransmissionTorrentFileStats? stats in torrent.FileStats ?? [])
|
||||
{
|
||||
@@ -65,8 +67,10 @@ public sealed class TransmissionService : DownloadServiceBase
|
||||
}
|
||||
}
|
||||
|
||||
// remove if all files are unwanted
|
||||
return shouldRemove || IsItemStuckAndShouldRemove(torrent);
|
||||
// remove if all files are unwanted or download is stuck
|
||||
result.ShouldRemove = shouldRemove || IsItemStuckAndShouldRemove(torrent);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task BlockUnwantedFilesAsync(string hash)
|
||||
@@ -116,6 +120,18 @@ public sealed class TransmissionService : DownloadServiceBase
|
||||
|
||||
private bool IsItemStuckAndShouldRemove(TorrentInfo torrent)
|
||||
{
|
||||
if (_queueCleanerConfig.StalledMaxStrikes is 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_queueCleanerConfig.StalledIgnorePrivate && (torrent.IsPrivate ?? false))
|
||||
{
|
||||
// ignore private trackers
|
||||
_logger.LogDebug("skip stalled check | download is private | {name}", torrent.Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (torrent.Status is not 4)
|
||||
{
|
||||
// not in downloading state
|
||||
@@ -144,7 +160,8 @@ public sealed class TransmissionService : DownloadServiceBase
|
||||
TorrentFields.ID,
|
||||
TorrentFields.ETA,
|
||||
TorrentFields.NAME,
|
||||
TorrentFields.STATUS
|
||||
TorrentFields.STATUS,
|
||||
TorrentFields.IS_PRIVATE
|
||||
];
|
||||
|
||||
// refresh cache
|
||||
|
||||
Reference in New Issue
Block a user