{
  "name": "VEILLE-RSS-MATIN",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "30 6 * * 1-5"
            }
          ]
        }
      },
      "id": "v-schedule",
      "name": "Tous les matins 6h30",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// SOURCES RSS — Fidulia (Phase 1, 100% propre)\n// PRIORITÉ : tes 7 Google Alerts convertis en flux RSS (déjà calés sur tes 3 thèmes).\n//   -> Sur google.com/alerts, édite chaque alerte, \"Diffuser vers\" = Flux RSS,\n//      copie l'URL du flux et colle-la ci-dessous à la place du placeholder.\n// + quelques flux presse stables. Vérifie chaque URL une fois (un flux mort = ignoré, grâce à onError).\nconst feeds = [\n  // --- Google Alerts (à remplir) ---\n  { url: 'PLACEHOLDER_GOOGLE_ALERT_LINKEDIN', source: 'Google Alert', theme: 'LinkedIn' },\n  { url: 'PLACEHOLDER_GOOGLE_ALERT_IA_PROFESSIONS', source: 'Google Alert', theme: 'IA' },\n  { url: 'PLACEHOLDER_GOOGLE_ALERT_AMF', source: 'Google Alert', theme: 'Professions' },\n  { url: 'PLACEHOLDER_GOOGLE_ALERT_CGP', source: 'Google Alert', theme: 'Professions' },\n  // --- Presse / institutions (flux stables) ---\n  { url: 'https://techcrunch.com/feed/', source: 'TechCrunch', theme: 'IA' },\n  { url: 'https://www.wired.com/feed/rss', source: 'Wired', theme: 'IA' },\n  { url: 'https://www.technologyreview.com/feed/', source: 'MIT Tech Review', theme: 'IA' },\n  { url: 'https://www.theverge.com/rss/index.xml', source: 'The Verge', theme: 'IA' },\n];\nreturn feeds\n  .filter(f => f.url && !f.url.startsWith('PLACEHOLDER'))\n  .map(f => ({ json: f }));\n"
      },
      "id": "v-sources",
      "name": "Sources RSS",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        0
      ]
    },
    {
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {}
      },
      "id": "v-rss",
      "name": "Lecture flux RSS",
      "type": "n8n-nodes-base.rssFeedRead",
      "typeVersion": 1.1,
      "position": [
        480,
        0
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "const cutoff = Date.now() - 48*3600*1000;\nconst seen = new Set();\nconst articles = [];\nfor (const item of $input.all()) {\n  const a = item.json || {};\n  const dateStr = a.isoDate || a.pubDate || a.date || a.published;\n  const t = dateStr ? new Date(dateStr).getTime() : Date.now();\n  if (isNaN(t) || t < cutoff) continue;\n  const link = a.link || a.guid || a.title;\n  if (!link || seen.has(link)) continue;\n  seen.add(link);\n  const snip = (a.contentSnippet || a.content || a.summary || '').toString().replace(/<[^>]*>/g,' ').slice(0,400);\n  articles.push({ title: a.title, link: a.link, date: dateStr, snippet: snip });\n}\narticles.sort((x,y) => new Date(y.date) - new Date(x.date));\nconst top = articles.slice(0, 25);\nconst systemPrompt = \"Tu es l'agent Veille + Stratege de Fidulia, l'agence LinkedIn de Fabien Massavie pour les professions de confiance (priorite CGP, puis avocats, experts-comptables, notaires).\\n\\nMission : a partir d'articles RSS collectes ce matin, produire le BRIEF MATIN envoye par email au client.\\n\\nSELECTION (strict) :\\n- Sources d'autorite uniquement : institutions (AMF, ACPR, ESMA, EBA, FCA, OEC, CNB, CNCGP, ANACOFI), presse serieuse (MIT Tech Review, HBR, Financial Times, The Economist, Les Echos, L'Agefi, Wired, TechCrunch), think tanks (McKinsey, Stanford HAI, OCDE, WEF).\\n- JAMAIS d'influenceur ni d'opinion sans donnee verifiable.\\n- 3 themes seulement : (1) LinkedIn/strategie de contenu, (2) IA appliquee aux metiers, (3) Professions reglementees/patrimoine.\\n- Chaque item garde a un fait ou chiffre verifiable + un lien.\\n- Maximum 5 items, qualite avant quantite. Si rien de solide : le dire honnetement, ne rien inventer.\\n\\nTAG par item : [POST] (inedit + angle fort + ICP CGP), [NEWSLETTER] (format long ou deja couvert), [COMMENT] (a relayer vite). N'inclus pas les [SKIP].\\n\\nSORTIE : renvoie UNIQUEMENT du HTML (corps d'email), sans <html> ni <body>. Style sobre, navy #0C132A et magenta #D70459, police sans-serif. Structure :\\n- Titre : Ton brief LinkedIn du [date du jour]\\n- Section Veille du jour : pour chaque item -> tag, source, titre, 1 phrase 'ce que ca dit', 1 phrase 'angle pour toi (CGP)', le lien cliquable.\\n- Sous chaque item, en petit : 'Options : traiter maintenant / plus tard - format : post, carrousel ou infographie - type : actualite ou evergreen'.\\n- Termine par : 'Reponds a cet email avec les numeros + ce que tu veux faire (ex : 1 carrousel maintenant, 2 plus tard, 3 skip).'\\nInterdits : superlatifs vides, tiret cadratin, jargon anglais pompeux. Ton direct et factuel.\";\nconst userPrompt = 'Articles RSS collectes ce matin (JSON) :\\n' + JSON.stringify(top, null, 2) + '\\n\\nProduis le brief HTML.';\nreturn [{ json: { count: top.length, systemPrompt, userPrompt, articles: top } }];\n"
      },
      "id": "v-bundle",
      "name": "Filtre 48h + Bundle",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.anthropic.com/v1/messages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "anthropic-version",
              "value": "2023-06-01"
            },
            {
              "name": "content-type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ model: 'claude-sonnet-4-6', max_tokens: 4000, system: $json.systemPrompt, messages: [ { role: 'user', content: $json.userPrompt } ] }) }}",
        "options": {
          "timeout": 60000
        }
      },
      "id": "v-claude",
      "name": "Claude API (filtre + redige)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        960,
        0
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 2000
    },
    {
      "parameters": {
        "jsCode": "const resp = $input.first().json || {};\nlet html = '';\ntry { html = resp.content[0].text; } catch (e) { html = '<p>Erreur extraction reponse Claude</p>'; }\nhtml = html.replace(/^\\s*```html\\s*/i, '').replace(/^\\s*```\\s*/, '').replace(/```\\s*$/, '').trim();\nreturn [{ json: { html } }];\n"
      },
      "id": "v-extract",
      "name": "Extraire HTML",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1200,
        0
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "send",
        "sendTo": "fabien@fabien-massavie.com",
        "subject": "=Ton brief LinkedIn du {{ $now.format('dd/MM/yyyy') }}",
        "emailType": "html",
        "message": "={{ $json.html }}",
        "options": {
          "appendAttribution": false
        }
      },
      "id": "v-gmail",
      "name": "Email brief client",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1440,
        0
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 2000
    }
  ],
  "connections": {
    "Tous les matins 6h30": {
      "main": [
        [
          {
            "node": "Sources RSS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sources RSS": {
      "main": [
        [
          {
            "node": "Lecture flux RSS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lecture flux RSS": {
      "main": [
        [
          {
            "node": "Filtre 48h + Bundle",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filtre 48h + Bundle": {
      "main": [
        [
          {
            "node": "Claude API (filtre + redige)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude API (filtre + redige)": {
      "main": [
        [
          {
            "node": "Extraire HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extraire HTML": {
      "main": [
        [
          {
            "node": "Email brief client",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "active": false
}