{
  "id": "giCidC755VfFMJMj",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Create daily AI news digest and send to Telegram",
  "tags": [],
  "nodes": [
    {
      "id": "80ab307e-e246-49ed-92f7-eee1c496f1b0",
      "name": "Daily 8 AM Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -432,
        160
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "b4f855a8-69b1-42a6-9bf3-27688b21fcde",
      "name": "Workflow Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        -208,
        160
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "newsSource1Url",
              "type": "string",
              "value": "https://news.google.com/rss/search?q=artificial+intelligence&hl=en-US&gl=US&ceid=US:en"
            },
            {
              "id": "id-2",
              "name": "newsSource2Url",
              "type": "string",
              "value": "https://www.theverge.com/rss/ai-artificial-intelligence/index.xml"
            },
            {
              "id": "id-3",
              "name": "newsSource3Url",
              "type": "string",
              "value": "https://techcrunch.com/category/artificial-intelligence/feed/"
            },
            {
              "id": "id-4",
              "name": "telegramChatId",
              "type": "string",
              "value": "<__PLACEHOLDER_VALUE__Your Telegram Chat ID__>"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "271dcf62-755d-4ebc-96cf-7c084d140fc2",
      "name": "Fetch AI News Source 1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        16,
        -32
      ],
      "parameters": {
        "url": "={{ $('Workflow Configuration').first().json.newsSource1Url }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "typeVersion": 4.2,
      "continueOnFail": true
    },
    {
      "id": "e030ed22-de8f-4904-ad13-f9e75c22ef9a",
      "name": "Fetch AI News Source 2",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        16,
        160
      ],
      "parameters": {
        "url": "={{ $('Workflow Configuration').first().json.newsSource2Url }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "typeVersion": 4.2,
      "continueOnFail": true
    },
    {
      "id": "49ff1fe2-71e9-41bf-94e9-482c06c25a8c",
      "name": "Fetch AI News Source 3",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        16,
        352
      ],
      "parameters": {
        "url": "={{ $('Workflow Configuration').first().json.newsSource3Url }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "typeVersion": 4.2,
      "continueOnFail": true
    },
    {
      "id": "9554da09-b7b4-416a-8367-88297e6f7960",
      "name": "Aggregate and Rank News",
      "type": "n8n-nodes-base.code",
      "position": [
        240,
        160
      ],
      "parameters": {
        "jsCode": "// Aggregate all news items from the three sources\nconst allNews = [];\n\n// Helper function to extract text from XML-like content\nfunction extractText(content, tag) {\n  const regex = new RegExp(`<${tag}[^>]*>([\\\\s\\\\S]*?)</${tag}>`, 'i');\n  const match = content.match(regex);\n  if (match) {\n    // Remove CDATA wrapper if present\n    let text = match[1].replace(/<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>/g, '$1');\n    // Remove HTML tags\n    text = text.replace(/<[^>]+>/g, '');\n    return text.trim();\n  }\n  return '';\n}\n\n// Helper function to extract link from RSS item\nfunction extractLink(itemContent) {\n  // Try standard link tag\n  let link = extractText(itemContent, 'link');\n  if (link) return link;\n  \n  // Try guid if it looks like a URL\n  let guid = extractText(itemContent, 'guid');\n  if (guid && guid.startsWith('http')) return guid;\n  \n  return '';\n}\n\n// Collect items from all input sources\nfor (const item of $input.all()) {\n  const data = item.json;\n  \n  // Skip error responses\n  if (!data || data.error) continue;\n  \n  // Check if it's RSS/XML format (string response)\n  if (typeof data === 'string' || data.data) {\n    const xmlContent = typeof data === 'string' ? data : data.data;\n    if (typeof xmlContent === 'string' && xmlContent.includes('<item>')) {\n      // Parse RSS items\n      const itemRegex = /<item>([\\s\\S]*?)<\\/item>/gi;\n      let match;\n      while ((match = itemRegex.exec(xmlContent)) !== null) {\n        const itemContent = match[1];\n        const title = extractText(itemContent, 'title');\n        const description = extractText(itemContent, 'description') || extractText(itemContent, 'content:encoded');\n        const link = extractLink(itemContent);\n        const pubDate = extractText(itemContent, 'pubDate');\n        const source = extractText(itemContent, 'source') || 'RSS Feed';\n        \n        if (title) {\n          allNews.push({\n            title: title,\n            description: description.substring(0, 300) + (description.length > 300 ? '...' : ''),\n            link: link,\n            source: source,\n            publishedAt: pubDate || new Date().toISOString()\n          });\n        }\n      }\n    }\n  }\n  // Check if it's JSON API format (NewsAPI style)\n  else if (data.articles && Array.isArray(data.articles)) {\n    data.articles.forEach(article => {\n      allNews.push({\n        title: article.title || '',\n        description: (article.description || article.summary || '').substring(0, 300),\n        link: article.url || article.link || '',\n        source: article.source?.name || article.source || 'Unknown',\n        publishedAt: article.publishedAt || article.pubDate || new Date().toISOString()\n      });\n    });\n  }\n  // Check if it's a single article object\n  else if (data.title) {\n    allNews.push({\n      title: data.title || '',\n      description: (data.description || data.summary || '').substring(0, 300),\n      link: data.url || data.link || '',\n      source: data.source?.name || data.source || 'Unknown',\n      publishedAt: data.publishedAt || data.pubDate || new Date().toISOString()\n    });\n  }\n}\n\n// Remove duplicates based on title\nconst seen = new Set();\nconst uniqueNews = allNews.filter(item => {\n  const key = item.title.toLowerCase().trim();\n  if (seen.has(key)) return false;\n  seen.add(key);\n  return true;\n});\n\n// Rank by recency (most recent first)\nuniqueNews.sort((a, b) => {\n  const dateA = new Date(a.publishedAt);\n  const dateB = new Date(b.publishedAt);\n  return dateB - dateA;\n});\n\n// Get top 5 stories\nconst top5News = uniqueNews.slice(0, 5);\n\n// Return the top 5 stories\nreturn top5News.map(article => ({\n  json: {\n    title: article.title,\n    description: article.description,\n    link: article.link,\n    source: article.source,\n    publishedAt: article.publishedAt\n  }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "d3903770-607d-4be5-b299-c79c97bf7e5a",
      "name": "AI News Summarizer Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        464,
        160
      ],
      "parameters": {
        "text": "You are an AI news summarizer. Analyze the top 5 AI news stories provided and create concise, engaging summaries for each. Return the data in the structured format defined by the output parser. Include story titles, summaries, and links.",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "58fba4c9-4c2f-4e8d-913d-c6056166cd6f",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        480,
        384
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "b0a0ac4c-d2d6-46b8-bc65-8061c717ebf0",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        608,
        384
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\t\"stories\": [\n\t\t{\n\t\t\t\"title\": \"AI Breakthrough in Healthcare\",\n\t\t\t\"summary\": \"Researchers develop new AI model for disease detection\",\n\t\t\t\"link\": \"https://example.com/article1\"\n\t\t},\n\t\t{\n\t\t\t\"title\": \"OpenAI Releases New Model\",\n\t\t\t\"summary\": \"Latest GPT model shows improved reasoning\",\n\t\t\t\"link\": \"https://example.com/article2\"\n\t\t}\n\t],\n\t\"imagePrompt\": \"A futuristic AI-themed illustration representing today's top AI news\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "e7753d4f-9eef-40d9-a585-8ee716cd63f2",
      "name": "Generate AI Image",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        816,
        160
      ],
      "parameters": {
        "prompt": "={{ $json.output.imagePrompt }}",
        "options": {
          "size": "1024x1024",
          "dalleQuality": "standard"
        },
        "resource": "image"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "29f0025e-0a06-418a-89ef-8ad6caaa3567",
      "name": "Format Telegram Message",
      "type": "n8n-nodes-base.code",
      "position": [
        1040,
        160
      ],
      "parameters": {
        "jsCode": "// Get the structured output from AI Agent\nconst agentOutput = $('AI News Summarizer Agent').first().json.output;\nconst imageData = $input.first().json.data;\n\n// Build Telegram message with emojis\nlet message = '\ud83e\udd16 *Daily AI News Digest*\\n';\nmessage += '\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\\n\\n';\n\nif (agentOutput && agentOutput.stories) {\n  agentOutput.stories.forEach((story, index) => {\n    const emoji = ['\ud83d\udd39', '\ud83d\udd38', '\ud83d\udca1', '\ud83d\ude80', '\u26a1'][index] || '\ud83d\udcf0';\n    message += `${emoji} *${story.title}*\\n`;\n    message += `${story.summary}\\n`;\n    message += `\ud83d\udd17 [Read more](${story.link})\\n\\n`;\n  });\n}\n\nmessage += '\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\\n';\nmessage += `\ud83d\udcc5 ${new Date().toLocaleDateString('ja-JP', { year: 'numeric', month: 'long', day: 'numeric' })}`;\n\nreturn [\n  {\n    json: {\n      telegramMessage: message,\n      imageUrl: imageData && imageData[0] ? imageData[0].url : null\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "5582fe93-f675-4350-99c4-5a22081ed5cf",
      "name": "Send to Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1264,
        160
      ],
      "parameters": {
        "file": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $json.imageUrl }}"
        },
        "chatId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Workflow Configuration').first().json.telegramChatId }}"
        },
        "operation": "sendPhoto",
        "additionalFields": {
          "caption": "={{ $json.telegramMessage }}",
          "parse_mode": "Markdown"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "45b1b8d2-fc34-4198-992e-157e6405690f",
      "name": "Chat AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -208,
        688
      ],
      "parameters": {
        "text": "You are a helpful AI assistant that can discuss the latest AI news. Answer questions about AI developments, trends, and stories. Be informative and engaging.",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "227555e4-2f69-4ef6-8fe6-ac8ba4bcd9e5",
      "name": "OpenAI Chat Model for Chat",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -208,
        912
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e61ad8d7-5780-4c44-b8d1-4ed02922d3d3",
      "name": "Window Buffer Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        -80,
        912
      ],
      "parameters": {
        "contextWindowLength": 40
      },
      "typeVersion": 1.3
    },
    {
      "id": "sticky-config-main",
      "name": "\u8a2d\u5b9a\u30ac\u30a4\u30c9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1168,
        -320
      ],
      "parameters": {
        "width": 464,
        "height": 732,
        "content": "\n## \ud83e\udd16 Daily AI News Digest + Chat\nThis workflow acts as your personal AI news editor. It scrapes the latest headlines, summarizes them using an AI Agent, generates a cover image, and delivers a briefing to Telegram every morning.\n\n### \ud83d\udcdd How it works\n1. **Trigger:** Runs automatically every day at 8:00 AM.\n2. **Fetch:** Pulls RSS feeds from Google News, The Verge, and TechCrunch.\n3. **Process:** De-duplicates and ranks stories to find the \"Top 5\".\n4. **AI Agent:** Summarizes the stories and writes a prompt for an image.\n5. **Generate:** DALL-E creates a visual based on the news topics.\n6. **Deliver:** Sends a formatted digest to your Telegram.\n7. **Chat:** (Bottom flow) Allows you to ask follow-up questions via the n8n Chat interface.\n\n### \u2699\ufe0f Setup Guide\n1. **Credentials:**\n   - OpenAI API (for GPT & DALL-E)\n   - Telegram API (for the bot)\n2. **Configuration:**\n   - Open the node named **`Workflow Configuration`**.\n   - Enter your **`telegramChatId`**.\n   *(To get ID: Message `@userinfobot` on Telegram)*\n"
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-credentials",
      "name": "\u8a8d\u8a3c\u60c5\u5831",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        432,
        -16
      ],
      "parameters": {
        "color": 7,
        "width": 504,
        "height": 524,
        "content": "## 3\ufe0f\u20e3 AI Analysis & Art\nThe **AI Agent** reads the top 5 stories and creates a concise summary using LangChain.\nIt also generates a descriptive prompt for **DALL-E 3** to create a unique header image for today's news.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-flow-explain",
      "name": "\u30d5\u30ed\u30fc\u8aac\u660e",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -496,
        -16
      ],
      "parameters": {
        "color": 7,
        "width": 408,
        "height": 332,
        "content": "## 1\ufe0f\u20e3 Configuration\n**Start here!**\nOpen this node to set your **Telegram Chat ID**.\nYou can also customize the RSS feed URLs here if you want to track different news sources (e.g., Crypto, Finance).\n"
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-chat-explain",
      "name": "\u30c1\u30e3\u30c3\u30c8\u8aac\u660e",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -528,
        544
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 520,
        "content": "## \ud83d\udcac Interactive Chat Mode\nThis section is separate from the daily automation.\nIt allows you to use the **\"Chat\"** button in n8n to talk to an AI Assistant about the news. It uses Window Buffer Memory to remember the context of your conversation."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-news-sources",
      "name": "\u30cb\u30e5\u30fc\u30b9\u30bd\u30fc\u30b9\u4e00\u89a7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 808,
        "content": "## 2\ufe0f\u20e3 Fetch & Rank\nWe fetch data from 3 different RSS sources.\nThe **Code Node** then:\n- Parses the XML/RSS data.\n- Removes duplicate stories.\n- Sorts by the most recent date.\n- Pick the top 5 articles.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "16a3c03b-7dad-48fe-8448-9044ca171655",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        -464,
        688
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    }
  ],
  "active": false,
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "5f0a4f5e-17bb-4217-aa99-66dbaf08d2d7",
  "connections": {
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Chat AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate AI Image": {
      "main": [
        [
          {
            "node": "Format Telegram Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI News Summarizer Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Daily 8 AM Trigger": {
      "main": [
        [
          {
            "node": "Workflow Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Window Buffer Memory": {
      "ai_memory": [
        [
          {
            "node": "Chat AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Fetch AI News Source 1": {
      "main": [
        [
          {
            "node": "Aggregate and Rank News",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch AI News Source 2": {
      "main": [
        [
          {
            "node": "Aggregate and Rank News",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch AI News Source 3": {
      "main": [
        [
          {
            "node": "Aggregate and Rank News",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Workflow Configuration": {
      "main": [
        [
          {
            "node": "Fetch AI News Source 1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch AI News Source 2",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch AI News Source 3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate and Rank News": {
      "main": [
        [
          {
            "node": "AI News Summarizer Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Telegram Message": {
      "main": [
        [
          {
            "node": "Send to Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI News Summarizer Agent": {
      "main": [
        [
          {
            "node": "Generate AI Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI News Summarizer Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model for Chat": {
      "ai_languageModel": [
        [
          {
            "node": "Chat AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}