Se refactoriza toda la comunicación con la API de Telegram para solucionar un problema de latencia severa en el entorno Docker. El problema era causado por un retraso en la resolución de red. - Se mejora la función en para forzar el uso de IPv4, añadir timeouts y soportar métodos GET/POST. - Se centraliza la lógica de la API en la clase , añadiendo los métodos , y . - Se modifica para que utilice los nuevos métodos centralizados, eliminando código cURL duplicado y aplicando la solución de red. - Se mantiene la instrumentación en para futuros diagnósticos, según lo solicitado.
226 lines
9.2 KiB
PHP
Executable File
226 lines
9.2 KiB
PHP
Executable File
<?php
|
|
|
|
// ---- INICIO DE INSTRUMENTACIÓN ----
|
|
$startTime = microtime(true);
|
|
function log_timing($message) {
|
|
static $lastTime = null;
|
|
global $startTime;
|
|
|
|
if ($lastTime === null) {
|
|
$lastTime = $startTime;
|
|
}
|
|
|
|
$now = microtime(true);
|
|
$elapsed = $now - $lastTime;
|
|
$totalElapsed = $now - $startTime;
|
|
|
|
$logMessage = sprintf(
|
|
"[%s] Total: %.4fs | Step: %.4fs | %s\n",
|
|
date('Y-m-d H:i:s'),
|
|
$totalElapsed,
|
|
$elapsed,
|
|
$message
|
|
);
|
|
|
|
// Usar __DIR__ para asegurar la ruta correcta
|
|
file_put_contents(__DIR__ . '/../logs/webhook_timing.log', $logMessage, FILE_APPEND);
|
|
|
|
$lastTime = $now;
|
|
}
|
|
// ---- FIN DE INSTRUMENTACIÓN ----
|
|
|
|
|
|
// Configurar logging de errores
|
|
error_reporting(E_ALL);
|
|
ini_set('log_errors', 1);
|
|
ini_set('error_log', __DIR__ . '/../public/logs/bot_error.log');
|
|
|
|
require_once __DIR__ . '/../config/config.php';
|
|
require_once __DIR__ . '/TelegramBot.php';
|
|
|
|
class TurnoBot {
|
|
private $bot;
|
|
private $config;
|
|
|
|
public function __construct() {
|
|
log_timing("TurnoBot: __construct start");
|
|
$this->config = require __DIR__ . '/../config/config.php';
|
|
$this->bot = new TelegramBot();
|
|
log_timing("TurnoBot: __construct end");
|
|
}
|
|
|
|
public function handleUpdate($update) {
|
|
log_timing("handleUpdate: start");
|
|
try {
|
|
// Manejar callback de botones inline
|
|
if (isset($update['callback_query'])) {
|
|
log_timing("handleUpdate: detected callback_query");
|
|
$this->handleCallback($update['callback_query']);
|
|
return;
|
|
}
|
|
|
|
// Manejar mensajes normales
|
|
if (!isset($update['message'])) {
|
|
log_timing("handleUpdate: no message found, exiting");
|
|
return;
|
|
}
|
|
|
|
$message = $update['message'];
|
|
$chatId = $message['chat']['id'];
|
|
$text = trim($message['text'] ?? '');
|
|
|
|
if (empty($text)) {
|
|
log_timing("handleUpdate: empty text, exiting");
|
|
return;
|
|
}
|
|
|
|
$textLower = mb_strtolower($text, 'UTF-8');
|
|
log_timing("handleUpdate: processing command '{$textLower}'");
|
|
|
|
// Comandos
|
|
if ($textLower === '/start' || $textLower === '/menu' || $textLower === 'menu') {
|
|
$this->sendMenu($chatId);
|
|
} elseif ($textLower === '/turnos' || $textLower === 'turnos') {
|
|
log_timing("handleUpdate: /turnos command start");
|
|
$this->bot->sendMessage($chatId, $this->bot->getTablaTurnos(8));
|
|
log_timing("handleUpdate: /turnos command end");
|
|
} elseif ($textLower === '/semana' || $textLower === 'semana' || $textLower === 'hoy') {
|
|
log_timing("handleUpdate: /semana command start");
|
|
$this->bot->sendMessage($chatId, $this->bot->getSemanaActual());
|
|
log_timing("handleUpdate: /semana command end");
|
|
} elseif ($textLower === '/ayudantes' || $textLower === 'ayudantes') {
|
|
log_timing("handleUpdate: /ayudantes command start");
|
|
$ayudantes = $this->bot->getListaAyudantesParaBusqueda();
|
|
$this->bot->sendMessage($chatId, "<b>AYUDANTES DISPONIBLES:</b>\n\n" . implode("\n", $ayudantes));
|
|
log_timing("handleUpdate: /ayudantes command end");
|
|
} elseif ($textLower === '/pdf' || $textLower === 'pdf' || $textLower === 'mi pdf') {
|
|
log_timing("handleUpdate: /pdf command start");
|
|
$this->bot->sendPDFGeneral($chatId);
|
|
log_timing("handleUpdate: /pdf command end");
|
|
} else {
|
|
log_timing("handleUpdate: searching by name '{$text}'");
|
|
$config = require __DIR__ . '/../config/config.php';
|
|
try {
|
|
log_timing("handleUpdate: DB connection start");
|
|
$pdo = new PDO(
|
|
"mysql:host={$config['db']['host']};port={$config['db']['port']};dbname={$config['db']['database']};charset=utf8mb4",
|
|
$config['db']['username'],
|
|
$config['db']['password'],
|
|
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
|
|
);
|
|
log_timing("handleUpdate: DB connection end");
|
|
} catch (Exception $e) {
|
|
log_timing("handleUpdate: DB connection FAILED");
|
|
$this->bot->sendMessage($chatId, "Error de conexion.");
|
|
return;
|
|
}
|
|
|
|
log_timing("handleUpdate: DB query start");
|
|
$stmt = $pdo->prepare("SELECT * FROM users WHERE (nombre LIKE ? OR username LIKE ?) AND rol = 'ayudante' AND activo = 1 LIMIT 1");
|
|
$stmt->execute(["%$text%", "%$text%"]);
|
|
$user = $stmt->fetch();
|
|
log_timing("handleUpdate: DB query end");
|
|
|
|
if ($user) {
|
|
log_timing("handleUpdate: user found, sending PDF");
|
|
$this->bot->sendMessage($chatId, "Generando PDF de turnos...");
|
|
$this->bot->sendPDF($chatId, $user['id']);
|
|
log_timing("handleUpdate: PDF sent");
|
|
} else {
|
|
log_timing("handleUpdate: user not found, getting plain text turnos");
|
|
$this->bot->sendMessage($chatId, $this->bot->getTurnosAyudante($text));
|
|
log_timing("handleUpdate: plain text turnos sent");
|
|
}
|
|
}
|
|
} catch (Exception $e) {
|
|
error_log("Error en handleUpdate: " . $e->getMessage());
|
|
log_timing("handleUpdate: EXCEPTION: " . $e->getMessage());
|
|
if (isset($update['message']['chat']['id'])) {
|
|
$this->bot->sendMessage($update['message']['chat']['id'], "Error: " . $e->getMessage());
|
|
}
|
|
}
|
|
log_timing("handleUpdate: end");
|
|
}
|
|
|
|
private function handleCallback($callback) {
|
|
log_timing("handleCallback: start");
|
|
try {
|
|
$callbackId = $callback['id'];
|
|
$data = $callback['data'];
|
|
$message = $callback['message'];
|
|
$chatId = $message['chat']['id'];
|
|
$messageId = $message['message_id'];
|
|
log_timing("handleCallback: processing data '{$data}'");
|
|
|
|
switch ($data) {
|
|
case 'ver_turnos':
|
|
$this->bot->answerCallback($callbackId, 'Cargando turnos...');
|
|
$this->bot->editMessage($chatId, $messageId, $this->bot->getTablaTurnos(8));
|
|
break;
|
|
|
|
case 'semana_actual':
|
|
$this->bot->answerCallback($callbackId, 'Cargando semana actual...');
|
|
$this->bot->editMessage($chatId, $messageId, $this->bot->getSemanaActual());
|
|
break;
|
|
|
|
case 'mi_pdf':
|
|
$this->bot->answerCallback($callbackId, 'Generando PDF...');
|
|
$this->bot->sendPDFGeneral($chatId);
|
|
break;
|
|
|
|
case 'buscar_nombre':
|
|
$this->bot->answerCallback($callbackId, '');
|
|
$this->bot->deleteMessage($chatId, $messageId);
|
|
$this->bot->sendMessage($chatId, "🔍 <b>Buscar por Nombre</b>\n\nEscribe el nombre del ayudante que buscas:");
|
|
break;
|
|
|
|
case 'mi_turno':
|
|
$this->bot->answerCallback($callbackId, 'Enviando tu turno...');
|
|
$this->bot->editMessage($chatId, $messageId, "Por favor ingresa tu nombre para ver tu turno:");
|
|
break;
|
|
|
|
default:
|
|
$this->bot->answerCallback($callbackId, 'Opcion no reconocida');
|
|
}
|
|
log_timing("handleCallback: data '{$data}' processed");
|
|
} catch (Exception $e) {
|
|
error_log("Error en handleCallback: " . $e->getMessage());
|
|
log_timing("handleCallback: EXCEPTION: " . $e->getMessage());
|
|
}
|
|
log_timing("handleCallback: end");
|
|
}
|
|
|
|
private function sendMenu($chatId) {
|
|
log_timing("sendMenu: start");
|
|
$mensaje = "<b>BOT DE TURNOS - CONTENEDOR IBIZA</b>\n\n";
|
|
$mensaje .= "Selecciona una opcion del menu:\n\n";
|
|
$mensaje .= "Ver Turnos - Tabla completa de asignaciones\n";
|
|
$mensaje .= "Semana Actual - Quien tiene turno esta semana\n";
|
|
$mensaje .= "Mi PDF - Descargar horarios en PDF\n";
|
|
$mensaje .= "Buscar por Nombre - Consultar un ayudante especifico\n";
|
|
$mensaje .= "Mi Turno - Ver tu proximo turno";
|
|
|
|
$this->bot->sendKeyboard($chatId, $mensaje);
|
|
log_timing("sendMenu: end");
|
|
}
|
|
}
|
|
|
|
// Recibir actualización
|
|
$update = json_decode(file_get_contents('php://input'), true);
|
|
log_timing("Webhook invoked");
|
|
|
|
|
|
// Log para debugging
|
|
// error_log("Webhook recibido: " . json_encode($update)); // Se puede comentar para no llenar el log de errores
|
|
|
|
if ($update) {
|
|
log_timing("Update received, initializing bot");
|
|
$bot = new TurnoBot();
|
|
$bot->handleUpdate($update);
|
|
log_timing("Script finished");
|
|
} else {
|
|
http_response_code(200);
|
|
log_timing("Webhook checked (no update provided)");
|
|
// echo "Webhook activo. Usa /start para ver el menu."; // No es necesario en producción
|
|
}
|