refactored method names; fixed qbit category creation

This commit is contained in:
Flaminel
2025-02-22 01:01:19 +02:00
parent 1ad07b1f51
commit e006521dc9
8 changed files with 82 additions and 33 deletions
@@ -40,11 +40,11 @@ public class TestDownloadService : DownloadService
public override Task<StalledResult> ShouldRemoveFromArrQueueAsync(string hash) => Task.FromResult(new StalledResult()); public override Task<StalledResult> ShouldRemoveFromArrQueueAsync(string hash) => Task.FromResult(new StalledResult());
public override Task<BlockFilesResult> BlockUnwantedFilesAsync(string hash, BlocklistType blocklistType, public override Task<BlockFilesResult> BlockUnwantedFilesAsync(string hash, BlocklistType blocklistType,
ConcurrentBag<string> patterns, ConcurrentBag<Regex> regexes) => Task.FromResult(new BlockFilesResult()); ConcurrentBag<string> patterns, ConcurrentBag<Regex> regexes) => Task.FromResult(new BlockFilesResult());
public override Task DeleteDownloadAsync(string hash) => Task.CompletedTask;
public override Task DeleteDownload(string hash) => Task.CompletedTask; public override Task CreateCategoryAsync(string name) => Task.CompletedTask;
public override Task<List<object>?> GetDownloadsToBeCleaned(List<CleanCategory> categories) => Task.FromResult<List<object>?>(null); public override Task<List<object>?> GetDownloadsToBeCleanedAsync(List<CleanCategory> categories) => Task.FromResult<List<object>?>(null);
public override Task<List<object>?> GetDownloadsToChangeCategory(List<string> categories) => Task.FromResult<List<object>?>(null); public override Task<List<object>?> GetDownloadsToChangeCategoryAsync(List<string> categories) => Task.FromResult<List<object>?>(null);
public override Task CleanDownloads(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes) => Task.CompletedTask; public override Task CleanDownloadsAsync(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes) => Task.CompletedTask;
public override Task ChangeCategoryForNoHardLinksAsync(List<object> downloads, HashSet<string> excludedHashes) => Task.CompletedTask; public override Task ChangeCategoryForNoHardLinksAsync(List<object> downloads, HashSet<string> excludedHashes) => Task.CompletedTask;
// Expose protected methods for testing // Expose protected methods for testing
@@ -19,6 +19,8 @@ public sealed class DownloadCleaner : GenericHandler
private readonly DownloadCleanerConfig _config; private readonly DownloadCleanerConfig _config;
private readonly HashSet<string> _excludedHashes = []; private readonly HashSet<string> _excludedHashes = [];
private static bool _hardLinkCategoryCreated = false;
public DownloadCleaner( public DownloadCleaner(
ILogger<DownloadCleaner> logger, ILogger<DownloadCleaner> logger,
IOptions<DownloadCleanerConfig> config, IOptions<DownloadCleanerConfig> config,
@@ -60,12 +62,18 @@ public sealed class DownloadCleaner : GenericHandler
await _downloadService.LoginAsync(); await _downloadService.LoginAsync();
List<object>? downloadsToBeCleaned = await _downloadService.GetDownloadsToBeCleaned(_config.Categories); List<object>? downloadsToBeCleaned = await _downloadService.GetDownloadsToBeCleanedAsync(_config.Categories);
List<object>? downloadsToChangeCategory = null; List<object>? downloadsToChangeCategory = null;
if (!string.IsNullOrEmpty(_config.NoHardlinksCategory) && _config.HardlinkCategories?.Count > 0) if (!string.IsNullOrEmpty(_config.NoHardlinksCategory) && _config.HardlinkCategories?.Count > 0)
{ {
downloadsToChangeCategory = await _downloadService.GetDownloadsToChangeCategory(_config.HardlinkCategories); if (!_hardLinkCategoryCreated)
{
await _downloadService.CreateCategoryAsync(_config.NoHardlinksCategory);
_hardLinkCategoryCreated = true;
}
downloadsToChangeCategory = await _downloadService.GetDownloadsToChangeCategoryAsync(_config.HardlinkCategories);
} }
bool hasDownloadsToClean = downloadsToBeCleaned?.Count > 0; bool hasDownloadsToClean = downloadsToBeCleaned?.Count > 0;
@@ -95,7 +103,7 @@ public sealed class DownloadCleaner : GenericHandler
if (hasDownloadsToClean) if (hasDownloadsToClean)
{ {
await _downloadService.CleanDownloads(downloadsToBeCleaned, _config.Categories, _excludedHashes); await _downloadService.CleanDownloadsAsync(downloadsToBeCleaned, _config.Categories, _excludedHashes);
} }
else else
{ {
@@ -196,7 +196,7 @@ public class DelugeService : DownloadService, IDelugeService
return result; return result;
} }
public override async Task<List<object>?> GetDownloadsToBeCleaned(List<CleanCategory> categories) public override async Task<List<object>?> GetDownloadsToBeCleanedAsync(List<CleanCategory> categories)
{ {
return (await _client.GetStatusForAllTorrents()) return (await _client.GetStatusForAllTorrents())
?.Where(x => !string.IsNullOrEmpty(x.Hash)) ?.Where(x => !string.IsNullOrEmpty(x.Hash))
@@ -206,13 +206,13 @@ public class DelugeService : DownloadService, IDelugeService
.ToList(); .ToList();
} }
public override Task<List<object>?> GetDownloadsToChangeCategory(List<string> categories) public override Task<List<object>?> GetDownloadsToChangeCategoryAsync(List<string> categories)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <inheritdoc/> /// <inheritdoc/>
public override async Task CleanDownloads(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes) public override async Task CleanDownloadsAsync(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes)
{ {
foreach (TorrentStatus download in downloads) foreach (TorrentStatus download in downloads)
{ {
@@ -266,6 +266,11 @@ public class DelugeService : DownloadService, IDelugeService
} }
} }
public override async Task CreateCategoryAsync(string name)
{
throw new NotImplementedException();
}
public override Task ChangeCategoryForNoHardLinksAsync(List<object> downloads, HashSet<string> excludedHashes) public override Task ChangeCategoryForNoHardLinksAsync(List<object> downloads, HashSet<string> excludedHashes)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -273,7 +278,7 @@ public class DelugeService : DownloadService, IDelugeService
/// <inheritdoc/> /// <inheritdoc/>
[DryRunSafeguard] [DryRunSafeguard]
public override async Task DeleteDownload(string hash) public override async Task DeleteDownloadAsync(string hash)
{ {
hash = hash.ToLowerInvariant(); hash = hash.ToLowerInvariant();
@@ -75,20 +75,23 @@ public abstract class DownloadService : IDownloadService
); );
/// <inheritdoc/> /// <inheritdoc/>
public abstract Task DeleteDownload(string hash); public abstract Task DeleteDownloadAsync(string hash);
/// <inheritdoc/> /// <inheritdoc/>
public abstract Task<List<object>?> GetDownloadsToBeCleaned(List<CleanCategory> categories); public abstract Task<List<object>?> GetDownloadsToBeCleanedAsync(List<CleanCategory> categories);
/// <inheritdoc/> /// <inheritdoc/>
public abstract Task<List<object>?> GetDownloadsToChangeCategory(List<string> categories); public abstract Task<List<object>?> GetDownloadsToChangeCategoryAsync(List<string> categories);
/// <inheritdoc/> /// <inheritdoc/>
public abstract Task CleanDownloads(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes); public abstract Task CleanDownloadsAsync(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes);
/// <inheritdoc/> /// <inheritdoc/>
public abstract Task ChangeCategoryForNoHardLinksAsync(List<object> downloads, HashSet<string> excludedHashes); public abstract Task ChangeCategoryForNoHardLinksAsync(List<object> downloads, HashSet<string> excludedHashes);
/// <inheritdoc/>
public abstract Task CreateCategoryAsync(string name);
protected void ResetStrikesOnProgress(string hash, long downloaded) protected void ResetStrikesOnProgress(string hash, long downloaded)
{ {
if (!_queueCleanerConfig.StalledResetStrikesOnProgress) if (!_queueCleanerConfig.StalledResetStrikesOnProgress)
@@ -53,17 +53,17 @@ public class DummyDownloadService : DownloadService
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override Task<List<object>?> GetDownloadsToBeCleaned(List<CleanCategory> categories) public override Task<List<object>?> GetDownloadsToBeCleanedAsync(List<CleanCategory> categories)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override Task<List<object>?> GetDownloadsToChangeCategory(List<string> categories) public override Task<List<object>?> GetDownloadsToChangeCategoryAsync(List<string> categories)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override Task CleanDownloads(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes) public override Task CleanDownloadsAsync(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@@ -73,7 +73,12 @@ public class DummyDownloadService : DownloadService
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override Task DeleteDownload(string hash) public override Task CreateCategoryAsync(string name)
{
throw new NotImplementedException();
}
public override Task DeleteDownloadAsync(string hash)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@@ -32,13 +32,18 @@ public interface IDownloadService : IDisposable
); );
/// <summary> /// <summary>
/// Fetches all downloads. /// Fetches all downloads that should be cleaned.
/// </summary> /// </summary>
/// <param name="categories">The categories by which to filter the downloads.</param> /// <param name="categories">The categories by which to filter the downloads.</param>
/// <returns>A list of downloads for the provided categories.</returns> /// <returns>A list of downloads for the provided categories.</returns>
Task<List<object>?> GetDownloadsToBeCleaned(List<CleanCategory> categories); Task<List<object>?> GetDownloadsToBeCleanedAsync(List<CleanCategory> categories);
Task<List<object>?> GetDownloadsToChangeCategory(List<string> categories); /// <summary>
/// Fetches all downloads that should have their category changed.
/// </summary>
/// <param name="categories">The categories by which to filter the downloads.</param>
/// <returns>A list of downloads for the provided categories.</returns>
Task<List<object>?> GetDownloadsToChangeCategoryAsync(List<string> categories);
/// <summary> /// <summary>
/// Cleans the downloads. /// Cleans the downloads.
@@ -46,7 +51,7 @@ public interface IDownloadService : IDisposable
/// <param name="downloads">The downloads to clean.</param> /// <param name="downloads">The downloads to clean.</param>
/// <param name="categoriesToClean">The categories that should be cleaned.</param> /// <param name="categoriesToClean">The categories that should be cleaned.</param>
/// <param name="excludedHashes">The hashes that should not be cleaned.</param> /// <param name="excludedHashes">The hashes that should not be cleaned.</param>
Task CleanDownloads(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes); Task CleanDownloadsAsync(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes);
/// <summary> /// <summary>
/// Changes the category for downloads that have no hardlinks. /// Changes the category for downloads that have no hardlinks.
@@ -58,5 +63,11 @@ public interface IDownloadService : IDisposable
/// <summary> /// <summary>
/// Deletes a download item. /// Deletes a download item.
/// </summary> /// </summary>
public Task DeleteDownload(string hash); public Task DeleteDownloadAsync(string hash);
/// <summary>
/// Creates a category.
/// </summary>
/// <param name="name">The category name.</param>
public Task CreateCategoryAsync(string name);
} }
@@ -209,7 +209,7 @@ public class QBitService : DownloadService, IQBitService
} }
/// <inheritdoc/> /// <inheritdoc/>
public override async Task<List<object>?> GetDownloadsToBeCleaned(List<CleanCategory> categories) => public override async Task<List<object>?> GetDownloadsToBeCleanedAsync(List<CleanCategory> categories) =>
(await _client.GetTorrentListAsync(new() (await _client.GetTorrentListAsync(new()
{ {
Filter = TorrentListFilter.Seeding Filter = TorrentListFilter.Seeding
@@ -219,7 +219,7 @@ public class QBitService : DownloadService, IQBitService
.Cast<object>() .Cast<object>()
.ToList(); .ToList();
public override async Task<List<object>?> GetDownloadsToChangeCategory(List<string> categories) public override async Task<List<object>?> GetDownloadsToChangeCategoryAsync(List<string> categories)
{ {
return (await _client.GetTorrentListAsync(new() return (await _client.GetTorrentListAsync(new()
{ {
@@ -231,7 +231,7 @@ public class QBitService : DownloadService, IQBitService
} }
/// <inheritdoc/> /// <inheritdoc/>
public override async Task CleanDownloads(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes) public override async Task CleanDownloadsAsync(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes)
{ {
foreach (TorrentInfo download in downloads) foreach (TorrentInfo download in downloads)
{ {
@@ -299,6 +299,18 @@ public class QBitService : DownloadService, IQBitService
} }
} }
public override async Task CreateCategoryAsync(string name)
{
IReadOnlyDictionary<string, Category>? existingCategories = await _client.GetCategoriesAsync();
if (existingCategories.Any(x => x.Value.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)))
{
return;
}
await _client.AddCategoryAsync(name);
}
public override async Task ChangeCategoryForNoHardLinksAsync(List<object> downloads, HashSet<string> excludedHashes) public override async Task ChangeCategoryForNoHardLinksAsync(List<object> downloads, HashSet<string> excludedHashes)
{ {
if (_downloadCleanerConfig.IgnoreRootDir) if (_downloadCleanerConfig.IgnoreRootDir)
@@ -380,7 +392,7 @@ public class QBitService : DownloadService, IQBitService
/// <inheritdoc/> /// <inheritdoc/>
[DryRunSafeguard] [DryRunSafeguard]
public override async Task DeleteDownload(string hash) public override async Task DeleteDownloadAsync(string hash)
{ {
await _client.DeleteAsync(hash, deleteDownloadedData: true); await _client.DeleteAsync(hash, deleteDownloadedData: true);
} }
@@ -183,7 +183,7 @@ public class TransmissionService : DownloadService, ITransmissionService
} }
/// <inheritdoc/> /// <inheritdoc/>
public override async Task<List<object>?> GetDownloadsToBeCleaned(List<CleanCategory> categories) public override async Task<List<object>?> GetDownloadsToBeCleanedAsync(List<CleanCategory> categories)
{ {
string[] fields = [ string[] fields = [
TorrentFields.FILES, TorrentFields.FILES,
@@ -220,13 +220,13 @@ public class TransmissionService : DownloadService, ITransmissionService
.ToList(); .ToList();
} }
public override Task<List<object>?> GetDownloadsToChangeCategory(List<string> categories) public override Task<List<object>?> GetDownloadsToChangeCategoryAsync(List<string> categories)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <inheritdoc/> /// <inheritdoc/>
public override async Task CleanDownloads(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes) public override async Task CleanDownloadsAsync(List<object> downloads, List<CleanCategory> categoriesToClean, HashSet<string> excludedHashes)
{ {
foreach (TorrentInfo download in downloads) foreach (TorrentInfo download in downloads)
{ {
@@ -288,13 +288,18 @@ public class TransmissionService : DownloadService, ITransmissionService
await _notifier.NotifyDownloadCleaned(download.uploadRatio ?? 0, seedingTime, category.Name, result.Reason); await _notifier.NotifyDownloadCleaned(download.uploadRatio ?? 0, seedingTime, category.Name, result.Reason);
} }
} }
public override async Task CreateCategoryAsync(string name)
{
throw new NotImplementedException();
}
public override Task ChangeCategoryForNoHardLinksAsync(List<object> downloads, HashSet<string> excludedHashes) public override Task ChangeCategoryForNoHardLinksAsync(List<object> downloads, HashSet<string> excludedHashes)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override async Task DeleteDownload(string hash) public override async Task DeleteDownloadAsync(string hash)
{ {
TorrentInfo? torrent = await GetTorrentAsync(hash); TorrentInfo? torrent = await GetTorrentAsync(hash);