#!/bin/sh # Supervise the app and keep yt-dlp fresh. # # yt-dlp breaks frequently against site changes, so we check PyPI once a day # for a newer release. The app imports yt_dlp at startup, so a new version # only takes effect on (re)start -- we therefore restart the app *only* when # an update was actually installed. If the app exits on its own, we propagate # its exit status so Docker's restart policy can handle it. set -e CHECK_INTERVAL=86400 # check for a new yt-dlp once per day POLL=60 # how often to check on the app # Upgrade yt-dlp only if PyPI has a newer version. # Returns 0 if an update was installed, 1 otherwise (incl. errors / up to date). # Versions are compared numerically: the installed version can be zero-padded # (e.g. 2026.06.09) while PyPI reports the normalized form (e.g. 2026.6.9). check_and_update() { if python3 - <<'PY' import json, sys, urllib.request try: import yt_dlp current = yt_dlp.version.__version__ latest = json.load(urllib.request.urlopen( 'https://pypi.org/pypi/yt-dlp/json', timeout=30))['info']['version'] except Exception as e: print(f"Could not check for yt-dlp updates ({e}); will retry.") sys.exit(1) def key(v): try: return tuple(int(p) for p in v.split('.')) except ValueError: return None ck, lk = key(current), key(latest) newer = (lk > ck) if (ck and lk) else (current != latest) if newer: print(f"New yt-dlp available: {current} -> {latest}. Updating...") sys.exit(0) print(f"yt-dlp is up to date ({current}).") sys.exit(1) PY then pip install --upgrade --quiet --root-user-action=ignore "yt-dlp[default,curl-cffi]" \ && return 0 echo "yt-dlp update failed; continuing with the installed version." fi return 1 } # Forward termination to the app so the container stops cleanly. trap 'kill "$APP_PID" 2>/dev/null; exit 0' TERM INT while true; do # Make sure we launch with the latest available yt-dlp. check_and_update || true "$@" & APP_PID=$! # Periodically check for updates; restart the app only when one is applied. while true; do waited=0 while [ "$waited" -lt "$CHECK_INTERVAL" ] && kill -0 "$APP_PID" 2>/dev/null; do sleep "$POLL" waited=$((waited + POLL)) done if ! kill -0 "$APP_PID" 2>/dev/null; then wait "$APP_PID" status=$? echo "App exited with status $status" exit "$status" fi if check_and_update; then echo "Restarting app to apply yt-dlp update..." kill "$APP_PID" 2>/dev/null || true wait "$APP_PID" 2>/dev/null || true break # outer loop relaunches the app fi done done