From d7913ae2b83687602b6951e60e10f89529ee565e Mon Sep 17 00:00:00 2001 From: Marius Nechifor Date: Sat, 11 Jan 2025 01:45:12 +0200 Subject: [PATCH] Add option to not use a download client (#35) --- README.md | 12 ++++++- .../DownloadClient/DownloadClientConfig.cs | 9 +++++ .../Configuration/EnvironmentVariables.cs | 6 ---- .../Enums/DownloadClient.cs | 5 +-- .../DependencyInjection/ConfigurationDI.cs | 1 + .../DependencyInjection/ServicesDI.cs | 1 + .../ContentBlocker/ContentBlocker.cs | 13 ++++++-- .../DownloadClient/DownloadServiceFactory.cs | 21 +++++------- .../DownloadClient/DummyDownloadService.cs | 33 +++++++++++++++++++ .../Verticals/Jobs/GenericHandler.cs | 6 +++- .../Verticals/QueueCleaner/QueueCleaner.cs | 11 +++++-- 11 files changed, 89 insertions(+), 29 deletions(-) create mode 100644 code/Common/Configuration/DownloadClient/DownloadClientConfig.cs delete mode 100644 code/Common/Configuration/EnvironmentVariables.cs rename code/{Domain => Common}/Enums/DownloadClient.cs (51%) create mode 100644 code/Infrastructure/Verticals/DownloadClient/DummyDownloadService.cs diff --git a/README.md b/README.md index df19acdb..37f058c1 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,14 @@ This tool is actively developed and still a work in progress. Join the Discord s - Execute the **content blocker** job, as explained in the [How it works](#how-it-works) section. - Execute the **queue cleaner** job, as explained in the [How it works](#how-it-works) section. +## Using cleanuperr just for failed *arr imports (works for Usenet users as well) + +1. Set `QUEUECLEANER_ENABLED` to `true`. +2. Set `QUEUECLEANER__IMPORT_FAILED_MAX_STRIKES` to a desired value. +3. Set `DOWNLOAD_CLIENT` to `none`. + +**No other action involving a download client would work (e.g. content blocking, removing stalled downloads etc.).** + ## Usage ### Docker compose yaml @@ -113,6 +121,8 @@ services: # - TRANSMISSION__URL=http://localhost:9091 # - TRANSMISSION__USERNAME=test # - TRANSMISSION__PASSWORD=testing + # OR + # - DOWNLOAD_CLIENT=none - SONARR__ENABLED=true - SONARR__SEARCHTYPE=Episode @@ -153,7 +163,7 @@ services: | CONTENTBLOCKER__WHITELIST__ENABLED | Yes if content blocker is enabled and blacklist is not enabled | Enable or disable the whitelist | false | | CONTENTBLOCKER__WHITELIST__PATH | Yes if whitelist is enabled | Path to the whitelist (local file or url)
Needs to be json compatible | empty | ||||| -| DOWNLOAD_CLIENT | No | Download client that is used by *arrs
Can be `qbittorrent`, `deluge` or `transmission` | `qbittorrent` | +| DOWNLOAD_CLIENT | No | Download client that is used by *arrs
Can be `qbittorrent`, `deluge`, `transmission` or `none` | `qbittorrent` | | QBITTORRENT__URL | No | qBittorrent instance url | http://localhost:8112 | | QBITTORRENT__USERNAME | No | qBittorrent user | empty | | QBITTORRENT__PASSWORD | No | qBittorrent password | empty | diff --git a/code/Common/Configuration/DownloadClient/DownloadClientConfig.cs b/code/Common/Configuration/DownloadClient/DownloadClientConfig.cs new file mode 100644 index 00000000..ebbe0467 --- /dev/null +++ b/code/Common/Configuration/DownloadClient/DownloadClientConfig.cs @@ -0,0 +1,9 @@ +using Microsoft.Extensions.Configuration; + +namespace Common.Configuration.DownloadClient; + +public sealed record DownloadClientConfig +{ + [ConfigurationKeyName("DOWNLOAD_CLIENT")] + public Enums.DownloadClient DownloadClient { get; init; } = Enums.DownloadClient.QBittorrent; +} \ No newline at end of file diff --git a/code/Common/Configuration/EnvironmentVariables.cs b/code/Common/Configuration/EnvironmentVariables.cs deleted file mode 100644 index 9ee9d4b5..00000000 --- a/code/Common/Configuration/EnvironmentVariables.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Common.Configuration; - -public static class EnvironmentVariables -{ - public const string DownloadClient = "DOWNLOAD_CLIENT"; -} \ No newline at end of file diff --git a/code/Domain/Enums/DownloadClient.cs b/code/Common/Enums/DownloadClient.cs similarity index 51% rename from code/Domain/Enums/DownloadClient.cs rename to code/Common/Enums/DownloadClient.cs index 8f67021c..6c72e835 100644 --- a/code/Domain/Enums/DownloadClient.cs +++ b/code/Common/Enums/DownloadClient.cs @@ -1,8 +1,9 @@ -namespace Domain.Enums; +namespace Common.Enums; public enum DownloadClient { QBittorrent, Deluge, - Transmission + Transmission, + None } \ No newline at end of file diff --git a/code/Executable/DependencyInjection/ConfigurationDI.cs b/code/Executable/DependencyInjection/ConfigurationDI.cs index f237985b..57fae7f4 100644 --- a/code/Executable/DependencyInjection/ConfigurationDI.cs +++ b/code/Executable/DependencyInjection/ConfigurationDI.cs @@ -14,6 +14,7 @@ public static class ConfigurationDI services .Configure(configuration.GetSection(QueueCleanerConfig.SectionName)) .Configure(configuration.GetSection(ContentBlockerConfig.SectionName)) + .Configure(configuration) .Configure(configuration.GetSection(QBitConfig.SectionName)) .Configure(configuration.GetSection(DelugeConfig.SectionName)) .Configure(configuration.GetSection(TransmissionConfig.SectionName)) diff --git a/code/Executable/DependencyInjection/ServicesDI.cs b/code/Executable/DependencyInjection/ServicesDI.cs index ed9ec24d..7c5503f8 100644 --- a/code/Executable/DependencyInjection/ServicesDI.cs +++ b/code/Executable/DependencyInjection/ServicesDI.cs @@ -18,6 +18,7 @@ public static class ServicesDI .AddTransient() .AddTransient() .AddTransient() + .AddTransient() .AddTransient() .AddTransient() .AddTransient() diff --git a/code/Infrastructure/Verticals/ContentBlocker/ContentBlocker.cs b/code/Infrastructure/Verticals/ContentBlocker/ContentBlocker.cs index 7c5d1d9a..aefe2fb1 100644 --- a/code/Infrastructure/Verticals/ContentBlocker/ContentBlocker.cs +++ b/code/Infrastructure/Verticals/ContentBlocker/ContentBlocker.cs @@ -1,5 +1,5 @@ -using Common.Configuration; -using Common.Configuration.Arr; +using Common.Configuration.Arr; +using Common.Configuration.DownloadClient; using Domain.Enums; using Domain.Models.Arr.Queue; using Infrastructure.Verticals.Arr; @@ -16,6 +16,7 @@ public sealed class ContentBlocker : GenericHandler public ContentBlocker( ILogger logger, + IOptions downloadClientConfig, IOptions sonarrConfig, IOptions radarrConfig, SonarrClient sonarrClient, @@ -23,13 +24,19 @@ public sealed class ContentBlocker : GenericHandler ArrQueueIterator arrArrQueueIterator, BlocklistProvider blocklistProvider, DownloadServiceFactory downloadServiceFactory - ) : base(logger, sonarrConfig.Value, radarrConfig.Value, sonarrClient, radarrClient, arrArrQueueIterator, downloadServiceFactory) + ) : base(logger, downloadClientConfig, sonarrConfig.Value, radarrConfig.Value, sonarrClient, radarrClient, arrArrQueueIterator, downloadServiceFactory) { _blocklistProvider = blocklistProvider; } public override async Task ExecuteAsync() { + if (_downloadClientConfig.DownloadClient is Common.Enums.DownloadClient.None) + { + _logger.LogWarning("download client is set to none"); + return; + } + await _blocklistProvider.LoadBlocklistAsync(); await base.ExecuteAsync(); } diff --git a/code/Infrastructure/Verticals/DownloadClient/DownloadServiceFactory.cs b/code/Infrastructure/Verticals/DownloadClient/DownloadServiceFactory.cs index 81390788..d02c9753 100644 --- a/code/Infrastructure/Verticals/DownloadClient/DownloadServiceFactory.cs +++ b/code/Infrastructure/Verticals/DownloadClient/DownloadServiceFactory.cs @@ -1,9 +1,7 @@ -using Common.Configuration; -using Common.Configuration.DownloadClient; +using Common.Configuration.DownloadClient; using Infrastructure.Verticals.DownloadClient.Deluge; using Infrastructure.Verticals.DownloadClient.QBittorrent; using Infrastructure.Verticals.DownloadClient.Transmission; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -12,24 +10,21 @@ namespace Infrastructure.Verticals.DownloadClient; public sealed class DownloadServiceFactory { private readonly IServiceProvider _serviceProvider; - private readonly Domain.Enums.DownloadClient _downloadClient; + private readonly Common.Enums.DownloadClient _downloadClient; - public DownloadServiceFactory(IServiceProvider serviceProvider, IConfiguration configuration) + public DownloadServiceFactory(IServiceProvider serviceProvider, IOptions downloadClientConfig) { _serviceProvider = serviceProvider; - _downloadClient = (Domain.Enums.DownloadClient)Enum.Parse( - typeof(Domain.Enums.DownloadClient), - configuration[EnvironmentVariables.DownloadClient] ?? Domain.Enums.DownloadClient.QBittorrent.ToString(), - true - ); + _downloadClient = downloadClientConfig.Value.DownloadClient; } public IDownloadService CreateDownloadClient() => _downloadClient switch { - Domain.Enums.DownloadClient.QBittorrent => _serviceProvider.GetRequiredService(), - Domain.Enums.DownloadClient.Deluge => _serviceProvider.GetRequiredService(), - Domain.Enums.DownloadClient.Transmission => _serviceProvider.GetRequiredService(), + Common.Enums.DownloadClient.QBittorrent => _serviceProvider.GetRequiredService(), + Common.Enums.DownloadClient.Deluge => _serviceProvider.GetRequiredService(), + Common.Enums.DownloadClient.Transmission => _serviceProvider.GetRequiredService(), + Common.Enums.DownloadClient.None => _serviceProvider.GetRequiredService(), _ => throw new ArgumentOutOfRangeException() }; } \ No newline at end of file diff --git a/code/Infrastructure/Verticals/DownloadClient/DummyDownloadService.cs b/code/Infrastructure/Verticals/DownloadClient/DummyDownloadService.cs new file mode 100644 index 00000000..bdffec93 --- /dev/null +++ b/code/Infrastructure/Verticals/DownloadClient/DummyDownloadService.cs @@ -0,0 +1,33 @@ +using Common.Configuration.QueueCleaner; +using Infrastructure.Verticals.ContentBlocker; +using Infrastructure.Verticals.ItemStriker; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Infrastructure.Verticals.DownloadClient; + +public sealed class DummyDownloadService : DownloadServiceBase +{ + public DummyDownloadService(ILogger logger, IOptions queueCleanerConfig, FilenameEvaluator filenameEvaluator, Striker striker) : base(logger, queueCleanerConfig, filenameEvaluator, striker) + { + } + + public override void Dispose() + { + } + + public override Task LoginAsync() + { + return Task.CompletedTask; + } + + public override Task ShouldRemoveFromArrQueueAsync(string hash) + { + throw new NotImplementedException(); + } + + public override Task BlockUnwantedFilesAsync(string hash) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/code/Infrastructure/Verticals/Jobs/GenericHandler.cs b/code/Infrastructure/Verticals/Jobs/GenericHandler.cs index 864abd0c..f40df8e5 100644 --- a/code/Infrastructure/Verticals/Jobs/GenericHandler.cs +++ b/code/Infrastructure/Verticals/Jobs/GenericHandler.cs @@ -1,17 +1,19 @@ using Common.Configuration.Arr; +using Common.Configuration.DownloadClient; using Domain.Enums; using Domain.Models.Arr; using Domain.Models.Arr.Queue; using Infrastructure.Verticals.Arr; using Infrastructure.Verticals.DownloadClient; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; +using Microsoft.Extensions.Options; namespace Infrastructure.Verticals.Jobs; public abstract class GenericHandler : IDisposable { protected readonly ILogger _logger; + protected readonly DownloadClientConfig _downloadClientConfig; protected readonly SonarrConfig _sonarrConfig; protected readonly RadarrConfig _radarrConfig; protected readonly SonarrClient _sonarrClient; @@ -21,6 +23,7 @@ public abstract class GenericHandler : IDisposable protected GenericHandler( ILogger logger, + IOptions downloadClientConfig, SonarrConfig sonarrConfig, RadarrConfig radarrConfig, SonarrClient sonarrClient, @@ -30,6 +33,7 @@ public abstract class GenericHandler : IDisposable ) { _logger = logger; + _downloadClientConfig = downloadClientConfig.Value; _sonarrConfig = sonarrConfig; _radarrConfig = radarrConfig; _sonarrClient = sonarrClient; diff --git a/code/Infrastructure/Verticals/QueueCleaner/QueueCleaner.cs b/code/Infrastructure/Verticals/QueueCleaner/QueueCleaner.cs index ec7098ed..be9599f1 100644 --- a/code/Infrastructure/Verticals/QueueCleaner/QueueCleaner.cs +++ b/code/Infrastructure/Verticals/QueueCleaner/QueueCleaner.cs @@ -1,5 +1,5 @@ using Common.Configuration.Arr; -using Common.Configuration.QueueCleaner; +using Common.Configuration.DownloadClient; using Domain.Enums; using Domain.Models.Arr; using Domain.Models.Arr.Queue; @@ -15,13 +15,14 @@ public sealed class QueueCleaner : GenericHandler { public QueueCleaner( ILogger logger, + IOptions downloadClientConfig, IOptions sonarrConfig, IOptions radarrConfig, SonarrClient sonarrClient, RadarrClient radarrClient, ArrQueueIterator arrArrQueueIterator, DownloadServiceFactory downloadServiceFactory - ) : base(logger, sonarrConfig.Value, radarrConfig.Value, sonarrClient, radarrClient, arrArrQueueIterator, downloadServiceFactory) + ) : base(logger, downloadClientConfig, sonarrConfig.Value, radarrConfig.Value, sonarrClient, radarrClient, arrArrQueueIterator, downloadServiceFactory) { } @@ -56,7 +57,11 @@ public sealed class QueueCleaner : GenericHandler continue; } - if (!arrClient.ShouldRemoveFromQueue(record) && !await _downloadService.ShouldRemoveFromArrQueueAsync(record.DownloadId)) + bool shouldRemoveFromArr = arrClient.ShouldRemoveFromQueue(record); + bool shouldRemoveFromDownloadClient = _downloadClientConfig.DownloadClient is not Common.Enums.DownloadClient.None && + await _downloadService.ShouldRemoveFromArrQueueAsync(record.DownloadId); + + if (!shouldRemoveFromArr && !shouldRemoveFromDownloadClient) { _logger.LogInformation("skip | {title}", record.Title); continue;