# Sistema de Generación Automática de Noticias Diarias

## Descripción General

Este sistema automatiza la generación de 5 posts diarios sobre finanzas en México para el sitio web **Pesos y Centavos**. El proceso combina tres servicios principales:

1. **NewsAPI**: Obtiene noticias recientes sobre finanzas en México
2. **OpenAI**: Genera contenido original basado en las noticias obtenidas
3. **WordPress REST API**: Publica los posts como borradores en WordPress

## Arquitectura del Sistema

### Componentes Principales

#### 1. `WordPressService` (`app/Services/WordPressService.php`)
- **Responsabilidad**: Interactuar con WordPress REST API
- **Funcionalidades**:
  - Crear posts como borradores
  - Obtener IDs de categorías
  - Crear/obtener IDs de tags
  - Autenticación con Application Password

#### 2. `DailyNewsService` (`app/Services/DailyNewsService.php`)
- **Responsabilidad**: Orquestar todo el flujo de generación
- **Proceso**:
  1. Obtiene noticias de NewsAPI (finanzas, México, español)
  2. Transforma el payload a formato reducido (40-50 artículos)
  3. Construye el prompt para OpenAI
  4. Genera 5 noticias con OpenAI
  5. Valida y parsea la respuesta JSON
  6. Publica cada noticia en WordPress como borrador

#### 3. `GenerateDailyNews` (`app/Console/Commands/GenerateDailyNews.php`)
- **Responsabilidad**: Comando Artisan para ejecutar el proceso
- **Uso**: `php artisan news:generate-daily`
- **Opciones**:
  - `--dry-run`: Ejecutar sin publicar a WordPress
  - `--force`: Forzar ejecución incluso si ya se ejecutó hoy

#### 4. Scheduler (`routes/console.php`)
- **Responsabilidad**: Ejecutar el comando automáticamente
- **Configuración**: Diario a la 1:00 AM (zona horaria America/Mexico_City)

## Flujo de Ejecución

```mermaid
flowchart TD
    A[Scheduler: 1:00 AM] --> B[Comando: news:generate-daily]
    B --> C[DailyNewsService]
    C --> D[NewsApiService: getEverything]
    D --> E[Transformar JSON: 40-50 artículos]
    E --> F[Construir Prompt OpenAI]
    F --> G[OpenAIService: createResponse]
    G --> H[Validar y Parsear JSON]
    H --> I{¿5 noticias válidas?}
    I -->|No| J[Intentar con gpt-4o]
    J --> H
    I -->|Sí| K[Para cada noticia N1-N5]
    K --> L[WordPressService: createPost]
    L --> M[Post creado como borrador]
    M --> N[Log de resultados]
```

## Configuración

### Variables de Entorno

Agregar al archivo `.env`:

```env
# WordPress Configuration
WORDPRESS_URL=https://tu-sitio-wordpress.com
WORDPRESS_USERNAME=usuario-wordpress
WORDPRESS_APP_PASSWORD=gDV9 mRw0 4SDN YxXi VsF1 b0Sj

# NewsAPI (ya configurado)
NEWSAPI_KEY=tu-api-key

# OpenAI (ya configurado)
OPENAI_API_KEY=tu-api-key
```

### Configuración de WordPress

1. **Crear Application Password en WordPress**:
   - Ir a: Usuarios > Tu Perfil > Application Passwords
   - Crear una nueva contraseña de aplicación
   - Copiar la contraseña generada (formato: `xxxx xxxx xxxx xxxx xxxx xxxx`)
   - Agregarla a `WORDPRESS_APP_PASSWORD` en el `.env`

2. **Verificar URL de WordPress**:
   - La URL debe ser la base de tu sitio WordPress (ej: `https://pesosycentavos.com`)
   - No incluir `/wp-json` al final

3. **Categorías en WordPress**:
   - El sistema intentará mapear las categorías automáticamente
   - Si una categoría no existe, el post se creará sin categoría
   - Categorías soportadas: Inflación, Ahorro, Crédito, Impuestos, Consumo, Mercados, Tecnología financiera, Canasta básica, Empleo, Vivienda, Seguros, Fraudes

## Cómo Funciona

### 1. Obtención de Noticias (NewsAPI)

El sistema busca noticias con los siguientes criterios:
- **Query**: "finanzas OR economía OR dinero OR banco OR crédito OR ahorro OR inversión OR inflación"
- **Idioma**: Español (`es`)
- **Fecha**: Últimas 24 horas
- **Orden**: Por fecha de publicación (más recientes primero)
- **Límite**: Hasta 100 artículos (se reducen a 40-50)

### 2. Transformación de Datos

De cada artículo de NewsAPI se extrae solo:
- `source.name`: Nombre de la fuente
- `title`: Título del artículo
- `description`: Descripción
- `content`: Contenido (si está disponible)
- `url`: URL del artículo original
- `publishedAt`: Fecha de publicación

### 3. Generación con OpenAI

El sistema construye un prompt detallado que incluye:

**System Prompt**:
- Define el rol: redactor profesional de finanzas personales
- Establece reglas críticas (no inventar datos, reescribir contenido, etc.)
- Especifica el tono: periodístico, didáctico, claro

**User Prompt**:
- Fecha objetivo
- Instrucciones editoriales detalladas
- Estructura requerida para cada noticia
- Formato JSON exacto esperado
- Contexto completo de noticias de NewsAPI

**Modelos utilizados**:
- Primero intenta con `gpt-4o-mini` (más económico)
- Si falla, intenta con `gpt-4o` (más potente)

### 4. Validación de Contenido

El sistema valida que:
- La respuesta sea JSON válido
- Contenga exactamente 5 noticias
- Cada noticia tenga los campos requeridos
- Los IDs sean N1, N2, N3, N4, N5
- Cada noticia tenga al menos 1 fuente

### 5. Publicación en WordPress

Para cada noticia generada:
1. Se buscan/crean las categorías en WordPress
2. Se buscan/crean los tags en WordPress
3. Se construye el contenido HTML del post
4. Se crea el post como **borrador** (status: `draft`)
5. Se registra el resultado en los logs

## Estructura de una Noticia Generada

Cada noticia generada contiene:

```json
{
  "id": "N1",
  "title": "Título de la noticia",
  "subtitle": "Bajada o subtítulo",
  "slug": "slug-seo-friendly",
  "meta_title": "Meta título para SEO (máx 60 caracteres)",
  "meta_description": "Meta descripción para SEO (máx 155 caracteres)",
  "category": "Inflación",
  "tags": ["tag1", "tag2", "tag3"],
  "reading_time_minutes": 5,
  "key_points": [
    "Punto clave 1",
    "Punto clave 2"
  ],
  "body_markdown": "Contenido completo en Markdown (~1000 palabras)",
  "pocket_impact": "Explicación de qué significa para el bolsillo",
  "disclaimer": "Esto no es asesoría financiera.",
  "sources": [
    {
      "publisher": "Nombre del medio",
      "title": "Título original",
      "url": "https://...",
      "published_at": "2024-01-20"
    }
  ]
}
```

## Uso del Sistema

### Ejecución Manual

Para ejecutar el proceso manualmente:

```bash
php artisan news:generate-daily
```

**Opciones disponibles**:

```bash
# Ejecutar sin publicar a WordPress (solo generar contenido)
php artisan news:generate-daily --dry-run

# Forzar ejecución (útil para pruebas)
php artisan news:generate-daily --force
```

### Ejecución Automática

El sistema está configurado para ejecutarse automáticamente todos los días a la **1:00 AM** (zona horaria America/Mexico_City).

**Importante**: Para que el scheduler funcione, necesitas configurar un cron job en el servidor:

```bash
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
```

### Verificar el Scheduler

Para ver las tareas programadas:

```bash
php artisan schedule:list
```

## Monitoreo y Logs

### Logs del Sistema

Todos los eventos se registran en `storage/logs/laravel.log`:

- Inicio del proceso
- Noticias obtenidas de NewsAPI
- Transformación de datos
- Generación con OpenAI
- Validación de contenido
- Publicación en WordPress
- Errores y excepciones

### Ver Logs en Tiempo Real

```bash
php artisan pail
```

O usar:

```bash
tail -f storage/logs/laravel.log
```

## Solución de Problemas

### Error: "OpenAI API key is not configured"
- Verificar que `OPENAI_API_KEY` esté en el `.env`
- Ejecutar `php artisan config:clear` después de modificar `.env`

### Error: "NewsAPI key is not configured"
- Verificar que `NEWSAPI_KEY` esté en el `.env`
- Ejecutar `php artisan config:clear`

### Error: "WordPress configuration is incomplete"
- Verificar que `WORDPRESS_URL`, `WORDPRESS_USERNAME` y `WORDPRESS_APP_PASSWORD` estén en el `.env`
- Verificar que la Application Password sea correcta (formato con espacios)

### Error: "Insufficient news articles"
- NewsAPI puede no tener suficientes noticias del día
- El sistema requiere al menos 10 artículos válidos
- Verificar que la búsqueda en NewsAPI esté funcionando

### Error: "Failed to generate valid news content"
- OpenAI puede no estar retornando JSON válido
- Verificar los logs para ver la respuesta de OpenAI
- El sistema intenta con `gpt-4o-mini` primero, luego con `gpt-4o`

### Posts no se publican en WordPress
- Verificar que la URL de WordPress sea correcta
- Verificar que la Application Password sea válida
- Verificar que el usuario tenga permisos para crear posts
- Revisar los logs para ver errores específicos de la API

### El scheduler no se ejecuta
- Verificar que el cron job esté configurado
- Verificar que `php artisan schedule:run` funcione manualmente
- Verificar la zona horaria del servidor

## Mejores Prácticas

1. **Revisar los borradores**: Siempre revisa los posts generados antes de publicarlos
2. **Monitorear logs**: Revisa los logs regularmente para detectar problemas
3. **Probar manualmente**: Ejecuta el comando manualmente antes de confiar en el scheduler
4. **Backup de WordPress**: Mantén backups regulares de WordPress
5. **Validar contenido**: Revisa que el contenido generado sea apropiado y preciso

## Limitaciones y Consideraciones

1. **NewsAPI Free Tier**: Tiene límites de requests por día
2. **OpenAI Costs**: El uso de OpenAI genera costos según el modelo y tokens
3. **WordPress API**: Depende de la disponibilidad de la API de WordPress
4. **Contenido Generado**: El contenido es generado por IA y debe ser revisado
5. **Fuentes**: Las noticias dependen de la disponibilidad en NewsAPI

## Personalización

### Modificar el Prompt de OpenAI

Editar el método `getSystemPrompt()` y `getUserPrompt()` en `app/Services/DailyNewsService.php`.

### Cambiar la Hora de Ejecución

Editar `routes/console.php` y modificar:

```php
Schedule::command('news:generate-daily')
    ->dailyAt('02:00') // Cambiar la hora
    ->timezone('America/Mexico_City')
```

### Modificar Categorías

Editar `config/wordpress.php` y modificar el array `category_mapping`.

### Cambiar el Modelo de OpenAI

Editar `app/Services/DailyNewsService.php` en el método `generateNewsWithAI()` y cambiar el modelo inicial.

## Soporte

Para problemas o preguntas:
1. Revisar los logs en `storage/logs/laravel.log`
2. Ejecutar el comando con `--dry-run` para pruebas
3. Verificar la configuración en `.env`
4. Consultar la documentación de las APIs:
   - [NewsAPI Docs](https://newsapi.org/docs)
   - [OpenAI API Docs](https://platform.openai.com/docs)
   - [WordPress REST API Docs](https://developer.wordpress.org/rest-api/)

---

**Última actualización**: Enero 2025
