server / status_server.py
pabla1322's picture
Upload 17 files
722781c verified
Raw
History Blame Contribute Delete
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()