66 lines
3.9 KiB
Python
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")
|