No changes
This commit is contained in:
parent
8680a02b13
commit
b6b398f5bf
17374 changed files with 2475441 additions and 0 deletions
320
ControlPanel/_website/adminserverlist.php
Normal file
320
ControlPanel/_website/adminserverlist.php
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
<?php
|
||||
// gameservers.world admin — mysqli only, bulk + per-row update, image base URL + small button
|
||||
|
||||
global $db;
|
||||
|
||||
/* === Configure your site base URL for image previews (MUST end with or without slash; we'll normalize) === */
|
||||
$SITE_BASE_URL = 'http://gameservers.world/';
|
||||
|
||||
/* include DB (must provide $db as mysqli) */
|
||||
$try = [
|
||||
__DIR__ . "db.php",
|
||||
(defined('ABSPATH') ? ABSPATH : $_SERVER['DOCUMENT_ROOT']) . "db.php",
|
||||
"db.php"
|
||||
];
|
||||
foreach ($try as $p) { if (empty($db) && is_readable($p)) include_once $p; }
|
||||
|
||||
/* show errors to WP admins during setup */
|
||||
if (function_exists('current_user_can') && current_user_can('manage_options')) { @ini_set('display_errors','1'); error_reporting(E_ALL); }
|
||||
|
||||
/* guards & helpers */
|
||||
if (!($db instanceof mysqli)) {
|
||||
echo '<div style="border:1px solid #c00;padding:10px;margin:10px 0;">
|
||||
<b>Admin panel error:</b> <code>$db</code> must be a <code>mysqli</code> connection (check panel/_db.php).
|
||||
</div>';
|
||||
return;
|
||||
}
|
||||
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
|
||||
function esc_mysqli($db, $v){ return $db->real_escape_string($v); }
|
||||
function fetch_all_assoc($db, $sql){
|
||||
$res = $db->query($sql);
|
||||
return $res ? $res->fetch_all(MYSQLI_ASSOC) : [];
|
||||
}
|
||||
function col_exists($db, $table, $col){
|
||||
$res = $db->query("SHOW COLUMNS FROM `$table` LIKE '".$db->real_escape_string($col)."'");
|
||||
return ($res && $res->num_rows > 0);
|
||||
}
|
||||
function parse_id_list($s){
|
||||
$tokens = preg_split('/\s+/', trim((string)$s));
|
||||
$out = [];
|
||||
foreach ($tokens as $t) {
|
||||
if ($t === '') continue;
|
||||
if (preg_match('/^\d+$/', $t)) $out[] = (int)$t;
|
||||
}
|
||||
return array_values(array_unique($out));
|
||||
}
|
||||
/* URL helpers for image preview */
|
||||
function is_abs_url($u){ return (bool)preg_match('~^(?:https?:)?//|^data:~i', (string)$u); }
|
||||
function join_base($base, $path){
|
||||
$base = rtrim((string)$base, '/');
|
||||
$path = ltrim((string)$path, '/');
|
||||
return $base !== '' ? $base.'/'.$path : $path;
|
||||
}
|
||||
|
||||
/* which column holds space-separated locations */
|
||||
$locationCol = col_exists($db, 'ogp_billing_services', 'remote_server_id') ? 'remote_server_id' :
|
||||
(col_exists($db, 'ogp_billing_services', 'remote_server') ? 'remote_server' : 'remote_server_id');
|
||||
|
||||
$flash = [];
|
||||
|
||||
/* A) Update global server location enable flags */
|
||||
if (isset($_POST['update_remote_servers'])) {
|
||||
$enabledIds = array_map('intval', $_POST['rs'] ?? []);
|
||||
$enabledSet = array_flip($enabledIds);
|
||||
$allIds = fetch_all_assoc($db, "SELECT remote_server_id FROM ogp_remote_servers");
|
||||
foreach ($allIds as $row) {
|
||||
$id = (int)$row['remote_server_id'];
|
||||
$e = isset($enabledSet[$id]) ? 1 : 0;
|
||||
$db->query("UPDATE ogp_remote_servers SET enabled={$e} WHERE remote_server_id={$id}");
|
||||
}
|
||||
$flash[] = "Server locations updated.";
|
||||
}
|
||||
|
||||
/* helper: update one service row from posted array */
|
||||
function update_service_row(mysqli $db, string $locationCol, int $sid, array $svc){
|
||||
$name = esc_mysqli($db, trim($svc['service_name'] ?? ''));
|
||||
$price = esc_mysqli($db, trim($svc['price_monthly'] ?? '0.00'));
|
||||
$img = esc_mysqli($db, trim($svc['img_url'] ?? ''));
|
||||
$en = !empty($svc['enabled']) ? 1 : 0;
|
||||
|
||||
$minSlots = max(1, (int)($svc['slot_min_qty'] ?? 1));
|
||||
$maxSlots = max($minSlots, (int)($svc['slot_max_qty'] ?? $minSlots));
|
||||
|
||||
$selected = [];
|
||||
if (!empty($svc['locations']) && is_array($svc['locations'])) {
|
||||
$selected = array_map('intval', $svc['locations']);
|
||||
$selected = array_values(array_unique($selected));
|
||||
}
|
||||
$primary = isset($svc['primary_location']) ? (int)$svc['primary_location'] : 0;
|
||||
if ($primary && in_array($primary, $selected, true)) {
|
||||
$selected = array_values(array_diff($selected, [$primary]));
|
||||
array_unshift($selected, $primary);
|
||||
}
|
||||
$locList = implode(' ', $selected);
|
||||
$locListEsc = esc_mysqli($db, $locList);
|
||||
|
||||
$sql = "UPDATE ogp_billing_services
|
||||
SET service_name='{$name}',
|
||||
`{$locationCol}`='{$locListEsc}',
|
||||
slot_min_qty={$minSlots},
|
||||
slot_max_qty={$maxSlots},
|
||||
price_monthly='{$price}',
|
||||
img_url='{$img}',
|
||||
enabled={$en}
|
||||
WHERE service_id={$sid}";
|
||||
$db->query($sql);
|
||||
}
|
||||
|
||||
/* B1) PER-ROW UPDATE */
|
||||
if (isset($_POST['update_single']) && isset($_POST['service']) && is_array($_POST['service'])) {
|
||||
$sid = (int)$_POST['update_single'];
|
||||
if (isset($_POST['service'][$sid])) {
|
||||
update_service_row($db, $locationCol, $sid, $_POST['service'][$sid]);
|
||||
$flash[] = "Service #{$sid} updated.";
|
||||
}
|
||||
}
|
||||
|
||||
/* B2) BULK UPDATE (single button at bottom) */
|
||||
if (isset($_POST['bulk_update']) && !empty($_POST['service']) && is_array($_POST['service'])) {
|
||||
foreach ($_POST['service'] as $sid => $svc) {
|
||||
update_service_row($db, $locationCol, (int)$sid, (array)$svc);
|
||||
}
|
||||
$flash[] = "All edited services have been updated.";
|
||||
}
|
||||
|
||||
/* C) Remove a service (separate small form) */
|
||||
if (isset($_POST['remove_service'], $_POST['service_id_remove'])) {
|
||||
$sid = (int)$_POST['service_id_remove'];
|
||||
$db->query("DELETE FROM ogp_billing_services WHERE service_id={$sid}");
|
||||
$flash[] = "Service #{$sid} removed.";
|
||||
}
|
||||
|
||||
/* fetch data for UI */
|
||||
$remoteServers = fetch_all_assoc($db, "SELECT remote_server_id, remote_server_name, enabled FROM ogp_remote_servers ORDER BY remote_server_name");
|
||||
$services = fetch_all_assoc($db, "SELECT service_id, service_name, `{$locationCol}` AS locs, slot_min_qty, slot_max_qty, price_monthly, img_url, enabled FROM ogp_billing_services ORDER BY service_name");
|
||||
?>
|
||||
|
||||
<?php if ($flash): ?>
|
||||
<div style="padding:8px;border:1px solid #ccc;margin:10px 0;"><?php foreach($flash as $m) echo "<div>".h($m)."</div>"; ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<h2>Enable/Disable Server Locations (Global)</h2>
|
||||
<form method="post" action="">
|
||||
<input type="hidden" name="update_remote_servers" value="1">
|
||||
<div style="display:flex;flex-wrap:wrap;gap:10px;">
|
||||
<?php foreach ($remoteServers as $rs): ?>
|
||||
<label style="border:1px solid #ddd;border-radius:6px;padding:6px 10px;min-width:240px;">
|
||||
<input type="checkbox" name="rs[]" value="<?php echo (int)$rs['remote_server_id']; ?>" <?php echo ((int)$rs['enabled']===1?'checked':''); ?>>
|
||||
<b><?php echo h($rs['remote_server_name']); ?></b>
|
||||
<small style="color:#666;">(ID: <?php echo (int)$rs['remote_server_id']; ?>)</small>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<div style="margin-top:10px;"><button type="submit">Update Enabled Servers</button></div>
|
||||
</form>
|
||||
|
||||
<hr style="margin:20px 0;">
|
||||
|
||||
<h2>Current Services</h2>
|
||||
<?php if (!$services): ?>
|
||||
<p>No services found.</p>
|
||||
<?php else: ?>
|
||||
|
||||
<!-- SINGLE BULK FORM FOR ALL SERVICES -->
|
||||
<form method="post" action="">
|
||||
|
||||
<table class="center" style="text-align:center;width:100%;border-collapse:collapse;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="border-bottom:1px solid #ddd;padding:6px;">Enabled</th>
|
||||
<th style="border-bottom:1px solid #ddd;padding:6px;">Service Name <small style="color:#777;">(ID below)</small></th>
|
||||
<th style="border-bottom:1px solid #ddd;padding:6px;">Min Slots</th>
|
||||
<th style="border-bottom:1px solid #ddd;padding:6px;">Max Slots</th>
|
||||
<th style="border-bottom:1px solid #ddd;padding:6px;">Price (Monthly)</th>
|
||||
<th style="border-bottom:1px solid #ddd;padding:6px;">Thumbnail URL</th>
|
||||
<th style="border-bottom:1px solid #ddd;padding:6px;">Preview</th>
|
||||
<th style="border-bottom:1px solid #ddd;padding:6px;">Update Row</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($services as $row): ?>
|
||||
<?php
|
||||
$sid = (int)$row['service_id'];
|
||||
$selected = parse_id_list($row['locs'] ?? '');
|
||||
$primary = $selected[0] ?? 0; // first ID is "primary"
|
||||
$selSet = array_flip($selected);
|
||||
$imgUrl = trim((string)$row['img_url']);
|
||||
$displayUrl = '';
|
||||
if ($imgUrl !== '') {
|
||||
$displayUrl = is_abs_url($imgUrl) ? $imgUrl : join_base($SITE_BASE_URL, $imgUrl);
|
||||
}
|
||||
?>
|
||||
|
||||
<!-- MAIN ROW (no bottom border) -->
|
||||
<tr>
|
||||
<!-- Enabled first -->
|
||||
<td style="padding:6px;">
|
||||
<input type="hidden" name="service[<?php echo $sid; ?>][enabled]" value="0">
|
||||
<input type="checkbox" name="service[<?php echo $sid; ?>][enabled]" value="1" <?php echo ((int)$row['enabled']===1?'checked':''); ?>>
|
||||
</td>
|
||||
|
||||
<!-- Service name (with tiny ID under it) -->
|
||||
<td style="padding:6px; text-align:left;">
|
||||
<input type="text" name="service[<?php echo $sid; ?>][service_name]" value="<?php echo h($row['service_name']); ?>" style="min-width:260px;">
|
||||
<div style="color:#777; font-size:12px; margin-top:2px;">ID: <?php echo $sid; ?></div>
|
||||
</td>
|
||||
|
||||
<td style="padding:6px;">
|
||||
<input type="number" name="service[<?php echo $sid; ?>][slot_min_qty]" value="<?php echo (int)$row['slot_min_qty']; ?>" min="1" step="1" style="width:90px;">
|
||||
</td>
|
||||
|
||||
<td style="padding:6px;">
|
||||
<input type="number" name="service[<?php echo $sid; ?>][slot_max_qty]" value="<?php echo (int)$row['slot_max_qty']; ?>" min="1" step="1" style="width:90px;">
|
||||
</td>
|
||||
|
||||
<td style="padding:6px;">
|
||||
<input type="text" name="service[<?php echo $sid; ?>][price_monthly]" value="<?php echo h($row['price_monthly']); ?>" size="8">
|
||||
</td>
|
||||
|
||||
<!-- Thumbnail URL input -->
|
||||
<td style="padding:6px; vertical-align:top;">
|
||||
<input type="text" name="service[<?php echo $sid; ?>][img_url]" value="<?php echo h($row['img_url']); ?>" style="min-width:240px;">
|
||||
</td>
|
||||
|
||||
<!-- Preview (uses BASE + relative path) -->
|
||||
<td style="padding:6px; vertical-align:top;">
|
||||
<?php if ($displayUrl !== ''): ?>
|
||||
<img src="<?php echo h($displayUrl); ?>" alt="preview" loading="lazy"
|
||||
style="max-height:48px; max-width:120px; border:1px solid #eee; display:block;"
|
||||
onerror="this.style.display='none'">
|
||||
<?php else: ?>
|
||||
<span style="color:#aaa;">(no image)</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
|
||||
<!-- Per-row Update (smaller) -->
|
||||
<td style="padding:6px;">
|
||||
<button type="submit" name="update_single" value="<?php echo $sid; ?>"
|
||||
style="padding:3px 8px; font-size:12px;">Update Row</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- LOCATIONS ROW (single bottom divider) -->
|
||||
<tr>
|
||||
<td colspan="8" style="border-bottom:1px solid #f0f0f0; padding:8px 6px; text-align:left;">
|
||||
<div class="locs-box" data-sid="<?php echo $sid; ?>" style="display:flex; flex-wrap:wrap; gap:8px;">
|
||||
<?php foreach ($remoteServers as $rs): ?>
|
||||
<?php
|
||||
$rid = (int)$rs['remote_server_id'];
|
||||
$isChecked = isset($selSet[$rid]);
|
||||
$isPrimary = ($primary === $rid);
|
||||
?>
|
||||
<label style="border:1px solid #eee;border-radius:6px;padding:6px 8px; display:inline-flex; align-items:center;">
|
||||
<input type="checkbox" class="locchk" data-sid="<?php echo $sid; ?>"
|
||||
name="service[<?php echo $sid; ?>][locations][]" value="<?php echo $rid; ?>"
|
||||
<?php echo $isChecked ? 'checked' : ''; ?> style="margin-right:6px;">
|
||||
<?php echo h($rs['remote_server_name']); ?> (<?php echo $rid; ?>)
|
||||
<span style="margin-left:10px;">
|
||||
<input type="radio" class="locprim" data-sid="<?php echo $sid; ?>"
|
||||
name="service[<?php echo $sid; ?>][primary_location]" value="<?php echo $rid; ?>"
|
||||
<?php echo $isPrimary ? 'checked' : ''; ?> <?php echo $isChecked ? '' : 'disabled'; ?>>
|
||||
<small>Primary</small>
|
||||
</span>
|
||||
<?php if ((int)$rs['enabled'] === 0): ?>
|
||||
<small style="color:#a00; margin-left:8px;">[Globally disabled]</small>
|
||||
<?php endif; ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div style="margin-top:14px; text-align:right;">
|
||||
<button type="submit" name="bulk_update" value="1">Update All</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<h3 style="margin-top:20px;">Remove a Service</h3>
|
||||
<form method="post" action="" style="display:flex;gap:8px;align-items:center;">
|
||||
<input type="hidden" name="remove_service" value="1">
|
||||
<select name="service_id_remove">
|
||||
<?php foreach ($services as $s): ?>
|
||||
<option value="<?php echo (int)$s['service_id']; ?>">
|
||||
<?php echo h($s['service_name']); ?> (ID: <?php echo (int)$s['service_id']; ?>)
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<button type="submit" onclick="return confirm('Remove this service? This cannot be undone.')">Remove</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- JS: Per-row: enable/disable Primary radios based on whether that location is checked -->
|
||||
<script>
|
||||
document.querySelectorAll('.locs-box').forEach(function(box){
|
||||
const sid = box.getAttribute('data-sid');
|
||||
const checks = box.querySelectorAll('input.locchk[data-sid="'+sid+'"]');
|
||||
|
||||
function refreshRadios() {
|
||||
checks.forEach(function(chk){
|
||||
const rid = chk.value;
|
||||
const rad = box.querySelector('input.locprim[data-sid="'+sid+'"][value="'+rid+'"]');
|
||||
if (!rad) return;
|
||||
if (chk.checked) {
|
||||
rad.disabled = false;
|
||||
} else {
|
||||
if (rad.checked) rad.checked = false;
|
||||
rad.disabled = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
checks.forEach(chk => chk.addEventListener('change', refreshRadios));
|
||||
refreshRadios();
|
||||
});
|
||||
</script>
|
||||
|
||||
321
ControlPanel/_website/ai.php
Normal file
321
ControlPanel/_website/ai.php
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
<?php
|
||||
/***********************
|
||||
* Assistant Chat (Full History) — PHP + cURL
|
||||
* - Persistent thread in session
|
||||
* - Full history render with Question / Answer labels
|
||||
* - SSL verification disabled (your hosting constraint)
|
||||
* - Citations: filename + page (when available)
|
||||
***********************/
|
||||
|
||||
// Debug (disable on production)
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
/* ------------------- CONFIG ------------------- */
|
||||
$OPENAI_API_KEY = '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';
|
||||
|
||||
$ASSISTANT_ID = 'asst_RAhtGzcy6higJeMwomZSqVjM'; // <-- set to your existing assistant
|
||||
$OPENAI_BASE_URL = 'https://api.openai.com/v1';
|
||||
$OPENAI_BETA_HDR = 'assistants=v2'; // required for Assistants v2
|
||||
$REQUEST_TIMEOUT = 30; // seconds for cURL calls
|
||||
$RUN_POLL_DELAY = 500000; // microseconds between run polls (0.5s)
|
||||
$RUN_POLL_MAX = 40; // max polls (~20s total); adjust as needed
|
||||
/* ---------------------------------------------- */
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
if (!isset($_SESSION['thread_id'])) {
|
||||
$_SESSION['thread_id'] = null;
|
||||
}
|
||||
|
||||
/** HTML escape helper */
|
||||
function h($v) { return htmlspecialchars((string)$v, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
|
||||
|
||||
/** Low-level OpenAI request helper */
|
||||
function openai_request($method, $endpoint, $payload = null, $query = []) {
|
||||
global $OPENAI_API_KEY;
|
||||
$url = "https://api.openai.com/v1" . $endpoint;
|
||||
if (!empty($query)) $url .= '?' . http_build_query($query);
|
||||
|
||||
$headers = [
|
||||
"Content-Type: application/json",
|
||||
"Authorization: Bearer {$OPENAI_API_KEY}",
|
||||
"OpenAI-Beta: assistants=v2"
|
||||
];
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
// Host requires SSL verification disabled
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
|
||||
if (!is_null($payload)) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
|
||||
|
||||
$resp = curl_exec($ch);
|
||||
if ($resp === false) {
|
||||
$err = curl_error($ch);
|
||||
curl_close($ch);
|
||||
throw new RuntimeException("cURL error: {$err}");
|
||||
}
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
$data = json_decode($resp, true);
|
||||
if ($code >= 400) {
|
||||
$msg = isset($data['error']['message']) ? $data['error']['message'] : 'Unknown API error';
|
||||
throw new RuntimeException("OpenAI API error ({$code}): {$msg}");
|
||||
}
|
||||
return is_array($data) ? $data : [];
|
||||
}
|
||||
|
||||
/** Create or reuse a per-visitor thread */
|
||||
function ensure_thread_id() {
|
||||
if (!empty($_SESSION['thread_id'])) return $_SESSION['thread_id'];
|
||||
$created = openai_request('POST', '/threads', ['metadata' => ['site' => $_SERVER['HTTP_HOST'] ?? 'unknown']]);
|
||||
$tid = $created['id'] ?? null;
|
||||
if (!$tid) throw new RuntimeException('Failed to create thread.');
|
||||
$_SESSION['thread_id'] = $tid;
|
||||
return $tid;
|
||||
}
|
||||
|
||||
/** Add a user message */
|
||||
function add_user_message($thread_id, $text) {
|
||||
openai_request('POST', "/threads/{$thread_id}/messages", [
|
||||
'role' => 'user',
|
||||
'content' => $text,
|
||||
]);
|
||||
}
|
||||
|
||||
/** Start a run */
|
||||
function start_run($thread_id, $assistant_id) {
|
||||
$run = openai_request('POST', "/threads/{$thread_id}/runs", [
|
||||
'assistant_id' => $assistant_id,
|
||||
]);
|
||||
$run_id = $run['id'] ?? null;
|
||||
if (!$run_id) throw new RuntimeException('Failed to start run.');
|
||||
return $run_id;
|
||||
}
|
||||
|
||||
/** Wait for completion (or fail/timeout) */
|
||||
function wait_for_run($thread_id, $run_id, $max_tries, $delay_us) {
|
||||
$terminal = ['completed', 'failed', 'requires_action', 'cancelled', 'expired'];
|
||||
for ($i = 0; $i < $max_tries; $i++) {
|
||||
usleep($delay_us);
|
||||
$run = openai_request('GET', "/threads/{$thread_id}/runs/{$run_id}");
|
||||
$status = $run['status'] ?? '';
|
||||
if (in_array($status, $terminal, true)) return $run;
|
||||
}
|
||||
return ['status' => 'timeout'];
|
||||
}
|
||||
|
||||
/** Cache of file_id => filename (per request) */
|
||||
$_FILE_NAME_CACHE = [];
|
||||
|
||||
/** Resolve file name from file_id (API returns "filename" or sometimes "display_name") */
|
||||
function get_file_name_by_id($file_id) {
|
||||
global $_FILE_NAME_CACHE;
|
||||
if (isset($_FILE_NAME_CACHE[$file_id])) return $_FILE_NAME_CACHE[$file_id];
|
||||
$file = openai_request('GET', "/files/{$file_id}");
|
||||
$name = $file['filename'] ?? ($file['display_name'] ?? ($file['name'] ?? $file_id));
|
||||
$_FILE_NAME_CACHE[$file_id] = $name;
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract message text + citations (filename + page if available).
|
||||
* Returns an array of entries: ['role' => 'user|assistant', 'text' => '...', 'refs' => [['filename'=>'','page'=>'','file_id'=>'']]]
|
||||
*/
|
||||
function normalize_messages($messages) {
|
||||
$out = [];
|
||||
if (empty($messages['data']) || !is_array($messages['data'])) return $out;
|
||||
|
||||
// The API returns newest first by default if not specifying; we request 'asc' in fetch.
|
||||
foreach ($messages['data'] as $m) {
|
||||
$role = $m['role'] ?? '';
|
||||
if (!in_array($role, ['user', 'assistant', 'system'], true)) continue;
|
||||
|
||||
if (empty($m['content']) || !is_array($m['content'])) continue;
|
||||
|
||||
$all_text = [];
|
||||
$refs = [];
|
||||
foreach ($m['content'] as $part) {
|
||||
if (($part['type'] ?? '') === 'text' && !empty($part['text']['value'])) {
|
||||
$all_text[] = $part['text']['value'];
|
||||
|
||||
// Parse annotations for citations (file_citation)
|
||||
$anns = $part['text']['annotations'] ?? [];
|
||||
if (is_array($anns)) {
|
||||
foreach ($anns as $ann) {
|
||||
if (($ann['type'] ?? '') === 'file_citation' && !empty($ann['file_citation']['file_id'])) {
|
||||
$fid = $ann['file_citation']['file_id'];
|
||||
$page = null;
|
||||
|
||||
// Page can appear under different shapes depending on backend. Try common keys:
|
||||
if (isset($ann['file_citation']['page'])) {
|
||||
$page = $ann['file_citation']['page'];
|
||||
} elseif (isset($ann['file_citation']['page_range']) && is_array($ann['file_citation']['page_range'])) {
|
||||
// Example: ['start' => 5, 'end' => 6]
|
||||
$start = $ann['file_citation']['page_range']['start'] ?? null;
|
||||
$end = $ann['file_citation']['page_range']['end'] ?? null;
|
||||
if ($start && $end && $start !== $end) $page = "{$start}-{$end}";
|
||||
elseif ($start) $page = (string)$start;
|
||||
}
|
||||
// Fetch filename
|
||||
try {
|
||||
$filename = get_file_name_by_id($fid);
|
||||
} catch (Throwable $e) {
|
||||
$filename = $fid;
|
||||
}
|
||||
$refs[] = [
|
||||
'file_id' => $fid,
|
||||
'filename' => $filename,
|
||||
'page' => $page ?? 'n/a',
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($all_text)) {
|
||||
$out[] = [
|
||||
'role' => $role,
|
||||
'text' => implode("\n", $all_text),
|
||||
'refs' => $refs,
|
||||
];
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/** Fetch conversation (ascending) */
|
||||
function fetch_history($thread_id) {
|
||||
$messages = openai_request('GET', "/threads/{$thread_id}/messages", null, ['order' => 'asc', 'limit' => 50]);
|
||||
return normalize_messages($messages);
|
||||
}
|
||||
|
||||
/* ------------------- HANDLE POST ------------------- */
|
||||
$error = null;
|
||||
$history = [];
|
||||
|
||||
try {
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (!empty($_POST['reset_thread'])) {
|
||||
$_SESSION['thread_id'] = null;
|
||||
} elseif (isset($_POST['user_input'])) {
|
||||
$user_text = trim((string)$_POST['user_input']);
|
||||
if ($user_text !== '') {
|
||||
$thread_id = ensure_thread_id();
|
||||
add_user_message($thread_id, $user_text);
|
||||
$run_id = start_run($thread_id, $ASSISTANT_ID);
|
||||
$run = wait_for_run($thread_id, $run_id, $POLL_MAX_TRIES, $POLL_DELAY_US);
|
||||
|
||||
if (($run['status'] ?? '') === 'failed') {
|
||||
$error = 'Assistant run failed.';
|
||||
} elseif (($run['status'] ?? '') === 'requires_action') {
|
||||
// If you later support tool calls, handle them here then submit outputs.
|
||||
} elseif (($run['status'] ?? '') === 'timeout') {
|
||||
$error = 'Assistant timed out. Please try again.';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_SESSION['thread_id'])) {
|
||||
$history = fetch_history($_SESSION['thread_id']);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
?>
|
||||
<!-- UI -->
|
||||
<div style="max-width:760px; margin:20px auto; font-family:Arial, sans-serif;">
|
||||
<h3>Site Assistant</h3>
|
||||
<p>Type a question below. Press <b>Enter</b> to send, <b>Shift+Enter</b> for a new line.</p>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div style="margin:10px 0; padding:8px; border:1px solid #c00; border-radius:6px;">
|
||||
<strong>Error:</strong> <?php echo h($error); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($_SESSION['thread_id'])): ?>
|
||||
<div style="margin:4px 0; font-size:12px;">Thread: <?php echo h($_SESSION['thread_id']); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form id="chat-form" method="post" style="margin:12px 0;">
|
||||
<textarea id="chat-input" name="user_input" rows="3" style="width:100%; padding:6px;" placeholder="Ask your question..."></textarea>
|
||||
<div style="margin-top:8px; display:flex; gap:8px;">
|
||||
<button type="submit">Send</button>
|
||||
<button type="submit" name="reset_thread" value="1">Reset Conversation</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php if (!empty($history) && is_array($history)): ?>
|
||||
<div style="margin-top:16px; padding:10px; border:1px solid #ccc; border-radius:8px;">
|
||||
<?php foreach ($history as $msg):
|
||||
// Label mapping: user => Question, assistant => Answer, system => (optional)
|
||||
$role = $msg['role'] ?? 'assistant';
|
||||
if ($role === 'user') $label = 'Question';
|
||||
elseif ($role === 'assistant') $label = 'Answer';
|
||||
else $label = ucfirst($role); // e.g., System
|
||||
$text = str_replace("\r\n", "\n", $msg['text'] ?? '');
|
||||
$refs = $msg['refs'] ?? [];
|
||||
?>
|
||||
<div style="margin-bottom:14px;">
|
||||
<div style="font-weight:bold;"><?php echo h($label); ?></div>
|
||||
<div style="white-space:pre-wrap;"><?php echo nl2br(h($text)); ?></div>
|
||||
|
||||
<?php if (!empty($refs)): ?>
|
||||
<div style="margin-top:6px; font-size:12px;">
|
||||
<em>References:</em>
|
||||
<ul style="margin:6px 0 0 18px; padding:0;">
|
||||
<?php foreach ($refs as $r):
|
||||
$fname = $r['filename'] ?? 'file';
|
||||
$page = $r['page'] ?? 'n/a';
|
||||
// If you have your own document links, replace '#' with a real URL.
|
||||
?>
|
||||
<li>
|
||||
<a href="#" title="file_id: <?php echo h($r['file_id']); ?>">
|
||||
<?php echo h($fname); ?> — page <?php echo h($page); ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div style="margin-top:10px; color:#666;">No messages yet.</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div style="margin-top:10px; font-size:12px; color:#555;">
|
||||
Conversation persists until you click “Reset Conversation”.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit on Enter (Shift+Enter = newline) -->
|
||||
<script>
|
||||
(function(){
|
||||
var form = document.getElementById('chat-form');
|
||||
var input = document.getElementById('chat-input');
|
||||
|
||||
input.addEventListener('keydown', function(e){
|
||||
if (e.key === 'Enter') {
|
||||
if (!e.shiftKey) {
|
||||
e.preventDefault();
|
||||
form.submit();
|
||||
}
|
||||
// if Shift+Enter, allow newline
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
258
ControlPanel/_website/cart.php
Normal file
258
ControlPanel/_website/cart.php
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
global $db, $view, $settings;
|
||||
|
||||
include "panel/_db.php";
|
||||
|
||||
|
||||
$user_id=$_SESSION['user_id'] ?? 0;
|
||||
$user_id = 186; // For testing purposes, set a default user ID
|
||||
|
||||
if ($user_id <= 0) {
|
||||
echo "<center><h4>Please login to view your cart</h4></center>";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_single'])) {
|
||||
$order_id = intval($_POST['delete_single']);
|
||||
if ($order_id > 0) {
|
||||
// First, check if the status is 'renew'
|
||||
$stmt = $db->prepare("SELECT status FROM ogp_billing_orders WHERE order_id = ? AND user_id = ?");
|
||||
$stmt->bind_param("ii", $order_id, $user_id);
|
||||
$stmt->execute();
|
||||
$stmt->bind_result($status);
|
||||
if ($stmt->fetch() && strtolower($status) === 'renew') {
|
||||
$stmt->close();
|
||||
// Set status to 'expired' if currently 'renew'
|
||||
$update = $db->prepare("UPDATE ogp_billing_orders SET status = 'expired' WHERE order_id = ? AND user_id = ?");
|
||||
$update->bind_param("ii", $order_id, $user_id);
|
||||
$update->execute();
|
||||
$update->close();
|
||||
} else {
|
||||
$stmt->close();
|
||||
// Otherwise, delete the order
|
||||
$delete = $db->prepare("DELETE FROM ogp_billing_orders WHERE order_id = ? AND user_id = ?");
|
||||
$delete->bind_param("ii", $order_id, $user_id);
|
||||
$delete->execute();
|
||||
$delete->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($db){
|
||||
$carts = $db->query("SELECT * FROM ogp_billing_orders AS cart
|
||||
WHERE (status = 'in-cart' OR status = 'renew') AND user_id = " . $user_id . " ORDER BY order_id ASC");
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div style="width:100%; max-width:1000px; margin:auto; padding:1rem; background-color:#ffffff; border-radius:0.75rem; box-shadow:0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05);">
|
||||
<h2 style="font-size:1.5rem; font-weight:bold; color:#1f2937; margin-bottom:1.5rem; text-align:center;">Your Cart</h2>
|
||||
|
||||
<!--
|
||||
This is our cart form just for display and deletion. There is a different form below that has the paypal button and fills in all the hidden fields
|
||||
-->
|
||||
|
||||
<table style="border-collapse:separate; border-spacing:0; width:100%; color:#000000;">
|
||||
<thead style="background-color:#f9fafb;">
|
||||
<tr>
|
||||
<th style="padding:1rem 1.5rem; text-align:center; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;"></th>
|
||||
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Server ID</th>
|
||||
|
||||
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Game Name</th>
|
||||
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Location</th>
|
||||
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Max Players</th>
|
||||
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Price per Player</th>
|
||||
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Months</th>
|
||||
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody style="background-color:#ffffff;">
|
||||
<?php
|
||||
$grandTotal = 0; // Initialize grand total variable
|
||||
|
||||
if (isset($carts) && $carts instanceof mysqli_result && $carts->num_rows > 0) {
|
||||
while ($row = $carts->fetch_assoc()) {
|
||||
?>
|
||||
<tr data-cart-id="<?php echo htmlspecialchars($row['order_id']); ?>" style="color:#000000;">
|
||||
<td style="padding:1rem 1.5rem; text-align:center; border-bottom:1px solid #e5e7eb;">
|
||||
<form method="post" action="" style="margin:0; display:inline;">
|
||||
<button type="submit" name="delete_single" value="<?php echo htmlspecialchars($row['order_id']); ?>" style="background-color:#ef4444; color:#fff; border:none; border-radius:0.25rem; width:2rem; height:2rem; font-weight:bold; cursor:pointer; display:flex; align-items:center; justify-content:center;">
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;"><?php echo htmlspecialchars($row['home_id']); ?></td>
|
||||
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;"><?php echo htmlspecialchars($row['home_name']); ?></td>
|
||||
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;"><?php echo htmlspecialchars($row['ip']); ?></td>
|
||||
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;"><?php echo htmlspecialchars($row['max_players']); ?></td>
|
||||
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;">$<?php echo number_format($row['price'], 2); ?></td>
|
||||
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;"><?php echo htmlspecialchars($row['qty']); ?></td>
|
||||
<?php $rowtotal = $row['price'] * $row['qty'] * $row['max_players'];?>
|
||||
<?php $grandTotal += $rowtotal; // Add to grand total ?>
|
||||
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;">$<?php echo number_format($rowtotal, 2); ?></td>
|
||||
|
||||
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Add total row
|
||||
?>
|
||||
<tr style="background-color:#f9fafb; font-weight:bold;">
|
||||
<td colspan="7" style="padding:1rem 1.5rem; text-align:right; border-top:2px solid #374151; font-weight:600; color:#374151;">
|
||||
Cart Total:
|
||||
</td>
|
||||
<td style="padding:1rem 1.5rem; text-align:left; border-top:2px solid #374151; font-weight:600; color:#374151; font-size:1.1rem;">
|
||||
$<?php echo number_format($grandTotal, 2); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
} else {
|
||||
// Display a message if no cart items are found
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="7" style="text-align:center; padding:1rem; color:#6b7280;">No items in your cart.</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<?php
|
||||
// These must already exist earlier in your cart page:
|
||||
// $grandTotal (number) e.g., 24.49
|
||||
// $invoice (array) e.g., [['serverID'=>'srv123','amount'=>9.99], ['serverID'=>'srv999','amount'=>14.50]]
|
||||
|
||||
// --- Sanity + normalization ---
|
||||
if (!isset($grandTotal) || !is_numeric($grandTotal)) {
|
||||
$grandTotal = 0.00;
|
||||
}
|
||||
if (!isset($invoice) || !is_array($invoice)) {
|
||||
$invoice = [];
|
||||
}
|
||||
$currency = 'USD';
|
||||
$amount = number_format((float)$grandTotal, 2, '.', '');
|
||||
$lineItems = [];
|
||||
|
||||
// Build PayPal-friendly items array (name, unit_amount, quantity, sku)
|
||||
foreach ($invoice as $i) {
|
||||
$sid = isset($i['serverID']) ? (string)$i['serverID'] : 'unknown';
|
||||
$amt = isset($i['amount']) && is_numeric($i['amount']) ? number_format((float)$i['amount'], 2, '.', '') : '0.00';
|
||||
$lineItems[] = [
|
||||
'name' => "Server $sid",
|
||||
'quantity' => '1',
|
||||
'unit_amount' => ['currency_code' => $currency, 'value' => $amt],
|
||||
'sku' => $sid
|
||||
];
|
||||
}
|
||||
|
||||
// Single overall invoice id for the order
|
||||
$invoiceId = 'INV-' . date('Ymd-His') . '-' . bin2hex(random_bytes(3));
|
||||
|
||||
// A short custom reference derived from your line items (<= 127 chars for PayPal)
|
||||
$customHash = substr(strtoupper(sha1(json_encode($invoice))), 0, 16);
|
||||
$customId = "INVREF-$customHash";
|
||||
|
||||
// Text on the PayPal side
|
||||
$description = 'Game server order (' . count($lineItems) . ' item' . (count($lineItems)===1?'': 's') . ')';
|
||||
|
||||
// URLs
|
||||
$siteBase = 'https://panel.iaregamer.com';
|
||||
$returnUrl = $siteBase . '/paypal/return.php?invoice=' . urlencode($invoiceId);
|
||||
$cancelUrl = $siteBase . '/paypal/return.php?invoice=' . urlencode($invoiceId) . '&cancel=1';
|
||||
|
||||
// API base (relative)
|
||||
$apiBase = '/paypal/api';
|
||||
?>
|
||||
<!-- PayPal JS SDK (Sandbox). Use LIVE client-id when going live. -->
|
||||
<script src="https://www.paypal.com/sdk/js?client-id=AfvY_C2zA_hTHxHq7TIhtOeub4xBdySYrt_Hjj3d_WYQwjWI9NfOAVOTeResx2rgZ_nP5tOoxQSAHw8c¤cy=USD&intent=capture"></script>
|
||||
|
||||
<div id="paypal-button-container"></div>
|
||||
<div id="pp-status" style="margin-top:12px;font:14px system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;"></div>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
const statusEl = document.getElementById('pp-status');
|
||||
|
||||
// Values from PHP
|
||||
const amount = "<?= $amount ?>";
|
||||
const currency = "<?= $currency ?>";
|
||||
const invoice_id = "<?= $invoiceId ?>";
|
||||
const custom_id = "<?= $customId ?>";
|
||||
const description = "<?= htmlspecialchars($description, ENT_QUOTES) ?>";
|
||||
const return_url = "<?= $returnUrl ?>";
|
||||
const cancel_url = "<?= $cancelUrl ?>";
|
||||
|
||||
// Line items (serverID + per-item amount) for your records and webhook correlation
|
||||
const line_invoices = <?php echo json_encode($invoice, JSON_UNESCAPED_SLASHES); ?>;
|
||||
|
||||
// PayPal "items" for purchase_units (shows on PayPal + returns in webhook under purchase_units)
|
||||
const items = <?php echo json_encode($lineItems, JSON_UNESCAPED_SLASHES); ?>;
|
||||
|
||||
function setStatus(msg){ if(statusEl) statusEl.textContent = msg; }
|
||||
|
||||
paypal.Buttons({
|
||||
createOrder: function() {
|
||||
setStatus('Creating order…');
|
||||
return fetch("<?= $apiBase ?>/create_order.php", {
|
||||
method: "POST",
|
||||
headers: {"Content-Type":"application/json"},
|
||||
body: JSON.stringify({
|
||||
amount, currency, invoice_id, custom_id, description,
|
||||
return_url, cancel_url,
|
||||
// The next two are for your server to include:
|
||||
items, // PayPal purchase_units[0].items
|
||||
line_invoices // your raw cart detail, persisted in your DB if you choose
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (!data.id) { throw new Error(data.error || 'No order id'); }
|
||||
setStatus('Order created.');
|
||||
return data.id;
|
||||
});
|
||||
},
|
||||
|
||||
onApprove: function(data) {
|
||||
setStatus('Capturing payment…');
|
||||
return fetch("<?= $apiBase ?>/capture_order.php", {
|
||||
method: "POST",
|
||||
headers: {"Content-Type":"application/json"},
|
||||
body: JSON.stringify({ order_id: data.orderID })
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(capture => {
|
||||
if (capture.status === 'COMPLETED') {
|
||||
// go to your return page; webhook will fill data/<invoice_id>.json
|
||||
window.location.href = return_url;
|
||||
} else {
|
||||
setStatus('Capture status: ' + capture.status);
|
||||
}
|
||||
})
|
||||
.catch(err => setStatus('Error: ' + err.message));
|
||||
},
|
||||
|
||||
onCancel: function() {
|
||||
window.location.href = cancel_url;
|
||||
},
|
||||
|
||||
onError: function(err){
|
||||
setStatus('PayPal error: ' + (err && err.message ? err.message : err));
|
||||
}
|
||||
}).render('#paypal-button-container');
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
35
ControlPanel/_website/db.php
Normal file
35
ControlPanel/_website/db.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
text/x-generic _db.php ( PHP script, ASCII text, with CRLF line terminators )
|
||||
<?php
|
||||
$servername = "panel.iaregamer.com";
|
||||
$username = "remoteuser";
|
||||
$password = "Pkloyn7yvpht!";
|
||||
$dbname = "panel";
|
||||
|
||||
// Create connection
|
||||
$db = mysqli_connect($servername, $username, $password, $dbname);
|
||||
|
||||
// Check connection
|
||||
if (!$db) {
|
||||
echo "failed";
|
||||
die("Connection failed: " . mysqli_connect_error());
|
||||
}
|
||||
|
||||
//This gets the current users role , Admin, User or other
|
||||
//returning true/false
|
||||
//$isAdmin = isAdmin(186);
|
||||
function isAdmin($userID){
|
||||
$adminField = $db->query("SELECT 'users_role' FROM ogp_users WHERE userID = $userID");
|
||||
if($adminField == "admin"){
|
||||
$adminStatus = true;
|
||||
}else{
|
||||
$adminStatus = false;
|
||||
}
|
||||
return $adminStatus;
|
||||
}
|
||||
|
||||
function logger($logtext){
|
||||
file_put_contents("logfile.txt",$logtext . PHP_EOL,FILE_APPEND);
|
||||
|
||||
}
|
||||
?>
|
||||
82
ControlPanel/_website/index.php
Normal file
82
ControlPanel/_website/index.php
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
echo <<<'HTML'
|
||||
<style>
|
||||
.gsw-outer-full{box-sizing:border-box;width:100vw!important;margin-left:calc(50% - 50vw)!important;margin-right:calc(50% - 50vw)!important}
|
||||
.gsw-page-center{display:flex;justify-content:center;padding:24px 12px}
|
||||
.gsw-wrap{width:min(95vw,1100px);margin:0 auto;line-height:1.55}
|
||||
|
||||
.gsw-hero{display:grid;gap:10px;margin-bottom:18px;text-align:center;justify-items:center}
|
||||
.gsw-hero h1{margin:0;font-size:2rem;letter-spacing:.2px}
|
||||
.gsw-hero p{margin:0;font-size:1.05rem}
|
||||
.gsw-badge{display:inline-block;margin-top:6px;padding:6px 10px;border:1px solid;border-radius:999px;font-weight:600;font-size:.92rem}
|
||||
|
||||
.gsw-callout{margin:14px 0 4px;padding:12px 14px;border:1px dashed;border-radius:10px;text-align:center;font-size:1rem}
|
||||
|
||||
.gsw-locations{margin:12px 0 20px}
|
||||
.gsw-locations h2{margin:0 0 10px;font-size:1.15rem;text-transform:uppercase;letter-spacing:.6px}
|
||||
.gsw-locations-list{display:grid;gap:8px;grid-template-columns:1fr;list-style:disc;margin:0;padding-left:22px}
|
||||
@media(min-width:680px){.gsw-locations-list{grid-template-columns:repeat(2,1fr)}}
|
||||
|
||||
.gsw-grid{display:grid;gap:14px;grid-template-columns:1fr}
|
||||
@media(min-width:720px){.gsw-grid{grid-template-columns:repeat(3,1fr)}}
|
||||
.gsw-card{padding:16px;border:1px solid;border-radius:10px}
|
||||
.gsw-card h3{margin:0 0 6px;font-size:1.1rem}
|
||||
.gsw-card p{margin:0}
|
||||
|
||||
.gsw-cta{display:flex;gap:12px;flex-wrap:wrap;margin-top:16px;justify-content:center}
|
||||
.gsw-btn{border:1px solid;border-radius:8px;padding:10px 14px;text-decoration:none;display:inline-block;font-weight:600}
|
||||
|
||||
.gsw-fine{font-size:.92rem;opacity:.9;text-align:center;margin-top:10px}
|
||||
</style>
|
||||
|
||||
<div class="gsw-outer-full">
|
||||
<div class="gsw-page-center">
|
||||
<section class="gsw-wrap" aria-label="GameServers.World">
|
||||
<header class="gsw-hero">
|
||||
<h1>Virtual Private Gameservers</h1>
|
||||
<p>Just like running on your own dedicated box — <strong>full configurability</strong> with <strong>help when you need it</strong>.</p>
|
||||
<span class="gsw-badge" aria-label="Never oversold">Never Oversold Capacity</span>
|
||||
<p style="margin-top:6px;">We also specialize in classics — <strong>50+ older/community-favorite games</strong> hosted right.</p>
|
||||
</header>
|
||||
|
||||
<div class="gsw-callout" role="note">
|
||||
Your server gets the resources it’s promised. No cramming, no noisy neighbors — predictable performance for your game and mods.
|
||||
</div>
|
||||
|
||||
<section class="gsw-locations" aria-label="Current locations">
|
||||
<h2>Current Locations</h2>
|
||||
<ul class="gsw-locations-list">
|
||||
<li><strong>East USA</strong></li>
|
||||
<li><strong>Central USA</strong></li>
|
||||
<li><strong>West USA</strong></li>
|
||||
<li><strong>Western Europe</strong></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="gsw-grid" aria-label="Highlights">
|
||||
<article class="gsw-card">
|
||||
<h3>Built for the classics</h3>
|
||||
<p>Low-latency routing and high-clock CPUs keep legacy engines smooth. We support favorites like CS 1.6, Urban Terror, DayZ Mod — and dozens more.</p>
|
||||
</article>
|
||||
<article class="gsw-card">
|
||||
<h3>Simple, affordable plans</h3>
|
||||
<p>Clear options, month-to-month flexibility, and room to scale as your community grows.</p>
|
||||
</article>
|
||||
<article class="gsw-card">
|
||||
<h3>Real humans, fast setup</h3>
|
||||
<p>We’ll help with configs, common mods, and a clean starter rotation so you can go live quickly.</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<nav class="gsw-cta" aria-label="Primary actions">
|
||||
<a class="gsw-btn" href="/server-list/">Browse Game Servers</a>
|
||||
<a class="gsw-btn" href="/contact/">Talk to Support</a>
|
||||
</nav>
|
||||
|
||||
<p class="gsw-fine">Looking for a specific title or region? Tell us what you need — we add games and locations regularly.</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
?>
|
||||
|
||||
289
ControlPanel/_website/order.php
Normal file
289
ControlPanel/_website/order.php
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This is the actual "order gameserver" page. There is a page that displays all the possible game servers we can rent. This page displays the options
|
||||
for a single specific game server and has the "Add to Cart" button.
|
||||
The gameserver selected is passed from the gameserverss page by a Post of the ServiceID
|
||||
When the user clicks the "Add to Cart" button, the next page to load is "add_to_cart.php" which creates all the DB entries.
|
||||
All the configuration info is passed to the add_to_cart.php in hidden fields
|
||||
|
||||
In our website, we are setting "post" pages with a "Tag". The first tag in our post should be the service ID from the services table
|
||||
There are other methods that might be better to get the info. But all we need is the "service_ID" in the "ogp_billing_services" table
|
||||
This method means we can use one code block in every game page and fill in the data dynamically.
|
||||
*/
|
||||
include "panel/_db.php";
|
||||
|
||||
|
||||
if (isset($_POST['save']) AND !empty($_POST['description']))
|
||||
{
|
||||
$new_description = str_replace("\\r\\n", "<br>", $_POST['description']);
|
||||
$service = $_POST['service_id'];
|
||||
|
||||
$change_description = "UPDATE opg_billing_services
|
||||
SET description ='".$new_description."'
|
||||
WHERE service_id=".$service;
|
||||
$save = $db->query($change_description);
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ------------------------------------------------------------------------------
|
||||
THIS IS WHAT WE DISPLAY ON THE SHOP PAGE AT THE TOP
|
||||
-->
|
||||
|
||||
<?php
|
||||
// Shop Form
|
||||
if(intval($_REQUEST['service_id']) !==0) $where_service_id = " WHERE enabled = 1 and service_id=".intval($_REQUEST['service_id']); else $where_service_id = " where enabled = 1";
|
||||
$qry_services = "SELECT * FROM ogp_billing_services ".$where_service_id ." ORDER BY service_name";
|
||||
$services = $db->query($qry_services);
|
||||
|
||||
if (isset($_REQUEST['service_id']) && $services === false) {
|
||||
echo "<meta http-equiv='refresh' content='1'>";
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($services as $key => $row) {
|
||||
$service_id[$key] = $row['service_id'];
|
||||
$home_cfg_id[$key] = $row['home_cfg_id'];
|
||||
$mod_cfg_id[$key] = $row['mod_cfg_id'];
|
||||
$service_name[$key] = $row['service_name'];
|
||||
$remote_server_id[$key] = $row['remote_server_id'];
|
||||
$slot_max_qty[$key] = $row['slot_max_qty'];
|
||||
$slot_min_qty[$key] = $row['slot_min_qty'];
|
||||
$price_daily[$key] = $row['price_daily'];
|
||||
$price_monthly[$key] = $row['price_monthly'];
|
||||
$price_year[$key] = $row['price_year'];
|
||||
$description[$key] = $row['description'];
|
||||
$img_url[$key] = $row['img_url'];
|
||||
$ftp[$key] = $row['ftp'];
|
||||
$install_method[$key] = $row['install_method'];
|
||||
$manual_url[$key] = $row['manual_url'];
|
||||
$access_rights[$key] = $row['access_rights'];
|
||||
}
|
||||
|
||||
?>
|
||||
<div style="border-left:10px solid transparent;">
|
||||
<?php
|
||||
foreach($services as $row)
|
||||
{
|
||||
if(!isset($_REQUEST['service_id']))
|
||||
{
|
||||
?>
|
||||
<div style="
|
||||
float:left;
|
||||
padding-top: 30px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 30px;
|
||||
padding-left: 20px;">
|
||||
|
||||
|
||||
|
||||
<img src="<?php echo $row['img_url'] ;?>" width="460" height="225" >
|
||||
<br>
|
||||
<?php echo $row['service_name'];?>
|
||||
<br>
|
||||
<?php
|
||||
if ($row['price_monthly'] == 0.0) {
|
||||
echo "FREE";
|
||||
} else {
|
||||
echo "$" . number_format(floatval($row['price_monthly']),2). " Monthly";
|
||||
}
|
||||
?>
|
||||
<br>
|
||||
<form action="<?php echo $row['description'];?>" method="POST">
|
||||
<input name="service_id" type="hidden" value="<?php echo $row['service_id'];?>" />
|
||||
|
||||
<input name="order_server" type="submit" value="Server Info">
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<input name="service_id" type="hidden" value="<?php echo $row['service_id'];?>" />
|
||||
|
||||
<input name="order_server" type="submit" value="Order Server">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</>
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
} else
|
||||
//THIS IS THE SERVER WE WANT TO ORDER
|
||||
{
|
||||
?>
|
||||
<div style="float:left; border: 4px solid transparent;border-bottom: 25px solid transparent;">
|
||||
|
||||
<img src="<?php echo $row['img_url'];?>" width=230 height=112 border=0 ">
|
||||
<center><b> <?php echo $row['service_name'];?></b></center>
|
||||
<?php
|
||||
|
||||
//$isAdmin = if( current_user_can('administrator')){
|
||||
//$isAdmin = true;
|
||||
//$isAdmin = $db->isAdmin($_SESSION['user_id'] );
|
||||
|
||||
$isAdmin = false;
|
||||
if($isAdmin)
|
||||
{
|
||||
if(!isset($_POST['edit']))
|
||||
{
|
||||
echo "<p style='color:gray;width:230px;' >$row[description]<p>";
|
||||
echo "<form action='' method='post'>".
|
||||
"<input type='hidden' name='service_id' value='$row[service_id]' />".
|
||||
"<input type='submit' name='edit' value='Edit' />".
|
||||
"</form>";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<form action='' method='post'>".
|
||||
"<textarea style='resize:none;width:230px;height:132px;' name='description' >".str_replace("<br>", "\r\n", $row['description'])."</textarea><br>".
|
||||
"<input type='hidden' name='service_id' value='$row[service_id]' />".
|
||||
"<input type='submit' name='save' value='Save' />".
|
||||
"</form>";
|
||||
}
|
||||
}
|
||||
else
|
||||
echo "<p style='color:gray;width:280px;' >$row[description]<p>";
|
||||
?>
|
||||
</div>
|
||||
<table style="float:left;">
|
||||
<form method="post" action="panel/_add_to_cart.php">
|
||||
<input type="hidden" name="service_id" size="15" value="<?php if(isset($_POST['service_id'])) echo $_POST['service_id'];?>">
|
||||
<input type="hidden" name="remote_control_password" size="15" value="ChangeMe">
|
||||
<input type="hidden" name="ftp_password" size="15" value="ChangeMe">
|
||||
<tr>
|
||||
<td align="right"><b>Game Server Name</b> </td>
|
||||
<td align="left">
|
||||
<input type="text" name="home_name" size="40" value="<?php echo $row['service_name'];?>">
|
||||
</td>
|
||||
<tr>
|
||||
<td align="right"><b>Location</b></td>
|
||||
<td align="left">
|
||||
<?php
|
||||
//loop through multiple remote server ID stored in services 'remote_server_ip' as text
|
||||
//change WHERE clause to IS IN clause
|
||||
$rsiArray = explode(" ", $row['remote_server_id']);
|
||||
$rsi = implode(",",$rsiArray);
|
||||
//get the out of stock into an array and see if the rsID is in that array
|
||||
$available_server = false;
|
||||
//loop through each of the assigned servers and see if its disabled
|
||||
foreach($rsiArray as $rsi)
|
||||
{
|
||||
$query = "SELECT * FROM ogp_remote_servers WHERE remote_server_id = ".$rsi;
|
||||
$result = $db->query($query);
|
||||
foreach($result as $rs)
|
||||
{
|
||||
|
||||
$rsID =$rs['remote_server_id'];
|
||||
$rsNAME = $rs['remote_server_name'];
|
||||
//echo "<option value='$rsID'>$rsNAME</option>";
|
||||
// add disabled to lable and input if $rsID is in out_of_stock
|
||||
$is_unavailable = "";
|
||||
$service_text_color = "";
|
||||
|
||||
|
||||
if($rs['enabled']==0)
|
||||
{
|
||||
$is_unavailable = "disabled";
|
||||
$service_text_color = "red";
|
||||
}
|
||||
if($is_unavailable == "")
|
||||
{
|
||||
$available_server = true;
|
||||
}
|
||||
|
||||
|
||||
//default radio button
|
||||
// //<input type='radio' $is_unavailable name='ip_id' id='$rsID' value='$rsID' >
|
||||
echo "<div>
|
||||
<input type='radio' $is_unavailable name='ip_id' id='$rsID' value='$rsID' required>
|
||||
<label for '$rsID' $is_unavailable ><span style='color:$service_text_color'>$rsNAME </span></label>
|
||||
</div>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right"><b>Configure</b></td>
|
||||
<td align="left">
|
||||
<div class="slidecontainer">
|
||||
<center><b>Player Slots</b> </center>
|
||||
<input type="range" name="max_players" min="<?php echo $row['slot_min_qty']?>" max="<?php echo $row['slot_max_qty']?>" value="<?php echo $row['slot_min_qty']?>" class="slider" id="playerRange">
|
||||
<center><b>Months</b></center>
|
||||
<input type="range" name="qty" min="1" max="24" value="1" class="slider" id="invoiceRange">
|
||||
|
||||
<p>Player Slots: <span id="playerSlots"></span><br>
|
||||
<span>Price: $<?php echo number_format(floatval($row['price_monthly']),2 );?> USD</span><br>
|
||||
<span id="invoiceDuration"></span><br>
|
||||
<span id="totalPrice"></span></p>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
var slider = document.getElementById("playerRange");
|
||||
var invoiceslider = document.getElementById("invoiceRange");
|
||||
|
||||
var output = document.getElementById("playerSlots");
|
||||
var price = document.getElementById("totalPrice");
|
||||
var invoiceDuration = document.getElementById("invoiceDuration");
|
||||
var totalvalue = 0;
|
||||
|
||||
|
||||
output.innerHTML = slider.value;
|
||||
invoiceDuration.innerHTML = "Duration: "+invoiceslider.value+" months";
|
||||
totalvalue = slider.value * invoiceslider.value * <?php echo number_format($row['price_monthly'],2);?>;
|
||||
price.innerHTML = "Total Price: $"+totalvalue.toFixed(2) ;
|
||||
|
||||
slider.oninput = function() {
|
||||
output.innerHTML = this.value;
|
||||
invoiceDuration.innerHTML = "Duration: "+invoiceslider.value+" months";
|
||||
totalvalue = invoiceslider.value * <?php echo number_format($row['price_monthly'],2);?>;
|
||||
price.innerHTML = "Total Price: $"+totalvalue.toFixed(2) ;
|
||||
}
|
||||
invoiceslider.oninput = function() {
|
||||
invoiceDuration.innerHTML = "Duration: "+invoiceslider.value+" months";
|
||||
totalvalue = slider.value * invoiceslider.value * <?php echo number_format($row['price_monthly'],2);?>;
|
||||
price.innerHTML = "Total Price: $"+totalvalue.toFixed(2) ;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<input type="hidden" name="invoice_duration" value="month" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td align="left" colspan="2">
|
||||
<input name="service_id" type="hidden" value="<?php echo $row['service_id'];?>"/>
|
||||
<?php
|
||||
if ($available_server)
|
||||
{
|
||||
?>
|
||||
<input type="submit" name="add_to_cart" value="Add to Cart"/>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" colspan="2">
|
||||
<form action ="https://gameservers.world/server-list/" method="POST">
|
||||
<button >Back to List</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
99
ControlPanel/_website/serverlist.php
Normal file
99
ControlPanel/_website/serverlist.php
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
include "db.php";
|
||||
|
||||
|
||||
// Save new description if admin
|
||||
if (isset($_POST['save']) && !empty($_POST['description'])) {
|
||||
$new_description = str_replace("\\r\\n", "<br>", $_POST['description']);
|
||||
$service = intval($_POST['service_id']);
|
||||
$stmt = $db->prepare("UPDATE ogp_billing_services SET description = ? WHERE service_id = ?");
|
||||
$stmt->bind_param("si", $new_description, $service);
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
}
|
||||
|
||||
// Fetch services
|
||||
$service_id = isset($_REQUEST['service_id']) ? intval($_REQUEST['service_id']) : 0;
|
||||
$where_service_id = $service_id !== 0 ? "WHERE enabled = 1 AND service_id = $service_id" : "WHERE enabled = 1";
|
||||
$qry_services = "SELECT * FROM ogp_billing_services $where_service_id ORDER BY service_name";
|
||||
$services = $db->query($qry_services);
|
||||
|
||||
if (!$services) {
|
||||
echo "<meta http-equiv='refresh' content='1'>";
|
||||
return;
|
||||
}
|
||||
?>
|
||||
|
||||
<div style="border-left:10px solid transparent;">
|
||||
<?php foreach ($services as $row): ?>
|
||||
<?php if (!isset($_REQUEST['service_id'])): ?>
|
||||
<!-- Service listing (all) -->
|
||||
<div style="float:left; padding:30px 20px;">
|
||||
<img src="../<?php echo $row['img_url']; ?>" width="460" height="225"><br>
|
||||
<strong><?php echo $row['service_name']; ?></strong><br>
|
||||
<?php
|
||||
echo ($row['price_monthly'] == 0.0) ? "FREE" : "$" . number_format(floatval($row['price_monthly']), 2) . " Monthly";
|
||||
?>
|
||||
<br>
|
||||
|
||||
<form action="https://gameservers.world/order-server" method="POST">
|
||||
<input type="hidden" name="service_id" value="<?php echo $row['service_id']; ?>">
|
||||
<input type="submit" name="order" value="Order Server" >
|
||||
</form>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<!-- Single service detail view -->
|
||||
<div style="float:left; border: 4px solid transparent; border-bottom: 25px solid transparent;">
|
||||
<img src="<?php echo $row['img_url']; ?>" width="230" height="112"><br>
|
||||
<center><b><?php echo $row['service_name']; ?></b></center>
|
||||
|
||||
<?php
|
||||
$isAdmin = false; // change to actual check, e.g. current_user_can('administrator')
|
||||
if ($isAdmin) {
|
||||
if (!isset($_POST['edit'])) {
|
||||
echo "<p style='color:gray;width:230px;'>{$row['description']}</p>";
|
||||
echo "<form method='post'>
|
||||
<input type='hidden' name='service_id' value='{$row['servioce_id']}'>
|
||||
<input type='submit' name='edit' value='Edit'>
|
||||
</form>";
|
||||
} else {
|
||||
$desc = str_replace("<br>", "\r\n", $row['description']);
|
||||
echo "<form method='post'>
|
||||
<textarea style='resize:none;width:230px;height:132px;' name='description'>$desc</textarea><br>
|
||||
<input type='hidden' name='service_id' value='{$row['service_id']}'>
|
||||
<input type='submit' name='save' value='Save'>
|
||||
</form>";
|
||||
}
|
||||
} else {
|
||||
echo "<p style='color:gray;width:280px;'>{$row['description']}</p>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<!-- Order Form -->
|
||||
<form method="post" action="order_server.php">
|
||||
<input type="hidden" name="service_id" value="<?php echo $row['service_id']; ?>">
|
||||
<input type="hidden" name="remote_control_password" value="ChangeMe">
|
||||
<input type="hidden" name="ftp_password" value="ChangeMe">
|
||||
<table style="float:left;">
|
||||
<tr>
|
||||
<td align="right"><b>Game Server Name</b></td>
|
||||
<td><input type="text" name="home_name" size="40" value="<?php echo $row['service_name']; ?>"></td>
|
||||
</tr>
|
||||
<!-- Add other form fields as needed -->
|
||||
<tr>
|
||||
<td colspan="2"><input type="submit" value="Add to Cart"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue