- PVSM.RU - https://www.pvsm.ru -

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

Привет жителям Хабра.

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

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

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

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

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

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

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

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

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

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

BotController

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

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

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

CheckerController

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

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

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

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

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

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

Будем работать с массивом 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 домена из команды и получаем данные о регистрации домена с помощью этой библиотеки [6].

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

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

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

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


preg_match('/RegistrysExpirysDate: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 [8] для 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);

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

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


$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 к пользователю

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


$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

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

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

TOR PROXY

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

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

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

sudo apt-get install tor

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


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

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

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

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

Исходный код проекта в моем [1] репозитории на github :)

Автор: Mazay98

Источник [12]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/programmirovanie/344530

Ссылки в тексте:

[1] моем: https://github.com/Mazay98/botDomain

[2] MVC: https://habr.com/ru/post/150267/

[3] webhook: https://core.telegram.org/bots/api#setwebhook

[4] wget: https://ru.wikipedia.org/wiki/Wget

[5] php://input: https://www.php.net/manual/ru/wrappers.php.php

[6] этой библиотеки: https://github.com/regru/php-whois

[7] регулярных выражений: https://www.php.net/manual/ru/function.preg-match.php

[8] openssl: https://ru.wikipedia.org/wiki/OpenSSL

[9] промежуточную таблицу : https://metanit.com/sql/tutorial/1.3.php

[10] Крон: https://help.ubuntu.ru/wiki/cron

[11] tor proxy: https://wiki.archlinux.org/index.php/Tor_(%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9)

[12] Источник: https://habr.com/ru/post/485392/?utm_source=habrahabr&utm_medium=rss&utm_campaign=485392