{
  "name": "IG_POST",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "25 10 * * *"
            },
            {
              "field": "cronExpression",
              "expression": "27 17 * * *"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        32,
        0
      ],
      "id": "a8bc7c2e-c5c7-4214-a5bf-7f4af99fc730",
      "name": "Schedule Trigger"
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "claude-3-5-sonnet-20241022",
          "mode": "list",
          "cachedResultName": "claude-3-5-sonnet-20241022"
        },
        "messages": {
          "values": [
            {
              "content": "=// ============================================================================\n// PROMPT OPENAI OPTIMIZADO V2 - VERSI\u00d3N CORREGIDA\n// ============================================================================\n// Variables: SOLO las que existen en el JSON real del nodo anterior\n// NO se usan variables inventadas\n// ============================================================================\n\nEres el creador de contenido oficial de {{ $json.prompt_structure.project.name }} ({{ $json.prompt_structure.project.url }}).\n\nTu misi\u00f3n es: {{ $json.prompt_structure.project.mission }}\n\nINFORMACI\u00d3N CR\u00cdTICA SOBRE ESTE POST:\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n\ud83c\udfaf TEMA Y ENFOQUE:\nT\u00edtulo: {{ $json.prompt_structure.main_theme.title }}\nTipo: {{ $json.prompt_structure.main_theme.type }}\nEnfoque ESPEC\u00cdFICO: {{ $json.prompt_structure.main_theme.focus_specific }}\nDescripci\u00f3n: {{ $json.prompt_structure.main_theme.description }}\nNotas especiales: {{ $json.prompt_structure.main_theme.special_notes }}\n\n\ud83d\ude0a MOOD Y TONO REQUERIDO:\nMood: {{ $json.metadata.mood }}\nEste mood DEBE reflejarse en CADA l\u00ednea del contenido\n\n\ud83d\udc65 AUDIENCIA OBJETIVO:\nQui\u00e9n es: {{ $json.prompt_structure.audience.target_type }}\nDescripci\u00f3n: {{ $json.prompt_structure.audience.description }}\nTono para ellos: {{ $json.prompt_structure.audience.tone_specific }}\nQu\u00e9 les importa: {{ $json.prompt_structure.audience.focus_area }}\n\n\ud83d\udccd CONTEXTO TEMPORAL Y CULTURAL:\nD\u00eda: {{ $json.metadata.day_of_week }}\nHora: {{ $json.metadata.hour }}:00 hrs\nPer\u00edodo del d\u00eda: {{ $json.prompt_structure.contexts.temporal.period }}\nEstaci\u00f3n: {{ $json.metadata.season }}\nContexto estacional: {{ $json.prompt_structure.contexts.seasonal.seasonal_element }}\nFestividad: {{ $json.metadata.holiday }}\nIdioma: {{ $json.prompt_structure.contexts.cultural.language }}\n\nEste contexto es IMPORTANTE: Incorpora la atm\u00f3sfera de {{ $json.prompt_structure.contexts.temporal.period }} en {{ $json.metadata.day_of_week }}, \nla estaci\u00f3n {{ $json.metadata.season }}, y considera cualquier festividad.\n\n\ud83c\udfa8 PLATAFORMA Y FORMATO:\nPlataforma: {{ $json.metadata.platform }}\nLongitud IDEAL: {{ $json.prompt_structure.platform.optimal_length }} caracteres\nM\u00c1XIMO ABSOLUTO: {{ $json.prompt_structure.platform.max_length }} caracteres\nFormato: {{ $json.prompt_structure.platform.format }}\nTipos de contenido que funcionan: {{ $json.prompt_structure.platform.best_content_types }}\nHashtags requeridos: {{ $json.prompt_structure.platform.hashtags_count }}\n\n\ud83d\udcca ESTRATEGIA:\nTipo de contenido: {{ $json.prompt_structure.strategy.type }}\nEnfoque: {{ $json.prompt_structure.strategy.approach }}\nElementos CLAVE que DEBES incluir:\n- {{ $json.prompt_structure.strategy.key_elements[0] }}\n- {{ $json.prompt_structure.strategy.key_elements[1] }}\n- {{ $json.prompt_structure.strategy.key_elements[2] }}\n\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\ud83d\udd34 GU\u00cdAS \u00c9TICAS Y DE MARCA (OBLIGATORIO):\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nVOZ DE MARCA {{ $json.prompt_structure.project.name }}:\n- Tono: aut\u00e9ntico, cercano, transparente, esperanzador\n- Valores: respetuoso, inspirador, empoderador\n- Estilo: inclusivo, accesible, genuino\n\nNOTAS ESPECIALES SOBRE ESTE CONTENIDO:\n{{ $json.prompt_structure.main_theme.special_notes }}\n\nREGLAS DE MARCA (NUNCA violarlas):\n- Regla 1 que NUNCA debes quebrantar\n- Regla 2 de conformidad de marca\n- Regla 3 de contenido\n- Regla 4 de tono\n\nRevisi\u00f3n \u00e9tica requerida: {{ $json.tracking.ethical_review_required }}\n\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\u2705 ESTRUCTURA OBLIGATORIA:\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nTu contenido DEBE tener esta estructura exacta:\n\n1. HOOK (1-2 l\u00edneas m\u00e1ximo):\n   - Algo impactante sobre: {{ $json.prompt_structure.main_theme.focus_specific }}\n   - Puede ser: Pregunta reflexiva, micro-historia, dato relevante\n   - DEBE generar curiosidad/emoci\u00f3n inmediatamente\n\n2. DESARROLLO (2-4 l\u00edneas):\n   - Contexto: {{ $json.prompt_structure.contexts.temporal.description }}\n   - Mood: {{ $json.metadata.mood }}\n   - Audiencia: {{ $json.prompt_structure.audience.target_type }}\n   - Elemento estacional: {{ $json.metadata.season }}\n   - Responde la pregunta o contin\u00faa la historia del hook\n   - Conecta emocionalmente\n\n3. CIERRE (1-2 l\u00edneas):\n   - Call to Action: {{ $json.prompt_structure.main_theme.call_to_action }}\n   - NO presionar, invitar a participar\n   - Ser natural y genuino\n\n4. EMOJIS:\n   - M\u00e1ximo 4-5, estrat\u00e9gicamente colocados\n   - Que reflejen el mood: {{ $json.metadata.mood }}\n   - Naturales, no excesivos\n\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n#\ufe0f\u20e3 HASHTAGS ({{ $json.prompt_structure.platform.hashtags_count }} TOTAL):\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nSelecciona exactamente {{ $json.prompt_structure.platform.hashtags_count }} hashtags relevantes que combinen:\n- Tema: {{ $json.prompt_structure.main_theme.type }}\n- Mood: {{ $json.metadata.mood }}\n- Audiencia: {{ $json.prompt_structure.audience.target_type }}\n- Plataforma: {{ $json.metadata.platform }}\n\nLos hashtags deben ser:\n\u2713 Relevantes y espec\u00edficos (NO gen\u00e9ricos)\n\u2713 Utilizables (tendencias reales)\n\u2713 Relacionados con {{ $json.prompt_structure.project.name }}\n\u2713 Variados (algunos grandes, algunos nicho)\n\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\ud83c\udfa8 SUGERENCIA VISUAL:\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nBasada en:\n- Contexto visual: {{ $json.prompt_structure.contexts.visual.suggested_context }}\n- Formato: {{ $json.prompt_structure.platform.format }}\n- Directrices visuales:\n  {{ $json.prompt_structure.contexts.visual.visual_guidelines[0] }}\n  {{ $json.prompt_structure.contexts.visual.visual_guidelines[1] }}\n\nProporciona una descripci\u00f3n clara de:\n- Plano recomendado (General, Medio, Detalle)\n- Elementos visuales principales\n- Atm\u00f3sfera y composici\u00f3n\n- Colores/tono visual recomendado\n- Qu\u00e9 EVITAR (textos legibles, n\u00fameros espec\u00edficos, eventos inventados)\n\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\u23f0 MEJOR HORA DE PUBLICACI\u00d3N:\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nBasada en:\n- Plataforma: {{ $json.metadata.platform }}\n- Audiencia: {{ $json.prompt_structure.audience.target_type }}\n- Momento actual: {{ $json.metadata.day_of_week }} a las {{ $json.metadata.hour }}:00 hrs\n- Per\u00edodo: {{ $json.prompt_structure.contexts.temporal.period }}\n- Estaci\u00f3n: {{ $json.metadata.season }}\n- Festividad: {{ $json.metadata.holiday }}\n\nProporciona hora ESPEC\u00cdFICA en formato HH:00 hrs\nJustifica por qu\u00e9 es \u00f3ptima para {{ $json.metadata.platform }} y la audiencia {{ $json.prompt_structure.audience.target_type }}\n\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\ud83d\udce4 FORMATO DE ENTREGA EXACTO:\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nIMPORTANTE: Sigue este formato EXACTAMENTE:\n\n[CONTENIDO DEL POST]\nHook + Desarrollo + CTA + Emojis\n(M\u00e1ximo {{ $json.prompt_structure.platform.optimal_length }} caracteres sin hashtags)\n\n---\n\n[HASHTAGS]\n#Hashtag1 #Hashtag2 #Hashtag3 #Hashtag4 #Hashtag5 #Hashtag6 #Hashtag7 #Hashtag8\n(Total: {{ $json.prompt_structure.platform.hashtags_count }})\n\n---\n\n[SUGERENCIA VISUAL]\nDescripci\u00f3n de imagen/video recomendada\n\n---\n\n[MEJOR HORA DE PUBLICACI\u00d3N]\nHora recomendada + Justificaci\u00f3n\n\n---\n\nID: {{ $json.metadata.content_id }}\n\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\ud83d\udd0d CHECKLIST ANTES DE ENTREGAR:\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nCONTENIDO:\n\u2611 Hook es impactante y genera curiosidad\n\u2611 Desarrollo conecta con {{ $json.prompt_structure.audience.target_type }}\n\u2611 Mood \"{{ $json.metadata.mood }}\" se refleja en CADA l\u00ednea\n\u2611 CTA es claro pero no presionante\n\u2611 Emojis son m\u00e1ximo 4-5 y estrat\u00e9gicos\n\u2611 Longitud respeta plataforma (m\u00e1x {{ $json.prompt_structure.platform.max_length }} caracteres)\n\nCONTEXTO:\n\u2611 Considera momento: {{ $json.metadata.day_of_week }} {{ $json.metadata.hour }}:00 hrs ({{ $json.prompt_structure.contexts.temporal.period }})\n\u2611 Incorpora estaci\u00f3n: {{ $json.metadata.season }}\n\u2611 Refleja contexto cultural si aplica\n\u2611 Lenguaje es natural y aut\u00e9ntico\n\n\u00c9TICA:\n\u2611 Respeta gu\u00edas \u00e9ticas de marca\n\u2611 Cumple reglas no negociables\n\u2611 NO hay datos/n\u00fameros inventados\n\u2611 NO hay presi\u00f3n/manipulaci\u00f3n\n\u2611 Dignidad preservada\n\nHASHTAGS:\n\u2611 Son {{ $json.prompt_structure.platform.hashtags_count }} exactamente\n\u2611 Relevantes para {{ $json.metadata.theme_type }}\n\u2611 Reflejan mood: {{ $json.metadata.mood }}\n\u2611 Variados (no todos peque\u00f1os o todos grandes)\n\nFORMATO:\n\u2611 Tiene todas 4 secciones: [CONTENIDO], [HASHTAGS], [VISUAL], [HORA]\n\u2611 Separadores \"---\" est\u00e1n presentes\n\u2611 ID est\u00e1 al final: {{ $json.metadata.content_id }}\n\n\u26a0\ufe0f SI ALGO NO CUMPLE \u2192 REHAZ ANTES DE ENTREGAR\n\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\ud83d\udca1 INFORMACI\u00d3N DE TRACKING Y CONTEXTO:\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nM\u00e9todo de generaci\u00f3n: {{ $json.tracking.generation_method }}\nTiempo estimado de creaci\u00f3n: {{ $json.tracking.estimated_creation_time }}\nCategor\u00eda tema: {{ $json.tracking.theme_category }}\nOptimizaci\u00f3n plataforma: {{ $json.tracking.platform_optimization }}\nSegmento audiencia: {{ $json.tracking.audience_segment }}\n\nMetadata completa:\n- Content ID: {{ $json.metadata.content_id }}\n- Timestamp: {{ $json.metadata.timestamp }}\n- Timezone: {{ $json.metadata.timezone }}\n- Lenguaje: {{ $json.prompt_structure.contexts.cultural.language }}\n\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n\u00a1Adelante! Crea contenido aut\u00e9ntico, relevante y emotivo. \ud83d\ude80\n\nRecuerda:\n- Audiencia: {{ $json.prompt_structure.audience.target_type }}\n- Mood: {{ $json.metadata.mood }}\n- Plataforma: {{ $json.metadata.platform }}\n- Proyecto: {{ $json.prompt_structure.project.name }}"
            }
          ]
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.anthropic",
      "typeVersion": 1,
      "position": [
        448,
        0
      ],
      "id": "0ccf5d38-bc02-4bfc-9346-6c24259a2dfe",
      "name": "Claude1",
      "retryOnFail": true,
      "waitBetweenTries": 5000,
      "maxTries": 2,
      "notesInFlow": true,
      "credentials": {
        "anthropicApi": {
          "name": "<your credential>"
        }
      },
      "notes": "Fallo en el proceso"
    },
    {
      "parameters": {
        "jsCode": "// ============================================================================\n// GENERADOR GEN\u00c9RICO DE IDEAS DE CONTENIDO PARA N8N\n// ============================================================================\n// Versi\u00f3n: 1.0 TEMPLATE - Plantilla Base Reutilizable\n// Descripci\u00f3n: Plantilla completamente gen\u00e9rica para crear diferentes nodos\n// Instrucciones: Personalizar la secci\u00f3n CONFIGURACI\u00d3N PERSONALIZABLE\n// ============================================================================\n\n/*\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551                        INSTRUCCIONES DE USO EN N8N                         \u2551\n\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\n\n1. CONFIGURACI\u00d3N INICIAL:\n   - Crear un nodo \"Code\" en n8n\n   - Copiar TODO este c\u00f3digo en el nodo\n   - Configurar la ejecuci\u00f3n como \"Run Once for All Items\"\n   - Language: JavaScript\n\n2. PERSONALIZACI\u00d3N REQUERIDA:\n   - SECCI\u00d3N 1: Configuraci\u00f3n Personalizable (l\u00edneas 50-150)\n     * Cambiar nombre del proyecto/organizaci\u00f3n\n     * Definir misi\u00f3n espec\u00edfica\n     * Configurar URL, zona horaria, idioma\n   - SECCI\u00d3N 2: Audiencias objetivo (personalizar seg\u00fan tu caso)\n   - SECCI\u00d3N 3: Temas de contenido (crear temas relevantes)\n   - SECCI\u00d3N 4: Directrices \u00e9ticas (adaptar a tu proyecto)\n\n3. CONEXI\u00d3N CON OPENAI:\n   - Conectar la salida de este nodo a un nodo \"OpenAI Chat Model\"\n   - En el prompt del nodo OpenAI, usar: {{ $json.prompt_completo }}\n   - Modelo recomendado: GPT-4 Turbo o GPT-4o\n   - Temperature: 0.8 (para creatividad balanceada)\n   - Max tokens: 1000-2000 (seg\u00fan longitud deseada)\n\n4. ESTRUCTURA DE DATOS RETORNADOS:\n   - prompt_completo: Prompt listo para enviar a OpenAI\n   - metadata: Informaci\u00f3n de tracking y contexto\n   - prompt_structure: Estructura completa (para referencia)\n   - tracking: Datos para auditor\u00eda y an\u00e1lisis\n\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551              \u26a0\ufe0f  SECCI\u00d3N 1: CONFIGURACI\u00d3N PERSONALIZABLE                   \u2551\n\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\n\nINSTRUCCIONES: Cambia TODOS estos valores seg\u00fan tu proyecto:\n*/\n\n// ============================================================================\n// CONFIGURACI\u00d3N PERSONALIZABLE - REEMPLAZA ESTOS VALORES\n// ============================================================================\n\nconst CONFIG = {\n  // Informaci\u00f3n b\u00e1sica del proyecto\n  project_name: 'TU_NOMBRE_PROYECTO',          // \u2190 CAMBIAR\n  project_url: 'https://tuproyecto.com',      // \u2190 CAMBIAR\n  project_mission: 'Tu misi\u00f3n espec\u00edfica aqu\u00ed', // \u2190 CAMBIAR\n  \n  // Zona horaria (formato IANA)\n  // Ejemplos: America/Mexico_City, America/New_York, Europe/Madrid, America/Argentina/Buenos_Aires\n  time_zone: 'America/Mexico_City',             // \u2190 CAMBIAR seg\u00fan zona\n  \n  // Idioma y regi\u00f3n\n  language: 'es-MX',                            // \u2190 CAMBIAR: es-ES, en-US, pt-BR, etc.\n  country: 'M\u00e9xico',                            // \u2190 CAMBIAR\n  language_name: 'espa\u00f1ol',                     // \u2190 CAMBIAR\n  \n  // Brand voice - personalizar seg\u00fan tu marca\n  brand_voice: {\n    tone: 'aut\u00e9ntico, cercano, transparente, esperanzador',\n    values: 'respetuoso, inspirador, empoderador',\n    style: 'inclusivo, accesible, genuino'\n  },\n  \n  // Plataformas donde se publica\n  platforms: [\n    {\n      name: 'Instagram',\n      max_length: 2200,\n      optimal_length: 150,\n      hashtags_recommended: 8,\n      format: 'Carrusel, Reels, Stories',\n      best_content: ['inspirador', 'visual', 'relatable']\n    },\n    {\n      name: 'Facebook',\n      max_length: 63206,\n      optimal_length: 300,\n      hashtags_recommended: 5,\n      format: 'Post, Video, Testimonios',\n      best_content: ['detallado', 'comunitario', 'conversacional']\n    },\n    {\n      name: 'LinkedIn',\n      max_length: 3000,\n      optimal_length: 400,\n      hashtags_recommended: 3,\n      format: 'Art\u00edculos, Reflexiones profesionales',\n      best_content: ['profesional', 'datos', 'insights']\n    },\n    {\n      name: 'TikTok',\n      max_length: 2500,\n      optimal_length: 100,\n      hashtags_recommended: 5,\n      format: 'Videos cortos, Trends',\n      best_content: ['viral', 'din\u00e1mico', 'entretenido']\n    }\n  ]\n};\n\n/*\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551              \u26a0\ufe0f  SECCI\u00d3N 2: DEFINE TUS AUDIENCIAS OBJETIVO                 \u2551\n\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\n\nINSTRUCCIONES: Personaliza las audiencias seg\u00fan a qui\u00e9n te diriges.\nEjemplo: Si eres una escuela, tus audiencias podr\u00edan ser padres, estudiantes, docentes.\n*/\n\nconst audiences = [\n  {\n    type: 'audiencia_1',              // \u2190 CAMBIAR nombre\n    name: 'Nombre descriptivo',        // \u2190 CAMBIAR\n    description: 'Descripci\u00f3n de esta audiencia',\n    tone: 'respetuoso, profesional',  // \u2190 CAMBIAR\n    focus_areas: [\n      '\u00e1rea_1',\n      '\u00e1rea_2',\n      '\u00e1rea_3'\n    ],\n    pain_points: [\n      'problema_1',\n      'problema_2'\n    ],\n    triggers: [\n      'trigger_1',\n      'trigger_2'\n    ]\n  },\n  // A\u00f1ade m\u00e1s audiencias seg\u00fan necesites duplicando este objeto\n];\n\n/*\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551              \u26a0\ufe0f  SECCI\u00d3N 3: DEFINE TUS TEMAS DE CONTENIDO                  \u2551\n\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\n\nINSTRUCCIONES: Crea temas que sean relevantes para tu proyecto.\n*/\n\nconst contentThemes = [\n  {\n    type: 'tema_tipo_1',              // \u2190 Identificador \u00fanico\n    title: 'T\u00edtulo del tema',          // \u2190 Nombre del tema\n    description: 'Descripci\u00f3n general del tema',\n    focus: [\n      'aspecto_1',\n      'aspecto_2',\n      'aspecto_3'\n    ],\n    mood: ['tono_1', 'tono_2', 'tono_3'],\n    cta: ['llamada_accion_1', 'llamada_accion_2'],\n    format_suggestions: ['tipo_contenido_1', 'tipo_contenido_2'],\n    special_notes: 'Notas especiales o consideraciones \u00e9ticas/importantes',\n    best_platforms: ['Instagram', 'Facebook'],\n    estimated_reach: 'medio'\n  },\n  // A\u00f1ade m\u00e1s temas duplicando este objeto\n];\n\n/*\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551              \u26a0\ufe0f  SECCI\u00d3N 4: DIRECTRICES \u00c9TICAS Y DE MARCA                  \u2551\n\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\n\nINSTRUCCIONES: Define los principios \u00e9ticos y normas de contenido para tu proyecto.\n*/\n\nconst ETHICAL_GUIDELINES = [\n  '\ud83d\udd34 PRINCIPIO CR\u00cdTICO 1: Describe tu principio m\u00e1s importante',\n  '\ud83d\udfe1 PRINCIPIO 2: Segundo principio fundamental',\n  '\ud83d\udfe2 PRINCIPIO 3: Tercer principio clave',\n  '\ud83d\udd35 PRINCIPIO 4: Cuarto principio',\n  '\u26ab TRANSPARENCIA: Siempre s\u00e9 honesto y verificable'\n];\n\nconst MANDATORY_BRAND_RULES = [\n  'Regla 1 que NUNCA debes quebrantar',\n  'Regla 2 de conformidad de marca',\n  'Regla 3 de contenido',\n  'Regla 4 de tono'\n];\n\n// ============================================================================\n// CALENDARIO DE FESTIVIDADES PERSONALIZABLE\n// ============================================================================\n// INSTRUCCIONES: A\u00f1ade o modifica las fechas seg\u00fan tu pa\u00eds/regi\u00f3n\n// Formato: 'MM-DD': 'identificador_festividad'\n\nconst localHolidays = {\n  '01-01': 'nuevo_ano',\n  '01-06': 'festividad_1',\n  '02-14': 'festividad_2',\n  // A\u00f1ade m\u00e1s fechas seg\u00fan tu calendario local\n  '12-25': 'festividad_a\u00f1o_fin'\n};\n\n// ============================================================================\n// FUNCIONES AUXILIARES - NO MODIFICAR\n// ============================================================================\n\nfunction getCurrentTimeInTimeZone(timeZone) {\n  const now = new Date();\n  return new Date(now.toLocaleString(\"en-US\", { timeZone: timeZone }));\n}\n\nfunction getSeasonForDate(date, region = 'northern') {\n  const month = date.getMonth() + 1;\n  \n  if (region === 'northern') {\n    if (month >= 3 && month <= 5) return 'primavera';\n    if (month >= 6 && month <= 8) return 'verano';\n    if (month >= 9 && month <= 11) return 'oto\u00f1o';\n    return 'invierno';\n  } else if (region === 'southern') {\n    if (month >= 9 && month <= 11) return 'primavera';\n    if (month >= 12 || month <= 2) return 'verano';\n    if (month >= 3 && month <= 5) return 'oto\u00f1o';\n    return 'invierno';\n  }\n  \n  return 'estaci\u00f3n_desconocida';\n}\n\nfunction getHolidayForDate(date, holidaysMap) {\n  const monthDay = `${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;\n  return holidaysMap[monthDay] || null;\n}\n\nfunction getDayOfWeek(date, language = 'es') {\n  const daysES = ['domingo', 'lunes', 'martes', 'mi\u00e9rcoles', 'jueves', 'viernes', 's\u00e1bado'];\n  const daysEN = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\n  const daysArray = language === 'es' ? daysES : daysEN;\n  return daysArray[date.getDay()];\n}\n\nfunction getTimeOfDayContext(hour) {\n  if (hour >= 6 && hour < 12) return { period: 'ma\u00f1ana', mood_suggestion: 'energ\u00e9tico, esperanzador' };\n  if (hour >= 12 && hour < 17) return { period: 'tarde', mood_suggestion: 'activo, motivador' };\n  if (hour >= 17 && hour < 21) return { period: 'atardecer', mood_suggestion: 'reflexivo, tranquilo' };\n  return { period: 'noche', mood_suggestion: 'contemplativo, \u00edntimo' };\n}\n\nfunction selectRandomElement(array) {\n  return array[Math.floor(Math.random() * array.length)];\n}\n\n// ============================================================================\n// L\u00d3GICA PRINCIPAL - NO MODIFICAR (usa configuraci\u00f3n de arriba)\n// ============================================================================\n\nconst nowInTimeZone = getCurrentTimeInTimeZone(CONFIG.time_zone);\nconst currentHour = nowInTimeZone.getHours();\nconst currentDayOfWeek = getDayOfWeek(nowInTimeZone, 'es');\nconst currentSeason = getSeasonForDate(nowInTimeZone);\nconst currentHoliday = getHolidayForDate(nowInTimeZone, localHolidays);\nconst timeContext = getTimeOfDayContext(currentHour);\n\n// Validaci\u00f3n de datos\nif (!contentThemes || contentThemes.length === 0) {\n  throw new Error('ERROR: Debes definir al menos un tema en contentThemes');\n}\n\nif (!audiences || audiences.length === 0) {\n  throw new Error('ERROR: Debes definir al menos una audiencia en audiences');\n}\n\n// Selecciones aleatorias\nconst selectedTheme = selectRandomElement(contentThemes);\nconst selectedAudience = selectRandomElement(audiences);\nconst selectedPlatform = selectRandomElement(CONFIG.platforms);\nconst selectedMood = selectRandomElement(selectedTheme.mood);\nconst selectedCTA = selectRandomElement(selectedTheme.cta);\nconst selectedFormat = selectRandomElement(selectedTheme.format_suggestions);\n\n// ============================================================================\n// CONSTRUCCI\u00d3N DEL PROMPT FINAL\n// ============================================================================\n\nconst contentPrompt = {\n  \n  // Informaci\u00f3n general\n  project: {\n    name: CONFIG.project_name,\n    url: CONFIG.project_url,\n    mission: CONFIG.project_mission\n  },\n  \n  // Tema principal seleccionado\n  main_theme: {\n    type: selectedTheme.type,\n    title: selectedTheme.title,\n    description: selectedTheme.description,\n    focus_specific: selectRandomElement(selectedTheme.focus),\n    mood_desired: selectedMood,\n    format_suggested: selectedFormat,\n    call_to_action: selectedCTA,\n    special_notes: selectedTheme.special_notes\n  },\n  \n  // Audiencia objetivo\n  audience: {\n    target_type: selectedAudience.type,\n    description: selectedAudience.description,\n    tone_specific: selectedAudience.tone,\n    focus_area: selectRandomElement(selectedAudience.focus_areas)\n  },\n  \n  // Contextos\n  contexts: {\n    temporal: {\n      hour: currentHour,\n      day_of_week: currentDayOfWeek,\n      period: timeContext.period,\n      description: `${timeContext.period} de ${CONFIG.country}`,\n      timestamp: nowInTimeZone.toISOString()\n    },\n    seasonal: {\n      season: currentSeason,\n      seasonal_element: `Contexto de ${currentSeason}`\n    },\n    cultural: {\n      holiday: currentHoliday,\n      language: CONFIG.language\n    },\n    visual: {\n      suggested_context: `Visual relevante para ${selectedTheme.type}`,\n      visual_guidelines: selectedTheme.format_suggestions.map(f => `- Considera formato: ${f}`)\n    }\n  },\n  \n  // Plataforma seleccionada\n  platform: {\n    name: selectedPlatform.name,\n    max_length: selectedPlatform.max_length,\n    optimal_length: selectedPlatform.optimal_length,\n    hashtags_recommended: selectedPlatform.hashtags_recommended,\n    hashtags_count: selectedPlatform.hashtags_recommended,\n    format: selectedPlatform.format,\n    best_content_types: selectedPlatform.best_content\n  },\n  \n  // Estrategia de contenido\n  strategy: {\n    type: selectedTheme.type,\n    approach: `Enfoque ${selectedMood} para ${selectedAudience.type}`,\n    key_elements: selectedTheme.focus.slice(0, 3)\n  },\n  \n  // Metadata t\u00e9cnica\n  metadata: {\n    generation_timestamp: nowInTimeZone.toISOString(),\n    time_zone: CONFIG.time_zone,\n    content_id: `${CONFIG.project_name.substring(0, 3).toUpperCase()}${nowInTimeZone.getTime().toString().slice(-6)}`,\n    language: CONFIG.language,\n    country: CONFIG.country\n  }\n};\n\n// ============================================================================\n// GENERACI\u00d3N DEL PROMPT PARA OPENAI\n// ============================================================================\n\nconst promptCompleto = `Eres el creador de contenido oficial de ${CONFIG.project_name} (${CONFIG.project_url}).\n\n\ud83d\udccb MISI\u00d3N:\n${CONFIG.project_mission}\n\n\ud83c\udfaf TEMA PRINCIPAL:\n${contentPrompt.main_theme.title}\nEnfoque espec\u00edfico: ${contentPrompt.main_theme.focus_specific}\nFormato sugerido: ${contentPrompt.main_theme.format_suggested}\n\n\ud83d\udccd CONTEXTO:\n- Momento del d\u00eda: ${contentPrompt.contexts.temporal.period} (${contentPrompt.contexts.temporal.day_of_week})\n- Estaci\u00f3n: ${contentPrompt.contexts.seasonal.season}\n${contentPrompt.contexts.cultural.holiday ? `- Fecha especial: ${contentPrompt.contexts.cultural.holiday}` : ''}\n- Visual sugerido: ${contentPrompt.contexts.visual.suggested_context}\n\n\ud83d\udc65 AUDIENCIA:\n${contentPrompt.audience.target_type} - Tono: ${contentPrompt.audience.tone_specific}\nEnfoque: ${contentPrompt.audience.focus_area}\n\n\ud83d\udcf1 PLATAFORMA: ${contentPrompt.platform.name}\n- Longitud \u00f3ptima: ${contentPrompt.platform.optimal_length} caracteres\n- M\u00e1ximo: ${contentPrompt.platform.max_length} caracteres\n- Hashtags: ${contentPrompt.platform.hashtags_recommended}\n- Tono: ${contentPrompt.platform.format}\n\n\u270d\ufe0f ESTRATEGIA:\nTipo: ${contentPrompt.strategy.type}\nEnfoque: ${contentPrompt.strategy.approach}\nElementos clave: ${contentPrompt.strategy.key_elements.join(', ')}\n\n\ud83d\udd34 REQUISITOS CR\u00cdTICOS NO NEGOCIABLES:\n\n1. VOZ DE MARCA:\n   ${CONFIG.brand_voice.tone}\n   Valores: ${CONFIG.brand_voice.values}\n   Estilo: ${CONFIG.brand_voice.style}\n\n2. DIRECTRICES \u00c9TICAS:\n${ETHICAL_GUIDELINES.map(guideline => `   ${guideline}`).join('\\n')}\n\n3. REGLAS DE MARCA:\n${MANDATORY_BRAND_RULES.map(rule => `   - ${rule}`).join('\\n')}\n\n4. ESTRUCTURA REQUERIDA:\n   - Inicio: Hook emotivo o dato relevante\n   - Desarrollo: ${contentPrompt.main_theme.focus_specific}\n   - Cierre: Llamado a acci\u00f3n claro \u2192 \"${contentPrompt.main_theme.call_to_action}\"\n   - Hashtags: ${contentPrompt.platform.hashtags_recommended} relevantes\n\n5. CONSIDERACIONES VISUALES:\n${contentPrompt.contexts.visual.visual_guidelines.join('\\n')}\n\n\ud83d\udcdd FORMATO DE ENTREGA:\n\n[CONTENIDO DEL POST]\n(Texto completo optimizado para ${contentPrompt.platform.name})\n\n---\n\n[HASHTAGS]\n(${contentPrompt.platform.hashtags_recommended} hashtags)\n\n---\n\n[SUGERENCIA VISUAL]\n(Descripci\u00f3n breve de imagen/video)\n\n---\n\n[MEJOR HORA DE PUBLICACI\u00d3N]\n(Hora recomendada considerando que es ${contentPrompt.contexts.temporal.day_of_week} a las ${contentPrompt.contexts.temporal.hour}:00 hrs)\n\n---\n\nID de contenido: ${contentPrompt.metadata.content_id}`;\n\n// ============================================================================\n// RETORNO FINAL PARA N8N\n// ============================================================================\n\nreturn [{\n  json: {\n    // PROMPT LISTO PARA OPENAI\n    prompt_completo: promptCompleto,\n    \n    // METADATOS PARA TRACKING\n    metadata: {\n      content_id: contentPrompt.metadata.content_id,\n      timestamp: contentPrompt.metadata.generation_timestamp,\n      timezone: contentPrompt.metadata.time_zone,\n      project: CONFIG.project_name,\n      platform: contentPrompt.platform.name,\n      theme_type: contentPrompt.main_theme.type,\n      theme_title: contentPrompt.main_theme.title,\n      audience: contentPrompt.audience.target_type,\n      mood: contentPrompt.main_theme.mood_desired,\n      season: contentPrompt.contexts.seasonal.season,\n      holiday: contentPrompt.contexts.cultural.holiday || 'ninguna',\n      day_of_week: contentPrompt.contexts.temporal.day_of_week,\n      hour: contentPrompt.contexts.temporal.hour\n    },\n    \n    // ESTRUCTURA COMPLETA (para referencia/debug)\n    prompt_structure: contentPrompt,\n    \n    // INFORMACI\u00d3N DE SEGUIMIENTO\n    tracking: {\n      generation_method: `Generador ${CONFIG.project_name} - Plantilla v1.0`,\n      estimated_creation_time: '15-25 minutos',\n      theme_category: selectedTheme.type,\n      platform_optimization: selectedPlatform.name,\n      audience_segment: selectedAudience.type,\n      ethical_review_required: selectedTheme.special_notes.length > 0\n    }\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        0
      ],
      "id": "ee5baf1a-f7fd-4a42-87f6-59f4c4249fd5",
      "name": "Generate Content Ideas"
    },
    {
      "parameters": {
        "resource": "image",
        "prompt": "={{\n  (function() {\n    // =======================================================================\n    // CONFIGURACI\u00d3N - PERSONALIZA SOLO ESTO\n    // =======================================================================\n    \n    const projectName = 'Proyecto';\n    const cameraLens = '35mm';\n    const culturalAdjective = 'contempor\u00e1neo';\n    const locationName = 'pa\u00eds';\n    const themeDescription = 'tema del proyecto';\n    const referenceStyleDescription = 'fotoperiodismo social, fotograf\u00eda documental urbana, realismo sin artificio';\n    \n    // =======================================================================\n    // 1. OBTENER Y PARSEAR OUTPUT DE CLAUDE1\n    // =======================================================================\n    \n    const claudeOutput = $('Claude1').first().json.content[0].text;\n    const postContent = claudeOutput.toLowerCase();\n    \n    // Funci\u00f3n para extraer secciones\n    function parseClaudeOutput(rawText) {\n      const sections = {};\n      \n      // Extraer [SUGERENCIA VISUAL]\n      const visualMatch = rawText.match(/\\[SUGERENCIA VISUAL\\]\\s*([\\s\\S]*?)(?=\\n\\[MEJOR HORA|\\[MEJOR HORA|$)/i);\n      sections.visualSuggestion = visualMatch ? visualMatch[1].trim() : '';\n      \n      return sections;\n    }\n    \n    const parsed = parseClaudeOutput(claudeOutput);\n    let visualSuggestion = parsed.visualSuggestion;\n    \n    // Limpiar la sugerencia de instrucciones t\u00e9cnicas\n    if (visualSuggestion) {\n      // Remover las instrucciones IMPORTANTE, ejemplos, etc\n      visualSuggestion = visualSuggestion.split('IMPORTANTE para la sugerencia visual:')[0].trim();\n      visualSuggestion = visualSuggestion.split('Ejemplos de sugerencias')[0].trim();\n    }\n    \n    // =======================================================================\n    // 2. AN\u00c1LISIS DEL CONTENIDO PARA CONTEXTO \u00c9TICO\n    // =======================================================================\n    \n    const isBeneficiarios = postContent.includes('dignidad') || \n                            postContent.includes('comunidad vulnerable') ||\n                            (postContent.includes('apoyo') && postContent.includes('necesidad'));\n    \n    const mentionsApp = postContent.includes('app') || \n                        postContent.includes('tel\u00e9fono') ||\n                        postContent.includes('notificaci\u00f3n');\n    \n    const mentionsFood = postContent.includes('comida') || \n                         postContent.includes('plato') || \n                         postContent.includes('sabor') ||\n                         postContent.includes('mesa');\n    \n    const isRestaurantes = postContent.includes('restaurante') || \n                           postContent.includes('cocina') ||\n                           postContent.includes('local');\n    \n    // =======================================================================\n    // 3. CONSTRUCCI\u00d3N DEL PROMPT\n    // =======================================================================\n    \n    let ethicalConstraints = \"\";\n    let prohibitions = \"\";\n    \n    // Restricciones \u00e9ticas seg\u00fan tema\n    if (isBeneficiarios) {\n      ethicalConstraints = `\nPROTECCI\u00d3N DE IDENTIDAD CR\u00cdTICA:\n- NUNCA mostrar rostros completos o identificables de personas vulnerables\n- Usar: siluetas, manos, espaldas, perfiles muy difuminados\n- Contexto de DIGNIDAD: momentos de comunidad y apoyo, NO sufrimiento\n- Ambiente limpio, ordenado y respetuoso`;\n\n      prohibitions = `\nPROHIBIDO ABSOLUTAMENTE:\n- Rostros identificables de personas vulnerables\n- Im\u00e1genes que degraden o victimicen\n- Contextos de sufrimiento innecesario\n- Ambientes descuidados o sucios`;\n      \n    } else if (mentionsApp) {\n      ethicalConstraints = `\nAUTENTICIDAD TECNOL\u00d3GICA:\n- Momento genuino de uso de tecnolog\u00eda, no pose comercial\n- Si aparece dispositivo, que sea natural en contexto\n- Expresiones genuinas de satisfacci\u00f3n sutil`;\n\n      prohibitions = `\nPROHIBIDO:\n- Pantallas con texto espec\u00edfico o UI detallada\n- Poses comerciales de stock photo\n- Iluminaci\u00f3n artificial de estudio`;\n      \n    } else if (isRestaurantes || mentionsFood) {\n      ethicalConstraints = `\nREALISMO GASTRON\u00d3MICO:\n- Balance entre ambiente arquitect\u00f3nico y actividad humana\n- Personas como parte natural del ambiente\n- Momentos aut\u00e9nticos sin performance para c\u00e1mara`;\n\n      prohibitions = `\nPROHIBIDO:\n- Enfoque solo en personas individuales\n- Risas dirigidas a c\u00e1mara\n- Poses publicitarias comerciales`;\n      \n    } else {\n      ethicalConstraints = `\nAUTENTICIDAD GENERAL:\n- Momentos genuinos, no dirigidos\n- Expresiones naturales variadas\n- Respeto y dignidad en toda representaci\u00f3n`;\n\n      prohibitions = `\nPROHIBIDO:\n- Poses publicitarias\n- Iluminaci\u00f3n artificial de estudio\n- Aspecto gen\u00e9rico de stock photo`;\n    }\n    \n    // =======================================================================\n    // 4. ESPECIFICACIONES T\u00c9CNICAS UNIVERSALES\n    // =======================================================================\n    \n    const photographyStyle = `Estilo documental urbano ${culturalAdjective} contempor\u00e1neo, fotograf\u00eda con lente ${cameraLens}, luz natural ambiental, captura de momentos aut\u00e9nticos cotidianos`;\n    \n    const realismTerms = \"Texturas naturales reales (madera, metal, piel con imperfecciones), materiales tangibles, expresiones faciales aut\u00e9nticas sin exageraci\u00f3n, posturas espont\u00e1neas, detalles de vida cotidiana\";\n    \n    const lightingSpecs = `Luz natural ${locationName} (intensa pero difusa) mezclada con iluminaci\u00f3n ambiental c\u00e1lida, sombras suaves naturales, profundidad de campo realista`;\n    \n    // =======================================================================\n    // 5. PROMPT FINAL\n    // =======================================================================\n    \n    const finalPrompt = `FOTOGRAF\u00cdA PROFESIONAL 100% REALISTA - NO ILUSTRACI\u00d3N NI ARTE DIGITAL\n\nFOTOGRAF\u00cdA DOCUMENTAL de contexto ${projectName}\n\nESTILO FOTOGR\u00c1FICO:\n${photographyStyle}\n\nCOMPOSICI\u00d3N Y ESCENA:\n${visualSuggestion || `Vista general de ambiente relacionado con ${themeDescription} en ${locationName}. Personas integradas naturalmente al espacio, expresiones genuinas variadas, luz natural ambiental. Atm\u00f3sfera c\u00e1lida y aut\u00e9ntica.`}\n\nESPECIFICACIONES T\u00c9CNICAS:\n- C\u00c1MARA: Lente ${cameraLens}, plano general o medio que capture contexto completo\n- ILUMINACI\u00d3N: ${lightingSpecs}\n- TEXTURAS: ${realismTerms}\n- PERSPECTIVA: Vista amplia que muestre ambiente y actividad natural\n\n${ethicalConstraints}\n\nCARACTER\u00cdSTICAS HUMANAS REALES (si aparecen personas):\n- EXPRESIONES: Momentos genuinos - satisfacci\u00f3n, concentraci\u00f3n, conversaci\u00f3n\n- ACTIVIDAD: Acciones naturales cotidianas, estados aut\u00e9nticos\n- AUTENTICIDAD: Sonrisas ocasionales genuinas cuando surgen naturalmente, NO risas simult\u00e1neas comerciales\n- DIVERSIDAD: Expresiones y actividades variadas simult\u00e1neas\n\nATM\u00d3SFERA:\n- Bienestar silencioso o energ\u00eda positiva seg\u00fan contexto\n- Ambiente viviente y activo sin artificialidad\n- Detalles que muestren vida real (texturas naturales, objetos usados, imperfecciones que dan credibilidad)\n- Luz natural que capture la calidez ${locationName}\n\n${prohibitions}\n- Textos visibles en pantallas, letreros o carteles\n- Close-ups extremos que pierdan contexto\n- UI o interfaces digitales detalladas\n\nELEMENTOS DE VERDADERO FOTOPERIODISMO:\n- Captura de momento real, no staged o preparado\n- Personas integradas naturalmente al contexto (si aparecen)\n- Momentos cotidianos aut\u00e9nticos sin performance\n- Imperfecciones y detalles que den credibilidad fotogr\u00e1fica\n- Plano general que cuente una historia visual completa\n\nOBJETIVO:\nImagen que parezca tomada por fot\u00f3grafo documental ${culturalAdjective} contempor\u00e1neo, capturando aut\u00e9nticamente la atm\u00f3sfera de ${projectName} con genuina humanidad, respeto absoluto y cero artificialidad comercial.\n\nEstilo referencia: ${referenceStyleDescription}\n\nCOMPOSICI\u00d3N: Plano general o medio (NUNCA close-up extremo) que muestre contexto completo y capture la esencia del momento.`;\n\n    // =======================================================================\n    // 6. RETURN\n    // =======================================================================\n    \n    return finalPrompt;\n  })()\n}}",
        "options": {
          "dalleQuality": "standard",
          "size": "1024x1024",
          "style": "natural",
          "returnImageUrls": true
        }
      },
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [
        800,
        0
      ],
      "id": "46fe860f-872f-4262-bdbf-90b679d04037",
      "name": "OpenAI",
      "retryOnFail": true,
      "maxTries": 2,
      "waitBetweenTries": 5000,
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// ============================================================================\n// PROCESADOR FINAL PARA INSTAGRAM - VERSI\u00d3N VERIFICADA\n// ============================================================================\n// Compatible con estructura real de Claude1: array[0].content[0].text\n\n// ============================================================================\n// 1. OBTENER DATOS DE LOS NODOS ANTERIORES\n// ============================================================================\n\n// Nodo del generador de ideas (primer Code node)\nconst generatorData = $('Generate Content Ideas').first().json;\n\n// Nodo Claude1 - ESTRUCTURA VERIFICADA: array[0].content[0].text\nconst claudeOutput = $('Claude1').first().json;\nconst claudeRawOutput = claudeOutput.content[0].text;\n\n// Nodo OpenAI DALL-E - Imagen generada\nconst dalleNode = $('OpenAI').first();\nconst dalleImageData = dalleNode ? dalleNode.json : null;\n\n// ============================================================================\n// 2. PARSEAR OUTPUT DE CLAUDE1 (EXTRAER SECCIONES)\n// ============================================================================\n\nfunction parseClaudeOutput(rawText) {\n  const sections = {};\n  \n  // Extraer [TEXTO DEL POST]\n  const textMatch = rawText.match(/\\[TEXTO DEL POST\\]\\s*([\\s\\S]*?)(?=\\n\\[HASHTAGS\\]|\\[HASHTAGS\\]|$)/i);\n  sections.text = textMatch ? textMatch[1].trim() : '';\n  \n  // Extraer [HASHTAGS]\n  const hashtagsMatch = rawText.match(/\\[HASHTAGS\\]\\s*([\\s\\S]*?)(?=\\n\\[SUGERENCIA VISUAL\\]|\\[SUGERENCIA VISUAL\\]|$)/i);\n  sections.hashtags = hashtagsMatch ? hashtagsMatch[1].trim() : '';\n  \n  // Extraer [SUGERENCIA VISUAL]\n  const visualMatch = rawText.match(/\\[SUGERENCIA VISUAL\\]\\s*([\\s\\S]*?)(?=\\n\\[MEJOR HORA DE PUBLICACI\u00d3N\\]|\\[MEJOR HORA|$)/i);\n  sections.visualSuggestion = visualMatch ? visualMatch[1].trim() : '';\n  \n  // Extraer [MEJOR HORA DE PUBLICACI\u00d3N]\n  const timeMatch = rawText.match(/\\[MEJOR HORA DE PUBLICACI\u00d3N\\]\\s*([\\s\\S]*?)$/i);\n  sections.bestTime = timeMatch ? timeMatch[1].trim() : '';\n  \n  return sections;\n}\n\nconst parsedContent = parseClaudeOutput(claudeRawOutput);\n\n// ============================================================================\n// 3. CONSTRUIR CAPTION FINAL PARA INSTAGRAM\n// ============================================================================\n\nlet finalCaption = parsedContent.text;\n\n// Asegurar que los hashtags est\u00e9n incluidos\nif (parsedContent.hashtags) {\n  // Verificar si ya est\u00e1n en el texto\n  const hashtagsAlreadyIncluded = parsedContent.hashtags.split(' ').every(tag => \n    finalCaption.includes(tag)\n  );\n  \n  if (!hashtagsAlreadyIncluded) {\n    finalCaption += '\\n\\n' + parsedContent.hashtags;\n  }\n}\n\n// Limpiar espacios extras y normalizar saltos de l\u00ednea\nfinalCaption = finalCaption.trim().replace(/\\n{3,}/g, '\\n\\n');\n\n// ============================================================================\n// 4. VERIFICAR Y OPTIMIZAR HASHTAGS\n// ============================================================================\n\nconst yoloPichoHashtags = [\n  '#YoloPicho',\n  '#CompartirEsAmar',\n  '#ImpactoReal', \n  '#SolidaridadMexico',\n  '#ComunidadYoloPicho',\n  '#RestaurantesConProp\u00f3sito',\n  '#Gastronom\u00edaSolidaria',\n  '#PuenteDeEsperanza',\n  '#JuntosHacemosM\u00e1s',\n  '#SaboresQueUnen',\n  '#MesaCompartida',\n  '#M\u00e9xicoGeneroso',\n  '#CadenaDeApoyo',\n  '#GestosSolidarios',\n  '#SaborConCausa',\n  '#UnidosPorElSabor'\n];\n\n// Contar hashtags actuales\nconst hashtagPattern = /#[\\w\u00c1\u00c9\u00cd\u00d3\u00da\u00e1\u00e9\u00ed\u00f3\u00fa\u00f1\u00d1]+/g;\nconst currentHashtags = finalCaption.match(hashtagPattern) || [];\nconst hashtagCount = currentHashtags.length;\n\n// Si faltan hashtags, agregar algunos (objetivo: 10-12)\nif (hashtagCount < 8) {\n  const additionalHashtags = yoloPichoHashtags\n    .filter(tag => !finalCaption.includes(tag))\n    .sort(() => 0.5 - Math.random())\n    .slice(0, Math.min(5, 12 - hashtagCount));\n  \n  if (additionalHashtags.length > 0) {\n    finalCaption += '\\n\\n' + additionalHashtags.join(' ');\n  }\n}\n\n// ============================================================================\n// 5. EXTRAER URL DE IMAGEN DE DALL-E\n// ============================================================================\n\nlet imageUrl = '';\nlet imageSource = 'none';\n\nif (dalleImageData) {\n  // Intentar diferentes estructuras posibles del nodo DALL-E\n  if (dalleImageData.data && Array.isArray(dalleImageData.data) && dalleImageData.data.length > 0) {\n    imageUrl = dalleImageData.data[0].url || dalleImageData.data[0].image_url || '';\n    imageSource = 'dalle3';\n  } else if (dalleImageData.url) {\n    imageUrl = dalleImageData.url;\n    imageSource = 'dalle3';\n  } else if (dalleImageData.image_url) {\n    imageUrl = dalleImageData.image_url;\n    imageSource = 'dalle3';\n  } else if (dalleImageData.output) {\n    imageUrl = dalleImageData.output;\n    imageSource = 'dalle3';\n  }\n}\n\n// Fallback si no hay imagen\nif (!imageUrl || imageUrl === '') {\n  const timestamp = Date.now();\n  imageUrl = `https://via.placeholder.com/1080x1080/FF6B6B/FFFFFF?text=YoloPicho+${timestamp}`;\n  imageSource = 'placeholder';\n}\n\n// ============================================================================\n// 6. CREAR METADATA COMPLETA DEL POST\n// ============================================================================\n\nconst finalHashtagCount = (finalCaption.match(hashtagPattern) || []).length;\n\nconst postMetadata = {\n  // IDs y tracking\n  content_id: generatorData.metadata?.content_id || `YP${Date.now()}`,\n  post_id: `yp_ig_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n  created_at: new Date().toISOString(),\n  \n  // Info del generador\n  theme_type: generatorData.metadata?.theme_type || 'unknown',\n  theme_title: generatorData.metadata?.theme_title || 'Contenido YoloPicho',\n  mood: generatorData.metadata?.mood || 'inspirador',\n  audience: generatorData.metadata?.audience || 'comunidad_general',\n  platform: 'instagram',\n  \n  // Contexto temporal\n  day_of_week: generatorData.metadata?.day_of_week || new Date().toLocaleDateString('es-MX', { weekday: 'long' }),\n  hour: generatorData.metadata?.hour || new Date().getHours(),\n  season: generatorData.metadata?.season || 'invierno',\n  holiday: generatorData.metadata?.holiday || 'ninguna',\n  \n  // Sensibilidad y tracking\n  sensitivity_level: generatorData.tracking?.sensitivity_level || 'NORMAL',\n  includes_beneficiaries: generatorData.tracking?.includes_beneficiaries || false,\n  includes_donors: generatorData.tracking?.includes_donors || false,\n  includes_restaurants: generatorData.tracking?.includes_restaurants || false,\n  ethical_review_required: generatorData.tracking?.ethical_review_required || false,\n  \n  // M\u00e9tricas de contenido\n  caption_length: finalCaption.length,\n  caption_length_without_hashtags: parsedContent.text.length,\n  hashtags_count: finalHashtagCount,\n  emoji_count: (finalCaption.match(/[\\u{1F300}-\\u{1F9FF}]/gu) || []).length,\n  has_image: imageSource !== 'none' && imageSource !== 'placeholder',\n  image_source: imageSource,\n  \n  // M\u00e9todo de generaci\u00f3n\n  generation_method: 'yolopicho_v2_claude_dalle',\n  automation_level: 'full_autonomous',\n  generator_version: '2.0_final'\n};\n\n// ============================================================================\n// 7. PREPARAR DATOS PARA INSTAGRAM API\n// ============================================================================\n\nconst instagramData = {\n  caption: finalCaption,\n  image_url: imageUrl,\n  access_token: process.env.INSTAGRAM_ACCESS_TOKEN || '',\n  instagram_account_id: process.env.INSTAGRAM_BUSINESS_ACCOUNT_ID || '',\n  // Opcional: location_id si quieres geolocalizar posts\n  // location_id: '...'\n};\n\n// ============================================================================\n// 8. ANALYTICS Y PREDICCIONES\n// ============================================================================\n\n// Funci\u00f3n: predecir engagement basado en tipo de tema\nfunction predictEngagement(themeType, mood, hashtagCount, captionLength) {\n  // Base scores por tema\n  const themeScores = {\n    'beneficiarios_dignidad': 92,\n    'beneficiarios_familias_pobreza': 88,\n    'beneficiarios_transformacion': 95,\n    'donantes_motivacion': 85,\n    'donantes_experiencia': 78,\n    'donantes_comunidad': 82,\n    'donantes_impacto_personal': 88,\n    'restaurantes_aliados': 75,\n    'restaurantes_proceso_union': 68,\n    'como_funciona_yolopicho': 70,\n    'eventos_comunidad_solidaria': 85,\n    'testimonios_comunidad_historias': 90\n  };\n  \n  let baseScore = themeScores[themeType] || 75;\n  \n  // Ajustar por mood\n  const moodModifiers = {\n    'inspirador': 8, 'emotivo': 10, 'esperanzador': 6, 'motivacional': 7,\n    'aut\u00e9ntico': 5, 'celebratorio': 8, 'agradecido': 4, 'respetuoso': 3,\n    'digno': 5, 'humano': 6, 'emp\u00e1tico': 5, 'profundo': 4\n  };\n  baseScore += (moodModifiers[mood] || 0);\n  \n  // Ajustar por hashtags (\u00f3ptimo: 10-12)\n  if (hashtagCount >= 10 && hashtagCount <= 12) baseScore += 3;\n  else if (hashtagCount >= 8 && hashtagCount <= 15) baseScore += 1;\n  else if (hashtagCount < 5) baseScore -= 5;\n  \n  // Ajustar por longitud del caption (\u00f3ptimo: 120-400 chars)\n  if (captionLength >= 120 && captionLength <= 400) baseScore += 5;\n  else if (captionLength < 80) baseScore -= 3;\n  else if (captionLength > 600) baseScore -= 2;\n  \n  const finalScore = Math.min(100, Math.max(40, baseScore));\n  \n  return {\n    predicted_score: finalScore,\n    confidence: finalScore > 85 ? 'high' : finalScore > 75 ? 'medium' : 'standard',\n    category: finalScore > 90 ? 'viral_potential' : finalScore > 80 ? 'strong_engagement' : 'standard_performance',\n    factors: {\n      base_theme_score: themeScores[themeType] || 75,\n      mood_bonus: moodModifiers[mood] || 0,\n      hashtag_optimization: hashtagCount >= 10 && hashtagCount <= 12,\n      caption_length_optimal: captionLength >= 120 && captionLength <= 400\n    }\n  };\n}\n\n// Funci\u00f3n: determinar hora \u00f3ptima de publicaci\u00f3n\nfunction getOptimalTime() {\n  const now = new Date();\n  const hour = now.getHours();\n  const day = now.getDay(); // 0=domingo, 6=s\u00e1bado\n  const isWeekend = day === 0 || day === 6;\n  \n  let status, reason, recommendation;\n  \n  if (isWeekend) {\n    if (hour >= 10 && hour <= 14) {\n      status = 'optimal';\n      reason = 'weekend_brunch_time';\n      recommendation = '\ud83d\udfe2 MOMENTO IDEAL - Fin de semana durante brunch';\n    } else if (hour >= 19 && hour <= 21) {\n      status = 'good';\n      reason = 'weekend_evening';\n      recommendation = '\ud83d\udfe1 Buen momento - Tarde de fin de semana';\n    } else {\n      status = 'ok';\n      reason = 'weekend_offpeak';\n      recommendation = '\u26aa Considera publicar 10-14hrs o 19-21hrs';\n    }\n  } else {\n    if (hour >= 12 && hour <= 14) {\n      status = 'optimal';\n      reason = 'lunch_break_peak';\n      recommendation = '\ud83d\udfe2 MOMENTO IDEAL - Hora de comida';\n    } else if (hour >= 19 && hour <= 21) {\n      status = 'optimal';\n      reason = 'post_work_relaxation';\n      recommendation = '\ud83d\udfe2 MOMENTO IDEAL - Despu\u00e9s del trabajo';\n    } else if (hour >= 8 && hour <= 10) {\n      status = 'good';\n      reason = 'morning_commute';\n      recommendation = '\ud83d\udfe1 Buen momento - Trayecto matutino';\n    } else if (hour >= 14 && hour <= 17) {\n      status = 'ok';\n      reason = 'afternoon_work_hours';\n      recommendation = '\u26aa Considera esperar a 19-21hrs';\n    } else {\n      status = 'low';\n      reason = 'late_night_early_morning';\n      recommendation = '\ud83d\udd34 Bajo engagement - Espera a 12-14hrs o 19-21hrs';\n    }\n  }\n  \n  return {\n    status,\n    reason,\n    recommendation,\n    current_time: now.toISOString(),\n    is_weekend: isWeekend,\n    current_hour: hour\n  };\n}\n\n// Funci\u00f3n: categorizar contenido\nfunction categorizeContent(caption, themeType) {\n  const lowerCaption = caption.toLowerCase();\n  \n  // Categor\u00edas basadas en palabras clave\n  if (lowerCaption.includes('historia') || lowerCaption.includes('conoce')) return 'storytelling';\n  if (lowerCaption.includes('gracias') || lowerCaption.includes('agradec')) return 'gratitude';\n  if (lowerCaption.includes('c\u00f3mo') || lowerCaption.includes('descubre') || lowerCaption.includes('aprende')) return 'educational';\n  if (lowerCaption.includes('\u00fanete') || lowerCaption.includes('participa') || lowerCaption.includes('s\u00famate')) return 'call_to_action';\n  if (lowerCaption.includes('inspira') || lowerCaption.includes('esperanza') || lowerCaption.includes('sue\u00f1o')) return 'inspirational';\n  if (lowerCaption.includes('comunidad') || lowerCaption.includes('juntos') || lowerCaption.includes('familia')) return 'community';\n  if (lowerCaption.match(/\\d+/) && (lowerCaption.includes('comida') || lowerCaption.includes('persona'))) return 'data_driven';\n  \n  // Fallback basado en tema\n  if (themeType.includes('beneficiarios')) return 'impact_storytelling';\n  if (themeType.includes('donantes')) return 'donor_engagement';\n  if (themeType.includes('restaurantes')) return 'partner_spotlight';\n  \n  return 'general_inspirational';\n}\n\n// Funci\u00f3n: calcular quality score\nfunction calculateQualityScore(caption, imageUrl, metadata, hashtagCount) {\n  let score = 60; // Base\n  \n  // Caption quality (30 puntos m\u00e1x)\n  const captionLength = caption.length;\n  if (captionLength >= 120 && captionLength <= 400) score += 15;\n  else if (captionLength >= 80 && captionLength <= 600) score += 10;\n  \n  if (hashtagCount >= 10 && hashtagCount <= 12) score += 10;\n  else if (hashtagCount >= 8 && hashtagCount <= 15) score += 5;\n  \n  if (caption.includes('YoloPicho')) score += 5;\n  \n  // Image quality (20 puntos m\u00e1x)\n  if (imageUrl.includes('dall-e') || imageUrl.includes('oaidalleapi')) score += 15;\n  else if (imageUrl.includes('cloudinary') || imageUrl.includes('imgur')) score += 10;\n  else if (!imageUrl.includes('placeholder')) score += 5;\n  \n  // Metadata quality (20 puntos m\u00e1x)\n  if (metadata.theme_type !== 'unknown') score += 5;\n  if (metadata.mood !== 'inspirador') score += 5; // Variedad es buena\n  if (metadata.sensitivity_level === 'M\u00c1XIMA' && metadata.ethical_review_required) score += 10; // Bien manejado\n  \n  // Content optimization (10 puntos m\u00e1x)\n  const emojiCount = (caption.match(/[\\u{1F300}-\\u{1F9FF}]/gu) || []).length;\n  if (emojiCount >= 2 && emojiCount <= 4) score += 5;\n  if (caption.split('\\n\\n').length >= 2) score += 5; // Tiene p\u00e1rrafos\n  \n  return Math.min(100, Math.max(0, Math.round(score)));\n}\n\n// Calcular analytics\nconst analyticsData = {\n  content_category: categorizeContent(finalCaption, postMetadata.theme_type),\n  expected_engagement: predictEngagement(\n    postMetadata.theme_type, \n    postMetadata.mood, \n    finalHashtagCount, \n    postMetadata.caption_length_without_hashtags\n  ),\n  optimal_posting: getOptimalTime(),\n  quality_score: calculateQualityScore(finalCaption, imageUrl, postMetadata, finalHashtagCount),\n  \n  // Metadata adicional\n  target_audience: postMetadata.audience,\n  content_source: 'yolopicho_generator_v2',\n  image_ai_generated: imageSource === 'dalle3',\n  automation_level: 'full_autonomous',\n  requires_manual_review: postMetadata.ethical_review_required\n};\n\n// ============================================================================\n// 9. DETERMINAR ESTADO DE PUBLICACI\u00d3N\n// ============================================================================\n\nconst readyForInstagram = !postMetadata.ethical_review_required && imageSource !== 'placeholder';\nconst requiresReview = postMetadata.ethical_review_required;\nconst missingImage = imageSource === 'placeholder';\n\nlet alerts = [];\nif (requiresReview) {\n  alerts.push('\u26a0\ufe0f CONTENIDO SENSIBLE - Requiere revisi\u00f3n \u00e9tica');\n  alerts.push('\u26a0\ufe0f Verificar protecci\u00f3n de identidad si incluye beneficiarios');\n}\nif (missingImage) {\n  alerts.push('\u26a0\ufe0f Imagen no generada - usando placeholder');\n}\nif (finalHashtagCount < 5) {\n  alerts.push('\u26a0\ufe0f Pocos hashtags - considerar agregar m\u00e1s');\n}\nif (analyticsData.quality_score < 70) {\n  alerts.push('\u26a0\ufe0f Quality score bajo - revisar contenido');\n}\n\n// ============================================================================\n// 10. LOG PARA DEBUGGING\n// ============================================================================\n\nconsole.log('\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550');\nconsole.log('\ud83c\udfa8 POST GENERADO Y PROCESADO EXITOSAMENTE');\nconsole.log('\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550');\nconsole.log(`\ud83d\udcdd Caption: ${postMetadata.caption_length} caracteres (${postMetadata.caption_length_without_hashtags} sin hashtags)`);\nconsole.log(`\ud83d\udd24 Hashtags: ${finalHashtagCount}`);\nconsole.log(`\ud83d\ude0a Emojis: ${postMetadata.emoji_count}`);\nconsole.log(`\ud83d\uddbc\ufe0f Imagen: ${imageSource.toUpperCase()} - ${imageUrl.substring(0, 60)}...`);\nconsole.log(`\ud83c\udfaf Tema: ${postMetadata.theme_type}`);\nconsole.log(`\ud83d\ude0a Mood: ${postMetadata.mood}`);\nconsole.log(`\ud83d\udc65 Audiencia: ${postMetadata.audience}`);\nconsole.log(`\ud83d\udcca Engagement predicho: ${analyticsData.expected_engagement.predicted_score}% (${analyticsData.expected_engagement.confidence})`);\nconsole.log(`\ud83d\udcc8 Categor\u00eda: ${analyticsData.expected_engagement.category}`);\nconsole.log(`\u2b50 Quality Score: ${analyticsData.quality_score}/100`);\nconsole.log(`\u23f0 Estado publicaci\u00f3n: ${analyticsData.optimal_posting.status.toUpperCase()}`);\nconsole.log(`\ud83d\udca1 ${analyticsData.optimal_posting.recommendation}`);\nconsole.log(`\ud83d\udea8 Sensibilidad: ${postMetadata.sensitivity_level}`);\nconsole.log(`\u2705 Listo para Instagram: ${readyForInstagram ? 'S\u00cd' : 'NO (requiere revisi\u00f3n)'}`);\nif (alerts.length > 0) {\n  console.log(`\u26a0\ufe0f  ALERTAS:`);\n  alerts.forEach(alert => console.log(`   ${alert}`));\n}\nconsole.log('\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550');\n\n// ============================================================================\n// 11. RETURN FINAL ESTRUCTURADO\n// ============================================================================\n\nreturn [{\n  json: {\n    // ========== DATOS PRINCIPALES PARA INSTAGRAM ==========\n    instagram_data: instagramData,\n    \n    // ========== CONTENIDO FINAL ==========\n    final_caption: finalCaption,\n    image_url: imageUrl,\n    \n    // ========== SECCIONES PARSEADAS ==========\n    parsed_sections: {\n      text: parsedContent.text,\n      hashtags: parsedContent.hashtags,\n      visual_suggestion: parsedContent.visualSuggestion,\n      best_time_suggestion: parsedContent.bestTime\n    },\n    \n    // ========== METADATA COMPLETA ==========\n    post_metadata: postMetadata,\n    analytics_data: analyticsData,\n    \n    // ========== ESTADO Y CONTROL ==========\n    ready_for_instagram: readyForInstagram,\n    requires_review: requiresReview,\n    missing_image: missingImage,\n    review_reason: requiresReview ? 'Contenido sobre beneficiarios - requiere aprobaci\u00f3n \u00e9tica' : null,\n    \n    posting_recommendation: analyticsData.optimal_posting.recommendation,\n    quality_assessment: analyticsData.quality_score >= 80 ? 'Excelente' : \n                        analyticsData.quality_score >= 70 ? 'Bueno' : \n                        analyticsData.quality_score >= 60 ? 'Aceptable' : 'Necesita mejoras',\n    \n    // ========== DATOS ORIGINALES ==========\n    original_generator_data: generatorData,\n    claude_raw_output: claudeRawOutput,\n    \n    // ========== TIMESTAMPS ==========\n    processing_completed_at: new Date().toISOString(),\n    \n    // ========== INFO DE NODOS ==========\n    node_info: {\n      generator_node: 'Generate Content Ideas',\n      claude_text_node: 'Claude1',\n      dalle_node: 'OpenAI',\n      processor_node: 'Final Processor'\n    },\n    \n    // ========== ALERTAS ==========\n    alerts: alerts\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        992,
        0
      ],
      "id": "a0c30a37-8f63-4597-b0c1-fff362efeb0b",
      "name": "Full Content"
    },
    {
      "parameters": {
        "httpRequestMethod": "POST",
        "graphApiVersion": "v23.0",
        "node": "={{ $env.INSTAGRAM_BUSINESS_ACCOUNT_ID }}",
        "edge": "media",
        "options": {
          "queryParameters": {
            "parameter": [
              {
                "name": "image_url",
                "value": "={{ $json.image_url }}"
              },
              {
                "name": "caption",
                "value": "={{ $json.final_caption }}"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.facebookGraphApi",
      "typeVersion": 1,
      "position": [
        1184,
        0
      ],
      "id": "20ccd9ae-dce4-4bbc-ac4f-3dee7e99ec01",
      "name": "Crear Contenedor",
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1392,
        0
      ],
      "id": "d1eaba70-9ba0-4771-9dec-f1647e98e9a8",
      "name": "Wait"
    },
    {
      "parameters": {
        "httpRequestMethod": "POST",
        "graphApiVersion": "v23.0",
        "node": "={{ $env.INSTAGRAM_BUSINESS_ACCOUNT_ID }}",
        "edge": "media_publish",
        "options": {
          "queryParameters": {
            "parameter": [
              {
                "name": "creation_id",
                "value": "={{ $('Crear Contenedor').item.json.id }}"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.facebookGraphApi",
      "typeVersion": 1,
      "position": [
        1600,
        0
      ],
      "id": "01cf9fa8-fd58-48ea-8d1a-ca3dd9e09e44",
      "name": "Facebook Graph Publish",
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Generate Content Ideas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude1": {
      "main": [
        [
          {
            "node": "OpenAI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Content Ideas": {
      "main": [
        [
          {
            "node": "Claude1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI": {
      "main": [
        [
          {
            "node": "Full Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Full Content": {
      "main": [
        [
          {
            "node": "Crear Contenedor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Crear Contenedor": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "Facebook Graph Publish",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": "zZ5hRjqXQNHgiNiy"
  },
  "versionId": "048e0d47-b17d-4604-8e0e-2446be1a336e",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "X6npT1pznKRJ1Qu6",
  "tags": []
}