import streamlit as st import subprocess import time import os import re import requests import zipfile import stat # ─── Config ─────────────────────────────────────────────── DATA_DIR = "/data" SERVER_DIR = os.path.join(DATA_DIR, "bedrock-server") PLAYIT_DIR = os.path.join(DATA_DIR, "playit_gg") PLAYIT_LOG = os.path.join(PLAYIT_DIR, "playit.log") SECRET_KEY = os.environ.get("SECRET_KEY", "") os.makedirs(SERVER_DIR, exist_ok=True) os.makedirs(PLAYIT_DIR, exist_ok=True) # ─── Download helpers ───────────────────────────────────── def download_file(url, dest): if not os.path.exists(dest): r = requests.get(url, allow_redirects=True) with open(dest, 'wb') as f: f.write(r.content) st.sidebar.write(f"Downloaded: {os.path.basename(dest)}") # ─── Setup ─────────────────────────────────────────────── def setup(): # Bedrock server if not os.path.exists(os.path.join(SERVER_DIR, "bedrock_server")): try: r = requests.get("https://www.minecraft.net/en-us/download/server/bedrock") match = re.search(r'https://www.minecraft.net/bedrockserver/[^"]+', r.text) url = match.group(0) if match else "https://www.minecraft.net/bedrockserver/bin-linux/bedrock-server-1.26.14.1.zip" except: url = "https://www.minecraft.net/bedrockserver/bin-linux/bedrock-server-1.26.14.1.zip" zip_path = "/tmp/bedrock-server.zip" download_file(url, zip_path) with zipfile.ZipFile(zip_path, 'r') as zf: zf.extractall(SERVER_DIR) os.chmod(os.path.join(SERVER_DIR, "bedrock_server"), 0o755) os.remove(zip_path) st.sidebar.write("Bedrock server ready.") # playit agent playit_bin = "/usr/local/bin/playit" if not os.path.exists(playit_bin): download_file("https://github.com/playit-cloud/playit-agent/releases/latest/download/playit-linux-amd64", playit_bin) os.chmod(playit_bin, 0o755) st.sidebar.write("playit agent ready.") # playit config playit_toml = os.path.join(PLAYIT_DIR, "playit.toml") if not os.path.exists(playit_toml): with open(playit_toml, 'w') as f: f.write("[tunnel.minecraft]\n") f.write("type = \"minecraft-bedrock\"\n") f.write("local_ip = \"0.0.0.0\"\n") f.write("local_port = 19132\n") # ─── Processes ───────────────────────────────────────────── playit_proc = None server_proc = None def start_processes(): global playit_proc, server_proc # playit cmd = ["/usr/local/bin/playit"] if SECRET_KEY: cmd.extend(["--secret", SECRET_KEY]) with open(PLAYIT_LOG, "w") as log: playit_proc = subprocess.Popen(cmd, stdout=log, stderr=subprocess.STDOUT) # bedrock server server_bin = os.path.join(SERVER_DIR, "bedrock_server") server_proc = subprocess.Popen([server_bin], cwd=SERVER_DIR, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) # ─── UI ───────────────────────────────────────────────────── st.set_page_config(page_title="Minecraft Server", page_icon="🎮") st.title("🎮 Minecraft Bedrock Server") st.markdown("Always‑on server via playit.gg") with st.sidebar: st.header("Setup") with st.spinner("Downloading..."): setup() if st.button("Restart Server"): if server_proc: server_proc.terminate() if playit_proc: playit_proc.terminate() start_processes() st.success("Restarted!") # Start if not running if not playit_proc or playit_proc.poll() is not None: start_processes() # Tunnel info st.header("Tunnel Connection") if os.path.exists(PLAYIT_LOG): log = open(PLAYIT_LOG).read() claim = re.search(r'https://playit\.gg/claim/[A-Za-z0-9_=-]+', log) addr = re.search(r'([a-z0-9-]+\.playit\.gg|[a-z0-9-]+\.joinmc\.link)(:[0-9]+)?', log) if addr: st.success(f"✅ LIVE – Connect to: `{addr.group(0)}`") elif claim: st.warning("🔑 Claim needed – open this link:") st.markdown(f"[{claim.group(0)}]({claim.group(0)})") else: st.info("⏳ Waiting for tunnel...") else: st.info("Starting...") st.caption("Auto‑refreshes every 10 seconds") time.sleep(10) st.rerun()