|
Equipo — The Good App
Mail 12 — Continuación del Mail 11 (noticias sindicadas automáticas)
|
|
Hola equipo,
Este correo continúa la línea del Mail 11 (plan-frontend/maileleven.html). En este ciclo implementamos la importación diaria de noticias positivas desde portales de prensa de Estados Unidos: texto e imagen principal, con enlace y atribución al origen, visibles en la app como cualquier noticia publicada por usuarios.
|
Resumen de cambios (API + Admin + Flutter)
- API (good-app): modelo
NewsPortal; campos en News (isSyndicated, sourceUrl, sourceAttribution, etc.); módulo syndication con RSS (rss-parser), scraping por portal (cheerio + JSON de selectores) e imágenes recortadas en servidor (sharp: cabecera 534×300, tarjeta 374×374, mismas medidas que la app sin CDN).
- Endpoints:
POST /api/v1/syndication/run-if-needed (JWT, dispara importación si hoy aún no corrió) y GET /api/v1/syndication/status.
- Admin (admin-goodapp): menú Portales de noticias (CRUD + JSON de scraping editable); menú Noticias importadas (editar / eliminar / crear manual); pestaña Sindicación en Configuración (activar, permitir sin imagen, ver última ejecución, resetear bandera diaria).
- Flutter (flutter-good): al entrar en la app (shell), llamada en segundo plano a
run-if-needed; en detalle de noticia, bloque Leer en la fuente con URL externa si la noticia es importada.
- Seed / migración: 4 portales US por defecto (Good News Network, Sunny Skyz, InspireMore, The Optimist Daily), categoría
positive-news, usuario sistema [email protected].
|
Cómo funciona la importación diaria
- Disparo: el primer usuario que abre la app en el día (con sesión válida) ejecuta la importación una sola vez; los siguientes reciben
ran: false sin volver a jalar.
- Límite: hasta 10 noticias por portal habilitado por ejecución (
maxItemsPerRun, editable en admin por portal).
- Bandera diaria: clave
news_syndication_last_run_date en Setting (fecha UTC YYYY-MM-DD). En admin: botón para borrarla y forzar un nuevo pull el mismo día.
- Concurrencia: lock transaccional (
SELECT … FOR UPDATE) para que varios usuarios entrando a la vez no dupliquen el trabajo.
- Deduplicación: no se reimporta la misma
sourceUrl ni el mismo guid RSS por portal.
- Tono positivo: portales curados + lista
blockedTitleKeywords en el JSON de cada portal (p. ej. murder, shooting).
|
Configuración de scraping por portal (admin)
Cada portal guarda un JSON en scrapeConfig (editable en el panel). Esquema unificado:
mode: rss_and_scrape (recomendado) o rss_only.
article.contentSelector, excerptSelector, imageSelector (+ atributos para meta og:*) — equivalente a indicar en admin dónde está el cuerpo, el resumen y la imagen en el HTML del artículo.
filters.blockedTitleKeywords: palabras que descartan el ítem si aparecen en título o excerpt.
Los 4 portales precargados ya traen un JSON de ejemplo; se puede ajustar RSS URL y selectores sin tocar código.
|
Experiencia en la app
- Las noticias importadas aparecen en Home / Near como
published, con las mismas imágenes base64 (cabecera + tarjeta).
- Al abrir el detalle, el usuario ve el texto completo importado y, al final, el enlace Leer en {fuente} que abre el artículo original en el portal.
- Campos API nuevos en el JSON de noticia:
isSyndicated, sourceUrl, sourceAttribution.
|
Despliegue en staging / producción
- API:
npx prisma migrate deploy (migración 20260515120000_news_syndication) y npm run prisma:seed (portales + settings + usuario sistema).
- Admin:
php artisan migrate (tablas/columnas espejo si aplica).
- Probar: en admin → Configuración → Sindicación → Resetear bandera diaria; abrir la app con un usuario logueado; revisar noticias en feed y menú Noticias importadas.
- Revisar stats: tras la corrida,
news_syndication_last_run_stats guarda importados, omitidos y errores por portal.
Archivo: good-app/plan-frontend/mailtwelve.html. Enlace en plan-frontend/index.html.
|
|
Saludos,
|
Correo interno — avance técnico (Mail 12)
|