Dodanie mapy serwera i poprawka pobierania modów
- Dodaje #16 - Mape serwera w panelu (z pluginem squaremap) - Poprawia pobieranie modów z Modrinth (dobra wersja i typ)
This commit is contained in:
parent
ee189b7e72
commit
efa85c5070
3 changed files with 174 additions and 34 deletions
141
app/api.py
141
app/api.py
|
@ -5,7 +5,7 @@ import subprocess
|
||||||
|
|
||||||
import docker
|
import docker
|
||||||
import requests
|
import requests
|
||||||
from flask import Blueprint, jsonify, request, send_from_directory, abort
|
from flask import Blueprint, jsonify, request, send_from_directory, abort, Response
|
||||||
|
|
||||||
from .auth import oidc
|
from .auth import oidc
|
||||||
from .docker_utils import start_server, stop_server, restart_server, get_logs, delete_server, save_server_info, \
|
from .docker_utils import start_server, stop_server, restart_server, get_logs, delete_server, save_server_info, \
|
||||||
|
@ -296,6 +296,108 @@ def stats():
|
||||||
return jsonify({"error": "Container not found"}), 404
|
return jsonify({"error": "Container not found"}), 404
|
||||||
|
|
||||||
|
|
||||||
|
# Map
|
||||||
|
# TODO: OTHER PROXYS ARE JUST A TEMPORARY FIX!!! MAKE SOMETHING PERMANENT INSTEAD
|
||||||
|
@api.route('/map')
|
||||||
|
@oidc.require_login
|
||||||
|
def map_proxy():
|
||||||
|
username = oidc.user_getfield('preferred_username')
|
||||||
|
container_name = f"mc-{username}"
|
||||||
|
container_ip = client.containers.get(container_name).attrs['NetworkSettings']['IPAddress']
|
||||||
|
url = f"http://{container_ip}:8080"
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(url, params=request.args, timeout=5)
|
||||||
|
return Response(
|
||||||
|
response.content,
|
||||||
|
status=response.status_code,
|
||||||
|
content_type=response.headers.get('Content-Type', 'application/octet-stream')
|
||||||
|
)
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
print(f"Error proxying map: {e}")
|
||||||
|
return jsonify({"message": "Mapa nie działa. Czy zainstalowałeś Squaremap?"}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@api.route('/js/<path:filename>', methods=['GET'])
|
||||||
|
@oidc.require_login
|
||||||
|
def proxy_js(filename):
|
||||||
|
username = oidc.user_getfield('preferred_username')
|
||||||
|
container_name = f"mc-{username}"
|
||||||
|
container_ip = client.containers.get(container_name).attrs['NetworkSettings']['IPAddress']
|
||||||
|
|
||||||
|
url = f"http://{container_ip}:8080/js/{filename}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(url, timeout=5)
|
||||||
|
return Response(
|
||||||
|
response.content,
|
||||||
|
status=response.status_code,
|
||||||
|
content_type=response.headers.get('Content-Type', 'application/javascript')
|
||||||
|
)
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
return jsonify({"message": "Błąd ładowania skryptu: " + str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@api.route('/css/<path:filename>', methods=['GET'])
|
||||||
|
@oidc.require_login
|
||||||
|
def proxy_css(filename):
|
||||||
|
username = oidc.user_getfield('preferred_username')
|
||||||
|
container_name = f"mc-{username}"
|
||||||
|
container_ip = client.containers.get(container_name).attrs['NetworkSettings']['IPAddress']
|
||||||
|
|
||||||
|
url = f"http://{container_ip}:8080/css/{filename}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(url, timeout=5)
|
||||||
|
return Response(
|
||||||
|
response.content,
|
||||||
|
status=response.status_code,
|
||||||
|
content_type=response.headers.get('Content-Type', 'text/css')
|
||||||
|
)
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
return jsonify({"message": "Błąd ładowania stylu: " + str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@api.route('/tiles/<path:filename>', methods=['GET'])
|
||||||
|
@oidc.require_login
|
||||||
|
def proxy_tiles_settings(filename):
|
||||||
|
username = oidc.user_getfield('preferred_username')
|
||||||
|
container_name = f"mc-{username}"
|
||||||
|
container_ip = client.containers.get(container_name).attrs['NetworkSettings']['IPAddress']
|
||||||
|
|
||||||
|
url = f"http://{container_ip}:8080/tiles/{filename}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(url, timeout=5)
|
||||||
|
return Response(
|
||||||
|
response.content,
|
||||||
|
status=response.status_code,
|
||||||
|
content_type=response.headers.get('Content-Type', 'text/json')
|
||||||
|
)
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
return jsonify({"message": "Błąd ładowania tiles: " + str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@api.route('/images/<path:filename>', methods=['GET'])
|
||||||
|
@oidc.require_login
|
||||||
|
def proxy_images(filename):
|
||||||
|
username = oidc.user_getfield('preferred_username')
|
||||||
|
container_name = f"mc-{username}"
|
||||||
|
container_ip = client.containers.get(container_name).attrs['NetworkSettings']['IPAddress']
|
||||||
|
|
||||||
|
url = f"http://{container_ip}:8080/images/{filename}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(url, timeout=5)
|
||||||
|
return Response(
|
||||||
|
response.content,
|
||||||
|
status=response.status_code,
|
||||||
|
content_type=response.headers.get('Content-Type', 'image/png')
|
||||||
|
)
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
return jsonify({"message": "Błąd ładowania tiles: " + str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
# Modrinth
|
# Modrinth
|
||||||
@api.route('/modrinth/search')
|
@api.route('/modrinth/search')
|
||||||
def modrinth_search():
|
def modrinth_search():
|
||||||
|
@ -327,19 +429,34 @@ def download_mod():
|
||||||
project_id = data['project_id']
|
project_id = data['project_id']
|
||||||
username = data['username']
|
username = data['username']
|
||||||
server_type = data['type']
|
server_type = data['type']
|
||||||
|
server_version = data['version']
|
||||||
|
|
||||||
version_response = requests.get(f"https://api.modrinth.com/v2/project/{project_id}/version")
|
base_path = f"./servers/mc-{username}/{'plugins' if server_type == 'paper' else 'mods'}"
|
||||||
version_data = version_response.json()
|
|
||||||
|
|
||||||
file_url = version_data[0]['files'][0]['url']
|
downloaded = []
|
||||||
file_name = version_data[0]['files'][0]['filename']
|
|
||||||
|
|
||||||
folder = 'plugins' if server_type == 'paper' else 'mods'
|
def download_project(pid, version_id=None):
|
||||||
file_path = f"./servers/mc-{username}/{folder}/{file_name}"
|
if version_id:
|
||||||
|
version_data = requests.get(f"https://api.modrinth.com/v2/version/{version_id}").json()
|
||||||
|
else:
|
||||||
|
all_versions = requests.get(f"https://api.modrinth.com/v2/project/{pid}/version").json()
|
||||||
|
version_data = next((v for v in all_versions if server_version in v['game_versions'] and server_type in v['loaders']), None)
|
||||||
|
if not version_data:
|
||||||
|
return
|
||||||
|
|
||||||
with requests.get(file_url, stream=True) as r:
|
file = version_data['files'][0]
|
||||||
with open(file_path, 'wb') as f:
|
file_path = f"{base_path}/{file['filename']}"
|
||||||
for chunk in r.iter_content(chunk_size=8192):
|
if file['filename'] not in downloaded:
|
||||||
f.write(chunk)
|
with requests.get(file['url'], stream=True) as r:
|
||||||
|
with open(file_path, 'wb') as f:
|
||||||
|
for chunk in r.iter_content(chunk_size=8192):
|
||||||
|
f.write(chunk)
|
||||||
|
downloaded.append(file['filename'])
|
||||||
|
|
||||||
return jsonify({"success": True, "file": file_name})
|
for dep in version_data.get('dependencies', []):
|
||||||
|
if dep.get('version_id'):
|
||||||
|
download_project(dep['project_id'], dep['version_id'])
|
||||||
|
|
||||||
|
download_project(project_id)
|
||||||
|
|
||||||
|
return jsonify({"success": True, "downloaded": downloaded})
|
||||||
|
|
|
@ -33,19 +33,36 @@ function searchMods() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function installMod(projectId) {
|
function installMod(projectId) {
|
||||||
const serverType = document.getElementById("server-type").value;
|
fetch('/api/config')
|
||||||
fetch('/api/modrinth/download', {
|
.then(response => response.json())
|
||||||
method: 'POST',
|
.then(configData => {
|
||||||
headers: { 'Content-Type': 'application/json' },
|
console.log(configData);
|
||||||
body: JSON.stringify({ project_id: projectId, username, type: serverType })
|
if (configData.success) {
|
||||||
})
|
const serverType = configData.type;
|
||||||
.then(r => r.json())
|
const serverVersion = configData.version;
|
||||||
.then(data => {
|
if (serverType && serverVersion) {
|
||||||
if (data.success) {
|
fetch('/api/modrinth/download', {
|
||||||
alert(`Zainstalowano: ${data.file}`);
|
method: 'POST',
|
||||||
loadFileList();
|
headers: { 'Content-Type': 'application/json' },
|
||||||
} else {
|
body: JSON.stringify({ project_id: projectId, username, type: serverType, version: serverVersion }),
|
||||||
alert("Nie udało się zainstalować moda.");
|
})
|
||||||
}
|
.then(r => r.json())
|
||||||
});
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
alert(`Zainstalowano: ${data.file}`);
|
||||||
|
loadFileList();
|
||||||
|
} else {
|
||||||
|
alert("Nie udało się zainstalować moda.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error('Server type or version not available');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('Server config not found');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Error fetching server config:', err);
|
||||||
|
});
|
||||||
}
|
}
|
|
@ -6,12 +6,13 @@
|
||||||
<button class="tab-button" onclick="showTab('controls')">Sterowanie 🎛️</button>
|
<button class="tab-button" onclick="showTab('controls')">Sterowanie 🎛️</button>
|
||||||
<button class="tab-button" onclick="showTab('console')">Konsola 📟</button>
|
<button class="tab-button" onclick="showTab('console')">Konsola 📟</button>
|
||||||
<button class="tab-button" onclick="showTab('files')">Pliki 📁</button>
|
<button class="tab-button" onclick="showTab('files')">Pliki 📁</button>
|
||||||
|
<button class="tab-button" onclick="showTab('config')">Konfiguracja 🛠️</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<button class="tab-button" onclick="showTab('config')">Konfiguracja 🛠️</button>
|
<button class="tab-button" onclick="showTab('map')">Mapa 🗺️</button>
|
||||||
<button class="tab-button" onclick="showTab('statistics')">Statystyki 📈</button>
|
|
||||||
<button class="tab-button" onclick="showTab('mods')">Mody/Pluginy 🧩</button>
|
<button class="tab-button" onclick="showTab('mods')">Mody/Pluginy 🧩</button>
|
||||||
|
<button class="tab-button" onclick="showTab('statistics')">Statystyki 📈</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
|
@ -112,11 +113,9 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-panel" id="statistics">
|
<div class="tab-panel" id="map">
|
||||||
<div class="charts-row">
|
<h2>Mapa Serwera</h2>
|
||||||
<div class="chart-container"><canvas id="cpuChart"></canvas></div>
|
<iframe src="/api/map" width="100%" height="500px"></iframe>
|
||||||
<div class="chart-container"><canvas id="ramChart"></canvas></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-panel" id="mods">
|
<div class="tab-panel" id="mods">
|
||||||
|
@ -124,6 +123,13 @@
|
||||||
<input type="text" id="mod-search" placeholder="Wyszukaj mod/plugin..." oninput="searchMods()">
|
<input type="text" id="mod-search" placeholder="Wyszukaj mod/plugin..." oninput="searchMods()">
|
||||||
<div id="mod-results"></div>
|
<div id="mod-results"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-panel" id="statistics">
|
||||||
|
<div class="charts-row">
|
||||||
|
<div class="chart-container"><canvas id="cpuChart"></canvas></div>
|
||||||
|
<div class="chart-container"><canvas id="ramChart"></canvas></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
|
Loading…
Add table
Reference in a new issue