diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 97197e6..d95c604 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -44,7 +44,7 @@ jobs: - name: "Build, Tag, and push the Docker image" env: - IMAGE_NAME: ghcr.io/manimatter/decluttarr + IMAGE_NAME: ghcr.io/fxsch/decluttarr IMAGE_TAG: dev run: | docker build -f docker/Dockerfile -t $IMAGE_NAME:$IMAGE_TAG . diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1a92383..360af2c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,6 +6,7 @@ on: - closed branches: - main + workflow_dispatch: jobs: # unit-tests: @@ -29,8 +30,6 @@ jobs: # python3 -m pytest --import-mode=append tests/ build-main: - # if: github.ref == 'refs/heads/main' - # needs: unit-tests runs-on: ubuntu-latest defaults: run: @@ -39,6 +38,12 @@ jobs: - name: 'Checkout GitHub Action' uses: actions/checkout@main + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: 'Login to GitHub Container Registry' uses: docker/login-action@v1 with: @@ -59,19 +64,17 @@ jobs: - name: "Build, Tag, and push the Docker image" env: - IMAGE_NAME: ghcr.io/manimatter/decluttarr + IMAGE_NAME: ghcr.io/fxsch/decluttarr IMAGE_TAG: ${{ steps.setversion.outputs.new_tag }} run: | - docker build -f docker/Dockerfile -t $IMAGE_NAME:$IMAGE_TAG . - docker push $IMAGE_NAME:$IMAGE_TAG + docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME:$IMAGE_TAG -f docker/Dockerfile --push . - name: "Build, Tag, and push the Docker image" env: - IMAGE_NAME: ghcr.io/manimatter/decluttarr + IMAGE_NAME: ghcr.io/fxsch/decluttarr IMAGE_TAG: latest run: | - docker build -f docker/Dockerfile -t $IMAGE_NAME:$IMAGE_TAG . - docker push $IMAGE_NAME:$IMAGE_TAG + docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME:$IMAGE_TAG -f docker/Dockerfile --push . # build-dev: # if: github.ref == 'refs/heads/dev' diff --git a/README.md b/README.md index ec15072..2f15a7c 100644 --- a/README.md +++ b/README.md @@ -8,29 +8,205 @@ Feature overview: - Automatically delete failed downloads (& trigger download from another source) - Automatically delete downloads belonging to Movies/TV shows/Music requests that have been deleted in the meantime ('Orphan downloads') - Automatically delete stalled downloads, after they have been found to be stalled multiple times in a row -- Automatically delete downloads belonging to Movies/TV/Music requests shows that are unmonitored +- Automatically delete downloads belonging to Movies/TV shows/Music that are unmonitored -You may run this locally by launch main.py, or by pulling the docker image. -A sample docker-compose.yml is included. +You may run this locally by launching main.py, or by pulling the docker image. +You can find a sample docker-compose.yml in the docker folder. ## Getting started -If you want to run in docker: -1) Adapt the sample docker-compose to your own needs -2) Study the config file to understand the settings -3) Have fun +There's two ways to run this: +- As a docker container with docker-compose +- By cloning the repository and running the script manually -If you want to run locally: -1) Pull decluttarr into whatever location you want -2) Study the config file to understand the settings -3) Edit the config file to your liking -4) run main.py -5) Enjoy +Both ways are explained below and there's an explanation for the different settings below that + +## Docker +1) Make a `docker-compose.yml` file +2) Use the following as a base for that and tweak the settings to your needs +``` +version: "3.3" +services: + decluttarr: + image: "ghcr.io/fxsch/decluttarr:latest" + container_name: decluttarr + restart: unless-stopped + network_mode: "host" + environment: + - TZ=Europe/Berlin + - PUID=1000 + - PGID=1000 + # General + - LOG_LEVEL=INFO + #- TEST_RUN=True + # Features + - REMOVE_TIMER=10 + - REMOVE_FAILED=True + - REMOVE_STALLED=True + - REMOVE_METADATA_MISSING=True + - REMOVE_ORPHANS=True + - REMOVE_UNMONITORED=True + - PERMITTED_ATTEMPTS=3 + - NO_STALLED_REMOVAL_QBIT_TAG=Don't Kill If Stalled + # Radarr + - RADARR_URL=http://localhost:7878 + - RADARR_KEY=$RADARR_API_KEY + # Sonarr + - SONARR_URL=http://localhost:8989 + - SONARR_KEY=$SONARR_API_KEY + # Lidarr + - LIDARR_URL=http://localhost:8686 + - LIDARR_KEY=$LIDARR_API_KEY + # qBittorrent + - QBITTORRENT_URL=http://localhost:8080 + #- QBITTORRENT_USERNAME=Your name + #- QBITTORRENT_PASSWORD=Your password +``` +3) Run `docker-compose up -d` in the directory where the file is located to create the docker container + +## Running manually +1) Clone the repository with `git clone https://github.com/Fxsch/decluttarr.git` +2) Tweak the `config.conf` file to your needs +3) Run the script with `python3 main.py` + +## Explanation of the settings +**LOG_LEVEL** +- Sets the level at which logging will take place +- `INFO` will only show changes applied to radarr/sonarr/lidarr +- `VERBOSE` will show when script runs (even if it results in no change) +- Type: String +- Permissible Values: CRITICAL, ERROR, WARNING, INFO, VERBOSE, DEBUG +- Is Mandatory: No (Defaults to INFO) + +**TEST_RUN** +- Allows you to safely try out this tool. If active, downloads will not be removed. +- Type: Boolean +- Permissible Values: True, False +- Is Mandatory: No (Defaults to False) + +--- + +### **Features settings** +- Steers which type of cleaning is applied to the downloads queue +- Requires `QUEUE_CLEANING` to be set to `True` to take effect + +**REMOVE_TIMER** +- Sets the frequency of how often the queue is checked for orphan and stalled downloads +- Type: Integer +- Unit: Minutes +- Is Mandatory: No (Defaults to 10) + +**REMOVE_FAILED** +- Steers whether failed downloads with no connections are removed from the queue +- These downloads are not added to the blocklist +- Type: Boolean +- Permissible Values: True, False +- Is Mandatory: No (Defaults to False) + +**REMOVE_STALLED** +- Steers whether stalled downloads with no connections are removed from the queue +- These downloads are added to the blocklist, so that they are not re-requested in the future +- A new download from another source is automatically added by radarr/sonarr/lidarr (if available) +- Type: Boolean +- Permissible Values: True, False +- Is Mandatory: No (Defaults to False) + +**REMOVE_METADATA_MISSING** +- Steers whether downloads stuck obtaining metadata are removed from the queue +- These downloads are added to the blocklist, so that they are not re-requested +- A new download from another source is automatically added by radarr/sonarr/lidarr (if available) +- Type: Boolean +- Permissible Values: True, False +- Is Mandatory: No (Defaults to False) + +**REMOVE_ORPHANS** +- Steers whether orphan downloads are removed from the queue +- Orphan downloads are those that do not belong to any requested media anymore (Since the media was removed from radarr/sonarr/lidarr after the download started) +- These downloads are not added to the blocklist +- Type: Boolean +- Permissible Values: True, False +- Is Mandatory: No (Defaults to False) + +**REMOVE_UNMONITORED** +- Steers whether downloads belonging to unmonitored media are removed from the queue +- Note: Will only remove from queue if all TV shows depending on the same download are unmonitored +- These downloads are not added to the blocklist +- Note: Since sonarr does not support multi-season packs, if you download one you should protect it with `NO_STALLED_REMOVAL_QBIT_TAG` that is explained further down +- Type: Boolean +- Permissible Values: True, False +- Is Mandatory: No (Defaults to False) + +**PERMITTED_ATTEMPTS** +- Defines how many times a download has to be caught as stalled or stuck downloading metadata before it is removed +- Type: Integer +- Unit: Number of scans +- Is Mandatory: No (Defaults to 3) + +**NO_STALLED_REMOVAL_QBIT_TAG** +- Downloads in qBittorrent tagged with this tag will not be killed even if they are stalled +- Tag is automatically created in qBittorrent (required qBittorrent is reachable on `QBITTORRENT_URL`) +- Also protects unmonitored downloads from being removed (relevant for multi-season packs) +- Type: String +- Is Mandatory: No (Defaults to `Don't Kill If Stalled`) + +--- + +### **Radarr section** +- Defines radarr instance on which download queue should be decluttered + +**RADARR_URL** +- URL under which the instance can be reached +- If not defined, this instance will not be monitored + +**RADARR_KEY** +- Your API key for radarr + +--- + +### **Sonarr section** +- Defines sonarr instance on which download queue should be decluttered + +**SONARR_URL** +- URL under which the instance can be reached +- If not defined, this instance will not be monitored + +**SONARR_KEY** +- Your API key for sonarr + +--- + +### **Lidarr section** +- Defines lidarr instance on which download queue should be decluttered + +**LIDARR_URL** +- URL under which the instance can be reached +- If not defined, this instance will not be monitored + +**LIDARR_KEY** +- Your API key for lidarr + +--- + +### **qBittorrent section** +- Defines settings to connect with qBittorrent + +**QBITTORRENT_URL** +- URL under which the instance can be reached +- If not defined, the NO_STALLED_REMOVAL_QBIT_TAG takes no effect + +**QBITTORRENT_USERNAME** +- Username used to log in to qBittorrent +- Optional; not needed if authentication bypassing on qBittorrent is enabled (for instance for local connections) + +**QBITTORRENT_PASSWORD** +- Password used to log in to qBittorrent +- Optional; not needed if authentication bypassing on qBittorrent is enabled (for instance for local connections) ## Dependencies Use Sonarr v4 & Radarr v5 (currently 'nightly' tag instead of 'latest'), else certain features may not work correctly. Use latest version of qBittorrent. ## Credits +- ManiMatter for making this, I just forked it to fix some stuff - Script for detecting stalled downloads expanded on code by MattDGTL/sonarr-radarr-queue-cleaner - Script to read out config expanded on code by syncarr/syncarr - SONARR/RADARR team & contributors for their great product, API documenation, and guidance in their Discord channel @@ -38,4 +214,3 @@ Use latest version of qBittorrent. ## Disclaimer This script comes free of any warranty, and you are using it at your own risk. -I do not intend to maintain this repo, feel free to fork & create PRs if you want to expand it for your own use diff --git a/config.conf b/config.conf new file mode 100644 index 0000000..6cc626a --- /dev/null +++ b/config.conf @@ -0,0 +1,30 @@ +[general] +LOG_LEVEL = VERBOSE +TEST_RUN = True + +[features] +REMOVE_TIMER = 10 +REMOVE_FAILED = True +REMOVE_STALLED = True +REMOVE_METADATA_MISSING = True +REMOVE_ORPHANS = True +REMOVE_UNMONITORED = True +PERMITTED_ATTEMPTS = 3 +NO_STALLED_REMOVAL_QBIT_TAG = Don't Kill If Stalled + +[radarr] +RADARR_URL = http://localhost:7878 +RADARR_KEY = $RADARR_API_KEY + +[sonarr] +SONARR_URL = http://localhost:8989 +SONARR_KEY = $SONARR_API_KEY + +[lidarr] +LIDARR_URL = http://localhost:8686 +LIDARR_KEY = $LIDARR_API_KEY + +[qbittorrent] +QBITTORRENT_URL = http://localhost:8080 +QBITTORRENT_USERNAME = Your name (or empty) +QBITTORRENT_PASSWORD = Your password (or empty) \ No newline at end of file diff --git a/config/config.conf-Example b/config/config.conf-Example deleted file mode 100644 index bd324aa..0000000 --- a/config/config.conf-Example +++ /dev/null @@ -1,30 +0,0 @@ -[general] -LOG_LEVEL = VERBOSE -TEST_RUN = True - -[features] -REMOVE_TIMER = 10 -REMOVE_FAILED = True -REMOVE_STALLED = True -REMOVE_METADATA_MISSING = True -REMOVE_ORPHANS = True -REMOVE_UNMONITORED = True -PERMITTED_ATTEMPTS = 3 -NO_STALLED_REMOVAL_QBIT_TAG = Don't Kill If Stalled - -[radarr] -RADARR_URL = http://radarr:7878 -RADARR_KEY = $RADARR_KEY - -[sonarr] -SONARR_URL = http://sonarr:8989 -SONARR_KEY = $SONARR_KEY - -[lidarr] -LIDARR_URL = http://lidarr:8686 -LIDARR_KEY = $LIDARR_KEY - -[qbittorrent] -QBITTORRENT_URL = http://qbittorrent:8080 -QBITTORRENT_USERNAME = YourName or Empty -QBITTORRENT_PASSWORD = YourPassword or Empty \ No newline at end of file diff --git a/config/config.conf-Explained b/config/config.conf-Explained deleted file mode 100644 index 506b1ce..0000000 --- a/config/config.conf-Explained +++ /dev/null @@ -1,130 +0,0 @@ -# The config file is only relevant when running main.py locally. -# When running within docker, all settings are to be set via the docker-compose.yml, and this config.conf file will be ignored - -################################# GENERAL SECTION ################################# -# General parameters such as log level / test run -[general] - -###### LOG_LEVEL ###### -# Sets the level at which logging will take place. -# INFO will only show changes applied to Radarr/Sonarr -# VERBOSE will show when script runs (even if it results in no change) -# Type: String -# Permissible Values: CRITICAL, ERROR, WARNING, INFO, VERBOSE, DEBUG -# Is Mandatory: No (Defaults to INFO) -LOG_LEVEL = INFO - -###### TEST_RUN ###### -# Allows you to safely try out this tool. If active, downloads will not be removed. -# Type: Boolean -# Permissible Values: True, False -# Is Mandatory: No (Defaults to False) -TEST_RUN = False - -################################# FEATURES SETTINGS ################################# -# Steers which type of cleaning is applied to the downloads queue. -# Requires QUEUE_CLEANING to be set to True to take effect. -[features] - -###### REMOVE_TIMER ###### -# Sets the frequency how often the queue is cleaned form orphan and stalled downloads -# Type: Integer -# Unit: Minutes -# Is Mandatory: No (Defaults to 10) -REMOVE_TIMER = 10 - -###### REMOVE_FAILED ###### -# Steers whether failed downloads with no connections are removed from the queue -# Failed downloads are not added to the blocklist -# Type: Boolean -# Permissible Values: True, False -# Is Mandatory: No (Defaults to False) -REMOVE_FAILED = False - -###### REMOVE_STALLED ###### -# Steers whether stalled downloads with no connections are removed from the queue -# Stalled downloads are added to the blocklist, so that they are not re-requested in the future -# A new download from another source is automatically added by sonarr/radarr (if available) -# Type: Boolean -# Permissible Values: True, False -# Is Mandatory: No (Defaults to False) -REMOVE_STALLED = False - -###### REMOVE_METADATA_MISSING ###### -# Steers whether downloads stuck obtaining meta data are removed from the queue -# These downloads are added the blocklist, so that they are not re-requested in the future -# A new download from another source is automatically added by sonarr/radarr (if available) -# Type: Boolean -# Permissible Values: True, False -# Is Mandatory: No (Defaults to False) -REMOVE_METADATA_MISSING = False - -###### REMOVE_ORPHANS ###### -# Steers whether orphan downloads are removed from the queue -# Orphan downloads those that do not belong to any movie/tvshow anymore (since the movie/TV show was deleted post request) -# Orphan downloads are not added to the block list -# Type: Boolean -# Permissible Values: True, False -# Is Mandatory: No (Defaults to False) -REMOVE_ORPHANS = False - -###### REMOVE_UNMONITORED ###### -# Steers whether downloads belonging to unmonitored movies/TV shows are removed from the queue -# Note: Will only remove from queue if all tv shows depending on the same download are unmonitored -# Unmonitored downloads are not added to the block list -# Note: Since Sonarr does not support multi-season packs, if you download one you should protect it with the below NO_STALLED_REMOVAL_QBIT_TAG. -# Type: Boolean -# Permissible Values: True, False -# Is Mandatory: No (Defaults to False) -REMOVE_UNMONITORED = False - -###### PERMITTED_ATTEMPTS ###### -# Defines how many times a download has to be caught as stalled or stuck downloading metadata before it is removed -# Type: Integer -# Unit: Number of scans -# Is Mandatory: No (Defaults to 3) -PERMITTED_ATTEMPTS= 3 - -###### NO_STALLED_REMOVAL_QBIT_TAG ###### -# Downloads in qBittorrent tagged with this tag will not be killed even if they are stalled -# Tag is automatically created in qBittorrent (required qBittorrent is reachable on QBITTORRENT_URL ) -# Also protects unmonitored downloads from being removed (relevant for multi-season packs) -# Type: String -# Is Mandatory: No (Defaults to "Don't Kill If Stalled") -NO_STALLED_REMOVAL_QBIT_TAG= Don't Kill If Stalled - -################################# RADARR SECTION ################################# -[radarr] -# Defines radarr instance on which download queue should be decluttered -# RADARR_URL : URL under which the instance can be reached. If not defined, this instance will not be monitored. -# RADARR_KEY : API Key (mandatory if RADARR_URL is specifidd) -RADARR_URL = http://radarrA:7878 -RADARR_KEY = XXXXX - -################################# SONARR SECTION ################################# -[sonarr] -# Please see the documentation under the RADARR section - the explanations the same. -SONARR_URL = http://sonarr:8989 -SONARR_KEY = XXXXX - -################################# SONARR SECTION ################################# -[sonarr] -# Please see the documentation under the RADARR section - the explanations the same. -SONARR_URL = http://sonarr:8989 -SONARR_KEY = XXXXX - -################################# SONARR SECTION ################################# -[lidarr] -# Please see the documentation under the RADARR section - the explanations the same. -LIDARR_URL = http://lidarr:8686 -LIDARR_KEY = XXXXX - -################################# QBITTORRENT SECTION ################################# -[qbittorrent] -# Defines settings to connect with qBittorrent -# QBITTORRENT_URL : URL under which the instance can be reached. If not defined, the NO_STALLED_REMOVAL_QBIT_TAG takes no effect -# QBITTORRENT_USERNAME: Optional; particularly not needed if authentication bypassing on qBittorrent is enabled (for instance for local connections) -# QBITTORRENT_PASSWORD: Optional; same reason as above -QBITTORRENT_URL = http://qbittorrent:8080 -QBITTORRENT_USERNAME = Your Name (or empty) -QBITTORRENT_PASSWORD = Your Password (or empty) \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index e584110..aeeab1b 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,6 +1,6 @@ #FROM python:3.9-slim-buster FROM python:3.10.13-slim -LABEL org.opencontainers.image.source="https://github.com/ManiMatter/decluttarr" +LABEL org.opencontainers.image.source="https://github.com/Fxsch/decluttarr" ENV IS_IN_DOCKER 1 diff --git a/docker/Sample docker-compose.yml b/docker/Sample docker-compose.yml deleted file mode 100644 index 4d2b494..0000000 --- a/docker/Sample docker-compose.yml +++ /dev/null @@ -1,34 +0,0 @@ -# decluttarr - Keeps radarr and sonarr download queues free of stalled and redundant items - decluttarr: - image: ghcr.io/manimatter/decluttarr:latest - container_name: decluttarr - restart: always - environment: - TZ: Europe/Zurich - PUID: 1000 - PGID: 1000 - # General - LOG_LEVEL: INFO - #TEST_RUN: True - # Features - REMOVE_TIMER: 10 - REMOVE_FAILED: True - REMOVE_STALLED: True - REMOVE_METADATA_MISSING: True - REMOVE_ORPHANS: True - REMOVE_UNMONITORED: True - PERMITTED_ATTEMPTS: 3 - NO_STALLED_REMOVAL_QBIT_TAG: Don't Kill If Stalled - # Radarr - RADARR_URL: http://radarr:7878 - RADARR_KEY: $RADARR_API_KEY - # Sonarr - SONARR_URL: http://sonarr:8989 - SONARR_KEY: $SONARR_API_KEY - # Lidarr - LIDARR_URL: http://lidarr:8686 - LIDARR_KEY: $LIDARR_KEY - # qBitorrent - QBITTORRENT_URL: http://qbittorrent:8080 - #QBITTORRENT_USERNAME: Your Name - #QBITTORRENT_PASSWORD: Your Password \ No newline at end of file