Primer commit del sistema separado falta mejorar mucho
This commit is contained in:
278
telegram/webhook/index.php
Executable file
278
telegram/webhook/index.php
Executable file
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
/**
|
||||
* Webhook Principal de Telegram
|
||||
* Recibe actualizaciones (mensajes, callbacks, etc.)
|
||||
*/
|
||||
|
||||
// Habilitar logging de errores en archivo, no en salida
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('log_errors', 1);
|
||||
ini_set('error_log', __DIR__ . '/../../logs/webhook_errors.log');
|
||||
|
||||
require_once __DIR__ . '/../../shared/utils/helpers.php';
|
||||
require_once __DIR__ . '/../../shared/database/connection.php';
|
||||
|
||||
// Cargar variables de entorno
|
||||
if (file_exists(__DIR__ . '/../../.env')) {
|
||||
$lines = file(__DIR__ . '/../../.env', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
foreach ($lines as $line) {
|
||||
if (strpos(trim($line), '#') === 0) continue;
|
||||
if (strpos($line, '=') === false) continue;
|
||||
list($key, $value) = explode('=', $line, 2);
|
||||
$_ENV[trim($key)] = trim($value);
|
||||
}
|
||||
}
|
||||
|
||||
// Constantes de Telegram
|
||||
define('TELEGRAM_BOT_TOKEN', $_ENV['TELEGRAM_BOT_TOKEN'] ?? getenv('TELEGRAM_BOT_TOKEN'));
|
||||
define('TELEGRAM_WEBHOOK_TOKEN', $_ENV['TELEGRAM_WEBHOOK_TOKEN'] ?? getenv('TELEGRAM_WEBHOOK_TOKEN')); // Token secreto para verificar el webhook
|
||||
|
||||
// Función auxiliar para registrar/actualizar destinatarios en la base de datos local
|
||||
function registerTelegramRecipient($db, $chatId, $chatType, $firstName = null, $lastName = null, $username = null) {
|
||||
$db = getDB(); // Asegurarse de tener una conexión a DB
|
||||
|
||||
// Asignar un nombre si no está disponible (ej. para canales o si no hay first_name)
|
||||
$name = $firstName ?: ($username ?: 'Chat/Usuario Telegram');
|
||||
|
||||
// Buscar si el destinatario ya existe
|
||||
$stmt = $db->prepare("SELECT id FROM destinatarios_telegram WHERE telegram_id = ?");
|
||||
$stmt->execute([$chatId]);
|
||||
$existingRecipient = $stmt->fetch();
|
||||
|
||||
if (!$existingRecipient) {
|
||||
// Si no existe, insertarlo
|
||||
$stmt = $db->prepare(<<<'SQL'
|
||||
INSERT INTO destinatarios_telegram (telegram_id, tipo, nombre, username, fecha_registro, ultima_interaccion)
|
||||
VALUES (?, ?, ?, ?, NOW(), NOW())
|
||||
SQL);
|
||||
$stmt->execute([$chatId, $chatType, $name, $username]);
|
||||
logToFile('telegram/recipients.log', "Nuevo destinatario registrado vía webhook: {$name} ({$chatId}) de tipo {$chatType}");
|
||||
} else {
|
||||
// Si existe, actualizar nombre y última interacción
|
||||
$stmt = $db->prepare("UPDATE destinatarios_telegram SET nombre = ?, username = ?, ultima_interaccion = NOW() WHERE telegram_id = ?");
|
||||
$stmt->execute([$name, $username, $chatId]);
|
||||
}
|
||||
}
|
||||
|
||||
// Función auxiliar para traducir texto
|
||||
function translateTextTelegram($text, $targetLang) {
|
||||
if (empty($text) || empty($targetLang) || empty(LIBRETRANSLATE_URL)) {
|
||||
return $text; // No traducir si faltan datos
|
||||
}
|
||||
$libreTranslateUrl = $_ENV['LIBRETRANSLATE_URL'] ?? getenv('LIBRETRANSLATE_URL');
|
||||
|
||||
try {
|
||||
$ch = curl_init($libreTranslateUrl . '/translate');
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json'
|
||||
]);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
|
||||
'q' => $text,
|
||||
'source' => 'auto', // Detectar idioma automáticamente
|
||||
'target' => $targetLang
|
||||
]));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($httpCode === 200 && $response) {
|
||||
$translatedData = json_decode($response, true);
|
||||
return $translatedData['translatedText'] ?? $text;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("Error al traducir con LibreTranslate: " . $e->getMessage());
|
||||
}
|
||||
return $text; // Retornar original en caso de fallo
|
||||
}
|
||||
|
||||
// Función para enviar mensajes a Telegram
|
||||
function sendTelegramMessage($chat_id, $text, $botToken, $parseMode = null, $replyMarkup = null, $photoUrl = null) {
|
||||
$telegramApiUrl = "https://api.telegram.org/bot{$botToken}/";
|
||||
$method = 'sendMessage';
|
||||
$postFields = [
|
||||
'chat_id' => $chat_id,
|
||||
];
|
||||
|
||||
if ($photoUrl) {
|
||||
$method = 'sendPhoto';
|
||||
$postFields['photo'] = $photoUrl;
|
||||
$postFields['caption'] = $text;
|
||||
} else {
|
||||
$postFields['text'] = $text;
|
||||
}
|
||||
|
||||
if ($parseMode) {
|
||||
$postFields['parse_mode'] = $parseMode;
|
||||
}
|
||||
if ($replyMarkup) {
|
||||
$postFields['reply_markup'] = $replyMarkup;
|
||||
}
|
||||
|
||||
$ch = curl_init($telegramApiUrl . $method);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postFields));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
return ['ok' => $httpCode === 200, 'response' => json_decode($response, true), 'http_code' => $httpCode];
|
||||
}
|
||||
|
||||
// Verificar secret token del webhook
|
||||
$headers = array_change_key_case(getallheaders(), CASE_LOWER);
|
||||
$secretToken = $headers['x-telegram-bot-api-secret-token'] ?? '';
|
||||
|
||||
if (TELEGRAM_WEBHOOK_TOKEN && $secretToken !== TELEGRAM_WEBHOOK_TOKEN) {
|
||||
http_response_code(403);
|
||||
error_log("Acceso no autorizado al webhook de Telegram. Token secreto inválido: {$secretToken}");
|
||||
exit('Acceso no autorizado');
|
||||
}
|
||||
|
||||
// Leer el body del request
|
||||
$update = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
// Si no hay update, salir
|
||||
if (empty($update)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$db = getDB(); // Conexión a DB para todas las operaciones
|
||||
|
||||
// Extraer información del usuario/chat
|
||||
$chatId = $update['message']['chat']['id'] ?? $update['callback_query']['message']['chat']['id'] ?? null;
|
||||
$chatType = $update['message']['chat']['type'] ?? ($update['callback_query']['message']['chat']['type'] ?? null);
|
||||
$fromId = $update['message']['from']['id'] ?? $update['callback_query']['from']['id'] ?? null;
|
||||
$firstName = $update['message']['from']['first_name'] ?? $update['callback_query']['from']['first_name'] ?? null;
|
||||
$lastName = $update['message']['from']['last_name'] ?? $update['callback_query']['from']['last_name'] ?? null;
|
||||
$username = $update['message']['from']['username'] ?? $update['callback_query']['from']['username'] ?? null;
|
||||
|
||||
// Registrar o actualizar destinatario que interactúa
|
||||
if ($fromId && $fromId == $chatId) { // Es un mensaje directo o de un usuario
|
||||
registerTelegramRecipient($db, $fromId, 'usuario', $firstName, $lastName, $username);
|
||||
} elseif ($chatId && $chatType && ($chatType === 'group' || $chatType === 'supergroup' || $chatType === 'channel')) {
|
||||
registerTelegramRecipient($db, $chatId, $chatType, $firstName, $lastName, $username); // Registra el chat/canal
|
||||
}
|
||||
|
||||
|
||||
// Obtener la preferencia de idioma del usuario/chat si está registrado
|
||||
$userLang = 'es'; // Idioma por defecto
|
||||
if ($fromId) {
|
||||
$stmtLang = $db->prepare("SELECT idioma_detectado FROM destinatarios_telegram WHERE telegram_id = ? AND tipo = 'usuario'");
|
||||
$stmtLang->execute([$fromId]);
|
||||
$userLang = $stmtLang->fetchColumn() ?: 'es';
|
||||
}
|
||||
|
||||
|
||||
// --- Manejar Mensajes ---
|
||||
if (isset($update['message'])) {
|
||||
$message = $update['message'];
|
||||
$text = $message['text'] ?? '';
|
||||
|
||||
// Detección de comandos de texto
|
||||
if (strpos($text, '/') === 0) { // Podría ser un comando
|
||||
$command = explode(' ', $text)[0]; // Obtener el comando principal
|
||||
|
||||
switch ($command) {
|
||||
case '/start':
|
||||
$response = "¡Hola! Soy tu bot de Telegram. ¿En qué puedo ayudarte?";
|
||||
if ($userLang !== 'es') {
|
||||
$response = translateTextTelegram($response, $userLang);
|
||||
}
|
||||
sendTelegramMessage($chatId, $response, TELEGRAM_BOT_TOKEN);
|
||||
logToFile('telegram/interactions.log', "Usuario {$username} ({$fromId}) ejecutó /start.");
|
||||
break;
|
||||
case '/help':
|
||||
$response = "Aquí tienes una lista de comandos disponibles:\n/start - Iniciar\n/help - Ver ayuda";
|
||||
if ($userLang !== 'es') {
|
||||
$response = translateTextTelegram($response, $userLang);
|
||||
}
|
||||
sendTelegramMessage($chatId, $response, TELEGRAM_BOT_TOKEN);
|
||||
logToFile('telegram/interactions.log', "Usuario {$username} ({$fromId}) ejecutó /help.");
|
||||
break;
|
||||
// Otros comandos de texto o comandos de plantilla
|
||||
default:
|
||||
// Intentar buscar el comando en las plantillas
|
||||
$cmdName = ltrim($command, '/');
|
||||
$stmt = $db->prepare("SELECT contenido FROM plantillas_telegram WHERE comando = ?");
|
||||
$stmt->execute([$cmdName]);
|
||||
$plantilla = $stmt->fetch();
|
||||
|
||||
if ($plantilla) {
|
||||
$responseContent = $plantilla['contenido'];
|
||||
if ($userLang !== 'es') {
|
||||
$responseContent = translateTextTelegram($responseContent, $userLang);
|
||||
}
|
||||
sendTelegramMessage($chatId, $responseContent, TELEGRAM_BOT_TOKEN, 'HTML'); // Asumimos HTML para plantillas
|
||||
logToFile('telegram/interactions.log', "Usuario {$username} ({$fromId}) ejecutó comando de plantilla: {$command}.");
|
||||
} else {
|
||||
$response = "Comando `{$command}` no reconocido.";
|
||||
if ($userLang !== 'es') {
|
||||
$response = translateTextTelegram($response, $userLang);
|
||||
}
|
||||
sendTelegramMessage($chatId, $response, TELEGRAM_BOT_TOKEN);
|
||||
logToFile('telegram/interactions.log', "Usuario {$username} ({$fromId}) ejecutó comando no reconocido: {$command}.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
exit;
|
||||
} elseif (strpos($text, '#grupo') !== false) { // Ejemplo de comando de texto no-slash
|
||||
$response = "Comando de texto `#grupo` detectado. Realizando acción de grupo (placeholder).";
|
||||
if ($userLang !== 'es') {
|
||||
$response = translateTextTelegram($response, $userLang);
|
||||
}
|
||||
sendTelegramMessage($chatId, $response, TELEGRAM_BOT_TOKEN);
|
||||
logToFile('telegram/interactions.log', "Usuario {$username} ({$fromId}) ejecutó comando de texto: #grupo.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Si no es un comando, y no es un chat de grupo/canal, podrías responder algo por defecto
|
||||
// o simplemente no hacer nada. Aquí no haremos nada por mensajes no-comando.
|
||||
logToFile('telegram/interactions.log', "Mensaje no-comando de {$username} ({$fromId}): {$text}");
|
||||
}
|
||||
|
||||
// --- Manejar Callback Queries (Botones Inline) ---
|
||||
if (isset($update['callback_query'])) {
|
||||
$callbackQuery = $update['callback_query'];
|
||||
$data = $callbackQuery['data'];
|
||||
$messageId = $callbackQuery['message']['message_id'];
|
||||
$chatId = $callbackQuery['message']['chat']['id'];
|
||||
|
||||
if (strpos($data, 'lang_select_') === 0) {
|
||||
$langCode = substr($data, strlen('lang_select_'));
|
||||
|
||||
// Actualizar preferencia en BD para el usuario que presionó el botón
|
||||
$stmt = $db->prepare("UPDATE destinatarios_telegram SET idioma_detectado = ? WHERE telegram_id = ? AND tipo = 'usuario'");
|
||||
$stmt->execute([$langCode, $fromId]);
|
||||
|
||||
// Responder a la callback query (quitar el "cargando..." del botón)
|
||||
$telegramApiUrl = "https://api.telegram.org/bot{$botToken}/answerCallbackQuery";
|
||||
$ch = curl_init($telegramApiUrl);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
|
||||
'callback_query_id' => $callbackQuery['id'],
|
||||
'text' => "Idioma cambiado a {$langCode}."
|
||||
]));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// Opcional: Editar el mensaje original para mostrar la nueva preferencia
|
||||
// sendTelegramMessage($chatId, "Tu idioma ha sido configurado a **{$langCode}**", TELEGRAM_BOT_TOKEN, 'Markdown', null, null, $messageId);
|
||||
|
||||
logToFile('telegram/interactions.log', "Usuario {$username} ({$fromId}) seleccionó y guardó idioma $langCode vía callback.");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Si no se manejó ninguna actualización específica, responder con OK para Telegram
|
||||
http_response_code(200);
|
||||
exit('OK');
|
||||
|
||||
Reference in New Issue
Block a user