Add option to set a tag instead of changing the category for unlinked downloads (#133)

This commit is contained in:
Flaminel
2025-05-08 21:51:08 +03:00
committed by GitHub
parent 569eeae181
commit 246ec4d6eb
11 changed files with 71 additions and 15 deletions

View File

@@ -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;

View File

@@ -57,6 +57,7 @@
}
],
"UNLINKED_TARGET_CATEGORY": "cleanuperr-unlinked",
"UNLINKED_USE_TAG": false,
"UNLINKED_IGNORED_ROOT_DIR": "",
"UNLINKED_CATEGORIES": [
"tv-sonarr",

View File

@@ -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": ""

View File

@@ -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;
}

View File

@@ -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("category changed for {name}", download.Name);
download.Category = _downloadCleanerConfig.UnlinkedTargetCategory;
}
else
{
_logger.LogInformation("tag added for {name}", download.Name);
}
_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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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: [