Spaces:
Configuration error
Configuration error
| import gradio as gr | |
| import json | |
| import sqlite3 | |
| from datetime import datetime | |
| from pathlib import Path | |
| import os | |
| # Configuración de la base de datos | |
| DB_FILE = 'osorno_runners.db' | |
| def init_db(): | |
| """Inicializar base de datos SQLite""" | |
| conn = sqlite3.connect(DB_FILE) | |
| cursor = conn.cursor() | |
| # Tabla de planes | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS planes ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| plan_data TEXT NOT NULL, | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| created_by TEXT NOT NULL, | |
| athlete_name TEXT NOT NULL, | |
| distance TEXT NOT NULL, | |
| race_date TEXT NOT NULL | |
| ) | |
| ''') | |
| # Tabla de usuarios | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS users ( | |
| username TEXT PRIMARY KEY, | |
| password TEXT NOT NULL, | |
| role TEXT NOT NULL, | |
| name TEXT NOT NULL | |
| ) | |
| ''') | |
| # Insertar usuarios por defecto si no existen | |
| cursor.execute('SELECT COUNT(*) FROM users') | |
| if cursor.fetchone()[0] == 0: | |
| cursor.execute("INSERT INTO users VALUES ('USER', '123', 'user', 'Usuario')") | |
| cursor.execute("INSERT INTO users VALUES ('ADMIN', '123', 'admin', 'Administrador')") | |
| print("✅ Usuarios por defecto creados: USER/123 y ADMIN/123") | |
| conn.commit() | |
| conn.close() | |
| print("✅ Base de datos inicializada correctamente") | |
| def save_plan_to_db(plan_data, username): | |
| """Guardar plan en la base de datos""" | |
| try: | |
| conn = sqlite3.connect(DB_FILE) | |
| cursor = conn.cursor() | |
| cursor.execute(''' | |
| INSERT INTO planes (plan_data, created_by, athlete_name, distance, race_date) | |
| VALUES (?, ?, ?, ?, ?) | |
| ''', ( | |
| json.dumps(plan_data), | |
| username, | |
| plan_data['userData']['name'], | |
| plan_data['userData']['distance'], | |
| plan_data['userData']['raceDate'] | |
| )) | |
| conn.commit() | |
| plan_id = cursor.lastrowid | |
| conn.close() | |
| print(f"✅ Plan guardado con ID: {plan_id}") | |
| return plan_id | |
| except Exception as e: | |
| print(f"❌ Error al guardar plan: {e}") | |
| return None | |
| def get_all_plans(username=None, role='user'): | |
| """Obtener todos los planes según permisos""" | |
| try: | |
| conn = sqlite3.connect(DB_FILE) | |
| cursor = conn.cursor() | |
| if role == 'admin': | |
| cursor.execute('SELECT id, plan_data, created_at, created_by FROM planes ORDER BY created_at DESC') | |
| else: | |
| cursor.execute('SELECT id, plan_data, created_at, created_by FROM planes WHERE created_by = ? ORDER BY created_at DESC', (username,)) | |
| plans = [] | |
| for row in cursor.fetchall(): | |
| plan_data = json.loads(row[1]) | |
| plan_data['id'] = row[0] | |
| plan_data['createdAt'] = row[2] | |
| plan_data['createdBy'] = row[3] | |
| plans.append(plan_data) | |
| conn.close() | |
| print(f"✅ Cargados {len(plans)} planes para {username} ({role})") | |
| return plans | |
| except Exception as e: | |
| print(f"❌ Error al cargar planes: {e}") | |
| return [] | |
| def delete_plan_from_db(plan_id): | |
| """Eliminar plan de la base de datos""" | |
| try: | |
| conn = sqlite3.connect(DB_FILE) | |
| cursor = conn.cursor() | |
| cursor.execute('DELETE FROM planes WHERE id = ?', (plan_id,)) | |
| conn.commit() | |
| conn.close() | |
| print(f"✅ Plan {plan_id} eliminado") | |
| return True | |
| except Exception as e: | |
| print(f"❌ Error al eliminar plan: {e}") | |
| return False | |
| def authenticate_user(username, password): | |
| """Autenticar usuario""" | |
| try: | |
| conn = sqlite3.connect(DB_FILE) | |
| cursor = conn.cursor() | |
| cursor.execute('SELECT role, name FROM users WHERE username = ? AND password = ?', | |
| (username.upper(), password)) | |
| result = cursor.fetchone() | |
| conn.close() | |
| if result: | |
| user_data = { | |
| 'username': username.upper(), | |
| 'role': result[0], | |
| 'name': result[1] | |
| } | |
| print(f"✅ Login exitoso: {username} ({result[0]})") | |
| return user_data | |
| else: | |
| print(f"❌ Login fallido: {username}") | |
| return None | |
| except Exception as e: | |
| print(f"❌ Error en autenticación: {e}") | |
| return None | |
| # APIs para el frontend | |
| def api_login(request: gr.Request): | |
| """API de login""" | |
| try: | |
| data = json.loads(request.query_params.get('data', '{}')) | |
| username = data.get('username', '') | |
| password = data.get('password', '') | |
| user = authenticate_user(username, password) | |
| if user: | |
| return json.dumps({'success': True, 'user': user}) | |
| return json.dumps({'success': False, 'error': 'Credenciales inválidas'}) | |
| except Exception as e: | |
| return json.dumps({'success': False, 'error': str(e)}) | |
| def api_save_plan(request: gr.Request): | |
| """API para guardar plan""" | |
| try: | |
| data = json.loads(request.query_params.get('data', '{}')) | |
| plan_json = data.get('plan', '{}') | |
| username = data.get('username', '') | |
| plan_data = json.loads(plan_json) | |
| plan_id = save_plan_to_db(plan_data, username) | |
| if plan_id: | |
| return json.dumps({'success': True, 'id': plan_id}) | |
| return json.dumps({'success': False, 'error': 'Error al guardar'}) | |
| except Exception as e: | |
| return json.dumps({'success': False, 'error': str(e)}) | |
| def api_get_plans(request: gr.Request): | |
| """API para obtener planes""" | |
| try: | |
| data = json.loads(request.query_params.get('data', '{}')) | |
| username = data.get('username', '') | |
| role = data.get('role', 'user') | |
| plans = get_all_plans(username, role) | |
| return json.dumps({'success': True, 'plans': plans}) | |
| except Exception as e: | |
| return json.dumps({'success': False, 'error': str(e)}) | |
| def api_delete_plan(request: gr.Request): | |
| """API para eliminar plan""" | |
| try: | |
| data = json.loads(request.query_params.get('data', '{}')) | |
| plan_id = data.get('plan_id', 0) | |
| success = delete_plan_from_db(plan_id) | |
| if success: | |
| return json.dumps({'success': True}) | |
| return json.dumps({'success': False, 'error': 'Error al eliminar'}) | |
| except Exception as e: | |
| return json.dumps({'success': False, 'error': str(e)}) | |
| # Inicializar BD al arrancar | |
| print("🚀 Iniciando Osorno Runners - Sistema de Entrenamiento") | |
| init_db() | |
| # Leer HTML | |
| html_path = Path("index.html") | |
| if html_path.exists(): | |
| html_content = html_path.read_text(encoding='utf-8') | |
| print("✅ HTML cargado correctamente") | |
| else: | |
| html_content = "<h1>Error: index.html no encontrado</h1>" | |
| print("❌ Error: index.html no encontrado") | |
| # Crear interfaz Gradio | |
| with gr.Blocks( | |
| title="Osorno Runners", | |
| theme=gr.themes.Soft(), | |
| css=""" | |
| .gradio-container {padding: 0 !important;} | |
| .contain {max-width: 100% !important;} | |
| """ | |
| ) as app: | |
| gr.HTML(html_content) | |
| # Configuración del servidor | |
| if __name__ == "__main__": | |
| print("🌐 Iniciando servidor en puerto 7860") | |
| app.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=False, | |
| show_error=True | |
| ) | |