This commit is contained in:
Lizandro Guarnizo
2026-01-28 03:09:52 -05:00
parent faec66ebf3
commit e96f507a06
12 changed files with 148 additions and 66 deletions
+151
View File
@@ -0,0 +1,151 @@
# 🤖 WhatsApp Bot Manager - Guía de Instalación Rápida
## 🚀 Pasos para poner en funcionamiento:
### 1. 📊 Instalar Base de Datos
- Abrir en navegador: `http://localhost/migrador/install.php`
- Hacer clic en "Ejecutar Instalación"
- Verificar que todas las tablas se crearon correctamente
### 2. 🔧 Verificar Sistema
- Abrir: `http://localhost/migrador/test.php`
- Revisar que todos los componentes estén en ✅
### 3. 🌐 Acceder al Panel
- Abrir: `http://localhost/migrador/index.php`
- Navegar por las diferentes secciones
### 4. ⚙️ Configurar WhatsApp (IMPORTANTE)
1. Ir a **Configuración** en el panel
2. Completar:
- **Token de WhatsApp**: EAAWTKu1iZAGABP46c7GZAFvHremu9uvTLOlgZCAa4eKUlaCqszzsQjjLcgnqORzo2EBhB7LZAcAqJ7clpGvNCk3oXKnqo8Fl0K2o7eHYoeaqZBesqjBPRfsd4ZBOdY4kN1YBJnmRznegTD9wtJZByVrRcMXF8YXaAJjLCuIFZCK7QFUpId7i4eVkFvbqUYnUKA91rgPvaeGRNZCLHa5ZC1ZB2Skn0gFNgPTBx7bedAMULYZD
- **Phone Number ID**: 938177732702718
- **Webhook Token**: mi_token_secreto_123
3. Guardar configuración
### 5. 🔗 Configurar Webhook en Facebook
1. Ir a [Facebook for Developers](https://developers.facebook.com)
2. Crear/configurar aplicación WhatsApp Business
3. Webhook URL: `https://tudominio.com/migrador/api/webhook.php`
4. Token de verificación: `mi_token_secreto_123`
5. Suscribirse a eventos: `conversations`
## 🎯 Prueba Rápida del Bot
Envía estos mensajes por WhatsApp para probar:
```
👤 Usuario: "Hola"
🤖 Bot: Mensaje de bienvenida
👤 Usuario: "menu"
🤖 Bot: Muestra menú principal
👤 Usuario: "1"
🤖 Bot: Muestra submenú de servicios
👤 Usuario: "ayuda"
🤖 Bot: Muestra información de ayuda
```
## 📋 Funcionalidades Principales
### 🤖 Bot Automático
- ✅ Menús navegables por números
- ✅ Respuestas automáticas
- ✅ Comandos especiales (menu, ayuda, salir)
- ✅ Gestión de estados de usuario
### 🎛️ Panel de Control
- ✅ Dashboard con estadísticas
- ✅ Gestión de conversaciones
- ✅ Administración de usuarios
- ✅ Editor de menús
- ✅ Envío de mensajes
- ✅ Configuración del sistema
### 🔧 APIs Disponibles
- ✅ Webhook para recibir mensajes
- ✅ Envío de mensajes individuales
- ✅ Envío masivo (broadcast)
- ✅ Gestión de menús
- ✅ Estadísticas y reportes
## 🛠️ Estructura de Archivos
```
bot/
├── 🏠 index.php # Panel principal
├── 🔧 install.php # Instalador automático
├── 🧪 test.php # Script de pruebas
├── 📖 README.md # Documentación completa
├── config/
│ └── config.php # Configuración
├── database/
│ └── schema.sql # Esquema de BD
├── api/ # APIs REST
│ ├── webhook.php # Webhook principal
│ ├── send_message.php # Envío de mensajes
│ ├── get_stats.php # Estadísticas
│ └── [más APIs...]
├── classes/
│ └── Database.php # Conexión BD
├── services/
│ ├── WhatsAppService.php # Servicio WhatsApp
│ └── BotService.php # Lógica del bot
└── assets/
├── css/styles.css # Estilos
└── js/app_simple.js # JavaScript
```
## 🎨 Personalización
### Cambiar Menús
1. Ir a **Menús** en el panel
2. Editar menús existentes o crear nuevos
3. Configurar opciones y acciones
### Agregar Respuestas Automáticas
1. Ir a **Respuestas Auto**
2. Agregar nuevas palabras clave
3. Definir respuestas personalizadas
### Configurar Mensajes Masivos
1. Ir a **Enviar Mensaje**
2. Usar la sección "Mensaje Masivo"
3. Seleccionar filtros de usuarios
## 🚨 Solución de Problemas
### ❌ Error de conexión BD
- Verificar credenciales en `config/config.php`
- Comprobar que MySQL esté funcionando
- Revisar permisos del usuario
### ❌ Webhook no funciona
- Verificar que la URL sea accesible públicamente
- Comprobar SSL (debe ser HTTPS)
- Revisar logs en el panel
### ❌ Bot no responde
- Verificar token en configuración
- Comprobar webhook en Facebook
- Revisar logs de PHP
## 📞 URLs de Prueba
- **Panel**: http://localhost/bot/index.php
- **Test**: http://localhost/bot/test.php
- **API Stats**: http://localhost/bot/api/get_stats.php
- **Webhook**: http://localhost/bot/api/webhook.php
## 🎯 ¡Sistema Listo!
Una vez completados todos los pasos, tendrás:
- 🤖 **Bot funcional** respondiendo mensajes automáticamente
- 🎛️ **Panel web** para gestión completa
- 📊 **Dashboard** con métricas en tiempo real
- 🔧 **APIs** para integraciones personalizadas
¡Disfruta de tu nuevo sistema de WhatsApp Bot! 🚀
+282
View File
@@ -0,0 +1,282 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🚀 WhatsApp Bot - Instalación</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);
}
.option-card {
border: 2px solid transparent;
border-radius: 15px;
transition: all 0.3s ease;
height: 100%;
}
.option-card:hover {
border-color: var(--primary-color);
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0,0,0,0.1);
}
.btn-install {
background: var(--bg-gradient);
border: none;
color: white;
padding: 12px 25px;
border-radius: 10px;
font-weight: 600;
width: 100%;
}
.btn-install:hover {
color: white;
transform: translateY(-2px);
}
.hosting-badge {
position: absolute;
top: -10px;
right: 15px;
font-size: 0.8rem;
padding: 5px 10px;
}
</style>
</head>
<body>
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-lg-10">
<div class="install-card p-5">
<div class="text-center mb-5">
<i class="fab fa-whatsapp text-success" style="font-size: 4rem;"></i>
<h1 class="mt-3 fw-bold">WhatsApp Bot Manager</h1>
<p class="text-muted">Elige el método de instalación según tu tipo de hosting</p>
<div class="mt-3">
<small class="text-muted">
Desarrollado por <strong><a href="https://u-site.app" target="_blank" class="text-decoration-none">U-Site.app</a></strong>
</small>
</div>
</div>
<div class="row g-3">
<!-- Instalación Automática -->
<div class="col-lg-2">
<div class="option-card bg-light p-3 position-relative">
<span class="hosting-badge badge bg-success">Local</span>
<div class="text-center mb-2">
<i class="fas fa-magic text-primary" style="font-size: 2rem;"></i>
</div>
<h6 class="text-center mb-2">🪄 Automática</h6>
<div class="mb-3">
<ul class="list-unstyled small">
<li>• Laragon/XAMPP</li>
<li>• VPS con root</li>
</ul>
</div>
<a href="install.php" class="btn btn-install btn-sm w-100">
<i class="fas fa-play me-1"></i>Usar
</a>
</div>
</div>
<!-- Instalación Manual -->
<div class="col-lg-2">
<div class="option-card bg-light p-3 position-relative">
<span class="hosting-badge badge bg-warning">Hosting</span>
<div class="text-center mb-2">
<i class="fas fa-tools text-warning" style="font-size: 2rem;"></i>
</div>
<h6 class="text-center mb-2">🛠️ Manual</h6>
<div class="mb-3">
<ul class="list-unstyled small">
<li>• HestiaCP</li>
<li>• Schema archivo</li>
</ul>
</div>
<a href="install_manual.php" class="btn btn-install bg-warning text-dark btn-sm w-100">
<i class="fas fa-wrench me-1"></i>Usar
</a>
</div>
</div>
<!-- Instalación Integrada -->
<div class="col-lg-2">
<div class="option-card bg-light p-3 position-relative">
<span class="hosting-badge badge bg-primary">Robusto</span>
<div class="text-center mb-2">
<i class="fas fa-cogs text-primary" style="font-size: 2rem;"></i>
</div>
<h6 class="text-center mb-2">🔧 Integrada</h6>
<div class="mb-3">
<ul class="list-unstyled small">
<li>• Schema interno</li>
<li>• Muy confiable</li>
</ul>
</div>
<a href="install_integrated.php" class="btn btn-install btn-sm w-100">
<i class="fas fa-cog me-1"></i>Usar
</a>
</div>
</div>
<!-- Instalación Ultra Básica -->
<div class="col-lg-3">
<div class="option-card bg-light p-3 position-relative border-danger">
<span class="hosting-badge badge bg-danger">SOLUCIÓN</span>
<div class="text-center mb-2">
<i class="fas fa-medkit text-danger" style="font-size: 2rem;"></i>
</div>
<h6 class="text-center mb-2">⚡ Ultra Básico</h6>
<div class="mb-3">
<ul class="list-unstyled small">
<li><strong>• Para errores "Table doesn't exist"</strong></li>
<li>• Solo tablas esenciales</li>
<li>• Paso a paso verificado</li>
</ul>
</div>
<a href="install_ultra_basic.php" class="btn btn-danger btn-sm w-100">
<i class="fas fa-medkit me-1"></i>SOLUCIONAR
</a>
</div>
</div>
<!-- Instalación Simplificada -->
<div class="col-lg-3">
<div class="option-card bg-light p-3 position-relative">
<span class="hosting-badge badge bg-info">Rápido</span>
<div class="text-center mb-2">
<i class="fas fa-rocket text-info" style="font-size: 2rem;"></i>
</div>
<h6 class="text-center mb-2">📦 Simple</h6>
<div class="mb-3">
<ul class="list-unstyled small">
<li>• Solo lo esencial</li>
<li>• Proceso rápido</li>
<li>• Principiantes</li>
</ul>
</div>
<a href="install_simple.php" class="btn btn-install btn-sm w-100" style="background: #17a2b8;">
<i class="fas fa-bolt me-1"></i>Usar
</a>
</div>
</div>
</div>
<div class="mt-5">
<div class="alert alert-danger">
<h5><i class="fas fa-exclamation-triangle me-2"></i>🚨 ¿Tienes errores de "Table doesn't exist"?</h5>
<div class="row">
<div class="col-md-8">
<p><strong>Si ves errores como:</strong></p>
<ul class="mb-2">
<li>❌ "Table 'usite_whatsapp_bot.menus' doesn't exist"</li>
<li>❌ "Table 'usite_whatsapp_bot.users' doesn't exist"</li>
<li>❌ "0 tablas, 0 elementos procesados"</li>
</ul>
</div>
<div class="col-md-4 text-center">
<a href="install_ultra_basic.php" class="btn btn-danger btn-lg">
<i class="fas fa-medkit me-2"></i>SOLUCIÓN AQUÍ
</a>
<br><small class="text-muted">Instalador Ultra Básico</small>
</div>
</div>
</div>
<div class="alert alert-warning">
<h5><i class="fas fa-question-circle me-2"></i>¿Cuál elegir según tu situación?</h5>
<div class="row">
<div class="col-md-6">
<h6>🔥 <strong>Si tuviste errores con schema.sql:</strong></h6>
<ul class="mb-2">
<li>❌ "Table doesn't exist"</li>
<li>❌ "0 tablas, 0 elementos"</li>
<li>❌ Errores de parsing SQL</li>
</ul>
<p><strong>👉 USA:</strong> <span class="badge bg-danger">Ultra Básico</span> - Resuelve el problema</p>
</div>
<div class="col-md-6">
<h6>💡 <strong>Recomendaciones generales:</strong></h6>
<ul class="mb-2">
<li><strong>Errores de tablas:</strong> Ultra Básico</li>
<li><strong>Primera vez:</strong> Integrada</li>
<li><strong>HestiaCP:</strong> Ultra Básico o Simple</li>
<li><strong>Desarrollo:</strong> Automática</li>
</ul>
</div>
</div>
</div>
</div>
<div class="row g-3 mt-4">
<div class="col-md-3">
<div class="text-center">
<a href="GUIA_HESTIACP.md" target="_blank" class="btn btn-outline-primary">
<i class="fas fa-book me-2"></i>Guía HestiaCP
</a>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<a href="debug_install.php" class="btn btn-outline-warning">
<i class="fas fa-bug me-2"></i>Diagnóstico
</a>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<a href="INSTALACION.md" target="_blank" class="btn btn-outline-success">
<i class="fas fa-file-alt me-2"></i>Documentación
</a>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<a href="test.php" class="btn btn-outline-info">
<i class="fas fa-vial me-2"></i>Probar Sistema
</a>
</div>
</div>
</div>
<!-- Footer -->
<div class="mt-5 pt-4 border-top text-center">
<small class="text-muted">
WhatsApp Bot Manager v1.0 |
Desarrollado por <strong>U-Site.app</strong> |
<a href="https://u-site.app/support" target="_blank">Soporte técnico</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>
+243
View File
@@ -0,0 +1,243 @@
<?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 'conversations' como alias de conversations
try {
$pdo->exec("
CREATE TABLE IF NOT EXISTS conversations (
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 'conversations' creada</div>";
} catch (PDOException $e) {
if (strpos($e->getMessage(), 'already exists') === false) {
echo "<div class='error'>❌ Error creando tabla conversations: " . htmlspecialchars($e->getMessage()) . "</div>";
} else {
echo "<div class='warning'>⚠️ Tabla 'conversations' ya existe</div>";
}
}
// Crear tabla 'system_config' como alias de system_config
try {
$pdo->exec("
CREATE TABLE IF NOT EXISTS system_config (
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 'system_config' creada</div>";
} catch (PDOException $e) {
if (strpos($e->getMessage(), 'already exists') === false) {
echo "<div class='error'>❌ Error creando tabla system_config: " . htmlspecialchars($e->getMessage()) . "</div>";
} else {
echo "<div class='warning'>⚠️ Tabla 'system_config' ya existe</div>";
}
}
echo "</div>";
// Copiar datos de system_config a system_config si no existen
echo "<div class='section'>";
echo "<h2>📊 SINCRONIZANDO CONFIGURACIÓN...</h2>";
try {
// Copiar datos de system_config a system_config
$pdo->exec("
INSERT IGNORE INTO system_config (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 system_config (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', 'conversations', 'system_config', '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>";
?>
+493
View File
@@ -0,0 +1,493 @@
<?php
/**
* Instalador automático del sistema WhatsApp Bot
* Desarrollado por U-Site.app - https://u-site.app
* Genera contraseña aleatoria y configura la base de datos
* 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 = 20) {
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*-_=+';
$password = '';
for ($i = 0; $i < $length; $i++) {
$password .= $chars[random_int(0, strlen($chars) - 1)];
}
return $password;
}
// Configuración de la instalación (compatible con cPanel)
$dbHost = 'localhost';
$dbName = 'whatsapp_bot';
$dbUser = 'whatsapp_user';
$dbPass = generateRandomPassword(20);
$dbRootUser = 'root';
$dbRootPass = ''; // En cPanel puede requerir contraseña
// Generar contraseña para admin
$adminPassword = generateRandomPassword(12);
$installStep = $_GET['step'] ?? 'welcome';
$errors = [];
$success = [];
// Procesar instalación
if ($installStep === 'install' && $_POST) {
try {
// 1. Intentar conectar como root para crear base de datos y usuario
try {
$rootPdo = new PDO("mysql:host=$dbHost;charset=utf8mb4", $dbRootUser, $dbRootPass);
$rootPdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
// Si no se puede conectar como root, es probable que sea hosting compartido
throw new Exception("⚠️ HOSTING COMPARTIDO DETECTADO ⚠️<br><br>" .
"No se pueden crear bases de datos automáticamente en este tipo de hosting.<br><br>" .
"<strong>SOLUCIÓN:</strong><br>" .
"1. Crea manualmente la base de datos y usuario en tu panel de control<br>" .
"2. Usa <a href='install_manual.php' class='btn btn-warning btn-sm'>install_manual.php</a> en su lugar<br>" .
"3. Lee la guía: <a href='GUIA_HESTIACP.md' target='_blank'>GUIA_HESTIACP.md</a><br><br>" .
"Error técnico: " . $e->getMessage());
}
// 2. Crear base de datos
$rootPdo->exec("CREATE DATABASE IF NOT EXISTS `$dbName` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
$success[] = "✅ Base de datos '$dbName' creada correctamente";
// 3. Crear usuario con permisos
$rootPdo->exec("DROP USER IF EXISTS '$dbUser'@'localhost'");
$rootPdo->exec("CREATE USER '$dbUser'@'localhost' IDENTIFIED BY '$dbPass'");
$rootPdo->exec("GRANT ALL PRIVILEGES ON `$dbName`.* TO '$dbUser'@'localhost'");
$rootPdo->exec("FLUSH PRIVILEGES");
$success[] = "✅ Usuario '$dbUser' creado con contraseña aleatoria";
// 4. Conectar con nuevo usuario
$pdo = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8mb4", $dbUser, $dbPass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 5. Crear tablas desde schema.sql
$schema = file_get_contents('database/schema.sql');
if (!$schema) {
throw new Exception("No se pudo leer el archivo schema.sql");
}
// Ejecutar comandos SQL uno por uno
$statements = array_filter(array_map('trim', explode(';', $schema)));
$tablesCreated = 0;
foreach ($statements as $statement) {
if (!empty($statement) && !preg_match('/^--/', $statement)) {
$pdo->exec($statement);
if (preg_match('/CREATE TABLE|INSERT INTO/', $statement)) {
$tablesCreated++;
}
}
}
$success[] = "$tablesCreated elementos de base de datos procesados";
// 6. 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_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);
file_put_contents($configFile, $configContent);
$success[] = "✅ Archivo config.php actualizado con nuevas credenciales";
// 7. Crear archivo de bloqueo de instalación
$lockContent = "Instalación completada: " . date('Y-m-d H:i:s') . "\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";
// 8. Crear archivo de credenciales para referencia
$credentialsFile = "CREDENCIALES_SISTEMA.txt";
$credentialsContent = "=== CREDENCIALES DEL SISTEMA WHATSAPP BOT ===\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 .= "Base de datos: $dbName\n";
$credentialsContent .= "Usuario: $dbUser\n";
$credentialsContent .= "Contraseña: $dbPass\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 .= "⚠️ Elimina este archivo después de guardar las credenciales.\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>🚀 Instalador 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;
}
.step-indicator {
width: 40px;
height: 40px;
border-radius: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
margin-right: 15px;
font-weight: bold;
}
.step-active { background: var(--primary-color); color: white; }
.step-completed { background: #28a745; color: white; }
.step-pending { background: #e9ecef; color: #6c757d; }
.console-output {
background: #1e1e1e;
color: #00ff00;
border-radius: 10px;
font-family: 'Courier New', monospace;
font-size: 0.9rem;
max-height: 300px;
overflow-y: auto;
}
.blink {
animation: blink 1s infinite;
}
@keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
</style>
</head>
<body>
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="install-card p-5">
<?php if ($installStep === 'welcome'): ?>
<!-- Pantalla de Bienvenida -->
<div class="text-center mb-4">
<i class="fas fa-database text-primary" style="font-size: 4rem;"></i>
<h1 class="mt-3 fw-bold">Instalador WhatsApp Bot</h1>
<p class="text-muted">Configuración automática con credenciales aleatorias</p>
<div class="mt-3">
<small class="text-muted">
Desarrollado por <strong><a href="https://u-site.app" target="_blank" class="text-decoration-none">U-Site.app</a></strong> |
<a href="https://u-site.app/support" target="_blank" class="text-decoration-none">Soporte técnico</a>
</small>
</div>
</div>
<div class="row g-3 mb-4">
<div class="col-md-4">
<div class="d-flex align-items-center">
<span class="step-indicator step-active">1</span>
<div>
<h6 class="mb-1">Crear BD</h6>
<small class="text-muted">Base de datos: <strong>whatsapp_bot</strong></small>
</div>
</div>
</div>
<div class="col-md-4">
<div class="d-flex align-items-center">
<span class="step-indicator step-pending">2</span>
<div>
<h6 class="mb-1">Crear Usuario</h6>
<small class="text-muted">Usuario: <strong>whatsapp_user</strong></small>
</div>
</div>
</div>
<div class="col-md-4">
<div class="d-flex align-items-center">
<span class="step-indicator step-pending">3</span>
<div>
<h6 class="mb-1">Configurar</h6>
<small class="text-muted">Aplicar configuración</small>
</div>
</div>
</div>
</div>
<div class="alert alert-info">
<i class="fas fa-info-circle me-2"></i>
<strong>Configuración automática para cPanel/hosting compartido:</strong>
<ul class="mb-0 mt-2">
<li><strong>Host:</strong> localhost (compatible con cualquier hosting)</li>
<li><strong>Base de datos:</strong> whatsapp_bot (se creará automáticamente)</li>
<li><strong>Usuario DB:</strong> whatsapp_user (se creará automáticamente)</li>
<li><strong>Contraseña DB:</strong> Se generará aleatoriamente (20 caracteres)</li>
<li><strong>Usuario Admin:</strong> admin</li>
<li><strong>Contraseña Admin:</strong> Se generará aleatoriamente (12 caracteres)</li>
</ul>
</div>
<div class="alert alert-success">
<i class="fas fa-shield-alt me-2"></i>
<strong>Características de seguridad:</strong>
<ul class="mb-0 mt-2">
<li>✅ Protección contra reinstalaciones</li>
<li>✅ Sistema de login con bloqueo por intentos</li>
<li>✅ Contraseñas encriptadas</li>
<li>✅ Auto-detección de URL del servidor</li>
<li>✅ Compatible con cualquier hosting cPanel</li>
</ul>
</div>
<div class="alert alert-warning">
<i class="fas fa-exclamation-triangle me-2"></i>
<strong>Requisitos:</strong> Asegúrate de que MySQL esté funcionando en Laragon
</div>
<div class="alert alert-danger">
<i class="fas fa-server me-2"></i>
<strong>⚠️ ¿Usas hosting compartido? (HestiaCP, cPanel, etc.)</strong><br>
Este instalador automático <strong>NO funcionará</strong> en hosting compartido porque requiere privilegios de administrador.<br><br>
<strong>👉 SOLUCIÓN:</strong>
<a href="install_manual.php" class="btn btn-warning btn-sm me-2">
<i class="fas fa-tools me-1"></i>Usar Instalador Manual
</a>
<a href="GUIA_HESTIACP.md" target="_blank" class="btn btn-info btn-sm">
<i class="fas fa-book me-1"></i>Ver Guía
</a>
</div>
<div class="text-center mb-4">
<div class="row g-3">
<div class="col-md-6">
<div class="password-display">
🔐 CONTRASEÑA BD:<br>
<strong><?= htmlspecialchars($dbPass) ?></strong>
</div>
</div>
<div class="col-md-6">
<div class="password-display">
👤 CONTRASEÑA ADMIN:<br>
<strong><?= htmlspecialchars($adminPassword) ?></strong>
</div>
</div>
</div>
</div>
<div class="text-center">
<a href="?step=install" class="btn btn-install btn-lg">
<i class="fas fa-play me-2"></i>Iniciar Instalación
</a>
</div>
<?php elseif ($installStep === 'install'): ?>
<!-- Pantalla de Instalación -->
<div class="text-center mb-4">
<i class="fas fa-cog fa-spin text-warning" style="font-size: 3rem;"></i>
<h2 class="mt-3">Instalando Sistema...</h2>
<p class="text-muted">Configurando base de datos automáticamente</p>
</div>
<form method="POST" id="installForm">
<div class="console-output p-4 mb-4">
<div>WhatsApp Bot Installer v1.0</div>
<div>Connecting to MySQL server (localhost)...</div>
<div>Generating secure random password...</div>
<div class="mt-3">
<strong style="color: #ffff00;">🔐 CONTRASEÑAS GENERADAS:</strong><br>
<span style="color: #00ffff; font-size: 1.0rem;">DB: <?= htmlspecialchars($dbPass) ?></span><br>
<span style="color: #00ff00; font-size: 1.0rem;">Admin: <?= htmlspecialchars($adminPassword) ?></span>
</div>
<div class="mt-2">Creating database 'whatsapp_bot'...</div>
<div>Creating user 'whatsapp_user'@'localhost'...</div>
<div>Granting privileges...</div>
<div>Installing database schema...</div>
<div>Updating configuration files...</div>
<div class="text-success mt-2">Ready to execute installation <span class="blink">_</span></div>
</div>
<div class="text-center">
<button type="submit" class="btn btn-install btn-lg">
<i class="fas fa-database me-2"></i>Ejecutar Instalación
</button>
</div>
</form>
<script>
// Auto-submit después de mostrar la información
setTimeout(function() {
document.getElementById('installForm').submit();
}, 4000);
</script>
<?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á listo para usar</p>
</div>
<!-- Mostrar errores si los hay -->
<?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; ?>
</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; ?>
<!-- Mostrar credenciales -->
<div class="row g-4 mb-4">
<div class="col-md-6">
<h5><i class="fas fa-database me-2 text-primary"></i>Credenciales de BD</h5>
<div class="bg-light p-3 rounded">
<div><strong>Host:</strong> <?= $dbHost ?></div>
<div><strong>Base de datos:</strong> <?= $dbName ?></div>
<div><strong>Usuario:</strong> <?= $dbUser ?></div>
<div class="mt-2">
<strong>Contraseña:</strong><br>
<div class="password-display mt-1">
<?= htmlspecialchars($dbPass) ?>
</div>
</div>
</div>
<h5 class="mt-3"><i class="fas fa-user-shield me-2 text-success"></i>Credenciales Admin</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-2"><strong>URL Login:</strong><br>
<a href="login.php" target="_blank"><?= AUTO_DETECTED_URL ?? $autoUrl ?? '' ?>/login.php</a>
</div>
</div>
</div>
<div class="col-md-6">
<h5><i class="fas fa-link me-2 text-success"></i>Próximos Pasos</h5>
<div class="d-grid gap-2">
<a href="login.php" class="btn btn-install">
<i class="fas fa-sign-in-alt me-2"></i>Iniciar Sesión
</a>
<a href="test.php" class="btn btn-outline-primary">
<i class="fas fa-check-circle me-2"></i>Probar Sistema
</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-warning">
<i class="fas fa-exclamation-triangle me-2"></i>
<strong>¡IMPORTANTE!</strong>
<ul class="mb-0 mt-2">
<li>Guarda las credenciales en un lugar seguro</li>
<li>El archivo <code>CREDENCIALES_SISTEMA.txt</code> contiene toda la información</li>
<li>Elimina este archivo después de guardar las credenciales</li>
<li><strong>El sistema está protegido contra reinstalaciones</strong></li>
<li>Configura tu token de WhatsApp después del login</li>
<li>Soporte técnico: <a href="mailto:support@u-site.app">support@u-site.app</a></li>
</ul>
</div>
<?php endif; ?>
<!-- Footer -->
<div class="mt-5 pt-4 border-top text-center">
<small class="text-muted">
WhatsApp Bot Manager v1.0 by <strong>U-Site.app</strong> |
Instalación automática con credenciales seguras |
<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>
+438
View File
@@ -0,0 +1,438 @@
<?php
/**
* Instalador con Schema Integrado
* Evita problemas de parsing del archivo schema.sql
* Desarrollado por U-Site.app
* Fecha: 14 de noviembre de 2025
*/
// Verificar si ya está instalado
if (file_exists('.installation_completed')) {
header('Location: login.php');
exit('Sistema ya instalado');
}
$step = $_GET['step'] ?? 'form';
$errors = [];
$success = [];
function generatePassword($length = 12) {
return bin2hex(random_bytes($length / 2));
}
$adminPassword = generatePassword(12);
// Schema SQL integrado (evita problemas de parsing)
$integratedSchema = [
// Crear tablas principales
"CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
phone_number VARCHAR(20) UNIQUE NOT NULL,
name VARCHAR(100),
email VARCHAR(100),
status ENUM('active', 'inactive', 'blocked') DEFAULT 'active',
current_menu_id INT NULL,
current_step INT DEFAULT 0,
session_data JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_phone (phone_number),
INDEX idx_status (status)
)",
"CREATE TABLE IF NOT EXISTS conversations (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
message_id VARCHAR(100),
direction ENUM('incoming', 'outgoing') NOT NULL,
message_type ENUM('text', 'image', 'audio', 'video', 'document', 'template') DEFAULT 'text',
content TEXT,
media_url VARCHAR(500),
status ENUM('sent', 'delivered', 'read', 'failed') DEFAULT 'sent',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
INDEX idx_user (user_id),
INDEX idx_created (created_at)
)",
"CREATE TABLE IF NOT EXISTS menus (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
title VARCHAR(200) NOT NULL,
description TEXT,
parent_id INT NULL,
is_root BOOLEAN DEFAULT FALSE,
is_active BOOLEAN DEFAULT TRUE,
order_position INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (parent_id) REFERENCES menus(id) ON DELETE CASCADE,
INDEX idx_parent (parent_id),
INDEX idx_active (is_active)
)",
"CREATE TABLE IF NOT EXISTS menu_options (
id INT AUTO_INCREMENT PRIMARY KEY,
menu_id INT NOT NULL,
option_number INT NOT NULL,
text VARCHAR(200) NOT NULL,
action_type ENUM('menu', 'message', 'api_call', 'end') NOT NULL,
action_value VARCHAR(500),
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (menu_id) REFERENCES menus(id) ON DELETE CASCADE,
UNIQUE KEY unique_menu_option (menu_id, option_number)
)",
"CREATE TABLE IF NOT EXISTS system_config (
id INT AUTO_INCREMENT PRIMARY KEY,
config_key VARCHAR(100) UNIQUE NOT NULL,
config_value TEXT,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)",
"CREATE TABLE IF NOT EXISTS autoresponses (
id INT AUTO_INCREMENT PRIMARY KEY,
trigger_type ENUM('keyword', 'menu_selection', 'welcome') NOT NULL,
trigger_value VARCHAR(200),
response_text TEXT NOT NULL,
response_type ENUM('text', 'template') DEFAULT 'text',
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)",
"CREATE TABLE IF NOT EXISTS webhook_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
request_body TEXT,
response_body TEXT,
status_code INT,
ip_address VARCHAR(45),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_created (created_at)
)"
];
$initialData = [
// Configuración inicial
"INSERT IGNORE INTO system_config (config_key, config_value, description) VALUES
('whatsapp_token', 'TU_TOKEN_AQUI', 'Token de WhatsApp Business API'),
('whatsapp_phone_number_id', 'TU_PHONE_ID_AQUI', 'ID del número de teléfono'),
('webhook_verify_token', 'mi_token_secreto_123', 'Token de verificación del webhook'),
('welcome_message', '¡Hola! 👋 Bienvenido. Escribe *menu* para ver opciones.', 'Mensaje de bienvenida'),
('business_name', 'Mi Empresa', 'Nombre de la empresa'),
('app_installed', '1', 'Marca de instalación completada'),
('install_date', NOW(), 'Fecha de instalación')",
// Menú principal
"INSERT IGNORE INTO menus (id, name, title, description, is_root, order_position) VALUES
(1, 'main_menu', '🏠 Menú Principal', 'Menú principal del sistema', TRUE, 1)",
// Opciones del menú principal
"INSERT IGNORE INTO menu_options (menu_id, option_number, text, action_type, action_value) VALUES
(1, 1, '📋 Información', 'message', 'Gracias por contactarnos. Un representante te atenderá pronto.'),
(1, 2, '📞 Soporte', 'message', 'Para soporte técnico, describe tu consulta y te ayudaremos.'),
(1, 0, '❌ Salir', 'end', 'Gracias por contactarnos. ¡Hasta pronto!')",
// Respuestas automáticas
"INSERT IGNORE INTO autoresponses (trigger_type, trigger_value, response_text) VALUES
('keyword', 'menu', 'Aquí tienes nuestro menú principal:'),
('keyword', 'hola', '¡Hola! 👋 Escribe *menu* para ver opciones.'),
('welcome', '', '¡Bienvenido! 👋 Escribe *menu* para comenzar.')"
];
if ($step === 'install' && $_POST) {
$dbHost = trim($_POST['db_host'] ?? 'localhost');
$dbPort = trim($_POST['db_port'] ?? '3306');
$dbName = trim($_POST['db_name'] ?? '');
$dbUser = trim($_POST['db_user'] ?? '');
$dbPass = $_POST['db_pass'] ?? '';
// Validar
if (empty($dbName)) $errors[] = "Nombre de BD requerido";
if (empty($dbUser)) $errors[] = "Usuario requerido";
if (empty($dbPass)) $errors[] = "Contraseña requerida";
if (empty($errors)) {
try {
// Conectar
$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
]);
$success[] = "✅ Conexión exitosa a '{$dbName}'";
// Ejecutar schema - PASO 1: Crear solo las tablas
$tablesCreated = 0;
$creationErrors = [];
echo "<script>console.log('Iniciando creación de tablas...');</script>";
foreach ($integratedSchema as $index => $sql) {
try {
echo "<script>console.log('Ejecutando SQL: " . substr($sql, 0, 50) . "...');</script>";
$result = $pdo->exec($sql);
$tablesCreated++;
// Extraer nombre de tabla para log
if (preg_match('/CREATE TABLE IF NOT EXISTS (\w+)/', $sql, $matches)) {
$tableName = $matches[1];
$success[] = "✅ Tabla '{$tableName}' creada/verificada";
// Verificar que la tabla realmente existe
try {
$checkQuery = "DESCRIBE `{$tableName}`";
$pdo->query($checkQuery);
} catch (PDOException $e) {
$creationErrors[] = "❌ Error verificando tabla '{$tableName}': " . $e->getMessage();
}
}
// Pequeña pausa para evitar problemas de timing
usleep(100000); // 0.1 segundos
} catch (PDOException $e) {
$errorMsg = $e->getMessage();
if (strpos($errorMsg, 'already exists') === false) {
$creationErrors[] = "❌ Error en tabla " . ($index + 1) . ": " . $errorMsg;
} else {
$tablesCreated++; // Contar como creada si ya existe
}
}
}
// Mostrar errores de creación si los hay
if (!empty($creationErrors)) {
foreach ($creationErrors as $error) {
$errors[] = $error;
}
}
// Solo continuar si se crearon las tablas principales
$essentialTables = ['users', 'conversations', 'menus', 'system_config'];
$missingTables = [];
foreach ($essentialTables as $table) {
try {
$pdo->query("DESCRIBE `{$table}`");
} catch (PDOException $e) {
$missingTables[] = $table;
}
}
if (!empty($missingTables)) {
$errors[] = "❌ Tablas esenciales no creadas: " . implode(', ', $missingTables);
$errors[] = "️ Intenta ejecutar el SQL manualmente en phpMyAdmin primero";
} else {
$success[] = "✅ Todas las tablas esenciales verificadas";
// PASO 2: Insertar datos solo si las tablas existen
$dataInserted = 0;
foreach ($initialData as $sql) {
try {
$pdo->exec($sql);
$dataInserted++;
} catch (PDOException $e) {
$errorMsg = $e->getMessage();
if (strpos($errorMsg, 'Duplicate entry') === false) {
$errors[] = "⚠️ Error insertando datos: " . $errorMsg;
}
}
}
$success[] = "{$tablesCreated} tablas procesadas, {$dataInserted} conjuntos de datos insertados";
}
// Actualizar config.php
$configFile = 'config/config.php';
if (file_exists($configFile)) {
$config = file_get_contents($configFile);
$config = preg_replace("/define\('DB_HOST',\s*'[^']*'\);/", "define('DB_HOST', '$dbHost');", $config);
$config = preg_replace("/define\('DB_PORT',\s*'[^']*'\);/", "define('DB_PORT', '$dbPort');", $config);
$config = preg_replace("/define\('DB_NAME',\s*'[^']*'\);/", "define('DB_NAME', '$dbName');", $config);
$config = preg_replace("/define\('DB_USER',\s*'[^']*'\);/", "define('DB_USER', '$dbUser');", $config);
$config = preg_replace("/define\('DB_PASS',\s*'[^']*'\);/", "define('DB_PASS', '$dbPass');", $config);
$config = preg_replace("/define\('ADMIN_PASSWORD',\s*'[^']*'\);/", "define('ADMIN_PASSWORD', '" . password_hash($adminPassword, PASSWORD_DEFAULT) . "');", $config);
// Auto-detectar URL
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https://' : 'http://';
$host = $_SERVER['HTTP_HOST'];
$path = dirname($_SERVER['SCRIPT_NAME']);
$autoUrl = $protocol . $host . $path;
$config = preg_replace("/define\('APP_URL',\s*'[^']*'\);/", "define('APP_URL', '$autoUrl');", $config);
if (file_put_contents($configFile, $config)) {
$success[] = "✅ Configuración actualizada";
} else {
$errors[] = "❌ No se pudo actualizar config.php";
}
}
// Verificar instalación
if (empty($errors)) {
try {
$userCount = $pdo->query("SELECT COUNT(*) FROM users")->fetchColumn();
$configCount = $pdo->query("SELECT COUNT(*) FROM system_config")->fetchColumn();
$success[] = "✅ Verificación: {$userCount} usuarios, {$configCount} configuraciones";
// Marcar como instalado
file_put_contents('.installation_completed', date('Y-m-d H:i:s'));
// Credenciales
$credentials = "USUARIO: admin\nCONTRASEÑA: {$adminPassword}\nFECHA: " . date('Y-m-d H:i:s');
file_put_contents('CREDENCIALES.txt', $credentials);
$success[] = "✅ Instalación completada exitosamente";
$step = 'completed';
} catch (Exception $e) {
$errors[] = "❌ Error en verificación: " . $e->getMessage();
}
}
} catch (PDOException $e) {
$errors[] = "❌ Error de conexión: " . $e->getMessage();
}
}
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🔧 Instalador Integrado</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>
body { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; }
.install-card { background: rgba(255,255,255,0.95); border-radius: 15px; }
.btn-primary { background: #667eea; border: none; }
</style>
</head>
<body class="d-flex align-items-center">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="install-card shadow-lg p-4">
<?php if ($step === 'form'): ?>
<div class="text-center mb-4">
<h2><i class="fas fa-cogs me-2"></i>Instalador con Schema Integrado</h2>
<p class="text-muted">Evita problemas de parsing del archivo schema.sql</p>
</div>
<div class="alert alert-info">
<i class="fas fa-info-circle me-2"></i>
<strong>Ventajas de este instalador:</strong>
<ul class="mb-0 mt-2">
<li>✅ Schema SQL integrado en el código</li>
<li>✅ No depende de archivos externos</li>
<li>✅ Ejecución paso a paso controlada</li>
<li>✅ Manejo de errores mejorado</li>
</ul>
</div>
<form method="POST" action="?step=install">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label"><i class="fas fa-server me-2"></i>Host</label>
<input type="text" class="form-control" name="db_host" value="localhost" required>
</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" required>
</div>
<div class="col-md-6">
<label class="form-label"><i class="fas fa-database me-2"></i>Base de datos</label>
<input type="text" class="form-control" name="db_name" placeholder="usite_whatsapp_bot" required>
<small class="text-muted">Debe existir previamente</small>
</div>
<div class="col-md-6">
<label class="form-label"><i class="fas fa-user me-2"></i>Usuario</label>
<input type="text" class="form-control" name="db_user" placeholder="usite_usuario" required>
</div>
<div class="col-12">
<label class="form-label"><i class="fas fa-key me-2"></i>Contraseña</label>
<input type="password" class="form-control" name="db_pass" required>
</div>
</div>
<div class="text-center mt-4">
<div class="alert alert-success">
<strong><i class="fas fa-user-shield me-2"></i>Credenciales de Admin:</strong><br>
<strong>Usuario:</strong> admin<br>
<strong>Contraseña:</strong> <code><?= $adminPassword ?></code>
</div>
<button type="submit" class="btn btn-primary btn-lg">
<i class="fas fa-rocket me-2"></i>Instalar con Schema Integrado
</button>
</div>
</form>
<?php elseif ($step === 'install'): ?>
<div class="text-center mb-4">
<h2><i class="fas fa-cog fa-spin me-2"></i>Instalando...</h2>
</div>
<?php if (!empty($errors)): ?>
<div class="alert alert-danger">
<h5><i class="fas fa-exclamation-triangle me-2"></i>Errores:</h5>
<?php foreach ($errors as $error): ?>
<div><?= htmlspecialchars($error) ?></div>
<?php endforeach; ?>
<hr>
<a href="?step=form" class="btn btn-outline-danger">Reintentar</a>
</div>
<?php endif; ?>
<?php if (!empty($success)): ?>
<div class="alert alert-success">
<h5><i class="fas fa-check-circle me-2"></i>Progreso:</h5>
<?php foreach ($success as $msg): ?>
<div><?= htmlspecialchars($msg) ?></div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php elseif ($step === 'completed'): ?>
<div class="text-center mb-4">
<h2 class="text-success"><i class="fas fa-check-circle me-2"></i>¡Instalación Exitosa!</h2>
<p class="text-muted">Sistema WhatsApp Bot instalado correctamente</p>
</div>
<div class="row g-4">
<div class="col-md-6">
<h5><i class="fas fa-key me-2 text-success"></i>Credenciales</h5>
<div class="alert alert-success">
<strong>Usuario:</strong> admin<br>
<strong>Contraseña:</strong> <code><?= $adminPassword ?></code><br>
<small>Guardadas en CREDENCIALES.txt</small>
</div>
</div>
<div class="col-md-6">
<h5><i class="fas fa-rocket me-2 text-primary"></i>Acciones</h5>
<div class="d-grid gap-2">
<a href="index.php" class="btn btn-primary">Panel de Control</a>
<a href="test.php" class="btn btn-outline-success">Probar Sistema</a>
<a href="login.php" class="btn btn-outline-info">Iniciar Sesión</a>
</div>
</div>
</div>
<div class="alert alert-info mt-4">
<i class="fas fa-info-circle me-2"></i>
<strong>Próximos pasos:</strong> Configura tu token de WhatsApp en el panel de administración.
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</body>
</html>
+544
View File
@@ -0,0 +1,544 @@
<?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>
+239
View File
@@ -0,0 +1,239 @@
<?php
/**
* Instalador Simplificado para Hosting Compartido
* Version mínima y robusta para HestiaCP/cPanel
* Desarrollado por U-Site.app
* Fecha: 13 de noviembre de 2025
*/
// Configuración básica
error_reporting(E_ALL);
ini_set('display_errors', 1);
$step = $_GET['step'] ?? 'form';
$errors = [];
$success = [];
// Generar contraseña admin
function generatePassword($length = 12) {
return bin2hex(random_bytes($length / 2));
}
$adminPassword = generatePassword(12);
if ($step === 'install' && $_POST) {
$dbHost = trim($_POST['db_host'] ?? 'localhost');
$dbPort = trim($_POST['db_port'] ?? '3306');
$dbName = trim($_POST['db_name'] ?? '');
$dbUser = trim($_POST['db_user'] ?? '');
$dbPass = $_POST['db_pass'] ?? '';
// Validar campos
if (empty($dbName)) $errors[] = "Nombre de BD requerido";
if (empty($dbUser)) $errors[] = "Usuario de BD requerido";
if (empty($dbPass)) $errors[] = "Contraseña de BD requerida";
if (empty($errors)) {
try {
// 1. Conectar a BD
$dsn = "mysql:host={$dbHost};port={$dbPort};dbname={$dbName};charset=utf8mb4";
$pdo = new PDO($dsn, $dbUser, $dbPass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
$success[] = "✅ Conexión exitosa";
// 2. Aplicar schema básico
$basicSchema = "
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
phone_number VARCHAR(20) UNIQUE NOT NULL,
name VARCHAR(100),
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS conversations (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
direction ENUM('incoming', 'outgoing') NOT NULL,
content TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE IF NOT EXISTS system_config (
id INT AUTO_INCREMENT PRIMARY KEY,
config_key VARCHAR(100) UNIQUE NOT NULL,
config_value TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT IGNORE INTO system_config (config_key, config_value) VALUES
('app_installed', '1'),
('install_date', NOW()),
('admin_user', 'admin');
";
$statements = array_filter(explode(';', $basicSchema));
foreach ($statements as $stmt) {
if (trim($stmt)) {
$pdo->exec(trim($stmt));
}
}
$success[] = "✅ Tablas creadas";
// 3. Actualizar config.php
$configFile = 'config/config.php';
if (file_exists($configFile)) {
$config = file_get_contents($configFile);
$config = preg_replace("/define\('DB_HOST',\s*'[^']*'\);/", "define('DB_HOST', '$dbHost');", $config);
$config = preg_replace("/define\('DB_PORT',\s*'[^']*'\);/", "define('DB_PORT', '$dbPort');", $config);
$config = preg_replace("/define\('DB_NAME',\s*'[^']*'\);/", "define('DB_NAME', '$dbName');", $config);
$config = preg_replace("/define\('DB_USER',\s*'[^']*'\);/", "define('DB_USER', '$dbUser');", $config);
$config = preg_replace("/define\('DB_PASS',\s*'[^']*'\);/", "define('DB_PASS', '$dbPass');", $config);
$config = preg_replace("/define\('ADMIN_PASSWORD',\s*'[^']*'\);/", "define('ADMIN_PASSWORD', '" . password_hash($adminPassword, PASSWORD_DEFAULT) . "');", $config);
file_put_contents($configFile, $config);
$success[] = "✅ Configuración actualizada";
}
// 4. Crear archivo de instalación completada
file_put_contents('.installation_completed', date('Y-m-d H:i:s'));
$success[] = "✅ Instalación completada";
// 5. Crear credenciales
$creds = "USUARIO ADMIN: admin\nCONTRASEÑA: $adminPassword\nFECHA: " . date('Y-m-d H:i:s');
file_put_contents('CREDENCIALES.txt', $creds);
$success[] = "✅ Credenciales guardadas en CREDENCIALES.txt";
$step = 'completed';
} catch (Exception $e) {
$errors[] = "❌ Error: " . $e->getMessage();
}
}
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>📦 Instalador Simplificado</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; }
.card { background: rgba(255,255,255,0.95); border-radius: 15px; }
.btn-primary { background: #667eea; border: none; }
</style>
</head>
<body class="d-flex align-items-center">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card shadow-lg p-4">
<?php if ($step === 'form'): ?>
<div class="text-center mb-4">
<h2>📦 Instalador Simplificado</h2>
<p class="text-muted">Para hosting compartido (HestiaCP/cPanel)</p>
</div>
<div class="alert alert-info">
<strong>Antes de continuar:</strong> Asegúrate de haber creado la base de datos y usuario en tu panel de control.
</div>
<form method="POST" action="?step=install">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">Host</label>
<input type="text" class="form-control" name="db_host" value="localhost" required>
</div>
<div class="col-md-6">
<label class="form-label">Puerto</label>
<input type="text" class="form-control" name="db_port" value="3306" required>
</div>
<div class="col-md-6">
<label class="form-label">Base de datos</label>
<input type="text" class="form-control" name="db_name" placeholder="mi_basedatos" required>
</div>
<div class="col-md-6">
<label class="form-label">Usuario</label>
<input type="text" class="form-control" name="db_user" placeholder="mi_usuario" required>
</div>
<div class="col-12">
<label class="form-label">Contraseña</label>
<input type="password" class="form-control" name="db_pass" required>
</div>
</div>
<div class="text-center mt-4">
<div class="alert alert-success">
<strong>Contraseña de administrador:</strong><br>
<code><?= $adminPassword ?></code>
</div>
<button type="submit" class="btn btn-primary btn-lg">
<i class="fas fa-play"></i> Instalar Sistema
</button>
</div>
</form>
<?php elseif ($step === 'install'): ?>
<div class="text-center mb-4">
<h2>⚙️ Instalando...</h2>
</div>
<?php if (!empty($errors)): ?>
<div class="alert alert-danger">
<h5>❌ Errores:</h5>
<?php foreach ($errors as $error): ?>
<div><?= htmlspecialchars($error) ?></div>
<?php endforeach; ?>
<hr>
<a href="?step=form" class="btn btn-outline-danger">Reintentar</a>
</div>
<?php endif; ?>
<?php if (!empty($success)): ?>
<div class="alert alert-success">
<h5>✅ Progreso:</h5>
<?php foreach ($success as $msg): ?>
<div><?= htmlspecialchars($msg) ?></div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php elseif ($step === 'completed'): ?>
<div class="text-center mb-4">
<h2 class="text-success">🎉 ¡Instalación Exitosa!</h2>
</div>
<div class="row g-4">
<div class="col-md-6">
<h5>🔐 Credenciales de Acceso</h5>
<div class="alert alert-success">
<strong>Usuario:</strong> admin<br>
<strong>Contraseña:</strong> <code><?= $adminPassword ?></code>
</div>
</div>
<div class="col-md-6">
<h5>🚀 Próximos Pasos</h5>
<div class="d-grid gap-2">
<a href="index.php" class="btn btn-primary">Panel de Control</a>
<a href="test.php" class="btn btn-outline-success">Probar Sistema</a>
</div>
</div>
</div>
<div class="alert alert-warning mt-4">
<strong>Importante:</strong> Guarda las credenciales. El archivo CREDENCIALES.txt contiene toda la información.
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</body>
</html>
+282
View File
@@ -0,0 +1,282 @@
<?php
/**
* Instalador Ultra Básico - Paso a Paso
* Para resolver problemas de creación de tablas
* Desarrollado por U-Site.app
* Fecha: 14 de noviembre de 2025
*/
error_reporting(E_ALL);
ini_set('display_errors', 1);
if (file_exists('.installation_completed')) {
header('Location: login.php');
exit('Sistema ya instalado');
}
$step = $_GET['step'] ?? 'form';
$errors = [];
$success = [];
$adminPassword = bin2hex(random_bytes(6)); // 12 caracteres
if ($step === 'install' && $_POST) {
$dbHost = trim($_POST['db_host'] ?? 'localhost');
$dbPort = trim($_POST['db_port'] ?? '3306');
$dbName = trim($_POST['db_name'] ?? '');
$dbUser = trim($_POST['db_user'] ?? '');
$dbPass = $_POST['db_pass'] ?? '';
if (empty($dbName)) $errors[] = "BD requerida";
if (empty($dbUser)) $errors[] = "Usuario requerido";
if (empty($dbPass)) $errors[] = "Contraseña requerida";
if (empty($errors)) {
try {
$dsn = "mysql:host={$dbHost};port={$dbPort};dbname={$dbName};charset=utf8mb4";
$pdo = new PDO($dsn, $dbUser, $dbPass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
$success[] = "✅ Conectado a '{$dbName}'";
// Crear tabla users primero
$sql = "CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
phone_number VARCHAR(20) UNIQUE NOT NULL,
name VARCHAR(100),
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)";
$pdo->exec($sql);
// Verificar que se creó
try {
$result = $pdo->query("SELECT COUNT(*) FROM users");
$success[] = "✅ Tabla 'users' creada y funcional";
} catch (Exception $e) {
$errors[] = "❌ Tabla users no funciona: " . $e->getMessage();
}
// Crear tabla system_config
$sql = "CREATE TABLE IF NOT EXISTS system_config (
id INT AUTO_INCREMENT PRIMARY KEY,
config_key VARCHAR(100) UNIQUE NOT NULL,
config_value TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)";
$pdo->exec($sql);
// Verificar
try {
$result = $pdo->query("SELECT COUNT(*) FROM system_config");
$success[] = "✅ Tabla 'system_config' creada y funcional";
} catch (Exception $e) {
$errors[] = "❌ Tabla system_config no funciona: " . $e->getMessage();
}
// Solo insertar datos si no hay errores
if (empty($errors)) {
// Insertar configuración básica
$configSql = "INSERT IGNORE INTO system_config (config_key, config_value) VALUES
('app_installed', '1'),
('install_date', NOW()),
('business_name', 'Mi Empresa'),
('admin_user', 'admin')";
try {
$pdo->exec($configSql);
$success[] = "✅ Configuración inicial insertada";
} catch (Exception $e) {
$errors[] = "⚠️ Error insertando config: " . $e->getMessage();
}
// Actualizar config.php
if (file_exists('config/config.php')) {
$config = file_get_contents('config/config.php');
$config = preg_replace("/define\('DB_HOST',\s*'[^']*'\);/", "define('DB_HOST', '$dbHost');", $config);
$config = preg_replace("/define\('DB_PORT',\s*'[^']*'\);/", "define('DB_PORT', '$dbPort');", $config);
$config = preg_replace("/define\('DB_NAME',\s*'[^']*'\);/", "define('DB_NAME', '$dbName');", $config);
$config = preg_replace("/define\('DB_USER',\s*'[^']*'\);/", "define('DB_USER', '$dbUser');", $config);
$config = preg_replace("/define\('DB_PASS',\s*'[^']*'\);/", "define('DB_PASS', '$dbPass');", $config);
$config = preg_replace("/define\('ADMIN_PASSWORD',\s*'[^']*'\);/", "define('ADMIN_PASSWORD', '" . password_hash($adminPassword, PASSWORD_DEFAULT) . "');", $config);
file_put_contents('config/config.php', $config);
$success[] = "✅ config.php actualizado";
}
// Verificar que todo funciona
try {
$userCount = $pdo->query("SELECT COUNT(*) FROM users")->fetchColumn();
$configCount = $pdo->query("SELECT COUNT(*) FROM system_config")->fetchColumn();
$success[] = "✅ Verificación final: {$userCount} usuarios, {$configCount} configs";
// Marcar como instalado
file_put_contents('.installation_completed', date('Y-m-d H:i:s'));
file_put_contents('CREDENCIALES_BASICO.txt', "USUARIO: admin\nCONTRASEÑA: {$adminPassword}\nFECHA: " . date('Y-m-d H:i:s'));
$success[] = "🎉 Instalación básica completada";
$step = 'completed';
} catch (Exception $e) {
$errors[] = "❌ Error en verificación final: " . $e->getMessage();
}
}
} catch (PDOException $e) {
$errors[] = "❌ Error de conexión: " . $e->getMessage();
}
}
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>⚡ Instalador Ultra Básico</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background: linear-gradient(45deg, #667eea, #764ba2); min-height: 100vh; }
.card { background: rgba(255,255,255,0.95); border-radius: 15px; box-shadow: 0 10px 30px rgba(0,0,0,0.3); }
</style>
</head>
<body class="d-flex align-items-center">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card p-4">
<?php if ($step === 'form'): ?>
<div class="text-center mb-4">
<h2>⚡ Instalador Ultra Básico</h2>
<p class="text-muted">Solo crea las tablas esenciales paso a paso</p>
</div>
<div class="alert alert-info">
<h6><i class="fas fa-info-circle me-2"></i>Este instalador:</h6>
<ul class="mb-0">
<li>✅ Crea solo 2 tablas esenciales: <code>users</code> y <code>system_config</code></li>
<li>✅ Verifica cada paso antes de continuar</li>
<li>✅ Proceso ultra simplificado</li>
<li>✅ Ideal para resolver problemas de creación de tablas</li>
</ul>
</div>
<form method="POST" action="?step=install">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">Host</label>
<input type="text" class="form-control" name="db_host" value="localhost" required>
</div>
<div class="col-md-6">
<label class="form-label">Puerto</label>
<input type="text" class="form-control" name="db_port" value="3306" required>
</div>
<div class="col-md-6">
<label class="form-label">Base de datos</label>
<input type="text" class="form-control" name="db_name" placeholder="usite_whatsapp_bot" required>
</div>
<div class="col-md-6">
<label class="form-label">Usuario</label>
<input type="text" class="form-control" name="db_user" required>
</div>
<div class="col-12">
<label class="form-label">Contraseña</label>
<input type="password" class="form-control" name="db_pass" required>
</div>
</div>
<div class="text-center mt-4">
<div class="alert alert-success">
<strong>Contraseña de admin que se generará:</strong><br>
<code><?= $adminPassword ?></code>
</div>
<button type="submit" class="btn btn-primary btn-lg">
⚡ Instalación Ultra Básica
</button>
</div>
</form>
<?php elseif ($step === 'install'): ?>
<div class="text-center mb-4">
<h2>⚙️ Instalando paso a paso...</h2>
</div>
<?php if (!empty($errors)): ?>
<div class="alert alert-danger">
<h5>❌ Errores:</h5>
<?php foreach ($errors as $error): ?>
<div><?= htmlspecialchars($error) ?></div>
<?php endforeach; ?>
<hr>
<a href="?step=form" class="btn btn-outline-danger">Reintentar</a>
</div>
<?php endif; ?>
<?php if (!empty($success)): ?>
<div class="alert alert-success">
<h5>✅ Progreso:</h5>
<?php foreach ($success as $msg): ?>
<div><?= htmlspecialchars($msg) ?></div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($step !== 'completed' && !empty($errors)): ?>
<div class="alert alert-warning">
<h6>💡 Sugerencias para resolver errores:</h6>
<ul class="mb-0">
<li>Verifica que la base de datos existe</li>
<li>Confirma que el usuario tiene permisos ALL en la BD</li>
<li>Prueba conectarte manualmente con phpMyAdmin</li>
<li>Si persiste, contacta soporte con estos mensajes</li>
</ul>
</div>
<?php endif; ?>
<?php elseif ($step === 'completed'): ?>
<div class="text-center mb-4">
<h2 class="text-success">🎉 ¡Instalación Básica Exitosa!</h2>
<p class="text-muted">Sistema mínimo funcional instalado</p>
</div>
<div class="row g-4">
<div class="col-md-6">
<h5>🔑 Credenciales</h5>
<div class="alert alert-success">
<strong>Usuario:</strong> admin<br>
<strong>Contraseña:</strong> <code><?= $adminPassword ?></code><br>
<small>Guardadas en: CREDENCIALES_BASICO.txt</small>
</div>
</div>
<div class="col-md-6">
<h5>🚀 Siguiente</h5>
<div class="d-grid gap-2">
<a href="test.php" class="btn btn-success">Probar Sistema</a>
<a href="index.php" class="btn btn-primary">Panel Admin</a>
<a href="login.php" class="btn btn-outline-info">Login</a>
</div>
</div>
</div>
<div class="alert alert-info mt-4">
<h6>📋 Lo que se instaló:</h6>
<ul class="mb-0">
<li>✅ Tabla <code>users</code> - Para gestión de usuarios</li>
<li>✅ Tabla <code>system_config</code> - Para configuración</li>
<li>✅ Configuración básica del sistema</li>
<li>✅ Credenciales de administrador</li>
</ul>
<hr>
<small><strong>Nota:</strong> Puedes agregar más funcionalidades desde el panel de administración.</small>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</body>
</html>