Compare commits

...

1 Commits

Author SHA1 Message Date
Flaminel
baf6a8c2f4 Add option to set failed import strikes per arr (#135) 2025-05-09 01:17:16 +03:00
15 changed files with 90 additions and 9 deletions

View File

@@ -1,4 +1,5 @@
using Common.Configuration.ContentBlocker;
using Microsoft.Extensions.Configuration;
namespace Common.Configuration.Arr;
@@ -7,6 +8,9 @@ public abstract record ArrConfig
public required bool Enabled { get; init; }
public Block Block { get; init; } = new();
[ConfigurationKeyName("IMPORT_FAILED_MAX_STRIKES")]
public short ImportFailedMaxStrikes { get; init; } = -1;
public required List<ArrInstance> Instances { get; init; }
}

View File

@@ -85,6 +85,7 @@
},
"Sonarr": {
"Enabled": true,
"IMPORT_FAILED_MAX_STRIKES": -1,
"SearchType": "Episode",
"Block": {
"Type": "blacklist",
@@ -99,6 +100,7 @@
},
"Radarr": {
"Enabled": true,
"IMPORT_FAILED_MAX_STRIKES": -1,
"Block": {
"Type": "blacklist",
"Path": "https://raw.githubusercontent.com/flmorg/cleanuperr/refs/heads/main/blacklist"
@@ -112,6 +114,7 @@
},
"Lidarr": {
"Enabled": true,
"IMPORT_FAILED_MAX_STRIKES": -1,
"Block": {
"Type": "blacklist",
"Path": "https://raw.githubusercontent.com/flmorg/cleanuperr/refs/heads/main/blacklist"

View File

@@ -72,6 +72,7 @@
},
"Sonarr": {
"Enabled": false,
"IMPORT_FAILED_MAX_STRIKES": -1,
"SearchType": "Episode",
"Block": {
"Type": "blacklist",
@@ -86,6 +87,7 @@
},
"Radarr": {
"Enabled": false,
"IMPORT_FAILED_MAX_STRIKES": -1,
"Block": {
"Type": "blacklist",
"Path": ""
@@ -99,6 +101,7 @@
},
"Lidarr": {
"Enabled": false,
"IMPORT_FAILED_MAX_STRIKES": -1,
"Block": {
"Type": "blacklist",
"Path": ""

View File

@@ -73,7 +73,7 @@ public abstract class ArrClient : IArrClient
return queueResponse;
}
public virtual async Task<bool> ShouldRemoveFromQueue(InstanceType instanceType, QueueRecord record, bool isPrivateDownload)
public virtual async Task<bool> ShouldRemoveFromQueue(InstanceType instanceType, QueueRecord record, bool isPrivateDownload, short arrMaxStrikes)
{
if (_queueCleanerConfig.ImportFailedIgnorePrivate && isPrivateDownload)
{
@@ -102,11 +102,19 @@ public abstract class ArrClient : IArrClient
_logger.LogDebug("skip failed import check | contains ignored pattern | {name}", record.Title);
return false;
}
if (arrMaxStrikes is 0)
{
_logger.LogDebug("skip failed import check | arr max strikes is 0 | {name}", record.Title);
return false;
}
ushort maxStrikes = arrMaxStrikes > 0 ? (ushort)arrMaxStrikes : _queueCleanerConfig.ImportFailedMaxStrikes;
return await _striker.StrikeAndCheckLimit(
record.DownloadId,
record.Title,
_queueCleanerConfig.ImportFailedMaxStrikes,
maxStrikes,
StrikeType.ImportFailed
);
}

View File

@@ -9,7 +9,7 @@ public interface IArrClient
{
Task<QueueListResponse> GetQueueItemsAsync(ArrInstance arrInstance, int page);
Task<bool> ShouldRemoveFromQueue(InstanceType instanceType, QueueRecord record, bool isPrivateDownload);
Task<bool> ShouldRemoveFromQueue(InstanceType instanceType, QueueRecord record, bool isPrivateDownload, short arrMaxStrikes);
Task DeleteQueueItemAsync(ArrInstance arrInstance, QueueRecord record, bool removeFromClient, DeleteReason deleteReason);

View File

@@ -75,7 +75,7 @@ public sealed class ContentBlocker : GenericHandler
await base.ExecuteAsync();
}
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType)
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType, ArrConfig config)
{
IReadOnlyList<string> ignoredDownloads = await _ignoredDownloadsProvider.GetIgnoredDownloads();

View File

@@ -127,7 +127,7 @@ public sealed class DownloadCleaner : GenericHandler
_logger.LogTrace("finished cleaning downloads");
}
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType)
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType, ArrConfig config)
{
using var _ = LogContext.PushProperty("InstanceName", instanceType.ToString());

View File

@@ -67,7 +67,7 @@ public abstract class GenericHandler : IHandler, IDisposable
_downloadService.Dispose();
}
protected abstract Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType);
protected abstract Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType, ArrConfig config);
protected async Task ProcessArrConfigAsync(ArrConfig config, InstanceType instanceType, bool throwOnFailure = false)
{
@@ -80,7 +80,7 @@ public abstract class GenericHandler : IHandler, IDisposable
{
try
{
await ProcessInstanceAsync(arrInstance, instanceType);
await ProcessInstanceAsync(arrInstance, instanceType, config);
}
catch (Exception exception)
{

View File

@@ -49,7 +49,7 @@ public sealed class QueueCleaner : GenericHandler
_ignoredDownloadsProvider = ignoredDownloadsProvider;
}
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType)
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType, ArrConfig config)
{
IReadOnlyList<string> ignoredDownloads = await _ignoredDownloadsProvider.GetIgnoredDownloads();
@@ -108,7 +108,7 @@ public sealed class QueueCleaner : GenericHandler
}
// failed import check
bool shouldRemoveFromArr = await arrClient.ShouldRemoveFromQueue(instanceType, record, downloadCheckResult.IsPrivate);
bool shouldRemoveFromArr = await arrClient.ShouldRemoveFromQueue(instanceType, record, downloadCheckResult.IsPrivate, config.ImportFailedMaxStrikes);
DeleteReason deleteReason = downloadCheckResult.ShouldRemove ? downloadCheckResult.DeleteReason : DeleteReason.ImportFailed;
if (!shouldRemoveFromArr && !downloadCheckResult.ShouldRemove)

View File

@@ -252,6 +252,7 @@ services:
# - TRANSMISSION__PASSWORD=testing
- SONARR__ENABLED=true
- SONARR__IMPORT_FAILED_MAX_STRIKES=-1
- SONARR__SEARCHTYPE=Episode
- SONARR__BLOCK__TYPE=blacklist
- SONARR__BLOCK__PATH=https://raw.githubusercontent.com/flmorg/cleanuperr/refs/heads/main/blacklist
@@ -259,12 +260,14 @@ services:
- SONARR__INSTANCES__0__APIKEY=425d1e713f0c405cbbf359ac0502c1f4
- RADARR__ENABLED=true
- RADARR__IMPORT_FAILED_MAX_STRIKES=-1
- RADARR__BLOCK__TYPE=blacklist
- RADARR__BLOCK__PATH=https://raw.githubusercontent.com/flmorg/cleanuperr/refs/heads/main/blacklist
- RADARR__INSTANCES__0__URL=http://radarr:7878
- RADARR__INSTANCES__0__APIKEY=8b7454f668e54c5b8f44f56f93969761
- LIDARR__ENABLED=true
- LIDARR__IMPORT_FAILED_MAX_STRIKES=-1
- LIDARR__BLOCK__TYPE=blacklist
- LIDARR__BLOCK__PATH=https://raw.githubusercontent.com/flmorg/cleanuperr/refs/heads/main/blacklist # TODO
- LIDARR__INSTANCES__0__URL=http://lidarr:8686

View File

@@ -118,6 +118,7 @@ services:
# - TRANSMISSION__PASSWORD=testing
- SONARR__ENABLED=true
- SONARR__IMPORT_FAILED_MAX_STRIKES=-1
- SONARR__SEARCHTYPE=Episode
- SONARR__BLOCK__TYPE=blacklist
- SONARR__BLOCK__PATH=https://example.com/path/to/file.txt
@@ -127,6 +128,7 @@ services:
- SONARR__INSTANCES__1__APIKEY=secret2
- RADARR__ENABLED=true
- RADARR__IMPORT_FAILED_MAX_STRIKES=-1
- RADARR__BLOCK__TYPE=blacklist
- RADARR__BLOCK__PATH=https://example.com/path/to/file.txt
- RADARR__INSTANCES__0__URL=http://localhost:7878
@@ -135,6 +137,7 @@ services:
- RADARR__INSTANCES__1__APIKEY=secret4
- LIDARR__ENABLED=true
- LIDARR__IMPORT_FAILED_MAX_STRIKES=-1
- LIDARR__BLOCK__TYPE=blacklist
- LIDARR__BLOCK__PATH=https://example.com/path/to/file.txt
- LIDARR__INSTANCES__0__URL=http://radarr:8686

View File

@@ -106,6 +106,7 @@ import { Note } from '@site/src/components/Admonition';
},
"Sonarr": {
"Enabled": true,
"IMPORT_FAILED_MAX_STRIKES=-1
"SearchType": "Episode",
"Block": {
"Type": "blacklist",
@@ -124,6 +125,7 @@ import { Note } from '@site/src/components/Admonition';
},
"Radarr": {
"Enabled": true,
"IMPORT_FAILED_MAX_STRIKES": -1,
"Block": {
"Type": "blacklist",
"Path": "https://example.com/path/to/file.txt"
@@ -141,6 +143,7 @@ import { Note } from '@site/src/components/Admonition';
},
"Lidarr": {
"Enabled": true,
"IMPORT_FAILED_MAX_STRIKES": -1,
"Block": {
"Type": "blacklist",
"Path": "https://example.com/path/to/file.txt"

View File

@@ -12,6 +12,24 @@ const settings: EnvVarProps[] = [
required: false,
acceptedValues: ["true", "false"],
},
{
name: "LIDARR__IMPORT_FAILED_MAX_STRIKES",
description: [
"Number of strikes before removing a failed import. Set to `0` to never remove failed imports.",
"A strike is given when an item fails to be imported."
],
type: "integer number",
defaultValue: "-1",
required: false,
notes: [
"If the value is a positive number, it overwrites the values of [QUEUECLEANER__IMPORT_FAILED_MAX_STRIKES](/cleanuperr/docs/configuration/queue-cleaner/import-failed?QUEUECLEANER__IMPORT_FAILED_MAX_STRIKES).",
"`0` means to never remove failed imports.",
"If not set to `0` or a negative number, the minimum value is `3`.",
],
warnings: [
"The value is not restricted to be a certain positive number. Use a low value (e.g. `1`) at your own risk."
]
},
{
name: "LIDARR__BLOCK__TYPE",
description: [

View File

@@ -12,6 +12,24 @@ const settings: EnvVarProps[] = [
required: false,
acceptedValues: ["true", "false"],
},
{
name: "RADARR__IMPORT_FAILED_MAX_STRIKES",
description: [
"Number of strikes before removing a failed import. Set to `0` to never remove failed imports.",
"A strike is given when an item fails to be imported."
],
type: "integer number",
defaultValue: "-1",
required: false,
notes: [
"If the value is a positive number, it overwrites the values of [QUEUECLEANER__IMPORT_FAILED_MAX_STRIKES](/cleanuperr/docs/configuration/queue-cleaner/import-failed?QUEUECLEANER__IMPORT_FAILED_MAX_STRIKES).",
"`0` means to never remove failed imports.",
"If not set to `0` or a negative number, the minimum value is `3`.",
],
warnings: [
"The value is not restricted to be a certain positive number. Use a low value (e.g. `1`) at your own risk."
]
},
{
name: "RADARR__BLOCK__TYPE",
description: [

View File

@@ -12,6 +12,24 @@ const settings: EnvVarProps[] = [
required: false,
acceptedValues: ["true", "false"],
},
{
name: "SONARR__IMPORT_FAILED_MAX_STRIKES",
description: [
"Number of strikes before removing a failed import. Set to `0` to never remove failed imports.",
"A strike is given when an item fails to be imported."
],
type: "integer number",
defaultValue: "-1",
required: false,
notes: [
"If the value is a positive number, it overwrites the values of [QUEUECLEANER__IMPORT_FAILED_MAX_STRIKES](/cleanuperr/docs/configuration/queue-cleaner/import-failed?QUEUECLEANER__IMPORT_FAILED_MAX_STRIKES).",
"`0` means to never remove failed imports.",
"If not set to `0` or a negative number, the minimum value is `3`.",
],
warnings: [
"The value is not restricted to be a certain positive number. Use a low value (e.g. `1`) at your own risk."
]
},
{
name: "SONARR__BLOCK__TYPE",
description: [