# AI Feeds

Plugin de WordPress para automatizar la ingesta, reescritura y publicación de noticias usando fuentes RSS, reglas editoriales y servicios de IA externos. El código está organizado para que puedas seguir todo el flujo: desde descubrir fuentes en la biblioteca de Cibeles.net hasta importar elementos concretos, procesarlos por lotes mediante la REST API y terminar con entradas publicadas con metadatos, SEO y campos personalizados.

## Arquitectura general
- **Bootstrap (`ai-feeds.php`)**: define constantes, carga el dominio de traducción y registra todos los módulos que viven en `includes/`. También activa un aviso (opcional) cuando la REST API de WordPress no está disponible porque el plugin depende de ella para cada procesamiento.
- **CPT doble**: `ai_feed` representa las fuentes guardadas por el usuario, mientras que `aife_original` actúa como cola/almacén de noticias sin procesar. Ambos se registran en `includes/cpt.php` y se fuerzan a estados concretos para simplificar la lógica del pipeline.
- **Flujo de datos externo**: `includes/class-ai-feeds-model.php` consulta la biblioteca pública de Cibeles.net, descubre subfeeds y lee artículos mediante SimplePie. Una vez seleccionada una noticia, `includes/endpoints.php` envía su contenido a `openai.editmaker.com` para generar partes específicas (categorías, titular, imagen, SEO, etc.), o delega en helpers locales para autor e imagen.
- **Persistencia y herencia de ajustes**: `includes/views.php` renderiza el formulario reutilizable de ajustes, `includes/save-settings.php` guarda las opciones globales (incluida la API de OpenAI) y `includes/save-feed-settings.php` aplica overrides por feed con un interruptor de herencia activable desde la lista de CPT y vía AJAX (`aife_toggle_herencia`).
- **Procesamiento en cola**: `includes/save-importar.php` inserta borradores en `aife_original`; `views/cola-trabajo.php` + `assets/js/procesador-noticia.js` consumen esos borradores llamando a los endpoints en secuencia y `includes/import-finished.php` crea el post final, asigna Yoast SEO y marca la noticia como procesada.

## Estructura de archivos y responsabilidades
- `ai-feeds.php`: cargador principal y registro de includes.
- `includes/functions.php`: utilidades compartidas (shortcode `[aife_post_meta]`, normalización de URLs, comprobación REST, helpers de metadatos, etc.).
- `includes/admin-menu.php`: crea el menú "AI Feeds" y todos los submenús (Biblioteca, Cola de trabajo, Ajustes, Historia, acciones contextuales del CPT). Cada página carga su vista correspondiente en `views/`.
- `includes/class-ai-feeds-model.php`: integra con la biblioteca de Cibeles.net, descarta duplicados, obtiene subfeeds y lee artículos con SimplePie. También mapea cada item RSS a un objeto `noticia` homogenizado.
- `includes/class-format-helper.php`: sanea HTML entrante eliminando atributos peligrosos, scripts o estilos antes de guardar el contenido original en la cola.
- `includes/enqueue.php`: encola CSS/JS específicos por página (Select2 para ajustes, scripts de biblioteca, importador y cola) y expone nonces/datos al front-end mediante `wp_localize_script`.
- `includes/cpt.php`, `includes/metaboxes.php`: definen los CPT, metaboxes de URL, columnas personalizadas y los campos de configuración heredable que se muestran en la lista de fuentes o en los posts finales.
- `includes/ajax.php`: endpoints AJAX autenticados para agregar feeds desde la biblioteca y activar/desactivar la herencia de ajustes.
- `includes/views.php`: formulario centralizado que comparte lógica entre la configuración global y la específica por feed, con secciones para OpenAI, categorías, autor, prompts, AutoSEO, campos personalizados y extras como FAQ o cronología.
- `includes/save-settings.php`, `includes/save-feed-settings.php`, `includes/save-importar.php`, `includes/import-finished.php`: controladores `admin_post` y REST que guardan ajustes, importan noticias y generan la entrada final.
- `includes/endpoints.php`: registra `ai-feeds/v1/procesar` y `/check-tags`, orquesta las llamadas a Editmaker y maneja casos especiales como autor/imágenes sin pasar por la API externa. También aplica procesadores locales (eliminar enlaces o añadir `rel="nofollow"`).
- `includes/ai-feeds-historial.php`: añade la vista de historial y la columna "AI Feed Imported" en el listado de posts para trazar qué entradas vienen del plugin, además de forzar filtros/meta queries cuando se navega por `aife_historial=1`.
- `views/`: plantillas PHP para cada pantalla administrativa (dashboard, biblioteca, cola, ajustes, ajustes por feed e importador) con markup adaptado a los scripts descritos arriba.
- `assets/css` y `assets/js`: estilos y scripts de comportamiento. Destacan `ai-feeds.js` (toggles de herencia), `biblioteca.js` (carga de subfeeds y filtros), `importador.js` (UI de selección masiva), `procesador-noticia.js` (pipeline REST) y `ajustes.js` (validaciones, Select2, herencia visual).
- `languages/`: `.po/.mo` con traducciones para múltiples locales; el dominio `ai-feeds` se carga en `plugins_loaded`.
- `actualizador_git.php`: script autónomo para espejar repos privados de GitHub en servidores sin Git, conservando ficheros señalados.

## Clases y helpers
### `aife_Model`
- Gestiona todas las lecturas externas: obtiene feeds y tags desde `https://cibeles.net/get_feeds.php`, descubre subfeeds (añadiendo `feed/?subfeeds=true`) y parsea cualquier RSS con SimplePie, intentando resolver URLs canónicas y detectar feeds embebidos en HTML si es necesario.
- `set_noticia_from_item()` homologa cada item a un objeto único con campos (`title`, `description`, `content`, `categories`, `original_url`, etc.) listo para guardarse en la cola, limpiando el HTML mediante `aife_Format_Helper`.

### `aife_Format_Helper`
- Repara HTML malformado con DOMDocument, elimina atributos peligrosos, hojas de estilo, scripts y botones para garantizar que el contenido importado no rompa el editor ni introduce código ajeno.

## Funciones, shortcodes y ganchos destacados
- `aife_get_subfeeds_callback`, `aife_agregar_feed_callback`: exponen AJAX seguros (nonce + `manage_options`) para descubrir subfeeds y crear entradas `ai_feed` sin recargar la página de biblioteca.
- `aife_normalize_feed_url`, `aife_normalizar_url`: normalizan URLs para evitar duplicados o errores al comparar GUID/links durante la importación.
- `aife_meta_key_existe` + `aife_registrar_meta_keys_dinamicamente`: permiten registrar campos personalizados dinámicos (antetítulo, FAQ, cifras, etc.) y exponerlos vía REST si el usuario los activa en ajustes. El shortcode `[aife_post_meta key="nombre"]` sirve para imprimirlos en plantillas o builders.
- `aife_comprobar_api_rest_activa`: cada script recibe en `aiFeeds.restEnabled` si la REST API está activa; el procesador detiene la cola con una alerta si no lo está.
- `aife_get_config_feed_y_general_from_aife_original_id` + `aife_obtenerConfig`: resuelven la configuración efectiva de un post original combinando meta del feed y ajustes globales cuando la herencia está activa, lo cual gobierna decisiones como eliminar enlaces, aplicar `nofollow` o generar AutoSEO.
- `aife_procesar_endpoint`: punto de entrada REST que enruta a OpenAI/Editmaker, añade datos extra (categorías disponibles, usuario actual) y sanea respuestas. Subendpoints `autor`, `imagen` e `importacion` se resuelven localmente para reducir llamadas externas.
- `aife_procesar_importacion`, `aife_procesar_importacion_post_final`: convierten selecciones en `aife_original`, guardan toda la metainformación y, una vez procesadas las respuestas IA, crean la entrada final con categorías, tags (existentes + fijos), imágenes subidas a la librería y campos Yoast. Además, marcan la noticia de la cola como `_procesado_en_cola` para no repetirla.
- `aife_filtrar_historial_admin` y filtros asociados: permiten navegar por `/wp-admin/edit.php?post_type=post&aife_historial=1` para ver solo publicaciones originadas por AI Feeds, con columnas que enlazan al feed original o a la URL de origen.

## Vistas, scripts e interfaz
- **Biblioteca** (`views/biblioteca.php` + `assets/js/biblioteca.js`): lista las fuentes públicas de Cibeles.net (ordenadas, con tags, subfeeds dinámicos y botones "Agregar"). Incluye filtros por etiquetas con UI plegable, indicaciones de feeds ya importados (desactivados) y llamadas AJAX que obtienen subfeeds y guardan feeds seleccionados.
- **Importador** (`views/importar.php` + `assets/js/importador.js`): muestra las noticias del feed seleccionado, permitiendo marcar cuáles enviar a la cola. El formulario usa un nonce específico por feed y el script permite seleccionar/deseleccionar en bloque, resaltando las tarjetas activadas.
- **Cola de trabajo** (`views/cola-trabajo.php` + `assets/js/procesador-noticia.js`): representa la primera noticia pendiente y un panel de resultados donde cada paso (categorías, titular, resumen, autor, imagen, tags, cifras, FAQ, cronología, AutoSEO) se pinta conforme llega la respuesta REST. El botón principal inicia/detiene la cola, muestra una cuenta atrás para continuar automáticamente y refresca cuando hay más entradas en espera.
- **Ajustes** (`views/ajustes.php`, `views/feed-ajustes.php`, `assets/js/ajustes.js`): el mismo formulario sirve tanto para ajustes globales como para overrides por feed. Incluye conexión OpenAI (Cibeles o API propia), selección de categoría automática/manual, autor firmante, estilo del refrito, estado del post, campos personalizados, prompts por sección, AutoSEO y extras (cifras, FAQ, cronología, tags fijos, texto de fuente). El JS aplica Select2, validaciones (p.ej., exigir categoría cuando no se usa IA), sincroniza herencias y bloquea opciones incompatibles (p.ej., `nofollow` queda desactivado si se eliminan enlaces).
- **Historial**: se accede desde el submenú "History" que abre el listado de posts filtrado; estilos extra (`assets/css/ai-feeds-historial.css`) remarcan columnas nuevas.
- **Dashboard genérico** (`views/dashboard.php`) sirve como placeholder.

## Flujo lógico del usuario
1. **Explorar y guardar fuentes**: desde "Source Library" el usuario filtra por tags, despliega subfeeds y añade aquellos que quiera seguir. Los feeds se guardan como `ai_feed` con su URL y nombre.
2. **Configurar reglas**: en "Settings" define opciones globales; desde la lista de "Mis fuentes" puede abrir "Feed Settings" para overrides o activar la herencia con el switch que expone `ai-feeds.js`.
3. **Importar noticias**: al pulsar "Importar ahora" en el listado de feeds se abre `views/importar.php`, se seleccionan entradas y se envían a la cola (`aife_original`).
4. **Procesar la cola**: en "Job Queue" se lanza el pipeline REST. Cada borrador genera respuestas IA que se muestran en vivo; al terminar se crea un post de WordPress con campos personalizados, imágenes subidas y metas Yoast, se marca `_procesado_en_cola` y se programa el siguiente elemento con una cuenta atrás.
5. **Revisar historial**: el submenú "History" abre el listado filtrado donde se pueden ver los posts finales, su feed de origen y la URL original gracias a los metadatos guardados durante la importación.

## Detalles de la interfaz
- **Switch de herencia en `ai_feed`**: cada fila muestra un toggle que llama a `aife_toggle_herencia` y deshabilita el botón de ajustes cuando hereda la configuración general, evitando overrides accidentales.
- **Filtros visuales en la biblioteca**: los tags actúan como toggles, muestran un contador de filtros activos y ofrecen un botón para limpiar todos. Las filas importadas se atenúan y sustituyen el botón por "✅ Ya importado" automáticamente.
- **Importador**: cada tarjeta contiene título, fecha, categorías, descripción, contenido y enlace original. Las seleccionadas cambian de estilo (`.activada`) y solo los enlaces marcados mantienen su campo oculto `enlaces[]` cuando se envía el formulario.
- **Cola**: el panel derecho muestra placeholders que se desvanecen con animaciones `fade-in`. El log incluye spinners, mensajes por etapa, advertencias cuando un generador está desactivado (p.ej., autor no configurado) y enlaces directos para previsualizar/editar el post final una vez creado.

## Endpoints REST, AJAX y seguridad
- `ai-feeds/v1/procesar`: único endpoint REST para procesar cada etapa (`endpoint` en el cuerpo JSON). Requiere `edit_posts`, nonce `wp_rest`, valida `post_id` y añade metadatos antes de enviar a Editmaker. El subendpoint `importacion` crea la entrada final y marca la noticia original como procesada.
- `ai-feeds/v1/check-tags`: recibe un array de tags y devuelve solo los ya existentes en WordPress para mezclarlos con los generados y los tags fijos definidos por el usuario.
- AJAX administrativos (requieren `manage_options` + nonce): `aife_get_subfeeds`, `aife_agregar_feed`, `aife_toggle_herencia`. Todos responden en JSON y se consumen desde la biblioteca o la lista de feeds.
- `admin_post` handlers: `aife_guardar_ajustes`, `aife_guardar_feed_ajustes`, `aife_procesar_importacion` validan nonces propios, capacidades y procedencia de datos antes de escribir en la base de datos.
- Helpers de seguridad: `aife_comprobar_api_rest_activa` (para bloquear interfaz si la REST API está caída) y `aife_eliminar_imagen_destacada_del_refrito` (evita duplicar la imagen principal en el contenido).

## Ejemplo de uso
1. Entra a **Source Library**, filtra por una etiqueta y pulsa "➕ Agregar" para guardar un feed en "Mis fuentes". La acción dispara `aife_agregar_feed` y crea un CPT `ai_feed` con la URL y título proporcionados.
2. Abre "Feed Settings" para esa fuente, define overrides (por ejemplo, estado "Pendiente" y un prompt personalizado para titular) y guarda. El formulario envía los datos a `aife_guardar_feed_ajustes`, que persiste cada meta y marca qué campos deben heredar la configuración general.
3. Desde la lista de "Mis fuentes", pulsa "Importar ahora", selecciona tres noticias y envíalas. `aife_procesar_importacion` insertará tres `aife_original` con los metadatos necesarios, listos para procesarse desde la cola.
4. En "Job Queue", pulsa "Iniciar cola": `procesador-noticia.js` recorrerá los endpoints (categorías, textos, imagen, tags, AutoSEO). Cuando termina, `aife_procesar_importacion_post_final` crea los posts finales (con Yoast, campos personalizados, imágenes subidas y tags). El panel mostrará enlaces de previsualización/edición y, tras la cuenta atrás, continuará con la siguiente noticia si existen más en la cola.

## Consideraciones para nuevos desarrolladores
- **REST API obligatoria**: el plugin aborta si `/wp-json` no responde con 200. Revisa `aife_comprobar_api_rest_activa()` si trabajas en entornos donde la API esté limitada.
- **Dependencia de servicios externos**: los feeds provienen de Cibeles.net y la generación de contenido pasa por `openai.editmaker.com`. Asegúrate de que tu entorno pueda resolver IPv4 (se fuerza vía `http_api_curl`) y tenga acceso saliente HTTPS.
- **Campos personalizados dinámicos**: cualquier meta registrado desde ajustes se expone vía REST y en el metabox de posts. Si añades nuevos campos que deban aceptar HTML, inclúyelos en `aife_html_fields()` y en la lista de saneado. El shortcode `[aife_post_meta key="campo"]` facilita imprimirlos en plantillas.
- **Cola protegida**: `aife_original` siempre permanece en `draft`, no puede restaurarse desde la papelera y se filtra por `_procesado_en_cola`. No cambies este comportamiento a menos que adaptes el pipeline completo.
- **Select2 y assets**: los scripts dependen de Select2 y estilos específicos; si añades vistas nuevas, encola recursos desde `includes/enqueue.php` siguiendo los patrones existentes.
- **Actualizaciones sin Git**: el repositorio incluye `actualizador_git.php` para desplegar mirrors desde GitHub cuando el servidor no tiene acceso a Git. Trátalo como una herramienta de mantenimiento (requiere token personal).

Con esta guía puedes navegar el código, comprender qué hace cada módulo y extenderlo sin romper el flujo completo de importación, procesamiento y publicación.
