VERSION 1.1.3s

Status
Not open for further replies.

Bobby

Staff member
Messages
9
Reaction score
0
Points
3
Location
Iceland
С данным обновлением была упрощена интеграция серверов с рейтингом:
  • Расширен перечень баннеров для HTML - кнопок, добавлены 5 баннеров 88х31.
  • Опубликована API - документация для администраторов серверов, с базовыми методами парсинга данных.
  • Доступен готовый скрипт выдачи бонусов за голосование для серверов World of Warcraft.
  • Актуализирован перевод и текст сообщений.
PHP:
<?php
header('Content-Type: text/html; charset=utf-8');
/* url к файлу статистики в формате json */
$config['staturl'] = 'https://api.mmorpg.top/api/user/server/...';
$config['world_name'] = 'SERVER NAME';//название мира как в топе mmorpg.top
/*
Чтобы включить soap, измените строчку 'SOAP.Enabled = 0' на 'SOAP.Enabled = 1' в файле worldserver.conf
Также вам необходимо установить SOAP для php:
    Чтобы установить soap в Ubuntu/Debian необходимо выполнить команду:
        sudo apt-get install php-soap
    В CentOS так:
        sudo yum install php-soap
    Активировать модуль можно так:
        sudo phpenmod soap
    Перезапустим Apache2 чтобы применить изменения
        sudo service apache2 restart
*/
$config['soapenable'] = true;//отправлять награду через soap? true/false
$config['soaphost'] = 'localhost';//адрес для подключения к soap
/*
Если WoW сервер и данный скрипт находятся на разных серверах,
вам потребуется изменить строчку 'SOAP.IP = "127.0.0.1"' на 'SOAP.IP = "0.0.0.0"',
либо введите туда ip адрес сервера, где расположен данный скрипт.
*/
$config['soapport'] = 7878;//порт для подключения к soap (параметр SOAP.Port в файле worldserver.conf)
$config['soapuser'] = 'user';//логин аккаунта WoW для подключения к soap, требуется GM уровень >= 3
$config['soappass'] = 'pass';//пароль аккаунта WoW для подключения к soap
$config['soapuri'] = 'urn:TC';
/* обычно urn:TC, но зависит от ядра, чтобы узнать точно, вам нужно выставить SOAP.IP = "0.0.0.0",
далее зайти по адресу http://АЙПИ_СЕРВЕРА:ПОРТ_SOAP, и найти на странице "xmlns:ns1=", там будет указан данный параметр
*/
$config['soapcommand'] = 'send items {name} "Награда за голос" "Спасибо, что поддерживаете наш сервер в топе mmorpg.top" 40752';
/*команда, которая будет отправляться серверу для награждения игрока
{name} - имя игрока, которое он ввёл при голосовании за сервер
40752 - айди предмета, который будет отправлен на почту игроку, в данном случае это [Эмблема героизма]
Вы можете изменить команду на любую другую, например на '.send money {name} "Тема письма" "Текст письма" 10000', в таком случае игрок получит 1 золотую монету (10000 бронзы)
*/
$config['dbname_realmd'] = 'realmd';//название базы данных с таблицей аккаунтов
$config['dbtable'] = 'mmorpg_votes';//название для технической таблицы в базе данных для хранения голосов игроков, таблица создаётся автоматически.
$config['dbhost_realmd'] = 'localhost';//адрес для подключения к БД с таблицей аккаунтов
$config['dbuser_realmd'] = 'root';//логин для подключения к БД с таблицей аккаунтов
$config['dbpassword_realmd'] = 'password';//пароль для подключения к БД с таблицей аккаунтов

$config['dbname_characters'] = 'characters';//название базы данных с таблицей персонажей
$config['dbhost_characters'] = 'localhost';//адрес для подключения к БД с таблицей персонажей
$config['dbuser_characters'] = 'root';//логин для подключения к БД с таблицей персонажей
$config['dbpassword_characters'] = 'password';//пароль для подключения к БД с таблицей персонажей

$config['dbreward'] = false;//отправлять награду через БД? true/false
$config['dbrewardstmt'] = "UPDATE characters.`characters` c LEFT JOIN realmd.`account` a ON a.id = c.account SET a.`shop_balance`=a.`shop_balance`+1 WHERE c.name='{name}'";
/*
    Запрос в mysql, который будет выполняться для награды игрока через базу данных.
    Данный sql запрос находит в базе данных characters в таблице `characters` персонажа с именем, которое игрок ввёл при голосовании (WHERE c.name='{name}'),
    берёт айди аккаунта у этого персонажа (ON a.id = c.account) и ищет этот аккаунт в базе realmd в таблице `account`,
    после чего в таблице `account` увеличивает столбец `shop_balance` на 1 (SET a.`shop_balance`=a.`shop_balance`+1).
    Данный sql запрос вы можете изменять по своему усмотрению.
    Обратите внимание, что в запросе нужно указывать названия баз данных (characters).`characters`, (realmd).`account`.
*/
$config['dbhost_reward'] = 'localhost';//адрес для подключения к БД для зачисления награды
$config['dbuser_reward'] = 'root';//логин для подключения к БД для зачисления награды
$config['dbpassword_reward'] = 'password';//пароль для подключения к БД для зачисления награды

/* ---- техническая часть скрипта ---- */

/* == подключаемся к БД == */
try{
    $pdo_realmd = new PDO("mysql:host=".$config['dbhost_realmd'].";dbname=".$config['dbname_realmd'].";charset=utf8", $config['dbuser_realmd'], $config['dbpassword_realmd']);
}catch (PDOException $e) {
    echo "Ошибка подключения к БД с таблицей аккаунтов\n";
    throw $e;
}
try{
    $pdo_characters = new PDO("mysql:host=".$config['dbhost_characters'].";dbname=".$config['dbname_characters'].";charset=utf8", $config['dbuser_characters'], $config['dbpassword_characters']);
}catch (PDOException $e) {
    echo "Ошибка подключения к БД с таблицей персонажей\n"
    throw $e;
}
if($config['dbreward']){
    try{
        $pdo_reward = new PDO("mysql:host=".$config['dbhost_reward'].";charset=utf8", $config['dbuser_reward'], $config['dbpassword_reward']);
    }catch (PDOException $e) {
        echo "Ошибка подключения к БД для начисления наград\n"
        throw $e;
    }
}
/* == подключаемя к soap, если включена награда через soap */
if($config['soapenable']){
    $client = new SoapClient(null, [
        'location'      =>  'http://'.$config['soaphost'].':'.$config['soapport'].'/',
        'uri'           =>  $config['soapuri'],
        'login'         =>  $config['soapuser'],
        'password'      =>  $config['soappass'],
        'style'         =>  SOAP_RPC,
        'encoding'        => 'UTF-8'
    ]);
}
/* == проверяем наличие технической таблицы в базе данных == */
$check_table = $pdo_realmd->prepare("SHOW TABLES LIKE ?");
$check_table->execute([$config['dbtable']]);
$table = $check_table->fetch();
if($table === false){//если нет таблицы, создаём её
    $create_table = $pdo_realmd->prepare("CREATE TABLE `".$config['dbtable']."` ( `id` INT NOT NULL AUTO_INCREMENT , `vote_id` VARCHAR(32) NOT NULL , `world_name` VARCHAR(255) NOT NULL , `user_id` INT(11) NOT NULL , `character_name` VARCHAR(32) NOT NULL , `date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP , PRIMARY KEY (`id`), INDEX `vote_id` (`vote_id`), INDEX `user_id` (`user_id`));");
    $create_table->execute();
}

/* == загружаем статистику с топа == */
$curl = curl_init($config['staturl']);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$html = curl_exec($curl);
curl_close($curl);
$live_votes = json_decode($html);

/* == загружаем голоса за последние 24 часа из технической базы данных == */
$stmt_votes = $pdo_realmd->prepare("SELECT * FROM `".$config['dbtable']."` WHERE `date`>='".date( 'Y-m-d H:i:s', time()-86400)."'");
$stmt_votes->execute();
$db_votes = $stmt_votes->fetchAll();
/* == ищем новые голоса == */
$new_votes = [];
foreach($live_votes as $votelive) {
    if(strtotime($votelive->date) < time()-86400){//старый голос, пропускаем
        continue;
    }
    $found = false;
    foreach($db_votes as $votedb) {
        if($votelive->voteId == $votedb["vote_id"] && $votelive->gameWorld == $config['world_name']){
            $found = true; //этот голос уже есть в технической базе, награда по нему выдана, пропускаем
        }
    }
    if(!$found){//голос не нашли в технической базе, получаем айди аккаунта игрока и добавляем в массив новых голосов
        if(!preg_match('/^([а-яА-ЯЁёa-zA-Z0-9_\s]+)$/u', $votelive->nickname))//игрок ввёл недопустимое имя персонажа, пропускаем его
            continue;
        $getAccountStmt = $pdo_characters->prepare("SELECT `account` FROM `characters` WHERE `name` = ?");//ищем персонажа в базе и получаем айди аккаунта
        $getAccountStmt->execute([$votelive->nickname]);
        $account = $getAccountStmt->fetch();
        if($account === false)//персонаж не найден, пропускаем
            continue;
        $votelive->accept = true;//переменная для следующих проверок на валидность голоса
        $votelive->user_id = $account["account"];//добавляем к голосу аккаунт игрока
        array_push($new_votes, $votelive);//добавляем голос в массив с новыми голосами
    }
}

/* == валидируем голоса == */
foreach($new_votes as $i => $vote){//проверяем все новые голоса на одинаковый акк
    foreach($new_votes as $j => $vote2){
        if($i == $j || !$vote->accept)
            continue;
        /*проверяем, не принадлежат ли голоса одному аккаунту оставленные в 1 день, если 1 голос оставлен 01.01.2022 в 23:59, а второй голос оставлен 02.01.2022 в 00:00, то оба голоса засчитываем*/
        if($vote->user_id == $vote2->user_id && date('d', strtotime($vote->date)) == date('d', strtotime($vote2->date)))
            $vote2->accept = false;//помечаем голос отклонённым
    }
}
foreach($new_votes as $i => $newvote){//проверяем все новые голоса на одинаковый акк с голосами, которые уже есть в базе
    foreach($db_votes as $j => $dbvote){
        if(!$newvote->accept)
            continue;
        if($newvote->user_id != $dbvote['user_id'])
            continue;
        if(date('d', strtotime($newvote->date)) != date('d', strtotime($dbvote['date'])))//аналогично сверяем день с голосом из бд
            continue;
        $newvote->accept = false;//помечаем голос отклонённым
    }
}

/* == добавляем в техническую таблицу новые голоса == */
$insertVotes_stmt = $pdo_realmd->prepare("INSERT INTO `".$config['dbtable']."` (`vote_id`, `world_name`, `user_id`, `character_name`, `date`) VALUES (?, ?, ?, ?, ?)");
try{
    $pdo_realmd->beginTransaction();
    foreach($new_votes as $vote){
        if(!$vote->accept)
            continue;
        $insertVotes_stmt->execute([$vote->voteId, $vote->gameWorld, $vote->user_id, $vote->nickname, $vote->date]);
    }
    $pdo_realmd->commit();
}catch(PDOException $e){
    $pdo_realmd->rollback();
    throw $e;
}

/* == рассылаем награды == */
foreach($new_votes as $vote){
    if(!$vote->accept)
        continue;
    if($config['soapenable'])//если включена награда через soap
        sendRewardSoap($vote->name);

    if($config['dbreward'])//если включена награда через mysql
        sendRewardMysql($vote->name);

}
function sendRewardSoap($name){
    global $config;
    global $client;
    try
    {
        $command = str_replace('{name}', $name, $config['soapcommand']);
        $client->executeCommand(new SoapParam($command, 'command'));
    }catch(Exception $e)
    {
        throw $e;
    }
}
function sendRewardMysql($name){
    global $config;
    global $pdo_reward;
    $sql = str_replace('{name}', $name, $config['dbrewardstmt']);
    $stmt_reward = $pdo_reward->prepare($sql);
    $stmt_reward->execute();
}
?>
______________________________________
Расшифровка значений:
Code:
voteId - key, int(11): Номер голоса в системе.
date - timestamp: Дата (День, Время).
serverId - int(10): Номер сервера в системе.
gameWorld - varchar(64): Название игрового мира.
nickname - varchar(64): Никнейм игрока.
ip - char(45): IP-адрес игрока.
voteType - int(10): Тип голоса, имеет следующие значения:
- 1 - обычный голос.
- 5 - премиум голос на 5 голосов.
- 10 - премиум голос на 10 голосов.
- 25 - премиум голос на 25 голосов.

Пример:
Code:
7    2022-02-15 18:39:17    2    Fire    Zeroman    212.133.32.xx    1

Базовый парсер:
PHP:
<?php
  $handle = curl_init();
  curl_setopt($handle, CURLOPT_URL, "https://api.mmorpg.top/api/user/server/...");
  curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
  $homepage = curl_exec($handle);
  curl_close($handle);
  echo $homepage;
?>
* Корректную ссылку можно сгенерировать в панели управления сервером.
Cron - классический демон-планировщик задач, использующийся для периодического выполнения заданий в определённое время.
Code:
Установка cron:
sudo apt update
sudo apt install cron

Установка правил для периодического выполнения заданий:
crontab -e

Примеры использования правил crontab:
- */10 * * * * php /opt/auto_reward.php - запускает скрипт auto_reward.php каждые 10 минут.
- 0 2 * * * php /opt/auto_reward.php - запускает скрипт auto_reward.php каждый день в 02:00.

При обнаружении ошибок сообщайте о них в разделе Bug Report или по форме обратной связи.
 
Status
Not open for further replies.
Top