Bot de telegrama que monitora o domínio

Olá para os moradores de Habr.

No processo de aprendizado de PHP, tive a idéia de praticar escrever alguns bot em PHP, sem usar estruturas.

A escolha recaiu sobre o bot, que receberá informações sobre a vida útil do domínio (whois), obterá a data de registro e incluirá esse domínio no banco de dados (mysql), com subsequente vinculação ao usuário e notificação em telegrama.

O código fonte no meu repositório no gita.

Eu queria usar a estrutura MVC , o que na minha opinião não era bem verdade, já que a visão não estava envolvida e isso não pode mais ser chamado de mvc, mas tudo bem ...

Estrutura de aplicação




Controladores - Um link que conecta o modelo e a lógica do aplicativo.
Modelos - Arquivos da "lógica de negócios" do aplicativo (tentei "empinar" todo o sql aqui).
Núcleo - arquivos "principais" do aplicativo.
Biblioteca - as bibliotecas usaram a biblioteca para analisar informações de nome de domínio.

Encaminhamento


O arquivo de roteamento (routes.php) está localizado no diretório principal .
2 endereços são adicionados no aplicativo:

/ bot - o Telegramm vai para esse endereço (você precisa definir o webhook para este endereço de uri / bot).
/ check - Nesse endereço, o wget rompe com o cron 1 por dia (às 12 horas), mais sobre isso mais tarde.

Botcontroller


Após a transição para esse controlador, obtemos os valores do corpo da solicitação POST e decodificamos como uma matriz.

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

php: // input - pega o corpo da solicitação POST

Checkercontroller


Após a transição para este controlador, é acionado um script que verifica todos os domínios e certificados SSL adicionados quanto à expiração, com o intervalo:

  • data atual
  • 2 dias
  • 7 dias
  • 30 dias

E envia notificações se a data de validade do domínio e do certificado SSL terminar.

Adicionando usuários


Quando o usuário escreve uma mensagem no bot de telegrama webhook e a envia para o nosso site, recebemos uma mensagem no formato json, que precisamos decodificar e converter em uma matriz para trabalhos futuros.



Vamos trabalhar com a matriz de mensagens.

Obter da mensagem da matriz ['chat'] : id , first_name
onde:

id - id de bate-papo
first_name - Nome de usuário

E a partir da matriz da mensagem ['text'] , obtemos o comando enviado pelo usuário.

Encontramos o usuário na tabela de usuários, se ele não estiver lá, crie

 //   $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; 

Adicionando domínios e SSL


Ao enviar o comando / addDomain url para o bot, obtemos o URL do domínio a partir do comando e obtemos os dados de registro do domínio usando esta biblioteca .

Obter o domínio


Recebemos uma resposta na forma de texto:



Usando expressões regulares , obtemos a data de registro do domínio.

 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]; 

Obter SSL


Eu decidi obter um certificado SSL usando o openssl para 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("Ymd", strtotime($date)); $date = str_replace('.','-',$date); return $date; 

Assim temos:

 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 

Analise o resultado usando expressões regulares

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



Resta apenas adicionar os dados à tabela.

 $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]); 

Ligamos o domínio e o ssl ao usuário


Os dados obtidos simplesmente precisam ser registrados em uma tabela intermediária para não "multiplicar" os domínios.

 $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]); 

Verificando a data de término do domínio


Quando o wget vai para o endereço / check, todos os domínios e certificados SSL com data de validade são selecionados e, se houver algum, ele envia uma mensagem de bate-papo à qual esse domínio está vinculado.

 $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


A coroa deste projeto é necessária para organizar a transição para o endereço '/ check', todos os dias às 12 horas.

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

Proxy Tor


Algumas palavras sobre o envio de mensagens para o telegrama.

Infelizmente, no território do meu país (Rússia), eles bloqueiam o telegrama, incluindo sua API.
Eu tenho que usar um proxy, minha escolha recaiu sobre o proxy (desde o último projeto).

Ele só precisa ser instalado.

 sudo apt-get install tor 

O proxy estará disponível na porta 9050.

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

Obrigado a todos por ler este artigo!

Este é o meu primeiro artigo, por isso não julgue estritamente :)

Comente este post, terei prazer em aceitar qualquer crítica.

O código fonte do projeto no meu repositório github :)

Source: https://habr.com/ru/post/pt485392/


All Articles