Бот в telegram, который следит за доменом

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.
Привет жителям Хабра.

В попытках изучения PHP и долгих раздумьях, пришла в голову мысль, для практики написать какого-нибудь бота на PHP, без использования фрэймворков.

Выбор пал на бота, который будет получать информацию о жизни домена (whois), затем доставать оттуда дату регистрации и добавлять этот домен в БД (mysql), с последующий привязкой к пользователю и уведомлением в telegram.

Исходный код в моем репозитории на гите.

Мне захотелось использовать MVC структуру, что оказалось на мой взгляд не совсем верным, так как view не был задействован и это уже нельзя назвать mvc, но да ладно…

Структура приложения




Contollerrs — Связующее звено, соединяет model и логику приложения.
Models — Файлы «бизнес-логики» приложения (Старался «запихнуть» сюда весь sql).
Core — Файлы «ядра» приложения.
Library — Библиотеки, использовал библиотеку для парсинга информации о доменном имени.

Маршрутизация


Файл маршрутизации (routes.php) расположил в каталоге core.
В приложении добавлены 2 адреса:

/bot — По этому адресу идет telegramm (необходимо установить webhook на этот адрес «uri/bot»).
/check — По этому адресу ломиться wget с помощью cron 1 в день (в 12 часов), об этом чуть позже.

BotController


При переходе в данный контролер, получаем значения из тела POST запроса, и декодируем его в виде массива.

json_decode(file_get_contents('php://input'), JSON_OBJECT_AS_ARRAY);

php://input — получаем тело POST запроса

CheckerController


При переходе в данный контроллер, срабатывает скрипт, который проверяет все добавленные домены и ssl сертификаты на окончание срока действия, с интервалом:

  • текущая дата
  • 2 дня
  • 7 дней
  • 30 дней

И отправляет уведомления если дата срока действия домена и ssl сертификата заканчивается.

Добавление пользователей


Когда пользователь пишет сообщение боту webhook telegram, отправляет его на наш сайт, далее нам приходит сообщение в json формате, которое нам нужно декодировать, и преобразовать в массив для дальнейшей работы.



Будем работать с массивом message.

Получаем из массива message['chat']: id , first_name
где:

id — идентификатор чата
first_name — Имя пользователя

А из массива message['text'], получаем отправленную пользователем команду.

Находим пользователя в таблице users, если его нет, создаем


// Ищем пользователя
$sql= "SELECT user_id FROM users WHERE chat_id=?";
$stmt = $db->prepare($sql);
$stmt->execute([$chat_id]);
$rows = $stmt->fetch(PDO::FETCH_ASSOC);
return (int)$rows['user_id'];


// Создаем пользователя
$sql = 'INSERT INTO users (user_name, chat_id) VALUES (:user_name, :chat_id)';
$insert = $db->prepare($sql);
$insert->execute([':user_name' => $name, ':chat_id' => $chat_id]);
return true;

Добавление Доменов и SSL


При отправке команды /addDomain url боту, получаем url домена из команды и получаем данные о регистрации домена с помощью этой библиотеки.

Получаем домен


Нам приходит ответ в виде текста:



Из него с помощью регулярных выражений, получаем дату регистрации домена.


preg_match('/Registry\sExpiry\sDate:\s(.*)\\r/', $date, $matches);
if (!$matches[1]){
    preg_match('/paid-till:\s*(.*)\\n/', $date, $matches);
}
$matches[1] = $this->formatDate($matches[1]);
return $matches[1];

Получаем SSL


SSL сертификат решил получать с помощью openssl для linux.


$getDomainSSL = shell_exec("echo | openssl s_client -servername $url -connect $url:443 2>/dev/null | openssl x509 -noout -dates");
preg_match('~notAfter=(\w+)\s(\d+)\s.+\s(\d+)~', $getDomainSSL, $matches);
$date =  $matches[2].$matches[1].$matches[3];
$date =  date("Y.m.d", strtotime($date));
$date = str_replace('.','-',$date);
return $date;

Таким образом получаем:

echo | openssl s_client -servername google.com -connect google.com:443 2>/dev/null | openssl x509 -noout -dates
notBefore=Jan  7 15:47:12 2020 GMT
notAfter=Mar 31 15:47:12 2020 GMT

Разбираем полученное с помощью регулярных выражений

preg_match('~notAfter=(\w+)\s(\d+)\s.+\s(\d+)~', $getDomainSSL, $matches);



Остается только добавить полученные данные в таблицу.


$sql = 'INSERT INTO domains (domain_name, date_start, date_end, date_end_ssl) VALUES (:domain_name, :date_start, :date_end, :date_end_ssl)';
$insert = $db->prepare($sql);
$insert->execute([':domain_name' => $url, ':date_end' => $exp, ':date_end_ssl'  => $ssl_date]);

Привязываем домен и ssl к пользователю


Полученные данные нужно просто записать в промежуточную таблицу для того чтобы не «размножать» домены.


$sql = 'INSERT INTO domain_users (user_id, domain_id) VALUES (:user_id, :domain_id)';
$insert = $db->prepare($sql);
$insert->execute([':user_id' => $user_id, ':domain_id' => $domain_id]);

Проверка даты окончания домена


Когда wget переходит по адресу /check, происходит выборка всех доменов и ssl сертификатов, у которых срок действия подходит к концу, и если такие есть, отправляет сообщение в чат к которому привязан данный домен.


$db = $this->db;

$sql= "
	SELECT user_name, chat_id, domain_name, date_end 
	FROM domain_users JOIN users USING (user_id)
	JOIN domains USING (domain_id)
	WHERE (
		domains.date_end = CURDATE() OR 
		domains.date_end = CURDATE() + INTERVAL 2 DAY OR 
		domains.date_end = CURDATE() + INTERVAL 7 DAY  OR 
		domains.date_end = CURDATE() + INTERVAL 30 DAY
	)
";
$stmt = $db->prepare($sql);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

CRON


Крон в данном проекте нужен для организации перехода по адресу '/check', каждый день в 12 часов.

crintab -e
0 12 * * * wget url/check

TOR PROXY


Пару слов о отправки сообщений в telegram.

К сожалению на территории мой страны (Россия), блокируют telegram, в том числе и его api.
Приходится использовать прокси, мой выбор пал на tor proxy (еще с прошлого проекта).

Его необходимо просто установить.

sudo apt-get install tor

Затем прокси будет доступен по порту 9050.


curl_setopt($myCurl, CURLOPT_PROXYTYPE, 7);
curl_setopt($myCurl, CURLOPT_PROXY, "127.0.0.1:9050");

Всем спасибо за прочтение данной статьи!

Эта моя первая статья, поэтому не судите строго :)

Комментируйте данный пост, с удовольствием приму любую критику.

Исходный код проекта в моем репозитории на github :)
Источник: https://habr.com/ru/post/485392/


Интересные статьи

Интересные статьи

Недавно мы писали про протектор, который скрывает вредоносную программу AgentTesla, заслуженного пенсионера на рынке вредоносного ПО. Однако AgentTesla и не думает уходить со сцены, с...
Недавно на проекте интегрировал модуль CRM Битрикса c виртуальной АТС Ростелеком. Делал по стандартной инструкции, где пошагово показано, какие поля заполнять. Оказалось, следование ей не гаран...
На работе я занимаюсь поддержкой пользователей и обслуживанием коробочной версии CRM Битрикс24, в том числе и написанием бизнес-процессов. Нужно отметить, что на самом деле я не «чист...
«Время жизни» технологий сократилось — смартфоны можно менять хоть каждый год. Но пока еще есть оборудование, которое работает на протяжении десятилетий и, вероятно, проработает еще долгие годы. ...
Как быстро определить, что на отдельно взятый сайт забили, и им никто не занимается? Если в подвале главной страницы в копирайте стоит не текущий год, а старый, то именно в этом году опека над са...