{
  "id": "rss-feed-mon-01",
  "meta": {
    "instanceId": "vorlux-hub"
  },
  "name": "Vorlux AI | RSS Feed Monitor (2h Scan)",
  "active": true,
  "nodes": [
    {
      "id": "a1b2c3d4-0001-4aaa-8001-000000000001",
      "name": "Every 2 Hours",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [220, 300],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 2
            }
          ]
        }
      }
    },
    {
      "id": "a1b2c3d4-0001-4aaa-8001-000000000002",
      "name": "Get Configured Feeds",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [460, 300],
      "parameters": {
        "method": "GET",
        "url": "={{$env.VORLUX_HUB_URL}}/api/content/rss/feeds?status=active",
        "options": {
          "timeout": 15000
        }
      }
    },
    {
      "id": "a1b2c3d4-0001-4aaa-8001-000000000003",
      "name": "Has Feeds?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [700, 300],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "leftValue": "={{ ($json.data || []).length > 0 }}",
              "rightValue": "true",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        }
      }
    },
    {
      "id": "a1b2c3d4-0001-4aaa-8001-000000000004",
      "name": "Fetch Each Feed XML",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [940, 200],
      "notes": "Fetches each RSS feed URL, parses XML, extracts articles",
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const feeds = $input.first().json.data || [];\nconst allArticles = [];\nconst feedResults = [];\n\nfor (const feed of feeds) {\n  try {\n    const res = await fetch(feed.url, { signal: AbortSignal.timeout(10000) });\n    const xml = await res.text();\n    \n    // Parse RSS XML - extract <item> elements\n    const items = xml.match(/<item[\\s\\S]*?<\\/item>/gi) || [];\n    const articles = items.slice(0, 10).map(item => {\n      const getTag = (tag) => {\n        const m = item.match(new RegExp('<' + tag + '>(.*?)</' + tag + '>', 's'));\n        return m ? m[1].replace(/<!\\[CDATA\\[|\\]\\]>/g, '').trim() : '';\n      };\n      return {\n        title: getTag('title'),\n        link: getTag('link'),\n        description: getTag('description').substring(0, 500),\n        pubDate: getTag('pubDate'),\n        source: feed.name || feed.url,\n        feedId: feed.id\n      };\n    });\n    \n    allArticles.push(...articles);\n    feedResults.push({ feedId: feed.id, name: feed.name, count: articles.length, status: 'ok' });\n  } catch (err) {\n    feedResults.push({ feedId: feed.id, name: feed.name, count: 0, status: 'error', error: String(err).substring(0, 100) });\n  }\n}\n\nreturn [{ json: { articles: allArticles, feedResults, totalArticles: allArticles.length, feedsProcessed: feedResults.length } }];"
      }
    },
    {
      "id": "a1b2c3d4-0001-4aaa-8001-000000000005",
      "name": "Deduplicate Articles",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [1180, 200],
      "notes": "Check against existing topic_feed entries to find only new articles",
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const articles = $input.first().json.articles || [];\nconst hubUrl = $env.VORLUX_HUB_URL || 'http://localhost:3010';\n\n// Fetch existing topics to deduplicate\nlet existing = new Set();\ntry {\n  const res = await fetch(hubUrl + '/api/content/topics?limit=500', { signal: AbortSignal.timeout(10000) });\n  const data = await res.json();\n  for (const t of (data.data || [])) {\n    existing.add((t.title || '').toLowerCase().trim());\n    if (t.url) existing.add(t.url);\n  }\n} catch {}\n\nconst newArticles = articles.filter(a => {\n  const titleKey = (a.title || '').toLowerCase().trim();\n  if (existing.has(titleKey) || existing.has(a.link)) return false;\n  existing.add(titleKey);\n  existing.add(a.link);\n  return true;\n});\n\nreturn [{ json: { newArticles, newCount: newArticles.length, totalScanned: articles.length, duplicatesSkipped: articles.length - newArticles.length } }];"
      }
    },
    {
      "id": "a1b2c3d4-0001-4aaa-8001-000000000006",
      "name": "Store in Topic Feed",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1420, 100],
      "parameters": {
        "method": "POST",
        "url": "={{$env.VORLUX_HUB_URL}}/api/content/pipeline",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ action: 'batch_ingest', source: 'rss_monitor', articles: $json.newArticles }) }}",
        "options": {
          "timeout": 30000
        }
      }
    },
    {
      "id": "a1b2c3d4-0001-4aaa-8001-000000000007",
      "name": "Discord Notify",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1420, 300],
      "parameters": {
        "method": "POST",
        "url": "={{$env.DISCORD_CONTENT_WEBHOOK}}",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\"embeds\":[{\"title\":\"RSS Monitor: {{ $json.newCount }} new articles found\",\"description\":\"Scanned {{ $json.totalScanned }} articles from feeds\\nDuplicates skipped: {{ $json.duplicatesSkipped }}\",\"color\":5793266,\"footer\":{\"text\":\"RSS Feed Monitor - runs every 2h\"}}]}",
        "options": {
          "timeout": 10000
        }
      }
    }
  ],
  "connections": {
    "Every 2 Hours": {
      "main": [
        [
          {
            "node": "Get Configured Feeds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Configured Feeds": {
      "main": [
        [
          {
            "node": "Has Feeds?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Feeds?": {
      "main": [
        [
          {
            "node": "Fetch Each Feed XML",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Fetch Each Feed XML": {
      "main": [
        [
          {
            "node": "Deduplicate Articles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Deduplicate Articles": {
      "main": [
        [
          {
            "node": "Store in Topic Feed",
            "type": "main",
            "index": 0
          },
          {
            "node": "Discord Notify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "saveExecutionProgress": true
  },
  "tags": [
    { "name": "rss" },
    { "name": "content" },
    { "name": "monitor" }
  ],
  "versionId": "2"
}