Files
whatsapp/instalar_bd.php
T
2026-01-12 11:06:43 -05:00

243 lines
8.9 KiB
PHP

<?php
/**
* 🗄️ INSTALADOR DE BASE DE DATOS - WhatsApp Bot
* Crea todas las tablas necesarias y corrige inconsistencias
*/
// Headers para mostrar errores
error_reporting(E_ALL);
ini_set('display_errors', 1);
set_time_limit(120); // 2 minutos máximo
echo "<!DOCTYPE html><html><head><meta charset='UTF-8'>";
echo "<title>🗄️ Instalador BD</title>";
echo "<style>body{font-family:monospace;margin:20px;background:#000;color:#00ff00}";
echo ".ok{color:#00ff00}.error{color:#ff0040}.warning{color:#ffaa00}";
echo ".section{background:#111;padding:15px;margin:10px 0;border:1px solid #333}";
echo "pre{background:#222;padding:10px;color:#ccc;overflow:auto;max-height:200px}";
echo "</style></head><body>";
echo "<h1>🗄️ INSTALADOR DE BASE DE DATOS</h1>";
// Cargar configuración
try {
require_once 'config/config.php';
} catch (Exception $e) {
echo "<div class='error'>❌ Error cargando configuración: " . htmlspecialchars($e->getMessage()) . "</div>";
exit;
}
// Verificar que existe el archivo schema.sql
if (!file_exists('database/schema.sql')) {
echo "<div class='error'>❌ CRÍTICO: database/schema.sql no encontrado</div>";
exit;
}
// Conectar a la base de datos
try {
$dsn = "mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
$pdo = new PDO($dsn, DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
echo "<div class='ok'>✅ Conectado a la base de datos</div>";
} catch (PDOException $e) {
echo "<div class='error'>❌ Error de conexión: " . htmlspecialchars($e->getMessage()) . "</div>";
exit;
}
// Leer archivo SQL
$sql_content = file_get_contents('database/schema.sql');
if (!$sql_content) {
echo "<div class='error'>❌ No se pudo leer database/schema.sql</div>";
exit;
}
echo "<div class='section'>";
echo "<h2>📋 EJECUTANDO SCHEMA SQL...</h2>";
// Separar comandos SQL
$commands = array_filter(
array_map('trim', explode(';', $sql_content)),
function($cmd) {
return !empty($cmd) && !preg_match('/^\s*--/', $cmd);
}
);
$success_count = 0;
$error_count = 0;
foreach ($commands as $i => $command) {
if (empty(trim($command))) continue;
// Mostrar progreso cada 5 comandos
if ($i % 5 === 0) {
echo "<div class='warning'>Procesando comando " . ($i + 1) . "/" . count($commands) . "...</div>";
flush();
}
try {
$pdo->exec($command);
$success_count++;
// Solo mostrar detalles de CREATE TABLE y INSERT importantes
if (preg_match('/CREATE TABLE (\w+)/', $command, $matches)) {
echo "<div class='ok'>✅ Tabla '{$matches[1]}' creada</div>";
} elseif (preg_match('/INSERT INTO (\w+)/', $command, $matches) && $i < 10) {
echo "<div class='ok'>✅ Datos insertados en '{$matches[1]}'</div>";
}
} catch (PDOException $e) {
$error_count++;
// Si es error de tabla existente, es OK
if (strpos($e->getMessage(), 'already exists') !== false) {
if (preg_match('/CREATE TABLE (\w+)/', $command, $matches)) {
echo "<div class='warning'>⚠️ Tabla '{$matches[1]}' ya existe</div>";
}
} else {
echo "<div class='error'>❌ Error en comando " . ($i + 1) . ": " . htmlspecialchars($e->getMessage()) . "</div>";
if (strlen($command) < 200) {
echo "<pre>" . htmlspecialchars($command) . "</pre>";
}
}
}
}
echo "<div class='ok'>📊 Comandos exitosos: $success_count</div>";
echo "<div class='error'>📊 Errores: $error_count</div>";
echo "</div>";
// Ahora crear tablas adicionales que faltan
echo "<div class='section'>";
echo "<h2>🔧 CREANDO TABLAS FALTANTES...</h2>";
// Crear tabla 'messages' como alias de conversations
try {
$pdo->exec("
CREATE TABLE IF NOT EXISTS messages (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
phone_number VARCHAR(20) NOT NULL,
message_text TEXT,
direction ENUM('incoming', 'outgoing') NOT NULL,
message_type ENUM('text', 'image', 'audio', 'video', 'document', 'template') DEFAULT 'text',
status ENUM('sent', 'delivered', 'read', 'failed') DEFAULT 'sent',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_phone (phone_number),
INDEX idx_direction (direction),
INDEX idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
");
echo "<div class='ok'>✅ Tabla 'messages' creada</div>";
} catch (PDOException $e) {
if (strpos($e->getMessage(), 'already exists') === false) {
echo "<div class='error'>❌ Error creando tabla messages: " . htmlspecialchars($e->getMessage()) . "</div>";
} else {
echo "<div class='warning'>⚠️ Tabla 'messages' ya existe</div>";
}
}
// Crear tabla 'settings' como alias de system_config
try {
$pdo->exec("
CREATE TABLE IF NOT EXISTS settings (
id INT AUTO_INCREMENT PRIMARY KEY,
setting_key VARCHAR(100) UNIQUE NOT NULL,
setting_value TEXT,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
");
echo "<div class='ok'>✅ Tabla 'settings' creada</div>";
} catch (PDOException $e) {
if (strpos($e->getMessage(), 'already exists') === false) {
echo "<div class='error'>❌ Error creando tabla settings: " . htmlspecialchars($e->getMessage()) . "</div>";
} else {
echo "<div class='warning'>⚠️ Tabla 'settings' ya existe</div>";
}
}
echo "</div>";
// Copiar datos de system_config a settings si no existen
echo "<div class='section'>";
echo "<h2>📊 SINCRONIZANDO CONFIGURACIÓN...</h2>";
try {
// Copiar datos de system_config a settings
$pdo->exec("
INSERT IGNORE INTO settings (setting_key, setting_value, description, created_at)
SELECT config_key, config_value, description, created_at
FROM system_config
WHERE config_key IS NOT NULL
");
$affected = $pdo->lastInsertId();
echo "<div class='ok'>✅ Configuraciones sincronizadas</div>";
} catch (PDOException $e) {
echo "<div class='warning'>⚠️ Error sincronizando: " . htmlspecialchars($e->getMessage()) . "</div>";
}
// Verificar que el SECRET_KEY esté definido
try {
if (!defined('SECRET_KEY') || empty(SECRET_KEY)) {
$secret_key = bin2hex(random_bytes(32));
$pdo->prepare("INSERT INTO settings (setting_key, setting_value, description) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)")
->execute(['SECRET_KEY', $secret_key, 'Clave secreta para encriptación']);
echo "<div class='ok'>✅ SECRET_KEY generada y guardada</div>";
echo "<div class='warning'>🔑 IMPORTANTE: Agrega esta línea a config/config.php:</div>";
echo "<pre>define('SECRET_KEY', '$secret_key');</pre>";
}
} catch (Exception $e) {
echo "<div class='error'>❌ Error generando SECRET_KEY: " . htmlspecialchars($e->getMessage()) . "</div>";
}
echo "</div>";
// Verificación final
echo "<div class='section'>";
echo "<h2>✅ VERIFICACIÓN FINAL</h2>";
$required_tables = ['conversations', 'messages', 'settings', 'message_templates', 'users', 'menus'];
$missing_tables = [];
foreach ($required_tables as $table) {
try {
$stmt = $pdo->query("SHOW TABLES LIKE '$table'");
if ($stmt->rowCount() > 0) {
// Contar registros
$count_stmt = $pdo->query("SELECT COUNT(*) as count FROM $table");
$count = $count_stmt->fetch()['count'];
echo "<div class='ok'>✅ Tabla '$table' existe ($count registros)</div>";
} else {
$missing_tables[] = $table;
}
} catch (Exception $e) {
echo "<div class='error'>❌ Error verificando tabla '$table': " . htmlspecialchars($e->getMessage()) . "</div>";
$missing_tables[] = $table;
}
}
if (empty($missing_tables)) {
echo "<div class='ok'>🎉 ¡TODAS LAS TABLAS ESTÁN LISTAS!</div>";
echo "<div class='ok'>✅ Base de datos completamente configurada</div>";
echo "<div class='ok'>✅ Sistema debería funcionar ahora</div>";
echo "<br><div class='warning'><strong>PRÓXIMO PASO:</strong></div>";
echo "<div class='warning'>• Probar: <a href='login.php' style='color:#ffaa00'>login.php</a></div>";
echo "<div class='warning'>• Si funciona, probar: <a href='index.php' style='color:#ffaa00'>index.php</a></div>";
} else {
echo "<div class='error'>❌ Faltan tablas: " . implode(', ', $missing_tables) . "</div>";
echo "<div class='error'>❌ Sistema NO puede funcionar</div>";
}
echo "</div>";
echo "</body></html>";
?>