From 733e3149c45ab28b59f1ab18b28484db7cd7f0a5 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 13 Jun 2026 20:55:19 -0400 Subject: [PATCH 1/9] Add Prometheus-backed home server status --- backend/app.py | 113 ++++++++++++++++++++++++++++++++++++++++++ site/index.html | 25 +++++++++- site/server-status.js | 43 ++++++++++++++++ 3 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 site/server-status.js diff --git a/backend/app.py b/backend/app.py index b857724..44d790c 100644 --- a/backend/app.py +++ b/backend/app.py @@ -1939,3 +1939,116 @@ def hardcore_leaderboard_points_combined(): return jsonify(rows[:100]) # --- end Hardcore stats aggregator ------------------------------------------- + + +@app.get("/api/server-status") +def public_server_status(): + import json + import os + import urllib.parse + import urllib.request + + prometheus_url = os.environ.get("PROMETHEUS_URL", "http://5.0.0.20:9090").rstrip("/") + + def prom_value(query): + url = prometheus_url + "/api/v1/query?" + urllib.parse.urlencode({"query": query}) + try: + with urllib.request.urlopen(url, timeout=2.5) as resp: + data = json.loads(resp.read().decode("utf-8")) + except Exception: + return 0 + + if data.get("status") != "success": + return 0 + + total = 0.0 + for result in data.get("data", {}).get("result", []): + value = result.get("value", [None, "0"])[1] + try: + total += float(value) + except (TypeError, ValueError): + pass + + return int(total) + + def q(metric, labels): + label_text = ",".join(f'{k}="{v}"' for k, v in labels.items()) + return f'sum({metric}{{{label_text}}}) or vector(0)' + + def newserv(region, service, ship, version): + return prom_value(q("pso_newserv_clients_connected", { + "region": region, + "service": service, + "ship": ship, + "version": version, + })) + + def adhoc(region, game): + return prom_value(q("psppeeps_adhoc_connected_clients_by_product", { + "region": region, + "service": f"{region}-psppeeps-adhoc", + "ship": "psp", + "game": game, + })) + + us = { + "alis_v2": newserv("us", "us-newserv-live", "live", "v2"), + "alis_v3": newserv("us", "us-newserv-live", "live", "v3"), + "alis_bb": newserv("us", "us-newserv-live", "live", "v4"), + "abion_hcbb": newserv("us", "us-newserv-hardcore", "hardcore", "v4"), + "adhoc_psp1": adhoc("us", "psp1"), + "adhoc_psp2i": adhoc("us", "psp2i"), + } + + eu = { + "palma_v2": newserv("eu", "eu-newserv-live", "live", "v2"), + "palma_v3": newserv("eu", "eu-newserv-live", "live", "v3"), + "palma_bb": newserv("eu", "eu-newserv-live", "live", "v4"), + "aiedo_hcbb": newserv("eu", "eu-newserv-hardcore", "hardcore", "v4"), + "adhoc_psp1": adhoc("eu", "psp1"), + "adhoc_psp2i": adhoc("eu", "psp2i"), + } + + us_total = sum(us.values()) + eu_total = sum(eu.values()) + + return jsonify({ + "servers": [ + { + "label": "US Server", + "players": us_total, + "ships": [ + {"label": "Alis", "rows": [ + {"label": "V2", "players": us["alis_v2"]}, + {"label": "V3", "players": us["alis_v3"]}, + {"label": "BB", "players": us["alis_bb"]}, + ]}, + {"label": "Abion", "rows": [ + {"label": "HC/BB", "players": us["abion_hcbb"]}, + ]}, + {"label": "AdHoc-US", "rows": [ + {"label": "PSP1", "players": us["adhoc_psp1"]}, + {"label": "PSP2i", "players": us["adhoc_psp2i"]}, + ]}, + ], + }, + { + "label": "EU Server", + "players": eu_total, + "ships": [ + {"label": "Palma", "rows": [ + {"label": "V2", "players": eu["palma_v2"]}, + {"label": "V3", "players": eu["palma_v3"]}, + {"label": "BB", "players": eu["palma_bb"]}, + ]}, + {"label": "Aiedo", "rows": [ + {"label": "HC/BB", "players": eu["aiedo_hcbb"]}, + ]}, + {"label": "AdHoc-EU", "rows": [ + {"label": "PSP1", "players": eu["adhoc_psp1"]}, + {"label": "PSP2i", "players": eu["adhoc_psp2i"]}, + ]}, + ], + }, + ], + }) diff --git a/site/index.html b/site/index.html index 935531d..28d0285 100644 --- a/site/index.html +++ b/site/index.html @@ -10,6 +10,7 @@ +
@@ -53,9 +54,29 @@

Server Status

-
US Server
+
US Server0 Players
+
Alis
+
V20 Players
+
V30 Players
+
BB0 Players
+
Abion
+
HC/BB0 Players
+
AdHoc-US
+
PSP10 Players
+
PSP2i0 Players
-
Alis0 Players
+
EU Server0 Players
+
Palma
+
V20 Players
+
V30 Players
+
BB0 Players
+
Aiedo
+
HC/BB0 Players
+
AdHoc-EU
+
PSP10 Players
+
PSP2i0 Players
+
+
Alis0 Players
V20 Players
V30 Players
BB0 Players
diff --git a/site/server-status.js b/site/server-status.js new file mode 100644 index 0000000..2697c26 --- /dev/null +++ b/site/server-status.js @@ -0,0 +1,43 @@ +(() => { + const list = document.querySelector(".status-list"); + if (!list) return; + + const esc = (value) => String(value ?? "").replace(/[&<>"']/g, (ch) => ({ + "&": "&", + "<": "<", + ">": ">", + "\"": """, + "'": "'", + }[ch])); + + const players = (value) => { + const n = Number(value || 0); + return `${n.toLocaleString()} ${n === 1 ? "Player" : "Players"}`; + }; + + const render = (data) => { + const servers = Array.isArray(data?.servers) ? data.servers : []; + if (!servers.length) return; + + list.innerHTML = servers.map((server) => ` +
+ ${esc(server.label)}${players(server.players)} +
+ ${(server.ships || []).map((ship) => ` +
+ ${esc(ship.label)} +
+ ${(ship.rows || []).map((row) => ` +
+ ${esc(row.label)}${players(row.players)} +
+ `).join("")} + `).join("")} + `).join(""); + }; + + fetch("/api/server-status", { cache: "no-store" }) + .then((res) => res.ok ? res.json() : null) + .then((data) => data && render(data)) + .catch(() => {}); +})(); From 8d4d1772ca000a184dc887b0d8beef7f9403f60e Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 13 Jun 2026 21:04:12 -0400 Subject: [PATCH 2/9] Fix home server status markup --- site/index.html | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/site/index.html b/site/index.html index 28d0285..d63eae7 100644 --- a/site/index.html +++ b/site/index.html @@ -10,7 +10,7 @@ - +
@@ -76,28 +76,6 @@
PSP10 Players
PSP2i0 Players
-
Alis0 Players
-
V20 Players
-
V30 Players
-
BB0 Players
- -
Abion
-
HC0 Players
- -
EU Server
- -
Palma0 Players
-
V20 Players
-
V30 Players
-
BB0 Players
- -
Aiedo
-
HC0 Players
- -
PSP Ship
-
PSP10 Players
-
PSP2i0 Players
-
@@ -138,6 +127,6 @@ - + From 7ce98d627563f6eef6bc53c86513a31b82ceae93 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 13 Jun 2026 21:08:44 -0400 Subject: [PATCH 4/9] Stretch home hardcore leaderboard card --- site/index.html | 2 +- site/style.css | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/site/index.html b/site/index.html index 5b2e4d9..370237a 100644 --- a/site/index.html +++ b/site/index.html @@ -8,7 +8,7 @@ - + diff --git a/site/style.css b/site/style.css index 52ede35..3713648 100644 --- a/site/style.css +++ b/site/style.css @@ -1857,4 +1857,14 @@ button.inline-link, overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; +}\n\n +/* Home right column: stretch Hardcore leaderboard after C Rank removal */ +.right-stack { + display: flex; + flex-direction: column; } + +.right-stack .leaderboard-card { + flex: 1; +} +\n \ No newline at end of file From 2a0b162a020eef97b55294673ea13219a4202ba8 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 13 Jun 2026 21:10:03 -0400 Subject: [PATCH 5/9] Stretch home right column --- site/index.html | 2 +- site/style.css | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/site/index.html b/site/index.html index 370237a..39addfd 100644 --- a/site/index.html +++ b/site/index.html @@ -8,7 +8,7 @@ - + diff --git a/site/style.css b/site/style.css index 3713648..c280b53 100644 --- a/site/style.css +++ b/site/style.css @@ -1867,4 +1867,21 @@ button.inline-link, .right-stack .leaderboard-card { flex: 1; } -\n \ No newline at end of file +\n + + +/* Home layout: stretch right column to match server status card */ +.home-grid { + align-items: stretch; +} + +.right-stack { + display: flex; + flex-direction: column; + height: 100%; +} + +.right-stack .leaderboard-card { + flex: 1 1 auto; +} + From 79915431fa42eb6bd864a7cc20a255d9528e27f8 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 13 Jun 2026 21:11:19 -0400 Subject: [PATCH 6/9] Narrow home server status list --- site/index.html | 2 +- site/style.css | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/site/index.html b/site/index.html index 39addfd..6a47e11 100644 --- a/site/index.html +++ b/site/index.html @@ -8,7 +8,7 @@ - + diff --git a/site/style.css b/site/style.css index c280b53..99444e1 100644 --- a/site/style.css +++ b/site/style.css @@ -1885,3 +1885,9 @@ button.inline-link, flex: 1 1 auto; } + +/* Home server status: reduce inner table width */ +.server-card .status-list { + max-width: 92%; +} + From d757468b7c55019805153c87832ab7144c3004b3 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 13 Jun 2026 21:14:59 -0400 Subject: [PATCH 7/9] Split home server status by region --- site/index.html | 50 +++++++++++++++++++++++-------------------- site/server-status.js | 23 +++++++++++--------- site/style.css | 30 +++++++++++++++++++++++--- 3 files changed, 67 insertions(+), 36 deletions(-) diff --git a/site/index.html b/site/index.html index 6a47e11..49b36bc 100644 --- a/site/index.html +++ b/site/index.html @@ -8,9 +8,9 @@ - + - +
@@ -53,28 +53,32 @@

Server Status

-
-
US Server0 Players
-
Alis
-
V20 Players
-
V30 Players
-
BB0 Players
-
Abion
-
HC/BB0 Players
-
AdHoc-US
-
PSP10 Players
-
PSP2i0 Players
+
+
+
US Server0 Players
+
Alis
+
V20 Players
+
V30 Players
+
BB0 Players
+
Abion
+
HC/BB0 Players
+
AdHoc-US
+
PSP10 Players
+
PSP2i0 Players
+
-
EU Server0 Players
-
Palma
-
V20 Players
-
V30 Players
-
BB0 Players
-
Aiedo
-
HC/BB0 Players
-
AdHoc-EU
-
PSP10 Players
-
PSP2i0 Players
+
+
EU Server0 Players
+
Palma
+
V20 Players
+
V30 Players
+
BB0 Players
+
Aiedo
+
HC/BB0 Players
+
AdHoc-EU
+
PSP10 Players
+
PSP2i0 Players
+
diff --git a/site/server-status.js b/site/server-status.js index 2697c26..e59ea6c 100644 --- a/site/server-status.js +++ b/site/server-status.js @@ -19,20 +19,23 @@ const servers = Array.isArray(data?.servers) ? data.servers : []; if (!servers.length) return; + list.classList.add("status-list--regions"); list.innerHTML = servers.map((server) => ` -
- ${esc(server.label)}${players(server.players)} -
- ${(server.ships || []).map((ship) => ` -
- ${esc(ship.label)} +
+
+ ${esc(server.label)}${players(server.players)}
- ${(ship.rows || []).map((row) => ` -
- ${esc(row.label)}${players(row.players)} + ${(server.ships || []).map((ship) => ` +
+ ${esc(ship.label)}
+ ${(ship.rows || []).map((row) => ` +
+ ${esc(row.label)}${players(row.players)} +
+ `).join("")} `).join("")} - `).join("")} +
`).join(""); }; diff --git a/site/style.css b/site/style.css index 99444e1..d5eb819 100644 --- a/site/style.css +++ b/site/style.css @@ -1886,8 +1886,32 @@ button.inline-link, } -/* Home server status: reduce inner table width */ -.server-card .status-list { - max-width: 92%; +/* Home server status: split US/EU into two inner boxes */ +.server-card .status-list.status-list--regions { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1rem; + background: transparent; + border: 0; + padding: 0; +} + +.server-card .status-region { + display: grid; + gap: 0.35rem; + padding: 1rem; + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 0.45rem; + background: rgba(0, 0, 0, 0.35); +} + +.server-card .status-region .status-row { + grid-template-columns: minmax(0, 1fr) max-content; +} + +@media (max-width: 720px) { + .server-card .status-list.status-list--regions { + grid-template-columns: 1fr; + } } From c04356f6a080ca68e34c89ad0a1c83f069c616b2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 13 Jun 2026 21:46:37 -0400 Subject: [PATCH 8/9] Add Caddy-compatible server status route --- backend/app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/app.py b/backend/app.py index 44d790c..a65a618 100644 --- a/backend/app.py +++ b/backend/app.py @@ -1941,6 +1941,7 @@ def hardcore_leaderboard_points_combined(): # --- end Hardcore stats aggregator ------------------------------------------- +@app.get("/server-status") @app.get("/api/server-status") def public_server_status(): import json From 8ae301ab2ddff603b17474713b1a886c36c78c5b Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 13 Jun 2026 21:52:27 -0400 Subject: [PATCH 9/9] Wire homepage server status to Prometheus --- site/index.html | 60 +++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/site/index.html b/site/index.html index 49b36bc..4c1ac1c 100644 --- a/site/index.html +++ b/site/index.html @@ -10,7 +10,7 @@ - +
@@ -53,31 +53,47 @@

Server Status

-
+
-
US Server0 Players
-
Alis
-
V20 Players
-
V30 Players
-
BB0 Players
-
Abion
-
HC/BB0 Players
-
AdHoc-US
-
PSP10 Players
-
PSP2i0 Players
+
+ US ServerLoading… +
+
+
Alis
+
V2
+
V3
+
BB
+
+
+
Abion
+
HC/BB
+
+
+
AdHoc-US
+
PSP1
+
PSP2i
+
-
EU Server0 Players
-
Palma
-
V20 Players
-
V30 Players
-
BB0 Players
-
Aiedo
-
HC/BB0 Players
-
AdHoc-EU
-
PSP10 Players
-
PSP2i0 Players
+
+ EU ServerLoading… +
+
+
Palma
+
V2
+
V3
+
BB
+
+
+
Aiedo
+
HC/BB
+
+
+
AdHoc-EU
+
PSP1
+
PSP2i
+