Iniciar sesión'); } // Función para generar contraseña aleatoria segura function generateRandomPassword($length = 12) { $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*-_=+'; $password = ''; for ($i = 0; $i < $length; $i++) { $password .= $chars[random_int(0, strlen($chars) - 1)]; } return $password; } $installStep = $_GET['step'] ?? 'config'; $errors = []; $success = []; // Generar contraseña para admin $adminPassword = generateRandomPassword(12); // Procesar instalación manual if ($installStep === 'install' && $_POST) { $dbHost = trim($_POST['db_host'] ?? 'localhost'); $dbName = trim($_POST['db_name'] ?? ''); $dbUser = trim($_POST['db_user'] ?? ''); $dbPass = trim($_POST['db_pass'] ?? ''); $dbPort = trim($_POST['db_port'] ?? '3306'); // Validar campos requeridos if (empty($dbName)) { $errors[] = "❌ El nombre de la base de datos es obligatorio"; } if (empty($dbUser)) { $errors[] = "❌ El usuario de la base de datos es obligatorio"; } if (empty($dbPass)) { $errors[] = "❌ La contraseña de la base de datos es obligatoria"; } if (empty($errors)) { try { // 1. Probar conexión con las credenciales proporcionadas $dsn = "mysql:host={$dbHost};port={$dbPort};charset=utf8mb4"; $testConnection = new PDO($dsn, $dbUser, $dbPass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_TIMEOUT => 5, ]); $success[] = "✅ Conexión al servidor MySQL exitosa"; // Verificar que la base de datos existe $dsn = "mysql:host={$dbHost};port={$dbPort};dbname={$dbName};charset=utf8mb4"; $pdo = new PDO($dsn, $dbUser, $dbPass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]); $success[] = "✅ Conexión a base de datos '$dbName' exitosa"; // 2. Verificar si las tablas ya existen $existingTables = []; $stmt = $pdo->query("SHOW TABLES"); while ($row = $stmt->fetch(PDO::FETCH_NUM)) { $existingTables[] = $row[0]; } if (!empty($existingTables)) { $success[] = "✅ Base de datos contiene " . count($existingTables) . " tablas existentes"; } // 3. Ejecutar schema.sql para crear/actualizar tablas $schemaFile = 'database/schema.sql'; if (!file_exists($schemaFile)) { throw new Exception("No se encontró el archivo schema.sql"); } $schema = file_get_contents($schemaFile); if (!$schema) { throw new Exception("No se pudo leer el archivo schema.sql"); } // Ejecutar comandos SQL uno por uno $statements = preg_split('/;\s*$/m', $schema); $tablesCreated = 0; $tablesUpdated = 0; $errors_sql = []; // Primero ejecutar solo CREATE TABLE foreach ($statements as $statement) { $statement = trim($statement); if (!empty($statement) && !preg_match('/^--/', $statement) && preg_match('/CREATE TABLE/i', $statement)) { try { $pdo->exec($statement); $tablesCreated++; // Extraer nombre de tabla para log if (preg_match('/CREATE TABLE\s+(?:IF NOT EXISTS\s+)?`?(\w+)`?/i', $statement, $matches)) { $success[] = "✅ Tabla '{$matches[1]}' creada"; } } catch (PDOException $e) { $errorMsg = $e->getMessage(); if (strpos($errorMsg, 'already exists') === false) { $errors_sql[] = "Error creando tabla: " . $errorMsg; } } } } // Luego ejecutar INSERT y otras operaciones foreach ($statements as $statement) { $statement = trim($statement); if (!empty($statement) && !preg_match('/^--/', $statement) && !preg_match('/CREATE TABLE/i', $statement) && (preg_match('/INSERT/i', $statement) || preg_match('/UPDATE/i', $statement) || preg_match('/SET/i', $statement))) { try { $pdo->exec($statement); if (preg_match('/INSERT INTO/i', $statement)) { $tablesUpdated++; } } catch (PDOException $e) { $errorMsg = $e->getMessage(); if (strpos($errorMsg, 'Duplicate entry') === false) { $errors_sql[] = "Error insertando datos: " . $errorMsg; } } } } if (empty($errors_sql)) { $success[] = "✅ Esquema aplicado: {$tablesCreated} tablas creadas, {$tablesUpdated} registros insertados"; } else { $success[] = "⚠️ Esquema procesado: {$tablesCreated} tablas, {$tablesUpdated} registros"; foreach ($errors_sql as $sqlError) { $errors[] = "⚠️ " . $sqlError; } } // 4. Actualizar archivo de configuración $configFile = 'config/config.php'; $configContent = file_get_contents($configFile); $configContent = preg_replace("/define\('DB_HOST',\s*'[^']*'\);/", "define('DB_HOST', '$dbHost');", $configContent); $configContent = preg_replace("/define\('DB_PORT',\s*'[^']*'\);/", "define('DB_PORT', '$dbPort');", $configContent); $configContent = preg_replace("/define\('DB_NAME',\s*'[^']*'\);/", "define('DB_NAME', '$dbName');", $configContent); $configContent = preg_replace("/define\('DB_USER',\s*'[^']*'\);/", "define('DB_USER', '$dbUser');", $configContent); $configContent = preg_replace("/define\('DB_PASS',\s*'[^']*'\);/", "define('DB_PASS', '$dbPass');", $configContent); $configContent = preg_replace("/define\('ADMIN_PASSWORD',\s*'[^']*'\);/", "define('ADMIN_PASSWORD', '" . password_hash($adminPassword, PASSWORD_DEFAULT) . "');", $configContent); // Auto-detectar URL del servidor $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https://' : 'http://'; $host = $_SERVER['HTTP_HOST']; $path = dirname($_SERVER['SCRIPT_NAME']); $autoUrl = $protocol . $host . $path; $configContent = preg_replace("/define\('APP_URL',\s*'[^']*'\);/", "define('APP_URL', '$autoUrl');", $configContent); if (file_put_contents($configFile, $configContent)) { $success[] = "✅ Archivo config.php actualizado"; } else { $errors[] = "❌ No se pudo actualizar config.php"; } // 5. Verificar que la configuración funcione try { // Probar directamente con PDO usando las nuevas credenciales $testPdo = new PDO("mysql:host={$dbHost};port={$dbPort};dbname={$dbName};charset=utf8mb4", $dbUser, $dbPass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]); $testQuery = $testPdo->query("SELECT COUNT(*) as count FROM users"); $userCount = $testQuery->fetch()['count']; $success[] = "✅ Prueba de conexión exitosa: {$userCount} usuarios registrados"; // Verificar que las tablas principales existan $mainTables = ['users', 'conversations', 'menus', 'system_config']; foreach ($mainTables as $table) { $checkTable = $testPdo->query("SHOW TABLES LIKE '{$table}'"); if ($checkTable->rowCount() > 0) { $success[] = "✅ Tabla '{$table}' verificada"; } else { $errors[] = "❌ Tabla '{$table}' no encontrada"; } } } catch (Exception $e) { $errors[] = "❌ Error probando la nueva configuración: " . $e->getMessage(); } if (empty($errors)) { // 6. Crear archivo de bloqueo de instalación $lockContent = "Instalación manual completada: " . date('Y-m-d H:i:s') . "\n"; $lockContent .= "Host: $dbHost\n"; $lockContent .= "Base de datos: $dbName\n"; $lockContent .= "Usuario BD: $dbUser\n"; $lockContent .= "Desarrollado por: U-Site.app\n"; $lockContent .= "URL: https://u-site.app\n"; file_put_contents($installationLockFile, $lockContent); $success[] = "✅ Sistema bloqueado contra reinstalaciones"; // 7. Crear archivo de credenciales $credentialsFile = "CREDENCIALES_SISTEMA.txt"; $credentialsContent = "=== CREDENCIALES DEL SISTEMA WHATSAPP BOT ===\n"; $credentialsContent .= "Instalación manual completada\n"; $credentialsContent .= "Desarrollado por: U-Site.app (https://u-site.app)\n"; $credentialsContent .= "Generado automáticamente: " . date('Y-m-d H:i:s') . "\n\n"; $credentialsContent .= "=== BASE DE DATOS ===\n"; $credentialsContent .= "Host: $dbHost\n"; $credentialsContent .= "Puerto: $dbPort\n"; $credentialsContent .= "Base de datos: $dbName\n"; $credentialsContent .= "Usuario: $dbUser\n"; $credentialsContent .= "Contraseña: [LA QUE CONFIGURASTE MANUALMENTE]\n\n"; $credentialsContent .= "=== PANEL ADMINISTRATIVO ===\n"; $credentialsContent .= "Usuario: admin\n"; $credentialsContent .= "Contraseña: $adminPassword\n"; $credentialsContent .= "URL Login: $autoUrl/login.php\n\n"; $credentialsContent .= "⚠️ IMPORTANTE: Guarda estas credenciales en un lugar seguro.\n"; $credentialsContent .= "⚠️ La contraseña de BD es la que TÚ configuraste manualmente.\n"; $credentialsContent .= "⚠️ El sistema está protegido contra reinstalaciones.\n\n"; $credentialsContent .= "📞 Soporte técnico: support@u-site.app\n"; file_put_contents($credentialsFile, $credentialsContent); $success[] = "✅ Archivo de credenciales creado: $credentialsFile"; $installStep = 'completed'; } } catch (PDOException $e) { $errors[] = "❌ Error de base de datos: " . $e->getMessage(); } catch (Exception $e) { $errors[] = "❌ Error general: " . $e->getMessage(); } } } ?>
Para hostings compartidos (HestiaCP, cPanel, etc.)
Este instalador es para cuando ya creaste manualmente:
Aplicando configuración con tus credenciales
Procesando configuración...
Tu sistema WhatsApp Bot está configurado y listo