# Memorial Digital David Gonzalez Suazo - Documentacion Completa

## Indice

1. Que es este proyecto
2. Arquitectura y archivos
3. Requisitos del sistema
4. Instalacion paso a paso
5. Configuracion
6. Como arrancar el servidor
7. Acceso remoto con Cloudflare Tunnel
8. Funcionalidades implementadas
9. Administracion
10. Estructura del codigo (servidor.py)
11. Tareas pendientes / futuras
12. Solucion de problemas

---

## 1. Que es este proyecto

Un servidor web autohospedado (Flask + Python) que sirve como memorial/testimonio digital para David Gonzalez Suazo. La familia puede acceder desde cualquier lugar para subir fotos, videos y escribir recuerdos. El servidor corre en el ordenador del padre y se expone a internet mediante Cloudflare Tunnel.

**Caracteristicas principales:**
- Galeria animada tipo collage con 5 filas de fotos en movimiento
- Fondo rotativo con fotos del memorial
- Musica de fondo (YouTube: Alan Walker, Christina Perri, Zara Larsson)
- Subida de fotos y videos por la familia
- Sistema de contraseñas de dos niveles (familia / admin)
- Registro de conexiones (quien entra, cuando, desde donde)
- Copias de seguridad automaticas cada 10 minutos
- Mejora automatica de brillo/contraste en fotos oscuras
- Panel de administracion para reordenar, editar y borrar recuerdos

---

## 2. Arquitectura y archivos

Todo el proyecto esta en una sola carpeta. Estructura:

```
web1/
├── servidor.py              ← Archivo principal. TODO el codigo (Flask + HTML/CSS/JS inline)
├── recuerdos.json           ← Base de datos de recuerdos (JSON, ~121 entradas)
├── conexiones.json          ← Log de conexiones de usuarios
├── .clave_sesion            ← Clave secreta de Flask (se genera automaticamente)
├── fotos/                   ← Carpeta con todas las fotos y videos subidos
├── copias_seguridad/        ← Backups automaticos de recuerdos.json (cada 10 min)
├── fotos_web_backup/        ← Backup de fotos originales antes de mejora de brillo
├── INICIAR.bat              ← Script para arrancar el servidor en Windows
├── INSTRUCCIONES_SERVIDOR.txt
├── servidor_BACKUP_antes_rediseno.py   ← Backup del codigo antes del rediseño
└── servidor_BACKUP_antes_collage.py    ← Backup del codigo antes del collage animado
```

**Archivo clave: `servidor.py`** (~930 lineas)

Contiene TODO en un solo archivo Python: el servidor Flask, las rutas, la logica de autenticacion, el HTML completo de la pagina, todo el CSS, todo el JavaScript, el manejo de subida de archivos, los backups, el logging de conexiones.

---

## 3. Requisitos del sistema

### Software necesario:
- **Python 3.8+** (recomendado 3.10+)
- **pip** (gestor de paquetes de Python, viene con Python)

### Librerias Python:
```
Flask
Pillow
```

### Opcional (para acceso remoto):
- **cloudflared** - Cloudflare Tunnel
- Descargar desde: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/

---

## 4. Instalacion paso a paso

### En Windows:

```batch
:: 1. Instalar Python (si no esta instalado)
::    Descargar desde https://www.python.org/downloads/
::    IMPORTANTE: marcar "Add Python to PATH" durante la instalacion

:: 2. Abrir CMD o PowerShell y navegar a la carpeta del proyecto
cd C:\ruta\a\web1

:: 3. Instalar dependencias
pip install flask pillow

:: 4. Verificar que funciona
python servidor.py
```

### En Mac/Linux:

```bash
# 1. Navegar a la carpeta
cd /ruta/a/web1

# 2. Instalar dependencias
pip3 install flask pillow

# 3. Arrancar
python3 servidor.py
```

---

## 5. Configuracion

### Contraseñas (dentro de servidor.py, primeras lineas):

```python
PASSWORD_FAMILIA = "Davicito2017"    # Acceso familia: ver y subir
PASSWORD_ADMIN   = "Davicito2017."   # Acceso admin: editar, borrar, reordenar (con PUNTO al final)
```

### Puerto del servidor:

```python
app.run(host="0.0.0.0", port=5000, debug=False)
```

Por defecto corre en el puerto 5000. Accesible en: http://localhost:5000

### Rutas de archivos (dentro de servidor.py):

```python
BASE = Path(__file__).resolve().parent
FOTOS = BASE / "fotos"
JSON_PATH = BASE / "recuerdos.json"
CONEXIONES_JSON = BASE / "conexiones.json"
BACKUP_DIR = BASE / "copias_seguridad"
```

Todo es relativo a donde esta servidor.py. No hay que configurar rutas absolutas.

---

## 6. Como arrancar el servidor

### Opcion A: Doble clic en INICIAR.bat (Windows)

El archivo INICIAR.bat contiene:
```batch
@echo off
cd /d "%~dp0"
python servidor.py
pause
```

### Opcion B: Desde terminal

```bash
cd /ruta/a/web1
python servidor.py
```

El servidor arranca en http://localhost:5000

### Verificar que funciona:
1. Abrir navegador
2. Ir a http://localhost:5000
3. Deberia pedir contraseña
4. Introducir "Davicito2017" (familia) o "Davicito2017." (admin)
5. Pedir nombre
6. Ver la pagina del memorial

---

## 7. Acceso remoto con Cloudflare Tunnel

### Tunnels rapidos (link cambia cada vez que se reinicia):

```bash
cloudflared tunnel --url http://localhost:5000
```

Genera un enlace tipo `https://algo-random.trycloudflare.com` que se puede compartir con la familia. El enlace cambia cada vez que se reinicia cloudflared.

### Tunnel permanente (requiere cuenta Cloudflare + dominio, no implementado aun):

Pasos:
1. Crear cuenta en Cloudflare
2. Comprar dominio (~9 EUR/año)
3. Crear Named Tunnel con token fijo
4. Configurar DNS
5. Crear COMPARTIR.bat con el token

---

## 8. Funcionalidades implementadas

### 8.1 Sistema de autenticacion
- Dos niveles: familia (ver/subir) y admin (ver/subir/editar/borrar/reordenar)
- Flujo: Contraseña → Nombre → Pagina principal
- Sesion dura 30 dias (cookie persistente)
- Clave de sesion se genera automaticamente y se guarda en `.clave_sesion`

### 8.2 Pagina principal
- Hero con titulo "Para ti, David" y frase rotativa (cambia cada 6 segundos)
- Fondo rotativo con fotos a pantalla completa (cambia cada 8s, blur 10px, brightness 0.35)
- Particulas doradas flotando
- Contador de momentos compartidos
- Collage animado con 5 filas moviéndose a distintas velocidades y direcciones
- Vista detalle: click en foto → vista grande con titulo, historia, autor
- Navegacion tactil (swipe) en movil
- Formulario de subida con titulo, historia, autor y lugar (opcional)

### 8.3 Musica de fondo (YouTube IFrame API)
- 3 canciones en bucle:
  1. Where Are You Now - Alan Walker (kId1v7JDJtY)
  2. A Thousand Years - Christina Perri (B0b9Kqiz_T0)
  3. Never Forget You - Zara Larsson (GTyN-DB_v5M)
- Boton dorado pulsante en esquina inferior derecha
- Desktop: se activa al primer clic en cualquier sitio
- iOS: requiere pulsar el boton directamente (restriccion de Apple)
- Deteccion automatica de iOS con playsinline y reintentos

### 8.4 Subida de archivos
- Fotos: JPG, PNG, WEBP, BMP, TIFF, HEIC
- Videos: MP4, MOV, AVI, MKV, WEBM
- Mejora automatica de brillo/contraste en fotos oscuras (Pillow ImageEnhance)
- Extraccion de fechas EXIF
- Nuevas subidas se insertan al principio

### 8.5 Administracion (solo contraseña admin)
- Flechas arriba/abajo para reordenar fotos
- Editar titulo, historia, autor, fecha, lugar
- Borrar recuerdos (con confirmacion)
- Pagina /admin/conexiones con tabla de quien se ha conectado

### 8.6 Backups automaticos
- Cada 10 minutos se guarda copia de recuerdos.json
- Formato: recuerdos_BACKUP_YYYYMMDD_HHMMSS.json
- Hilo daemon en segundo plano
- Primera copia 30 segundos despues de arrancar

### 8.7 Registro de conexiones
- Registra: nombre, nivel, IP real (Cloudflare headers), fecha/hora, navegador
- Guarda ultimas 500 conexiones
- Escritura atomica (archivo temporal + rename)
- Vista en /admin/conexiones (solo admin)

---

## 9. Endpoints API

| Ruta | Metodo | Descripcion |
|------|--------|-------------|
| `/` | GET | Pagina principal |
| `/login` | GET/POST | Login (contraseña + nombre) |
| `/api/recuerdos` | GET | Lista todos los recuerdos (JSON) |
| `/api/subir` | POST | Subir foto/video con datos |
| `/api/editar/<id>` | POST | Editar un recuerdo (admin) |
| `/api/borrar/<id>` | POST | Borrar un recuerdo (admin) |
| `/api/mover/<id>` | POST | Mover recuerdo arriba/abajo (admin) |
| `/fotos/<archivo>` | GET | Servir foto/video |
| `/admin/conexiones` | GET | Ver log de conexiones (admin) |

---

## 10. Estructura del codigo (servidor.py)

Organizado aproximadamente asi:

```
Lineas 1-30:      Imports, configuracion (passwords, rutas, Flask app)
Lineas 30-60:     Clave de sesion, configuracion de sesion permanente
Lineas 60-100:    Funciones auxiliares (cargar/guardar JSON, es_admin_local, registrar_conexion)
Lineas 100-130:   Decorador @requiere_login (functools.wraps)
Lineas 130-160:   Hilo de backup automatico (threading.Thread, daemon=True)
Lineas 160-200:   HTML del login (LOGIN_CSS, LOGIN_PASS_HTML, LOGIN_NAME_HTML)
Lineas 200-560:   PAGINA principal completa (HTML + CSS)
Lineas 560-930:   JavaScript completo (collage, detalle, swipe, musica YouTube, admin, subida)
Lineas 930+:      Rutas Flask (@app.route)
```

### Patrones clave del codigo:

**Escritura atomica** (evita corrupcion de datos):
```python
tmp = JSON_PATH.with_suffix(".json.tmp")
tmp.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
tmp.replace(JSON_PATH)
```

**Decorador de login**:
```python
def requiere_login(f):
    @wraps(f)
    def wrap(*a, **kw):
        if not session.get("nivel"):
            if request.path.startswith("/api/"):
                return "login requerido", 401
            return redirect(url_for("login"))
        return f(*a, **kw)
    return wrap
```

**Deteccion admin**:
```python
def es_admin_local():
    if session.get("nivel") == "admin":
        return True
    remoto = request.remote_addr or ""
    via_tunnel = request.headers.get("Cf-Connecting-Ip") or request.headers.get("X-Forwarded-For")
    if via_tunnel:
        return False
    return remoto in ("127.0.0.1", "::1", "localhost")
```

### Formato de recuerdos.json:
```json
[
  {
    "id": 1,
    "archivo": "foto_abc123.jpg",
    "archivo_original": "IMG_20230415.jpg",
    "titulo": "En el parque",
    "historia": "Un dia precioso jugando...",
    "autor": "Papa",
    "fecha": "2023-04-15",
    "lugar": "Madrid",
    "subido_en": "2025-04-28 15:30:00"
  }
]
```

---

## 11. Tareas pendientes / futuras

- **Mapa de recuerdos**: Campo "lugar" ya existe. Idea: pagina /mapa con OpenStreetMap. Necesita fotos con ubicacion.
- **Dominio permanente**: Comprar dominio en Cloudflare (~9 EUR/año) + Named Tunnel con token fijo.
- **Libro de fotos para abogado/juez**: Generar PDF con fotos y recuerdos. Esperar a que la familia termine de subir.

---

## 12. Solucion de problemas

**"No puedo acceder desde el movil"**: Verificar servidor corriendo + cloudflared activo. El link de trycloudflare cambia al reiniciar.

**"La musica no suena en iPhone/iPad"**: En iOS hay que pulsar el boton dorado directamente. Apple no permite reproduccion automatica.

**"Las fotos se ven cortadas"**: Limpiar cache del navegador (Ctrl+Shift+R). Las fotos usan object-fit: contain.

**"Se ha perdido recuerdos.json"**: Ir a copias_seguridad/ y copiar el backup mas reciente. Renombrar a recuerdos.json.

**"Error al arrancar: ModuleNotFoundError"**: Ejecutar `pip install flask pillow`

**"Error de puerto en uso"**: Cambiar el puerto en la ultima linea de servidor.py o cerrar lo que use el puerto 5000.

---

*Documento generado el 1 de mayo de 2026*
*Proyecto: Memorial Digital David Gonzalez Suazo*
