Skip to content

Instantly share code, notes, and snippets.

@Bluscream
Last active June 8, 2023 02:11
Show Gist options
  • Save Bluscream/dbba7ee2e8b2e9c8c9b31150a7d2e502 to your computer and use it in GitHub Desktop.
Save Bluscream/dbba7ee2e8b2e9c8c9b31150a7d2e502 to your computer and use it in GitHub Desktop.
Raidmax Server List Scraper with caching (supports "php", "php-pretty", "csv", "json", "html","txt","favorites")
{
"require": {
"symfony/browser-kit": "^5.4",
"symfony/process": "^5.4",
"symfony/http-client": "^5.4",
"symfony/dom-crawler": "^5.4",
"symfony/css-selector": "^5.4",
"voku/stringy": "^6.5"
}
}
<?php
// ini_set('display_errors', 1);
// ini_set('display_startup_errors', 1);
// error_reporting(E_ALL);
$debug_output = '';
$array_text = '';
function scriptlog($msg) {
global $debug_output;
$fancy = print_r($msg, TRUE);
error_log($fancy . "\n", 3, 'index.log'); // /var/www/html/iw4/favorites/
$debug_output .= $msg . "<br>";
}
function process_array($array) {
$processed_array = [];
foreach ($array as $item) {
if (strpos($item, ':') === false) {
// Add default port to items without a port
$processed_array[] = $item . ':28960';
} else {
$processed_array[] = $item;
}
}
return $processed_array;
}
function merge_arrays($array1, $array2) {
scriptlog("Merging Array 1 (" . count($array1) . " elements) with Array 2 (" . count($array2) . " elements)");
$merged_array = array_merge($array1, $array2);
$duplicates = (count($array1) + count($array2)) - count($merged_array);
scriptlog("Merged array is now " . count($merged_array) . " elements large. ($duplicates duplicates removed)");
return $merged_array;
}
function merge_json_files($input_files, $input_urls) {
global $array_text;
$merged_array = [];
$context = stream_context_create([
'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false ]
]);
// Merge the arrays from input files
foreach ($input_files as $file) {
$data = json_decode(file_get_contents($file), true);
scriptlog("Got array with " . count($data) . " elements from $file");
$data = process_array($data);
$merged_array = merge_arrays($merged_array, $data);
}
// Merge the array from input URLs
foreach ($input_urls as $input_url) {
$data = json_decode(file_get_contents($input_url, false, $context), true);
scriptlog("Got array with " . count($data) . " elements from $input_url");
$data = process_array($data);
$merged_array = merge_arrays($merged_array, $data);
}
$oldsize = count($merged_array);
// Remove duplicates and sort the merged array
$merged_array = array_values(array_unique($merged_array));
$newsize = count($merged_array);
$duplicates = $oldsize - $newsize;
scriptlog("Final array is $newsize elements large. ($duplicates duplicates removed)");
sort($merged_array);
// Generate the output file
$output_file = 'favourites.json';
$array_text = json_encode($merged_array, JSON_PRETTY_PRINT);
file_put_contents($output_file, $array_text);
// Provide the merged file for download
header('Content-Disposition: attachment; filename="' . basename($output_file) . '"');
header('Content-Type: application/json');
header('Content-Length: ' . filesize($output_file));
readfile($output_file);
exit;
}
$now = date("d.m.Y - H:i");
scriptlog("Running at $now");
// Check if the form was submitted
if (isset($_POST['submit'])) {
$input_files = [];
$input_urls = [];
// Handle uploaded input files
foreach ($_FILES['input_files']['tmp_name'] as $tmp_name) {
if (!empty($tmp_name)) {
$input_files[] = $tmp_name;
}
}
// Handle input URL
$input_urls[] = $_POST['input_url'];
// Merge the JSON files and provide the merged file for download
merge_json_files($input_files, $input_urls);
} else {
// Pre-fill the input URL
$input_url = 'http://minopia.de/iw4/servers?format=favorites&games=iw4&filename=favourites.json&dl';
}
scriptlog($debug_output);
?>
<!DOCTYPE html>
<html>
<head>
<title>IW4x Favorites Merger</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1 class="mt-5 mb-4">IW4x Favorites Merger</h1>
<form method="POST" enctype="multipart/form-data">
<div class="form-group">
<label for="input_files">Upload Input Files:</label>
<label for="input_files">(Usually <code>C:\Program Files (x86)\Steam\steamapps\common\Call of Duty Modern Warfare 2\players\favourites.json</code>)</label>
<input type="file" class="form-control-file" name="input_files[]" multiple>
</div>
<div class="form-group">
<label for="input_url">Input URL:</label>
<input type="text" class="form-control" name="input_url" value="<?php echo $input_url; ?>">
</div>
<button type="submit" name="submit" class="btn btn-primary">Merge and Download</button>
</form>
<hr>
<!-- <h4>Debug Output:</h4> -->
<textarea class="form-control" rows="10" readonly><?php echo htmlentities($array_text); ?></textarea>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script>
console.log(`<?php echo $debug_output; ?>`);
</script>
</body>
</html>
import argparse
import json
def process_array(array):
processed_array = []
for item in array:
if ":" not in item:
# Add default port to items without a port
processed_array.append(f"{item}:28960")
else:
processed_array.append(item)
return processed_array
def merge_json_files(input_files:list[str], output_file:str):
merged_array = []
# Iterate over each input file
for file_path in input_files:
# Read the JSON file
with open(file_path, 'r') as file:
data = json.load(file)
print(f"Got array with {len(data)} elements from {file_path}")
data = process_array(data)
# Merge the arrays without duplicates
merged_array = list(set(merged_array + data))
print(f"Merged array is now {len(merged_array)} elements large.")
merged_array = sorted(merged_array)
# Write the merged array into the output file
with open(output_file, 'w') as file:
print(f"Writing {len(merged_array)} elements to {output_file}")
json.dump(merged_array, file, indent=4)
# Create the argument parser
parser = argparse.ArgumentParser(description='Merge multiple JSON files.')
# Add the positional arguments
# parser.add_argument('input_files', nargs='+', help='input JSON files')
parser.add_argument('--output_file', default='output.json', help='output JSON file')
# Parse the command-line arguments
args = parser.parse_args()
if not "input_files" in args or not args.input_files:
args.input_files = [
"G:/Steam/steamapps/common/Call of Duty Modern Warfare 2/players/favourites.json",
"D:/Downloads/favourites.json",
"D:/Downloads/favorites.json",
]
# Merge the JSON files
merge_json_files(args.input_files, args.output_file)
from pathlib import Path
from json import load, dump
import requests
# File path for the favourites.json file
favourites_file = Path("S:/Call of Duty/CoD 6 (MW2)/players/favourites.json")
game_name = "iw4"
servers_url = f"http://minopia.de/iw4/servers/?games={game_name}&format=json"
# servers_url = f"http://192.168.2.38/iw4/servers/index.json"
print(f"Requesting server list from {servers_url}")
response = requests.get(servers_url, timeout=1)
print(f"Got response from server: {response.text[:100]}")
server_data = response.json()
servers = []
print(f"Got {len(server_data)} games from {servers_url}")
print(f"Got {len(server_data[game_name])} games in {game_name}")
for server in server_data["iw4"]:
ip = server["ip"]
port = server["port"] if "port" in server else "28960"
if ip and port:
server_address = ip + ":" + port
if server_address not in servers:
servers.append(server_address)
print(f"Added {server_address} to favorites")
else:
print(f"{server_address} already exists in favorites")
with open(favourites_file, "r") as file:
favourites = load(file)
print(f"Loaded {len(favourites)} favorites from {favourites_file}")
merged_favourites = favourites + servers
merged_favourites = list(set(merged_favourites))
backup_file = favourites_file.with_stem("favorites.bak")
favourites_file.rename(backup_file)
print(f"Created backup at {backup_file}")
with open(favourites_file, "w") as file:
dump(merged_favourites, file, indent=4)
print(f"Wrote {len(merged_favourites)} favorites to {favourites_file}")
<?php
// ini_set('display_errors', 1);
// ini_set('display_startup_errors', 1);
// error_reporting(E_ALL);
require 'vendor/autoload.php';
use Symfony\Component\BrowserKit\HttpBrowser;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\DomCrawler\Crawler;
$color_codes = [
'^0' => 'black',
'^1' => 'red',
'^2' => 'green',
'^3' => 'yellow',
'^4' => 'blue',
'^5' => 'cyan',
'^6' => 'pink',
'^7' => 'white',
'^8' => 'black',
'^9' => 'black',
'^;' => '', // map
'^:' => '' // rainbow
];
$games = array(
"csgo" => "Counter-Strike: Global Offensive",
"t4" => "Call of Duty 4: Modern Warfare",
"t5" => "Call of Duty: World at War",
"t6" => "Call of Duty: Modern Warfare 2",
"t7" => "Call of Duty: Black Ops",
"iw3" => "Call of Duty: Modern Warfare 3",
"h1" => "Call of Duty: Ghosts",
"iw4" => "Call of Duty: Advanced Warfare",
"shg1"=> "Call of Duty: WWII",
"iw5" => "Call of Duty: Black Ops 4",
"iw6" => "Call of Duty: Modern Warfare (2019)",
);
$game_modes = array(
"0" => "Unknown",
"aiz" => "Aliens in Zombies",
"aliens" => "Aliens",
"cj" => "Cranked",
"CLASSICX" => "Classic",
"clean" => "Clean",
"cmp" => "Champion Hill",
"conf" => "Confirmed",
"ctf" => "Capture the Flag",
"dd" => "Drop Zone",
"deathrun" => "Deathrun",
"dem" => "Demolition",
"dm" => "Deathmatch",
"dom" => "Domination",
"freezetag" => "Freeze Tag",
"gun" => "Gun Game",
"gungame" => "Gun Game",
"hq" => "Headquarters",
"infect" => "Infected",
"koth" => "King of the Hill",
"mike" => "Mike Myers",
"oic" => "One in the Chamber",
"prop" => "Prop Hunt",
"sas" => "Search & Rescue",
"sd" => "Search & Destroy",
"surv" => "Survival",
"survival" => "Survival",
"tdm" => "Team Deathmatch",
"teamgungame" => "Team Gun Game",
"ts" => "Trick Shot",
"twar" => "Team War",
"war" => "Team Deathmatch",
"zclassic" => "Zombies Classic",
"zcleansed" => "Zombies Cleansed",
"zgrief" => "Zombies Grief",
"zom" => "Zombies",
"zombies" => "Zombies",
"zstandard" => "Zombies Standard"
);
$options = [
"format" => ["php", "php-pretty", "csv", "json", "html","txt","favorites"],
"games" => $games,// ["csgo","h1","iw3","iw4","iw5","iw6","shg1","t4","t5","t6","t7"],
"modes" => $game_modes, // ["zstandard","zombies","zom","zgrief","zcleansed","zclassic","war","twar","teamgungame","tdm","survival","surv","sd","sas","prop","oic","mike","koth","infect","hq","gungame","gun","gametype","freezetag","dom","dm","dem","deathrun","dd","ctf","conf","cmp","clean","CLASSICX","cj","aliens","aiz","0"],
"names" => [""],
"sort" => ["name","ip","port","mode","map","clients_online","clients_max"],
"no_ts" => [""],
"minclients" => ["0","1","18"],
"maxclients" => ["0","1","18"],
"debug" => [""],
"dl" => [""],
"filename" => [""],
"scrape" => [],
];
if (!function_exists('str_contains')) {
function str_contains($haystack, $needle) {
return $needle !== '' && mb_strpos($haystack, $needle) !== false;
}
}
function newline($amount = 1) {
return str_repeat("<br>\n", $amount);
}
function println($msg = "") {
echo $msg . newline();
}
function normalize($string) {
return titleCaseSpecial(str_replace("_", " ", htmlspecialchars($string)));
}
function parse_color_codes($string) {
global $color_codes;
$string = htmlspecialchars($string);
// Define an associative array that maps the color codes to their corresponding HTML color names.
// Use the preg_replace_callback function to search for the color codes in the input string and replace them with the appropriate HTML tags.
$result = preg_replace_callback('/\^([\d;:])/',
function ($matches) use ($color_codes) {
return '<text color="' . $color_codes[$matches[0]] . '">';
},
$string
);
// Close the opened <text> tags.
$result .= str_repeat('</text>', substr_count($result, '<text'));
return $result;
}
function getCurrentUrl() {
$protocol = strpos(strtolower($_SERVER['SERVER_PROTOCOL']),'https') === FALSE ? 'http' : 'https';
$host = $_SERVER['HTTP_HOST'];
$script = $_SERVER['SCRIPT_NAME'];
$params = $_SERVER['QUERY_STRING'];
return $protocol . '://' . $host . $script . '?' . $params;
}
function addToUrl($url, $key, $value = null) {
$query = parse_url($url, PHP_URL_QUERY);
if ($query) {
parse_str($query, $queryParams);
$queryParams[$key] = $value;
$url = str_replace("?$query", '?' . http_build_query($queryParams), $url);
} else {
$url .= '?' . urlencode($key) . '=' . urlencode($value);
}
return $url;
}
function buildUrl($params) {
return $_SERVER['PHP_SELF'] . '?' . http_build_query($params);
}
function writeUrl($params, $text = NULL) {
$url = buildUrl($params);
if (is_null($text)) $text = $url;
return "<a href='$url'>$text</a>";
}
function writeUrlAddParam($key, $value = null, $text = null) {
global $currentUrl;
$url = addToUrl($currentUrl, $key, $value);
if (is_null($text)) $text = $url;
return "<a href='$url'>$text</a>";
}
function copyToClipboardButton($text, $buttonText) {
return "<button onclick=\"copyToClipboard('$text')\">$buttonText</button>";
}
if (!function_exists('array_is_list')) {
function array_is_list(array $arr)
{
if ($arr === []) {
return true;
}
return array_keys($arr) === range(0, count($arr) - 1);
}
}
function transformOptionsToArray($options)
{
global $currentUrl;
$menuItems = [];
// $currentUrl = strtok($_SERVER['REQUEST_URI'], '?');
foreach ($options as $menu => $items) {
if (array_is_list($items)) {
foreach ($items as $item) {
$href = addToUrl($currentUrl, $menu, $item);
$menuItems[$menu][$item] = $href;
}
} else {
foreach ($items as $name => $description) {
$href = addToUrl($currentUrl, $menu, $name);
$menuItems[$menu][$description] = $href;
}
}
}
return $menuItems;
}
function print_header()
{
echo '<!DOCTYPE html><html lang="en" data-bs-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Raidmax Servers</title>
<link rel="stylesheet" href="https://mdbcdn.b-cdn.net/wp-content/themes/mdbootstrap4/docs-app/css/dist/mdb5/standard/core.min.css">
<!-- link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.31.3/js/jquery.tablesorter.min.js"></script>
</head><body class="dark" data-bs-theme="dark">
<script>
function copyToClipboard(text) {
var tmp = document.createElement("input");
tmp.setAttribute("display", "none");
tmp.setAttribute("type", "text");
tmp.setAttribute("value", text);
document.body.appendChild(tmp);
tmp.select();
tmp.setSelectionRange(0, 99999);
document.execCommand("copy");
navigator.clipboard.writeText(tmp.value);
tmp.parentElement.removeChild(tmp);
}
</script>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">XLabs Toolbox</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>';
}
function print_menu_start() {
echo '<div class="collapse navbar-collapse" id="navbarSupportedContent"><ul class="nav navbar-nav mr-auto">';
}
function print_menu_items($menuItems) {
foreach ($menuItems as $menu => $items) {
echo '<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="' . $menu . 'Dropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' . ucfirst($menu) . '</a>
<div class="dropdown-menu" aria-labelledby="' . $menu . 'Dropdown">';
foreach ($items as $itemName => $href) {
echo '<a class="dropdown-item" href="' . $href . '">' . ucfirst($itemName) . '</a>';
}
echo '</div></li>';
}
}
function print_menu_end() {
echo '</ul></div></nav>';
}
function print_options() {
global $options;
foreach ($options as $option => $values) {
// $url = "<a href='".$_SERVER["PHP_SELF"] . "?";
echo writeUrlAddParam($option, null, normalize($option)) . ":&nbsp;";
if (array_is_list($values)) {
foreach ($values as $value) {
echo writeUrlAddParam($option, $value, $value) . "&nbsp;";
}
} else {
foreach ($values as $name => $description) {
echo writeUrlAddParam($option, $name, $description) . "&nbsp;";
}
}
println();
}
}
function print_options_fancy()
{
global $options;
print_menu_items(transformOptionsToArray($options));
}
function print_banner() {
print_header();
print_menu_start();
print_menu_items([
"Mirrors" => [
"xlabs-mirror.github.io" => "https://xlabs-mirror.github.io/",
"xlabs-mirror.gitlab.io/xlabs.dev" => "https://xlabs-mirror.gitlab.io/xlabs.dev/",
"minopia.de/archive/xlabs.dev" => "https://minopia.de/archive/xlabs.dev/",
"minopia.de/archive/xlabs.dev" => "https://minopia.de/archive/xlabs.dev/",
"minopia.de/archive/updater.xlabs.dev" => "https://minopia.de/archive/updater.xlabs.dev/",
],
"Tools" => [
"Servers" => "https://minopia.de/iw4/servers/?formats",
"Favorites Merge Tool" => "https://minopia.de/iw4/favorites/",
],
"|" => [],
]);
print_options_fancy();
print_menu_end();
}
if (isset($_GET["help"])||isset($_GET["about"])||isset($_GET["formats"])) {
print_banner();
exit();
} elseif (isset($_GET["debug"])) {
print_options();
exit();
}
function get($key, $default=NULL) {
return array_key_exists($key, $_GET) ? $_GET[$key] : $default;
}
function appendThings(/* map[string,mixed] */ &$array, /* string */ $key, /* string */ $value) {
if (!isset($array[$key]))
$array[$key] = $value;
else if (is_array($array[$key]))
$array[$key][] = $value;
else
$array[$key] = array($array[$key], $value);
return $array;
}
function highlight_array($array, $name = 'var') {
highlight_string("<?php\n\$$name =\n" . var_export($array, true) . ";\n?>");
}
function titleCaseSpecial($string)
{
return preg_replace_callback(
'~[/.-]\p{Ll}~u',
function ($m) {
return mb_strtoupper($m[0], 'UTF-8');
},
mb_convert_case($string, MB_CASE_TITLE, 'UTF-8')
);
}
function remove_html_comments($content = '') {
return preg_replace('/<!--(.|\s)*?-->/', '', $content);
}
function generateHtmlTable($array) {
global $game_modes;
$table = '<table class="table table-striped table-bordered table-hover" style="font-size:medium;">';
$table .= '<thead><tr>';
$table .= "<th><b>".count($array)."</b></th>";
foreach ($array[0] as $key => $value) {
$table .= '<th>' . normalize($key) . '</th>';
}
$table .= '</tr></thead>';
$table .= '<tbody>';
foreach ($array as $row) {
$table .= '<tr>';
if (is_array($row)) {
$ip = $row["ip"];
$btn = copyToClipboardButton("connect ".$ip.":".$row["port"], "📄");
// $table .= "<td>". $btn . "&nbsp;<img src='http://api.hostip.info/flag.php?ip=$ip' style='display:block!important'/></td>";
$table .= "<td>$btn</td>";
foreach ($row as $key=>$value) {
if (is_array($value)) {
$table .= '<td>' . generateHtmlTable($value) . '</td>';
} else {
$table .= '<td>';
if ($key === "hostname") {
$table .= parse_color_codes($value);
} elseif ($key === "gametype") {
$hostname = strtolower($row["hostname"]);
if (str_contains($hostname, "trick") || str_contains($hostname, "tsd")) $value = "ts";
$table .= $game_modes[$value];
} else {
$table .= $value;
if ($key === "ip") $table .= "&nbsp;<i class='flag flag-".strtolower(geoip_country_code_by_name($key))."' />";
}
$table .= '</td>';
}
}
}
$table .= '</tr>';
}
$table .= '</tbody></table>';
return $table;
}
function generateCsv($array) {
if (empty($array) || !is_array($array) || empty(reset($array)) || !is_array(reset($array))) {
return '';
}
$first_game = reset($array);
$keys = array_keys(reset($first_game));
$csv = "game," . implode(',', $keys) . "\n";
foreach($array as $game => $game_servers) {
foreach ($game_servers as $row) {
$rowData = array();
foreach ($keys as $key) {
$rowData[] = isset($row[$key]) ? '"' . str_replace('"', '""', $row[$key]) . '"' : '';
}
$csv .= "\"$game\"," . implode(',', $rowData) . "\n";
}
}
return $csv;
}
function fetchFileWithCaching($url, $expirationTime = 60, $cacheFile = NULL) { // , $force = false
global $force;
if (is_null($cacheFile)) $cacheFile = md5($url);
if (!$force && file_exists($cacheFile) && time() - filemtime($cacheFile) < $expirationTime) {
} else {
$browser = new HttpBrowser(HttpClient::create());
$response = $browser->request('GET', $url);
if ($browser->getResponse()->getStatusCode() === 200) {
$content = $browser->getResponse()->getContent();
file_put_contents($cacheFile, $content);
return $content;
}
}
return file_get_contents($cacheFile);
}
function scrapeServersFromHTML($url) {
global $filter_games;
if (!isset($url)) $url = "https://master.iw4.zip/servers"; // http://api.raidmax.org:5000/servers
$html = remove_html_comments(fetchFileWithCaching($url, 60, "servers.html"));
$crawler = new Crawler($html);
$servers = [];
$games = $crawler->filterXPath("//div[contains(concat(' ', normalize-space(@class), ' '), ' game-server-panel ')]");
$games->each(function (Crawler $game) use (&$servers, &$filter_games) {
$name = strtolower(str_replace("_servers", "", $game->attr('id') ?? 'Unknown'));
if (!is_null($filter_games) && !empty($filter_games) && !in_array($name, $filter_games)) return;
$serverRows = $game->filterXPath("//tr[contains(@class, 'server-row')]");
$serverRows->each(function (Crawler $row) use (&$servers, &$name, &$game) {
$hostnameNode = $row->filter('td.server-hostname');
$ipNode = $row->filter('[data-ip]');
$portNode = $row->filter('[data-port]');
$gameModeNode = $row->filter('td.server-gametype');
$mapNameNode = $row->filter('td.server-map');
$clientInfoNode = $row->filter('td.server-clientnum');
$server = [
"name" => $hostnameNode->count() ? $hostnameNode->attr('data-hostname') : '',
"ip" => $ipNode->count() ? $ipNode->attr('data-ip') : '',
"port" => $portNode->count() ? $portNode->attr('data-port') : '',
"mode" => $gameModeNode->count() ? $gameModeNode->attr('data-gametype') : '',
"map" => $mapNameNode->count() ? $mapNameNode->attr('data-map') : '',
"clients_online" => $clientInfoNode->count() ? $clientInfoNode->attr('data-clientnum') : '',
"clients_max" => $clientInfoNode->count() ? $clientInfoNode->attr('data-maxclientnum') : '',
];
if ($server["ip"] === "0.0.0.0" || $server["ip"] === "127.0.0.1") return;
if (!array_key_exists($name, $servers)) $servers[$name] = array();
appendThings($servers, $name, $server); // TODO: Fix this omg
});
});
return $servers;
}
function getServersFromJSON($url) {
global $filter_games;global $filter_modes;global $filter_names;global $no_trickshot;global $minclients;global $maxclients;
if (!isset($url)) $url = "http://api.raidmax.org:5000/instance/";
$data = json_decode(fetchFileWithCaching($url, 60, "servers.json"), true);
$servers = [];
foreach ($data as $instance) {
if (isset($instance['servers'])) {
foreach ($instance['servers'] as $server) {
$game = strtolower($server['game']);
if (!is_null($filter_games) && $filter_games && !in_array($game, $filter_games)) continue;
$hostname = $server['hostname'];
$lower_hostname = strtolower($hostname);
if (!is_null($filter_names) && $filter_names && in_array($lower_hostname, $filter_names)) continue;
if ($no_trickshot && in_array($lower_hostname, ["trick","ts"])) continue;
$ip = $server['ip'];
$port = $server['port'];
$gametype = $server['gametype'];
if (!is_null($filter_modes) && $filter_modes && !in_array($gametype, $filter_modes)) continue;
$map = $server['map'];
$clients_online = $server['clientnum'];
if (!is_null($minclients) && $minclients && $clients_online < $minclients) continue;
if (!is_null($maxclients) && $maxclients && $clients_online > $maxclients) continue;
$clients_max = $server['maxclientnum'];
$game_version = $server['version'];
$server = compact('hostname', 'ip', 'port', 'gametype', 'map', 'clients_online', 'clients_max', 'game_version');
if (!array_key_exists($game, $servers)) $servers[$game] = array();
appendThings($servers, $game, $server); // TODO: Fix this omg
}
}
}
// print_r($servers);
return $servers;
}
$currentUrl = getCurrentUrl();
$filter_games = get("games", NULL);
if (!is_null($filter_games)) {
$filter_games = explode(",", strtolower($filter_games));
}
$filter_modes = get("modes", NULL);
if (!is_null($filter_modes)) {
$filter_modes = explode(",", strtolower($filter_modes));
}
$filter_names = get("names", NULL);
if (!is_null($filter_names)) {
$filter_names = array_map('strtolower', explode(",", strtolower($filter_names)));
}
$no_trickshot = isset($_GET["no_ts"]);
$minclients = get("minclients", NULL);
if (!is_null($minclients)) {
$minclients = intval($minclients);
}
$maxclients = get("maxclients", NULL);
if (!is_null($maxclients)) {
$maxclients = intval($maxclients);
}
$url = get("url", NULL);
$force = get("force", false);
if (isset($_GET["scrape"])) $servers = scrapeServersFromHTML($url);
else $servers = getServersFromJSON($url);
$sort = get("sort", "clients_online");
if (!is_null($sort)) {
foreach($servers as $game => &$game_servers) {
uasort($game_servers, fn($a, $b) => $a[$sort] <=> $b[$sort]);
}
}
$output = "";$filename = "servers.txt";
$format = get("format", "html");
switch ($format) {
case "php":
header('Content-Type: text/plain');
$output = var_export($servers, true);
$filename="servers.php";
break;
case "php-pretty":
header('Content-Type: text/html');
$output = highlight_array($servers, 'servers');
$filename="servers.html";
break;
case "txt":
header('Content-Type: text/plain');
foreach($servers as $game => $game_servers) {
foreach($game_servers as $server) {
$output .= $server["ip"] . ":" . (empty($server["port"]) ? '28960' : $server["port"]) . "\n";
}
}
$filename="servers.txt";
break;
case "csv":
if (isset($_GET["dl"])) header("Content-type: text/csv");
else header('Content-Type: text/plain');
$output = generateCsv($servers);
$filename="servers.csv";
break;
case "json":
header('Content-Type: application/json');
$output = json_encode(array_filter($servers), JSON_PRETTY_PRINT);
$filename="servers.json";
break;
case "favorites":
header('Content-Type: application/json');
$favs = array();
foreach($servers as $game => $game_servers) {
foreach($game_servers as $server) {
$favs[] = $server["ip"] . ":" . (empty($server["port"]) ? '28960' : $server["port"]);
}
}
sort($favs);
$output = json_encode(array_filter($favs), JSON_PRETTY_PRINT);
$filename="servers.json";
break;
case "html":
header('Content-Type: text/html');
print_banner();
$output .= '<script> $(document).ready(function() { $(".table").tablesorter({
theme : "blue",
sortList: [[6,1],[8,1]]
}); }); </script>';
// foreach($servers as $game => $game_servers) {
// $_url = addToUrl($currentUrl, "games", $game);
// // $output .= "<h1><a href=\"" . $_url . "\">" . strtoupper(normalize($game)) . "</a> (" . count($game_servers) . ")</h1>";
// // $output .= generateHtmlTable($game_servers);
// }
$output .= '<script> $(document).ready(function() { $(".table").tablesorter(); }); </script>';
$output .= '<div class="container" style="min-width:95%;margin-left:auto;margin-right:auto;">';
// $output .= '<h2>Server List</h2>';
// $output .= '<p><strong>Note:</strong> Click on the headers to expand/collapse the server lists.</p>';
$output .= '<div class="accordion" id="server-accordion">';
ksort($servers);
$collapse = count($servers) > 1 ? "collapse" : "";
foreach($servers as $game => $game_servers) {
// $_url = writeUrlAddParam($currentUrl, "games", "filter");
$output .= '</br><div class="card">';
$output .= '<div class="card-header">';
$output .= '<h4 class="panel-title">';
$output .= '<a data-toggle="collapse" data-parent="#server-accordion" href="#servers_' . htmlspecialchars($game) . '"><center>';
$output .= strtoupper(normalize($game)); // . ' (' . count($game_servers) . ')';
$output .= '</center></a>';
// $output .= "&nbsp;(" . $_url . ")";
$output .= '</h4></div>';
$output .= "<div id='servers_" . htmlspecialchars($game) . "' class='$collapse'>";
$output .= '<div class="card-body">';
$output .= generateHtmlTable($game_servers);
$output .= '</div></div></div>';
}
$output .= '</div></div>';
$filename="servers.html";
break;
default:
die("\"$format\" is not a valid format!");
$filename="servers";
}
if (isset($_GET["filename"])) $filename = get("filename",$filename);
if (isset($_GET["dl"])) header('Content-Disposition: attachment; filename="' . $filename . '"');
echo $output;
// else header('Content-Disposition: inline; filename="' . $filename . '"');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment