mirror of
https://github.com/Cleanuparr/Cleanuparr.git
synced 2026-01-09 06:18:20 -05:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
baf6a8c2f4 | ||
|
|
cd345afc54 | ||
|
|
246ec4d6eb | ||
|
|
569eeae181 |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -4,9 +4,11 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: flmorg/universal-workflows/.github/workflows/dotnet.build.app.yml@main
|
||||
uses: flmorg/universal-workflows-testing/.github/workflows/dotnet.build.app.yml@main
|
||||
with:
|
||||
dockerRepository: flaminel/cleanuperr
|
||||
githubContext: ${{ toJSON(github) }}
|
||||
outputName: cleanuperr
|
||||
selfContained: false
|
||||
baseImage: 9.0-bookworm-slim
|
||||
secrets: inherit
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ public sealed record DownloadCleanerConfig : IJobConfig, IIgnoredDownloadsConfig
|
||||
[ConfigurationKeyName("UNLINKED_TARGET_CATEGORY")]
|
||||
public string UnlinkedTargetCategory { get; init; } = "cleanuperr-unlinked";
|
||||
|
||||
[ConfigurationKeyName("UNLINKED_USE_TAG")]
|
||||
public bool UnlinkedUseTag { get; init; }
|
||||
|
||||
[ConfigurationKeyName("UNLINKED_IGNORED_ROOT_DIR")]
|
||||
public string UnlinkedIgnoredRootDir { get; init; } = string.Empty;
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
}
|
||||
],
|
||||
"UNLINKED_TARGET_CATEGORY": "cleanuperr-unlinked",
|
||||
"UNLINKED_USE_TAG": false,
|
||||
"UNLINKED_IGNORED_ROOT_DIR": "",
|
||||
"UNLINKED_CATEGORIES": [
|
||||
"tv-sonarr",
|
||||
@@ -84,6 +85,7 @@
|
||||
},
|
||||
"Sonarr": {
|
||||
"Enabled": true,
|
||||
"IMPORT_FAILED_MAX_STRIKES": -1,
|
||||
"SearchType": "Episode",
|
||||
"Block": {
|
||||
"Type": "blacklist",
|
||||
@@ -98,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"
|
||||
@@ -111,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"
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"DELETE_PRIVATE": false,
|
||||
"CATEGORIES": [],
|
||||
"UNLINKED_TARGET_CATEGORY": "cleanuperr-unlinked",
|
||||
"UNLINKED_USE_TAG": false,
|
||||
"UNLINKED_IGNORED_ROOT_DIR": "",
|
||||
"UNLINKED_CATEGORIES": [],
|
||||
"IGNORED_DOWNLOADS_PATH": ""
|
||||
@@ -71,6 +72,7 @@
|
||||
},
|
||||
"Sonarr": {
|
||||
"Enabled": false,
|
||||
"IMPORT_FAILED_MAX_STRIKES": -1,
|
||||
"SearchType": "Episode",
|
||||
"Block": {
|
||||
"Type": "blacklist",
|
||||
@@ -85,6 +87,7 @@
|
||||
},
|
||||
"Radarr": {
|
||||
"Enabled": false,
|
||||
"IMPORT_FAILED_MAX_STRIKES": -1,
|
||||
"Block": {
|
||||
"Type": "blacklist",
|
||||
"Path": ""
|
||||
@@ -98,6 +101,7 @@
|
||||
},
|
||||
"Lidarr": {
|
||||
"Enabled": false,
|
||||
"IMPORT_FAILED_MAX_STRIKES": -1,
|
||||
"Block": {
|
||||
"Type": "blacklist",
|
||||
"Path": ""
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<PackageReference Include="MassTransit" Version="8.3.6" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.2" />
|
||||
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
|
||||
<PackageReference Include="Mono.Unix" Version="7.1.0-final.1.21458.1" />
|
||||
<PackageReference Include="Quartz" Version="3.13.1" />
|
||||
<PackageReference Include="Scrutor" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -86,9 +86,12 @@ public sealed class DownloadCleaner : GenericHandler
|
||||
{
|
||||
if (!_hardLinkCategoryCreated)
|
||||
{
|
||||
_logger.LogDebug("creating category {cat}", _config.UnlinkedTargetCategory);
|
||||
|
||||
await _downloadService.CreateCategoryAsync(_config.UnlinkedTargetCategory);
|
||||
if (_downloadClientConfig.DownloadClient is Common.Enums.DownloadClient.QBittorrent && !_config.UnlinkedUseTag)
|
||||
{
|
||||
_logger.LogDebug("creating category {cat}", _config.UnlinkedTargetCategory);
|
||||
await _downloadService.CreateCategoryAsync(_config.UnlinkedTargetCategory);
|
||||
}
|
||||
|
||||
_hardLinkCategoryCreated = true;
|
||||
}
|
||||
|
||||
@@ -124,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());
|
||||
|
||||
|
||||
@@ -251,6 +251,15 @@ public class QBitService : DownloadService, IQBitService
|
||||
?.Cast<TorrentInfo>()
|
||||
.Where(x => !string.IsNullOrEmpty(x.Hash))
|
||||
.Where(x => categories.Any(cat => cat.Equals(x.Category, StringComparison.InvariantCultureIgnoreCase)))
|
||||
.Where(x =>
|
||||
{
|
||||
if (_downloadCleanerConfig.UnlinkedUseTag)
|
||||
{
|
||||
return !x.Tags.Any(tag => tag.Equals(_downloadCleanerConfig.UnlinkedTargetCategory, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.Cast<object>()
|
||||
.ToList();
|
||||
|
||||
@@ -436,12 +445,18 @@ public class QBitService : DownloadService, IQBitService
|
||||
}
|
||||
|
||||
await _dryRunInterceptor.InterceptAsync(ChangeCategory, download.Hash, _downloadCleanerConfig.UnlinkedTargetCategory);
|
||||
|
||||
if (_downloadCleanerConfig.UnlinkedUseTag)
|
||||
{
|
||||
_logger.LogInformation("tag added for {name}", download.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("category changed for {name}", download.Name);
|
||||
download.Category = _downloadCleanerConfig.UnlinkedTargetCategory;
|
||||
}
|
||||
|
||||
_logger.LogInformation("category changed for {name}", download.Name);
|
||||
|
||||
await _notifier.NotifyCategoryChanged(download.Category, _downloadCleanerConfig.UnlinkedTargetCategory);
|
||||
|
||||
download.Category = _downloadCleanerConfig.UnlinkedTargetCategory;
|
||||
await _notifier.NotifyCategoryChanged(download.Category, _downloadCleanerConfig.UnlinkedTargetCategory, _downloadCleanerConfig.UnlinkedUseTag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,6 +482,12 @@ public class QBitService : DownloadService, IQBitService
|
||||
[DryRunSafeguard]
|
||||
protected virtual async Task ChangeCategory(string hash, string newCategory)
|
||||
{
|
||||
if (_downloadCleanerConfig.UnlinkedUseTag)
|
||||
{
|
||||
await _client.AddTorrentTagAsync([hash], newCategory);
|
||||
return;
|
||||
}
|
||||
|
||||
await _client.SetTorrentCategoryAsync([hash], newCategory);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -10,5 +10,5 @@ public interface INotificationPublisher
|
||||
|
||||
Task NotifyDownloadCleaned(double ratio, TimeSpan seedingTime, string categoryName, CleanReason reason);
|
||||
|
||||
Task NotifyCategoryChanged(string oldCategory, string newCategory);
|
||||
Task NotifyCategoryChanged(string oldCategory, string newCategory, bool isTag = false);
|
||||
}
|
||||
@@ -123,21 +123,29 @@ public class NotificationPublisher : INotificationPublisher
|
||||
}
|
||||
}
|
||||
|
||||
public virtual async Task NotifyCategoryChanged(string oldCategory, string newCategory)
|
||||
public virtual async Task NotifyCategoryChanged(string oldCategory, string newCategory, bool isTag = false)
|
||||
{
|
||||
CategoryChangedNotification notification = new()
|
||||
{
|
||||
Title = "Category changed",
|
||||
Title = isTag? "Tag added" : "Category changed",
|
||||
Description = ContextProvider.Get<string>("downloadName"),
|
||||
Fields =
|
||||
[
|
||||
new() { Title = "Hash", Text = ContextProvider.Get<string>("hash").ToLowerInvariant() },
|
||||
new() { Title = "Old category", Text = oldCategory },
|
||||
new() { Title = "New category", Text = newCategory }
|
||||
new() { Title = "Hash", Text = ContextProvider.Get<string>("hash").ToLowerInvariant() }
|
||||
],
|
||||
Level = NotificationLevel.Important
|
||||
};
|
||||
|
||||
if (isTag)
|
||||
{
|
||||
notification.Fields.Add(new() { Title = "Tag", Text = newCategory });
|
||||
}
|
||||
else
|
||||
{
|
||||
notification.Fields.Add(new() { Title = "Old category", Text = oldCategory });
|
||||
notification.Fields.Add(new() { Title = "New category", Text = newCategory });
|
||||
}
|
||||
|
||||
await NotifyInternal(notification);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -221,15 +221,18 @@ services:
|
||||
- DOWNLOADCLEANER__ENABLED=true
|
||||
- DOWNLOADCLEANER__IGNORED_DOWNLOADS_PATH=/ignored
|
||||
- DOWNLOADCLEANER__DELETE_PRIVATE=false
|
||||
|
||||
- DOWNLOADCLEANER__CATEGORIES__0__NAME=tv-sonarr
|
||||
- DOWNLOADCLEANER__CATEGORIES__0__MAX_RATIO=-1
|
||||
- DOWNLOADCLEANER__CATEGORIES__0__MIN_SEED_TIME=0
|
||||
- DOWNLOADCLEANER__CATEGORIES__0__MAX_SEED_TIME=99999
|
||||
- DOWNLOADCLEANER__CATEGORIES__1__NAME=nohardlink
|
||||
- DOWNLOADCLEANER__CATEGORIES__1__NAME=cleanuperr-unlinked
|
||||
- DOWNLOADCLEANER__CATEGORIES__1__MAX_RATIO=-1
|
||||
- DOWNLOADCLEANER__CATEGORIES__1__MIN_SEED_TIME=0
|
||||
- DOWNLOADCLEANER__CATEGORIES__1__MAX_SEED_TIME=99999
|
||||
|
||||
- DOWNLOADCLEANER__UNLINKED_TARGET_CATEGORY=cleanuperr-unlinked
|
||||
- DOWNLOADCLEANER__UNLINKED_USE_TAG=false
|
||||
- DOWNLOADCLEANER__UNLINKED_IGNORED_ROOT_DIR=/downloads
|
||||
- DOWNLOADCLEANER__UNLINKED_CATEGORIES__0=tv-sonarr
|
||||
- DOWNLOADCLEANER__UNLINKED_CATEGORIES__1=radarr
|
||||
@@ -249,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
|
||||
@@ -256,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
|
||||
|
||||
@@ -91,6 +91,7 @@ services:
|
||||
|
||||
# change category for downloads with no hardlinks
|
||||
- DOWNLOADCLEANER__UNLINKED_TARGET_CATEGORY=cleanuperr-unlinked
|
||||
- DOWNLOADCLEANER__UNLINKED_USE_TAG=false
|
||||
- DOWNLOADCLEANER__UNLINKED_IGNORED_ROOT_DIR=/downloads
|
||||
- DOWNLOADCLEANER__UNLINKED_CATEGORIES__0=tv-sonarr
|
||||
- DOWNLOADCLEANER__UNLINKED_CATEGORIES__1=radarr
|
||||
@@ -117,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
|
||||
@@ -126,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
|
||||
@@ -134,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
|
||||
|
||||
@@ -78,6 +78,7 @@ import { Note } from '@site/src/components/Admonition';
|
||||
}
|
||||
],
|
||||
"UNLINKED_TARGET_CATEGORY": "cleanuperr-unlinked",
|
||||
"DOWNLOADCLEANER__UNLINKED_USE_TAG": false,
|
||||
"UNLINKED_IGNORED_ROOT_DIR": "/downloads",
|
||||
"UNLINKED_CATEGORIES": [
|
||||
"tv-sonarr",
|
||||
@@ -105,6 +106,7 @@ import { Note } from '@site/src/components/Admonition';
|
||||
},
|
||||
"Sonarr": {
|
||||
"Enabled": true,
|
||||
"IMPORT_FAILED_MAX_STRIKES=-1
|
||||
"SearchType": "Episode",
|
||||
"Block": {
|
||||
"Type": "blacklist",
|
||||
@@ -123,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"
|
||||
@@ -140,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"
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -11,6 +11,20 @@ const settings: EnvVarProps[] = [
|
||||
defaultValue: "cleanuperr-unlinked",
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "DOWNLOADCLEANER__UNLINKED_USE_TAG",
|
||||
description: [
|
||||
"If set to true, a tag will be set instead of changing the category.",
|
||||
],
|
||||
type: "boolean",
|
||||
defaultValue: "false",
|
||||
required: false,
|
||||
acceptedValues: ["true", "false"],
|
||||
notes: [
|
||||
"Works only for qBittorrent.",
|
||||
],
|
||||
|
||||
},
|
||||
{
|
||||
name: "DOWNLOADCLEANER__UNLINKED_IGNORED_ROOT_DIR",
|
||||
description: [
|
||||
|
||||
Reference in New Issue
Block a user