{
  "name": "Company News Intelligence Analyzer",
  "nodes": [
    {
      "parameters": {},
      "id": "02140815-edd9-44ad-858b-771917a74dff",
      "name": "When clicking ‘Test workflow’",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        4240,
        -784
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 2
            }
          ]
        }
      },
      "id": "01e88508-3b43-419f-9a05-ab569a33d844",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        4448,
        -608
      ]
    },
    {
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "options": {}
      },
      "id": "70d87a82-a2c3-44c2-8ab4-5529578d32b1",
      "name": "Aggregate Results",
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        6352,
        -704
      ]
    },
    {
      "parameters": {
        "jsCode": "// Build full nested Intelligence Report structure\nconst inputData = $input.first().json.data || $input.all().map(i => i.json);\nconst companyName = $(\"Split In Batches1\").first().json.company_name || \"Company\";\n\nconst report = {\n  company_intelligence_report: {\n    company_name: companyName,\n    executive_summary: { \n      overall_sentiment: \"neutral\", \n      top_event_types: [],\n      article_count: inputData.length \n    },\n    corporate_events: { \n      acquisitions: [], \n      funding_rounds: [], \n      layoffs: [], \n      partnerships: [] \n    },\n    people: { \n      leadership_changes: [], \n      key_people: [] \n    },\n    financial_metrics: {},\n    employees: { \n      headcount_changes: [], \n      hiring_areas: [] \n    },\n    key_insights: [],\n    article_analyses: []\n  }\n};\n\nlet sentimentList = [];\nlet eventSet = new Set();\nlet hiringSet = new Set();\n\ninputData.forEach(item => {\n  const a = item.analysis || {};\n  const art = item.article || {};\n  \n  if (a.sentiment) sentimentList.push(a.sentiment);\n  if (a.event_types) a.event_types.forEach(e => eventSet.add(e));\n  if (a.acquisitions) report.company_intelligence_report.corporate_events.acquisitions.push(...a.acquisitions);\n  if (a.funding) report.company_intelligence_report.corporate_events.funding_rounds.push(a.funding);\n  if (a.layoffs) report.company_intelligence_report.corporate_events.layoffs.push(a.layoffs);\n  if (a.partnerships) report.company_intelligence_report.corporate_events.partnerships.push(...a.partnerships);\n  if (a.leadership_changes) report.company_intelligence_report.people.leadership_changes.push(...a.leadership_changes);\n  if (a.employees?.hiring_areas) a.employees.hiring_areas.forEach(h => hiringSet.add(h));\n  if (a.key_insights) report.company_intelligence_report.key_insights.push(...a.key_insights);\n  \n  if (a.financial_metrics) {\n      Object.assign(report.company_intelligence_report.financial_metrics, a.financial_metrics);\n  }\n\n  report.company_intelligence_report.article_analyses.push({\n    title: art.title,\n    summary: a.summary,\n    url: art.url\n  });\n});\n\n// Final formatting\nreport.company_intelligence_report.executive_summary.top_event_types = Array.from(eventSet);\nreport.company_intelligence_report.employees.hiring_areas = Array.from(hiringSet);\nreport.company_intelligence_report.key_insights = [...new Set(report.company_intelligence_report.key_insights)].slice(0, 10);\n\n// Simple sentiment frequency\nif (sentimentList.length > 0) {\n  const counts = sentimentList.reduce((acc, s) => ({ ...acc, [s]: (acc[s] || 0) + 1 }), {});\n  report.company_intelligence_report.executive_summary.overall_sentiment = Object.keys(counts).reduce((a, b) => counts[a] > counts[b] ? a : b);\n}\n\n// Build Telegram message string\nlet telegramMsg = `<b>🚀 Intelligence Report: ${companyName}</b>\\n`;\ntelegramMsg += `───────────────────\\n`;\ntelegramMsg += `📊 <b>Summary:</b> ${report.company_intelligence_report.executive_summary.overall_sentiment.toUpperCase()} sentiment across ${inputData.length} sources.\\n`;\n\nif (report.company_intelligence_report.corporate_events.layoffs.length > 0) {\n    telegramMsg += `\\n⚠️ <b>Layoffs Detected:</b> Impact reported in news cycle.\\n`;\n}\n\ntelegramMsg += `\\n💡 <b>Top Insights:</b>\\n`;\nreport.company_intelligence_report.key_insights.slice(0, 5).forEach(i => telegramMsg += `• ${i}\\n`);\n\ntelegramMsg += `\\n<a href=\"https://news.google.com/search?q=${encodeURIComponent(companyName)}\">View Full Feed</a>`;\n\nreturn [{ json: { ...report, telegram_message: telegramMsg } }];"
      },
      "id": "b308cb79-9b8e-4543-842f-e88b58ef88c2",
      "name": "Format Intelligence Report",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        6576,
        -704
      ]
    },
    {
      "parameters": {
        "chatId": "-1003540593724",
        "text": "={{ $json.telegram_message }}",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "42dbd800-711e-481f-a307-6cf9351a9614",
      "name": "Telegram",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.1,
      "position": [
        6800,
        -704
      ],
      "webhookId": "4912a3f3-67da-40da-881c-0582a4630174",
      "credentials": {
        "telegramApi": {
          "id": "cBUm2qz5RbGf3sq5",
          "name": "News Analyzer"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// --- DYNAMIC COMPANY LIST ---\nconst companies = ['NVIDIA', 'Microsoft', 'OpenAI', 'Tesla'];\n\nreturn companies.map(name => ({\n  json: {\n    company_name: name,\n    max_articles: 5\n  }\n}));"
      },
      "id": "2ba30de4-8ba6-4860-9929-a3f2c00349b8",
      "name": "Dynamic Company List1",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        4752,
        -704
      ]
    },
    {
      "parameters": {
        "options": {}
      },
      "id": "1f98b0ad-6ee8-4974-bab1-b86c7d486d61",
      "name": "Split In Batches1",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        4992,
        -704
      ]
    },
    {
      "parameters": {
        "url": "=https://news.google.com/rss/search?q={{ encodeURIComponent($json.company_name + ' company news') }}&hl=en-US&gl=US&ceid=US:en",
        "options": {
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        }
      },
      "id": "0d59f527-03ff-4bd4-a4e3-48b04e98e7d3",
      "name": "Fetch Google News RSS1",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        5216,
        -704
      ]
    },
    {
      "parameters": {
        "jsCode": "const rssText = $input.first().json.data;\nconst company = $(\"Split In Batches1\").first().json.company_name;\nconst items = [];\nconst itemRegex = /<item>(.*?)<\\/item>/gs;\nlet match;\n\nif (!rssText) return [];\n\nwhile ((match = itemRegex.exec(rssText)) !== null && items.length < 5) {\n  const itemXml = match[1];\n  const getField = (tag) => {\n    const m = itemXml.match(new RegExp(`<${tag}[^>]*>([\\\\s\\\\S]*?)<\\/${tag}>`, 'i'));\n    return m ? m[1].replace(/<!\\[CDATA\\[|\\]\\]>/g, '').trim() : '';\n  };\n  items.push({ json: { company_name: company, title: getField('title'), url: getField('link'), description: getField('description').replace(/<[^>]+>/g, ' '), source: getField('source') } });\n}\nreturn items;"
      },
      "id": "c0c10487-551a-4030-bbd5-394a672f3caa",
      "name": "Parse RSS Articles1",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        5440,
        -704
      ]
    },
    {
      "parameters": {
        "jsCode": "// Fixed Prompt Generator for full intelligence extraction\nreturn $input.all().map(item => {\n  const article = item.json;\n  const prompt = `You are a corporate intelligence analyst. Analyze news for ${article.company_name}.\nArticle: ${article.title}\nContent: ${article.description}\n\nReturn ONLY a JSON object with this exact structure (use null for unknown values):\n{\n  \"summary\": \"2 sentence summary\",\n  \"event_types\": [\"acquisition\", \"funding\", \"layoff\", \"leadership\", \"partnership\", \"earnings\", \"product\"],\n  \"acquisitions\": [{\"target\": \"name\", \"value\": \"value\"}],\n  \"funding\": {\"round\": \"A/B/C\", \"amount\": \"val\", \"valuation\": \"val\"},\n  \"layoffs\": {\"count\": null, \"reason\": \"str\"},\n  \"leadership_changes\": [{\"person\": \"name\", \"new_role\": \"title\", \"action\": \"appointed/left\"}],\n  \"financial_metrics\": {\"revenue\": \"val\", \"profit\": \"val\", \"market_cap\": \"val\"},\n  \"employees\": {\"headcount_change\": \"increase/decrease\", \"hiring_areas\": [\"tech\", \"sales\"]},\n  \"sentiment\": \"positive/negative/neutral\",\n  \"key_insights\": [\"insight 1\", \"insight 2\"]\n}`;\n\n  return {\n    json: {\n      prompt,\n      article_data: article\n    }\n  };\n});"
      },
      "id": "8e9196a7-3eb5-4225-b2e4-f2519cfc5a2a",
      "name": "Prepare Gemini Prompt1",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        5648,
        -704
      ]
    },
    {
      "parameters": {
        "jsCode": "// Robust Gemini Parser with meta-data recovery\nconst inputJson = $input.first().json;\nconst responseText = inputJson.text || inputJson.output || inputJson.content?.parts?.[0]?.text || \"\";\nconst articleData = $input.first().json.article_data || $item(0).$node[\"Prepare Gemini Prompt1\"].json.article_data;\n\nlet analysis = {};\ntry {\n  const jsonMatch = responseText.match(/\\{[\\s\\S]*\\}/);\n  if (jsonMatch) {\n    const cleaned = jsonMatch[0].replace(/[\\u0000-\\u001F\\u007F-\\u009F]/g, \"\");\n    analysis = JSON.parse(cleaned);\n  } else {\n    analysis = { error: \"No JSON found\", raw: responseText.substring(0, 100) };\n  }\n} catch (e) {\n  analysis = { error: \"Parse failed\", raw: responseText.substring(0, 100) };\n}\n\nreturn [{ json: { article: articleData, analysis } }];"
      },
      "id": "1071cff1-5de5-4860-bb28-eccce5d0d185",
      "name": "Parse Gemini Response1",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        6128,
        -704
      ]
    },
    {
      "parameters": {
        "model": "gemma4:31b-cloud",
        "options": {
          "temperature": 0
        }
      },
      "id": "e9781f1f-6195-4d2f-bd00-cdcbda18e87b",
      "name": "Ollama Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOllama",
      "typeVersion": 1,
      "position": [
        5824,
        -448
      ],
      "credentials": {
        "ollamaApi": {
          "id": "9k920xXzUND3cX1z",
          "name": "Ollama account"
        }
      }
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "gemma4:31b-cloud",
          "mode": "list",
          "cachedResultName": "gemma4:31b-cloud"
        },
        "messages": {
          "values": [
            {
              "content": "={{ $json.prompt }}"
            }
          ]
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.ollama",
      "typeVersion": 1,
      "position": [
        5808,
        -784
      ],
      "id": "e7d89d03-ce2e-4673-b6fb-88359f177a97",
      "name": "Message a model",
      "credentials": {
        "ollamaApi": {
          "id": "9k920xXzUND3cX1z",
          "name": "Ollama account"
        }
      }
    }
  ],
  "pinData": {},
  "connections": {
    "When clicking ‘Test workflow’": {
      "main": [
        [
          {
            "node": "Dynamic Company List1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Dynamic Company List1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Results": {
      "main": [
        [
          {
            "node": "Format Intelligence Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Intelligence Report": {
      "main": [
        [
          {
            "node": "Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dynamic Company List1": {
      "main": [
        [
          {
            "node": "Split In Batches1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split In Batches1": {
      "main": [
        [
          {
            "node": "Fetch Google News RSS1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Aggregate Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Google News RSS1": {
      "main": [
        [
          {
            "node": "Parse RSS Articles1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse RSS Articles1": {
      "main": [
        [
          {
            "node": "Prepare Gemini Prompt1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Gemini Prompt1": {
      "main": [
        [
          {
            "node": "Message a model",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Gemini Response1": {
      "main": [
        [
          {
            "node": "Split In Batches1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Message a model": {
      "main": [
        [
          {
            "node": "Parse Gemini Response1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false
  },
  "versionId": "c3421a8d-f0eb-431f-8665-a36c0bca1bcf",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "e09d1f0f8b9f78e80ac70b6dc8726dd263b0b6ffc4300b0eee3b58f6da316f29"
  },
  "id": "EJsPsu4Y3hPSnemm",
  "tags": [
    {
      "updatedAt": "2026-03-18T22:49:30.672Z",
      "createdAt": "2026-03-18T22:49:30.672Z",
      "id": "w3YWknU07IFxAbCs",
      "name": "News"
    }
  ]
}