Bot Discord - Commit completo con todos los cambios

This commit is contained in:
Admin
2026-01-16 20:24:38 -06:00
commit cf8ecfcf64
151 changed files with 28808 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
#!/usr/bin/env php
<?php
// scripts/cleanup_old_translations.php
// Limpia registros antiguos de la cola de traducción
require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../includes/db.php';
require_once __DIR__ . '/../includes/logger.php';
custom_log("[CLEANUP] Iniciando limpieza de registros antiguos");
try {
// Configurar días de retención
$retentionDays = 7;
// Eliminar registros completados o fallidos antiguos
$stmt = $pdo->prepare("
DELETE FROM translation_queue
WHERE status IN ('completed', 'failed')
AND created_at < DATE_SUB(NOW(), INTERVAL ? DAY)
");
$stmt->execute([$retentionDays]);
$deleted = $stmt->rowCount();
custom_log("[CLEANUP] Eliminados {$deleted} registros antiguos (>{$retentionDays} días)");
// Obtener estadísticas actuales
$stmt = $pdo->query("
SELECT
status,
COUNT(*) as count
FROM translation_queue
GROUP BY status
");
$stats = $stmt->fetchAll(PDO::FETCH_ASSOC);
custom_log("[CLEANUP] Estadísticas actuales:");
foreach ($stats as $stat) {
custom_log("[CLEANUP] {$stat['status']}: {$stat['count']}");
}
// Verificar trabajos atascados (en processing por más de 10 minutos)
$stmt = $pdo->prepare("
UPDATE translation_queue
SET status = 'pending',
worker_id = NULL,
processing_started_at = NULL
WHERE status = 'processing'
AND processing_started_at < DATE_SUB(NOW(), INTERVAL 10 MINUTE)
");
$stmt->execute();
$reset = $stmt->rowCount();
if ($reset > 0) {
custom_log("[CLEANUP] Reiniciados {$reset} trabajos atascados");
}
custom_log("[CLEANUP] Limpieza completada");
} catch (Exception $e) {
custom_log("[CLEANUP] Error: " . $e->getMessage());
exit(1);
}
exit(0);

View File

@@ -0,0 +1,34 @@
#!/bin/bash
# scripts/fix_discord_duplicate.sh
# Corrige el problema de Discord bot duplicado
echo "Deteniendo todos los procesos de discord_bot..."
sudo supervisorctl stop discordbot
# Esperar un momento
sleep 2
# Matar cualquier proceso huérfano
DISCORD_PIDS=$(ps aux | grep '[d]iscord_bot.php' | awk '{print $2}')
if [ -n "$DISCORD_PIDS" ]; then
echo "Matando procesos huérfanos: $DISCORD_PIDS"
echo "$DISCORD_PIDS" | xargs sudo kill -9
fi
# Esperar
sleep 2
# Iniciar un solo proceso
echo "Iniciando discord bot..."
sudo supervisorctl start discordbot
# Verificar
sleep 3
PROCESS_COUNT=$(ps aux | grep '[d]iscord_bot.php' | wc -l)
echo "Procesos de discord_bot activos: $PROCESS_COUNT"
if [ "$PROCESS_COUNT" -eq 1 ]; then
echo "✓ Discord bot funcionando correctamente (1 proceso)"
else
echo "⚠ Advertencia: Hay $PROCESS_COUNT procesos activos"
fi

74
scripts/fix_installation.sh Executable file
View File

@@ -0,0 +1,74 @@
#!/bin/bash
# scripts/fix_installation.sh
# Script para corregir problemas comunes después de la instalación
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
print_step() {
echo -e "${BLUE}==>${NC} $1"
}
print_success() {
echo -e "${GREEN}${NC} $1"
}
print_error() {
echo -e "${RED}${NC} $1"
}
if [ "$EUID" -ne 0 ]; then
print_error "Este script debe ejecutarse como root (usa sudo)"
exit 1
fi
print_step "Corrigiendo problemas de instalación..."
echo ""
# Corregir permisos de logs
print_step "1. Corrigiendo permisos de logs..."
chown -R www-data:www-data /var/www/html/bot/logs/
chmod -R 775 /var/www/html/bot/logs/
print_success "Permisos de logs corregidos"
# Reiniciar workers
print_step "2. Reiniciando workers..."
supervisorctl restart translation-worker-pool
sleep 3
print_success "Workers reiniciados"
# Verificar workers
print_step "3. Verificando workers..."
WORKER_COUNT=$(ps aux | grep -c '[T]ranslationWorker' || echo "0")
if [ "$WORKER_COUNT" -ge 4 ]; then
print_success "Workers activos: $WORKER_COUNT"
else
print_error "Workers activos: $WORKER_COUNT (esperados: 4+)"
echo "Ver logs: tail -f /var/www/html/bot/logs/translation-worker-pool.err.log"
exit 1
fi
# Verificar Redis
print_step "4. Verificando Redis..."
if redis-cli ping &> /dev/null; then
print_success "Redis funcionando"
else
print_error "Redis no responde"
exit 1
fi
echo ""
print_success "Todos los problemas corregidos"
echo ""
# Mostrar estadísticas
print_step "Estadísticas del sistema:"
APP_ENVIRONMENT=reod php /var/www/html/bot/scripts/translation_stats.php
echo ""
print_success "Sistema funcionando correctamente"

View File

@@ -0,0 +1,256 @@
#!/bin/bash
# scripts/install_translation_system.sh
# Script automatizado para instalar y configurar el sistema de traducción optimizado
# Uso: sudo bash scripts/install_translation_system.sh [pruebas|reod]
set -e # Detener si hay algún error
# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Función para imprimir con color
print_step() {
echo -e "${BLUE}==>${NC} $1"
}
print_success() {
echo -e "${GREEN}${NC} $1"
}
print_warning() {
echo -e "${YELLOW}${NC} $1"
}
print_error() {
echo -e "${RED}${NC} $1"
}
# Verificar que se ejecuta como root
if [ "$EUID" -ne 0 ]; then
print_error "Este script debe ejecutarse como root (usa sudo)"
exit 1
fi
# Obtener environment (pruebas o reod)
ENVIRONMENT=${1:-reod}
if [ "$ENVIRONMENT" != "pruebas" ] && [ "$ENVIRONMENT" != "reod" ]; then
print_error "Environment inválido. Usa: pruebas o reod"
exit 1
fi
print_step "Instalando sistema de traducción optimizado para environment: $ENVIRONMENT"
echo ""
# ============================================
# PASO 1: Instalar Redis Server
# ============================================
print_step "PASO 1/6: Instalando Redis Server..."
if command -v redis-server &> /dev/null; then
print_warning "Redis ya está instalado"
else
apt-get update -qq
apt-get install -y redis-server redis-tools
print_success "Redis instalado"
fi
# Iniciar y habilitar Redis
systemctl start redis-server
systemctl enable redis-server
# Verificar que Redis funciona
if redis-cli ping &> /dev/null; then
print_success "Redis funcionando correctamente"
else
print_error "Redis no responde"
exit 1
fi
echo ""
# ============================================
# PASO 2: Instalar extensión PHP Redis
# ============================================
print_step "PASO 2/6: Instalando extensión PHP Redis..."
if php -m | grep -q redis; then
print_warning "Extensión PHP Redis ya está instalada"
else
apt-get install -y php-redis
print_success "Extensión PHP Redis instalada"
fi
# Reiniciar servicios PHP
if systemctl list-units --type=service | grep -q php.*fpm; then
systemctl restart php*-fpm
print_success "PHP-FPM reiniciado"
fi
if systemctl list-units --type=service | grep -q apache2; then
systemctl restart apache2
print_success "Apache reiniciado"
fi
# Verificar extensión
if php -m | grep -q redis; then
print_success "Extensión PHP Redis verificada"
else
print_error "Extensión PHP Redis no está disponible"
exit 1
fi
echo ""
# ============================================
# PASO 3: Verificar extensión PCNTL
# ============================================
print_step "PASO 3/6: Verificando extensión PHP PCNTL..."
if php -m | grep -q pcntl; then
print_success "Extensión PCNTL disponible"
else
print_warning "Instalando extensión PCNTL..."
apt-get install -y php-pcntl
systemctl restart php*-fpm 2>/dev/null || true
if php -m | grep -q pcntl; then
print_success "Extensión PCNTL instalada"
else
print_error "No se pudo instalar PCNTL"
exit 1
fi
fi
echo ""
# ============================================
# PASO 4: Actualizar configuración de Supervisor
# ============================================
print_step "PASO 4/6: Actualizando configuración de Supervisor..."
SUPERVISOR_CONF="/etc/supervisor/conf.d/bot.conf"
# Hacer backup de la configuración actual
if [ -f "$SUPERVISOR_CONF" ]; then
cp "$SUPERVISOR_CONF" "$SUPERVISOR_CONF.backup.$(date +%Y%m%d_%H%M%S)"
print_success "Backup de configuración creado"
fi
# Detener worker antiguo si existe
if supervisorctl status translation-worker &> /dev/null; then
supervisorctl stop translation-worker
print_success "Worker antiguo detenido"
fi
# Crear nueva configuración
cat > "$SUPERVISOR_CONF" << 'EOF'
# Bot de Discord (sin cambios)
[program:discordbot]
command=/usr/bin/php /var/www/html/bot/discord_bot.php
environment=APP_ENVIRONMENT="reod"
directory=/var/www/html/bot/
autostart=true
autorestart=true
stderr_logfile=/var/www/html/bot/logs/discordbot.err.log
stdout_logfile=/var/www/html/bot/logs/discordbot.out.log
user=www-data
# Pool de Workers de Traducción (NUEVO)
[program:translation-worker-pool]
command=/usr/bin/php /var/www/html/bot/scripts/start_worker_pool.php
environment=APP_ENVIRONMENT="reod"
directory=/var/www/html/bot/
autostart=true
autorestart=true
stderr_logfile=/var/www/html/bot/logs/translation-worker-pool.err.log
stdout_logfile=/var/www/html/bot/logs/translation-worker-pool.out.log
user=www-data
numprocs=1
stopwaitsecs=30
stopsignal=TERM
EOF
print_success "Configuración de Supervisor actualizada"
# Recargar Supervisor
supervisorctl reread
supervisorctl update
print_success "Supervisor recargado"
echo ""
# ============================================
# PASO 5: Iniciar pool de workers
# ============================================
print_step "PASO 5/6: Iniciando pool de workers..."
# Dar permisos de ejecución a scripts
chmod +x /var/www/html/bot/scripts/*.sh
chmod +x /var/www/html/bot/scripts/*.php
# Iniciar pool
supervisorctl start translation-worker-pool
sleep 3
# Verificar estado
if supervisorctl status translation-worker-pool | grep -q RUNNING; then
print_success "Pool de workers iniciado"
else
print_error "Pool de workers no se inició correctamente"
supervisorctl tail translation-worker-pool stderr
exit 1
fi
echo ""
# ============================================
# PASO 6: Verificar instalación
# ============================================
print_step "PASO 6/6: Verificando instalación..."
# Verificar workers activos
WORKER_COUNT=$(ps aux | grep -c '[T]ranslationWorker' || echo "0")
if [ "$WORKER_COUNT" -ge 4 ]; then
print_success "Workers activos: $WORKER_COUNT"
else
print_warning "Workers activos: $WORKER_COUNT (esperados: 4+)"
fi
# Verificar Redis
if redis-cli -h 10.10.4.17 -p 6379 ping &> /dev/null; then
print_success "Conexión a Redis: OK"
else
print_warning "No se puede conectar a Redis en 10.10.4.17:6379"
fi
# Verificar supervisor
if supervisorctl status | grep -q "translation-worker-pool.*RUNNING"; then
print_success "Supervisor: OK"
else
print_warning "Supervisor: Verificar estado"
fi
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} INSTALACIÓN COMPLETADA EXITOSAMENTE ${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
# Mostrar estadísticas
print_step "Estadísticas del sistema:"
php /var/www/html/bot/scripts/translation_stats.php
echo ""
print_step "Comandos útiles:"
echo " Ver logs: tail -f /var/www/html/bot/logs/translation-worker-pool.out.log"
echo " Ver estadísticas: php /var/www/html/bot/scripts/translation_stats.php"
echo " Reiniciar: sudo supervisorctl restart translation-worker-pool"
echo " Detener: sudo supervisorctl stop translation-worker-pool"
echo ""
print_success "Sistema de traducción optimizado instalado y funcionando"
print_success "Capacidad: ~400 traducciones/minuto (13x más que antes)"

43
scripts/start_worker_pool.php Executable file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/env php
<?php
// scripts/start_worker_pool.php
// Script para iniciar el pool de workers de traducción
// Permitir ejecución indefinida
set_time_limit(0);
// Verificar que se ejecuta desde CLI
if (php_sapi_name() !== 'cli') {
die("Este script solo puede ejecutarse desde la línea de comandos.\n");
}
// Cargar configuración
require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../includes/db.php';
require_once __DIR__ . '/../includes/logger.php';
require_once __DIR__ . '/../src/TranslationWorkerPool.php';
custom_log("=== INICIANDO POOL DE WORKERS DE TRADUCCIÓN ===");
custom_log("Environment: " . (getenv('APP_ENVIRONMENT') ?: 'default'));
custom_log("PID del proceso principal: " . getmypid());
try {
// Verificar que PCNTL está disponible
if (!function_exists('pcntl_fork')) {
throw new Exception("La extensión PCNTL no está disponible. Instala php-pcntl.");
}
// Crear pool de workers
$pool = new TranslationWorkerPool($pdo);
// Iniciar pool (esto bloqueará hasta que se detenga)
$pool->start();
} catch (Exception $e) {
custom_log("ERROR FATAL: " . $e->getMessage());
custom_log("Stack trace: " . $e->getTraceAsString());
exit(1);
}
custom_log("=== POOL DE WORKERS DETENIDO ===");
exit(0);

View File

@@ -0,0 +1,30 @@
#!/bin/bash
# scripts/start_workers_pruebas.sh
# Iniciar workers de traducción en ambiente de pruebas
export APP_ENVIRONMENT=pruebas
echo "Iniciando workers de traducción..."
echo "Environment: pruebas"
echo "Workers: 4"
# Iniciar pool de workers en background
nohup php /var/www/html/bot/scripts/start_worker_pool.php >> /var/www/html/bot/logs/translation-worker-pool.out.log 2>&1 &
POOL_PID=$!
echo "Pool iniciado con PID: $POOL_PID"
# Esperar un momento para que los workers se inicien
sleep 2
# Verificar que los workers están corriendo
WORKER_COUNT=$(ps aux | grep -c "[T]ranslationWorker")
echo "Workers activos: $WORKER_COUNT"
if [ $WORKER_COUNT -gt 0 ]; then
echo "✓ Workers iniciados correctamente"
exit 0
else
echo "✗ Error: No se detectaron workers activos"
exit 1
fi

30
scripts/start_workers_reod.sh Executable file
View File

@@ -0,0 +1,30 @@
#!/bin/bash
# scripts/start_workers_reod.sh
# Iniciar workers de traducción en ambiente de producción
export APP_ENVIRONMENT=reod
echo "Iniciando workers de traducción..."
echo "Environment: reod (producción)"
echo "Workers: 4"
# Iniciar pool de workers en background
nohup php /var/www/html/bot/scripts/start_worker_pool.php >> /var/www/html/bot/logs/translation-worker-pool.out.log 2>&1 &
POOL_PID=$!
echo "Pool iniciado con PID: $POOL_PID"
# Esperar un momento para que los workers se inicien
sleep 2
# Verificar que los workers están corriendo
WORKER_COUNT=$(ps aux | grep -c "[T]ranslationWorker")
echo "Workers activos: $WORKER_COUNT"
if [ $WORKER_COUNT -gt 0 ]; then
echo "✓ Workers iniciados correctamente"
exit 0
else
echo "✗ Error: No se detectaron workers activos"
exit 1
fi

46
scripts/stop_workers.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/bin/bash
# scripts/stop_workers.sh
# Detener todos los workers de traducción
echo "Deteniendo workers de traducción..."
# Buscar y matar el proceso del pool
POOL_PID=$(ps aux | grep "[s]tart_worker_pool.php" | awk '{print $2}')
if [ -n "$POOL_PID" ]; then
echo "Deteniendo pool (PID: $POOL_PID)..."
kill -TERM $POOL_PID
sleep 2
# Verificar si terminó
if ps -p $POOL_PID > /dev/null 2>&1; then
echo "Pool no respondió a SIGTERM, enviando SIGKILL..."
kill -9 $POOL_PID
fi
echo "✓ Pool detenido"
else
echo "No se encontró pool activo"
fi
# Verificar workers huérfanos
ORPHAN_WORKERS=$(ps aux | grep "[T]ranslationWorker" | awk '{print $2}')
if [ -n "$ORPHAN_WORKERS" ]; then
echo "Deteniendo workers huérfanos..."
echo "$ORPHAN_WORKERS" | xargs kill -TERM
sleep 1
echo "✓ Workers huérfanos detenidos"
fi
# Verificar que no queden procesos
REMAINING=$(ps aux | grep -c "[T]ranslation")
if [ $REMAINING -eq 0 ]; then
echo "✓ Todos los workers detenidos correctamente"
exit 0
else
echo "⚠ Advertencia: Aún hay $REMAINING procesos de traducción activos"
ps aux | grep "[T]ranslation"
exit 1
fi

121
scripts/translation_stats.php Executable file
View File

@@ -0,0 +1,121 @@
#!/usr/bin/env php
<?php
// scripts/translation_stats.php
// Muestra estadísticas del sistema de traducción
require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../includes/db.php';
require_once __DIR__ . '/../src/TranslationCache.php';
echo "\n=== ESTADÍSTICAS DEL SISTEMA DE TRADUCCIÓN ===\n\n";
// Estadísticas de la cola
echo "📊 COLA DE TRADUCCIÓN:\n";
$stmt = $pdo->query("
SELECT
status,
COUNT(*) as count,
AVG(attempts) as avg_attempts
FROM translation_queue
GROUP BY status
");
$queueStats = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($queueStats as $stat) {
$avgAttempts = round($stat['avg_attempts'], 2);
echo " {$stat['status']}: {$stat['count']} (avg attempts: {$avgAttempts})\n";
}
// Total de traducciones hoy
$stmt = $pdo->query("
SELECT COUNT(*) as count
FROM translation_queue
WHERE DATE(created_at) = CURDATE()
");
$todayCount = $stmt->fetchColumn();
echo "\n Traducciones hoy: {$todayCount}\n";
// Traducciones por plataforma
echo "\n📱 POR PLATAFORMA:\n";
$stmt = $pdo->query("
SELECT
platform,
status,
COUNT(*) as count
FROM translation_queue
WHERE DATE(created_at) = CURDATE()
GROUP BY platform, status
");
$platformStats = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($platformStats as $stat) {
echo " {$stat['platform']} - {$stat['status']}: {$stat['count']}\n";
}
// Workers activos
echo "\n👷 WORKERS ACTIVOS:\n";
$workerCount = 0;
exec("ps aux | grep -c '[T]ranslationWorker'", $output, $returnCode);
if ($returnCode === 0 && isset($output[0])) {
$workerCount = (int)$output[0];
}
echo " Workers en ejecución: {$workerCount}\n";
// Workers únicos en la BD
$stmt = $pdo->query("
SELECT DISTINCT worker_id, COUNT(*) as jobs
FROM translation_queue
WHERE status = 'processing'
GROUP BY worker_id
");
$activeWorkers = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!empty($activeWorkers)) {
echo "\n Workers procesando:\n";
foreach ($activeWorkers as $worker) {
echo " - {$worker['worker_id']}: {$worker['jobs']} job(s)\n";
}
}
// Estadísticas de caché
echo "\n💾 CACHÉ DE TRADUCCIONES:\n";
try {
$cache = new TranslationCache();
$cacheStats = $cache->getStats();
if ($cacheStats['enabled']) {
echo " Estado: Habilitado ✓\n";
echo " Hits: {$cacheStats['hits']}\n";
echo " Misses: {$cacheStats['misses']}\n";
echo " Total requests: {$cacheStats['total_requests']}\n";
echo " Hit rate: {$cacheStats['hit_rate']}%\n";
} else {
echo " Estado: Deshabilitado ✗\n";
}
} catch (Exception $e) {
echo " Error: " . $e->getMessage() . "\n";
}
// Tiempos promedio
echo "\n⏱️ RENDIMIENTO:\n";
$stmt = $pdo->query("
SELECT
AVG(TIMESTAMPDIFF(SECOND, created_at, processed_at)) as avg_time,
MIN(TIMESTAMPDIFF(SECOND, created_at, processed_at)) as min_time,
MAX(TIMESTAMPDIFF(SECOND, created_at, processed_at)) as max_time
FROM translation_queue
WHERE status = 'completed'
AND DATE(created_at) = CURDATE()
AND processed_at IS NOT NULL
");
$perfStats = $stmt->fetch(PDO::FETCH_ASSOC);
if ($perfStats && $perfStats['avg_time'] !== null) {
echo " Tiempo promedio: " . round($perfStats['avg_time'], 2) . " segundos\n";
echo " Tiempo mínimo: " . round($perfStats['min_time'], 2) . " segundos\n";
echo " Tiempo máximo: " . round($perfStats['max_time'], 2) . " segundos\n";
} else {
echo " No hay datos de rendimiento para hoy\n";
}
echo "\n" . str_repeat("=", 50) . "\n\n";