This repository has been archived on 2026-10-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2024-11-05 11:26:22 -08:00

553 lines
21 KiB
PHP

<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/mysql.php"; ?>
<?php
if(!isset($_SESSION['siteusername'])) {
header("Location: /");
exit();
}
if($user['status'] != "admin") {
header("Location: /");
exit();
}
if($_SERVER['REQUEST_METHOD'] == "POST") {
if($_POST['type'] == "ban") {
$stmt = $db->prepare("SELECT * FROM users WHERE username = :username");
$stmt->execute([':username' => $_POST['username']]);
if($stmt->rowCount()) {
$stmt = $db->prepare("INSERT INTO bans (username, reason) VALUES (:username, :reason)");
$stmt->execute([
':username' => $_POST['username'],
':reason' => $_POST['reason']
]);
$_SESSION['success'] = "Successfully banned";
header('Location: /admin/');
exit();
} else {
$_SESSION['error'] = "User not found";
header('Location: /admin/');
exit();
}
} else if($_POST['type'] == "ipban") {
$stmt = $db->prepare("SELECT ip FROM users WHERE username = :username");
$stmt->execute([':username' => $_POST['username']]);
if(!$stmt->rowCount()) {
$_SESSION['error'] = "User not found";
header('Location: /admin/');
exit();
}
$ip = $stmt->fetch(PDO::FETCH_ASSOC)['ip'];
$stmt = $db->prepare("INSERT INTO bans (username, reason) VALUES (:username, :reason)");
$stmt->execute([
':username' => $ip,
':reason' => $_POST['reason']
]);
$_SESSION['success'] = "Successfully banned";
header('Location: /admin/');
exit();
} else if($_POST['type'] == "unban") {
$stmt = $db->prepare("SELECT ip FROM users WHERE username = :username");
$stmt->execute([':username' => $_POST['username']]);
if(!$stmt->rowCount()) {
$_SESSION['error'] = "User not found";
header('Location: /admin/');
exit();
}
$stmt = $db->prepare("DELETE FROM bans WHERE username = :username");
$stmt->execute([
':username' => $_POST['username']
]);
$_SESSION['success'] = "Successfully banned";
header('Location: /admin/');
exit();
} else if ($_POST['type'] == "delbyusr") {
$stmt = $db->prepare("SELECT * FROM servers WHERE author = :username AND online = 1");
$stmt->execute([':username' => $_POST['username']]);
while($server = $stmt->fetch(PDO::FETCH_ASSOC)) {
$response = file_get_contents("https://api.novetusserverlist.com/stop?port=" . $server['port'] . "&key=verysecretomgomgskibiti");
}
$stmt = $db->prepare("SELECT COUNT(*) FROM servers WHERE author = :username");
$stmt->execute([':username' => $_POST['username']]);
$servers = $stmt->fetchColumn();
$stmt = $db->prepare("DELETE FROM servers WHERE author = :username");
$stmt->execute([':username' => $_POST['username']]);
$_SESSION['success'] = "Successfully deleted " . $servers . " servers";
header('Location: /admin/');
exit();
}
}
?>
<html>
<head>
<?php require $_SERVER['DOCUMENT_ROOT'] . "/modules/head.php"; ?>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
@keyframes fadeInUp2 {
0% {
opacity: 0;
-webkit-transform: translate3d(0, 25%, 0);
transform: translate3d(0, 25%, 0)
}
to {
opacity: 0.6;
-webkit-transform: none;
transform: none
}
}
@keyframes fadeOutDown2 {
0% {
opacity: 0.6
}
to {
opacity: 0;
-webkit-transform: translate3d(0, 25%, 0);
transform: translate3d(0, 25%, 0)
}
}
.console {
position: absolute;
top: 0;
z-index: 999999;
width: 100%;
height: 100%;
}
.consoleIn {
animation: fadeInUp2 0.25s ease;
}
.consoleDown {
animation: fadeOutDown2 0.25s ease;
}
.console .card {
height: 648px;
}
.consoleBackground {
position: absolute;
pointer-events: none;
width: 100%;
height: 100%;
background-color: black;
opacity: 0.6;
}
.console-window {
width: 100%;
height: 100%;
background-color: black;
color: white;
font-family: monospace;
padding: 10px;
overflow-y: auto;
border: 2px solid var(--gray);
}
</style>
</head>
<body>
<div id="particles-js"></div>
<div class="container">
<?php require $_SERVER['DOCUMENT_ROOT'] . "/modules/header.php"; ?>
<div id="app" class="card mt-5">
<div class="card-header">Admin Panel</div>
<div class="card-body">
<h2>Dashboard</h2>
<div class="d-flex flex-row">
<div class="col-md-6 d-flex flex-column">
<div class="card w-100">
<div class="card-body">
<p>CPU load: <span id="cpu">0</span>/100%</p>
<p>RAM Usage: <span id="ram">0</span>/16 GB</p>
<div>
<canvas id="resourceChart" width="400" height="300"></canvas>
</div>
<script>
async function fetchData() {
const response = await fetch('stats');
const data = await response.json();
return data;
}
async function updateChart() {
const data = await fetchData();
const usedMemoryGB = (data.memory_usage.used / (1024 * 1024 * 1024)).toFixed(1);
const freeMemoryGB = (data.memory_usage.free / (1024 * 1024 * 1024)).toFixed(1);
resourceChart.data.labels.push('');
resourceChart.data.datasets[0].data.push(data.cpu_load);
resourceChart.data.datasets[1].data.push(usedMemoryGB);
document.getElementById('cpu').innerHTML = data.cpu_load;
document.getElementById('ram').innerHTML = usedMemoryGB;
if (resourceChart.data.labels.length > 100) {
resourceChart.data.labels.shift();
resourceChart.data.datasets[0].data.shift();
resourceChart.data.datasets[1].data.shift();
}
resourceChart.update();
}
const ctx = document.getElementById('resourceChart').getContext('2d');
const resourceChart = new Chart(ctx, {
type: 'line',
data: {
labels: [],
datasets: [
{
label: 'CPU Load (%)',
data: [],
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1,
yAxisID: 'y-axis-cpu',
fill: false
},
{
label: 'Used Memory (GB)',
data: [],
borderColor: 'rgba(255, 99, 132, 1)',
borderWidth: 1,
yAxisID: 'y-axis-memory',
fill: false
}
]
},
options: {
scales: {
x: {
display: true,
title: {
display: true,
text: 'Time (s)',
color: 'white'
},
ticks: {
color: 'white'
}
},
'y-axis-cpu': {
type: 'linear',
position: 'left',
title: {
display: true,
text: 'CPU Load (%)',
color: 'white'
},
ticks: {
color: 'white'
},
min: 0,
max: 100
},
'y-axis-memory': {
type: 'linear',
position: 'right',
title: {
display: true,
text: 'Used Memory (GB)',
color: 'white'
},
ticks: {
color: 'white'
},
min: 0,
max: 16
}
},
plugins: {
legend: {
labels: {
color: 'white'
}
}
},
layout: {
padding: {
top: 10,
bottom: 10,
left: 10,
right: 10
}
},
responsive: true,
maintainAspectRatio: false
}
});
setInterval(updateChart, 5000);
</script>
</div>
</div>
<div class="card w-100 mt-4">
<div class="card-body">
<form method="POST">
<div class="form-group">
<input type="hidden" name="type" value="ban">
<label for="username" class="col-form-label text-md-right"><small>Username</small></label>
<input type="text" name="username" placeholder="Username" class="form-control" required>
<label for="reason" class="col-form-label text-md-right"><small>Reason</small></label>
<input type="reason" name="reason" placeholder="Reason" class="form-control" required>
<div class="d-flex flex-column align-items-center">
<button type="submit" class="btn btn-danger mt-3">Ban</button>
</div>
</div>
</form>
</div>
</div>
<div class="card w-100 mt-4">
<div class="card-body">
<form method="POST">
<div class="form-group">
<input type="hidden" name="type" value="ipban">
<label for="username" class="col-form-label text-md-right"><small>Username</small></label>
<input type="text" name="username" placeholder="Username" class="form-control" required>
<label for="reason" class="col-form-label text-md-right"><small>Reason</small></label>
<input type="reason" name="reason" placeholder="Reason" class="form-control" required>
<div class="d-flex flex-column align-items-center">
<button type="submit" class="btn btn-danger mt-3">IP Ban</button>
</div>
</div>
</form>
</div>
</div>
<div class="card w-100 mt-4">
<div class="card-body">
<form method="POST">
<div class="form-group">
<input type="hidden" name="type" value="unban">
<label for="username" class="col-form-label text-md-right"><small>Username</small></label>
<input type="text" name="username" placeholder="Username" class="form-control" required>
<label for="reason" class="col-form-label text-md-right"><small>Reason</small></label>
<input type="reason" name="reason" placeholder="Reason" class="form-control" required>
<div class="d-flex flex-column align-items-center">
<button type="submit" class="btn btn-danger mt-3">Unban</button>
</div>
</div>
</form>
</div>
</div>
<div class="card w-100 mt-4">
<div class="card-body">
<form method="POST">
<div class="form-group">
<input type="hidden" name="type" value="delbyusr">
<label for="username" class="col-form-label text-md-right"><small>Username</small></label>
<input type="text" name="username" placeholder="Username" class="form-control" required>
<div class="d-flex flex-column align-items-center">
<button type="submit" class="btn btn-danger mt-3">Delete Servers</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-6 d-flex flex-column">
<div class="card w-100">
<div class="card-body">
<div class="d-flex justify-content-center text-center flex-column">
<?php
$stmt = $db->prepare("SELECT * FROM servers WHERE online = 1 ORDER BY created DESC");
$stmt->execute();
while($server = $stmt->fetch(PDO::FETCH_ASSOC)) {
$server['players'] = json_decode($server['players'], true); ?>
<div class="card mt-3 w-100" style="margin-left: auto;margin-right: auto;">
<div class="card-body">
<div class="d-flex flex-row">
<div>
<img src="/img/66134779.png" style="width: 75%;height: auto;">
</div>
<div style="min-width: 30%;">
<p class="m-0"><strong><?php echo htmlspecialchars($server['title']) ?></strong></p>
<p class="m-0">Client: <?php echo $server['client'] ?></p>
<p class="m-0"><?php echo ($server['hosting'] == 2) ? "Hosted by novetusserverlist.com" : "Self-hosted"; ?></p>
<p class="m-0"><?php echo ($server['hosting'] == 2) ? count($server['players']) : "?"; ?>/<?php echo $server['maxplayers'] ?> <span class="text-<?php echo ($server['online'] == 1) ? "success" : "danger"; ?>" id="status<?php echo $server['id'] ?>"><?php echo ($server['online'] == 1) ? "Online" : "Offline"; ?></span></p>
<?php if($server['hosting'] == 2) { ?>
<button class="btn btn-danger btn-sm mt-auto" id="close<?php echo $server['id'] ?>" onclick="stopServer(<?php echo $server['id'] ?>);"<?php echo ($server['online'] == 0) ? " disabled" : "" ?>>Stop</button><br>
<button class="btn btn-primary btn-sm mt-1" onclick="openConsole();updateCMD(<?php echo $server['id'] ?>);toggleCMD('console')">Open console</button>
<?php } ?>
</div>
<div class="mr-5" style="margin-left: auto;">
<p class="m-0">Created: <?php echo date("m/d/Y g:i A", strtotime($server['created'])) ?></p>
<p class="m-0">By: <?php echo htmlspecialchars($server['author']) ?></p>
</div>
</div>
</div>
</div>
<?php } ?>
<?php if(!$stmt->rowCount()) { ?>
No online servers.
<?php } ?>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<?php require $_SERVER['DOCUMENT_ROOT'] . "/modules/footer.php"; ?>
</div>
<div class="d-flex justify-content-center console" id="consoleCard" style="display: none;">
<div class="consoleBackground"></div>
<div class="card mt-5">
<div class="card-header">
Console <button class="btn btn-danger float-right" onclick="closeConsole();">X</button>
</div>
<div class="card-body">
<div id="consoleCMD" class="console-window"></div>
</div>
</div>
</div>
<script>
const console = document.getElementById("consoleCard");
const consoleWindow = document.getElementById("consoleCMD");
function openConsole() {
console.style.display = "";
console.style.zIndex = 999999;
console.classList.add("consoleIn");
$(window).scrollTop(0);
document.querySelector('body').style.overflow = "hidden";
console.querySelectorAll("*").forEach(element => {
if(element.id != "editForm") {
element.style.display = "";
}
});
}
function closeConsole() {
console.classList.remove("consoleIn");
console.classList.add("consoleDown");
document.querySelector('body').style.overflow = "";
setTimeout(function() {
console.style.display = "none";
console.style.zIndex = -999;
console.querySelectorAll("*").forEach(element => {
element.style.display = "none";
});
console.classList.remove("consoleDown");
}, 250)
}
function updateCMD(id) {
const xhr = new XMLHttpRequest();
xhr.open('GET', "/api/get_console?id=" + id, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
logToConsole(JSON.parse(xhr.responseText).message);
} else {
logToConsole('Error: ' + JSON.parse(xhr.responseText).message + ' ' + JSON.parse(xhr.responseText).status);
}
};
xhr.onerror = function() {
logToConsole('Network Error');
};
xhr.send();
}
function startServer(id) {
const xhr = new XMLHttpRequest();
openConsole();
logToConsole('<img src="/img/loading.gif" width="16" height="16">');
document.getElementById("open" + id).disabled = true;
xhr.open('GET', "/api/start_server?id=" + id, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
var msg = JSON.parse(xhr.responseText).message;
var msg = JSON.parse(msg);
var log = msg.stdout + msg.stderr;
logToConsole(nl2br(log));
document.getElementById("close" + id).disabled = false;
document.getElementById("status" + id).classList.remove("text-danger");
document.getElementById("status" + id).classList.add("text-success");
document.getElementById("status" + id).innerText = "Online";
} else {
document.getElementById("open" + id).disabled = false;
logToConsole('Error: ' + JSON.parse(xhr.responseText).message + ' ' + JSON.parse(xhr.responseText).status);
}
};
xhr.onerror = function() {
document.getElementById("open" + id).disabled = false;
logToConsole('Network Error');
};
xhr.send();
}
function stopServer(id) {
const xhr = new XMLHttpRequest();
openConsole();
logToConsole('<img src="/img/loading.gif" width="16" height="16">');
document.getElementById("close" + id).disabled = true;
xhr.open('GET', "/api/end_server?id=" + id, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
logToConsole(JSON.parse(xhr.responseText).message);
document.getElementById("close" + id).disabled = true;
document.getElementById("status" + id).classList.remove("text-success");
document.getElementById("status" + id).classList.add("text-danger");
document.getElementById("status" + id).innerText = "Offline";
} else {
document.getElementById("close" + id).disabled = false;
logToConsole('Error: ' + JSON.parse(xhr.responseText).message + ' ' + JSON.parse(xhr.responseText).status);
}
};
xhr.onerror = function() {
document.getElementById("close" + id).disabled = false;
logToConsole('Network Error');
};
xhr.send();
}
function nl2br(str) {
return str.replace(/(?:\r\n|\r|\n)/g, '<br>');
}
function logToConsole(text) {
consoleWindow.innerHTML = text;
consoleWindow.scrollTop = consoleWindow.scrollHeight;
}
console.style.zIndex = -999;
console.querySelectorAll("*").forEach(element => {
element.style.display = "none";
});
</script>
</body>
</html>