diff --git a/README.md b/README.md index d137772..1f62be7 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Die Datei `env.php` enthält alle sensiblen Zugangsdaten und Umgebungsvariablen ## Robust.ini Setup MapTileURL = "${Const|BaseURL}/oswebinterface/maptile.php"; + MessageUrl = "${Const|BaseURL}/oswebinterface/messages.php" SearchURL = "${Const|BaseURL}/oswebinterface/search.php" DestinationGuide = "${Const|BaseURL}/oswebinterface/guide.php" AvatarPicker = "${Const|BaseURL}/oswebinterface/avatarpicker.php" @@ -90,10 +91,3 @@ Die Datei `env.php` enthält alle sensiblen Zugangsdaten und Umgebungsvariablen GridStatusRSS = ${Const|BaseURL}/oswebinterface/gridstatusrss.php --- - - - - - - - diff --git a/message.php b/message.php index a64e87f..8015825 100644 --- a/message.php +++ b/message.php @@ -1,35 +1,116 @@ "$greeting auf " . SITE_NAME . "! Bitte beachte unsere Regeln und Richtlinien.", - "type" => "system", - "url_tos" => BASE_URL . "/include/tos.php", - "url_dmca" => BASE_URL . "/include/dmca.php" - ]; -} else { - // Statische MOTD - $message = [ - "message" => MOTD_STATIC_MESSAGE, - "type" => MOTD_STATIC_TYPE, - "url_tos" => MOTD_STATIC_URL_TOS, - "url_dmca" => MOTD_STATIC_URL_DMCA - ]; + + $accept = $_SERVER['HTTP_ACCEPT'] ?? ''; + return stripos($accept, 'application/json') !== false; } -// JSON-Ausgabe -echo json_encode($message, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); -?> \ No newline at end of file +/** + * Query a single numeric value and return null on failure. + */ +function query_scalar_int(mysqli $conn, string $sql): ?int +{ + $result = $conn->query($sql); + if ($result === false) { + return null; + } + + $row = $result->fetch_row(); + $result->free(); + + if (!$row || !isset($row[0])) { + return null; + } + + return (int)$row[0]; +} + +/** + * Read live grid stats from the Robust database. + */ +function load_grid_stats(): ?array +{ + if (!defined('DB_SERVER') || !defined('DB_USERNAME') || !defined('DB_PASSWORD') || !defined('DB_NAME')) { + return null; + } + + $conn = @new mysqli(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME); + if ($conn->connect_errno) { + return null; + } + + $stats = [ + 'online_users' => query_scalar_int($conn, 'SELECT COUNT(*) FROM Presence'), + 'regions' => query_scalar_int($conn, 'SELECT COUNT(*) FROM regions'), + 'accounts' => query_scalar_int($conn, 'SELECT COUNT(*) FROM UserAccounts'), + 'active_30d' => query_scalar_int($conn, 'SELECT COUNT(*) FROM GridUser WHERE Login > (UNIX_TIMESTAMP() - (30*86400))'), + 'grid_users' => query_scalar_int($conn, 'SELECT COUNT(*) FROM GridUser'), + ]; + + $conn->close(); + + foreach ($stats as $value) { + if ($value !== null) { + return $stats; + } + } + + return null; +} + +/** + * Build MOTD text for viewer login. + */ +function build_message_text(?array $stats): string +{ + if (defined('MOTD') && MOTD !== 'Dyn') { + return defined('MOTD_STATIC_MESSAGE') ? (string)MOTD_STATIC_MESSAGE : 'Welcome to the grid!'; + } + + $hour = (int)date('G'); + $greeting = $hour < 12 ? 'Good morning' : 'Good day'; + $siteName = defined('SITE_NAME') ? SITE_NAME : 'to the Grid'; + $text = $greeting . ' on ' . $siteName . '!'; + + if ($stats !== null) { + $text .= sprintf( + ' Online: %d - Regions: %d - Active 30 days: %d', + (int)($stats['online_users'] ?? 0), + (int)($stats['regions'] ?? 0), + (int)($stats['active_30d'] ?? 0) + ); + } + + return $text; +} + +$stats = load_grid_stats(); +$messageText = build_message_text($stats); + +$payload = [ + 'message' => $messageText, + 'type' => defined('MOTD_STATIC_TYPE') ? MOTD_STATIC_TYPE : 'system', + 'url_tos' => defined('MOTD_STATIC_URL_TOS') ? MOTD_STATIC_URL_TOS : (BASE_URL . '/include/tos.php'), + 'url_dmca' => defined('MOTD_STATIC_URL_DMCA') ? MOTD_STATIC_URL_DMCA : (BASE_URL . '/include/dmca.php'), + 'stats' => $stats, + 'generated_at' => gmdate('c'), +]; + +if (wants_json_response()) { + header('Content-Type: application/json; charset=utf-8'); + echo json_encode($payload, JSON_UNESCAPED_SLASHES); + exit; +} + +header('Content-Type: text/plain; charset=utf-8'); +echo $messageText; \ No newline at end of file diff --git a/search.php b/search.php index 5e6d792..db75eab 100644 --- a/search.php +++ b/search.php @@ -1,116 +1,327 @@ + 0); + if ($res !== false) { + mysqli_free_result($res); + } + mysqli_stmt_close($stmt); + return $exists; +} + +$queryText = gs_param(array('q', 'query', 'search', 'term', 's', 'text'), ''); +$queryType = strtolower(gs_param(array('type', 'category', 'scope', 't'), 'all')); + +$typeAlias = array( + 'person' => 'people', + 'avatars' => 'people', + 'avatar' => 'people', + 'group' => 'groups', + 'place' => 'places', + 'regions' => 'places', + 'region' => 'places', + 'classified' => 'classifieds', + 'classifieds' => 'classifieds', +); +if (isset($typeAlias[$queryType])) { + $queryType = $typeAlias[$queryType]; +} + +$allowedTypes = array('all', 'people', 'groups', 'places', 'classifieds'); +if (!in_array($queryType, $allowedTypes, true)) { + $queryType = 'all'; +} + +$mysqli = @mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME); +if ($mysqli === false) { + http_response_code(500); + echo 'Datenbankverbindung fehlgeschlagen.'; + exit; +} + +$rows = array(); +$warnings = array(); + +if ($queryText !== '') { + $needle = '%' . gs_escape_like($queryText) . '%'; + + if ($queryType === 'all' || $queryType === 'people') { + $sql = 'SELECT FirstName, LastName FROM UserAccounts WHERE FirstName LIKE ? OR LastName LIKE ? ORDER BY FirstName, LastName LIMIT 100'; + $stmt = mysqli_prepare($mysqli, $sql); + if ($stmt !== false) { + mysqli_stmt_bind_param($stmt, 'ss', $needle, $needle); + mysqli_stmt_execute($stmt); + $res = mysqli_stmt_get_result($stmt); + if ($res !== false) { + while ($r = mysqli_fetch_assoc($res)) { + $rows[] = array( + 'type' => 'People', + 'name' => trim(($r['FirstName'] ?? '') . ' ' . ($r['LastName'] ?? '')), + 'extra' => '', + ); + } + mysqli_free_result($res); + } + mysqli_stmt_close($stmt); + } + } + + if ($queryType === 'all' || $queryType === 'groups') { + $sql = 'SELECT Name, Charter FROM os_groups_groups WHERE Name LIKE ? OR Charter LIKE ? ORDER BY Name LIMIT 100'; + $stmt = mysqli_prepare($mysqli, $sql); + if ($stmt !== false) { + mysqli_stmt_bind_param($stmt, 'ss', $needle, $needle); + mysqli_stmt_execute($stmt); + $res = mysqli_stmt_get_result($stmt); + if ($res !== false) { + while ($r = mysqli_fetch_assoc($res)) { + $rows[] = array( + 'type' => 'Groups', + 'name' => (string) ($r['Name'] ?? ''), + 'extra' => (string) ($r['Charter'] ?? ''), + ); + } + mysqli_free_result($res); + } + mysqli_stmt_close($stmt); + } + } + + if ($queryType === 'all' || $queryType === 'places') { + $sql = 'SELECT regionName, serverIP, serverPort FROM regions WHERE regionName LIKE ? ORDER BY regionName LIMIT 100'; + $stmt = mysqli_prepare($mysqli, $sql); + if ($stmt !== false) { + mysqli_stmt_bind_param($stmt, 's', $needle); + mysqli_stmt_execute($stmt); + $res = mysqli_stmt_get_result($stmt); + if ($res !== false) { + while ($r = mysqli_fetch_assoc($res)) { + $extra = (string) ($r['serverIP'] ?? ''); + if (isset($r['serverPort']) && $r['serverPort'] !== '') { + $extra .= ':' . $r['serverPort']; + } + $rows[] = array( + 'type' => 'Places', + 'name' => (string) ($r['regionName'] ?? ''), + 'extra' => $extra, + ); + } + mysqli_free_result($res); + } + mysqli_stmt_close($stmt); + } + } + + if ($queryType === 'all' || $queryType === 'classifieds') { + if (gs_table_exists($mysqli, 'classifieds')) { + $sql = 'SELECT name, simname, parcelname FROM classifieds WHERE name LIKE ? OR description LIKE ? OR simname LIKE ? ORDER BY expirationdate DESC LIMIT 100'; + $stmt = mysqli_prepare($mysqli, $sql); + if ($stmt !== false) { + mysqli_stmt_bind_param($stmt, 'sss', $needle, $needle, $needle); + mysqli_stmt_execute($stmt); + $res = mysqli_stmt_get_result($stmt); + if ($res !== false) { + while ($r = mysqli_fetch_assoc($res)) { + $rows[] = array( + 'type' => 'Classifieds', + 'name' => (string) ($r['name'] ?? ''), + 'extra' => trim((string) ($r['simname'] ?? '') . ' / ' . (string) ($r['parcelname'] ?? ''), ' /'), + ); + } + mysqli_free_result($res); + } + mysqli_stmt_close($stmt); + } + } elseif ($queryType === 'classifieds') { + $warnings[] = 'Classifieds table not found in this database.'; + } + } + +} + +mysqli_close($mysqli); +?>
- -Search parameter can be passed by viewer as `q`, `query`, `search` or `term`.
+ +Results:
+ + + +| Type | +Name | +Extra | +
|---|---|---|
| No results found. | ||
| + | + | + |