8
n8n 한국어amn8n.com

Gemini AI를 사용하여 Discord에 선택된 로컬 뉴스 요약 생성

고급

이것은Content Creation, Multimodal AI분야의자동화 워크플로우로, 20개의 노드를 포함합니다.주로 Code, Sort, Limit, Merge, Discord 등의 노드를 사용하며. 사용자 Gemini AI를 통해 Discord에서 선정된 지역 뉴스 요약 생성

사전 요구사항
  • Discord Bot Token 또는 Webhook
  • 대상 API의 인증 정보가 필요할 수 있음
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "meta": {
    "instanceId": "105694f414213a0eca348284005921253960bd1b0223294a4970522d0da53055",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "e5629011-82f2-4107-967f-91659ee7455f",
      "name": "매일 오전 8시 트리거",
      "type": "n8n-nodes-base.scheduleTrigger",
      "notes": "Change the cron expression to adjust schedule. Current: 8AM daily",
      "position": [
        -400,
        48
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "fb7df187-44df-4e20-bc35-64ef353e6ee0",
      "name": "RSS 피닉스 뉴스 타임즈",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        -192,
        -256
      ],
      "parameters": {
        "url": "https://www.phoenixnewtimes.com/phoenix/Rss.xml",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "9d60cd62-960a-451b-bde1-5543eaef63ae",
      "name": "RSS AZ 프리 뉴스",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        -192,
        -96
      ],
      "parameters": {
        "url": "https://azfreenews.com/feed/",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "6dbf6940-9f45-48be-87f2-1d03727c2f71",
      "name": "RSS Reddit 피닉스",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        -192,
        48
      ],
      "parameters": {
        "url": "https://www.reddit.com/r/Phoenix/.rss",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "6633710a-8742-45f6-b21b-07c800067043",
      "name": "RSS Reddit 스코츠데일",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        -192,
        192
      ],
      "parameters": {
        "url": "https://www.reddit.com/r/Scottsdale/.rss",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "b5248dc3-2541-4ee1-8ae8-342c363963f6",
      "name": "RSS Reddit 애리조나",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        -192,
        336
      ],
      "parameters": {
        "url": "https://www.reddit.com/r/Arizona/.rss",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "834fa6ed-9b2d-433f-b121-f58ff9dba58b",
      "name": "모든 RSS 피드 병합",
      "type": "n8n-nodes-base.merge",
      "position": [
        16,
        48
      ],
      "parameters": {
        "numberInputs": 5
      },
      "typeVersion": 3
    },
    {
      "id": "588b18cf-44a7-42b8-940e-219bb5176cfb",
      "name": "중복 제거 및 준비",
      "type": "n8n-nodes-base.code",
      "position": [
        208,
        48
      ],
      "parameters": {
        "jsCode": "// Deduplicate articles based on URL and prepare for Gemini scoring\nconst items = $input.all();\nconst uniqueArticles = new Map();\nconst locations = ['Phoenix', 'Scottsdale', 'Paradise Valley', 'Arizona', 'Tempe', 'Mesa', 'Chandler'];\n\n// Process and deduplicate\nfor (const item of items) {\n  const url = item.json.link || item.json.url || '';\n  const title = item.json.title || '';\n  const description = item.json.description || item.json.content || item.json.summary || '';\n  const source = item.json.source || 'Unknown';\n  const pubDate = item.json.pubDate || item.json.published || new Date().toISOString();\n  \n  // Create unique key based on URL or title\n  const key = url || title;\n  \n  if (key && !uniqueArticles.has(key)) {\n    // Check if article mentions any of our locations\n    const fullText = `${title} ${description}`.toLowerCase();\n    const mentionsLocation = locations.some(loc => fullText.includes(loc.toLowerCase()));\n    \n    uniqueArticles.set(key, {\n      title: title.substring(0, 200),\n      url: url,\n      description: description.substring(0, 500),\n      source: source,\n      pubDate: pubDate,\n      mentionsLocation: mentionsLocation\n    });\n  }\n}\n\n// Convert to array and return\nconst deduplicatedArticles = Array.from(uniqueArticles.values());\n\n// Sort by date (newest first) and filter to most recent 50 for processing\nconst sortedArticles = deduplicatedArticles\n  .sort((a, b) => new Date(b.pubDate) - new Date(a.pubDate))\n  .slice(0, 50);\n\nreturn sortedArticles.map(article => ({ json: article }));"
      },
      "typeVersion": 2,
      "continueOnFail": true
    },
    {
      "id": "add1c53d-bfb6-4ae7-898d-3205404f96b6",
      "name": "Gemini용 준비",
      "type": "n8n-nodes-base.code",
      "position": [
        416,
        48
      ],
      "parameters": {
        "jsCode": "// Prepare batch of articles for Gemini scoring - ONLY TITLES for efficiency\nconst articles = $input.all().map(item => item.json);\n\n// Create a text summary for Gemini to score - ONLY TITLES to save tokens\nconst titlesText = articles.map((article, index) => {\n  return `${index + 1}. ${article.title}`;\n}).join('\\n');\n\n// Return both the articles and the formatted text\nreturn [{\n  json: {\n    articles: articles,\n    titlesText: titlesText,\n    articlesCount: articles.length\n  }\n}];"
      },
      "typeVersion": 2,
      "continueOnFail": true
    },
    {
      "id": "8e245ef2-dada-4bdf-b0cf-82f36732ae7e",
      "name": "Gemini 관련성 점수 매기기",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "REPLACE YOUR_GEMINI_API_KEY_HERE with your actual Gemini API key",
      "position": [
        608,
        48
      ],
      "parameters": {
        "url": "=https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent?key=YOUR_KEY_HERE",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({\n  \"contents\": [{\n    \"parts\": [{\n      \"text\": \"You are a local news relevance scorer for Phoenix, Scottsdale, and Paradise Valley area. Score the following \" + $json.articlesCount + \" article TITLES based on their local relevance.\\n\\nScore each from 0-100 based on:\\n- Local relevance (50%): Is it about Phoenix/Scottsdale/Paradise Valley?\\n- Community impact (30%): Will locals care?\\n- News value (20%): Is it newsworthy?\\n\\nArticle titles:\\n\" + $json.titlesText + \"\\n\\nReturn ONLY a JSON array with scores in the same order. Example: [85, 72, 45, 90, 33]\\nBe strict - only highly local news should score above 70.\"\n    }]\n  }],\n  \"generationConfig\": {\n    \"temperature\": 0.3,\n    \"topK\": 40,\n    \"topP\": 0.95,\n    \"maxOutputTokens\": 512\n  }\n}) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "8d17b168-d628-403e-8d02-7c28ef911b04",
      "name": "점수 처리",
      "type": "n8n-nodes-base.code",
      "position": [
        816,
        48
      ],
      "parameters": {
        "jsCode": "// Process Gemini response and add scores to articles\nconst geminiResponse = $input.first().json;\nconst preparedData = $('Prepare for Gemini').first().json;\nconst articles = preparedData.articles;\n\n// Extract scores from Gemini response\nlet scores = [];\ntry {\n  // Parse the response from Gemini\n  const responseText = geminiResponse.candidates[0].content.parts[0].text;\n  \n  // Try to extract JSON array from the response\n  const jsonMatch = responseText.match(/\\[.*\\]/s);\n  if (jsonMatch) {\n    scores = JSON.parse(jsonMatch[0]);\n  } else {\n    // Fallback: assign default scores based on location mentions\n    scores = articles.map(article => article.mentionsLocation ? 75 : 50);\n  }\n} catch (error) {\n  console.error('Error parsing Gemini response:', error);\n  // Fallback scoring based on location mentions\n  scores = articles.map(article => article.mentionsLocation ? 75 : 50);\n}\n\n// Combine articles with scores\nconst scoredArticles = articles.map((article, index) => ({\n  ...article,\n  relevanceScore: scores[index] || 50\n}));\n\nreturn scoredArticles.map(article => ({ json: article }));"
      },
      "typeVersion": 2,
      "continueOnFail": true
    },
    {
      "id": "339e1098-65ba-4e89-85e1-9edcd6049ec9",
      "name": "관련성 기준 정렬",
      "type": "n8n-nodes-base.sort",
      "position": [
        1008,
        48
      ],
      "parameters": {
        "options": {},
        "sortFieldsUi": {
          "sortField": [
            {
              "order": "descending",
              "fieldName": "relevanceScore"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "03a00299-fa97-4cb2-8265-d1b0962344a3",
      "name": "상위 5개로 제한",
      "type": "n8n-nodes-base.limit",
      "notes": "Change maxItems to adjust how many articles to send (e.g., 15)",
      "position": [
        1216,
        48
      ],
      "parameters": {
        "maxItems": 5
      },
      "typeVersion": 1
    },
    {
      "id": "1e31fe92-f998-4e72-a8a6-388d0b3db8e1",
      "name": "Discord 메시지 형식 지정",
      "type": "n8n-nodes-base.code",
      "notes": "Using RSS descriptions directly - no additional AI summarization to save tokens",
      "position": [
        1408,
        48
      ],
      "parameters": {
        "jsCode": "// Collect all incoming articles\nconst articles = $input.all().map(item => item.json);\n\n// Get today's date formatted\nconst today = new Date().toLocaleDateString('en-US', { \n  weekday: 'long', \n  year: 'numeric', \n  month: 'long', \n  day: 'numeric' \n});\n\n// Utility: strip HTML tags from text\nfunction stripHtml(html) {\n  return html\n    .replace(/<[^>]*>/g, '')   // remove HTML tags\n    .replace(/\\s+/g, ' ')      // collapse whitespace\n    .trim();\n}\n\n// Build the full digest string\nlet discordMessage = `🌵 **LOCAL NEWS DIGEST** 🌵\\n📅 ${today}\\n${'━'.repeat(40)}\\n\\n`;\n\narticles.forEach((article, index) => {\n  const emoji = index === 0 ? '🥇' : index === 1 ? '🥈' : index === 2 ? '🥉' : `${index + 1}.`;\n  \n  const description = stripHtml(article.description || 'No description available');\n\n  discordMessage += `${emoji} **${article.title}**\\n`;\n  discordMessage += `📍 ${description}\\n`;\n  discordMessage += `🔗 ${article.url}\\n\\n`;\n});\n\ndiscordMessage += `${'━'.repeat(40)}\\n`;\ndiscordMessage += `_Powered by n8n automation | Phoenix • Scottsdale • Paradise Valley_`;\n\n// Discord has a 2000 character limit, so split into multiple messages if necessary\nconst maxLength = 1900; // leave buffer for safety\nconst messages = [];\n\nfor (let i = 0; i < discordMessage.length; i += maxLength) {\n  messages.push(discordMessage.slice(i, i + maxLength));\n}\n\n// Return multiple items (Discord node will send each separately)\nreturn messages.map(msg => ({\n  json: { content: msg }\n}));\n"
      },
      "typeVersion": 2,
      "continueOnFail": true
    },
    {
      "id": "6b23ead3-4d35-451f-b0f2-7e5146dd26a1",
      "name": "Discord로 전송",
      "type": "n8n-nodes-base.discord",
      "notes": "REPLACE with your actual Discord webhook URL",
      "position": [
        1616,
        48
      ],
      "webhookId": "5565d2a2-5e59-43c4-8733-d6b1ca51f509",
      "parameters": {
        "content": "={{ $json.content }}",
        "options": {},
        "authentication": "webhook"
      },
      "credentials": {
        "discordWebhookApi": {
          "id": "6S341y8tVCvOIO8r",
          "name": "All Ops Notis Discord Webhook"
        }
      },
      "typeVersion": 2,
      "continueOnFail": true
    },
    {
      "id": "9983e297-ee82-4fc9-bd87-74f46857afaf",
      "name": "스티커 메모",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        528,
        -336
      ],
      "parameters": {
        "height": 304,
        "content": "## Set Your Gemini API Key. Get for free!\n**Link Below For Example: Get your key at Google AI Studio**\n\nhttps://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent?key=YOUR_KEY_HERE"
      },
      "typeVersion": 1
    },
    {
      "id": "0cb7e7cd-9818-40fd-9444-7a040fe054bf",
      "name": "스티커 메모1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -256,
        -496
      ],
      "parameters": {
        "height": 208,
        "content": "## Set Your News Feeds Here\n**Make sure they are rss**\n\nSee examples below for link structures. There are tools online to help you find RSS feeds for websites. "
      },
      "typeVersion": 1
    },
    {
      "id": "5e83db58-6f66-4e74-b355-e7d32ff6649d",
      "name": "스티커 메모2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1136,
        272
      ],
      "parameters": {
        "height": 112,
        "content": "## Set how many articles you want.\n**Default is 5**\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ef2042de-6862-4981-b195-2dfc11d68df6",
      "name": "스티커 메모3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1328,
        -224
      ],
      "parameters": {
        "height": 192,
        "content": "## Might need changing for other sending locations, telegram whatsapp etc.\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "023096cc-74b9-4c66-91ad-9102f6ba209c",
      "name": "스티커 메모4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1584,
        224
      ],
      "parameters": {
        "height": 112,
        "content": "## Recieve your relevant news articles\n"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "03a00299-fa97-4cb2-8265-d1b0962344a3": {
      "main": [
        [
          {
            "node": "1e31fe92-f998-4e72-a8a6-388d0b3db8e1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8d17b168-d628-403e-8d02-7c28ef911b04": {
      "main": [
        [
          {
            "node": "339e1098-65ba-4e89-85e1-9edcd6049ec9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9d60cd62-960a-451b-bde1-5543eaef63ae": {
      "main": [
        [
          {
            "node": "834fa6ed-9b2d-433f-b121-f58ff9dba58b",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "e5629011-82f2-4107-967f-91659ee7455f": {
      "main": [
        [
          {
            "node": "fb7df187-44df-4e20-bc35-64ef353e6ee0",
            "type": "main",
            "index": 0
          },
          {
            "node": "9d60cd62-960a-451b-bde1-5543eaef63ae",
            "type": "main",
            "index": 0
          },
          {
            "node": "6dbf6940-9f45-48be-87f2-1d03727c2f71",
            "type": "main",
            "index": 0
          },
          {
            "node": "6633710a-8742-45f6-b21b-07c800067043",
            "type": "main",
            "index": 0
          },
          {
            "node": "b5248dc3-2541-4ee1-8ae8-342c363963f6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "339e1098-65ba-4e89-85e1-9edcd6049ec9": {
      "main": [
        [
          {
            "node": "03a00299-fa97-4cb2-8265-d1b0962344a3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "add1c53d-bfb6-4ae7-898d-3205404f96b6": {
      "main": [
        [
          {
            "node": "8e245ef2-dada-4bdf-b0cf-82f36732ae7e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b5248dc3-2541-4ee1-8ae8-342c363963f6": {
      "main": [
        [
          {
            "node": "834fa6ed-9b2d-433f-b121-f58ff9dba58b",
            "type": "main",
            "index": 4
          }
        ]
      ]
    },
    "6dbf6940-9f45-48be-87f2-1d03727c2f71": {
      "main": [
        [
          {
            "node": "834fa6ed-9b2d-433f-b121-f58ff9dba58b",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "834fa6ed-9b2d-433f-b121-f58ff9dba58b": {
      "main": [
        [
          {
            "node": "588b18cf-44a7-42b8-940e-219bb5176cfb",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "588b18cf-44a7-42b8-940e-219bb5176cfb": {
      "main": [
        [
          {
            "node": "add1c53d-bfb6-4ae7-898d-3205404f96b6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fb7df187-44df-4e20-bc35-64ef353e6ee0": {
      "main": [
        [
          {
            "node": "834fa6ed-9b2d-433f-b121-f58ff9dba58b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6633710a-8742-45f6-b21b-07c800067043": {
      "main": [
        [
          {
            "node": "834fa6ed-9b2d-433f-b121-f58ff9dba58b",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "1e31fe92-f998-4e72-a8a6-388d0b3db8e1": {
      "main": [
        [
          {
            "node": "6b23ead3-4d35-451f-b0f2-7e5146dd26a1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8e245ef2-dada-4bdf-b0cf-82f36732ae7e": {
      "main": [
        [
          {
            "node": "8d17b168-d628-403e-8d02-7c28ef911b04",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

고급 - 콘텐츠 제작, 멀티모달 AI

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수20
카테고리2
노드 유형9
난이도 설명

고급 사용자를 위한 16+개 노드의 복잡한 워크플로우

저자
Kaden Reese

Kaden Reese

@kadenreese

I started automating with Python in 2020 and still use it in workflows when needed, but I’ve recently leaned into n8n for client-facing solutions. Lately I’ve focused on real estate automations, though I also build workflows for email, scraping, and other use cases. Currently Building 👇🏻

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34