Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -5,12 +5,25 @@ import subprocess
|
|
5 |
import sys
|
6 |
import shutil
|
7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
PAPER_JAR_URL = "https://fill-data.papermc.io/v1/objects/234a9b32098100c6fc116664d64e36ccdb58b5b649af0f80bcccb08b0255eaea/paper-1.20.1-196.jar"
|
9 |
-
NGROK_URL = "https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz"
|
10 |
|
11 |
DATA_DIR = Path("/data")
|
12 |
JAVA_DIR = DATA_DIR / "java"
|
13 |
-
NGROK_DIR = DATA_DIR / "ngrok"
|
14 |
JAR_NAME = "paper-1.20.1-196.jar"
|
15 |
JAR_PATH = DATA_DIR / JAR_NAME
|
16 |
|
@@ -119,9 +132,13 @@ def install_ngrok():
|
|
119 |
return False
|
120 |
|
121 |
def setup_ngrok():
|
122 |
-
"""Setup ngrok with authentication token"""
|
123 |
print("Setting up ngrok...")
|
124 |
|
|
|
|
|
|
|
|
|
125 |
env_vars = load_env_vars()
|
126 |
ngrok_token = env_vars.get('NGROK_TOKEN')
|
127 |
|
@@ -130,109 +147,39 @@ def setup_ngrok():
|
|
130 |
print("Please set NGROK_TOKEN in your .env file or Hugging Face Space secrets")
|
131 |
return False
|
132 |
|
133 |
-
# Get ngrok path
|
134 |
-
ngrok_path = check_ngrok()
|
135 |
-
if not ngrok_path:
|
136 |
-
print("ngrok not found. Installing...")
|
137 |
-
if not install_ngrok():
|
138 |
-
print("Failed to install ngrok")
|
139 |
-
return False
|
140 |
-
ngrok_path = check_ngrok()
|
141 |
-
if not ngrok_path:
|
142 |
-
print("ngrok installation failed")
|
143 |
-
return False
|
144 |
-
|
145 |
-
# Configure ngrok with auth token
|
146 |
-
print("Configuring ngrok with auth token...")
|
147 |
try:
|
148 |
-
|
149 |
-
|
150 |
-
|
|
|
151 |
|
152 |
-
if result.returncode == 0:
|
153 |
-
print("✓ ngrok configured successfully")
|
154 |
-
return True
|
155 |
-
else:
|
156 |
-
print(f"Failed to configure ngrok: {result.stderr}")
|
157 |
-
return False
|
158 |
-
|
159 |
except Exception as e:
|
160 |
print(f"Failed to configure ngrok: {e}")
|
161 |
return False
|
162 |
|
163 |
def start_ngrok_tunnel(port=25565):
|
164 |
-
"""Start ngrok tunnel for the Minecraft server"""
|
165 |
print(f"Starting ngrok tunnel for port {port}...")
|
166 |
|
167 |
-
|
168 |
-
|
169 |
-
print("ngrok not found. Run setup first.")
|
170 |
return None, None
|
171 |
|
172 |
try:
|
173 |
-
#
|
174 |
-
print("
|
175 |
-
|
176 |
-
|
177 |
-
], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
178 |
|
179 |
-
|
180 |
-
|
181 |
-
import json
|
182 |
-
import urllib.request
|
183 |
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
|
188 |
-
|
189 |
-
time.sleep(1)
|
190 |
-
retry_count += 1
|
191 |
-
|
192 |
-
try:
|
193 |
-
# Check if ngrok process is still running
|
194 |
-
if process.poll() is not None:
|
195 |
-
# Process has ended, check for errors
|
196 |
-
stdout, stderr = process.communicate()
|
197 |
-
print(f"ngrok process ended unexpectedly:")
|
198 |
-
print(f"STDOUT: {stdout}")
|
199 |
-
print(f"STDERR: {stderr}")
|
200 |
-
return None, None
|
201 |
-
|
202 |
-
# Try to connect to ngrok API
|
203 |
-
api_url = "http://localhost:4040/api/tunnels"
|
204 |
-
with urllib.request.urlopen(api_url, timeout=2) as response:
|
205 |
-
data = json.loads(response.read().decode())
|
206 |
-
|
207 |
-
if data.get('tunnels'):
|
208 |
-
tunnel_url = data['tunnels'][0]['public_url']
|
209 |
-
print(f"✓ ngrok tunnel active: {tunnel_url}")
|
210 |
-
print(f"Players can connect to: {tunnel_url.replace('tcp://', '')}")
|
211 |
-
return process, tunnel_url
|
212 |
-
else:
|
213 |
-
print(f"Waiting for tunnel... (attempt {retry_count}/{max_retries})")
|
214 |
-
|
215 |
-
except urllib.error.URLError as e:
|
216 |
-
if retry_count % 5 == 0: # Print every 5 seconds
|
217 |
-
print(f"Waiting for ngrok API... (attempt {retry_count}/{max_retries})")
|
218 |
-
continue
|
219 |
-
except Exception as e:
|
220 |
-
print(f"Error checking ngrok status: {e}")
|
221 |
-
continue
|
222 |
|
223 |
-
# If we get here, we timed out
|
224 |
-
print("Timeout waiting for ngrok to start. Checking process status...")
|
225 |
-
if process.poll() is None:
|
226 |
-
print("ngrok process is still running but API is not responding.")
|
227 |
-
print("You may need to check the ngrok dashboard manually at http://localhost:4040")
|
228 |
-
return process, None
|
229 |
-
else:
|
230 |
-
stdout, stderr = process.communicate()
|
231 |
-
print(f"ngrok process ended during startup:")
|
232 |
-
print(f"STDOUT: {stdout}")
|
233 |
-
print(f"STDERR: {stderr}")
|
234 |
-
return None, None
|
235 |
-
|
236 |
except Exception as e:
|
237 |
print(f"Failed to start ngrok tunnel: {e}")
|
238 |
return None, None
|
@@ -451,26 +398,45 @@ def start_server():
|
|
451 |
print(f"Failed to start server: {e}")
|
452 |
return False
|
453 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
454 |
if __name__ == "__main__":
|
455 |
print("=== Minecraft Server Setup ===")
|
456 |
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
import sys
|
6 |
import shutil
|
7 |
|
8 |
+
# Try to import pyngrok, install if not available
|
9 |
+
try:
|
10 |
+
from pyngrok import ngrok, conf
|
11 |
+
PYNGROK_AVAILABLE = True
|
12 |
+
except ImportError:
|
13 |
+
print("pyngrok not found. Installing...")
|
14 |
+
try:
|
15 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "pyngrok"])
|
16 |
+
from pyngrok import ngrok, conf
|
17 |
+
PYNGROK_AVAILABLE = True
|
18 |
+
print("✓ pyngrok installed successfully")
|
19 |
+
except Exception as e:
|
20 |
+
print(f"Failed to install pyngrok: {e}")
|
21 |
+
PYNGROK_AVAILABLE = False
|
22 |
+
|
23 |
PAPER_JAR_URL = "https://fill-data.papermc.io/v1/objects/234a9b32098100c6fc116664d64e36ccdb58b5b649af0f80bcccb08b0255eaea/paper-1.20.1-196.jar"
|
|
|
24 |
|
25 |
DATA_DIR = Path("/data")
|
26 |
JAVA_DIR = DATA_DIR / "java"
|
|
|
27 |
JAR_NAME = "paper-1.20.1-196.jar"
|
28 |
JAR_PATH = DATA_DIR / JAR_NAME
|
29 |
|
|
|
132 |
return False
|
133 |
|
134 |
def setup_ngrok():
|
135 |
+
"""Setup ngrok with authentication token using pyngrok"""
|
136 |
print("Setting up ngrok...")
|
137 |
|
138 |
+
if not PYNGROK_AVAILABLE:
|
139 |
+
print("pyngrok is not available. Cannot setup ngrok.")
|
140 |
+
return False
|
141 |
+
|
142 |
env_vars = load_env_vars()
|
143 |
ngrok_token = env_vars.get('NGROK_TOKEN')
|
144 |
|
|
|
147 |
print("Please set NGROK_TOKEN in your .env file or Hugging Face Space secrets")
|
148 |
return False
|
149 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
try:
|
151 |
+
# Set the auth token
|
152 |
+
ngrok.set_auth_token(ngrok_token)
|
153 |
+
print("✓ ngrok configured successfully with pyngrok")
|
154 |
+
return True
|
155 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
except Exception as e:
|
157 |
print(f"Failed to configure ngrok: {e}")
|
158 |
return False
|
159 |
|
160 |
def start_ngrok_tunnel(port=25565):
|
161 |
+
"""Start ngrok tunnel for the Minecraft server using pyngrok"""
|
162 |
print(f"Starting ngrok tunnel for port {port}...")
|
163 |
|
164 |
+
if not PYNGROK_AVAILABLE:
|
165 |
+
print("pyngrok is not available. Cannot start tunnel.")
|
|
|
166 |
return None, None
|
167 |
|
168 |
try:
|
169 |
+
# Create a TCP tunnel
|
170 |
+
print("Creating ngrok tunnel...")
|
171 |
+
tunnel = ngrok.connect(port, "tcp")
|
172 |
+
tunnel_url = tunnel.public_url
|
|
|
173 |
|
174 |
+
print(f"✓ ngrok tunnel active: {tunnel_url}")
|
175 |
+
print(f"Players can connect to: {tunnel_url.replace('tcp://', '')}")
|
|
|
|
|
176 |
|
177 |
+
# Get all active tunnels for reference
|
178 |
+
tunnels = ngrok.get_tunnels()
|
179 |
+
print(f"Active tunnels: {len(tunnels)}")
|
180 |
|
181 |
+
return tunnel, tunnel_url
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
182 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
except Exception as e:
|
184 |
print(f"Failed to start ngrok tunnel: {e}")
|
185 |
return None, None
|
|
|
398 |
print(f"Failed to start server: {e}")
|
399 |
return False
|
400 |
|
401 |
+
def cleanup_ngrok():
|
402 |
+
"""Clean up ngrok tunnels on exit"""
|
403 |
+
if PYNGROK_AVAILABLE:
|
404 |
+
try:
|
405 |
+
ngrok.kill()
|
406 |
+
print("✓ ngrok tunnels cleaned up")
|
407 |
+
except:
|
408 |
+
pass
|
409 |
+
|
410 |
if __name__ == "__main__":
|
411 |
print("=== Minecraft Server Setup ===")
|
412 |
|
413 |
+
try:
|
414 |
+
# Step 1: Setup Minecraft server
|
415 |
+
if not setup_minecraft_server():
|
416 |
+
print("Setup failed. Cannot start server.")
|
417 |
+
sys.exit(1)
|
418 |
+
|
419 |
+
# Step 2: Setup ngrok
|
420 |
+
print("\n=== Setting up ngrok ===")
|
421 |
+
if not setup_ngrok():
|
422 |
+
print("ngrok setup failed. Server will start but won't be accessible externally.")
|
423 |
+
tunnel = None
|
424 |
+
else:
|
425 |
+
# Step 3: Start ngrok tunnel
|
426 |
+
print("\n=== Starting ngrok tunnel ===")
|
427 |
+
tunnel, tunnel_url = start_ngrok_tunnel()
|
428 |
+
if not tunnel:
|
429 |
+
print("Failed to start ngrok tunnel. Server will start but won't be accessible externally.")
|
430 |
+
|
431 |
+
# Step 4: Start the server
|
432 |
+
print("\n=== Starting Minecraft Server ===")
|
433 |
+
start_server()
|
434 |
+
|
435 |
+
except KeyboardInterrupt:
|
436 |
+
print("\n\nShutting down...")
|
437 |
+
cleanup_ngrok()
|
438 |
+
sys.exit(0)
|
439 |
+
except Exception as e:
|
440 |
+
print(f"Unexpected error: {e}")
|
441 |
+
cleanup_ngrok()
|
442 |
+
sys.exit(1)
|