This workflow follows the HTTP Request → Notion 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 →
{
"name": "Raindrop Knowledge Management",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 30
}
]
}
},
"id": "6c84895f-7e29-4776-afc5-c6e290b13fc6",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
-1680,
400
]
},
{
"parameters": {
"url": "https://api.raindrop.io/rest/v1/raindrops/0",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "raindropOAuth2Api",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "sort",
"value": "-created"
},
{
"name": "perpage",
"value": "10"
}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "261cd63d-97ef-44dd-9899-7f0080689f77",
"name": "\u53d6\u5f97 Raindrop \u6536\u85cf",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
-1460,
400
],
"credentials": {
"raindropOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// 30\u5206\u9418\u89f8\u767c\u5c0d\u61c9\u7684\u7be9\u9078\u908f\u8f2f\nconst items = $input.all();\nconst response = items[0].json;\nconst newItems = [];\n\n// \u89f8\u767c\u9593\u9694 30 \u5206\u9418\uff0c\u6642\u9593\u7a97\u53e3\u8a2d\u70ba 35 \u5206\u9418\uff08\u591a 5 \u5206\u9418\u7de9\u885d\uff09\nconst scheduleInterval = 30; // \u5206\u9418\nconst timeWindow = (scheduleInterval + 5) * 60 * 1000; // 35 \u5206\u9418\nconst cutoffTime = Date.now() - timeWindow;\n\nconsole.log(`\u6aa2\u67e5 ${response.items?.length || 0} \u500b\u6536\u85cf\u9805\u76ee`);\nconsole.log(`\u6642\u9593\u7a97\u53e3\uff1a\u6700\u8fd1 ${scheduleInterval + 5} \u5206\u9418`);\nconsole.log(`\u622a\u6b62\u6642\u9593\uff1a${new Date(cutoffTime).toLocaleString('zh-TW')}`);\n\n// \u6309\u5efa\u7acb\u6642\u9593\u6392\u5e8f\uff0c\u6700\u65b0\u7684\u5728\u524d\u9762\nconst sortedItems = (response.items || []).sort((a, b) => {\n return new Date(b.created).getTime() - new Date(a.created).getTime();\n});\n\nfor (const item of sortedItems) {\n const createdTime = new Date(item.created).getTime();\n const minutesAgo = Math.round((Date.now() - createdTime) / (60 * 1000));\n \n if (createdTime > cutoffTime) {\n newItems.push({\n id: item._id,\n title: item.title || '\u7121\u6a19\u984c',\n link: item.link,\n excerpt: item.excerpt || '',\n tags: item.tags || [],\n created: item.created,\n domain: item.domain || '',\n type: item.type || 'link',\n minutesAgo: minutesAgo\n });\n \n console.log(`\u2705 \u65b0\u9805\u76ee\uff1a${item.title} (${minutesAgo} \u5206\u9418\u524d)`);\n } else {\n console.log(`\u23ed\ufe0f \u8df3\u904e\u820a\u9805\u76ee\uff1a${item.title} (${minutesAgo} \u5206\u9418\u524d\uff0c\u8d85\u904e 35 \u5206\u9418)`);\n }\n}\n\n// \u9650\u5236\u6bcf\u6b21\u6700\u591a\u8655\u7406 5 \u500b\u9805\u76ee\uff08\u907f\u514d\u7a81\u7136\u5927\u91cf\u8655\u7406\uff09\nconst maxItems = 5;\nconst finalItems = newItems.slice(0, maxItems);\n\nif (finalItems.length < newItems.length) {\n console.log(`\ud83d\udcdd \u9650\u5236\u8655\u7406\u6578\u91cf\uff1a${finalItems.length}/${newItems.length} \u500b\u9805\u76ee`);\n}\n\nif (finalItems.length === 0) {\n console.log('\ud83d\udced \u6c92\u6709\u7b26\u5408\u6642\u9593\u7a97\u53e3\u7684\u65b0\u6536\u85cf\u9805\u76ee');\n return [];\n}\n\nconsole.log(`\ud83c\udfaf \u767c\u73fe ${finalItems.length} \u500b\u65b0\u9805\u76ee\u6e96\u5099\u8655\u7406`);\nreturn finalItems.map(item => ({ json: item }));"
},
"id": "dff50a0b-e500-424f-a30c-6520a1fcb180",
"name": "\u7be9\u9078\u65b0\u9805\u76ee",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-1240,
400
]
},
{
"parameters": {
"jsCode": "// \u8655\u7406\u5167\u5bb9 - \u652f\u63f4\u591a\u7b46\u8cc7\u6599\u8655\u7406\nconst items = $input.all();\nconst results = [];\n\nconsole.log(`\ud83d\udcc4 \u6e96\u5099\u8655\u7406 ${items.length} \u500b\u9805\u76ee\u7684\u5167\u5bb9`);\n\n// \u5f37\u5316\u7684\u6587\u672c\u6e05\u7406\u51fd\u6578 - \u5c08\u9580\u8655\u7406 JSON \u76f8\u5bb9\u6027\nfunction sanitizeForJson(text) {\n if (!text) return '';\n \n return text\n // \u79fb\u9664\u6240\u6709\u63a7\u5236\u5b57\u7b26\n .replace(/[\\u0000-\\u001F\\u007F-\\u009F]/g, '')\n // \u8655\u7406 JSON \u7279\u6b8a\u5b57\u7b26\n .replace(/\\\\/g, '\\\\\\\\') // \u53cd\u659c\u7dda\n .replace(/\"/g, '\\\\\"') // \u96d9\u5f15\u865f\n .replace(/'/g, \"\\\\'\") // \u55ae\u5f15\u865f\n // \u7d71\u4e00\u8655\u7406\u63db\u884c\u548c\u7a7a\u767d\n .replace(/[\\r\\n\\t]/g, ' ')\n .replace(/\\s+/g, ' ')\n // \u79fb\u9664 Markdown \u7279\u6b8a\u7b26\u865f\uff08\u4fdd\u7559\u5167\u5bb9\uff09\n .replace(/^#+\\s*/gm, '') // \u79fb\u9664 # \u6a19\u984c\u7b26\u865f\n .replace(/\\*\\*(.*?)\\*\\*/g, '$1') // \u79fb\u9664\u7c97\u9ad4\u6a19\u8a18\n .replace(/\\*(.*?)\\*/g, '$1') // \u79fb\u9664\u659c\u9ad4\u6a19\u8a18\n .replace(/`(.*?)`/g, '$1') // \u79fb\u9664\u7a0b\u5f0f\u78bc\u6a19\u8a18\n .replace(/---+/g, '') // \u79fb\u9664\u5206\u9694\u7dda\n // \u6e05\u7406\u591a\u9918\u7b26\u865f\n .replace(/[{}[\\]]/g, '') // \u79fb\u9664\u5927\u62ec\u865f\u548c\u4e2d\u62ec\u865f\n .trim();\n}\n\n// HTML \u6e05\u7406\u51fd\u6578\nfunction cleanHtml(html) {\n if (!html) return '';\n \n return html\n .replace(/<script[^>]*>[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<style[^>]*>[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<nav[^>]*>[\\s\\S]*?<\\/nav>/gi, '')\n .replace(/<footer[^>]*>[\\s\\S]*?<\\/footer>/gi, '')\n .replace(/<aside[^>]*>[\\s\\S]*?<\\/aside>/gi, '')\n .replace(/<header[^>]*>[\\s\\S]*?<\\/header>/gi, '')\n .replace(/<div[^>]*class=\"[^\"]*ad[^\"]*\"[^>]*>[\\s\\S]*?<\\/div>/gi, '')\n .replace(/<[^>]*>/g, ' ')\n .replace(/ /g, ' ')\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/\\s+/g, ' ')\n .replace(/\\n+/g, '\\n')\n .trim();\n}\n\nfunction extractTitle(html) {\n const titleMatches = [\n html.match(/<title[^>]*>([^<]+)<\\/title>/i),\n html.match(/<h1[^>]*>([^<]+)<\\/h1>/i),\n html.match(/<meta[^>]*property=\"og:title\"[^>]*content=\"([^\"]+)\"/i)\n ];\n \n for (const match of titleMatches) {\n if (match && match[1] && match[1].trim()) {\n return match[1].trim().replace(/\\s+/g, ' ');\n }\n }\n return '';\n}\n\nfunction extractDescription(html) {\n const descMatches = [\n html.match(/<meta[^>]*name=\"description\"[^>]*content=\"([^\"]+)\"/i),\n html.match(/<meta[^>]*property=\"og:description\"[^>]*content=\"([^\"]+)\"/i)\n ];\n \n for (const match of descMatches) {\n if (match && match[1] && match[1].trim()) {\n return match[1].trim().replace(/\\s+/g, ' ');\n }\n }\n return '';\n}\n\nfunction detectContentType(url, content, domain) {\n const lowerContent = (content || '').toLowerCase();\n const lowerDomain = (domain || '').toLowerCase();\n \n if (lowerDomain.includes('reddit.com')) return '\u793e\u7fa4\u8a0e\u8ad6';\n if (lowerDomain.includes('github.com')) return '\u958b\u6e90\u5c08\u6848';\n if (lowerDomain.includes('medium.com') || lowerDomain.includes('dev.to')) return '\u6280\u8853\u6587\u7ae0';\n if (lowerDomain.includes('stackoverflow.com')) return '\u6280\u8853\u554f\u7b54';\n if (lowerDomain.includes('youtube.com') || lowerDomain.includes('youtu.be')) return '\u5f71\u7247\u6559\u5b78';\n if (lowerDomain.includes('twitter.com') || lowerDomain.includes('x.com')) return '\u793e\u7fa4\u8a0e\u8ad6';\n if (lowerDomain.includes('facebook.com')) return '\u793e\u7fa4\u8a0e\u8ad6';\n \n if (lowerContent.includes('tutorial') || lowerContent.includes('\u6559\u5b78')) return '\u6559\u5b78';\n if (lowerContent.includes('tool') || lowerContent.includes('\u5de5\u5177')) return '\u5de5\u5177';\n if (lowerContent.includes('news') || lowerContent.includes('\u65b0\u805e')) return '\u65b0\u805e';\n \n return '\u6280\u8853\u6587\u7ae0';\n}\n\n// \u8655\u7406\u6bcf\u500b\u9805\u76ee\nfor (let i = 0; i < items.length; i++) {\n const item = items[i].json;\n const html = item.data || '';\n const originalData = items[i].json; // \u73fe\u5728\u5c31\u662f\u7576\u524d\u9805\u76ee\u7684\u8cc7\u6599\n\n console.log(`\\n\ud83d\udcc4 \u8655\u7406\u9805\u76ee ${i + 1}/${items.length}\uff1a${originalData.title}`);\n console.log(`\ud83d\udcca \u6293\u53d6\u72c0\u614b\uff1a${item.fetchSuccess ? '\u6210\u529f' : '\u5931\u6557'}`);\n\n // \u5982\u679c\u6293\u53d6\u5931\u6557\uff0c\u4f7f\u7528 Raindrop \u63d0\u4f9b\u7684\u8cc7\u8a0a\n if (!item.fetchSuccess && item.usedFallback) {\n console.log(`\ud83d\udcdd \u4f7f\u7528 Raindrop \u6458\u8981\u4f5c\u70ba\u5167\u5bb9`);\n \n results.push({\n json: {\n // \u539f\u59cb\u8cc7\u6599\n id: originalData.id,\n title: sanitizeForJson(originalData.title || '\u7121\u6a19\u984c'),\n link: originalData.link,\n tags: originalData.tags || [],\n domain: originalData.domain,\n created: originalData.created,\n raindropExcerpt: sanitizeForJson(originalData.excerpt || ''),\n \n // \u8655\u7406\u5f8c\u7684\u5167\u5bb9\n cleanContent: sanitizeForJson(originalData.excerpt || '\u7121\u6cd5\u53d6\u5f97\u5167\u5bb9\uff0c\u8acb\u76f4\u63a5\u67e5\u770b\u539f\u59cb\u9023\u7d50'),\n metaDescription: sanitizeForJson(originalData.excerpt || ''),\n webTitle: sanitizeForJson(originalData.title || ''),\n \n // \u5167\u5bb9\u5206\u6790\n contentLength: (originalData.excerpt || '').length,\n estimatedReadTime: 2, // \u9810\u8a2d 2 \u5206\u9418\n detectedType: detectContentType(originalData.link, originalData.excerpt, originalData.domain),\n \n // \u6c7a\u5b9a\u662f\u5426\u4f7f\u7528 AI\uff08\u4fdd\u6301\u539f\u672c\u908f\u8f2f\uff09\n useAI: false, // \u5167\u5bb9\u4e0d\u8db3\uff0c\u4e0d\u4f7f\u7528 AI\n \n // \u932f\u8aa4\u8cc7\u8a0a\n fetchError: item.fetchError,\n processedAt: new Date().toISOString(),\n minutesAfterCreation: originalData.minutesAgo\n }\n });\n continue;\n }\n\n // \u7e7c\u7e8c\u8655\u7406\u6210\u529f\u6293\u53d6\u7684\u5167\u5bb9\n const cleanContent = cleanHtml(html);\n const webTitle = extractTitle(html);\n const metaDescription = extractDescription(html);\n\n // \u539f\u672c\u7684 AI \u5224\u65b7\u908f\u8f2f\n const worthAnalyzing = cleanContent.length > 300 && \n cleanContent.length < 8000 && \n !originalData.domain.includes('twitter.com') &&\n !originalData.domain.includes('x.com');\n\n console.log(`\ud83d\udcca \u5167\u5bb9\u9577\u5ea6\uff1a${cleanContent.length} \u5b57\u5143`);\n console.log(`\ud83e\udd16 \u662f\u5426\u4f7f\u7528 AI\uff1a${worthAnalyzing ? '\u662f' : '\u5426'}`);\n\n results.push({\n json: {\n id: originalData.id,\n title: sanitizeForJson(originalData.title || webTitle || '\u7121\u6a19\u984c'),\n link: originalData.link,\n tags: originalData.tags || [],\n domain: originalData.domain,\n created: originalData.created,\n raindropExcerpt: sanitizeForJson(originalData.excerpt || ''),\n \n cleanContent: sanitizeForJson(cleanContent.substring(0, 6000)),\n metaDescription: sanitizeForJson(metaDescription),\n webTitle: sanitizeForJson(webTitle),\n \n contentLength: cleanContent.length,\n estimatedReadTime: Math.max(1, Math.ceil(cleanContent.split(' ').length / 200)),\n detectedType: detectContentType(originalData.link, cleanContent, originalData.domain),\n \n useAI: worthAnalyzing, // \u4fdd\u6301\u539f\u672c\u7684\u908f\u8f2f\u5224\u65b7\n \n processedAt: new Date().toISOString(),\n minutesAfterCreation: originalData.minutesAgo,\n fetchedUrl: item.fetchedUrl\n }\n });\n}\n\nconsole.log(`\\n\ud83c\udfaf \u8655\u7406\u5b8c\u6210\uff0c\u5171 ${results.length} \u500b\u9805\u76ee`);\nreturn results;"
},
"id": "c62e2b5a-0075-4df0-b324-0f85157dd187",
"name": "\u8655\u7406\u5167\u5bb9",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-840,
400
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"id": "useai-condition",
"leftValue": "={{$json.useAI}}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equal"
}
},
{
"id": "6e7af8d3-19a1-4d96-9dfd-c1db04007e35",
"leftValue": "={{ $json.useAI }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
},
{
"id": "d00e51a7-6a5d-4d55-928c-9ee6538a5145",
"leftValue": "={{ $json.useAI }}",
"rightValue": "f",
"operator": {
"type": "boolean",
"operation": "false",
"singleValue": true
}
}
],
"combinator": "or"
},
"options": {}
},
"id": "bcfeaecb-58fa-4176-b72f-58460a9da6d5",
"name": "\u662f\u5426\u4f7f\u7528 AI \u5206\u6790",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
-620,
400
]
},
{
"parameters": {
"method": "POST",
"url": "https://demo-ai-svc-res929348950322.cognitiveservices.azure.com/openai/deployments/o4-mini/chat/completions?api-version=2025-01-01-preview",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "azureOpenAiApi",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"\u4f60\u662f\u4e00\u500b\u5c08\u696d\u7684\u5167\u5bb9\u5206\u6790\u5e2b\u3002\u8acb\u5206\u6790\u7db2\u9801\u5167\u5bb9\u4e26\u63d0\u4f9b\u7d50\u69cb\u5316\u5206\u6790\u3002\\n\\n\u8acb\u4ee5 JSON \u683c\u5f0f\u56de\u61c9\uff1a\\n{\\n \\\"summary\\\": \\\"2-3\u53e5\u8a71\u7684\u7cbe\u8981\u6458\u8981\\\",\\n \\\"keyPoints\\\": [\\\"\u91cd\u9ede1\\\", \\\"\u91cd\u9ede2\\\", \\\"\u91cd\u9ede3\\\"],\\n \\\"suggestedTags\\\": [\\\"\u6a19\u7c641\\\", \\\"\u6a19\u7c642\\\", \\\"\u6a19\u7c643\\\"],\\n \\\"priority\\\": \\\"\u9ad8|\u4e2d|\u4f4e\\\",\\n \\\"category\\\": \\\"\u6280\u8853\u6587\u7ae0|\u6559\u5b78|\u5de5\u5177|\u65b0\u805e|\u958b\u6e90\u5c08\u6848|\u6280\u8853\u554f\u7b54|\u5176\u4ed6\\\",\\n \\\"difficulty\\\": \\\"\u521d\u7d1a|\u4e2d\u7d1a|\u9ad8\u7d1a\\\",\\n \\\"practicalValue\\\": \\\"\u9ad8|\u4e2d|\u4f4e\\\",\\n \\\"learningGoals\\\": [\\\"\u76ee\u6a191\\\", \\\"\u76ee\u6a192\\\"]\\n}\\n\\n\u7528\u7e41\u9ad4\u4e2d\u6587\u56de\u61c9\u3002\"\n },\n {\n \"role\": \"user\",\n \"content\": \"={{ '\u6a19\u984c\uff1a' + ($json.title || 'N/A') + '\\\\n\u7db2\u7ad9\uff1a' + ($json.domain || 'N/A') + '\\\\n\u63cf\u8ff0\uff1a' + ($json.metaDescription || 'N/A') + '\\\\n\u985e\u578b\uff1a' + ($json.detectedType || 'N/A') + '\\\\n\\\\n\u5167\u5bb9\uff1a\\\\n' + ($json.cleanContent || 'N/A').substring(0, 3500) }}\"\n }\n ],\n \"max_completion_tokens\": 1000\n}",
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "051e3887-da01-4337-ba78-8d79b24b02fd",
"name": "Azure AI \u5167\u5bb9\u5206\u6790",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
-400,
300
],
"credentials": {
"azureOpenAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// \u6574\u5408 AI \u5206\u6790\u7d50\u679c - \u652f\u63f4\u591a\u7b46\u8cc7\u6599\u8655\u7406\nconst azureItems = $input.all();\nconst processedItems = $('\u8655\u7406\u5167\u5bb9').all();\n\nconsole.log(`\ud83e\udd16 \u6e96\u5099\u6574\u5408 ${azureItems.length} \u500b AI \u5206\u6790\u7d50\u679c`);\nconsole.log(`\ud83d\udcc4 \u539f\u59cb\u8655\u7406\u9805\u76ee\u6578\u91cf\uff1a${processedItems.length}`);\n\nconst results = [];\n\n// \ud83c\udff7\ufe0f \u667a\u80fd\u6a19\u7c64\u6e05\u7406\u548c\u8655\u7406\u51fd\u6578\nfunction cleanAndProcessTags(originalTags, suggestedTags) {\n console.log('\ud83c\udff7\ufe0f \u8655\u7406\u6a19\u7c64\uff1a');\n console.log('\u539f\u59cb\u6a19\u7c64:', originalTags);\n console.log('\u5efa\u8b70\u6a19\u7c64:', suggestedTags);\n \n // \u5408\u4f75\u6240\u6709\u6a19\u7c64\uff0c\u78ba\u4fdd\u90fd\u662f\u9663\u5217\n const allTags = [\n ...(Array.isArray(originalTags) ? originalTags : []),\n ...(Array.isArray(suggestedTags) ? suggestedTags : [])\n ];\n \n // \u6e05\u7406\u6a19\u7c64\u51fd\u6578\n function cleanTag(tag) {\n if (!tag || typeof tag !== 'string') return null;\n \n return tag\n .trim()\n // \u79fb\u9664 Reddit r/ \u524d\u7db4\n .replace(/^r\\//, '')\n // \u79fb\u9664\u7279\u6b8a\u5b57\u7b26\uff0c\u53ea\u4fdd\u7559\u4e2d\u82f1\u6587\u3001\u6578\u5b57\u3001\u7a7a\u683c\u3001\u9023\u5b57\u7b26\n .replace(/[^\\w\\s\\u4e00-\\u9fff-]/g, '')\n // \u79fb\u9664\u591a\u9918\u7a7a\u683c\n .replace(/\\s+/g, ' ')\n .trim()\n // \u9650\u5236\u9577\u5ea6\n .substring(0, 50);\n }\n \n // \u8655\u7406\u4e26\u6e05\u7406\u6a19\u7c64\n const cleanedTags = allTags\n .map(cleanTag)\n .filter(tag => tag && tag.length > 0) // \u79fb\u9664\u7a7a\u6a19\u7c64\n .filter(tag => tag.length >= 2) // \u79fb\u9664\u592a\u77ed\u7684\u6a19\u7c64\n .map(tag => {\n // \u6a19\u6e96\u5316\u5e38\u898b\u6a19\u7c64\n const tagLower = tag.toLowerCase();\n if (tagLower.includes('chatgpt')) return 'ChatGPT';\n if (tagLower.includes('javascript') || tagLower === 'js') return 'JavaScript';\n if (tagLower.includes('python')) return 'Python';\n if (tagLower.includes('react')) return 'React';\n if (tagLower.includes('vue')) return 'Vue';\n if (tagLower.includes('node')) return 'Node.js';\n if (tagLower.includes('frontend') || tagLower.includes('\u524d\u7aef')) return '\u524d\u7aef\u958b\u767c';\n if (tagLower.includes('backend') || tagLower.includes('\u5f8c\u7aef')) return '\u5f8c\u7aef\u958b\u767c';\n if (tagLower.includes('ai') || tagLower.includes('\u4eba\u5de5\u667a\u6167')) return 'AI';\n if (tagLower.includes('tutorial') || tagLower.includes('\u6559\u5b78')) return '\u6559\u5b78';\n if (tagLower.includes('tool') || tagLower.includes('\u5de5\u5177')) return '\u5de5\u5177';\n if (tagLower.includes('coding') || tagLower.includes('\u7a0b\u5f0f')) return '\u7a0b\u5f0f\u8a2d\u8a08';\n \n return tag;\n });\n \n // \u53bb\u91cd\u4e26\u9650\u5236\u6578\u91cf\n const uniqueTags = [...new Set(cleanedTags)].slice(0, 6);\n \n console.log('\u2705 \u6e05\u7406\u5f8c\u6a19\u7c64:', uniqueTags);\n return uniqueTags;\n}\n\n// \u8655\u7406\u6bcf\u500b Azure AI \u56de\u61c9\nfor (let i = 0; i < azureItems.length; i++) {\n const azureResponse = azureItems[i].json;\n const originalData = processedItems[i]?.json || {};\n\n console.log(`\\n\ud83e\udd16 \u8655\u7406 AI \u5206\u6790\u7d50\u679c ${i + 1}/${azureItems.length}`);\n console.log(`\ud83d\udcc4 \u539f\u59cb\u9805\u76ee\uff1a${originalData?.title || '\u672a\u77e5\u6a19\u984c'}`);\n\n let aiAnalysis;\n try {\n // Azure AI \u56de\u61c9\u5728 choices[0].message.content\n const aiContent = azureResponse.choices[0].message.content;\n console.log('\ud83d\udcdd AI \u539f\u59cb\u56de\u61c9 (\u524d100\u5b57):', aiContent.substring(0, 100));\n \n // \u53bb\u9664 ```json``` \u5305\u88dd\u4e26\u63d0\u53d6 JSON\n let jsonString = aiContent;\n \n // \u5982\u679c\u5167\u5bb9\u88ab ```json``` \u5305\u88dd\uff0c\u63d0\u53d6 JSON \u90e8\u5206\n const jsonMatch = aiContent.match(/```json\\s*([\\s\\S]*?)\\s*```/);\n if (jsonMatch) {\n jsonString = jsonMatch[1];\n console.log('\u2702\ufe0f \u63d0\u53d6\u51fa JSON \u90e8\u5206');\n } else {\n // \u5982\u679c\u6c92\u6709\u5305\u88dd\uff0c\u5617\u8a66\u76f4\u63a5\u63d0\u53d6 JSON \u7269\u4ef6\n const directJsonMatch = aiContent.match(/\\{[\\s\\S]*\\}/);\n if (directJsonMatch) {\n jsonString = directJsonMatch[0];\n }\n }\n \n // \u89e3\u6790 JSON\n aiAnalysis = JSON.parse(jsonString);\n console.log('\u2705 AI \u5206\u6790\u89e3\u6790\u6210\u529f');\n \n } catch (error) {\n console.log('\u274c AI \u56de\u61c9\u89e3\u6790\u5931\u6557:', error.message);\n console.log('\ud83d\udd0d \u539f\u59cb\u56de\u61c9 choices:', azureResponse.choices?.[0]);\n \n // \u89e3\u6790\u5931\u6557\u6642\u4f7f\u7528\u9810\u8a2d\u503c\n aiAnalysis = {\n summary: originalData?.raindropExcerpt || originalData?.metaDescription || 'AI \u5206\u6790\u5931\u6557\uff0c\u8acb\u67e5\u770b\u539f\u59cb\u9023\u7d50',\n keyPoints: ['AI \u89e3\u6790\u932f\u8aa4', '\u4f7f\u7528\u57fa\u672c\u8cc7\u8a0a'],\n suggestedTags: [],\n priority: '\u4e2d',\n category: originalData?.detectedType || '\u5176\u4ed6',\n difficulty: '\u4e2d\u7d1a',\n practicalValue: '\u4e2d',\n learningGoals: ['\u67e5\u770b\u539f\u59cb\u5167\u5bb9']\n };\n }\n\n // \u8655\u7406\u6a19\u7c64\n const processedTags = cleanAndProcessTags(\n originalData?.tags || [], \n aiAnalysis?.suggestedTags || []\n );\n\n // \u683c\u5f0f\u5316\u91cd\u9ede\u5217\u8868\n const formattedKeyPoints = (aiAnalysis?.keyPoints || ['\u7121\u91cd\u9ede\u8cc7\u8a0a'])\n .filter(point => point && point.length > 0)\n .map(point => `\u2022 ${point}`)\n .join('\\n');\n\n // \u683c\u5f0f\u5316\u5b78\u7fd2\u76ee\u6a19\n const formattedLearningGoals = (aiAnalysis?.learningGoals || ['\u5b78\u7fd2\u65b0\u77e5\u8b58'])\n .filter(goal => goal && goal.length > 0)\n .map(goal => `\ud83c\udfaf ${goal}`)\n .join('\\n');\n\n // \u78ba\u4fdd\u6240\u6709\u5fc5\u8981\u6b04\u4f4d\u90fd\u6709\u503c\n const finalData = {\n // \u57fa\u672c\u8cc7\u6599\n title: originalData?.title || '\u7121\u6a19\u984c',\n url: originalData?.link || '',\n summary: aiAnalysis?.summary || '\u7121\u6458\u8981',\n keyPoints: formattedKeyPoints || '\u2022 \u7121\u91cd\u9ede\u8cc7\u8a0a',\n tags: processedTags,\n priority: aiAnalysis?.priority || '\u4e2d',\n readingTime: originalData?.estimatedReadTime || 5,\n category: aiAnalysis?.category || '\u5176\u4ed6',\n difficulty: aiAnalysis?.difficulty || '\u4e2d\u7d1a',\n domain: originalData?.domain || '',\n collectedDate: originalData?.created || new Date().toISOString(),\n status: '\u672a\u8b80',\n analysisType: 'AI',\n \n // AI \u7279\u6709\u7684\u984d\u5916\u8cc7\u8a0a\n practicalValue: aiAnalysis?.practicalValue || '\u4e2d',\n learningGoals: formattedLearningGoals || '\ud83c\udfaf \u5b78\u7fd2\u65b0\u77e5\u8b58',\n \n // API \u4f7f\u7528\u8cc7\u8a0a\n tokensUsed: azureResponse?.usage?.total_tokens || 0,\n aiModel: azureResponse?.model || 'o4-mini',\n analysisTime: new Date().toISOString()\n };\n\n console.log(`\ud83d\udcca \u9805\u76ee ${i + 1} \u6700\u7d42\u6574\u5408\u8cc7\u6599:`);\n console.log('\u6a19\u984c:', finalData.title);\n console.log('\u6a19\u7c64:', finalData.tags);\n console.log('\u5206\u985e:', finalData.category);\n console.log('\u512a\u5148\u7d1a:', finalData.priority);\n\n results.push({ json: finalData });\n}\n\nconsole.log(`\\n\ud83c\udfaf AI \u5206\u6790\u6574\u5408\u5b8c\u6210\uff0c\u5171 ${results.length} \u500b\u9805\u76ee`);\nreturn results;"
},
"id": "b0488b17-d26d-4b1b-b16c-9033b81f1418",
"name": "\u6574\u5408 AI \u5206\u6790\u7d50\u679c",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-180,
300
]
},
{
"parameters": {
"jsCode": "// \u57fa\u672c\u5206\u6790 - \u4fee\u6b63\u7248\u672c\uff08\u8655\u7406\u55ae\u7b46\u8cc7\u6599\uff09\nconst data = $input.first().json;\n\nconsole.log(`\ud83d\udcca \u57fa\u672c\u5206\u6790\uff1a${data?.title || '\u672a\u77e5\u6a19\u984c'}`);\n\n// \u5206\u6790\u5167\u5bb9\u51fd\u6578\nfunction analyzeContent(title, content, domain) {\n let priority = '\u4e2d';\n let difficulty = '\u521d\u7d1a';\n let tags = [];\n \n const text = ((title || '') + ' ' + (content || '')).toLowerCase();\n const lowerDomain = (domain || '').toLowerCase();\n \n // \u6839\u64da\u57df\u540d\u5224\u65b7\n if (lowerDomain.includes('reddit.com')) {\n tags.push('reddit', '\u793e\u7fa4\u8a0e\u8ad6');\n if (text.includes('chatgptcoding') || text.includes('programming')) {\n tags.push('\u7a0b\u5f0f\u8a2d\u8a08');\n difficulty = '\u4e2d\u7d1a';\n priority = '\u9ad8';\n }\n }\n \n if (lowerDomain.includes('facebook.com')) {\n tags.push('facebook', '\u793e\u7fa4\u8a0e\u8ad6');\n if (text.includes('ai') || text.includes('copilot')) {\n tags.push('AI\u5de5\u5177');\n priority = '\u9ad8';\n }\n }\n \n if (text.includes('webdev') || text.includes('javascript')) {\n tags.push('\u524d\u7aef\u958b\u767c');\n difficulty = '\u4e2d\u7d1a';\n }\n \n if (text.includes('machinelearning') || text.includes('ai')) {\n tags.push('ai');\n priority = '\u9ad8';\n difficulty = '\u9ad8\u7d1a';\n }\n \n // \u6839\u64da\u6a19\u984c\u95dc\u9375\u5b57\n if (text.includes('tutorial') || text.includes('guide')) {\n tags.push('\u6559\u5b78');\n priority = '\u9ad8';\n }\n \n if (text.includes('tool') || text.includes('library')) {\n tags.push('\u5de5\u5177');\n priority = '\u4e2d';\n }\n \n return { priority, difficulty, tags };\n}\n\n// Reddit \u5167\u5bb9\u7279\u6b8a\u8655\u7406\u51fd\u6578\nfunction analyzeRedditContent(title, domain, excerpt) {\n let priority = '\u4e2d';\n let difficulty = '\u521d\u7d1a';\n let tags = ['reddit', '\u793e\u7fa4\u8a0e\u8ad6'];\n \n const text = ((title || '') + ' ' + (excerpt || '')).toLowerCase();\n \n // \u6839\u64da subreddit \u5224\u65b7\n if (text.includes('chatgptcoding') || text.includes('programming')) {\n tags.push('\u7a0b\u5f0f\u8a2d\u8a08');\n difficulty = '\u4e2d\u7d1a';\n priority = '\u9ad8';\n }\n \n if (text.includes('webdev') || text.includes('javascript')) {\n tags.push('\u524d\u7aef\u958b\u767c');\n difficulty = '\u4e2d\u7d1a';\n }\n \n if (text.includes('machinelearning') || text.includes('ai')) {\n tags.push('ai');\n priority = '\u9ad8';\n difficulty = '\u9ad8\u7d1a';\n }\n \n // \u6839\u64da\u6a19\u984c\u95dc\u9375\u5b57\n if (text.includes('tutorial') || text.includes('guide')) {\n tags.push('\u6559\u5b78');\n priority = '\u9ad8';\n }\n \n if (text.includes('tool') || text.includes('library')) {\n tags.push('\u5de5\u5177');\n priority = '\u4e2d';\n }\n \n return { priority, difficulty, tags };\n}\n\nconst analysis = (data?.domain || '').includes('reddit.com') \n ? analyzeRedditContent(data?.title, data?.domain, data?.raindropExcerpt)\n : analyzeContent(data?.title, data?.cleanContent, data?.domain);\n\nreturn {\n title: data?.title || '\u7121\u6a19\u984c',\n url: data?.link || '',\n summary: data?.raindropExcerpt || data?.metaDescription || '\u793e\u7fa4\u8a0e\u8ad6\u4e32\uff0c\u5efa\u8b70\u76f4\u63a5\u67e5\u770b\u539f\u59cb\u9023\u7d50\u4e86\u89e3\u8a73\u7d30\u5167\u5bb9',\n keyPoints: `\u2022 \u793e\u7fa4\u8a0e\u8ad6\u5167\u5bb9\\n\u2022 \u4e3b\u984c\uff1a${data?.title || '\u672a\u77e5'}\\n\u2022 \u5efa\u8b70\u76f4\u63a5\u700f\u89bd\u539f\u59cb\u9023\u7d50`,\n tags: [...(data?.tags || []), ...analysis.tags],\n priority: analysis.priority,\n readingTime: data?.estimatedReadTime || 3,\n category: data?.detectedType || '\u793e\u7fa4\u8a0e\u8ad6',\n difficulty: analysis.difficulty,\n domain: data?.domain || '',\n collectedDate: data?.created || new Date().toISOString(),\n status: '\u672a\u8b80',\n analysisType: 'Basic'\n};"
},
"id": "62463155-faaa-4f50-84e2-59e5e7b10b67",
"name": "\u57fa\u672c\u5206\u6790",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-400,
500
]
},
{
"parameters": {},
"id": "fb851800-7ffc-4622-9e24-466adaaa725c",
"name": "\u5408\u4f75\u5206\u6790\u7d50\u679c",
"type": "n8n-nodes-base.merge",
"typeVersion": 2.1,
"position": [
40,
400
]
},
{
"parameters": {
"resource": "databasePage",
"databaseId": {
"__rl": true,
"value": "1ff930aa1b1280278ff5d95c98ce3ffd",
"mode": ""
},
"propertiesUi": {
"propertyValues": [
{
"key": "\u6a19\u984c|title",
"title": "={{$json.title}}"
},
{
"key": "\u9023\u7d50|url",
"urlValue": "={{$json.url}}"
},
{
"key": "\u6458\u8981|rich_text",
"textContent": "={{$json.summary}}"
},
{
"key": "\u91cd\u9ede|rich_text",
"textContent": "={{$json.keyPoints}}"
},
{
"key": "\u6a19\u7c64|multi_select",
"multiSelectValue": "={{$json.tags}}"
},
{
"key": "\u512a\u5148\u7d1a|select",
"selectValue": "={{$json.priority}}"
},
{
"key": "\u9810\u4f30\u95b1\u8b80\u6642\u9593|number",
"numberValue": "={{$json.readingTime}}"
},
{
"key": "\u5206\u985e|select",
"selectValue": "={{$json.category}}"
},
{
"key": "\u96e3\u5ea6|select",
"selectValue": "={{$json.difficulty}}"
},
{
"key": "\u4f86\u6e90\u7db2\u7ad9|rich_text",
"textContent": "={{$json.domain}}"
},
{
"key": "\u6536\u85cf\u65e5\u671f|date",
"date": "={{$json.collectedDate}}"
},
{
"key": "\u72c0\u614b|select",
"selectValue": "={{$json.status}}"
}
]
},
"blockUi": {
"blockValues": [
{
"type": "heading_1",
"richText": true,
"text": {
"text": [
{
"text": "={{$json.title}}",
"annotationUi": {
"bold": true,
"color": "blue"
}
}
]
}
},
{
"richText": true,
"text": {
"text": [
{
"text": "=\ud83c\udf10 \u4f86\u6e90\uff1a{{$json.domain}} | \ud83d\udcc5 {{new Date($json.collectedDate).toLocaleDateString('zh-TW')}} | \u23f1\ufe0f {{$json.readingTime}}\u5206\u9418",
"annotationUi": {
"italic": true,
"color": "gray"
}
}
]
}
},
{
"richText": true,
"text": {
"text": [
{
"text": "\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",
"annotationUi": {
"color": "gray"
}
}
]
}
},
{
"type": "heading_2",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udca1 \u5167\u5bb9\u6458\u8981",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"richText": true,
"text": {
"text": [
{
"text": "={{$json.summary}}",
"annotationUi": {
"color": "blue"
}
}
]
}
},
{
"type": "heading_2",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udccb \u91cd\u9ede\u6458\u8981",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"richText": true,
"text": {
"text": [
{
"text": "={{$json.keyPoints}}",
"annotationUi": {}
}
]
}
},
{
"type": "heading_2",
"richText": true,
"text": {
"text": [
{
"text": "\ud83c\udfaf \u5b78\u7fd2\u76ee\u6a19",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"richText": true,
"text": {
"text": [
{
"text": "={{$json.learningGoals || '\ud83c\udfaf \u63a2\u7d22\u65b0\u77e5\u8b58\u8207\u6280\u80fd\\n\ud83c\udfaf \u63d0\u5347\u5c08\u696d\u80fd\u529b\\n\ud83c\udfaf \u5be6\u969b\u61c9\u7528\u6240\u5b78\u5167\u5bb9'}}",
"annotationUi": {
"color": "green"
}
}
]
}
},
{
"type": "heading_2",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udcca \u5167\u5bb9\u8a73\u7d30\u8cc7\u8a0a",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "bulleted_list_item",
"richText": true,
"text": {
"text": [
{
"text": "=\ud83d\udcda \u5206\u985e\uff1a{{$json.category}}",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "bulleted_list_item",
"richText": true,
"text": {
"text": [
{
"text": "=\u26a1 \u512a\u5148\u7d1a\uff1a{{$json.priority}}",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "bulleted_list_item",
"richText": true,
"text": {
"text": [
{
"text": "=\ud83d\udcc8 \u96e3\u5ea6\u7b49\u7d1a\uff1a{{$json.difficulty}}",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "bulleted_list_item",
"richText": true,
"text": {
"text": [
{
"text": "=\u23f1\ufe0f \u9810\u4f30\u95b1\u8b80\u6642\u9593\uff1a{{$json.readingTime}} \u5206\u9418",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "bulleted_list_item",
"richText": true,
"text": {
"text": [
{
"text": "=\ud83e\udd16 \u5206\u6790\u65b9\u5f0f\uff1a{{$json.analysisType}}",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "heading_2",
"richText": true,
"text": {
"text": [
{
"text": "\ud83c\udff7\ufe0f \u76f8\u95dc\u6a19\u7c64",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"richText": true,
"text": {
"text": [
{
"text": "=={{$json.tags.join(' \u2022 ')}}",
"annotationUi": {
"code": true,
"color": "purple"
}
}
]
}
},
{
"richText": true,
"text": {
"text": [
{
"text": "\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",
"annotationUi": {
"color": "gray"
}
}
]
}
},
{
"type": "heading_2",
"richText": true,
"text": {
"text": [
{
"text": "\u2705 \u5b78\u7fd2\u9032\u5ea6\u8ffd\u8e64",
"annotationUi": {
"bold": true,
"color": "green"
}
}
]
}
},
{
"type": "to_do",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udcd6 \u521d\u6b65\u700f\u89bd\u5167\u5bb9",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "to_do",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udd0d \u6df1\u5165\u95b1\u8b80\u7406\u89e3",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "to_do",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udca1 \u638c\u63e1\u6838\u5fc3\u6982\u5ff5",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "to_do",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udee0\ufe0f \u52d5\u624b\u5be6\u4f5c\u7df4\u7fd2",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "to_do",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udcdd \u6574\u7406\u5b78\u7fd2\u7b46\u8a18",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "to_do",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udd04 \u8907\u7fd2\u4e26\u61c9\u7528",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "heading_2",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udcdd \u6211\u7684\u5b78\u7fd2\u7b46\u8a18",
"annotationUi": {
"bold": true,
"color": "yellow"
}
}
]
}
},
{
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udcad \u5728\u9019\u88e1\u8a18\u9304\u4f60\u7684\u5b78\u7fd2\u5fc3\u5f97\u3001\u91cd\u8981\u767c\u73fe\u548c\u500b\u4eba\u601d\u8003...",
"annotationUi": {
"italic": true,
"color": "gray"
}
}
]
}
},
{},
{},
{
"type": "heading_3",
"richText": true,
"text": {
"text": [
{
"text": "\ud83e\udd14 \u5b78\u7fd2\u904e\u7a0b\u4e2d\u7684\u554f\u984c\u8207\u601d\u8003",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "bulleted_list_item"
},
{
"type": "bulleted_list_item"
},
{
"type": "heading_3",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udca1 \u5be6\u4f5c\u60f3\u6cd5\u8207\u61c9\u7528\u8a08\u756b",
"annotationUi": {
"bold": true
}
}
]
}
},
{
"type": "bulleted_list_item"
},
{
"type": "bulleted_list_item"
},
{
"type": "heading_3",
"richText": true,
"text": {
"text": [
{
"text": "\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",
"annotationUi": {
"color": "gray"
}
}
]
}
},
{
"type": "heading_2",
"richText": true,
"text": {
"text": [
{
"text": "\ud83d\udd17 \u539f\u59cb\u5167\u5bb9\u9023\u7d50",
"annotationUi": {
"bold": true,
"color": "blue"
}
}
]
}
},
{
"richText": true,
"text": {
"text": [
{
"text": "=\ud83d\udd17 \u9ede\u64ca\u67e5\u770b\u539f\u59cb\u6587\u7ae0\uff1a{{$json.title}}",
"isLink": true,
"textLink": "={{$json.url}}",
"annotationUi": {
"bold": true,
"underline": true,
"color": "blue"
}
}
]
}
},
{
"richText": true,
"text": {
"text": [
{
"text": "=\ud83c\udf10 \u7db2\u5740\uff1a{{$json.url}}",
"annotationUi": {
"code": true,
"color": "gray"
}
}
]
}
},
{
"type": "heading_3",
"richText": true,
"text": {
"text": [
{
"text": "\u2139\ufe0f \u7cfb\u7d71\u8cc7\u8a0a",
"annotationUi": {
"color": "gray"
}
}
]
}
},
{
"type": "bulleted_list_item",
"richText": true,
"text": {
"text": [
{
"text": "=\ud83d\udcc5 \u6536\u85cf\u6642\u9593\uff1a{{new Date($json.collectedDate).toLocaleString('zh-TW')}}",
"annotationUi": {
"code": true
}
},
{
"text": "=\ud83e\udd16 AI \u6a21\u578b\uff1a{{$json.aiModel || 'N/A'}}",
"annotationUi": {
"code": true
}
},
{
"text": "=\ud83d\udd22 Token \u4f7f\u7528\u91cf\uff1a{{$json.tokensUsed || 0}}",
"annotationUi": {
"code": true
}
}
]
}
},
{
"richText": true,
"text": {
"text": [
{
"text": "\ud83e\udd16 \u6b64\u9801\u9762\u7531 AI \u81ea\u52d5\u751f\u6210\u5206\u6790\uff0c\u5305\u542b\u667a\u80fd\u6a19\u7c64\u3001\u91cd\u9ede\u6458\u8981\u548c\u500b\u4eba\u5316\u5b78\u7fd2\u5efa\u8b70\u3002\u6b61\u8fce\u5728\u7b46\u8a18\u5340\u57df\u8a18\u9304\u4f60\u7684\u60f3\u6cd5\uff01",
"annotationUi": {
"italic": true,
"color": "gray"
}
}
]
}
}
]
},
"options": {}
},
"id": "3be53dbd-e356-4957-b2fc-b0be0b1590ce",
"name": "\u5b58\u5165 Notion \u8cc7\u6599\u5eab",
"type": "n8n-nodes-base.notion",
"typeVersion": 2,
"position": [
260,
400
],
"credentials": {
"notionApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// \u5f37\u5316\u7248\u7db2\u9801\u6293\u53d6 - \u8655\u7406\u591a\u7b46\u8cc7\u6599\nconst items = $input.all();\nconst results = [];\n\nconsole.log(`\ud83c\udf10 \u6e96\u5099\u8655\u7406 ${items.length} \u500b\u9805\u76ee`);\n\n// \u70ba\u4e0d\u540c\u7db2\u7ad9\u8a2d\u5b9a\u4e0d\u540c\u7684\u6293\u53d6\u7b56\u7565\nfunction getRequestConfig(url, domain) {\n const baseConfig = {\n url: url,\n method: 'GET',\n timeout: 30000,\n sendHeaders: true,\n headerParameters: {\n parameters: [\n {\n name: 'User-Agent',\n value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'\n },\n {\n name: 'Accept',\n value: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'\n },\n {\n name: 'Accept-Language',\n value: 'en-US,en;q=0.9,zh-TW;q=0.8,zh;q=0.7'\n },\n {\n name: 'Accept-Encoding',\n value: 'gzip, deflate, br'\n },\n {\n name: 'Connection',\n value: 'keep-alive'\n },\n {\n name: 'Upgrade-Insecure-Requests',\n value: '1'\n }\n ]\n },\n options: {\n response: {\n response: {\n responseFormat: 'text'\n }\n }\n }\n };\n\n // \u91dd\u5c0d\u7279\u5b9a\u7db2\u7ad9\u7684\u7279\u6b8a\u8655\u7406\n if (domain.includes('reddit.com')) {\n // Reddit \u7279\u6b8a\u8655\u7406\n baseConfig.headerParameters.parameters.push(\n {\n name: 'Referer',\n value: 'https://www.reddit.com/'\n },\n {\n name: 'DNT',\n value: '1'\n },\n {\n name: 'Sec-Fetch-Dest',\n value: 'document'\n },\n {\n name: 'Sec-Fetch-Mode',\n value: 'navigate'\n },\n {\n name: 'Sec-Fetch-Site',\n value: 'same-origin'\n }\n );\n \n // \u5617\u8a66\u4f7f\u7528 old.reddit.com\n if (!url.includes('old.reddit.com')) {\n baseConfig.url = url.replace('www.reddit.com', 'old.reddit.com');\n console.log(`\ud83d\udd04 \u6539\u7528 old.reddit.com\uff1a${baseConfig.url}`);\n }\n }\n \n if (domain.includes('twitter.com') || domain.includes('x.com')) {\n // Twitter/X \u7279\u6b8a\u8655\u7406\n baseConfig.headerParameters.parameters.push({\n name: 'Referer',\n value: 'https://twitter.com/'\n });\n }\n \n if (domain.includes('linkedin.com')) {\n // LinkedIn \u7279\u6b8a\u8655\u7406\n baseConfig.headerParameters.parameters.push({\n name: 'Referer',\n value: 'https://www.linkedin.com/'\n });\n }\n\n return baseConfig;\n}\n\n// \u8655\u7406\u6bcf\u500b\u9805\u76ee\nfor (let i = 0; i < items.length; i++) {\n const originalData = items[i].json;\n const url = originalData.link;\n const domain = originalData.domain || '';\n\n console.log(`\\n\ud83d\udcc4 \u8655\u7406\u9805\u76ee ${i + 1}/${items.length}\uff1a${originalData.title}`);\n console.log(`\ud83d\udccd \u7db2\u5740\uff1a${url}`);\n console.log(`\ud83c\udfe0 \u57df\u540d\uff1a${domain}`);\n\n // \u53d6\u5f97\u8acb\u6c42\u8a2d\u5b9a\n const requestConfig = getRequestConfig(url, domain);\n\n try {\n // \u9032\u884c HTTP \u8acb\u6c42\n const response = await $http.request(requestConfig);\n \n if (response.data) {\n console.log(`\u2705 \u6210\u529f\u6293\u53d6\u5167\u5bb9\uff0c\u9577\u5ea6\uff1a${response.data.length} \u5b57\u5143`);\n results.push({\n json: {\n ...originalData,\n data: response.data,\n fetchSuccess: true,\n fetchedUrl: requestConfig.url,\n fetchTime: new Date().toISOString()\n }\n });\n } else {\n console.log(`\u26a0\ufe0f \u56de\u61c9\u70ba\u7a7a`);\n throw new Error('Empty response');\n }\n \n } catch (error) {\n console.log(`\u274c \u6293\u53d6\u5931\u6557\uff1a${error.message}`);\n \n // \u5982\u679c\u662f Reddit \u4e14\u7b2c\u4e00\u6b21\u5617\u8a66\u5931\u6557\uff0c\u5617\u8a66\u4e0d\u540c\u7684\u65b9\u6cd5\n if (domain.includes('reddit.com') && !requestConfig.url.includes('old.reddit.com')) {\n console.log(`\ud83d\udd04 \u5617\u8a66\u4f7f\u7528 old.reddit.com`);\n \n try {\n const fallbackConfig = {\n ...requestConfig,\n url: url.replace('www.reddit.com', 'old.reddit.com').replace('reddit.com', 'old.reddit.com')\n };\n \n const fallbackResponse = await $http.request(fallbackConfig);\n \n if (fallbackResponse.data) {\n console.log(`\u2705 old.reddit.com \u6210\u529f\uff0c\u9577\u5ea6\uff1a${fallbackResponse.data.length} \u5b57\u5143`);\n results.push({\n json: {\n ...originalData,\n data: fallbackResponse.data,\n fetchSuccess: true,\n fetchedUrl: fallbackConfig.url,\n fetchTime: new Date().toISOString(),\n fallbackUsed: 'old.reddit.com'\n }\n });\n continue; // \u6210\u529f\u5f8c\u8df3\u5230\u4e0b\u4e00\u500b\u9805\u76ee\n }\n } catch (fallbackError) {\n console.log(`\u274c old.reddit.com \u4e5f\u5931\u6557\uff1a${fallbackError.message}`);\n }\n }\n \n // \u5982\u679c\u6293\u53d6\u5931\u6557\uff0c\u8fd4\u56de\u57fa\u672c\u8cc7\u8a0a\uff0c\u8b93\u5de5\u4f5c\u6d41\u7a0b\u7e7c\u7e8c\n console.log(`\ud83d\udcdd \u6293\u53d6\u5931\u6557\uff0c\u4f7f\u7528 Raindrop \u6458\u8981\u4f5c\u70ba\u5f8c\u5099`);\n results.push({\n json: {\n ...originalData,\n data: `<html><head><title>${originalData.title}</title><meta name=\"description\" content=\"${originalData.excerpt}\"></head><body><p>${originalData.excerpt}</p></body></html>`,\n fetchSuccess: false,\n fetchError: error.message,\n fetchTime: new Date().toISOString(),\n usedFallback: true\n }\n });\n }\n}\n\nconsole.log(`\\n\ud83c\udfaf \u8655\u7406\u5b8c\u6210\uff0c\u5171 ${results.length} \u500b\u9805\u76ee`);\nreturn results;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-1040,
400
],
"id": "a2adc7a9-b643-42a3-a904-bf77dccde236",
"name": "\u6293\u53d6\u7db2\u9801\u5167\u5bb9"
}
],
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "\u53d6\u5f97 Raindrop \u6536\u85cf",
"type": "main",
"index": 0
}
]
]
},
"\u53d6\u5f97 Raindrop \u6536\u85cf": {
"main": [
[
{
"node": "\u7be9\u9078\u65b0\u9805\u76ee",
"type": "main",
"index": 0
}
]
]
},
"\u7be9\u9078\u65b0\u9805\u76ee": {
"main": [
[
{
"node": "\u6293\u53d6\u7db2\u9801\u5167\u5bb9",
"type": "main",
"index": 0
}
]
]
},
"\u8655\u7406\u5167\u5bb9": {
"main": [
[
{
"node": "\u662f\u5426\u4f7f\u7528 AI \u5206\u6790",
"type": "main",
"index": 0
}
]
]
},
"\u662f\u5426\u4f7f\u7528 AI \u5206\u6790": {
"main": [
[
{
"node": "Azure AI \u5167\u5bb9\u5206\u6790",
"type": "main",
"index": 0
}
],
[
{
"node": "\u57fa\u672c\u5206\u6790",
"type": "main",
"index": 0
}
]
]
},
"Azure AI \u5167\u5bb9\u5206\u6790": {
"main": [
[
{
"node": "\u6574\u5408 AI \u5206\u6790\u7d50\u679c",
"type": "main",
"index": 0
}
]
]
},
"\u6574\u5408 AI \u5206\u6790\u7d50\u679c": {
"main": [
[
{
"node": "\u5408\u4f75\u5206\u6790\u7d50\u679c",
"type": "main",
"index": 0
}
]
]
},
"\u57fa\u672c\u5206\u6790": {
"main": [
[
{
"node": "\u5408\u4f75\u5206\u6790\u7d50\u679c",
"type": "main",
"index": 1
}
]
]
},
"\u5408\u4f75\u5206\u6790\u7d50\u679c": {
"main": [
[
{
"node": "\u5b58\u5165 Notion \u8cc7\u6599\u5eab",
"type": "main",
"index": 0
}
]
]
},
"\u6293\u53d6\u7db2\u9801\u5167\u5bb9": {
"main": [
[
{
"node": "\u8655\u7406\u5167\u5bb9",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "7f2db0e4-5103-4b3b-9897-deb9ac3d8165",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "E1OK2GVGla40YBIp",
"tags": [
{
"name": "raindrop",
"id": "67ge26Co3u11nufo",
"createdAt": "2025-05-27T17:26:59.646Z",
"updatedAt": "2025-05-27T17:26:59.646Z"
},
{
"name": "notion",
"id": "jJONDkvSm8dw29BK",
"createdAt": "2025-05-27T17:27:01.909Z",
"updatedAt": "2025-05-27T17:27:01.909Z"
},
{
"name": "knowledge",
"id": "qU6ml7ppBu4zvXak",
"createdAt": "2025-05-27T17:27:08.636Z",
"updatedAt": "2025-05-27T17:27:08.636Z"
}
]
}
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.
azureOpenAiApinotionApiraindropOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Raindrop Knowledge Management. Uses httpRequest, notion. Scheduled trigger; 11 nodes.
Source: https://github.com/lettucebo/N8N-Flows/blob/52ab732270953f61117544747dae01a81fdde982/flows/RaindropKnowledgeManagement/Raindrop_Knowledge_Management.json — 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.
This template is designed for social media managers, content creators, data analysts, and anyone who wants to automatically save and analyze their Meta Threads posts in Notion.
> Transform your content strategy with automated competitor intelligence
⚠️ COMMUNITY TEMPLATE DISCLAIMER: This is a community-contributed template that uses ScrapeGraphAI (a community node). Please ensure you have the ScrapeGraphAI community node installed in your n8n ins
n8n workflows can go out of hand when you're automating as much as we do at n8n. We needed a place to document them and keep track of who owns and maintains them. To facilitate this we use this n8n wo
Opportunity Radar Weekly. Uses httpRequest, notion. Scheduled trigger; 8 nodes.