Download status_server.py from pabla1322/server: direct link, hf CLI and curl.
- Browser
- Download file 7.04 kB
-
https://huggingface.co/spaces/pabla1322/server/resolve/main/status_server.py
- Command line
-
hf download hf://spaces/pabla1322/server/status_server.py
-
curl -L -o status_server.py https://huggingface.co/spaces/pabla1322/server/resolve/main/status_server.py
7.04 kB
| #!/usr/bin/env python3 | |
| """ | |
| Live status dashboard for Alpha MC — serves on port 7860. | |
| Reads /tmp/mc_status.json and log files to show real-time info. | |
| """ | |
| import http.server | |
| import json | |
| import os | |
| import subprocess | |
| import time | |
| from datetime import datetime | |
| STATUS_FILE = "/tmp/mc_status.json" | |
| MC_LOG = "/data/logs/minecraft.log" | |
| PLAYIT_LOG = "/data/playit_gg/playit.log" | |
| MONITOR_LOG = "/data/logs/monitor.log" # kept for compat | |
| def read_status(): | |
| try: | |
| with open(STATUS_FILE) as f: | |
| return json.load(f) | |
| except Exception: | |
| return { | |
| "mc_online": False, | |
| "playit_online": False, | |
| "tunnel_address": "", | |
| "started_at": "", | |
| "uptime": "unknown" | |
| } | |
| def tail_file(path, lines=30): | |
| try: | |
| result = subprocess.run( | |
| ["tail", "-n", str(lines), path], | |
| capture_output=True, text=True, timeout=3 | |
| ) | |
| return result.stdout.strip() or "(no logs yet)" | |
| except Exception: | |
| return "(log unavailable)" | |
| def get_system_stats(): | |
| try: | |
| mem = subprocess.run(["free", "-h"], capture_output=True, text=True).stdout | |
| mem_line = [l for l in mem.splitlines() if l.startswith("Mem:")][0].split() | |
| mem_used, mem_total = mem_line[2], mem_line[1] | |
| except Exception: | |
| mem_used, mem_total = "?", "?" | |
| try: | |
| disk = subprocess.run(["df", "-h", "/data"], capture_output=True, text=True).stdout | |
| disk_line = disk.splitlines()[1].split() | |
| disk_used, disk_total, disk_pct = disk_line[2], disk_line[1], disk_line[4] | |
| except Exception: | |
| disk_used, disk_total, disk_pct = "?", "?", "?" | |
| try: | |
| load = subprocess.run(["uptime"], capture_output=True, text=True).stdout | |
| load = load.split("load average:")[-1].strip() | |
| except Exception: | |
| load = "?" | |
| return { | |
| "mem_used": mem_used, "mem_total": mem_total, | |
| "disk_used": disk_used, "disk_total": disk_total, "disk_pct": disk_pct, | |
| "load": load | |
| } | |
| def get_tunnel_address(): | |
| """Try to extract the live tunnel address from playit log.""" | |
| try: | |
| result = subprocess.run( | |
| ["grep", "-oE", r"[a-z0-9-]+\.playit\.gg(:[0-9]+)?", PLAYIT_LOG], | |
| capture_output=True, text=True, timeout=3 | |
| ) | |
| addr = result.stdout.strip().splitlines() | |
| return addr[0] if addr else "" | |
| except Exception: | |
| return "" | |
| def render_html(): | |
| status = read_status() | |
| stats = get_system_stats() | |
| tunnel = get_tunnel_address() or status.get("tunnel_address", "") | |
| mc_log = tail_file(MC_LOG, 40) | |
| now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
| mc_status_color = "#4ade80" if status.get("mc_online") else "#f87171" | |
| mc_status_text = "🟢 Online" if status.get("mc_online") else "🔴 Offline" | |
| tunnel_color = "#4ade80" if tunnel else "#facc15" | |
| tunnel_text = tunnel if tunnel else "Waiting for tunnel..." | |
| return f"""<!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <meta http-equiv="refresh" content="15"> | |
| <title>⛏️ Alpha MC — Status</title> | |
| <style> | |
| * {{ box-sizing: border-box; margin: 0; padding: 0; }} | |
| body {{ | |
| background: #0f1117; | |
| color: #e2e8f0; | |
| font-family: 'Segoe UI', system-ui, sans-serif; | |
| padding: 24px; | |
| min-height: 100vh; | |
| }} | |
| h1 {{ font-size: 1.8rem; color: #4ade80; margin-bottom: 4px; }} | |
| .subtitle {{ color: #64748b; font-size: 0.9rem; margin-bottom: 24px; }} | |
| .grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; margin-bottom: 24px; }} | |
| .card {{ | |
| background: #1e2333; | |
| border-radius: 12px; | |
| padding: 20px; | |
| border: 1px solid #2d3748; | |
| }} | |
| .card-label {{ color: #64748b; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 6px; }} | |
| .card-value {{ font-size: 1.2rem; font-weight: 600; }} | |
| .tunnel-box {{ | |
| background: #1e2333; | |
| border-radius: 12px; | |
| padding: 20px; | |
| border: 1px solid #2d3748; | |
| margin-bottom: 24px; | |
| }} | |
| .tunnel-addr {{ | |
| font-family: monospace; | |
| font-size: 1.4rem; | |
| color: {tunnel_color}; | |
| word-break: break-all; | |
| margin-top: 8px; | |
| }} | |
| .log-box {{ | |
| background: #0a0c10; | |
| border-radius: 12px; | |
| padding: 20px; | |
| border: 1px solid #2d3748; | |
| }} | |
| .log-box h2 {{ color: #94a3b8; font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 12px; }} | |
| pre {{ | |
| font-family: 'Cascadia Code', 'Fira Code', monospace; | |
| font-size: 0.78rem; | |
| color: #94a3b8; | |
| white-space: pre-wrap; | |
| word-break: break-word; | |
| line-height: 1.5; | |
| max-height: 400px; | |
| overflow-y: auto; | |
| }} | |
| .badge {{ | |
| display: inline-block; | |
| background: #2d3748; | |
| border-radius: 6px; | |
| padding: 2px 10px; | |
| font-size: 0.8rem; | |
| margin-left: 8px; | |
| vertical-align: middle; | |
| }} | |
| .footer {{ color: #334155; font-size: 0.75rem; margin-top: 20px; text-align: center; }} | |
| </style> | |
| </head> | |
| <body> | |
| <h1>⛏️ Alpha MC</h1> | |
| <p class="subtitle">Minecraft Bedrock Server · Auto-refreshes every 15s · Last updated: {now}</p> | |
| <div class="grid"> | |
| <div class="card"> | |
| <div class="card-label">Server Status</div> | |
| <div class="card-value" style="color:{mc_status_color}">{mc_status_text}</div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-label">RAM Usage</div> | |
| <div class="card-value">{stats['mem_used']} <span style="color:#64748b;font-size:0.9rem">/ {stats['mem_total']}</span></div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-label">Disk Usage</div> | |
| <div class="card-value">{stats['disk_used']} <span style="color:#64748b;font-size:0.9rem">/ {stats['disk_total']} ({stats['disk_pct']})</span></div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-label">CPU Load</div> | |
| <div class="card-value">{stats['load']}</div> | |
| </div> | |
| </div> | |
| <div class="tunnel-box"> | |
| <div class="card-label">🔗 Connect Address <span class="badge">Minecraft → Add Server → paste below</span></div> | |
| <div class="tunnel-addr">{tunnel_text}</div> | |
| </div> | |
| <div class="log-box"> | |
| <h2>📋 Minecraft Server Log (last 40 lines)</h2> | |
| <pre>{mc_log}</pre> | |
| </div> | |
| <p class="footer">Alpha MC · Powered by HuggingFace Spaces + playit.gg · Page auto-refreshes every 15 seconds</p> | |
| </body> | |
| </html>""" | |
| class StatusHandler(http.server.BaseHTTPRequestHandler): | |
| def do_GET(self): | |
| html = render_html() | |
| self.send_response(200) | |
| self.send_header("Content-Type", "text/html; charset=utf-8") | |
| self.send_header("Content-Length", str(len(html.encode()))) | |
| self.end_headers() | |
| self.wfile.write(html.encode()) | |
| def log_message(self, format, *args): | |
| pass # suppress access logs | |
| if __name__ == "__main__": | |
| server = http.server.HTTPServer(("0.0.0.0", 7860), StatusHandler) | |
| print(f"[OK] Status dashboard running on http://0.0.0.0:7860") | |
| server.serve_forever() | |