Compare commits

...

7 Commits

Author SHA1 Message Date
Marius Nechifor
54cabd98b4 remove empty creds restriction (#10)
* removed empty checks on qbit and deluge credentials

* updated configuration readme
2024-11-19 23:54:16 +02:00
Marius Nechifor
cbc5c571b3 fixed missing torrent check on content blocker (#9) 2024-11-19 23:23:22 +02:00
Marius Nechifor
beea640d49 fixed content blocker crashing on empty download id (#8) 2024-11-19 23:02:43 +02:00
Marius Nechifor
65b8a7f988 removed Transmission validation on empty credentials (#6) 2024-11-19 13:46:40 +02:00
Flaminel
b86173d6c0 updated readme with more details 2024-11-19 00:16:43 +02:00
Flaminel
09c4b2a28e added permissive blacklist 2024-11-19 00:16:20 +02:00
Flaminel
6e8545e4ca updated readme to include a short description 2024-11-19 00:05:38 +02:00
7 changed files with 94 additions and 40 deletions

View File

@@ -1,16 +1,27 @@
# cleanuperr
### This tool is actively developed and not yet stable. Join the discord server if you want to get in touch with me as soon as possible (or if you just want to be informed of new releases), so we can squash those pesky bugs together: https://discord.gg/cJYPs9Bt
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.
cleanuperr was created primarily to address malicious files, such as `*.lnk` or `*.zipx`, that were getting stuck in Sonarr/Radarr and required manual intervention. Some of the reddit posts that made cleanuperr come to life can be found [here](https://www.reddit.com/r/sonarr/comments/1gqnx16/psa_sonarr_downloaded_a_virus/), [here](https://www.reddit.com/r/sonarr/comments/1gqwklr/sonar_downloaded_a_mkv_file_which_looked_like_a/), [here](https://www.reddit.com/r/sonarr/comments/1gpw2wa/downloaded_waiting_to_import/) and [here](https://www.reddit.com/r/sonarr/comments/1gpi344/downloads_not_importing_no_files_found/).
The tool supports both qBittorrent's built-in exclusion features and its own blocklist-based system. Binaries for all platforms are provided, along with Docker images for easy deployment.
Refer to the [Environment variables](#Environment-variables) section for detailed configuration instructions and the [Setup](#Setup) section for an in-depth explanation of the cleanup process.
## Important note
Only the <b>latest versions</b> of qBittorrent, Deluge, Sonarr etc. are supported, or earlier versions that have the same API as the latest version.
This tool is actively developed and still a work in progress. 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/cJYPs9Bt
# Setup
## Using qBittorrent's built-in feature (works only with qBittorrent)
1. Go to qBittorrent -> Options -> Downloads -> make sure `Excluded file names` is checked -> Set the exclusion list found [here](https://raw.githubusercontent.com/flmorg/cleanuperr/refs/heads/main/blacklist) or create your own.
1. Go to qBittorrent -> Options -> Downloads -> make sure `Excluded file names` is checked -> Set an exclusion list.
- [blacklist](https://raw.githubusercontent.com/flmorg/cleanuperr/refs/heads/main/blacklist)
- [permissive blacklist](https://raw.githubusercontent.com/flmorg/cleanuperr/refs/heads/main/blacklist_permissive)
- create your own
2. Start cleanuperr with `QUEUECLEANER__ENABLED` set to `true`.
3. cleanuperr will execute a queue cleaner cron job at every 5 minutes that will:
1. go through all items from Sonarr/Radarr's queue.
@@ -118,23 +129,23 @@ services:
|||||
| CONTENTBLOCKER__ENABLED | No | Enable or disable the content blocker | false |
| CONTENTBLOCKER__BLACKLIST__ENABLED | Yes if content blocker is enabled and whitelist is not enabled | Enable or disable the blacklist | false |
| CONTENTBLOCKER__BLACKLIST__PATH | Yes if blacklist is enabled | Path to the blacklist (local file or url) | empty |
| CONTENTBLOCKER__BLACKLIST__PATH | Yes if blacklist is enabled | Path to the blacklist (local file or url); Needs to be json compatible | empty |
| CONTENTBLOCKER__WHITELIST__ENABLED | Yes if content blocker is enabled and blacklist is not enabled | Enable or disable the whitelist | false |
| CONTENTBLOCKER__BLACKLIST__PATH | Yes if whitelist is enabled | Path to the whitelist (local file or url) | empty |
| CONTENTBLOCKER__BLACKLIST__PATH | Yes if whitelist is enabled | Path to the whitelist (local file or url); Needs to be json compatible | empty |
|||||
| QBITTORRENT__ENABLED | No | Enable or disable qBittorrent | true |
| QBITTORRENT__URL | Yes if qBittorrent is enabled | qBittorrent instance url | http://localhost:8112 |
| QBITTORRENT__USERNAME | Yes if qBittorrent is enabled | qBittorrent user | empty |
| QBITTORRENT__PASSWORD | Yes if qBittorrent is enabled | qBittorrent password | empty |
| QBITTORRENT__URL | No | qBittorrent instance url | http://localhost:8112 |
| QBITTORRENT__USERNAME | No | qBittorrent user | empty |
| QBITTORRENT__PASSWORD | No | qBittorrent password | empty |
|||||
| DELUGE__ENABLED | No | Enable or disable Deluge | false |
| DELUGE__URL | Yes if Deluge is enabled | Deluge instance url | http://localhost:8080 |
| DELUGE__PASSWORD | Yes if Deluge is enabled | Deluge password | empty |
| DELUGE__URL | No | Deluge instance url | http://localhost:8080 |
| DELUGE__PASSWORD | No | Deluge password | empty |
|||||
| TRANSMISSION__ENABLED | No | Enable or disable Transmission | true |
| TRANSMISSION__URL | Yes if Transmission is enabled | Transmission instance url | http://localhost:9091 |
| TRANSMISSION__USERNAME | Yes if Transmission is enabled | Transmission user | empty |
| TRANSMISSION__PASSWORD | Yes if Transmission is enabled | Transmission password | empty |
| TRANSMISSION__URL | No | Transmission instance url | http://localhost:9091 |
| TRANSMISSION__USERNAME | No | Transmission user | empty |
| TRANSMISSION__PASSWORD | No | Transmission password | empty |
|||||
| SONARR__ENABLED | No | Whether Sonarr cleanup is enabled or not | true |
| SONARR__INSTANCES__0__URL | Yes | First Sonarr instance url | http://localhost:8989 |
@@ -148,8 +159,9 @@ services:
### To be noted
1. The blacklist and the whitelist can not be both enabled at the same time.
2. Only one download client can be enabled at a time. If you have more than one download client, you should deploy multiple instances of cleanuperr.
3. The blocklists (blacklist/whitelist) should have a single pattern on each line and supports the following:
2. The queue cleaner and content blocker can be enabled or disabled separately, if you want to run only one of them.
3. Only one download client can be enabled at a time. If you have more than one download client, you should deploy multiple instances of cleanuperr.
4. The blocklists (blacklist/whitelist) should have a single pattern on each line and supports the following:
```
*example // file name ends with "example"
example* // file name starts with "example"
@@ -157,7 +169,7 @@ example* // file name starts with "example"
example // file name is exactly the word "example"
<ANY_REGEX> // regex
```
4. Multiple Sonarr/Radarr instances can be specified using this format, where `<NUMBER>` starts from 0:
5. Multiple Sonarr/Radarr instances can be specified using this format, where `<NUMBER>` starts from 0:
```
SONARR__INSTANCES__<NUMBER>__URL
SONARR__INSTANCES__<NUMBER>__APIKEY

51
blacklist_permissive Normal file
View File

@@ -0,0 +1,51 @@
*.apk
*.bat
*.bin
*.bmp
*.cmd
*.com
*.db
*.diz
*.dll
*.dmg
*.etc
*.exe
*.gif
*.htm
*.html
*.ico
*.ini
*.iso
*.jar
*.jpg
*.js
*.link
*.lnk
*.msi
*.nfo
*.perl
*.php
*.pl
*.png
*.ps1
*.psc1
*.psd1
*.psm1
*.py
*.pyd
*.rb
*.readme
*.reg
*.run
*.scr
*.sh
*.sql
*.text
*.thumb
*.torrent
*.txt
*.url
*.vbs
*.wsf
*.xml
*.zipx

View File

@@ -23,10 +23,5 @@ public sealed record DelugeConfig : IConfig
{
throw new ArgumentNullException(nameof(Url));
}
if (string.IsNullOrEmpty(Password))
{
throw new ArgumentNullException(nameof(Password));
}
}
}

View File

@@ -25,15 +25,5 @@ public sealed class QBitConfig : IConfig
{
throw new ArgumentNullException(nameof(Url));
}
if (string.IsNullOrEmpty(Username))
{
throw new ArgumentNullException(nameof(Username));
}
if (string.IsNullOrEmpty(Password))
{
throw new ArgumentNullException(nameof(Password));
}
}
}

View File

@@ -23,15 +23,5 @@ public record TransmissionConfig
{
throw new ArgumentNullException(nameof(Url));
}
if (string.IsNullOrEmpty(Username))
{
throw new ArgumentNullException(nameof(Username));
}
if (string.IsNullOrEmpty(Password))
{
throw new ArgumentNullException(nameof(Password));
}
}
}

View File

@@ -77,6 +77,17 @@ public sealed class ContentBlocker : IDisposable
{
foreach (QueueRecord record in items)
{
if (record.Protocol is not "torrent")
{
continue;
}
if (string.IsNullOrEmpty(record.DownloadId))
{
_logger.LogDebug("skip | download id is null for {title}", record.Title);
continue;
}
_logger.LogDebug("searching unwanted files for {title}", record.Title);
await _downloadService.BlockUnwantedFilesAsync(record.DownloadId);
}

View File

@@ -27,6 +27,11 @@ public sealed class QBitService : IDownloadService
public async Task LoginAsync()
{
if (string.IsNullOrEmpty(_config.Username) && string.IsNullOrEmpty(_config.Password))
{
return;
}
await _client.LoginAsync(_config.Username, _config.Password);
}