This workflow corresponds to n8n.io template #8991 — we link there as the canonical source.
This workflow follows the Discord → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "e5629011-82f2-4107-967f-91659ee7455f",
"name": "Daily 8AM Trigger",
"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 Phoenix New Times",
"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 Free News",
"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 Phoenix",
"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 Scottsdale",
"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 Arizona",
"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": "Merge All RSS Feeds",
"type": "n8n-nodes-base.merge",
"position": [
16,
48
],
"parameters": {
"numberInputs": 5
},
"typeVersion": 3
},
{
"id": "588b18cf-44a7-42b8-940e-219bb5176cfb",
"name": "Deduplicate & Prepare",
"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": "Prepare for 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 Relevance Scoring",
"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": "Process Scores",
"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": "Sort by Relevance",
"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": "Limit to Top 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": "Format Discord Message",
"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 = `\ud83c\udf35 **LOCAL NEWS DIGEST** \ud83c\udf35\\n\ud83d\udcc5 ${today}\\n${'\u2501'.repeat(40)}\\n\\n`;\n\narticles.forEach((article, index) => {\n const emoji = index === 0 ? '\ud83e\udd47' : index === 1 ? '\ud83e\udd48' : index === 2 ? '\ud83e\udd49' : `${index + 1}.`;\n \n const description = stripHtml(article.description || 'No description available');\n\n discordMessage += `${emoji} **${article.title}**\\n`;\n discordMessage += `\ud83d\udccd ${description}\\n`;\n discordMessage += `\ud83d\udd17 ${article.url}\\n\\n`;\n});\n\ndiscordMessage += `${'\u2501'.repeat(40)}\\n`;\ndiscordMessage += `_Powered by n8n automation | Phoenix \u2022 Scottsdale \u2022 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": "Send to Discord",
"type": "n8n-nodes-base.discord",
"notes": "REPLACE with your actual Discord webhook URL",
"position": [
1616,
48
],
"parameters": {
"content": "={{ $json.content }}",
"options": {},
"authentication": "webhook"
},
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
},
"typeVersion": 2,
"continueOnFail": true
},
{
"id": "9983e297-ee82-4fc9-bd87-74f46857afaf",
"name": "Sticky Note",
"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": "Sticky Note1",
"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": "Sticky Note2",
"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": "Sticky Note3",
"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": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1584,
224
],
"parameters": {
"height": 112,
"content": "## Recieve your relevant news articles\n"
},
"typeVersion": 1
}
],
"connections": {
"Limit to Top 5": {
"main": [
[
{
"node": "Format Discord Message",
"type": "main",
"index": 0
}
]
]
},
"Process Scores": {
"main": [
[
{
"node": "Sort by Relevance",
"type": "main",
"index": 0
}
]
]
},
"RSS AZ Free News": {
"main": [
[
{
"node": "Merge All RSS Feeds",
"type": "main",
"index": 1
}
]
]
},
"Daily 8AM Trigger": {
"main": [
[
{
"node": "RSS Phoenix New Times",
"type": "main",
"index": 0
},
{
"node": "RSS AZ Free News",
"type": "main",
"index": 0
},
{
"node": "RSS Reddit Phoenix",
"type": "main",
"index": 0
},
{
"node": "RSS Reddit Scottsdale",
"type": "main",
"index": 0
},
{
"node": "RSS Reddit Arizona",
"type": "main",
"index": 0
}
]
]
},
"Sort by Relevance": {
"main": [
[
{
"node": "Limit to Top 5",
"type": "main",
"index": 0
}
]
]
},
"Prepare for Gemini": {
"main": [
[
{
"node": "Gemini Relevance Scoring",
"type": "main",
"index": 0
}
]
]
},
"RSS Reddit Arizona": {
"main": [
[
{
"node": "Merge All RSS Feeds",
"type": "main",
"index": 4
}
]
]
},
"RSS Reddit Phoenix": {
"main": [
[
{
"node": "Merge All RSS Feeds",
"type": "main",
"index": 2
}
]
]
},
"Merge All RSS Feeds": {
"main": [
[
{
"node": "Deduplicate & Prepare",
"type": "main",
"index": 0
}
]
]
},
"Deduplicate & Prepare": {
"main": [
[
{
"node": "Prepare for Gemini",
"type": "main",
"index": 0
}
]
]
},
"RSS Phoenix New Times": {
"main": [
[
{
"node": "Merge All RSS Feeds",
"type": "main",
"index": 0
}
]
]
},
"RSS Reddit Scottsdale": {
"main": [
[
{
"node": "Merge All RSS Feeds",
"type": "main",
"index": 3
}
]
]
},
"Format Discord Message": {
"main": [
[
{
"node": "Send to Discord",
"type": "main",
"index": 0
}
]
]
},
"Gemini Relevance Scoring": {
"main": [
[
{
"node": "Process Scores",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
discordWebhookApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Stay on top of what’s happening in your community without drowning in endless RSS feeds.
Source: https://n8n.io/workflows/8991/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Automatically fetch, rank, and summarize the top financial stories from curated RSS feeds each day, then deliver a concise AI-written digest to Telegram and log the run to Google Sheets. Runs on a dai
Automatically collect, analyze, and store industry news articles with intelligent filtering and dual-database storage
Huggingface. Uses discord, httpRequest, itemLists. Scheduled trigger; 11 nodes.
This comprehensive n8n automation template orchestrates a complete end-to-end workflow for generating engaging short-form Point-of-View (POV) style videos using multiple AI services and automatically
This workflow helps you repurpose your YouTube videos across multiple social media platforms with zero manual effort. It’s designed for creators, businesses, and marketers who want to maximize reach w