Files
whatsapp/legacy/install_manual.php
T
2026-01-28 03:09:52 -05:00

544 lines
27 KiB
PHP

<?php
/**
* Instalador manual para hostings compartidos (HestiaCP, cPanel, etc.)
* Desarrollado por U-Site.app - https://u-site.app
* Para cuando ya creaste la BD y usuario manualmente
* Fecha: 13 de noviembre de 2025
*/
// Verificar si la instalación ya está completada
$installationLockFile = '.installation_completed';
if (file_exists($installationLockFile)) {
header('Location: login.php');
exit('La instalación ya está completada. <a href="login.php">Iniciar sesión</a>');
}
// 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();
}
}
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🛠️ Instalación Manual - WhatsApp Bot</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
:root {
--primary-color: #25d366;
--secondary-color: #075e54;
--bg-gradient: linear-gradient(135deg, #25d366 0%, #075e54 100%);
}
body {
background: var(--bg-gradient);
min-height: 100vh;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.install-card {
background: rgba(255,255,255,0.95);
border-radius: 20px;
backdrop-filter: blur(10px);
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
}
.btn-install {
background: var(--bg-gradient);
border: none;
color: white;
padding: 15px 30px;
border-radius: 10px;
font-weight: 600;
}
.btn-install:hover {
transform: translateY(-2px);
color: white;
}
.password-display {
background: #f8f9fa;
border: 2px dashed #28a745;
border-radius: 10px;
font-family: 'Courier New', monospace;
font-size: 1.1rem;
font-weight: bold;
color: #155724;
word-break: break-all;
padding: 15px;
}
.form-control:focus {
border-color: var(--primary-color);
box-shadow: 0 0 0 0.2rem rgba(37, 211, 102, 0.25);
}
.hosting-info {
background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 15px;
padding: 20px;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="container mt-4">
<div class="row justify-content-center">
<div class="col-lg-10">
<div class="install-card p-4">
<?php if ($installStep === 'config'): ?>
<!-- Pantalla de Configuración Manual -->
<div class="text-center mb-4">
<i class="fas fa-tools text-warning" style="font-size: 3rem;"></i>
<h1 class="mt-3 fw-bold">Instalación Manual</h1>
<p class="text-muted">Para hostings compartidos (HestiaCP, cPanel, etc.)</p>
</div>
<div class="hosting-info">
<h5><i class="fas fa-server me-2"></i>Configuración para Hosting Compartido</h5>
<p class="mb-2">Este instalador es para cuando ya creaste manualmente:</p>
<div class="row">
<div class="col-md-6">
<ul class="mb-0">
<li>✅ Base de datos MySQL</li>
<li>✅ Usuario de base de datos</li>
</ul>
</div>
<div class="col-md-6">
<ul class="mb-0">
<li>✅ Permisos asignados</li>
<li>✅ Acceso desde tu dominio</li>
</ul>
</div>
</div>
</div>
<div class="alert alert-info">
<h6><i class="fas fa-info-circle me-2"></i>Pasos previos en HestiaCP/cPanel:</h6>
<ol class="mb-0">
<li><strong>Crear base de datos:</strong> Ve a MySQL Databases</li>
<li><strong>Crear usuario:</strong> Asigna un usuario a la BD</li>
<li><strong>Asignar permisos:</strong> Da ALL PRIVILEGES al usuario</li>
<li><strong>Anotar credenciales:</strong> Host, nombre BD, usuario y contraseña</li>
</ol>
</div>
<form action="?step=install" method="POST">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label"><i class="fas fa-server me-2"></i>Host de BD</label>
<input type="text" class="form-control" name="db_host" value="localhost" required>
<small class="text-muted">Generalmente 'localhost' en hosting compartido</small>
</div>
<div class="col-md-6">
<label class="form-label"><i class="fas fa-plug me-2"></i>Puerto</label>
<input type="text" class="form-control" name="db_port" value="3306">
<small class="text-muted">Puerto estándar de MySQL</small>
</div>
<div class="col-md-6">
<label class="form-label"><i class="fas fa-database me-2"></i>Nombre de BD <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="db_name" placeholder="mi_basedatos" required>
<small class="text-muted">Nombre exacto de la base de datos creada</small>
</div>
<div class="col-md-6">
<label class="form-label"><i class="fas fa-user me-2"></i>Usuario de BD <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="db_user" placeholder="mi_usuario" required>
<small class="text-muted">Usuario asignado a la base de datos</small>
</div>
<div class="col-12">
<label class="form-label"><i class="fas fa-key me-2"></i>Contraseña de BD <span class="text-danger">*</span></label>
<input type="password" class="form-control" name="db_pass" required>
<small class="text-muted">Contraseña del usuario de base de datos</small>
</div>
</div>
<div class="mt-4">
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-user-shield me-2 text-success"></i>Credenciales Admin</h6>
<div class="alert alert-success">
<strong>Usuario:</strong> admin<br>
<strong>Contraseña:</strong> <span class="password-display d-inline p-2"><?= htmlspecialchars($adminPassword) ?></span>
</div>
</div>
<div class="col-md-6">
<h6><i class="fas fa-shield-alt me-2 text-primary"></i>Que incluye</h6>
<ul class="list-unstyled">
<li>✅ Configuración automática</li>
<li>✅ Creación de tablas</li>
<li>✅ Datos iniciales</li>
<li>✅ Protección contra reinstalación</li>
</ul>
</div>
</div>
</div>
<div class="text-center mt-4">
<button type="submit" class="btn btn-install btn-lg">
<i class="fas fa-cog me-2"></i>Configurar Sistema
</button>
</div>
</form>
<?php elseif ($installStep === 'install'): ?>
<!-- Pantalla de Procesamiento -->
<div class="text-center mb-4">
<i class="fas fa-cog fa-spin text-warning" style="font-size: 3rem;"></i>
<h2 class="mt-3">Configurando Sistema...</h2>
<p class="text-muted">Aplicando configuración con tus credenciales</p>
</div>
<!-- Mostrar errores -->
<?php if (!empty($errors)): ?>
<div class="alert alert-danger">
<h5><i class="fas fa-exclamation-triangle me-2"></i>Errores encontrados:</h5>
<?php foreach ($errors as $error): ?>
<div><?= htmlspecialchars($error) ?></div>
<?php endforeach; ?>
<hr>
<a href="?step=config" class="btn btn-outline-danger">
<i class="fas fa-arrow-left me-2"></i>Volver a intentar
</a>
</div>
<?php endif; ?>
<!-- Mostrar éxitos -->
<?php if (!empty($success)): ?>
<div class="alert alert-success">
<h5><i class="fas fa-check-circle me-2"></i>Progreso de instalación:</h5>
<?php foreach ($success as $msg): ?>
<div><?= htmlspecialchars($msg) ?></div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if (!empty($errors) && empty($success)): ?>
<!-- Solo mostrar si hay errores sin éxitos -->
<?php elseif ($installStep !== 'completed'): ?>
<div class="text-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Procesando...</span>
</div>
<p class="mt-2">Procesando configuración...</p>
</div>
<?php endif; ?>
<?php elseif ($installStep === 'completed'): ?>
<!-- Pantalla de Completado -->
<div class="text-center mb-4">
<i class="fas fa-check-circle text-success" style="font-size: 4rem;"></i>
<h1 class="mt-3 text-success fw-bold">¡Instalación Completada!</h1>
<p class="text-muted">Tu sistema WhatsApp Bot está configurado y listo</p>
</div>
<!-- Mostrar errores si los hay -->
<?php if (!empty($errors)): ?>
<div class="alert alert-warning">
<h5><i class="fas fa-exclamation-triangle me-2"></i>Advertencias:</h5>
<?php foreach ($errors as $error): ?>
<div><?= htmlspecialchars($error) ?></div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<!-- Mostrar éxitos -->
<?php if (!empty($success)): ?>
<div class="alert alert-success">
<h5><i class="fas fa-check-circle me-2"></i>Instalación exitosa:</h5>
<?php foreach ($success as $msg): ?>
<div><?= htmlspecialchars($msg) ?></div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<div class="row g-4 mb-4">
<div class="col-md-6">
<h5><i class="fas fa-user-shield me-2 text-success"></i>Acceso al Sistema</h5>
<div class="bg-light p-3 rounded">
<div><strong>Usuario:</strong> admin</div>
<div class="mt-2">
<strong>Contraseña:</strong><br>
<div class="password-display mt-1">
<?= htmlspecialchars($adminPassword) ?>
</div>
</div>
<div class="mt-3">
<a href="login.php" class="btn btn-install btn-sm">
<i class="fas fa-sign-in-alt me-2"></i>Iniciar Sesión
</a>
</div>
</div>
</div>
<div class="col-md-6">
<h5><i class="fas fa-link me-2 text-primary"></i>Próximos Pasos</h5>
<div class="d-grid gap-2">
<a href="test.php" class="btn btn-outline-success">
<i class="fas fa-check-circle me-2"></i>Probar Sistema
</a>
<a href="index.php" class="btn btn-outline-primary">
<i class="fas fa-home me-2"></i>Ir al Panel
</a>
<a href="server_setup.php" class="btn btn-outline-warning">
<i class="fab fa-whatsapp me-2"></i>Configurar WhatsApp
</a>
</div>
</div>
</div>
<div class="alert alert-info">
<h6><i class="fas fa-info-circle me-2"></i>Información Importante:</h6>
<ul class="mb-0">
<li><strong>Credenciales guardadas:</strong> Revisa el archivo CREDENCIALES_SISTEMA.txt</li>
<li><strong>Base de datos:</strong> Se conecta usando tus credenciales existentes</li>
<li><strong>Sistema protegido:</strong> No se puede reinstalar accidentalmente</li>
<li><strong>Soporte:</strong> <a href="mailto:support@u-site.app">support@u-site.app</a></li>
</ul>
</div>
<?php endif; ?>
<!-- Footer -->
<div class="mt-4 pt-3 border-top text-center">
<small class="text-muted">
Instalación Manual WhatsApp Bot |
Desarrollado por <strong><a href="https://u-site.app" target="_blank">U-Site.app</a></strong> |
<a href="https://u-site.app/support" target="_blank">Soporte</a>
</small>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>