From 11e026448a2957b3105b5644b988fb9d185a835f Mon Sep 17 00:00:00 2001 From: m3taversal Date: Tue, 21 Apr 2026 11:01:15 +0100 Subject: [PATCH] =?UTF-8?q?sync:=20dashboard=5Froutes.py=20from=20VPS=20?= =?UTF-8?q?=E2=80=94=20digest=20+=20contributor-graph=20endpoints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- diagnostics/dashboard_routes.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/diagnostics/dashboard_routes.py b/diagnostics/dashboard_routes.py index f81c020..e66db4f 100644 --- a/diagnostics/dashboard_routes.py +++ b/diagnostics/dashboard_routes.py @@ -1310,6 +1310,7 @@ def register_dashboard_routes(app: web.Application, get_conn): app.router.add_get("/api/telegram-extractions", handle_telegram_extractions) app.router.add_get("/api/contributor-growth", handle_contributor_growth) app.router.add_get("/api/digest/latest", handle_digest_latest) + app.router.add_get("/api/contributor-graph", handle_contributor_graph) async def handle_digest_latest(request): @@ -1324,3 +1325,25 @@ async def handle_digest_latest(request): return web.json_response({"error": "No digest available yet"}, status=404) except Exception as e: return web.json_response({"error": str(e)}, status=500) + + +async def handle_contributor_graph(request): + """GET /api/contributor-graph — serve the PNG chart.""" + import subprocess, os + png_path = "/opt/teleo-eval/static/contributor-graph.png" + # Regenerate if older than 1 hour or missing + regen = not os.path.exists(png_path) + if not regen: + age = __import__('time').time() - os.path.getmtime(png_path) + regen = age > 3600 + if regen: + try: + subprocess.run( + ['python3', '/opt/teleo-eval/scripts/contributor-graph.py'], + timeout=30, capture_output=True + ) + except Exception: + pass + if not os.path.exists(png_path): + return web.Response(text='Chart not available', status=503) + return web.FileResponse(png_path, headers={'Content-Type': 'image/png'})