From 3e2f46377eadaec0eae418398b87773d57270902 Mon Sep 17 00:00:00 2001 From: Dominik Polakovics Date: Wed, 26 Nov 2025 21:08:58 +0100 Subject: [PATCH] fix: pyload and filebot --- hosts/fw/modules/pyload.nix | 122 ++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 54 deletions(-) diff --git a/hosts/fw/modules/pyload.nix b/hosts/fw/modules/pyload.nix index 96c48c1..101063b 100644 --- a/hosts/fw/modules/pyload.nix +++ b/hosts/fw/modules/pyload.nix @@ -3,24 +3,59 @@ let cids = import ./staticids.nix; networkPrefix = config.networkPrefix; - # FileBot post-processing script + # FileBot post-processing script for PyLoad hooks filebotScript = pkgs.writeShellScript "filebot-process.sh" '' #!/usr/bin/env bash set -euo pipefail # FileBot AMC script for automated media organization - # Arguments: $1 = download directory (passed by pyload) + # Called by PyLoad's package_extracted hook with parameters: + # $1 = package_id + # $2 = package_name + # $3 = download_folder (actual path to extracted files) + # $4 = password (optional) + + PACKAGE_ID="''${1:-}" + PACKAGE_NAME="''${2:-unknown}" + DOWNLOAD_DIR="''${3:-/downloads}" + PASSWORD="''${4:-}" - DOWNLOAD_DIR="''${1:-/downloads}" OUTPUT_DIR="/multimedia" - LOG_FILE="/var/lib/filebot/amc.log" - EXCLUDE_LIST="/var/lib/filebot/amc-exclude-list.txt" + LOG_FILE="/var/lib/pyload/filebot-amc.log" + EXCLUDE_LIST="/var/lib/pyload/filebot-exclude-list.txt" - # Ensure log directory exists + # Ensure FileBot data directory exists + mkdir -p /var/lib/pyload/.local/share/filebot/data mkdir -p "$(dirname "$LOG_FILE")" touch "$EXCLUDE_LIST" - echo "$(date): Starting FileBot processing for: $DOWNLOAD_DIR" >> "$LOG_FILE" + # Install FileBot license if not already installed + if [ ! -f /var/lib/pyload/.local/share/filebot/data/.license ]; then + echo "$(date): Installing FileBot license..." >> "$LOG_FILE" + ${pkgs.filebot}/bin/filebot --license /var/lib/pyload/filebot-license.psm || true + fi + + echo "===========================================" >> "$LOG_FILE" + echo "$(date): PyLoad package extracted hook triggered" >> "$LOG_FILE" + echo "Package ID: $PACKAGE_ID" >> "$LOG_FILE" + echo "Package Name: $PACKAGE_NAME" >> "$LOG_FILE" + echo "Download Directory: $DOWNLOAD_DIR" >> "$LOG_FILE" + echo "===========================================" >> "$LOG_FILE" + + # Check if download directory exists and has media files + if [ ! -d "$DOWNLOAD_DIR" ]; then + echo "$(date): Download directory does not exist: $DOWNLOAD_DIR" >> "$LOG_FILE" + exit 0 + fi + + # Check if there are any video/media files to process + if ! find "$DOWNLOAD_DIR" -type f \( -iname "*.mkv" -o -iname "*.mp4" -o -iname "*.avi" -o -iname "*.m4v" -o -iname "*.mov" \) -print -quit | grep -q .; then + echo "$(date): No media files found in: $DOWNLOAD_DIR" >> "$LOG_FILE" + echo "$(date): Skipping FileBot processing" >> "$LOG_FILE" + exit 0 + fi + + echo "$(date): Starting FileBot processing" >> "$LOG_FILE" # Run FileBot AMC script ${pkgs.filebot}/bin/filebot \ @@ -37,12 +72,16 @@ let ut_dir="$DOWNLOAD_DIR" \ ut_kind=multi \ clean=y \ - skipExtract=y + skipExtract=y || { + echo "$(date): FileBot processing failed with exit code $?" >> "$LOG_FILE" + exit 0 # Don't fail the hook even if FileBot fails + } # Clean up empty directories find "$DOWNLOAD_DIR" -type d -empty -delete 2>/dev/null || true - echo "$(date): FileBot processing completed" >> "$LOG_FILE" + echo "$(date): FileBot processing completed successfully" >> "$LOG_FILE" + exit 0 ''; pyloadUser = { @@ -51,6 +90,7 @@ let group = "pyload"; home = "/var/lib/pyload"; createHome = true; + extraGroups = [ "jellyfin" ]; # Access to multimedia directories }; pyloadGroup = { gid = cids.gids.pyload; @@ -67,26 +107,12 @@ let jellyfinGroup = { gid = cids.gids.jellyfin; }; - - filebotUser = { - isSystemUser = true; - uid = cids.uids.filebot; - group = "filebot"; - home = "/var/lib/filebot"; - createHome = true; - extraGroups = [ "pyload" "jellyfin" ]; # Access to both download and media directories - }; - filebotGroup = { - gid = cids.gids.filebot; - }; in { users.users.pyload = pyloadUser; users.groups.pyload = pyloadGroup; users.users.jellyfin = jellyfinUser; users.groups.jellyfin = jellyfinGroup; - users.users.filebot = filebotUser; - users.groups.filebot = filebotGroup; # Create the directory structure on the host systemd.tmpfiles.rules = [ @@ -96,14 +122,19 @@ in "d /var/lib/multimedia/tv-shows 0775 jellyfin jellyfin - -" "d /var/lib/multimedia/music 0755 jellyfin jellyfin - -" "d /var/lib/jellyfin 0755 jellyfin jellyfin - -" - "d /var/lib/filebot 0755 filebot filebot - -" + + # PyLoad hook scripts directory + "d /var/lib/pyload/config 0755 pyload pyload - -" + "d /var/lib/pyload/config/scripts 0755 pyload pyload - -" + "d /var/lib/pyload/config/scripts/package_extracted 0755 pyload pyload - -" + "L+ /var/lib/pyload/config/scripts/package_extracted/filebot-process.sh - - - - ${filebotScript}" ]; # FileBot license secret sops.secrets.filebot-license = { mode = "0440"; - owner = config.users.users.root.name; - group = config.users.groups.root.name; + owner = "pyload"; + group = "pyload"; }; containers.pyload = { @@ -155,11 +186,7 @@ in hostPath = "/var/lib/multimedia"; isReadOnly = false; }; - "/var/lib/filebot" = { - hostPath = "/var/lib/filebot"; - isReadOnly = false; - }; - "/var/lib/filebot/license.psm" = { + "/var/lib/pyload/filebot-license.psm" = { hostPath = config.sops.secrets.filebot-license.path; isReadOnly = true; }; @@ -247,6 +274,10 @@ in # Disable SSL certificate verification PYLOAD__GENERAL__SSL_VERIFY = "0"; + # Download speed limiting (150 Mbit/s = 19200 KiB/s) + PYLOAD__DOWNLOAD__LIMIT_SPEED = "1"; + PYLOAD__DOWNLOAD__MAX_SPEED = "19200"; + # Enable ExtractArchive plugin PYLOAD__EXTRACTARCHIVE__ENABLED = "1"; PYLOAD__EXTRACTARCHIVE__DELETE = "1"; @@ -254,6 +285,10 @@ in PYLOAD__EXTRACTARCHIVE__REPAIR = "1"; PYLOAD__EXTRACTARCHIVE__RECURSIVE = "1"; PYLOAD__EXTRACTARCHIVE__FULLPATH = "1"; + + # Enable ExternalScripts plugin for hooks + PYLOAD__EXTERNALSCRIPTS__ENABLED = "1"; + PYLOAD__EXTERNALSCRIPTS__UNLOCK = "1"; # Run hooks asynchronously }; # Bind-mount DNS configuration files into the chroot @@ -265,27 +300,8 @@ in "/etc/ssl" "/etc/static/ssl" ]; - }; - }; - - # FileBot processing service - systemd.services.filebot-process = { - description = "FileBot media file processing"; - serviceConfig = { - Type = "oneshot"; - User = "filebot"; - Group = "filebot"; - ExecStart = "${filebotScript}"; - }; - }; - - # Watch for completed downloads and trigger FileBot - systemd.paths.filebot-watch = { - description = "Watch for completed downloads"; - wantedBy = [ "multi-user.target" ]; - pathConfig = { - PathModified = "/downloads"; - Unit = "filebot-process.service"; + # Bind mount multimedia directory as writable for FileBot hook scripts + BindPaths = [ "/multimedia" ]; }; }; @@ -297,8 +313,6 @@ in users.groups.pyload = pyloadGroup; users.users.jellyfin = jellyfinUser; users.groups.jellyfin = jellyfinGroup; - users.users.filebot = filebotUser; - users.groups.filebot = filebotGroup; system.stateVersion = "24.05"; };