ATEM: read the saved-file folder through this Mac's own Remote Login when macOS keeps the page out of Google Drive

A launchd-run python3 gets 'Operation not permitted' on ~/Library/CloudStorage; sshd does not. The
page now lists and reads the folder over ssh to localhost with the panel's own key when the local
read is blocked (the Ingest Mac's Setup card gains that authorise step). Pick the newest verified
on NA Ingest.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 15:18:39 -04:00
co-authored by Claude Fable 5.1
parent 3b3a1c7245
commit 10e545d4e0
4 changed files with 62 additions and 15 deletions
+58 -13
View File
@@ -19,6 +19,7 @@ import logging
import logging.handlers
import os
import re
import shlex
import socket
import subprocess
import sys
@@ -645,15 +646,9 @@ class Handler(http.server.BaseHTTPRequestHandler):
if path == "/api/atem-reference/folder":
folder = os.path.expanduser((site.cfg.get("atem") or {}).get("source_folder") or "")
mounted = bool(folder and os.path.isdir(folder))
files = sorted(glob.glob(os.path.join(folder, "*.xml")), key=os.path.getmtime, reverse=True) if mounted else []
blocked = False
if mounted and not files:
try:
blocked = not os.listdir(folder) and "/Library/CloudStorage/" in folder # a cloud folder that looks empty to a background process
except OSError:
blocked = True
return self.send(200, {"folder": folder, "mounted": mounted, "blocked": blocked,
"files": [{"name": os.path.basename(f), "when": os.path.getmtime(f)} for f in files[:10]]})
files, via, blocked = cloud_files(site.cfg, folder) if mounted else ([], "", False)
return self.send(200, {"folder": folder, "mounted": mounted, "blocked": blocked, "via": via,
"files": [{"name": n, "when": t} for n, t in files[:10]]})
if path == "/api/live/midi":
snap = site.read_json("snapshot.json", {}) or {}
return self.send(200, {"local": snap.get("midi"), "remote": snap.get("remote_midi")})
@@ -865,11 +860,15 @@ class Handler(http.server.BaseHTTPRequestHandler):
return self.send(200, {"draft": self.masked_draft(draft), "from": src, "errors": errors, "warnings": warnings})
if path == "/api/atem-reference/pick-newest":
folder = os.path.expanduser((site.cfg.get("atem") or {}).get("source_folder") or "")
files = sorted(glob.glob(os.path.join(folder, "*.xml")), key=os.path.getmtime) if folder and os.path.isdir(folder) else []
files, via, blocked = cloud_files(site.cfg, folder) if folder and os.path.isdir(folder) else ([], "", False)
if not files:
return self.send(404, {"error": "no .xml files in the folder (is Google Drive signed in?)"})
with open(files[-1], "rb") as f:
return self.send(200, dict(self.take_atem(f.read()), file=os.path.basename(files[-1])))
return self.send(404, {"error": "no .xml files in the folder (is Google Drive signed in?)" if not blocked else
"this page is not allowed to read the cloud folder; use Upload a saved file"})
newest = os.path.join(folder, files[0][0])
raw = cloud_read(site.cfg, newest, via)
if raw is None:
return self.send(502, {"error": "could not read %s" % files[0][0]})
return self.send(200, dict(self.take_atem(raw), file=files[0][0]))
if path == "/api/atem-reference/discard":
self.discard_atem()
return self.send(200, {"ok": True})
@@ -1109,6 +1108,52 @@ class Handler(http.server.BaseHTTPRequestHandler):
return "http://%s:%d/" % (host, self.server.server_address[1])
def self_ssh(cfg):
"""ssh to this very Mac with the panel's own key: sshd may read the cloud folders a background
program is kept out of (macOS privacy), and the key is already on this Mac."""
key = os.path.expanduser(cfg.get("ssh_key", "~/.ssh/id_status_panel"))
return ["/usr/bin/ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=4", "-o", "StrictHostKeyChecking=accept-new", "-i", key, "localhost"]
def cloud_files(cfg, folder):
"""(files [(name, mtime)] newest first, how, blocked). Reads the folder here; when macOS keeps this process
out of a cloud folder, asks this Mac over ssh instead."""
try:
names = [n for n in os.listdir(folder) if n.lower().endswith(".xml")]
files = sorted(((n, os.path.getmtime(os.path.join(folder, n))) for n in names), key=lambda x: x[1], reverse=True)
if files or "/Library/CloudStorage/" not in folder:
return files, "local", False
except OSError:
pass
try:
r = subprocess.run(self_ssh(cfg) + ["cd %s && stat -f '%%m %%N' *.xml" % shlex.quote(folder)], capture_output=True, text=True, timeout=15)
if r.returncode == 0:
files = []
for line in r.stdout.splitlines():
m, _, n = line.partition(" ")
if n.lower().endswith(".xml"):
files.append((n, float(m)))
return sorted(files, key=lambda x: x[1], reverse=True), "ssh", False
log.warning("cloud folder over ssh: %s", (r.stderr or r.stdout).strip()[-200:])
except (OSError, subprocess.TimeoutExpired, ValueError) as e:
log.warning("cloud folder over ssh: %s", e)
return [], "", True
def cloud_read(cfg, path, via):
if via != "ssh":
try:
with open(path, "rb") as f:
return f.read()
except OSError:
pass
try:
r = subprocess.run(self_ssh(cfg) + ["cat %s" % shlex.quote(path)], capture_output=True, timeout=30)
return r.stdout if r.returncode == 0 else None
except (OSError, subprocess.TimeoutExpired):
return None
class Server(http.server.ThreadingHTTPServer):
daemon_threads = True
allow_reuse_address = True