187 lines
6.6 KiB
Nix
187 lines
6.6 KiB
Nix
{ pkgs }:
|
|
|
|
pkgs.writeShellScriptBin "filebot-process" ''
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# FileBot AMC script for automated media organization
|
|
# 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:-/var/lib/downloads}"
|
|
PASSWORD="''${4:-}"
|
|
|
|
OUTPUT_DIR="/var/lib/multimedia"
|
|
LOG_FILE="/var/lib/pyload/filebot-amc.log"
|
|
EXCLUDE_LIST="/var/lib/pyload/filebot-exclude-list.txt"
|
|
PASSWORD_FILE="/var/lib/pyload/extraction-passwords.txt"
|
|
|
|
# Ensure FileBot data directory exists
|
|
mkdir -p /var/lib/pyload/.local/share/filebot/data
|
|
mkdir -p "$(dirname "$LOG_FILE")"
|
|
touch "$EXCLUDE_LIST"
|
|
|
|
# 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 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
|
|
if [ ! -d "$DOWNLOAD_DIR" ]; then
|
|
echo "$(date): Download directory does not exist: $DOWNLOAD_DIR" >> "$LOG_FILE"
|
|
exit 0
|
|
fi
|
|
|
|
# --- Archive Extraction ---
|
|
|
|
# Try extraction with passwords, then without
|
|
try_extract() {
|
|
local archive="$1"
|
|
local outdir
|
|
outdir="$(dirname "$archive")"
|
|
|
|
# Try each password from file
|
|
if [ -f "$PASSWORD_FILE" ]; then
|
|
while IFS= read -r pass || [ -n "$pass" ]; do
|
|
[ -z "$pass" ] && continue
|
|
case "$archive" in
|
|
*.rar) ${pkgs.unrar}/bin/unrar x -p"$pass" -o+ "$archive" "$outdir/" >/dev/null 2>&1 && return 0 ;;
|
|
*.7z) ${pkgs.p7zip}/bin/7z x -p"$pass" -aoa -o"$outdir" "$archive" >/dev/null 2>&1 && return 0 ;;
|
|
*.zip) ${pkgs.p7zip}/bin/7z x -p"$pass" -aoa -o"$outdir" "$archive" >/dev/null 2>&1 && return 0 ;;
|
|
esac
|
|
done < "$PASSWORD_FILE"
|
|
fi
|
|
|
|
# Try without password
|
|
case "$archive" in
|
|
*.rar) ${pkgs.unrar}/bin/unrar x -o+ "$archive" "$outdir/" >/dev/null 2>&1 && return 0 ;;
|
|
*.7z) ${pkgs.p7zip}/bin/7z x -aoa -o"$outdir" "$archive" >/dev/null 2>&1 && return 0 ;;
|
|
*.zip) ${pkgs.p7zip}/bin/7z x -aoa -o"$outdir" "$archive" >/dev/null 2>&1 && return 0 ;;
|
|
esac
|
|
return 1
|
|
}
|
|
|
|
# Delete all parts of a split RAR archive
|
|
delete_rar_parts() {
|
|
local first_part="$1"
|
|
local base dir
|
|
|
|
dir="$(dirname "$first_part")"
|
|
# Extract base name: "foo.part1.rar" -> "foo", "foo.part01.rar" -> "foo"
|
|
base="$(basename "$first_part" | ${pkgs.gnused}/bin/sed -E 's/\.part[0-9]+\.rar$//')"
|
|
|
|
# Delete all parts matching the pattern
|
|
find "$dir" -maxdepth 1 -type f -iname "''${base}.part*.rar" -delete
|
|
echo "$(date): Deleted all parts: ''${base}.part*.rar" >> "$LOG_FILE"
|
|
}
|
|
|
|
# Extract archives in directory
|
|
extract_archives() {
|
|
local dir="$1"
|
|
local extracted=0
|
|
|
|
# 1. Handle split RAR archives (*.part1.rar or *.part01.rar - first part only)
|
|
while IFS= read -r -d "" archive; do
|
|
echo "$(date): Extracting split RAR: $archive" >> "$LOG_FILE"
|
|
if try_extract "$archive"; then
|
|
echo "$(date): Extraction successful" >> "$LOG_FILE"
|
|
delete_rar_parts "$archive"
|
|
extracted=1
|
|
else
|
|
echo "$(date): Extraction FAILED: $archive" >> "$LOG_FILE"
|
|
fi
|
|
done < <(find "$dir" -type f \( -iname "*.part1.rar" -o -iname "*.part01.rar" \) -print0 2>/dev/null)
|
|
|
|
# 2. Handle single RAR files (not part of split archive)
|
|
while IFS= read -r -d "" archive; do
|
|
echo "$(date): Extracting RAR: $archive" >> "$LOG_FILE"
|
|
if try_extract "$archive"; then
|
|
echo "$(date): Extraction successful, deleting: $archive" >> "$LOG_FILE"
|
|
rm -f "$archive"
|
|
extracted=1
|
|
else
|
|
echo "$(date): Extraction FAILED: $archive" >> "$LOG_FILE"
|
|
fi
|
|
done < <(find "$dir" -type f -iname "*.rar" ! -iname "*.part*.rar" -print0 2>/dev/null)
|
|
|
|
# 3. Handle 7z and zip archives
|
|
while IFS= read -r -d "" archive; do
|
|
echo "$(date): Extracting: $archive" >> "$LOG_FILE"
|
|
if try_extract "$archive"; then
|
|
echo "$(date): Extraction successful, deleting: $archive" >> "$LOG_FILE"
|
|
rm -f "$archive"
|
|
extracted=1
|
|
else
|
|
echo "$(date): Extraction FAILED: $archive" >> "$LOG_FILE"
|
|
fi
|
|
done < <(find "$dir" -type f \( -iname "*.7z" -o -iname "*.zip" \) -print0 2>/dev/null)
|
|
|
|
[ "$extracted" -eq 1 ] && return 0 || return 1
|
|
}
|
|
|
|
# Run extraction (loop to handle nested archives)
|
|
echo "$(date): Starting archive extraction..." >> "$LOG_FILE"
|
|
for i in 1 2 3; do
|
|
extract_archives "$DOWNLOAD_DIR" || break
|
|
done
|
|
echo "$(date): Archive extraction complete" >> "$LOG_FILE"
|
|
|
|
# --- Media Processing ---
|
|
|
|
# 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
|
|
set +e # Temporarily disable exit on error to capture exit code
|
|
${pkgs.filebot}/bin/filebot \
|
|
-script fn:amc \
|
|
--output "$OUTPUT_DIR" \
|
|
--action move \
|
|
--conflict auto \
|
|
-non-strict \
|
|
--log-file "$LOG_FILE" \
|
|
--def \
|
|
excludeList="$EXCLUDE_LIST" \
|
|
movieFormat="$OUTPUT_DIR/movies/{n} ({y})/{n} ({y}) - {vf}" \
|
|
seriesFormat="$OUTPUT_DIR/tv-shows/{n}/Season {s.pad(2)}/{n} - {s00e00} - {t}" \
|
|
ut_dir="$DOWNLOAD_DIR" \
|
|
ut_kind=multi \
|
|
clean=y \
|
|
skipExtract=y
|
|
|
|
FILEBOT_EXIT_CODE=$?
|
|
set -e # Re-enable exit on error
|
|
|
|
if [ $FILEBOT_EXIT_CODE -ne 0 ]; then
|
|
echo "$(date): FileBot processing failed with exit code $FILEBOT_EXIT_CODE" >> "$LOG_FILE"
|
|
exit 0 # Don't fail the hook even if FileBot fails
|
|
fi
|
|
|
|
echo "$(date): FileBot processing completed successfully" >> "$LOG_FILE"
|
|
|
|
# Clean up any remaining empty directories
|
|
find "$DOWNLOAD_DIR" -type d -empty -delete 2>/dev/null || true
|
|
|
|
echo "$(date): All processing completed" >> "$LOG_FILE"
|
|
exit 0
|
|
''
|