Мониторинг сервера CS:S

Скрипт мониторинга сервера CS:S какой стоит на этом сайте.

Для работы мониторинга надо плагины:
- SoD Player Stats
- Chat Logger

Создаем config.php.

В нем будем такое вот:
$host = "ip адрес";
$port = "порт сервера";
$username = "логин фтп";
$password = "пароль фтп";
$destination_file = getcwd()."/other/cssdm.sq3"; // куда грузить бд
$source_file = "cstrike/addons/sourcemod/data/sqlite/sourcemod-local.sq3";
$rcon = "пароль Rcon";
$destination_file_txt = getcwd()."/other/chatdm.txt"; // куда грузить файл с чат-логом
$source_file_txt = "cstrike/addons/sourcemod/logs/chat_".date('Ymd').".txt";


Создаем файл index.php. И копируем в него это:
require_once 'config.php';

if( !defined( '__DIR__' ) ) {
	define( '__DIR__', dirname( __FILE__ ) );
}

require_once __DIR__.'/sourcequery/SourceQuery.class.php';
require_once __DIR__.'/sxgeo/SxGeo.class.php';
$SxGeo = new SxGeo(__DIR__.'/sxgeo/SxGeoCity.dat', SXGEO_BATCH | SXGEO_MEMORY); 
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />";

function dbopen($location) {
    $handle = new SQLite3($location);
    return $handle;
}
function dbclose($handle) {
    $handle->close();
}
function dbquery($dbhandle,$query) {
    $array['dbhandle'] = $dbhandle;
    $array['query'] = $query;
    $result = $dbhandle->query($query);
    return $result;
}
function dbarray(&$result) {
    $resx = $result->fetchArray();
    return $resx;
}

function online_css($ip, $port, $request) {
    $fp = @fsockopen("udp://$ip", $port, $errno, $errstr, 1);
    if (!$fp) { return FALSE; } 
    stream_set_timeout($fp, 1, 0); stream_set_blocking($fp, true);  
    if ($request == "settings" || $request == "players") {
        $challenge_code = "\xFF\xFF\xFF\xFF\x57"; 
        fwrite($fp, $challenge_code);
        $buffer = fread($fp, 4096);
        if (!trim($buffer)) { fclose($fp); return FALSE; }
        $challenge_code = substr($buffer, 5, 4);
    }
    if ($request == "info")     { $challenge = "\xFF\xFF\xFF\xFFTSource Engine Query\x00"; }
    if ($request == "players")  { $challenge = "\xFF\xFF\xFF\xFFU".$challenge_code;        }
    if ($request == "settings") { $challenge = "\xFF\xFF\xFF\xFFV".$challenge_code;        }
    fwrite($fp, $challenge);
    $buffer = fread($fp, 4096);
    if (!$buffer) { fclose($fp); return FALSE; } 
    if ($request == "settings") {
        $second_packet = fread($fp, 4096);
        if (strlen($second_packet) > 0) {
            $reverse_check = dechex(ord($buffer[8]));      
            if ($reverse_check[0] == "1")
            {
                $tmp = $buffer;                    
                $buffer = $second_packet;
                $second_packet = $tmp;
            }                 
            $buffer = substr($buffer, 13);          
            $second_packet = substr($second_packet, 9);    
            $buffer = trim($buffer.$second_packet); 
        } else {
            $buffer = trim(substr($buffer, 4)); 
        }
    }
    else
    {
        $buffer = trim(substr($buffer, 4)); 
    }
    fclose($fp); 
    if (!trim($buffer)) { return FALSE; } 
    if ($request == "info") {
        $tmp = substr($buffer, 2); 
        $tmp = explode("\x00", $tmp);
        $place = strlen($tmp[0].$tmp[1].$tmp[2].$tmp[3]) + 8;
        $data['gamemod']       = $tmp[2];
        $data['hostname']      = $tmp[0];
        $data['mapname']       = $tmp[1];
        $data['players']       = ord($buffer[$place]);
        $data['maxplayers']    = ord($buffer[$place + 1]);
        $data['password']      = ord($buffer[$place + 5]);
        $data['datatype']      = $buffer[0];               
        $data['version']       = ord($buffer[1]);          
        $data['description']   = $tmp[3];
        $data['botplayers']    = ord($buffer[$place + 2]);
        $data['server_type']   = $buffer[$place + 3];      
        $data['server_os']     = $buffer[$place + 4];      
        $data['server_bots']   = ord($buffer[$place + 2]); 
        $data['server_secure'] = ord($buffer[$place + 6]); 
        if ($data['datatype'] != "I")
        {
            return FALSE; 
        }
        return $data; 
    }
    if ($request == "players") {
        $player_number = 0;
        $position = 2;                                             
        do
        { 
            $player_number++;                                        
            $player[$player_number]['id'] = ord($buffer[$position]);
            $position ++;                                            
            while($buffer[$position] != "\x00" && $position < 4000)  
            {
                $player[$player_number]['name'] .= $buffer[$position]; 
                $position ++;
            }
            $player[$player_number]['score'] = (ord($buffer[$position + 1]))
                                             + (ord($buffer[$position + 2]) * 256)
                                             + (ord($buffer[$position + 3]) * 65536)
                                             + (ord($buffer[$position + 4]) * 16777216);
            if ($player[$player_number]['score'] > 2147483648) { $player[$player_number]['score'] -= 4294967296; }  
            $time = substr($buffer, $position + 5, 4);               
            if (strlen($time) < 4) { return FALSE; }                 
            list(,$time) = unpack("f", $time);                       
            $time = mktime(0, 0, $time);                             
            $player[$player_number]['time'] = date("H:i:s", $time);  
            $position += 9;
        }
        while ($position < strlen($buffer));                       
        return $player;
    }
    if ($request == "settings")
    {
        $tmp = substr($buffer, 2); 
        $rawdata = explode("\x00", $tmp);
        for ($i=1; $i<count($rawdata); $i=$i+2)
        {
            $rawdata[$i] = strtolower($rawdata[$i]);  
            $setting[$rawdata[$i]] = $rawdata[$i+1];  
        }
        return $setting;
    }
}

function cut_str($start, $stop, $str) {
	$spos = strpos($str, $start);
	$spos = $spos + strlen($start);
	$text = substr($str, $spos);
	$end_pos = strpos($text, $stop);
	$text = substr($text, 0, $end_pos);
	return $text;
}

function stripinput($text) {
	if (!is_array($text)) {
		$text = trim($text);
		$search = array("\"", "'", "\\", '\"', "\'", "<", ">", "&nbsp;", ", ...");
		$replace = array("&quot;", "&#39;", "&#92;", "&quot;", "&#39;", "&lt;", "&gt;", " ", "");
		$text = preg_replace("/(&amp;)+(?=\#([0-9]{2,3});)/i", "&", str_replace($search, $replace, $text));
	} else {
		foreach ($text as $key => $value) {
			$text[$key] = stripinput($value);
		}
	}
	return $text;
}

function img ($name) {
	$img = str_replace(" ", "_", strtoupper($name)).".png";
	if (file_exists(__DIR__."/flags/".$img)){
		$cont = "<img src=\"flags/".$img."\" border=\"0\" align=\"middle\" alt=\"".$name."\" title=\"".$name."\">";
	} else {
		$cont = "<img src=\"flags/00.png\" border=\"0\" align=\"middle\" alt=\"".$name."\" title=\"".$name."\">";
	}
	return $cont;
}

function translit($str) {
    $rus = array('А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', 'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я');
    $lat = array('A', 'B', 'V', 'G', 'D', 'E', 'E', 'Gh', 'Z', 'I', 'Y', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'H', 'C', 'Ch', 'Sh', 'Sch', 'Y', 'Y', 'Y', 'E', 'Yu', 'Ya', 'a', 'b', 'v', 'g', 'd', 'e', 'e', 'gh', 'z', 'i', 'y', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f', 'h', 'c', 'ch', 'sh', 'sch', 'y', 'y', 'y', 'e', 'yu', 'ya');
    return str_replace($rus, $lat, $str);
}

$db2 = dbopen($destination_file);

define( 'SQ_SERVER_ADDR', $host );
define( 'SQ_SERVER_PORT', $port );
define( 'SQ_TIMEOUT',     1 );
define( 'SQ_ENGINE',      SourceQuery :: SOURCE );
$Query = new SourceQuery( );
$Query->Connect( SQ_SERVER_ADDR, SQ_SERVER_PORT, SQ_TIMEOUT, SQ_ENGINE );	
$Query->SetRconPassword( $rcon );
$in = $Query->Rcon( 'status' );
preg_match_all("|# [0-9](.*)\n|U", $in, $arr);
$Query->Disconnect( );

$data = online_css($host, $port, "info");

echo "<br><br><h2>".$data['hostname']."</h2>
<input type='text' size='40' value='".$host.":".$port."'>
<table style='width: 100%; border-collapse: collapse;'>
<tr>
<td><img alt='".$data['mapname']."' title='".$data['mapname']."' src='".(file_exists(__DIR__."/maps/".$data['mapname'].".jpg") ? "maps/".$data['mapname'].".jpg" : "maps/noimage.jpg")."' vspace='2' style='border: 1px solid #610001'></td>
<td><pre> Игроков: ".(isset($data['players']) && isset($data['maxplayers']) ? "<b>".$data['players']."/".$data['maxplayers']."</b>" : "None")." (-".$data['botplayers']." БОТа для баланса)
 Карта: ".(isset($data['mapname']) ? "<b>".$data['mapname']."</b>" : "None")."
 Заголовок в ServerBrowser: ".$data['description']."
 Версия: ".$data['version']."
 <b>Deathmatch</b> («смертельный бой» или «бой насмерть») — вид игрового
 процесса многопользовательской компьютерной игры,
 в котором основная задача — прямое уничтожение противников..
</pre>
</td>
</tr>
</table>";

echo "<table style='width: 100%; border-collapse: collapse;'>
<tr>
<td><b>#</b></td>
<td><b>Флаг</b></td>
<td><b>Страна</b></td>
<td><b>Город</b></td>
<!--<td><b>Регион</b></td>-->
<td><b>Игрок</b></td>
</tr>";
$i = 0;

foreach ($arr[0] as $key => $value) {
    
	$str = $arr[0][$key];
	$ip = cut_str('active ', ':', $str);
	$nick = cut_str('"', '"', $str);
	$steamid = cut_str('STEAM_', ' ', $str);
	$i++;	
	$arrr = $SxGeo->getCityFull($ip);
	echo "<tr>
	<td>".$i."</td>
	<td>".img($arrr['country']['iso'])."</td>
	<td>".(empty($arrr['country']['name_en']) ? "None" : $arrr['country']['name_en'])."</td>
	<!--<td>".(empty($arrr['region']['name_en']) ? "None" : $arrr['region']['name_en'])."</td>-->
	<td>".(empty($arrr['city']['name_en']) ? "None" : $arrr['city']['name_en'])."</td>
	<td>".stripinput($nick)." (STEAM_".$steamid.")</td>
	</tr>";
}

echo "</table>";

$result = dbquery($db2, "SELECT COUNT(rank) as nng FROM players WHERE last_connect LIKE '%".date('Y-m-d')."%'");
$j = dbarray($result);

$result = dbquery($db2, "SELECT SUM(shots) as nng, SUM(hits) as nng2, SUM(kills) as nng3, SUM(headshots) as nng4 FROM players");
$k = dbarray($result);

$result = dbquery($db2, "SELECT COUNT(rank) as nng FROM players");
$l = dbarray($result);


echo "<br>Статистика: ";
echo "<br><b>Посетителей за сегодня:</b> ".number_format($j['nng']);
echo "<br><b>Посетило игроков за все время:</b> ".number_format($l['nng']);
echo "<br><b>Всего выстрелов на сервере:</b> ".number_format($k['nng']);
echo "<br><b>Всего попаданий на сервере:</b> ".number_format($k['nng2']);
echo "<br><b>Убийств на сервере:</b> ".number_format($k['nng3']);
echo "<br><b>Убийств в голову на сервере:</b> ".number_format($k['nng4']);

echo "<br><br>Проценты: ";
echo "<br><b>Процент выстрелов/попаданий на сервере:</b> ".number_format($k['nng2']/$k['nng']*100)."%";
echo "<br><b>Процент выстрелов/убийств на сервере:</b> ".number_format($k['nng3']/$k['nng']*100)."%";
echo "<br><b>Процент попаданий/убийств на сервере:</b> ".number_format($k['nng3']/$k['nng2']*100)."%";
echo "<br><b>Процент убийств/убийств в голову на сервере:</b> ".number_format($k['nng4']/$k['nng3']*100)."%";

echo "<br><br>Последнее в чатике: <br><pre>";
$lines = file($destination_file_txt);
for ($i = 1; $i<=15; $i++) echo $lines[count($lines)-$i];
echo "</pre>";

if (isset($_POST['chatgo']) && !empty($_POST['chatgo'])) {
	$text = translit($_POST['chatgo']);
	$Query->Connect( SQ_SERVER_ADDR, SQ_SERVER_PORT, SQ_TIMEOUT, SQ_ENGINE );	
	$Query->SetRconPassword( $rcon );
	$in = $Query->Rcon( 'say "'.$text.'"');
	$Query->Disconnect( );
}
 
echo "<br>Отправить в чатик сообщение: <br>
<form method='post'>
><input type='text' name='chatgo' size='40' value=''>
<input type='submit' class='button' size='40' value='OK'>
</form>";


Создаем файл cron.php
require_once 'config.php';
$conn_id = ftp_connect($host);
$login_result = ftp_login($conn_id, $username, $password);
unlink($destination_file);
if (ftp_get($conn_id, $destination_file, $source_file, FTP_BINARY)) {
    echo "OK\n";
} else {
    echo "Bad\n";
}
unlink($destination_file_txt);
if (ftp_get($conn_id, $destination_file_txt, $source_file_txt, FTP_BINARY)) {
    echo "OK 2\n";
} else {
    echo "Bad 2\n";
}
ftp_close($conn_id);
die ("done");


И ставим cron задачу. Полный путь к файлу и запуск cron.php, на интервал каждый час(@hourly).
cd /var/www/epic/data/www/название/system/source/ && php -f cron.php



Просмотров: 2070
23.02.2015, 09:41 -

Категория: Статьи » Программирование » PHP

Коментарии к Мониторинг сервера CS:S: