"""Loopback-only, empty-data UI preview. Never used by the production runtime.""" from __future__ import annotations import argparse from dataclasses import replace from typing import Mapping from urllib.parse import urlsplit from arr_web.app import PortalApplication, SessionLedger from arr_web.contracts import PortalError, Response, failure from arr_web.repository import UnavailablePortalRepository from arr_web.server import serve class EmptyPreviewRepository(UnavailablePortalRepository): def list_jobs(self, month_key, limit=50, offset=0): return [], 0 def list_monthly_runs(self, month_key, limit=50, offset=0): return [], 0 def list_history_month_counts(self): return [] def list_months(self): return [] class ReadOnlyPreview: """Render the actual portal with unavailable services and no external state.""" def __init__(self) -> None: self._sessions = SessionLedger() self._app = PortalApplication( repository=EmptyPreviewRepository(), sessions=self._sessions ) def handle( self, method: str, target: str, headers: Mapping[str, str], body: bytes = b"", client_id: str = "direct", ) -> Response: if method != "GET": return Response.json(405, failure(PortalError( "PREVIEW_READ_ONLY", "本地预览仅供查看,不能提交业务操作。", 405 )), headers={"Allow": "GET"}) path = urlsplit(target).path if path == "/assets/preview.css": return Response(200, ( ".local-preview-banner{margin:0 0 20px;padding:12px 16px;" "border:1px solid var(--line);border-radius:12px;" "background:var(--blue-soft);color:var(--ink);font-size:13px}" ).encode(), "text/css; charset=utf-8", {"Cache-Control": "no-store"}) # Internal, transient identity belongs only to this empty preview instance. # No browser cookie, credentials, runtime configuration or real service is used. session_id, _ = self._sessions.issue("") request_headers = {k: v for k, v in headers.items() if k.lower() != "cookie"} request_headers["Cookie"] = f"arr_session={session_id}" try: response = self._app.handle(method, target, request_headers, body, client_id) finally: self._sessions.revoke(session_id) if path in {"/", "/index.html"} and response.status == 200: html = response.body.decode("utf-8").replace( "ARR Report", "ARR Report · 本地只读预览" ).replace( "", '' ).replace( '
', '
' '', ) response = replace(response, body=html.encode("utf-8")) return response def main() -> None: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--port", type=int, default=8872) args = parser.parse_args() print(f"Read-only preview: http://127.0.0.1:{args.port}/", flush=True) serve(ReadOnlyPreview(), "127.0.0.1", args.port) if __name__ == "__main__": main()