📱 Carrusel diario (Content Daily V2)
Archivo: /Users/user/rifai-agents/agentes/content/content-daily-v2.ts · Plist: com.rifai.content-daily · Horario: todos los días a las 13:00 (Europe/Madrid, StartCalendarInterval Hour=13 Min=0)
> El plist com.rifai.content-daily ejecuta este V2 (no la versión vieja content-daily.ts).
Qué hace
Publica cada día un carrusel temático de 6 slides en la Página de Facebook (como álbum) y, si está vinculada, en Instagram Business (como carrusel). El tema rota según el día de la semana (lunes mantenimiento, martes comparativas, miércoles normativa DGT, jueves tips urbanos, viernes tecnología auto, sábado OFERTA de producto, domingo inspiración). Cada slide lleva un fondo lifestyle generado con fal.ai y texto overlay incrustado con Sharp. El sábado promociona un producto top del catálogo Shopify; el último slide (CTA) usa siempre una foto real de producto. Incluye A/B testing de caption (variante A/B al 50%) y registra resultados en SQLite.
Cómo funciona
1. Carga .env, calcula el día de Madrid y elige el tema (o FORCE_TEMA si se pasa).
2. Si el tema es oferta, descarga un producto rotativo de TOP_PRODUCT_IDS vía REST Shopify.
3. Inyecta contexto del Brain (getCorporateIdentity('content') + captions ganadores similares) en el system prompt.
4. Llama al binario local gemini-cli (modelo sonnet) para generar un JSON con caption_completa + 6 slides (texto + fondo_prompt en inglés).
5. A/B: en el 50% de los casos genera una caption variante B con ángulo emocional distinto.
6. Genera las 6 imágenes en paralelo con fal.ai (flux/schnell, square_hd), añadiendo KICK_SCOOTER_SUFFIX para forzar patinete de pie y evitar motos. El último slide usa la foto real del producto Shopify.
7. Compone cada slide con Sharp (caja oscura + texto blanco con borde) y las sube a fal storage para obtener URL pública.
8. Publica álbum en FB (/photos unpublished → /feed con attached_media); detecta IG Business y publica carrusel (containers → CAROUSEL → media_publish).
9. Guarda histórico en data/content-daily-state.json, registra en SQLite (recordSocialPost) y notifica vía router (social_post_published).
Datos/APIs
- Shopify Admin REST (
/admin/api/2024-10): productos de oferta y foto real CTA. Vars:SHOPIFY_STORE,SHOPIFY_ACCESS_TOKEN. - fal.ai (
flux/schnell+ storage): generación y hosting de imágenes. Var:FAL_API_KEY. - Meta Graph API v21.0: FB Page album + IG carousel. Vars:
META_PAGE_ID(default 112610281241802),META_PAGE_TOKENoMETA_ACCESS_TOKEN. - LLM local
tools/gemini-cli(modelo sonnet) — sin var, binario en disco. - Brain
brain/tools/brain.js(identidad + captions históricos), SQLitetools/metrics-db.js. - Notificaciones:
tools/notify-router.ts(Sofía social + CEOSEC).
Cómo probarlo
cd /Users/user/rifai-agents && npx tsx agentes/content/content-daily-v2.ts
# Forzar un tema concreto (no depende del día):
cd /Users/user/rifai-agents && FORCE_TEMA=oferta npx tsx agentes/content/content-daily-v2.ts
Espera ver: tema del día, generación de contenido (6 slides), imágenes fal.ai, composición de slides, publicación FB (✅ FB: ...) e IG (o aviso de IG no vinculada). Publica de verdad en redes; úsalo con cuidado.
Si se rompe / recuperar
launchctl unload ~/Library/LaunchAgents/com.rifai.content-daily.plist
launchctl load ~/Library/LaunchAgents/com.rifai.content-daily.plist
Logs en /Users/user/rifai-agents/logs/content-daily.log. Estado en data/content-daily-state.json (borrar si el índice de producto se corrompe). Fallos típicos: token Meta caducado (regenerar META_PAGE_TOKEN), IG no vinculada en Business Suite, o gemini-cli devolviendo JSON inválido (extractJSON aborta).
Cómo replicarlo
- Lector de
.envestándar de la flota. - Tabla de temas por día +
TOP_PRODUCT_IDS. - Binario LLM local (
gemini-cli) con system prompt de community manager + regla "kick scooter". - fal.ai (
flux/schnellpara fondos + storage upload). - Sharp para overlay de texto (SVG compositado).
- Cliente Meta Graph (FB album: photos unpublished + feed; IG carousel: containers + CAROUSEL + publish).
- Shopify REST para producto/foto real.
- Brain (identidad + similares) y SQLite (
recordSocialPost) opcionales. notify-routery un plistStartCalendarIntervala las 13:00.