mirror of
https://github.com/Cleanuparr/Cleanuparr.git
synced 2026-01-02 10:57:52 -05:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
569eeae181 | ||
|
|
5a0ef56074 | ||
|
|
09bd4321fb | ||
|
|
4939e37210 |
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
|
||||
@@ -2,7 +2,7 @@ _Love this project? Give it a ⭐️ and let others know!_
|
||||
|
||||
# <img width="24px" src="./Logo/256.png" alt="cleanuperr"></img> Cleanuperr
|
||||
|
||||
[](https://discord.gg/sWggpnmGNY)
|
||||
[](https://discord.gg/SCtMCgtsc4)
|
||||
|
||||
Cleanuperr is a tool for automating the cleanup of unwanted or blocked files in Sonarr, Radarr, and supported download clients like qBittorrent. It removes incomplete or blocked downloads, updates queues, and enforces blacklists or whitelists to manage file selection. After removing blocked content, Cleanuperr can also trigger a search to replace the deleted shows/movies.
|
||||
|
||||
@@ -38,13 +38,13 @@ Cleanuperr supports both qBittorrent's built-in exclusion features and its own b
|
||||
|
||||
Docs can be found [here](https://flmorg.github.io/cleanuperr/).
|
||||
|
||||
# <img width="24px" src="./Logo/256.png" alt="Cleanuperr"> Cleanuperr <svg width="14px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M376.6 84.5c11.3-13.6 9.5-33.8-4.1-45.1s-33.8-9.5-45.1 4.1L192 206 56.6 43.5C45.3 29.9 25.1 28.1 11.5 39.4S-3.9 70.9 7.4 84.5L150.3 256 7.4 427.5c-11.3 13.6-9.5 33.8 4.1 45.1s33.8 9.5 45.1-4.1L192 306 327.4 468.5c11.3 13.6 31.5 15.4 45.1 4.1s15.4-31.5 4.1-45.1L233.7 256 376.6 84.5z"/></svg> Huntarr <img width="24px" src="https://github.com/plexguide/Huntarr.io/blob/main/frontend/static/logo/256.png?raw=true" alt Huntarr></img>
|
||||
# <img style="vertical-align: middle;" width="24px" src="./Logo/256.png" alt="Cleanuperr"> <span style="vertical-align: middle;">Cleanuperr</span> <img src="https://raw.githubusercontent.com/FortAwesome/Font-Awesome/6.x/svgs/solid/x.svg" height="24px" width="30px" style="vertical-align: middle;"> <span style="vertical-align: middle;">Huntarr</span> <img style="vertical-align: middle;" width="24px" src="https://github.com/plexguide/Huntarr.io/blob/main/frontend/static/logo/512.png?raw=true" alt Huntarr></img>
|
||||
|
||||
Think of **Cleanuperr** as the janitor of your server; it keeps your download queue spotless, removes clutter, and blocks malicious files. Now imagine combining that with **Huntarr**, the compulsive librarian who finds missing and upgradable media to complete your collection
|
||||
|
||||
While **Huntarr** fills in the blanks and improves what you already have, **Cleanuperr** makes sure that only clean downloads get through. If you're aiming for a reliable and self-sufficient setup, **Cleanuperr** and **Huntarr** will take your automated media stack to another level.
|
||||
|
||||
<span style="font-size:24px"> ➡️ [**Huntarr**](https://github.com/plexguide/Huntarr.io) </span>
|
||||
<span style="font-size:24px"> ➡️ [**Huntarr**](https://github.com/plexguide/Huntarr.io) <span style="vertical-align: middle"></span></span>
|
||||
|
||||
# Credits
|
||||
Special thanks for inspiration go to:
|
||||
|
||||
@@ -33,11 +33,6 @@ public sealed record DownloadCleanerConfig : IJobConfig, IIgnoredDownloadsConfig
|
||||
return;
|
||||
}
|
||||
|
||||
if (Categories?.Count is null or 0)
|
||||
{
|
||||
throw new ValidationException("no categories configured");
|
||||
}
|
||||
|
||||
if (Categories?.GroupBy(x => x.Name).Any(x => x.Count() > 1) is true)
|
||||
{
|
||||
throw new ValidationException("duplicated clean categories found");
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -58,9 +58,12 @@ public sealed class DownloadCleaner : GenericHandler
|
||||
return;
|
||||
}
|
||||
|
||||
if (_config.Categories?.Count is null or 0)
|
||||
bool isUnlinkedEnabled = !string.IsNullOrEmpty(_config.UnlinkedTargetCategory) && _config.UnlinkedCategories?.Count > 0;
|
||||
bool isCleaningEnabled = _config.Categories?.Count > 0;
|
||||
|
||||
if (!isUnlinkedEnabled && !isCleaningEnabled)
|
||||
{
|
||||
_logger.LogWarning("no categories configured");
|
||||
_logger.LogWarning("{name} is not configured properly", nameof(DownloadCleaner));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -68,9 +71,18 @@ public sealed class DownloadCleaner : GenericHandler
|
||||
|
||||
await _downloadService.LoginAsync();
|
||||
List<object>? downloads = await _downloadService.GetSeedingDownloads();
|
||||
List<object>? downloadsToChangeCategory = null;
|
||||
|
||||
if (downloads?.Count is null or 0)
|
||||
{
|
||||
_logger.LogDebug("no seeding downloads found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_config.UnlinkedTargetCategory) && _config.UnlinkedCategories?.Count > 0)
|
||||
_logger.LogTrace("found {count} seeding downloads", downloads.Count);
|
||||
|
||||
List<object>? downloadsToChangeCategory = null;
|
||||
|
||||
if (isUnlinkedEnabled)
|
||||
{
|
||||
if (!_hardLinkCategoryCreated)
|
||||
{
|
||||
@@ -89,17 +101,27 @@ public sealed class DownloadCleaner : GenericHandler
|
||||
await ProcessArrConfigAsync(_sonarrConfig, InstanceType.Sonarr, true);
|
||||
await ProcessArrConfigAsync(_radarrConfig, InstanceType.Radarr, true);
|
||||
await ProcessArrConfigAsync(_lidarrConfig, InstanceType.Lidarr, true);
|
||||
|
||||
if (isUnlinkedEnabled)
|
||||
{
|
||||
_logger.LogTrace("found {count} potential downloads to change category", downloadsToChangeCategory?.Count);
|
||||
await _downloadService.ChangeCategoryForNoHardLinksAsync(downloadsToChangeCategory, _excludedHashes, ignoredDownloads);
|
||||
_logger.LogTrace("finished changing category");
|
||||
}
|
||||
|
||||
_logger.LogTrace("looking for downloads to change category");
|
||||
await _downloadService.ChangeCategoryForNoHardLinksAsync(downloadsToChangeCategory, _excludedHashes, ignoredDownloads);
|
||||
if (_config.Categories?.Count is null or 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<object>? downloadsToClean = _downloadService.FilterDownloadsToBeCleanedAsync(downloads, _config.Categories);
|
||||
|
||||
// release unused objects
|
||||
downloads = null;
|
||||
|
||||
_logger.LogTrace("looking for downloads to clean");
|
||||
|
||||
_logger.LogTrace("found {count} potential downloads to clean", downloadsToClean?.Count);
|
||||
await _downloadService.CleanDownloadsAsync(downloadsToClean, _config.Categories, _excludedHashes, ignoredDownloads);
|
||||
_logger.LogTrace("finished cleaning downloads");
|
||||
}
|
||||
|
||||
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType)
|
||||
|
||||
@@ -13,7 +13,7 @@ Cleanuperr was created primarily to address malicious files, such as `*.lnk` or
|
||||
<Warning>
|
||||
Because this tool is actively developed and still a work in progress, using the `latest` Docker tag may result in breaking changes.
|
||||
|
||||
Join the Discord server if you want to reach out to me quickly (or just stay updated on new releases) so we can squash those pesky bugs together: https://discord.gg/sWggpnmGNY
|
||||
Join the Discord server if you want to reach out to me quickly (or just stay updated on new releases) so we can squash those pesky bugs together: https://discord.gg/SCtMCgtsc4
|
||||
</Warning>
|
||||
|
||||
|
||||
|
||||
@@ -12,8 +12,12 @@ services:
|
||||
image: ghcr.io/flmorg/cleanuperr:latest
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
# if you want persistent logs
|
||||
- ./cleanuperr/logs:/var/logs
|
||||
# if you want to ignore certain downloads from being processed
|
||||
- ./cleanuperr/ignored.txt:/ignored.txt
|
||||
# if you're using cross-seed and the hardlinks functionality
|
||||
- ./downloads:/downloads
|
||||
environment:
|
||||
# general settings
|
||||
- TZ=America/New_York
|
||||
|
||||
@@ -61,7 +61,7 @@ const config: Config = {
|
||||
position: 'right',
|
||||
},
|
||||
{
|
||||
href: 'https://discord.gg/sWggpnmGNY',
|
||||
href: 'https://discord.gg/SCtMCgtsc4',
|
||||
label: 'Discord',
|
||||
position: 'right',
|
||||
}
|
||||
|
||||
@@ -30,11 +30,17 @@ const settings: EnvVarProps[] = [
|
||||
title: "Multiple patterns can be specified using incrementing numbers starting from 0.",
|
||||
content: `DOWNLOADCLEANER__UNLINKED_CATEGORIES__0=tv-sonarr
|
||||
DOWNLOADCLEANER__UNLINKED_CATEGORIES__1=radarr`
|
||||
}
|
||||
},
|
||||
],
|
||||
type: "text",
|
||||
defaultValue: "Empty",
|
||||
required: false,
|
||||
notes: [
|
||||
"The category name must match the category that was set in the *arr.",
|
||||
"For qBittorrent, the category name is the name of the download category.",
|
||||
"For Deluge, the category name is the name of the label.",
|
||||
"For Transmission, the category name is the last directory from the save location.",
|
||||
],
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user