#!/bin/bash # Everything that does NOT need root: the venv, yt-dlp, the POT container, the # database. # # Normally invoked for you by deploy.sh, which creates the state directory first. # Safe to run directly as susan afterwards โ€” for instance to rebuild the venv: # # /opt/ytstream/deploy/bootstrap.sh set -euo pipefail STATE=/var/lib/ytstream VENV=$STATE/venv REPO=/opt/ytstream say() { printf '\n\033[1m==> %s\033[0m\n' "$1"; } if [[ ! -d $STATE ]]; then echo "$STATE does not exist. Run 'sudo $REPO/deploy/deploy.sh' โ€” it creates the" >&2 echo "directory and then calls this script." >&2 exit 1 fi if [[ ! -w $STATE ]]; then echo "$STATE is not writable by $(id -un). Expected mode 0770 susan:automation." >&2 exit 1 fi say "Creating the virtualenv" python3 -m venv "$VENV" "$VENV/bin/pip" install --quiet --upgrade pip "$VENV/bin/pip" install --quiet -e "$REPO" say "Verifying yt-dlp and the POT plugin" # The plugin is what makes YouTube reachable at all. A venv without it looks fine # until the first playback fails with a bare 403. "$VENV/bin/yt-dlp" --version "$VENV/bin/python3" - <<'PY' import importlib.util missing = [name for name in ("yt_dlp_plugins",) if importlib.util.find_spec(name) is None] print("POT plugin:", "MISSING" if missing else "present") raise SystemExit(1 if missing else 0) PY say "Installing the Deno JS runtime" # MANDATORY, not optional. Without a JS runtime yt-dlp cannot solve the `n` # challenge, and youtube-automate measured the consequence on this machine: 22 # formats instead of 29, and throttled downloads. yt-dlp finds it by PATH, and the # unit pins PATH to this venv's bin, so it has to live here rather than anywhere # more natural. if [[ -x $VENV/bin/deno ]]; then echo " already present: $("$VENV/bin/deno" --version | head -1)" elif [[ -x /var/lib/youtube-automate/venv/bin/deno ]]; then # Same machine, same architecture, already verified working. Prefer it over a # download while youtube-automate is still installed. install -m 0755 /var/lib/youtube-automate/venv/bin/deno "$VENV/bin/deno" echo " copied from the youtube-automate venv: $("$VENV/bin/deno" --version | head -1)" else tmp=$(mktemp -d) curl -fsSL -o "$tmp/deno.zip" \ https://github.com/denoland/deno/releases/latest/download/deno-x86_64-unknown-linux-gnu.zip unzip -q "$tmp/deno.zip" -d "$tmp" install -m 0755 "$tmp/deno" "$VENV/bin/deno" rm -rf "$tmp" echo " installed $("$VENV/bin/deno" --version | head -1)" fi say "Confirming yt-dlp can solve JS challenges" # All three lines must appear, per youtube-automate specs.md ยง3. if "$VENV/bin/yt-dlp" -v --simulate --no-warnings \ "https://www.youtube.com/watch?v=dQw4w9WgXcQ" 2>&1 \ | grep -q "JS runtimes: deno"; then echo " yt-dlp reports the deno runtime" else echo " WARNING: yt-dlp did not report a deno JS runtime โ€” playback may be" >&2 echo " throttled or missing formats. Check: ytstream doctor" >&2 fi say "Starting the POT provider container if it is not already up" if ! curl -sf --max-time 5 http://127.0.0.1:4416/ping >/dev/null 2>&1; then docker run -d --name bgutil-provider --restart unless-stopped \ -p 4416:4416 brainicism/bgutil-ytdlp-pot-provider || true else echo " already responding on 127.0.0.1:4416" fi say "Initialising the database" "$VENV/bin/ytstream" status || true say "Virtualenv ready at $VENV"