#!/usr/bin/env python3 """Deliver a completed edge task through the existing guarded WeChat sender.""" from __future__ import annotations import importlib.util import json import os import socket import sys import time from pathlib import Path HOME = Path.home() ADAPTIVE_RECORDER = HOME / ".local" / "lib" / "wechat-health-watch" / "wechat_adaptive_recorder.py" GUI_BRIDGE = HOME / ".local" / "lib" / "wechat-health-watch" / "wechat_adaptive_gui_bridge.py" XDG_RUNTIME_DIR = Path(os.environ.get("XDG_RUNTIME_DIR", f"/run/user/{os.getuid()}")) GUI_SENDER_SOCKET = Path( os.environ.get( "JWEBOT_GUI_SENDER_SOCKET", str(XDG_RUNTIME_DIR / "jwebot-gui-sender.sock"), ) ).expanduser() GUI_SENDER_TIMEOUT_SECONDS = float( os.environ.get("JWEBOT_GUI_SENDER_TIMEOUT_SECONDS", "55") ) GUI_SENDER_MAX_PAYLOAD_BYTES = 65536 def load_adaptive_recorder(): spec = importlib.util.spec_from_file_location( "jwebot_edge_adaptive_recorder", ADAPTIVE_RECORDER, ) if spec is None or spec.loader is None: raise RuntimeError("adaptive recorder is unavailable") module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module spec.loader.exec_module(module) return module def submit_gui_sender(payload: dict[str, str]) -> dict[str, object]: with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as connection: connection.settimeout(GUI_SENDER_TIMEOUT_SECONDS) connection.connect(str(GUI_SENDER_SOCKET)) connection.sendall((json.dumps(payload, ensure_ascii=False) + "\n").encode()) chunks: list[bytes] = [] size = 0 while True: chunk = connection.recv(4096) if not chunk: break chunks.append(chunk) size += len(chunk) if b"\n" in chunk: break if size > GUI_SENDER_MAX_PAYLOAD_BYTES: raise RuntimeError("GUI sender response is too large") try: response = json.loads(b"".join(chunks).split(b"\n", 1)[0]) except (IndexError, json.JSONDecodeError, UnicodeDecodeError) as error: raise RuntimeError("GUI sender response is invalid") from error if not isinstance(response, dict) or response.get("ok") is not True: raise RuntimeError("GUI sender returned an error") return response def main() -> int: payload = json.load(sys.stdin) if not isinstance(payload, dict): raise RuntimeError("delivery payload must be an object") expected_group = str(payload.get("group_fingerprint", "")) reply = str(payload.get("reply", "")) event_id = str(payload.get("event_id", "")) if not expected_group: raise RuntimeError("missing expected group fingerprint") if not reply or len(reply) > 900: raise RuntimeError("invalid delivery reply") socket_payload = { "op": "send", "event_id": event_id, "group_fingerprint": expected_group, "reply": reply, "source": "delivery-helper", } if GUI_SENDER_SOCKET.exists(): try: submit_gui_sender(socket_payload) return 0 except (FileNotFoundError, ConnectionRefusedError): pass adaptive = load_adaptive_recorder() started = time.monotonic() upstream = adaptive.load_upstream() adaptive.configure_state(upstream) original_capture = upstream.capture_image def capture_with_current_layout(): adaptive.configure_layout(upstream) return original_capture() upstream.capture_image = capture_with_current_layout upstream.GUI_BRIDGE = str(GUI_BRIDGE) adaptive.configure_layout(upstream) try: upstream.send_reply(reply, expected_group, event_id=event_id) except Exception as error: adaptive.TELEMETRY.elapsed( "delivery.gui.send", started, status="error", group_id=expected_group, chars=len(reply), process="delivery-helper", error_type=type(error).__name__, ) raise adaptive.TELEMETRY.elapsed( "delivery.gui.send", started, group_id=expected_group, chars=len(reply), process="delivery-helper", delivered=True, ) return 0 if __name__ == "__main__": raise SystemExit(main())