Files
felhom.eu/documentation/audits/fixes-2026-10-21/tools/load.py
T

66 lines
3.9 KiB
Python

#!/usr/bin/python3
"""load.py — the rehearsal's first-afternoon uploads, repeated (fixes 2026-10-21 Part 4): three streams at once, each
sequential — the PDFs to Paperless (as irisz), the photos to Immich (as odon), the Nextcloud tree (rclone, 4 transfers,
into a NEW folder so every file is new work). Passwords by env (handed in on stdin by the caller); never printed.
One log line per file or event, UTC; each stream ends with its counts."""
import glob, json, os, subprocess, sys, threading, time, datetime as dt
import requests, urllib3
urllib3.disable_warnings()
IP = "192.168.0.139"; D = "tester4.test"
env = dict(l.split("=", 1) for l in sys.stdin.read().splitlines() if "=" in l)
log_lock = threading.Lock()
def log(*a):
with log_lock:
print(time.strftime("%H:%M:%SZ", time.gmtime()), *a, flush=True)
def s(host):
x = requests.Session(); x.verify = False; x.headers["Host"] = f"{host}.{D}"
if env.get("COOKIE"): # the household's dashboard session: the setup gate lets only the household make the first admin
x.headers["Cookie"] = env["COOKIE"]
return x
def u(path): return f"https://{IP}{path}"
def paperless():
x = s("paperless"); x.auth = ("irisz", env["IRISZ"]); ok = bad = 0
for f in sorted(glob.glob("/root/data/paperless/*")):
try:
r = x.post(u("/api/documents/post_document/"), files={"document": open(f, "rb")}, timeout=300)
ok += r.status_code == 200; bad += r.status_code != 200
log("paperless", os.path.basename(f), r.status_code)
except Exception as e:
bad += 1; log("paperless", os.path.basename(f), "ERR", str(e)[:120])
log("paperless DONE ok", ok, "bad", bad)
def immich():
x = s("photos")
r = x.post(u("/api/auth/admin-sign-up"), json={"email": "tester4+odon@felhom.eu", "password": env["ODON"], "name": "Ödön"}, timeout=60)
log("immich admin-sign-up", r.status_code)
r = x.post(u("/api/auth/login"), json={"email": "tester4+odon@felhom.eu", "password": env["ODON"]}, timeout=60)
if r.status_code not in (200, 201):
log("immich login", r.status_code); return
x.headers["Authorization"] = "Bearer " + r.json()["accessToken"]; ok = bad = 0
for f in sorted(glob.glob("/root/data/immich/**/*", recursive=True)):
if not os.path.isfile(f):
continue
st = os.stat(f); ts = dt.datetime.utcfromtimestamp(st.st_mtime).isoformat() + "Z"
try:
r = x.post(u("/api/assets"), files={"assetData": open(f, "rb")}, data={"deviceAssetId": f, "deviceId": "rh1021", "fileCreatedAt": ts, "fileModifiedAt": ts}, timeout=600)
ok += r.status_code in (200, 201); bad += r.status_code not in (200, 201)
log("immich", os.path.basename(f), r.status_code)
except Exception as e:
bad += 1; log("immich", os.path.basename(f), "ERR", str(e)[:120])
log("immich DONE ok", ok, "bad", bad)
def nextcloud():
obs = subprocess.run(["rclone", "obscure", "-"], input=env["ODON"], capture_output=True, text=True).stdout.strip()
e = dict(os.environ, RCLONE_CONFIG_NC_TYPE="webdav", RCLONE_CONFIG_NC_URL=f"https://cloud.{D}/remote.php/dav/files/odon",
RCLONE_CONFIG_NC_VENDOR="nextcloud", RCLONE_CONFIG_NC_USER="odon", RCLONE_CONFIG_NC_PASS=obs)
log("nextcloud rclone START")
p = subprocess.run(["rclone", "copy", "--no-check-certificate", "--transfers", "4", "--stats", "60s", "--stats-one-line", "-v",
"--max-size", "1G", "/root/data/nextcloud/Csalad", "nc:/Csalad_feltoltes"], env=e, capture_output=True, text=True)
for l in (p.stderr or "").splitlines():
if "Transferred:" in l or "ERROR" in l:
log("nextcloud", l.strip()[:200])
log("nextcloud DONE rc", p.returncode)
want = sys.argv[1:] or ["paperless", "immich", "nextcloud"]
ts = [threading.Thread(target=f) for f in (paperless, immich, nextcloud) if f.__name__ in want]
log("LOAD START")
[t.start() for t in ts]; [t.join() for t in ts]
log("LOAD END")