From 4d788c1acc7406baaaf7e1694358d4335ceea404 Mon Sep 17 00:00:00 2001 From: Ekaropolus Date: Sat, 3 Jan 2026 19:56:05 -0600 Subject: [PATCH] Better format for site agent response to telegram bots --- pxy_agents_coral/formatters.py | 37 ++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/pxy_agents_coral/formatters.py b/pxy_agents_coral/formatters.py index 6e2588e..3a3f7aa 100644 --- a/pxy_agents_coral/formatters.py +++ b/pxy_agents_coral/formatters.py @@ -3,10 +3,12 @@ import json import re import requests from typing import Any, Dict, Tuple, Optional, List +from urllib.parse import urlparse from django.conf import settings from django.http import JsonResponse, HttpRequest from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods +from core.urlbuild import public_base, public_url # ---------- helpers ---------- def _base(request: HttpRequest) -> str: @@ -125,6 +127,34 @@ def _parse_sites_shorthand(body: Dict[str, Any]) -> Tuple[Dict[str, Any], str]: return payload, "shorthand" +def _normalize_urls_to_public(data: Dict[str, Any], request: HttpRequest) -> None: + if not isinstance(data, dict): + return + base = public_base(request) + url_keys = { + "share_url", "map_url", "demand_map_url", "competition_map_url", + "main_download_url", "demand_download_url", "competition_download_url", + "main_preview_url", "demand_preview_url", "competition_preview_url", + "isochrones_geojson_url", "candidates_geojson_url", + "pois_competition_geojson_url", "popgrid_geojson_url", + "chart_url", + } + for k in url_keys: + v = data.get(k) + if not isinstance(v, str) or not v: + continue + if v.startswith("/"): + data[k] = public_url(v, request) + continue + try: + p = urlparse(v) + except Exception: + continue + if p.scheme in ("http", "https") and (p.hostname in {"127.0.0.1", "localhost"}): + q = f"?{p.query}" if p.query else "" + frag = f"#{p.fragment}" if p.fragment else "" + data[k] = f"{base}{p.path}{q}{frag}" + def _apply_sites_defaults(payload: Dict[str, Any], body: Dict[str, Any]) -> Dict[str, Any]: out = dict(payload or {}) loc = (body.get("input") or {}).get("location") or {} @@ -216,8 +246,9 @@ def _text_sites(data: Dict[str, Any]) -> str: for i, c in enumerate(data["candidates"][:3], 1): lat = c.get("lat", 0); lon = c.get("lon", 0); sc = c.get("score", 0) lines.append(f"{i}. score={sc:.2f} @ ({lat:.5f},{lon:.5f})") - for k in ("share_url", "isochrones_geojson_url", "candidates_geojson_url"): - if data.get(k): lines.append(data[k]) + if data.get("share_url"): + lines.append("") + lines.append(data["share_url"]) return "\n".join(lines) if data.get("code"): return f"⚠️ {data.get('code')}: {data.get('message','')}" @@ -232,6 +263,7 @@ def format_sami(request: HttpRequest): status, data = _post_execute(request, "sami", payload, timeout=30.0) # add echo + text data = data if isinstance(data, dict) else {"result": data} + _normalize_urls_to_public(data, request) data.setdefault("_echo", {"src": src, "payload_keys": list(payload.keys())}) try: data["text"] = _text_sami(data) @@ -249,6 +281,7 @@ def format_sites(request: HttpRequest): payload = _apply_sites_defaults(payload, body) status, data = _post_execute(request, "sites", payload, timeout=30.0) data = data if isinstance(data, dict) else {"result": data} + _normalize_urls_to_public(data, request) data.setdefault("_echo", {"src": src, "payload_keys": list(payload.keys())}) try: data["text"] = _text_sites(data)