52 lines
2.4 KiB
Python
52 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""landed.py — Part E1: per imported episode/film, where the download was, where the library file is, hardlink or copy,
|
|
and which download app. Source: Sonarr's and Radarr's own `downloadFolderImported` history (droppedPath, importedPath,
|
|
downloadClientName) + a stat of both files NOW. Run INSIDE the guest (run_in_guest.py landed.py). Keys read at runtime,
|
|
never printed."""
|
|
import json, os, re, subprocess, urllib.request
|
|
|
|
|
|
def sh(c):
|
|
return subprocess.run(c, shell=True, capture_output=True, text=True).stdout.strip()
|
|
|
|
|
|
def get(app, port, path):
|
|
key = re.search(r"<ApiKey>([^<]+)</ApiKey>", open(f"/var/lib/docker/volumes/{app}_{app}_config/_data/config.xml").read()).group(1)
|
|
ip = sh(f"docker inspect {app} -f '{{{{range .NetworkSettings.Networks}}}}{{{{.IPAddress}}}}{{{{end}}}}'")
|
|
req = urllib.request.Request(f"http://{ip}:{port}/api/v3/{path}", headers={"X-Api-Key": key, "Host": app})
|
|
return json.load(urllib.request.urlopen(req, timeout=60))
|
|
|
|
|
|
def drive(p):
|
|
return p.split("/")[3] if p and p.startswith("/mnt/felhom-drives/") else "?"
|
|
|
|
|
|
def st(p):
|
|
try:
|
|
s = os.stat(p)
|
|
return (s.st_dev, s.st_ino, s.st_nlink)
|
|
except OSError:
|
|
return None
|
|
|
|
|
|
for app, port, kind in (("sonarr", 8989, "series"), ("radarr", 7878, "movie")):
|
|
tags = {t["id"]: t["label"] for t in get(app, port, "tag")}
|
|
items = {x["id"]: x for x in get(app, port, kind)}
|
|
hist = get(app, port, "history?pageSize=500&eventType=3")["records"] # 3 = downloadFolderImported
|
|
print(f"== {app}: {len(hist)} import(s)")
|
|
for x in items.values():
|
|
print(f" {kind} {x['title']}: root={drive(x.get('rootFolderPath') or x.get('path'))} tags={[tags.get(i, i) for i in x['tags']]}")
|
|
for h in sorted(hist, key=lambda h: h["date"]):
|
|
d = h["data"]
|
|
src, dst = d.get("droppedPath"), d.get("importedPath")
|
|
a, b = st(src), st(dst)
|
|
if a and b and a[:2] == b[:2]:
|
|
how = "HARDLINK"
|
|
elif b and b[2] == 1:
|
|
how = "COPY" if not a or a[:2] != b[:2] else "?"
|
|
else:
|
|
how = "library file gone" if not b else "?"
|
|
title = items.get(h.get("seriesId") or h.get("movieId"), {}).get("title", "?")
|
|
print(f" {title[:24]:24} {os.path.basename(dst or '')[:46]:46} client={d.get('downloadClientName'):22} "
|
|
f"download={drive(src)} library={drive(dst)} {how}")
|