""" NOC Dashboard โ€” clean, modern fleet monitor for all 8 publisher sites. """ import json, time, threading, requests from datetime import datetime from flask import Flask, jsonify app = Flask(__name__) SITES = { "ai": {"name": "AI Insights", "ip": "10.30.20.240", "ct": 135, "color": "#7c3aed"}, "tech": {"name": "Tech Frontier", "ip": "10.30.20.241", "ct": 136, "color": "#2563eb"}, "science": {"name": "Science Decoded", "ip": "10.30.20.242", "ct": 137, "color": "#059669"}, "crypto": {"name": "Crypto Compass", "ip": "10.30.20.243", "ct": 138, "color": "#f59e0b"}, "linux": {"name": "Linux Lab", "ip": "10.30.20.244", "ct": 139, "color": "#f97316"}, "gaming": {"name": "Game Layer", "ip": "10.30.20.246", "ct": 140, "color": "#ec4899"}, "diy": {"name": "Maker Forge", "ip": "10.30.20.247", "ct": 141, "color": "#ef4444"}, "guides": {"name": "Practical Guides", "ip": "10.30.20.248", "ct": 142, "color": "#0891b2"}, } cache = {"data": {}, "ts": None} def probe(vertical, info): s = dict(vertical=vertical, name=info["name"], ip=info["ip"], ct=info["ct"], color=info["color"], alive=False, articles=0, views=0, today=0, subs=0, latency=0, arts=[], error=None) try: t0 = time.time() r = requests.get(f"http://{info['ip']}:80/health", timeout=5) s["latency"] = round((time.time() - t0) * 1000) if r.status_code == 200: s["alive"] = True s["articles"] = r.json().get("articles", 0) r2 = requests.get(f"http://{info['ip']}:80/api/stats", timeout=5) if r2.status_code == 200: d = r2.json() s["views"] = d.get("total_views", 0) s["today"] = d.get("today_views", 0) r3 = requests.get(f"http://{info['ip']}:80/api/articles?limit=3", timeout=5) if r3.status_code == 200: s["arts"] = [{"t": a.get("title", "")[:65], "s": a.get("slug", ""), "d": (a.get("published_at") or "")[:10], "w": a.get("word_count", 0)} for a in r3.json()[:3]] except Exception as e: s["error"] = str(e)[:50] return vertical, s def refresh(): import concurrent.futures with concurrent.futures.ThreadPoolExecutor(max_workers=8) as ex: results = dict(ex.map(lambda x: probe(*x), [(v, i) for v, i in SITES.items()])) cache["data"] = results cache["ts"] = datetime.now().isoformat() @app.route("/") def home(): if not cache["ts"] or (datetime.now() - datetime.fromisoformat(cache["ts"])).seconds > 30: threading.Thread(target=refresh, daemon=True).start() data = cache["data"] or {} return HTML.format( alive=sum(1 for s in data.values() if s.get("alive")), total=len(data), articles=sum(s.get("articles", 0) for s in data.values()), views=sum(s.get("views", 0) for s in data.values()), today=sum(s.get("today", 0) for s in data.values()), subs=sum(s.get("subs", 0) for s in data.values()), updated=(cache["ts"] or "")[:19], cards=build_cards(data), ) def build_cards(data): out = [] for v, s in data.items(): dot = "up" if s["alive"] else "down" lat = s["latency"] lc = "lat-ok" if lat < 80 else ("lat-warn" if lat < 250 else "lat-bad") err = (s.get("error") or "OK")[:25] arts = "" for a in s.get("arts", []): arts += f'
{a["d"]}{a["t"]}{a["w"]}w
' if not arts: arts = '
No articles yet
' out.append(f'''
{s['name']}
{v}.thetempleofdoom.com
๐Ÿ–ฅ {s['ip']}:80
{s['articles']}
Articles
{s['views']}
Views
{s['today']}
Today
{s['subs']}
Subs
{lat}ms
Latency
{err}
Status
Latest Articles
{arts}
''') return "\n".join(out) @app.route("/api/fleet") def api_fleet(): refresh() return jsonify({"updated": cache["ts"], "sites": cache["data"]}) @app.route("/api/refresh", methods=["POST"]) def api_refresh(): refresh() return jsonify({"status": "ok"}) @app.route("/health") def health(): return jsonify({"status": "ok", "ts": cache["ts"]}) # โ”€โ”€ Template โ”€โ”€ HTML = """ Publisher Fleet
Publisher FleetNOC
{alive} / {total} online {updated}
{articles}
Articles
{views}
Total Views
{today}
Today
{subs}
Subscribers
6 AM
Next Publish
{articles}
Network Total
{cards}
Publisher Fleet NOC ยท Auto-refresh 60s ยท Pipeline ยท Kalshi
""" if __name__ == "__main__": import argparse ap = argparse.ArgumentParser() ap.add_argument("--port", type=int, default=5090) ap.add_argument("--host", default="127.0.0.1") a = ap.parse_args() print(f"NOC โ†’ http://{a.host}:{a.port}") refresh() app.run(host=a.host, port=a.port, debug=False)