feat: Implement Discord translation feature with ephemeral messages and refined content filtering

This commit introduces a comprehensive message translation system for the Discord bot, featuring:
- Interactive language selection buttons for each translatable message.
- Ephemeral translation responses visible only to the requesting user.
- Robust filtering to prevent translation buttons for messages consisting solely of emojis, stickers, GIFs, or other non-translatable content.
- Preservation of non-textual elements (images, video thumbnails, stickers) alongside translated text in embeds.
- Full compatibility with DiscordPHP v7, addressing various API usage and error handling specifics (e.g.,  then , correct handling of null message properties,  intent).

Additionally, this commit resolves an incompatibility introduced in the shared  class, ensuring that the Telegram bot's translation functionality remains fully operational by correctly parsing  return values across both platforms.

The following files were modified:
- : Main Discord bot logic for message handling, button generation, and interaction processing.
- : Adjusted  to return full API response including confidence score.
- : Updated environment variable loading and added new constants for service URLs and tokens.
- : Updated constructor to include  for absolute URL generation.
- : Adjusted all calls to  to correctly extract language codes from the new array return format, resolving Telegram bot's translation issues.
This commit is contained in:
2026-02-08 16:28:17 -06:00
parent 3f0727984a
commit bc77082c20
5 changed files with 242 additions and 83 deletions

View File

@@ -8,11 +8,13 @@ class TelegramSender
private $botToken;
private $apiUrl = 'https://api.telegram.org/bot';
private $pdo;
private $baseUrl; // Nueva propiedad para almacenar BOT_BASE_URL
public function __construct($botToken, $pdo)
public function __construct($botToken, $pdo, string $baseUrl)
{
$this->botToken = $botToken;
$this->pdo = $pdo;
$this->baseUrl = rtrim($baseUrl, '/'); // Asegurarse de que no tenga una barra al final
}
public function sendMessage($chatId, $content, $options = [], $addTranslateButton = false, $messageLanguage = 'es', $originalFullContent = null)
@@ -302,7 +304,7 @@ class TelegramSender
// Convertir rutas relativas a absolutas si es necesario
if (!preg_match('/^https?:\/\//', $image_url)) {
$base_url = rtrim($_ENV['APP_URL'], '/');
$base_url = $this->baseUrl;
$image_url = $base_url . '/' . ltrim($image_url, '/');
custom_log("[DEBUG] URL de imagen convertida: " . $image_url);
@@ -605,7 +607,7 @@ class TelegramSender
// Si la URL es relativa, intentar convertirla a absoluta
if (!preg_match('/^https?:\/\//i', $url)) {
$baseUrl = rtrim($_ENV['APP_URL'], '/');
$baseUrl = $this->baseUrl;
$absoluteUrl = $baseUrl . '/' . ltrim($url, '/');
custom_log("${logPrefix} URL relativa detectada, convirtiendo a absoluta: $absoluteUrl");
$url = $absoluteUrl;
@@ -712,7 +714,7 @@ class TelegramSender
}
if (!preg_match('/^https?:\/\//', $url)) {
$baseUrl = rtrim($_ENV['APP_URL'], '/');
$baseUrl = $this->baseUrl;
$url = $baseUrl . '/' . ltrim($url, '/');
custom_log("[DEBUG] isValidImageUrl: URL convertida a absoluta: " . $url);
}

View File

@@ -22,7 +22,7 @@ ini_set('log_errors', 1);
// Verificación de autenticación
$authToken = $_GET['auth_token'] ?? '';
$expectedToken = $_ENV['TELEGRAM_WEBHOOK_TOKEN'] ?? '';
$expectedToken = TELEGRAM_WEBHOOK_TOKEN;
if (!empty($expectedToken) && $authToken !== $expectedToken) {
http_response_code(403);
custom_log("Acceso no autorizado: token inválido.");
@@ -30,7 +30,7 @@ if (!empty($expectedToken) && $authToken !== $expectedToken) {
}
// Verificar token del bot
$botToken = $_ENV['TELEGRAM_BOT_TOKEN'] ?? '';
$botToken = TELEGRAM_BOT_TOKEN;
if (empty($botToken)) {
http_response_code(500);
custom_log("Token de bot no configurado.");
@@ -49,8 +49,8 @@ if (!$update) {
custom_log("Update recibido: " . json_encode($update, JSON_PRETTY_PRINT));
try {
$telegram = new TelegramSender($botToken, $pdo);
$translator = new Translate();
$telegram = new TelegramSender(TELEGRAM_BOT_TOKEN, $pdo, BOT_BASE_URL);
$translator = new Translate(LIBRETRANSLATE_URL);
$commandLocker = new CommandLocker($pdo);
$message = $update['message'] ?? $update['channel_post'] ?? null;
@@ -248,7 +248,8 @@ try {
if (!empty($originalText)) {
try {
$sourceLang = $translator->detectLanguage($originalText);
$detectionResult = $translator->detectLanguage($originalText);
$sourceLang = $detectionResult[0]['language'] ?? null;
if ($sourceLang && $sourceLang !== $targetLang) {
$translatedText = $translator->translateHtml($originalText, $sourceLang, $targetLang);
$telegram->answerCallbackQuery($callbackId, ['text' => $translatedText, 'show_alert' => true]);
@@ -279,7 +280,8 @@ try {
if ($originalContent) {
// Detectar idioma real del contenido y aplicar fallback si coincide con el destino
$plain = strip_tags(html_entity_decode($originalContent, ENT_QUOTES | ENT_HTML5, 'UTF-8'));
$sourceLang = $translator->detectLanguage($plain) ?? 'es';
$detectionResult = $translator->detectLanguage($plain);
$sourceLang = $detectionResult[0]['language'] ?? 'es';
if ($sourceLang === $targetLang) {
$fallbackSrc = 'es';
if ($fallbackSrc !== $targetLang) {
@@ -351,7 +353,8 @@ try {
function handleCommand($pdo, $telegram, $commandLocker, $translator, $text, $from, $chatId, $messageId) {
$userId = $from['id'];
$detectedLang = $translator->detectLanguage($text) ?? 'es';
$detectionResult = $translator->detectLanguage($text);
$detectedLang = $detectionResult[0]['language'] ?? 'es';
if (strpos($text, '/setlang') === 0 || strpos($text, '/setlanguage') === 0) {
$parts = explode(' ', $text, 2);
@@ -459,7 +462,8 @@ function handleCommand($pdo, $telegram, $commandLocker, $translator, $text, $fro
$converter = new HtmlToTelegramHtmlConverter();
$content = $converter->convert($content);
$detectedLang = $translator->detectLanguage(strip_tags($content)) ?? 'es';
$detectionResult = $translator->detectLanguage(strip_tags($content));
$detectedLang = $detectionResult[0]['language'] ?? 'es';
if ($detectedLang !== 'es') {
$translatedContent = $translator->translateHtml($content, $detectedLang, 'es');
if ($translatedContent) $content = $translatedContent;
@@ -520,7 +524,8 @@ function handleRegularMessage($pdo, $telegram, $commandLocker, $translator, $tex
try {
// 1. Detectar el idioma del mensaje entrante
$detectedLang = $translator->detectLanguage(strip_tags($text)) ?? 'es';
$detectionResult = $translator->detectLanguage(strip_tags($text));
$detectedLang = $detectionResult[0]['language'] ?? 'es';
// 2. Guardar la interacción original en la base de datos
try {