Бот в 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 часов.

crontab -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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *