#!/bin/sh set -eu IMMICH_URL="${IMMICH_URL:?IMMICH_URL is required}" # e.g. http://immich:8080 IMMICH_API_KEY="${IMMICH_API_KEY:?IMMICH_API_KEY is required}" SCAN_DIR="${SCAN_DIR:-/drop}" DELETE_ON_SUCCESS="${DELETE_ON_SUCCESS:-true}" SCAN_INTERVAL="${SCAN_INTERVAL:-5}" ALLOW_INSECURE_SSL="${ALLOW_INSECURE_SSL:-false}" CONCURRENCY="${CONCURRENCY:-4}" IDLE_SLEEP="${IDLE_SLEEP:-3}" case "$CONCURRENCY" in ''|*[!0-9]*) CONCURRENCY=1 ;; esac [ "$CONCURRENCY" -lt 1 ] && CONCURRENCY=1 echo "[uploader] Target: ${IMMICH_URL}" echo "[uploader] Source (drop): ${SCAN_DIR} (scan every ${SCAN_INTERVAL}s, concurrency ${CONCURRENCY})" CURL_OPTS="-sS -m 5 -o /dev/null -w %{http_code}" [ "$ALLOW_INSECURE_SSL" = "true" ] && CURL_OPTS="$CURL_OPTS -k" PING="${IMMICH_URL%/}/api/server-info" wait_for_immich() { backoff=1 max_backoff=30 last="" while :; do code="$(curl $CURL_OPTS "$PING" 2>/dev/null || true)" case "$code" in 2*|3*|4*) [ "$last" != "up" ] && echo "[uploader] Immich is up (HTTP $code)."; return 0 ;; *) [ "$last" != "down" ] && echo "[uploader] Waiting for Immich at $PING ...";; esac last="down" sleep "$backoff" [ "$backoff" -lt "$max_backoff" ] && backoff=$((backoff*2)) [ "$backoff" -gt "$max_backoff" ] && backoff="$max_backoff" done } prune_empty_parents() { dir="$(dirname "$1")" while [ "$dir" != "$SCAN_DIR" ]; do rmdir "$dir" 2>/dev/null || break dir="$(dirname "$dir")" done } upload_one() { f="$1" if immich-go upload from-folder \ --server "${IMMICH_URL}" \ --api-key "${IMMICH_API_KEY}" \ --no-ui --on-server-errors continue \ --pause-immich-jobs=false \ --recursive=false \ "$f" >/dev/null 2>&1 then echo "[uploader] OK: $(basename "$f")" if [ "$DELETE_ON_SUCCESS" = "true" ]; then rm -f -- "$f" || true prune_empty_parents "$f" fi else echo "[uploader] FAIL: $(basename "$f") — will retry next loop" fi } upload_batch() { count="$#" echo "[uploader] Found $count file(s) to upload" running=0 pids="" for f in "$@"; do upload_one "$f" & pid=$! pids="$pids $pid" running=$((running+1)) if [ "$running" -ge "$CONCURRENCY" ]; then set -- $pids pid_to_wait="$1" pids="${pids# $pid_to_wait}" wait "$pid_to_wait" || true running=$((running-1)) fi done for pid in $pids; do wait "$pid" || true done } while :; do wait_for_immich file_list="$(find "$SCAN_DIR" -type f -size +0c -print0 | xargs -0 -I{} printf '%s\n' "{}")" if [ -z "$file_list" ]; then sleep "$IDLE_SLEEP" continue fi oldifs="$IFS" IFS=' ' set -- $file_list IFS="$oldifs" upload_batch "$@" sleep "$SCAN_INTERVAL" done