from __future__ import annotations from collections.abc import Callable from datetime import datetime from flask import Flask, request from templates import load_templates, parse_color, save_templates def _fmt_dt(dt: datetime | None) -> str: if dt is None: return "—" try: return dt.isoformat(timespec="seconds") except Exception: return str(dt) def create_app( *, get_state: Callable[[], dict], get_next_event: Callable[[], dict], ) -> Flask: app = Flask(__name__) @app.get("/") def index() -> str: state = get_state() or {} next_event = get_next_event() or {} locations = state.get("last_locations") or [] locations_html = "".join(f"
  • {loc}
  • " for loc in locations) return ( "" "thc-webhook" "" "" "

    thc-webhook

    " "

    Status

    " "" "

    Next scheduled

    " "" "

    Locations (latest)

    " f"

    Total: {len(locations)}

    " f"" "" ) @app.get("/admin") def admin_get() -> str: templates_path = app.config.get("TEMPLATES_PATH", "templates.json") templates = load_templates(templates_path) blocks = [] for key, tpl in templates.items(): text = (tpl.get("text") or "").replace("'", "'") color = tpl.get("color") image_url = tpl.get("image_url") or "" blocks.append( "
    " f"{key}" f"
    " f"
    " f"" "
    " ) blocks_html = "".join(blocks) return ( "" "thc-webhook admin" "" "" "

    Admin: templates

    " "

    Edits are saved to the templates JSON file on disk.

    " "
    " f"{blocks_html}" "" "
    " "" ) @app.post("/admin") def admin_post() -> tuple[str, int]: templates_path = app.config.get("TEMPLATES_PATH", "templates.json") current = load_templates(templates_path) errors: list[str] = [] updated: dict[str, dict] = {} for key in current.keys(): text = request.form.get(f"{key}__text", "").strip() color_raw = request.form.get(f"{key}__color", "").strip() image_url = request.form.get(f"{key}__image_url", "").strip() if not text: errors.append(f"{key}: text is required") continue try: color = parse_color(color_raw) except Exception as e: errors.append(f"{key}: invalid color ({e})") continue tpl: dict = {"text": text, "color": color} if image_url: tpl["image_url"] = image_url updated[key] = tpl if errors: msg = "
    ".join(errors) return ( "" "

    Admin: templates

    " f"

    Errors:
    {msg}

    " "

    Back

    " "", 400, ) save_templates(templates_path, updated) return ( "" "

    Admin: templates

    " "

    Saved.

    " "

    Back

    " "", 200, ) return app