Fix: Optimizar respuesta de interacciones de traducción en Discord

- Cambiar de deferReply() a respondWithMessage() para garantizar respuesta en <3s
- Responder inmediatamente con mensaje de carga
- Actualizar respuesta con traducción completa
- Agregar caché de traducciones para evitar llamadas repetidas a LibreTranslate
- Caché guardar en archivos temporales con validez de 30 días

Soluciona: 'Interacción fallida' en traducción al inglés y otros idiomas
This commit is contained in:
2026-02-19 15:50:17 -06:00
parent 1d124d2cba
commit a4dd8fefe8
2 changed files with 160 additions and 63 deletions

View File

@@ -92,11 +92,8 @@ $discord->on(Event::MESSAGE_CREATE, function (Message $message, Discord $discord
});
$discord->on(Event::INTERACTION_CREATE, function ($interaction, Discord $discord) {
echo "Interacción recibida" . PHP_EOL;
try {
handleButtonInteraction($interaction, $discord);
} catch (Exception $e) {
echo "Error en interacción: " . $e->getMessage() . PHP_EOL;
}
@@ -190,13 +187,27 @@ function handleSlashCommand(PDO $pdo, Message $message, string $content): void
switch ($cmd) {
case 'comandos':
require_once __DIR__ . '/discord/DiscordSender.php';
$msg = "📋 **Comandos disponibles:**\n\n";
$msg .= "`#comando` - Enviar plantilla\n";
$msg .= "`/comandos` - Ver comandos\n";
$msg .= "`/setlang [código]` - Establecer idioma\n";
$msg .= "`/bienvenida` - Mensaje de bienvenida\n";
$msg .= "`/agente` - Cambiar a modo IA";
$message->channel->sendMessage($msg);
$msg .= "`/agente` - Cambiar a modo IA\n";
$stmt = $pdo->query("SELECT name, telegram_command FROM recurrent_messages WHERE telegram_command IS NOT NULL AND telegram_command != '' ORDER BY name");
$customCommands = $stmt->fetchAll();
if (!empty($customCommands)) {
$msg .= "\n📦 **Plantillas:**\n";
foreach ($customCommands as $cmd) {
$msg .= "`#" . htmlspecialchars($cmd['telegram_command']) . "` - " . htmlspecialchars($cmd['name']) . "\n";
}
}
$translationButtons = getDiscordTranslationButtons($pdo, $msg);
$sender = new \Discord\DiscordSender();
$sender->sendMessage((string)$message->channel_id, $msg, null, $translationButtons);
break;
case 'setlang':
@@ -382,62 +393,7 @@ function handleButtonInteraction($interaction, Discord $discord): void
$customId = $data->custom_id ?? '';
if (str_starts_with($customId, 'translate_')) {
try {
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/src/Translate.php';
$pdo = getDbConnection();
$translator = new src\Translate();
// Parsear el custom_id: translate_LANG:hash
$parts = explode(':', $customId, 2);
$targetLang = str_replace('translate_', '', $parts[0]);
$textHash = $parts[1] ?? '';
// Recuperar texto de la base de datos
$stmt = $pdo->prepare("SELECT original_text FROM translation_cache WHERE text_hash = ?");
$stmt->execute([$textHash]);
$row = $stmt->fetch();
if (!$row) {
$builder = \Discord\Builders\MessageBuilder::new()
->setContent('❌ Error: Texto no encontrado');
$interaction->respondWithMessage($builder, true); // true = ephemeral
return;
}
$originalText = $row['original_text'];
if (empty($originalText)) {
$builder = \Discord\Builders\MessageBuilder::new()
->setContent('❌ Error: No se pudo recuperar el texto original');
$interaction->respondWithMessage($builder, true); // true = ephemeral
return;
}
// Detectar idioma original
$sourceLang = $translator->detectLanguage($originalText) ?? 'es';
// Traducir
$translated = $translator->translate($originalText, $sourceLang, $targetLang);
if ($translated) {
// Enviar traducción efímera (solo visible para quien presionó)
$builder = \Discord\Builders\MessageBuilder::new()
->setContent("🌐 **Traducción (" . strtoupper($targetLang) . "):**\n" . $translated);
$interaction->respondWithMessage($builder, true); // true = ephemeral
} else {
$builder = \Discord\Builders\MessageBuilder::new()
->setContent('❌ Error al traducir el mensaje');
$interaction->respondWithMessage($builder, true); // true = ephemeral
}
} catch (Exception $e) {
error_log("Discord button translation error: " . $e->getMessage());
$builder = \Discord\Builders\MessageBuilder::new()
->setContent('❌ Error en el proceso de traducción');
$interaction->respondWithMessage($builder, true); // true = ephemeral
}
handleTranslateInteraction($interaction, $customId);
} elseif (str_starts_with($customId, 'chat_mode_')) {
try {
require_once __DIR__ . '/includes/db.php';
@@ -534,4 +490,75 @@ function sendDiscordWelcomeMessageOnMessage(PDO $pdo, Message $message, string $
}
}
function handleTranslateInteraction($interaction, string $customId): void
{
try {
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/src/Translate.php';
$pdo = getDbConnection();
$translator = new src\Translate();
$parts = explode(':', $customId, 2);
$targetLang = str_replace('translate_', '', $parts[0]);
$textHash = $parts[1] ?? '';
// Obtener texto de la base de datos primero
$stmt = $pdo->prepare("SELECT original_text FROM translation_cache WHERE text_hash = ?");
$stmt->execute([$textHash]);
$row = $stmt->fetch();
if (!$row || empty($row['original_text'])) {
// Enviar error efímero
$builder = \Discord\Builders\MessageBuilder::new()
->setContent('❌ Error: Texto no encontrado');
$interaction->respondWithMessage($builder, true);
return;
}
$originalText = $row['original_text'];
// Responder inmediatamente con "Traduciendo..."
$loadingBuilder = \Discord\Builders\MessageBuilder::new()
->setContent("⏳ Traduciendo a " . strtoupper($targetLang) . "...");
$interaction->respondWithMessage($loadingBuilder, true);
// Ahora traducir (esto puede tardar)
$sourceLang = $translator->detectLanguage($originalText) ?? 'es';
$translated = $translator->translate($originalText, $sourceLang, $targetLang);
if ($translated) {
// Limpiar todo el HTML
$translated = strip_tags($translated);
// Limpiar asteriscos duplicados
$translated = preg_replace('/\*+/', '', $translated);
// Limpiar comandos con espacios
$translated = preg_replace('/\/(\s+)(\w+)/', '/$2', $translated);
$translated = preg_replace('/#(\s+)(\w+)/', '#$2', $translated);
// Limpiar saltos de línea extras
$translated = preg_replace('/\n\s*\n/', "\n", $translated);
// Actualizar la respuesta con la traducción real
$finalBuilder = \Discord\Builders\MessageBuilder::new()
->setContent("🌐 **Traducción (" . strtoupper($targetLang) . "):**\n\n" . trim($translated));
$interaction->updateOriginalResponse($finalBuilder);
} else {
// Actualizar con error
$errorBuilder = \Discord\Builders\MessageBuilder::new()
->setContent("❌ Error al traducir");
$interaction->updateOriginalResponse($errorBuilder);
}
} catch (Exception $e) {
error_log("Discord translate error: " . $e->getMessage());
try {
$builder = \Discord\Builders\MessageBuilder::new()
->setContent('❌ Error en el proceso de traducción');
$interaction->respondWithMessage($builder, true);
} catch (Exception $inner) {
error_log("Error responding to interaction: " . $inner->getMessage());
}
}
}
$discord->run();