fix: use build_catalog.sh as single source of truth for catalog
This commit is contained in:
1 parent
7a078319a6
commit
e0bfb2e8ed
2 files changed
+33
-71
No files matched your search
Binary file not shown.
@@ -25,7 +25,7 @@ from pydantic import BaseModel
|
||||
|
||||
APP_DIR = Path(os.environ.get("APP_DIR", "/data/app"))
|
||||
MOVIES_DIR = APP_DIR / "movies"
|
||||
CATALOG = APP_DIR / "catalog.json"
|
||||
CATALOG = MOVIES_DIR / "catalog.json"
|
||||
WEBHOOK = os.environ.get("DEPLOY_WEBHOOK", "")
|
||||
WEBHOOK_TOKEN = os.environ.get("COOLIFY_TOKEN", "")
|
||||
|
||||
@@ -48,10 +48,6 @@ def load_catalog():
|
||||
return {"movies": []}
|
||||
return json.loads(CATALOG.read_text(encoding="utf-8"))
|
||||
|
||||
def save_catalog(cat):
|
||||
cat["updated"] = datetime.date.today().isoformat()
|
||||
CATALOG.write_text(json.dumps(cat, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
def deploy():
|
||||
if not WEBHOOK:
|
||||
return {"deployed": False, "reason": "no webhook configured"}
|
||||
@@ -100,50 +96,18 @@ def torrent_hash(path: Path):
|
||||
return hashlib.sha1(enc(info)).hexdigest()
|
||||
|
||||
def rebuild_catalog():
|
||||
"""Rebuild catalog.json from /movies folders (port of build_catalog.sh)."""
|
||||
movies = []
|
||||
if MOVIES_DIR.exists():
|
||||
for entry in sorted(os.listdir(MOVIES_DIR)):
|
||||
d = MOVIES_DIR / entry
|
||||
if not d.is_dir() or entry.startswith("."):
|
||||
continue
|
||||
meta = {"id": entry}
|
||||
mf = d / "meta.txt"
|
||||
if mf.exists():
|
||||
for line in mf.read_text(encoding="utf-8", errors="replace").splitlines():
|
||||
line = line.strip()
|
||||
if not line or ":" not in line:
|
||||
continue
|
||||
k, v = line.split(":", 1)
|
||||
k, v = k.strip(), v.strip()
|
||||
if k in ("title", "original_title", "description"):
|
||||
meta[k] = v
|
||||
elif k == "year":
|
||||
meta["year"] = int(v) if v.isdigit() else v
|
||||
elif k == "genre":
|
||||
meta["genre"] = [g.strip() for g in v.split(",") if g.strip()]
|
||||
elif k == "rating":
|
||||
try: meta["rating"] = float(v)
|
||||
except: pass
|
||||
# poster
|
||||
for ext in ("jpg", "png", "jpeg", "webp"):
|
||||
p = d / ("poster." + ext)
|
||||
if p.exists():
|
||||
meta["poster"] = "movies/%s/poster.%s" % (entry, ext)
|
||||
break
|
||||
# torrent
|
||||
tors = list(d.glob("*.torrent"))
|
||||
if tors:
|
||||
try:
|
||||
meta["hash"] = torrent_hash(tors[0])
|
||||
meta["torrent"] = "movies/%s/%s" % (entry, tors[0].name)
|
||||
except Exception as e:
|
||||
meta["torrent_error"] = str(e)
|
||||
movies.append(meta)
|
||||
"""Rebuild catalog.json by running the project's build_catalog.sh
|
||||
(keeps a single source of truth for catalog generation)."""
|
||||
script = MOVIES_DIR.parent / "build_catalog.sh"
|
||||
if not script.exists():
|
||||
raise HTTPException(500, "build_catalog.sh not found at %s" % script)
|
||||
try:
|
||||
subprocess.run(["bash", str(script)], check=True,
|
||||
capture_output=True, text=True, timeout=120)
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise HTTPException(500, "build failed: " + (e.stderr or e.stdout or str(e)))
|
||||
cat = load_catalog()
|
||||
cat["movies"] = movies
|
||||
save_catalog(cat)
|
||||
return len(movies)
|
||||
return len(cat.get("movies", []))
|
||||
|
||||
# ---------- endpoints ----------
|
||||
|
||||
@@ -247,16 +211,27 @@ class PatchBody(BaseModel):
|
||||
@app.patch("/movie/{fid}")
|
||||
def patch_movie(fid: str, body: PatchBody):
|
||||
fid = valid_id(fid)
|
||||
cat = load_catalog()
|
||||
m = next((x for x in cat.get("movies", []) if x.get("id") == fid), None)
|
||||
if not m:
|
||||
d = MOVIES_DIR / fid
|
||||
if not d.exists():
|
||||
raise HTTPException(404, "no such film")
|
||||
mf = d / "meta.txt"
|
||||
# update meta.txt fields (source of truth for build_catalog.sh)
|
||||
fields = {}
|
||||
if mf.exists():
|
||||
for line in mf.read_text(encoding="utf-8", errors="replace").splitlines():
|
||||
line = line.strip()
|
||||
if not line or ":" not in line:
|
||||
continue
|
||||
k, v = line.split(":", 1)
|
||||
fields[k.strip()] = v.strip()
|
||||
for k in ("title", "year", "description", "poster", "original_title"):
|
||||
v = getattr(body, k)
|
||||
if v is not None:
|
||||
m[k] = v
|
||||
save_catalog(cat)
|
||||
return {"updated": fid, "deploy": deploy()}
|
||||
fields[k] = str(v)
|
||||
mf.write_text("\n".join("%s: %s" % (k, v) for k, v in fields.items()) + "\n",
|
||||
encoding="utf-8")
|
||||
n = rebuild_catalog()
|
||||
return {"updated": fid, "catalog_movies": n, "deploy": deploy()}
|
||||
|
||||
@app.post("/movie/{fid}/meta")
|
||||
def post_meta(fid: str, meta: UploadFile = File(None)):
|
||||
@@ -283,13 +258,8 @@ def post_poster(fid: str, poster: UploadFile = File(...)):
|
||||
if ext not in ("jpg", "jpeg", "png", "webp"):
|
||||
raise HTTPException(400, "bad poster ext")
|
||||
(d / ("poster." + ext)).write_bytes(poster.file.read())
|
||||
# update catalog poster ref
|
||||
cat = load_catalog()
|
||||
m = next((x for x in cat.get("movies", []) if x.get("id") == fid), None)
|
||||
if m:
|
||||
m["poster"] = "movies/%s/poster.%s" % (fid, ext)
|
||||
save_catalog(cat)
|
||||
return {"poster_updated": fid, "deploy": deploy()}
|
||||
n = rebuild_catalog()
|
||||
return {"poster_updated": fid, "catalog_movies": n, "deploy": deploy()}
|
||||
|
||||
@app.post("/movie/{fid}/torrent")
|
||||
def post_torrent(fid: str, torrent: UploadFile = File(...)):
|
||||
@@ -317,16 +287,8 @@ def rename_movie(fid: str, body: RenameBody):
|
||||
if (MOVIES_DIR / new).exists():
|
||||
raise HTTPException(409, "target %s exists" % new)
|
||||
d.rename(MOVIES_DIR / new)
|
||||
cat = load_catalog()
|
||||
for m in cat.get("movies", []):
|
||||
if m.get("id") == fid:
|
||||
m["id"] = new
|
||||
if "poster" in m:
|
||||
m["poster"] = m["poster"].replace("movies/%s/" % fid, "movies/%s/" % new)
|
||||
if "torrent" in m:
|
||||
m["torrent"] = m["torrent"].replace("movies/%s/" % fid, "movies/%s/" % new)
|
||||
save_catalog(cat)
|
||||
return {"renamed": fid, "to": new, "deploy": deploy()}
|
||||
n = rebuild_catalog()
|
||||
return {"renamed": fid, "to": new, "catalog_movies": n, "deploy": deploy()}
|
||||
|
||||
@app.get("/check")
|
||||
def check():
|
||||
|
||||
Reference in new issue
Block a user