Workflow-App/Workflow/scripts/_clear_ufc_documents.py

102 lines
3.5 KiB
Python
Raw Normal View History

"""Clear all three UFC documents, after saving local copies.
The user asked to remove every document from the UFC resolution:
1. ysterbaard_resolutions.signed_letter
2. ysterbaard_director_resignations.letter
3. ysterbaard_director_resignations.signature
PocketBase file deletion is irreversible, so the bytes are copied into
scripts/_backup_ufc_docs/ first. This script never deletes the record itself —
only the file fields, which is what "remove the documents" means here.
"""
import io
import json
import urllib.error
import urllib.parse
import urllib.request
from pathlib import Path
from pypdf import PdfReader
JEI = Path(r"C:\Users\SJ\.minimax-agent\projects\JEI")
WORKFLOW = Path(r"C:\Users\SJ\.minimax-agent\projects\Workflow")
BACKUP = WORKFLOW / "scripts" / "_backup_ufc_docs"
env = {}
for line in (JEI / ".env.local").read_text(encoding="utf-8").splitlines():
line = line.strip()
if line and not line.startswith("#") and "=" in line:
k, v = line.split("=", 1)
env[k.strip()] = v.strip().strip('"').strip("'")
PB = env.get("NEXT_PUBLIC_PB_URL") or env["PB_URL"]
TOK = env["PB_TOKEN"]
TARGETS = [
("pbc_266170881", "e0dbxprazb70rqx", "signed_letter", "resolution_signed_letter"),
("ysterbaard_director_resignations", "8cfie18uhgy0n0o", "letter", "resignation_letter"),
("ysterbaard_director_resignations", "8cfie18uhgy0n0o", "signature", "resignation_signature"),
]
APPLY = "--apply" in __import__("sys").argv
def req(url, method="GET", body=None, ctype="application/json"):
r = urllib.request.Request(url, data=body, method=method,
headers={"Authorization": TOK, "Content-Type": ctype})
try:
with urllib.request.urlopen(r, timeout=120) as resp:
return resp.status, resp.read()
except urllib.error.HTTPError as e:
return e.code, e.read()
BACKUP.mkdir(parents=True, exist_ok=True)
for col, rid, field, label in TARGETS:
status, raw = req(f"{PB}/api/collections/{col}/records/{rid}")
rec = json.loads(raw)
fname = rec.get(field)
if not fname:
print(f"{label}: already empty")
continue
# 1) Back the bytes up locally.
furl = f"{PB}/api/files/{col}/{rid}/{urllib.parse.quote(fname)}"
status, blob = req(furl)
if status == 200:
out = BACKUP / f"{label}_{fname}"
out.write_bytes(blob)
try:
rd = PdfReader(io.BytesIO(blob))
imgs = sum(len(p.images) for p in rd.pages)
pages = len(rd.pages)
except Exception:
imgs, pages = "?", "?"
print(f"{label}: backed up {len(blob)} B -> {out.name} (pages={pages}, signature_images={imgs})")
else:
print(f"{label}: BACKUP FAILED HTTP {status} — aborting, nothing cleared")
raise SystemExit(1)
if not APPLY:
print(f" (dry run) would clear {field} on {col}/{rid}")
continue
# 2) Clear the file field.
status, raw = req(
f"{PB}/api/collections/{col}/records/{rid}",
method="PATCH",
body=json.dumps({field: ""}).encode(),
)
if status != 200:
print(f" FAILED to clear {field}: HTTP {status} {raw[:200]}")
continue
now = json.loads(raw).get(field)
print(f" cleared {field} -> {now!r}")
if not APPLY:
print("\nDRY RUN — re-run with --apply")
else:
print("\n=== final state ===")
for col, rid, field, label in TARGETS:
_, raw = req(f"{PB}/api/collections/{col}/records/{rid}")
print(f" {label:26s} {field:15s} = {json.loads(raw).get(field)!r}")
print(f"\nlocal backups in: {BACKUP}")