Hola a los residentes de Habr.
En el proceso de aprendizaje de PHP, se me ocurrió la idea de practicar escribir algún bot en PHP, sin usar frameworks.
La elección recayó en el bot, que recibirá información sobre la vida del dominio (whois), luego obtendrá la fecha de registro desde allí y agregará este dominio a la base de datos (mysql), con el posterior enlace al usuario y notificación en telegrama.
El código fuente en
mi repositorio en gita.
Quería usar la estructura
MVC , que en
mi opinión no era del todo cierto, ya que la vista no estaba involucrada y esto ya no se puede llamar mvc, pero bueno ...
Estructura de aplicación
Controladores : un enlace que conecta el modelo y la lógica de la aplicación.
Modelos : archivos de la "lógica de negocios" de la aplicación (intenté "meter" todo el sql aquí).
Core : archivos "core" de la aplicación.
Biblioteca : las bibliotecas utilizan la biblioteca para analizar la información del nombre de dominio.
Enrutamiento
El archivo de enrutamiento (routes.php) se encuentra en el directorio
central .
Se agregan 2 direcciones en la aplicación:
/ bot :
Telegramm va a esta dirección (debe configurar el
webhook en esta dirección uri / bot).
/ check : en esta dirección,
wget rompe con cron 1 por día (a las 12 en punto), más sobre eso más adelante.
Controlador de bot
Tras la transición a este controlador, obtenemos los valores del cuerpo de la solicitud
POST y lo decodificamos como una matriz.
json_decode(file_get_contents('php://input'), JSON_OBJECT_AS_ARRAY);
php: // input - obtiene el cuerpo de la solicitud POST
Checkercontroller
Tras la transición a este controlador, se activa un script que verifica la caducidad de todos los dominios y certificados SSL agregados, con el intervalo:
- fecha actual
- 2 dias
- 7 dias
- 30 dias
Y envía notificaciones si finaliza la fecha de vencimiento del dominio y el certificado SSL.
Agregar usuarios
Cuando el usuario escribe un mensaje en el bot de telegramas webhook, lo envía a nuestro sitio web, luego recibimos un mensaje en formato json, que necesitamos decodificar y convertir a una matriz para un trabajo posterior.

Trabajaremos con la matriz de
mensajes.Obtener del
mensaje de matriz
['chat'] :
id ,
first_namedonde:
id -
id de chat
first_name - Nombre de usuario
Y de la matriz de
mensaje ['texto'] , recibimos el comando enviado por el usuario.
Encontramos al usuario en la tabla de usuarios, si no está allí, crea
Agregar dominios y SSL
Al enviar el
comando / addDomain url al bot, obtenemos la url del dominio del comando y obtenemos los datos de registro del dominio utilizando
esta biblioteca .
Obtén el dominio
Recibimos una respuesta en forma de texto:

Usando
expresiones regulares , obtenemos la fecha de registro del dominio.
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];
Obtén SSL
Decidí obtener un certificado SSL usando
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;
Así obtenemos:
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
Analiza el resultado usando expresiones regulares
preg_match('~notAfter=(\w+)\s(\d+)\s.+\s(\d+)~', $getDomainSSL, $matches);

Solo queda agregar los datos a la tabla.
$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]);
Vinculamos el dominio y ssl al usuario
Los datos obtenidos simplemente deben registrarse en
una tabla intermedia para no "multiplicar" los dominios.
$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]);
Comprobación de la fecha de finalización del dominio
Cuando wget va a la dirección / check, se seleccionan todos los dominios y certificados SSL con una fecha de vencimiento, y si los hay, envía un mensaje de chat al que está vinculado este dominio.
$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
La corona en este proyecto es necesaria para organizar la transición a la dirección '/ cheque', todos los días a las 12 en punto.
crontab -e 0 12 * * * wget url/check
Tor proxy
Algunas palabras sobre el envío de mensajes a telegram.
Desafortunadamente, en el territorio de mi país (Rusia), bloquean el telegrama, incluida su API.
Tengo que usar un proxy, mi elección recayó en el
proxy tor (desde el último proyecto).
Solo necesita ser instalado.
sudo apt-get install tor
Entonces el proxy estará disponible en el puerto 9050.
curl_setopt($myCurl, CURLOPT_PROXYTYPE, 7); curl_setopt($myCurl, CURLOPT_PROXY, "127.0.0.1:9050");
¡Gracias a todos por leer este artículo!
Este es mi primer artículo, así que no juzgues estrictamente :)
Comente esta publicación, aceptaré con gusto cualquier crítica.
El código fuente del proyecto en
mi repositorio github :)