refactor(scripts): extract shared sae_* helpers and dedupe gallery builders

Consolidate copy-pasted logic across the gallery/run scripts into shared
modules:
  - sae_env.py     — zero-dependency .env loader (populates os.environ)
  - sae_tmdb.py    — TMDB API helpers (tmdb_get, person images, id lookups)
  - sae_jellyfin.py— Jellyfin API helpers (jf_get, id/URL normalisation)
  - sae_gallery.py — image download + gallery.json writing

make_gallery, make_jellyfin_gallery and filter_gallery now import these
instead of carrying their own near-identical copies.
This commit is contained in:
2026-07-04 18:55:37 +02:00
parent aacaefb3dc
commit 152c34b1f4
7 changed files with 431 additions and 258 deletions
+49
View File
@@ -0,0 +1,49 @@
"""Zero-dependency .env loader.
The gallery/run scripts read credentials (JELLYFIN_URL, JELLYFIN_API_KEY,
TMDB_API_KEY) from os.environ, but nothing populated os.environ from the
project's .env file — so the keys only worked if you'd manually
`set -a; source .env`. This loads .env into os.environ on import, without
pulling in python-dotenv.
Import this module early (before argparse reads os.environ defaults) so the
.env values are available as defaults.
"""
import os
from pathlib import Path
# Walk up from this file to find the project root's .env (scripts/ is one
# level down from the repo root).
_DEFAULT_ENV = Path(__file__).resolve().parent.parent / ".env"
def load_env(path: Path | str = _DEFAULT_ENV, *, override: bool = False) -> None:
"""Parse a .env file into os.environ.
Lines are KEY=VALUE; blank lines and #-comments are ignored, surrounding
whitespace is stripped, and a single layer of matching quotes around the
value is removed. Existing os.environ entries win unless override=True, so
an explicitly exported var (or one set on the command line) takes
precedence over the file.
"""
path = Path(path)
if not path.is_file():
return
for raw in path.read_text().splitlines():
line = raw.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, _, value = line.partition("=")
key = key.strip()
value = value.strip()
if len(value) >= 2 and value[0] == value[-1] and value[0] in ("'", '"'):
value = value[1:-1]
if not key:
continue
if override or key not in os.environ:
os.environ[key] = value
# Load on import so `os.environ.get(...)` argparse defaults see .env values.
load_env()