Spaces:
Runtime error
Runtime error
| #!/usr/bin/env python3 | |
| import os | |
| import subprocess | |
| import tempfile | |
| import threading | |
| import time | |
| from pathlib import Path | |
| from flask import Flask, Response, jsonify, render_template_string, request | |
| SETUP_FLAG = Path("/tmp/setup_mode") | |
| START_SCRIPT = "/opt/server/start.sh" | |
| UPLOAD_DIR = Path("/tmp/world_upload") | |
| UPLOAD_DIR.mkdir(parents=True, exist_ok=True) | |
| app = Flask(__name__) | |
| app.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 1024 | |
| SETUP_HTML = r""" | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Server Setup</title> | |
| </head> | |
| <body> | |
| <h1>First-Run Setup</h1> | |
| <label>HuggingFace Token</label><br> | |
| <input type="password" id="hf-token" placeholder="hf_..."><br><br> | |
| <label>World ZIP</label><br> | |
| <input type="file" id="fi" accept=".zip"><br><br> | |
| <div id="fname"></div><br> | |
| <button id="btn" disabled onclick="submitUpload()"> | |
| Upload & Start Server | |
| </button> | |
| <progress id="progress" value="0" max="100" style="display:none;"></progress> | |
| <div id="msg"></div> | |
| <script> | |
| let file = null; | |
| const fi = document.getElementById("fi"); | |
| const btn = document.getElementById("btn"); | |
| const fname = document.getElementById("fname"); | |
| const progress = document.getElementById("progress"); | |
| const msg = document.getElementById("msg"); | |
| function check() { | |
| const token = document.getElementById("hf-token").value.trim(); | |
| btn.disabled = !(file && token); | |
| } | |
| document.getElementById("hf-token").addEventListener("input", check); | |
| fi.addEventListener("change", () => { | |
| if (!fi.files[0]) return; | |
| file = fi.files[0]; | |
| fname.textContent = | |
| `${file.name} (${(file.size / 1048576).toFixed(1)} MB)`; | |
| check(); | |
| }); | |
| function submitUpload() { | |
| const token = document.getElementById("hf-token").value.trim(); | |
| if (!file || !token) return; | |
| btn.disabled = true; | |
| progress.style.display = "block"; | |
| msg.textContent = "Uploading..."; | |
| const fd = new FormData(); | |
| fd.append("world", file); | |
| fd.append("hf_token", token); | |
| const xhr = new XMLHttpRequest(); | |
| xhr.open("POST", "/setup/upload"); | |
| xhr.upload.onprogress = e => { | |
| if (e.lengthComputable) { | |
| progress.value = (e.loaded / e.total) * 100; | |
| } | |
| }; | |
| xhr.onload = () => { | |
| let r; | |
| try { | |
| r = JSON.parse(xhr.responseText); | |
| } catch { | |
| r = { ok: false, message: xhr.responseText }; | |
| } | |
| if (r.ok) { | |
| msg.textContent = | |
| "Done! Server is starting. Refresh in ~30 seconds."; | |
| } else { | |
| msg.textContent = | |
| "Error: " + (r.message || "Unknown error"); | |
| btn.disabled = false; | |
| } | |
| }; | |
| xhr.onerror = () => { | |
| msg.textContent = "Network error"; | |
| btn.disabled = false; | |
| }; | |
| xhr.send(fd); | |
| } | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| NOT_FOUND_HTML = """ | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <body><p>pp</p></body> | |
| </html> | |
| """ | |
| def root(): | |
| if SETUP_FLAG.exists(): | |
| return render_template_string(SETUP_HTML) | |
| return Response(NOT_FOUND_HTML, 200, {"Content-Type": "text/html"}) | |
| def setup_upload(): | |
| if not SETUP_FLAG.exists(): | |
| return jsonify({"ok": False, "message": "Not in setup mode"}), 403 | |
| hf_token = (request.form.get("hf_token") or "").strip() | |
| if not hf_token: | |
| return jsonify({"ok": False, "message": "HF token is required"}), 400 | |
| f = request.files.get("world") | |
| if not f or not f.filename.endswith(".zip"): | |
| return jsonify({"ok": False, "message": "A .zip file is required"}), 400 | |
| tmp_path = UPLOAD_DIR / "world_upload.zip" | |
| f.save(str(tmp_path)) | |
| os.environ["HF_TOKEN"] = hf_token | |
| import importlib, sys | |
| sys.path.insert(0, "/opt/server") | |
| import sync_world | |
| importlib.reload(sync_world) | |
| ok = sync_world.store_uploaded_zip(str(tmp_path)) | |
| if not ok: | |
| return jsonify({"ok": False, | |
| "message": "HF upload failed — check token / repo id"}), 500 | |
| SETUP_FLAG.unlink(missing_ok=True) | |
| def _restart(): | |
| time.sleep(1) | |
| subprocess.Popen(["/bin/bash", START_SCRIPT]) | |
| threading.Thread(target=_restart, daemon=True).start() | |
| return jsonify({"ok": True}) | |
| if __name__ == "__main__": | |
| app.run(host="0.0.0.0", port=5000, threaded=True) |