使用 Gemini AI 进行 X (Twitter) 品牌情感分析及 Slack 提醒
高级
这是一个自动化工作流,包含 42 个节点。主要使用 If, Set, Code, Wait, Limit 等节点。 使用 Gemini AI 进行 X (Twitter) 品牌情感分析及 Slack 提醒
前置要求
- •Slack Bot Token 或 Webhook URL
- •可能需要目标 API 的认证凭证
- •Google Sheets API 凭证
- •Google Gemini API Key
使用的节点 (42)
分类
-
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"meta": {
"instanceId": "12b5738dbe70639f3b7d069a122c5f581ca4347fcd62ddef39ad5c33b40e7e5e",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "59dc116b-2c89-4dd0-a65d-707c9c19a7d0",
"name": "代码",
"type": "n8n-nodes-base.code",
"position": [
656,
-1104
],
"parameters": {
"jsCode": "// Get the input data from the first item\nconst inputData = items[0].json;\n\n// This will hold our final list of individual items\nconst outputItems = [];\n\nconst nextCursor = inputData.next_cursor;\n\n// Loop through each tweet in the 'tweets' array from the input\nfor (const tweet of inputData.tweets) {\n // 1. Create the clean object for a single tweet\n const cleanTweet = {\n id:tweet.id,\n text: tweet.text,\n url: tweet.url,\n authorUsername: tweet.author.userName,\n authorName: tweet.author.name,\n createdAt: tweet.createdAt,\n likeCount: tweet.likeCount,\n retweetCount: tweet.retweetCount,\n replyCount: tweet.replyCount,\n quoteCount: tweet.quoteCount,\n viewCount: tweet.viewCount,\n isReply: tweet.isReply,\n nextCursor: nextCursor \n };\n\n if (tweet.isReply) {\n cleanTweet.inReplyToUsername = tweet.inReplyToUsername;\n cleanTweet.inReplyToId = tweet.inReplyToId;\n }\n\n // 2. Wrap this single tweet object in the required N8N item structure\n const n8nItem = {\n json: cleanTweet\n };\n\n // 3. Add this new item to our output list\n outputItems.push(n8nItem);\n}\n\n// Return the array of individual items\nreturn outputItems;"
},
"typeVersion": 2
},
{
"id": "4a4011b2-34e4-460d-aeaa-16f7d268387e",
"name": "在表格中追加行",
"type": "n8n-nodes-base.googleSheets",
"position": [
880,
-1104
],
"parameters": {
"columns": {
"value": {
"URL": "={{ $json.url }}",
"Date": "={{ $json.createdAt }}",
"Likes": "={{ $json.likeCount }}",
"Views": "={{ $json.viewCount }}",
"Quotes": "={{ $json.quoteCount }}",
"Content": "={{ $json.text }}",
"Replies": "={{ $json.replyCount }}",
"isreply": "={{ $json.isReply }}",
"Retweets": "={{ $json.retweetCount }}",
"Tweet_ID": "={{ $json.id }}",
"Author_Name": "={{ $json.authorName }}",
"next_cursor": "={{ $json.nextCursor }}",
"Author_Username": "={{ $json.authorUsername }}"
},
"schema": [
{
"id": "Tweet_ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Tweet_ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "URL",
"type": "string",
"display": true,
"required": false,
"displayName": "URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Content",
"type": "string",
"display": true,
"required": false,
"displayName": "Content",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Author_Username",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Author_Username",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Author_Name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Author_Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Likes",
"type": "string",
"display": true,
"required": false,
"displayName": "Likes",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Views",
"type": "string",
"display": true,
"required": false,
"displayName": "Views",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Retweets",
"type": "string",
"display": true,
"required": false,
"displayName": "Retweets",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "next_cursor",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "next_cursor",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Replies",
"type": "string",
"display": true,
"required": false,
"displayName": "Replies",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Quotes",
"type": "string",
"display": true,
"required": false,
"displayName": "Quotes",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "isreply",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "isreply",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {
"useAppend": true
},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c/edit?usp=drivesdk",
"cachedResultName": "Tweet Data"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "6q55WdTedKPZERoF",
"name": "Google Sheets account 3"
}
},
"typeVersion": 4.7
},
{
"id": "86afb72d-92d7-460c-b9c0-5d96674c7931",
"name": "计数",
"type": "n8n-nodes-base.set",
"position": [
-240,
-1040
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "75e9cf42-928f-4dc2-a354-7b1edd7dfebb",
"name": "count",
"type": "number",
"value": 1
},
{
"id": "866e2004-3995-4431-b373-ac8b3b93c147",
"name": "query",
"type": "string",
"value": "emergentlabs"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "ae1ff19a-ff35-4cba-9269-1eeff32763ca",
"name": "计数器",
"type": "n8n-nodes-base.set",
"position": [
-16,
-1040
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f8c5768f-f465-42ca-b990-0f687ccc7805",
"name": "counter",
"type": "number",
"value": "={{ $json.count }}"
},
{
"id": "2290eb4e-938c-4b66-aefd-1b88a37f5f00",
"name": "cursor",
"type": "string",
"value": "={{ $json['next cursor'] }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "f0abc5af-dddc-48df-b916-0b7d79835171",
"name": "条件判断",
"type": "n8n-nodes-base.if",
"position": [
1360,
-1120
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "e80112e6-c902-4185-af64-8d706550886c",
"operator": {
"type": "number",
"operation": "equals"
},
"leftValue": "={{ $('counter').item.json.counter }}",
"rightValue": 1
}
]
}
},
"typeVersion": 2.2
},
{
"id": "38daa357-3e8f-46a5-8256-37717205b53d",
"name": "限制",
"type": "n8n-nodes-base.limit",
"position": [
256,
-896
],
"parameters": {},
"typeVersion": 1
},
{
"id": "91a1fc06-52d9-4aef-af97-151199bded57",
"name": "设置递增",
"type": "n8n-nodes-base.set",
"position": [
480,
-896
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f2a3a921-640f-42b7-b455-4110cfc76f6e",
"name": "counter",
"type": "string",
"value": "={{ $('counter').item.json.counter }}"
},
{
"id": "8cad4530-b5b8-4a6f-b901-926f432b0ff3",
"name": "cursor",
"type": "string",
"value": "={{ $('Tweet Scraper').item.json.next_cursor }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "306f0c25-2e3a-4d2a-8d6a-4c50f3873ecf",
"name": "代码1",
"type": "n8n-nodes-base.code",
"position": [
704,
-896
],
"parameters": {
"jsCode": "const items = $input.all();\n\nreturn items.map(item => {\n // Default to 1 if no counter exists\n let newCount = 1;\n\n // 1. Correctly check if the counter EXISTS\n if (item.json && item.json.counter != null) {\n // 2. Convert the counter text to a number before adding\n newCount = parseInt(item.json.counter) + 1;\n }\n\n // Make sure the json object exists\n if (!item.json) {\n item.json = {};\n }\n\n // Add the new, calculated count to the item\n item.json.count = newCount;\n\n // 3. Return the single MODIFIED item, not the whole list\n return item;\n});"
},
"typeVersion": 2
},
{
"id": "639373f6-2282-49c6-bf3c-fe2fc14baf9b",
"name": "设置计数和游标",
"type": "n8n-nodes-base.set",
"position": [
1152,
-848
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "42e55567-d8e4-4ee6-9649-a1299c09c2d3",
"name": "count",
"type": "string",
"value": "={{ $json.count }}"
},
{
"id": "c654e218-d1f6-49ef-b401-fb81ef428bbf",
"name": "cursor",
"type": "string",
"value": "={{ $json.cursor }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "143ba536-5062-4f1f-8930-8a3c1b1d0ac7",
"name": "等待",
"type": "n8n-nodes-base.wait",
"position": [
208,
-1104
],
"webhookId": "792f7689-0419-41a5-9ccd-1bdd83002e48",
"parameters": {},
"typeVersion": 1.1
},
{
"id": "bcb717ef-5bd5-444b-8aa3-4921774b109a",
"name": "Google Calendar MCP",
"type": "n8n-nodes-base.switch",
"position": [
-272,
-448
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4ed77836-9697-4a95-aa7a-ffbe4790f57b",
"operator": {
"type": "string",
"operation": "notExists",
"singleValue": true
},
"leftValue": "={{ $json.Content }}",
"rightValue": ""
}
]
}
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"typeVersion": 3.2
},
{
"id": "eda67442-2198-4692-bbdb-8db08dbf576f",
"name": "Google Gemini 聊天模型",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
32,
-304
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"id": "sFPucaeaikoDAevM",
"name": "Google Gemini(PaLM) Api account 3"
}
},
"typeVersion": 1
},
{
"id": "e441a2b2-7abf-4c1f-a8d6-9a910474d85b",
"name": "从数据库获取推文",
"type": "n8n-nodes-base.googleSheetsTool",
"position": [
448,
-320
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c/edit?usp=drivesdk",
"cachedResultName": "Tweet Data"
},
"descriptionType": "manual",
"toolDescription": "Use this tool to get all recent tweets mentioning our brand from the Google Sheets database. It returns a complete list of tweets with details like content, author, likes, and retweets."
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "6q55WdTedKPZERoF",
"name": "Google Sheets account 3"
}
},
"typeVersion": 4.7
},
{
"id": "3edca455-922f-4956-8f45-6a47fd8024d2",
"name": "在 sheet1 中追加行",
"type": "n8n-nodes-base.googleSheets",
"position": [
1136,
-480
],
"parameters": {
"columns": {
"value": {
"summary": "={{ $json.summary }}",
"tweetId": "={{ $json.tweetID }}",
"urgency": "={{ $json.urgency }}",
"keyTopic": "={{ $json.keyTopic }}",
"sentiment": "={{ $json.sentiment }}",
"action taken ": "Notmarked",
"date_analyzed": "={{ $now }}"
},
"schema": [
{
"id": "tweetId",
"type": "string",
"display": true,
"required": false,
"displayName": "tweetId",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "sentiment",
"type": "string",
"display": true,
"required": false,
"displayName": "sentiment",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "keyTopic",
"type": "string",
"display": true,
"required": false,
"displayName": "keyTopic",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "urgency",
"type": "string",
"display": true,
"required": false,
"displayName": "urgency",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "summary",
"type": "string",
"display": true,
"required": false,
"displayName": "summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "date_analyzed",
"type": "string",
"display": true,
"required": false,
"displayName": "date_analyzed",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "action taken ",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "action taken ",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 454621199,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c/edit#gid=454621199",
"cachedResultName": "Sheet2"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c/edit?usp=drivesdk",
"cachedResultName": "Tweet Data"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "6q55WdTedKPZERoF",
"name": "Google Sheets account 3"
}
},
"typeVersion": 4.7
},
{
"id": "a9435786-bbe9-4f10-871c-97d1ccd314a0",
"name": "聚合",
"type": "n8n-nodes-base.aggregate",
"position": [
1728,
-688
],
"parameters": {
"options": {},
"fieldsToAggregate": {
"fieldToAggregate": [
{
"renameField": true,
"outputFieldName": "final",
"fieldToAggregate": "Content"
}
]
}
},
"typeVersion": 1
},
{
"id": "cd92a7ce-d58d-4291-b128-d67373128b2b",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1184,
-1120
],
"parameters": {
"width": 640,
"height": 320,
"content": "# 🎯 收集器与分析器工作流"
},
"typeVersion": 1
},
{
"id": "b41a6ef6-be6b-49a7-acd8-d335d07796d1",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-480,
-1296
],
"parameters": {
"width": 624,
"height": 544,
"content": "# 🚀 启动引擎"
},
"typeVersion": 1
},
{
"id": "5aeb7918-f3cd-4796-956d-b390ba82bca5",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
176,
-1328
],
"parameters": {
"color": 5,
"width": 1856,
"height": 752,
"content": "# 🐦 推文收集器(循环)"
},
"typeVersion": 1
},
{
"id": "2fdc6db0-a947-42bf-ae04-f4869c7fd224",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-736,
-688
],
"parameters": {
"color": 4,
"width": 352,
"height": 480,
"content": "# 🤔 守门员"
},
"typeVersion": 1
},
{
"id": "9277459d-8348-41a2-87fe-1c2fc3ca9bf8",
"name": "便签说明4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-240,
-160
],
"parameters": {
"color": 4,
"width": 800,
"height": 352,
"content": "# 🧠 AI 分析师"
},
"typeVersion": 1
},
{
"id": "5a9c2c81-2b56-4f42-b606-0dff90cb5242",
"name": "翻译器",
"type": "n8n-nodes-base.code",
"position": [
752,
-480
],
"parameters": {
"jsCode": "// Get the raw text output and remove any leading/trailing whitespace\nconst rawOutput = $input.first().json.output.trim();\nconst outputItems = [];\n\n// 1. Split the entire text into individual analysis blocks using \"---\"\nconst analyses = rawOutput.split('\\n---\\n');\n\n// 2. Loop through each text block\nfor (const chunk of analyses) {\n // Skip any empty blocks that might result from the split\n if (chunk.trim() === '') continue;\n\n const lines = chunk.trim().split('\\n');\n const cleanAnalysis = {};\n\n // 3. Loop through each line (e.g., \"Sentiment:: Positive\")\n for (const line of lines) {\n const parts = line.split('::');\n if (parts.length === 2) {\n // This part cleans up the key, e.g., \"Key Topic\" becomes \"keyTopic\"\n let key = parts[0].trim();\n key = key.charAt(0).toLowerCase() + key.slice(1).replace(/\\s+(\\w)/g, (match, letter) => letter.toUpperCase());\n \n const value = parts[1].trim();\n cleanAnalysis[key] = value;\n }\n }\n\n // 4. If we successfully built an object, add it to the output\n if (Object.keys(cleanAnalysis).length > 0) {\n outputItems.push({ json: cleanAnalysis });\n }\n}\n\nreturn outputItems;"
},
"typeVersion": 2
},
{
"id": "4c9bf29e-084e-47d1-8e69-c22b3bc34876",
"name": "推文抓取器",
"type": "n8n-nodes-base.httpRequest",
"position": [
432,
-1104
],
"parameters": {
"url": "https://api.twitterapi.io/twitter/tweet/advanced_search",
"options": {
"batching": {
"batch": {
"batchSize": 1,
"batchInterval": 2000
}
},
"pagination": {}
},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "query",
"value": "={{ $('Count').item.json.query }}"
},
{
"name": " queryType",
"value": "Latest"
},
{
"name": "cursor",
"value": "={{ $json.cursor }}"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"id": "wJgzPVfBYohOim1J",
"name": "twitter api io"
}
},
"typeVersion": 4.2
},
{
"id": "a2679e6f-eb6f-4e44-ac7f-a3f550a95976",
"name": "便签说明5",
"type": "n8n-nodes-base.stickyNote",
"position": [
640,
-320
],
"parameters": {
"width": 320,
"height": 512,
"content": "# 🧹 翻译器"
},
"typeVersion": 1
},
{
"id": "5c4fe7a8-3747-4489-8829-0d91b15919ce",
"name": "便签 6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1024,
-336
],
"parameters": {
"color": 4,
"width": 400,
"height": 720,
"content": "# 💾 系统内存"
},
"typeVersion": 1
},
{
"id": "ec4bf437-8fdb-468f-abda-06f98fc6d37c",
"name": "定时触发器",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-432,
-1008
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.2
},
{
"id": "331ce67e-1830-4cc6-82c0-7e5ea2ccad26",
"name": "AI 分析师",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
192,
-480
],
"parameters": {
"text": "=For each distinct post, identify the following: 1. **Sentiment:** Is it Positive, Negative, or Neutral/Question? 2. **Key Topic:** What is the main subject (e.g., \"Product Quality,\" \"Customer Service,\" \"App Bug,\" \"Sales Inquiry\")? 3. **Urgency:** Is this something that requires an immediate response (High), a normal response (Medium), or no response (Low)? 4. **Summary:** 5. **Tweet ID::** \n6.Briefly summarize the post in one sentence.\n\n**CRITICAL FORMATTING RULES:**\n1. Your entire response must ONLY be the extracted data. Do not add any introductory or concluding text like \"Here's the summary...\".\n2. Format each post's analysis using the exact `Key:: Value` structure shown in the example. Use a double colon `::` with no extra formatting.\n3. Separate each distinct post analysis with a single line containing only three dashes `---`.\n\n**EXAMPLE OUTPUT:**\n\nTweet ID:: 1234567890\nSentiment:: Positive\nKey Topic:: Product Quality\nUrgency:: Low\nSummary:: The user is praising the new feature and says it works perfectly.\n---\nTweet ID:: 9876543210\nSentiment:: Negative\nKey Topic:: App Bug\nUrgency:: High\nSummary:: The user reports that the app crashes on startup after the latest update.",
"options": {
"systemMessage": "You are an expert Social Media Brand Analyst for \"EmergentLabs\". Your goal is to create a strategic summary of recent brand mentions. To do this, you must first use your available tools to fetch the latest tweets from the database."
},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "6ecb4d34-0fb5-4467-b298-09ddcc98bc65",
"name": "Google Gemini聊天模型1",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
976,
1264
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"id": "sFPucaeaikoDAevM",
"name": "Google Gemini(PaLM) Api account 3"
}
},
"typeVersion": 1
},
{
"id": "3aff36f1-2d9d-4d7a-836c-8c622bc8d67c",
"name": "获取表格中的行",
"type": "n8n-nodes-base.googleSheets",
"position": [
304,
1024
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "Notmarked",
"lookupColumn": "action taken "
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 454621199,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c/edit#gid=454621199",
"cachedResultName": "Sheet2"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1SVkQU85XCFkr7KGvMxG61f9xuSD6qHf9CaSWo43LL3c/edit?usp=drivesdk",
"cachedResultName": "Tweet Data"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "6q55WdTedKPZERoF",
"name": "Google Sheets account 3"
}
},
"typeVersion": 4.7
},
{
"id": "bc97d230-329b-46d0-ba78-525ac0b0f6dc",
"name": "解析警报",
"type": "n8n-nodes-base.code",
"position": [
1472,
1104
],
"parameters": {
"jsCode": "// Get the full text output from the AI\nconst aiOutput = $input.first().json.text;\n\n// Regex to find the JSON code block\nconst jsonRegex = /```json\\n([\\s\\S]*?)```/;\nconst match = aiOutput.match(jsonRegex);\n\n// If we found a JSON block, parse it and return each object as a separate item\nif (match && match[1]) {\n try {\n const jsonString = match[1];\n const actionableTweets = JSON.parse(jsonString);\n\n if (Array.isArray(actionableTweets)) {\n // This returns multiple items, one for each urgent tweet\n return actionableTweets.map(tweet => ({ json: tweet }));\n }\n } catch (error) {\n console.log(\"Failed to parse JSON:\", error);\n return []; // Return nothing if JSON is broken\n }\n}\n\n// Return nothing if no JSON block was found\nreturn [];"
},
"typeVersion": 2
},
{
"id": "cc2e2d5e-1f82-4cac-a8d8-6b5229ebde78",
"name": "发送消息",
"type": "n8n-nodes-base.slack",
"position": [
1696,
912
],
"webhookId": "fd363969-823b-440f-8f1d-429edcb9702f",
"parameters": {
"text": "=📈 *Brand Sentry: Daily Strategic Briefing* 📈 *Generated on: {{ new Date().toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) }}* {{ $json.summaryReport }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09GMSQAHUP",
"cachedResultName": "brand-alerts"
},
"otherOptions": {
"includeLinkToWorkflow": false
},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "aTFdliaAoi5NenQp",
"name": "Slack account"
}
},
"typeVersion": 2.3
},
{
"id": "ede3bb3e-34b6-4a8f-b708-068cb54c5a87",
"name": "发送消息1",
"type": "n8n-nodes-base.slack",
"position": [
1920,
1104
],
"webhookId": "a50a8bd5-4016-4cb4-9920-3b51735ebc20",
"parameters": {
"text": "=🚨 *URGENT ACTION REQUIRED* 🚨 A social media mention has been flagged for immediate attention. *Urgency:* `{{ $json.urgency }}` *Reason:* {{ $json.reason }} *Tweet ID:* `{{ $json.tweetId }}` *Direct Link:* https://x.com/user/status/{{ $json.tweetId }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09HWHG5L8K",
"cachedResultName": "urgent"
},
"otherOptions": {
"includeLinkToWorkflow": false
},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "aTFdliaAoi5NenQp",
"name": "Slack account"
}
},
"typeVersion": 2.3
},
{
"id": "888243e5-3d56-4d5d-9e7b-9135e21282a2",
"name": "遍历项目",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1696,
1104
],
"parameters": {
"options": {
"reset": false
}
},
"typeVersion": 3
},
{
"id": "0f91c2bf-c478-4c5b-8a7b-96e747347d87",
"name": "策略师代理",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
944,
1008
],
"parameters": {
"text": "=You are a Social Media Insights Expert. Your task is to analyze the provided social media data and generate a two-part report.\n\n**Part 1: The Summary Report**\nBased on all the posts, generate a summary report with these sections:\n1. Overall Sentiment\n2. Key Themes\n3. Positive Testimonials\n4. Most Influential Post\n\n**Part 2: Actionable Items JSON**\nAfter the summary report, you MUST provide a section titled \"--- ACTIONABLE TWEETS JSON ---\" followed by a valid JSON array. This array should contain objects ONLY for the tweets that have an Urgency of \"High\" or \"Medium\".\n\nEach JSON object must have the following keys: \"tweetId\", \"urgency\", \"reason\".\n- \"tweetId\": The ID of the tweet.\n- \"urgency\": The assessed urgency (High or Medium).\n- \"reason\": A brief, one-sentence explanation of why this tweet is actionable (e.g., \"User reports a critical bug,\" \"User is very angry about billing,\" \"User is asking a direct question about documentation.\").\n\nHere is the data:\n{{ $json.preparedText }}\n\n\nExample of the final JSON output format:\n--- ACTIONABLE TWEETS JSON ---\n```json\n[\n {\n \"tweetId\": \"1969737770261438710\",\n \"urgency\": \"High\",\n \"reason\": \"User is strongly criticizing the product's core functionality, stating it 'SUCKS'.\"\n },\n {\n \"tweetId\": \"1941086912703504401\",\n \"urgency\": \"Medium\",\n \"reason\": \"User is asking for more detailed product documentation, which could be a sales opportunity.\"\n }\n]\n\n",
"batching": {
"batchSize": 1
},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "4d2ec48f-415f-4fd4-824f-27506b8f0cb7",
"name": "解析器",
"type": "n8n-nodes-base.code",
"position": [
608,
1072
],
"parameters": {
"jsCode": "const items = $input.all();\nlet combinedText = \"Here are the recent analyses to summarize:\\n\\n\";\nconst rowsToUpdate = [];\n\n// Loop through every row from the Google Sheet\nfor (const item of items) {\n const data = item.json;\n // Add the row number to our list for later\n rowsToUpdate.push({ rowNumber: item.json.rowNumber });\n \n // Create a neat summary for each analysis\n const entry = `\n---\nTweet ID: ${data.tweetId}\nSentiment: ${data.sentiment}\nKey Topic: ${data.keyTopic}\nUrgency: ${data.urgency}\nSummary: ${data.summary}\n---\n `;\n combinedText += entry;\n}\n\n// Return a SINGLE item with all the data we need\nreturn [{\n json: {\n preparedText: combinedText, // For the AI\n rowsToUpdate: rowsToUpdate // For the update step\n }\n}];"
},
"typeVersion": 2
},
{
"id": "55265036-18e2-44bb-8427-685219a56eea",
"name": "摘要",
"type": "n8n-nodes-base.code",
"position": [
1472,
912
],
"parameters": {
"jsCode": "// Get the full text output from the AI\nconst aiOutput = $input.first().json.text;\n\n// Define the delimiter that separates the summary from the JSON\nconst summaryDelimiter = \"--- ACTIONABLE TWEETS JSON ---\";\n\n// Find where the summary text ends\nconst summaryEndIndex = aiOutput.indexOf(summaryDelimiter);\n\n// The summary is everything before the delimiter. If delimiter isn't found, use the whole text.\nconst summaryReport = summaryEndIndex !== -1 ? aiOutput.substring(0, summaryEndIndex).trim() : aiOutput.trim();\n\n// Return a single item with just the summary report\nreturn [{ json: { summaryReport: summaryReport } }];"
},
"typeVersion": 2
},
{
"id": "65f4b982-4196-4315-9b8f-caf5a2c03388",
"name": "## 为什么选择 4o 模型?👆",
"type": "n8n-nodes-base.stickyNote",
"position": [
-512,
896
],
"parameters": {
"width": 512,
"height": 320,
"content": "# 🎯 策略师工作流"
},
"typeVersion": 1
},
{
"id": "15bd2e16-77cd-499a-9ca1-40b732a14a56",
"name": "便签 9",
"type": "n8n-nodes-base.stickyNote",
"position": [
16,
576
],
"parameters": {
"width": 480,
"height": 880,
"content": "# 📊 1. 读取\"待办\"列表"
},
"typeVersion": 1
},
{
"id": "b2f0cd05-fe05-486a-a7a6-604369ab4091",
"name": "便签10",
"type": "n8n-nodes-base.stickyNote",
"position": [
528,
592
],
"parameters": {
"width": 288,
"height": 864,
"content": "# 📚 2. 汇编简报书"
},
"typeVersion": 1
},
{
"id": "7b62b892-025c-4d71-9673-5a1ab509fb09",
"name": "便签11",
"type": "n8n-nodes-base.stickyNote",
"position": [
832,
560
],
"parameters": {
"color": 4,
"width": 416,
"height": 896,
"content": "# 👑 3. 策略师 AI"
},
"typeVersion": 1
},
{
"id": "71eb9e89-8314-4324-9b43-6441e9711b55",
"name": "便签12",
"type": "n8n-nodes-base.stickyNote",
"position": [
1264,
560
],
"parameters": {
"color": 5,
"width": 656,
"height": 496,
"content": "# 📜 4a. 摘要报告路径"
},
"typeVersion": 1
},
{
"id": "153bf685-006e-416c-aaf9-40b89625b2c1",
"name": "便签13",
"type": "n8n-nodes-base.stickyNote",
"position": [
1264,
1072
],
"parameters": {
"color": 3,
"width": 816,
"height": 496,
"content": "# 🚨 4b. 紧急警报路径"
},
"typeVersion": 1
},
{
"id": "a2d428b0-4ccd-4f74-a38e-35af8474022a",
"name": "计划触发器1",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
48,
1056
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 9
}
]
}
},
"typeVersion": 1.2
}
],
"pinData": {},
"connections": {
"If": {
"main": [
[
{
"node": "Aggregate",
"type": "main",
"index": 0
}
],
[
{
"node": "Limit",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "Append row in sheet",
"type": "main",
"index": 0
}
]
]
},
"Wait": {
"main": [
[
{
"node": "Tweet Scraper",
"type": "main",
"index": 0
}
]
]
},
"Code1": {
"main": [
[
{
"node": "set count and cursor",
"type": "main",
"index": 0
}
]
]
},
"Count": {
"main": [
[
{
"node": "counter",
"type": "main",
"index": 0
}
]
]
},
"Limit": {
"main": [
[
{
"node": "set increase",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "AI Analyst",
"type": "main",
"index": 0
}
],
[]
]
},
"parser": {
"main": [
[
{
"node": "Strategist Agent",
"type": "main",
"index": 0
}
]
]
},
"counter": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"summary": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
},
"Aggregate": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"AI Analyst": {
"main": [
[
{
"node": "Translator",
"type": "main",
"index": 0
}
]
]
},
"Translator": {
"main": [
[
{
"node": "Append row in sheet1",
"type": "main",
"index": 0
}
]
]
},
"parseAlerts": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"set increase": {
"main": [
[
{
"node": "Code1",
"type": "main",
"index": 0
}
]
]
},
"Tweet Scraper": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[],
[
{
"node": "Send a message1",
"type": "main",
"index": 0
}
]
]
},
"Send a message1": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Count",
"type": "main",
"index": 0
}
]
]
},
"Strategist Agent": {
"main": [
[
{
"node": "summary",
"type": "main",
"index": 0
},
{
"node": "parseAlerts",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger1": {
"main": [
[
{
"node": "Get row(s) in sheet",
"type": "main",
"index": 0
}
]
]
},
"Append row in sheet": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"Get row(s) in sheet": {
"main": [
[
{
"node": "parser",
"type": "main",
"index": 0
}
]
]
},
"Append row in sheet1": {
"main": [
[]
]
},
"set count and cursor": {
"main": [
[
{
"node": "counter",
"type": "main",
"index": 0
}
]
]
},
"getTweetsFromDatabase": {
"ai_tool": [
[
{
"node": "AI Analyst",
"type": "ai_tool",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Analyst",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Google Gemini Chat Model1": {
"ai_languageModel": [
[
{
"node": "Strategist Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
在可视化参考库中探索n8n节点
在可视化参考库中探索n8n节点
If
Ftp
Set
+93
113 节点I versus AI
其他
WordPress博客自动化专业版(深度研究)v2.1市场
使用GPT-4o、Perplexity AI和多语言支持自动化SEO优化的博客创建
If
Set
Xml
+27
125 节点Daniel Ng
内容创作
(Duc)深度研究市场模板
集成PerplexityAI研究和OpenAI内容的多层级WordPress博客生成器
If
Set
Xml
+28
132 节点Daniel Ng
人工智能
宠物店 4
🐶 宠物店预约 AI 代理
If
Set
Code
+41
187 节点Bruno Dias
人工智能
LinkedIn和X病毒内容自动引擎
使用AI生成和发布自动创建LinkedIn和X的病毒内容
If
Set
Wait
+26
156 节点Diptamoy Barman
内容创作
每日 WhatsApp 群组智能分析:GPT-4.1 分析与语音消息转录
每日 WhatsApp 群组智能分析:GPT-4.1 分析与语音消息转录
If
Set
Code
+20
52 节点Daniel Lianes
杂项