feat: add folder support for workflows (fixes #70)

This commit is contained in:
Praveen Mudalgeri
2025-08-05 09:40:47 +05:30
parent 307d530f9b
commit c4885eee92
2057 changed files with 985290 additions and 974268 deletions

View File

@@ -0,0 +1,231 @@
{
"nodes": [
{
"name": "Cron",
"type": "n8n-nodes-base.cron",
"position": [
-700,
1500
],
"parameters": {
"triggerTimes": {
"item": [
{
"hour": 10,
"mode": "everyWeek"
}
]
}
},
"typeVersion": 1
},
{
"name": "Shopify",
"type": "n8n-nodes-base.shopify",
"position": [
-500,
1500
],
"parameters": {
"options": {},
"operation": "getAll"
},
"credentials": {
"shopifyApi": "shopify_nodeqa"
},
"typeVersion": 1
},
{
"name": "Function",
"type": "n8n-nodes-base.function",
"position": [
300,
1400
],
"parameters": {
"functionCode": "let totalOrders = items.length;\nlet ordersSum = 0;\n\nfor(let i=0; i < items.length; i++) {\n ordersSum = ordersSum + parseFloat(items[i].json.orderPrice);\n}\nreturn [{json:{totalOrders, ordersSum}}]"
},
"typeVersion": 1
},
{
"name": "Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
500,
1500
],
"parameters": {
"options": {},
"sheetId": "1GVyV1yYwWZu510NTzVgi2RyesrsnuP3RxXmWbX1O7DQ",
"operation": "append",
"authentication": "oAuth2"
},
"credentials": {
"googleSheetsOAuth2Api": "google_sheets_oauth"
},
"typeVersion": 1
},
{
"name": "Slack",
"type": "n8n-nodes-base.slack",
"position": [
500,
1300
],
"parameters": {
"text": "=Hey team, this week we had {{$json[\"totalOrders\"]}} orders with a total value of € {{$json[\"ordersSum\"]}}.",
"channel": "shopify",
"attachments": [],
"otherOptions": {}
},
"credentials": {
"slackApi": "slack_nodeqa"
},
"typeVersion": 1
},
{
"name": "Date & Time",
"type": "n8n-nodes-base.dateTime",
"position": [
-300,
1500
],
"parameters": {
"value": "={{$json[\"created_at\"]}}",
"options": {},
"dataPropertyName": "order_date"
},
"typeVersion": 1
},
{
"name": "IF",
"type": "n8n-nodes-base.if",
"position": [
-100,
1500
],
"parameters": {
"conditions": {
"dateTime": [
{
"value1": "={{$node[\"Date & Time\"].json[\"order_date\"]}}",
"value2": "2021-08-17T15:00:53.223Z"
}
]
}
},
"typeVersion": 1
},
{
"name": "NoOp",
"type": "n8n-nodes-base.noOp",
"position": [
100,
1600
],
"parameters": {},
"typeVersion": 1
},
{
"name": "Set price",
"type": "n8n-nodes-base.set",
"position": [
100,
1400
],
"parameters": {
"values": {
"number": [
{
"name": "orderPrice",
"value": "={{$json[\"total_price\"]}}"
}
]
},
"options": {},
"keepOnlySet": true
},
"typeVersion": 1
}
],
"connections": {
"IF": {
"main": [
[
{
"node": "Set price",
"type": "main",
"index": 0
}
],
[
{
"node": "NoOp",
"type": "main",
"index": 0
}
]
]
},
"Cron": {
"main": [
[
{
"node": "Shopify",
"type": "main",
"index": 0
}
]
]
},
"Shopify": {
"main": [
[
{
"node": "Date & Time",
"type": "main",
"index": 0
}
]
]
},
"Function": {
"main": [
[
{
"node": "Slack",
"type": "main",
"index": 0
},
{
"node": "Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Set price": {
"main": [
[
{
"node": "Function",
"type": "main",
"index": 0
}
]
]
},
"Date & Time": {
"main": [
[
{
"node": "IF",
"type": "main",
"index": 0
}
]
]
}
}
}

View File

@@ -0,0 +1,340 @@
{
"nodes": [
{
"name": "On clicking 'execute'",
"type": "n8n-nodes-base.manualTrigger",
"position": [
240,
300
],
"parameters": {},
"typeVersion": 1
},
{
"name": "Item Lists",
"type": "n8n-nodes-base.itemLists",
"position": [
1120,
300
],
"parameters": {
"options": {},
"fieldToSplitOut": "post"
},
"typeVersion": 1
},
{
"name": "Extract Posts",
"type": "n8n-nodes-base.htmlExtract",
"position": [
900,
300
],
"parameters": {
"options": {},
"extractionValues": {
"values": [
{
"key": "post",
"cssSelector": ".blog-listing__post-content",
"returnArray": true,
"returnValue": "html"
}
]
}
},
"typeVersion": 1
},
{
"name": "Fetch Website",
"type": "n8n-nodes-base.httpRequest",
"position": [
680,
300
],
"parameters": {
"url": "={{$json[\"base_domain\"]}}/blog/category/release",
"options": {
"timeout": 10000
},
"responseFormat": "string"
},
"typeVersion": 1
},
{
"name": "Set URL",
"type": "n8n-nodes-base.set",
"position": [
460,
300
],
"parameters": {
"values": {
"string": [
{
"name": "base_domain",
"value": "https://baserow.io"
}
]
},
"options": {}
},
"typeVersion": 1
},
{
"name": "Complete Link",
"type": "n8n-nodes-base.set",
"position": [
240,
500
],
"parameters": {
"values": {
"string": [
{
"name": "link",
"value": "={{$item(0).$node[\"Set URL\"].json[\"base_domain\"]}}{{$json[\"link\"]}}"
}
]
},
"options": {}
},
"typeVersion": 1
},
{
"name": "Format Date",
"type": "n8n-nodes-base.dateTime",
"position": [
460,
500
],
"parameters": {
"value": "={{$json[\"date\"]}}",
"options": {},
"toFormat": "YYYY-MM-DD",
"dataPropertyName": "date"
},
"typeVersion": 1
},
{
"name": "Create RSS Items",
"type": "n8n-nodes-base.functionItem",
"position": [
680,
500
],
"parameters": {
"functionCode": "return {\n rss_item: \n`<item>\n <title>${item.title}</title>\n <link>${item.link}</link>\n <description>${item.description}</description>\n <pubDate>${item.date}</pubDate>\n</item>`\n}"
},
"typeVersion": 1
},
{
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
240,
100
],
"webhookId": "27c1e4db-568f-4bf9-9474-0898ce1173f7",
"parameters": {
"path": "baserow-releases",
"options": {},
"responseMode": "responseNode"
},
"typeVersion": 1
},
{
"name": "Respond to Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1120,
500
],
"parameters": {
"options": {
"responseHeaders": {
"entries": [
{
"name": "content-type",
"value": "application/xml"
}
]
}
},
"respondWith": "text",
"responseBody": "={{$json[\"feed\"]}}"
},
"typeVersion": 1
},
{
"name": "Prepare Response",
"type": "n8n-nodes-base.function",
"position": [
900,
500
],
"parameters": {
"functionCode": "let feed =\n`<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<rss version=\"2.0\">\n\n<channel>\n <title>Baserow Releases</title>\n <link>https://baserow.io/blog/category/release</link>\n <description>Stay up to date with the latest changes and updates of Baserow</description>\n ${items.map(e => e.json.rss_item).join('\\n')}\n</channel>\n\n</rss>`;\n\nreturn [{\n json: {\n feed: feed\n }\n}];"
},
"typeVersion": 1
},
{
"name": "Extract Fields",
"type": "n8n-nodes-base.htmlExtract",
"position": [
1340,
300
],
"parameters": {
"options": {},
"dataPropertyName": "post",
"extractionValues": {
"values": [
{
"key": "date",
"cssSelector": ".blog-listing__post-info > strong"
},
{
"key": "title",
"cssSelector": ".blog-listing__post-title"
},
{
"key": "link",
"attribute": "href",
"cssSelector": ".blog-listing__post-title > a",
"returnValue": "attribute"
},
{
"key": "description",
"cssSelector": ".blog-listing__post-description"
}
]
}
},
"typeVersion": 1
}
],
"connections": {
"Set URL": {
"main": [
[
{
"node": "Fetch Website",
"type": "main",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "Set URL",
"type": "main",
"index": 0
}
]
]
},
"Item Lists": {
"main": [
[
{
"node": "Extract Fields",
"type": "main",
"index": 0
}
]
]
},
"Format Date": {
"main": [
[
{
"node": "Create RSS Items",
"type": "main",
"index": 0
}
]
]
},
"Complete Link": {
"main": [
[
{
"node": "Format Date",
"type": "main",
"index": 0
}
]
]
},
"Extract Posts": {
"main": [
[
{
"node": "Item Lists",
"type": "main",
"index": 0
}
]
]
},
"Fetch Website": {
"main": [
[
{
"node": "Extract Posts",
"type": "main",
"index": 0
}
]
]
},
"Extract Fields": {
"main": [
[
{
"node": "Complete Link",
"type": "main",
"index": 0
}
]
]
},
"Create RSS Items": {
"main": [
[
{
"node": "Prepare Response",
"type": "main",
"index": 0
}
]
]
},
"Prepare Response": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"On clicking 'execute'": {
"main": [
[
{
"node": "Set URL",
"type": "main",
"index": 0
}
]
]
}
}
}

View File

@@ -0,0 +1,393 @@
{
"meta": {
"instanceId": "8c8c5237b8e37b006a7adce87f4369350c58e41f3ca9de16196d3197f69eabcd"
},
"nodes": [
{
"id": "6f869392-1501-49b9-be86-4b767f7ec597",
"name": "Previous Month",
"type": "n8n-nodes-base.dateTime",
"position": [
360,
420
],
"parameters": {
"value": "={{Date()}}",
"action": "calculate",
"options": {},
"duration": 1,
"timeUnit": "months",
"operation": "subtract"
},
"typeVersion": 1
},
{
"id": "1446eb44-bd1e-4dad-9ecc-c2a1e8cb2ca6",
"name": "1st of Every month at 8am",
"type": "n8n-nodes-base.cron",
"position": [
180,
420
],
"parameters": {
"triggerTimes": {
"item": [
{
"hour": 8,
"mode": "everyMonth"
}
]
}
},
"typeVersion": 1
},
{
"id": "a044ac76-49d9-4046-b008-2b4adf6512b1",
"name": "Check Summary for Illness or Holiday",
"type": "n8n-nodes-base.switch",
"position": [
760,
420
],
"parameters": {
"rules": {
"rules": [
{
"value2": "Holiday",
"operation": "contains"
},
{
"output": 1,
"value2": "Illness",
"operation": "contains"
}
]
},
"value1": "={{$json[\"summary\"]}}",
"dataType": "string"
},
"typeVersion": 1
},
{
"id": "6b40beab-7938-4aaa-a8a8-7a1e364dc2de",
"name": "Holiday",
"type": "n8n-nodes-base.noOp",
"position": [
980,
220
],
"parameters": {},
"typeVersion": 1
},
{
"id": "b069f3ce-66d1-4f64-946b-f9fda27db46b",
"name": "Illness",
"type": "n8n-nodes-base.noOp",
"position": [
980,
400
],
"parameters": {},
"typeVersion": 1
},
{
"id": "5725626b-2bfd-47a0-947e-efd28f0c29fe",
"name": "Filter Holiday Days",
"type": "n8n-nodes-base.set",
"position": [
1180,
220
],
"parameters": {
"values": {
"string": [
{
"name": "Name",
"value": "={{$json[\"description\"].split(\",\")[0]}}"
},
{
"name": "Days",
"value": "={{(new Date($json[\"end\"][\"date\"]).getTime() - new Date($json[\"start\"][\"date\"]).getTime()) / (1000 * 3600 * 24)}}"
},
{
"name": "Type",
"value": "Holiday"
}
]
},
"options": {},
"keepOnlySet": true
},
"typeVersion": 1
},
{
"id": "3114eb4f-a5be-452c-9729-b94d2904eb4b",
"name": "Filter Illness Days",
"type": "n8n-nodes-base.set",
"position": [
1180,
400
],
"parameters": {
"values": {
"string": [
{
"name": "Name",
"value": "={{$json[\"description\"].split(\",\")[0]}}"
},
{
"name": "Days",
"value": "={{(new Date($json[\"end\"][\"date\"]).getTime() - new Date($json[\"start\"][\"date\"]).getTime()) / (1000 * 3600 * 24)}}"
},
{
"name": "Type",
"value": "Illness"
}
]
},
"options": {},
"keepOnlySet": true
},
"typeVersion": 1
},
{
"id": "04617849-c162-4af5-9634-ab8ffd925625",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
1620,
320
],
"parameters": {},
"typeVersion": 1
},
{
"id": "daf227d9-938d-4110-9a47-5bf8bb661586",
"name": "Get previous months events",
"type": "n8n-nodes-base.googleCalendar",
"position": [
560,
420
],
"parameters": {
"options": {
"timeMax": "={{new Date().toISOString()}}",
"timeMin": "={{$json[\"data\"]}}"
},
"calendar": "[Select Cal]",
"operation": "getAll",
"returnAll": true
},
"credentials": {
"googleCalendarOAuth2Api": {
"id": "50",
"name": "Google Calendar account"
}
},
"typeVersion": 1
},
{
"id": "19ec862a-e71a-49f9-b799-26f73a410553",
"name": "Send email to payroll",
"type": "n8n-nodes-base.emailSend",
"position": [
1980,
320
],
"parameters": {
"text": "={{$json[\"message\"]}}",
"options": {},
"subject": "Absences from last month",
"toEmail": "payroll-team@mydomain.tld",
"fromEmail": "n8n@mydomain.tld"
},
"credentials": {
"smtp": {
"id": "16",
"name": "mailtrap"
}
},
"typeVersion": 1
},
{
"id": "5805b2e1-e723-4803-a7e0-8df5fd4cf84d",
"name": "Combine Holiday Counts",
"type": "n8n-nodes-base.code",
"position": [
1380,
220
],
"parameters": {
"jsCode": "let names = $input.all().map(e => e.json.Name);\nlet unique_names = [...new Set(names)];\nlet results = [];\n\nfor (thisName of unique_names) {\n let result = {\n \"Name\": thisName,\n \"Days\": 0,\n \"Type\": \"Holiday\"\n }\n\n for (matching_item of $input.all().filter(e => e.json.Name === thisName)) {\n result.Days += parseInt(matching_item.json.Days);\n }\n \n results.push(result);\n}\n\nreturn results.map(e => { return {json: e} });"
},
"typeVersion": 1
},
{
"id": "c30345ae-1a19-4453-a67b-eda71cb7326e",
"name": "Combine Illness Counts",
"type": "n8n-nodes-base.code",
"position": [
1380,
400
],
"parameters": {
"jsCode": "let names = $input.all().map(e => e.json.Name);\nlet unique_names = [...new Set(names)];\nlet results = [];\n\nfor (thisName of unique_names) {\n let result = {\n \"Name\": thisName,\n \"Days\": 0,\n \"Type\": \"Illness\"\n }\n\n for (matching_item of $input.all().filter(e => e.json.Name === thisName)) {\n result.Days += parseInt(matching_item.json.Days);\n }\n \n results.push(result);\n}\n\nreturn results.map(e => { return {json: e} });"
},
"typeVersion": 1
},
{
"id": "7bac2604-ca55-4300-a7a5-38fc96830ba6",
"name": "Build the message to send",
"type": "n8n-nodes-base.code",
"position": [
1800,
320
],
"parameters": {
"jsCode": "let illnessMessage = \"\";\nlet holidayMessage = \"\";\nlet message = \"Here is a breakdown of absences for the last month.\\n\\n\";\n\n// Loop the input items\nfor (item of $input.all()) {\n if (item.json.Type == \"Holiday\") {\n holidayMessage += item.json.Name + \" had \" + item.json.Days + \" days\\n\";\n }\n if (item.json.Type == \"Illness\") {\n illnessMessage += item.json.Name + \" had \" + item.json.Days + \" days\\n\";\n }\n}\n\nif (holidayMessage != \"\") {\n message += \"Holiday Events\\n\";\n message += holidayMessage + \"\\n\";\n} else {\n message += \"No Holiday Events\\n\";\n}\n\nif (illnessMessage != \"\") {\n message += \"Illness Events\\n\";\n message += illnessMessage;\n} else {\n message += \"No Illness Events\\n\";\n}\n\n// Return our message\nreturn [{json: {message}}];"
},
"typeVersion": 1
}
],
"connections": {
"Merge": {
"main": [
[
{
"node": "Build the message to send",
"type": "main",
"index": 0
}
]
]
},
"Holiday": {
"main": [
[
{
"node": "Filter Holiday Days",
"type": "main",
"index": 0
}
]
]
},
"Illness": {
"main": [
[
{
"node": "Filter Illness Days",
"type": "main",
"index": 0
}
]
]
},
"Previous Month": {
"main": [
[
{
"node": "Get previous months events",
"type": "main",
"index": 0
}
]
]
},
"Filter Holiday Days": {
"main": [
[
{
"node": "Combine Holiday Counts",
"type": "main",
"index": 0
}
]
]
},
"Filter Illness Days": {
"main": [
[
{
"node": "Combine Illness Counts",
"type": "main",
"index": 0
}
]
]
},
"Combine Holiday Counts": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Combine Illness Counts": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"1st of Every month at 8am": {
"main": [
[
{
"node": "Previous Month",
"type": "main",
"index": 0
}
]
]
},
"Build the message to send": {
"main": [
[
{
"node": "Send email to payroll",
"type": "main",
"index": 0
}
]
]
},
"Get previous months events": {
"main": [
[
{
"node": "Check Summary for Illness or Holiday",
"type": "main",
"index": 0
}
]
]
},
"Check Summary for Illness or Holiday": {
"main": [
[
{
"node": "Holiday",
"type": "main",
"index": 0
}
],
[
{
"node": "Illness",
"type": "main",
"index": 0
}
]
]
}
}
}

View File

@@ -0,0 +1,474 @@
{
"meta": {
"instanceId": "a2434c94d549548a685cca39cc4614698e94f527bcea84eefa363f1037ae14cd"
},
"nodes": [
{
"id": "0bacf032-53d6-4ba6-ab71-e01625c49cc4",
"name": "On schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1960,
160
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 1
}
]
}
},
"typeVersion": 1.1
},
{
"id": "2e0d9aef-0a60-4506-9c11-c6c2cccb16ea",
"name": "Derive last request time",
"type": "n8n-nodes-base.dateTime",
"position": [
-1740,
160
],
"parameters": {
"duration": 1,
"timeUnit": "minutes",
"magnitude": "={{ $json.timestamp }}",
"operation": "subtractFromDate",
"outputFieldName": "last_request_time"
},
"typeVersion": 2
},
{
"id": "f726c448-b4c4-4159-8ca5-c94c092127b7",
"name": "Get emails from label and last request time",
"type": "n8n-nodes-base.gmail",
"position": [
-1520,
160
],
"parameters": {
"filters": {
"labelIds": [
"Label_9178764513576607415"
]
},
"operation": "getAll",
"returnAll": true
},
"credentials": {
"gmailOAuth2": {
"id": "31",
"name": "REPLACE ME"
}
},
"typeVersion": 2
},
{
"id": "9b86331f-d33b-4266-ba34-bc0491a0da24",
"name": "Create database page",
"type": "n8n-nodes-base.notion",
"position": [
-620,
60
],
"parameters": {
"title": "={{ $('If database page not found').item.json.Subject }}",
"blockUi": {
"blockValues": [
{
"type": "heading_3",
"textContent": "Snippet"
},
{
"textContent": "={{ $('If database page not found').item.json.snippet }}"
},
{
"text": {
"text": [
{
"text": "See more",
"isLink": true,
"textLink": "=https://mail.google.com/mail/u/{{ $json.emailAddress }}/#all/{{ $('If database page not found').item.json.id }}",
"annotationUi": {}
}
]
},
"richText": true
}
]
},
"options": {
"icon": "https://avatars.githubusercontent.com/u/45487711?s=280&v=4",
"iconType": "file"
},
"resource": "databasePage",
"databaseId": {
"__rl": true,
"mode": "list",
"value": "e606a7c1-e93d-47fd-8b8d-8000cd6e7522",
"cachedResultUrl": "https://www.notion.so/e606a7c1e93d47fd8b8d8000cd6e7522",
"cachedResultName": "Gmail"
},
"propertiesUi": {
"propertyValues": [
{
"key": "Thread ID|rich_text",
"textContent": "={{ $('If database page not found').item.json.id }}"
},
{
"key": "Email thread|url",
"urlValue": "=https://mail.google.com/mail/u/{{ $json.emailAddress }}/#all/{{ $('If database page not found').item.json.id }}"
}
]
}
},
"credentials": {
"notionApi": {
"id": "18",
"name": "[UPDATE ME]"
}
},
"typeVersion": 2
},
{
"id": "d7198578-4c83-4f57-8eba-5b5a9b89195c",
"name": "Try get database page",
"type": "n8n-nodes-base.notion",
"position": [
-1360,
220
],
"parameters": {
"filters": {
"conditions": [
{
"key": "Thread ID|rich_text",
"condition": "equals",
"richTextValue": "={{ $json.id }}"
}
]
},
"options": {},
"resource": "databasePage",
"operation": "getAll",
"returnAll": true,
"databaseId": {
"__rl": true,
"mode": "list",
"value": "e606a7c1-e93d-47fd-8b8d-8000cd6e7522",
"cachedResultUrl": "https://www.notion.so/e606a7c1e93d47fd8b8d8000cd6e7522",
"cachedResultName": "My Gmail Tasks"
},
"filterType": "manual"
},
"credentials": {
"notionApi": {
"id": "18",
"name": "[UPDATE ME]"
}
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "f8188ab9-9a80-4aa9-b773-73cd90b8dbd3",
"name": "If checked off",
"type": "n8n-nodes-base.if",
"position": [
-1740,
460
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.Complete }}",
"value2": true
}
]
}
},
"typeVersion": 1
},
{
"id": "bfcfeeb1-ad8b-47fb-8a09-b58e7b649a25",
"name": "On updated database page",
"type": "n8n-nodes-base.notionTrigger",
"position": [
-1960,
460
],
"parameters": {
"event": "pagedUpdatedInDatabase",
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"databaseId": {
"__rl": true,
"mode": "list",
"value": "e606a7c1-e93d-47fd-8b8d-8000cd6e7522",
"cachedResultUrl": "https://www.notion.so/e606a7c1e93d47fd8b8d8000cd6e7522",
"cachedResultName": "My Gmail Tasks"
}
},
"credentials": {
"notionApi": {
"id": "18",
"name": "[UPDATE ME]"
}
},
"typeVersion": 1
},
{
"id": "dc2c59b8-6e0d-46b3-946a-e48b0461c48f",
"name": "Remove label from target email",
"type": "n8n-nodes-base.gmail",
"position": [
-1520,
460
],
"parameters": {
"labelIds": [
"Label_9178764513576607415"
],
"messageId": "={{ $json['Thread ID'] }}",
"operation": "removeLabels"
},
"credentials": {
"gmailOAuth2": {
"id": "31",
"name": "REPLACE ME"
}
},
"typeVersion": 2
},
{
"id": "0f693c2f-ce89-4a2f-a85f-9230b7bcb94d",
"name": "Not yet checked off, do nothing",
"type": "n8n-nodes-base.noOp",
"position": [
-1520,
660
],
"parameters": {},
"typeVersion": 1
},
{
"id": "bf792470-fc0a-45a2-b655-df5c977faa97",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
-1220,
100
],
"parameters": {
"mode": "combine",
"options": {},
"joinMode": "enrichInput1",
"mergeByFields": {
"values": [
{
"field1": "id",
"field2": "property_thread_id"
}
]
}
},
"typeVersion": 2.1
},
{
"id": "f910c34c-4c3d-481f-8223-a8aae710dbbd",
"name": "If found, do nothing",
"type": "n8n-nodes-base.noOp",
"position": [
-840,
260
],
"parameters": {},
"typeVersion": 1
},
{
"id": "7086cd15-9f2e-40e4-be3b-47d117dde670",
"name": "If database page not found",
"type": "n8n-nodes-base.if",
"position": [
-1060,
160
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.property_thread_id }}",
"operation": "isEmpty"
}
]
}
},
"typeVersion": 1
},
{
"id": "86ce380c-0810-4edb-94e4-fb67b0ca422c",
"name": "Find my email address",
"type": "n8n-nodes-base.httpRequest",
"position": [
-840,
60
],
"parameters": {
"url": "https://gmail.googleapis.com/gmail/v1/users/me/profile",
"options": {},
"authentication": "predefinedCredentialType",
"nodeCredentialType": "gmailOAuth2"
},
"credentials": {
"gmailOAuth2": {
"id": "31",
"name": "REPLACE ME"
}
},
"typeVersion": 4.1
},
{
"id": "f576f785-49e4-4ed2-b83e-400b001b6c3a",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2540,
100
],
"parameters": {
"width": 501.0810810810809,
"height": 545.405405405404,
"content": "## Send labeled email to a Notion database\nThis workflow sends the contents of an email to a Notion database. The email must be labeled with a specific label for the workflow to trigger. The email subject will be the title of the Notion page, and a snippet of the email body will be the content of the Notion page. The email link will be added to the Notion page as a property.\n\n### How it works\nOn scheduled intervals, find all emails with a specific label. For each email, check if the email already exists in the Notion database. If it does not exist, create a new page in the Notion database, otherwise do nothing. When the task in the Notion database is checked off, the label will be removed from the email.\n\n### Setup\nThis workflow requires that you set up a Notion database or use an existing one with at least the following fields:\n- Title (title)\n- Thread ID (text)\n- Email thread (URL)\n\n\nAdditionally, create a label that will be used to trigger the workflow in Gmail. In this workflow, the label is called \"Notion\"."
},
"typeVersion": 1
}
],
"connections": {
"Merge": {
"main": [
[
{
"node": "If database page not found",
"type": "main",
"index": 0
}
]
]
},
"On schedule": {
"main": [
[
{
"node": "Derive last request time",
"type": "main",
"index": 0
}
]
]
},
"If checked off": {
"main": [
[
{
"node": "Remove label from target email",
"type": "main",
"index": 0
}
],
[
{
"node": "Not yet checked off, do nothing",
"type": "main",
"index": 0
}
]
]
},
"Find my email address": {
"main": [
[
{
"node": "Create database page",
"type": "main",
"index": 0
}
]
]
},
"Try get database page": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Derive last request time": {
"main": [
[
{
"node": "Get emails from label and last request time",
"type": "main",
"index": 0
}
]
]
},
"On updated database page": {
"main": [
[
{
"node": "If checked off",
"type": "main",
"index": 0
}
]
]
},
"If database page not found": {
"main": [
[
{
"node": "Find my email address",
"type": "main",
"index": 0
}
],
[
{
"node": "If found, do nothing",
"type": "main",
"index": 0
}
]
]
},
"Get emails from label and last request time": {
"main": [
[
{
"node": "Try get database page",
"type": "main",
"index": 0
},
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
}
}
}

View File

@@ -0,0 +1,359 @@
{
"meta": {
"instanceId": "a2434c94d549548a685cca39cc4614698e94f527bcea84eefa363f1037ae14cd"
},
"nodes": [
{
"id": "713d2864-efd0-4938-871e-1d37a7c58b67",
"name": "On schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
1280,
840
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "0cedfde1-6ae1-485c-bd2c-b6114f6e4deb",
"name": "Try get database page",
"type": "n8n-nodes-base.notion",
"position": [
2160,
900
],
"parameters": {
"filters": {
"conditions": [
{
"key": "Event ID|rich_text",
"condition": "equals",
"richTextValue": "={{ $json.id }}"
}
]
},
"options": {},
"resource": "databasePage",
"operation": "getAll",
"returnAll": true,
"databaseId": {
"__rl": true,
"mode": "list",
"value": "6318457d-052d-4107-9c5b-8041f530fa03",
"cachedResultUrl": "https://www.notion.so/6318457d052d41079c5b8041f530fa03",
"cachedResultName": "Outlook Calendar"
},
"filterType": "manual"
},
"credentials": {
"notionApi": {
"id": "18",
"name": "[UPDATE ME]"
}
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "92ebdd55-0950-471c-aa44-2fed31b17870",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
2380,
780
],
"parameters": {
"mode": "combine",
"options": {},
"joinMode": "enrichInput1",
"mergeByFields": {
"values": [
{
"field1": "id",
"field2": "property_event_id"
}
]
}
},
"typeVersion": 2.1
},
{
"id": "d38e4228-b3ab-443f-bfac-ffd0bc10fd08",
"name": "If database page not found",
"type": "n8n-nodes-base.if",
"position": [
2600,
840
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.property_event_id }}",
"operation": "isEmpty"
}
]
}
},
"typeVersion": 1
},
{
"id": "6ef0f18c-51fe-42e7-9e42-fd6ca8564e6e",
"name": "Create database page",
"type": "n8n-nodes-base.notion",
"position": [
2820,
740
],
"parameters": {
"title": "={{ $json.subject }}",
"options": {
"icon": "https://avatars.githubusercontent.com/u/45487711?s=280&v=4",
"iconType": "file"
},
"resource": "databasePage",
"databaseId": {
"__rl": true,
"mode": "list",
"value": "6318457d-052d-4107-9c5b-8041f530fa03",
"cachedResultUrl": "https://www.notion.so/6318457d052d41079c5b8041f530fa03",
"cachedResultName": "Outlook Calendar"
},
"propertiesUi": {
"propertyValues": [
{
"key": "Date|date",
"range": true,
"dateEnd": "={{ $json.end.dateTime }}",
"timezone": "={{ $json.start.timeZone }}",
"dateStart": "={{ $json.start.dateTime }}"
},
{
"key": "Event ID|rich_text",
"textContent": "={{ $json.id }}"
},
{
"key": "Link|url",
"urlValue": "={{ $json.webLink }}"
}
]
}
},
"credentials": {
"notionApi": {
"id": "18",
"name": "[UPDATE ME]"
}
},
"typeVersion": 2
},
{
"id": "2d324002-348b-4f23-bffe-57f685a8a761",
"name": "Update database page",
"type": "n8n-nodes-base.notion",
"position": [
2820,
940
],
"parameters": {
"pageId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.id }}"
},
"resource": "databasePage",
"operation": "update",
"propertiesUi": {
"propertyValues": [
{
"key": "Date|date",
"range": true,
"dateEnd": "={{ $json.end.dateTime }}",
"timezone": "={{ $json.start.timeZone }}",
"dateStart": "={{ $json.start.dateTime }}"
},
{
"key": "Link|url",
"urlValue": "={{ $json.webLink }}"
},
{
"key": "Name|title",
"title": "={{ $json.subject }}"
}
]
}
},
"credentials": {
"notionApi": {
"id": "18",
"name": "[UPDATE ME]"
}
},
"typeVersion": 2
},
{
"id": "ee4792c4-d71c-4fd3-a8a3-babae5ff3479",
"name": "X days into the future",
"type": "n8n-nodes-base.dateTime",
"position": [
1500,
840
],
"parameters": {
"duration": 365,
"magnitude": "={{ $json.timestamp }}",
"operation": "addToDate",
"outputFieldName": "Future date"
},
"typeVersion": 2
},
{
"id": "00b53a21-97c7-4293-a5eb-8321afddd4bc",
"name": "Split out items",
"type": "n8n-nodes-base.itemLists",
"position": [
1940,
840
],
"parameters": {
"options": {},
"fieldToSplitOut": "value"
},
"typeVersion": 2.2
},
{
"id": "a7541bb9-0c0d-48b5-a39e-57e5681330da",
"name": "Get Outlook Calendar events",
"type": "n8n-nodes-base.httpRequest",
"position": [
1720,
840
],
"parameters": {
"url": "https://graph.microsoft.com/v1.0/me/calendarview",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "oAuth2Api",
"queryParameters": {
"parameters": [
{
"name": "startdatetime",
"value": "={{ new Date($('On schedule').item.json.timestamp).toISOString() }}"
},
{
"name": "enddatetime",
"value": "={{ new Date($json['Future date']).toISOString() }}"
}
]
}
},
"credentials": {
"oAuth2Api": {
"id": "dxBfWhTrnERPMHGs",
"name": "REPLACE ME"
}
},
"typeVersion": 4.1
}
],
"connections": {
"Merge": {
"main": [
[
{
"node": "If database page not found",
"type": "main",
"index": 0
}
]
]
},
"On schedule": {
"main": [
[
{
"node": "X days into the future",
"type": "main",
"index": 0
}
]
]
},
"Split out items": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
},
{
"node": "Try get database page",
"type": "main",
"index": 0
}
]
]
},
"Try get database page": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"X days into the future": {
"main": [
[
{
"node": "Get Outlook Calendar events",
"type": "main",
"index": 0
}
]
]
},
"If database page not found": {
"main": [
[
{
"node": "Create database page",
"type": "main",
"index": 0
}
],
[
{
"node": "Update database page",
"type": "main",
"index": 0
}
]
]
},
"Get Outlook Calendar events": {
"main": [
[
{
"node": "Split out items",
"type": "main",
"index": 0
}
]
]
}
}
}

View File

@@ -0,0 +1,196 @@
{
"id": 1,
"name": "Google Cal to Zoom meeting",
"nodes": [
{
"name": "On clicking 'execute'",
"type": "n8n-nodes-base.manualTrigger",
"position": [
0,
330
],
"parameters": {},
"typeVersion": 1
},
{
"name": "Zoom",
"type": "n8n-nodes-base.zoom",
"position": [
380,
410
],
"parameters": {
"topic": "=Meeting with {{$node[\"IF Zoom meeting\"].json[\"summary\"]}}",
"authentication": "oAuth2",
"additionalFields": {
"duration": "={{(Date.parse($node[\"IF Zoom meeting\"].json[\"end\"][\"dateTime\"])-Date.parse($node[\"IF Zoom meeting\"].json[\"start\"][\"dateTime\"]))/(60*1000)}}",
"settings": {},
"timeZone": "={{$node[\"IF Zoom meeting\"].json[\"start\"][\"timeZone\"]}}",
"startTime": "={{$node[\"IF Zoom meeting\"].json[\"start\"][\"dateTime\"]}}"
}
},
"credentials": {
"zoomOAuth2Api": {
"id": "3",
"name": "Zoom account"
}
},
"typeVersion": 1
},
{
"name": "Date & Time",
"type": "n8n-nodes-base.dateTime",
"position": [
200,
230
],
"parameters": {
"value": "={{new Date().toISOString()}}",
"action": "calculate",
"options": {},
"duration": 12,
"timeUnit": "hours",
"dataPropertyName": "later"
},
"typeVersion": 1
},
{
"name": "Google Calendar",
"type": "n8n-nodes-base.googleCalendar",
"position": [
350,
230
],
"parameters": {
"options": {
"timeMax": "={{$node[\"Date & Time\"].json[\"later\"]}}",
"timeMin": "={{new Date(new Date().getTime() + (0 * 60 * 60 * 1000)).toISOString()}}",
"singleEvents": true
},
"calendar": "REPLACE_WITH_CALENDAR_ID",
"operation": "getAll"
},
"credentials": {
"googleCalendarOAuth2Api": {
"id": "1",
"name": "Google Calendar account"
}
},
"typeVersion": 1
},
{
"name": "IF Zoom meeting",
"type": "n8n-nodes-base.if",
"notes": "filters out:\n- existing Zoom meetings made by Calendly\n- in person zoom meetings\n- signal meetings\n- canceled Calendly meetings (\"transparent\")",
"position": [
180,
430
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{$node[\"Google Calendar\"].json[\"transparency\"]}}",
"value2": "transparent",
"operation": "notContains"
},
{
"value1": "={{$node[\"Google Calendar\"].json[\"summary\"]}}",
"value2": "=signal",
"operation": "notContains"
},
{
"value1": "{{$node[\"Google Calendar\"].json[\"summary\"]}}",
"value2": "minute meeting",
"operation": "notContains"
},
{
"value1": "={{$node[\"Google Calendar\"].json[\"summary\"]}}",
"value2": "in person",
"operation": "notContains"
}
],
"boolean": []
}
},
"typeVersion": 1
},
{
"name": "Cron Once a Day",
"type": "n8n-nodes-base.cron",
"position": [
0,
170
],
"parameters": {
"triggerTimes": {
"item": [
{
"hour": 7
}
]
}
},
"typeVersion": 1
}
],
"active": true,
"settings": {},
"connections": {
"Date & Time": {
"main": [
[
{
"node": "Google Calendar",
"type": "main",
"index": 0
}
]
]
},
"Cron Once a Day": {
"main": [
[
{
"node": "Date & Time",
"type": "main",
"index": 0
}
]
]
},
"Google Calendar": {
"main": [
[
{
"node": "IF Zoom meeting",
"type": "main",
"index": 0
}
]
]
},
"IF Zoom meeting": {
"main": [
[
{
"node": "Zoom",
"type": "main",
"index": 0
}
]
]
},
"On clicking 'execute'": {
"main": [
[
{
"node": "Date & Time",
"type": "main",
"index": 0
}
]
]
}
}
}

View File

@@ -0,0 +1,507 @@
{
"meta": {
"instanceId": "257476b1ef58bf3cb6a46e65fac7ee34a53a5e1a8492d5c6e4da5f87c9b82833",
"templateId": "2075"
},
"nodes": [
{
"id": "e3df7c90-fd1e-4e56-b4b8-ee2095720077",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
380,
240
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.1
},
{
"id": "fd37f3cc-b42c-43db-ba4c-8f760d620050",
"name": "PURGE DAYS",
"type": "n8n-nodes-base.dateTime",
"position": [
920,
460
],
"parameters": {
"options": {},
"duration": 30,
"magnitude": "={{ $now }}",
"operation": "subtractFromDate"
},
"typeVersion": 2
},
{
"id": "88d38a16-3dad-466f-adab-5c5ac846a65e",
"name": "DELETE OLD BACKUPS",
"type": "n8n-nodes-base.dropbox",
"position": [
1520,
460
],
"parameters": {
"path": "={{ $json.pathDisplay }}",
"operation": "delete",
"authentication": "oAuth2"
},
"credentials": {
"dropboxOAuth2Api": {
"id": "28",
"name": "Dropbox account"
}
},
"typeVersion": 1
},
{
"id": "ff2b37de-8bc8-446a-8369-9bc52a54addd",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
820,
-20
],
"parameters": {
"width": 932.4394074276975,
"height": 223.80675203725258,
"content": "MOVE CURRENT BACKUPS TO OLD FOLDER"
},
"typeVersion": 1
},
{
"id": "732eeb83-f552-4c4a-b0dc-e7e25e7a74cb",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
820,
220
],
"parameters": {
"width": 931.4765002625034,
"height": 185.32013969732247,
"content": "BACKUP ALL CURRENT WORKFLOWS"
},
"typeVersion": 1
},
{
"id": "fb8e941b-343a-47c0-9806-10f13a0e1c2d",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
817.111278504417,
420
],
"parameters": {
"width": 932.4394074276973,
"height": 203.55064027939466,
"content": "PURGE BACKUPS OLDER THEN 30 DAYS\n"
},
"typeVersion": 1
},
{
"id": "cbf0c9a8-f188-499f-ba9b-68ea6bfdb38b",
"name": "GET WORKFLOWS",
"type": "n8n-nodes-base.n8n",
"position": [
1100,
260
],
"parameters": {
"filters": {}
},
"credentials": {
"n8nApi": {
"id": "9zn8iY4B9oVtPrcc",
"name": "n8n account"
}
},
"typeVersion": 1
},
{
"id": "43436e4f-83e8-422c-8726-6257976dd9ab",
"name": "MAKE JSON FILES",
"type": "n8n-nodes-base.moveBinaryData",
"position": [
1300,
260
],
"parameters": {
"mode": "jsonToBinary",
"options": {
"fileName": "={{ $json.name }}"
}
},
"notesInFlow": true,
"typeVersion": 1
},
{
"id": "4a3df15e-3679-415a-bcfc-51b19961b08b",
"name": "UPLOAD WORKFLOWS",
"type": "n8n-nodes-base.dropbox",
"position": [
1520,
260
],
"parameters": {
"path": "={{ $('DESTINATION FOLDER').last().json.folder }}{{ $('GET WORKFLOWS').item.json.name }}.json",
"binaryData": true,
"authentication": "oAuth2"
},
"credentials": {
"dropboxOAuth2Api": {
"id": "28",
"name": "Dropbox account"
}
},
"notesInFlow": true,
"typeVersion": 1
},
{
"id": "1350580e-a6b8-4d18-b2f3-322f3dbefd0b",
"name": "DESTINATION FOLDER",
"type": "n8n-nodes-base.set",
"position": [
580,
240
],
"parameters": {
"fields": {
"values": [
{
"name": "folder",
"stringValue": "/n8n_backups/"
}
]
},
"include": "none",
"options": {}
},
"notesInFlow": true,
"typeVersion": 3.2
},
{
"id": "920c837e-f328-47bc-ac01-da4584640e01",
"name": "WAIT FOR MOVE TO FINISH",
"type": "n8n-nodes-base.merge",
"position": [
900,
260
],
"parameters": {
"mode": "chooseBranch",
"output": "input2"
},
"typeVersion": 2.1
},
{
"id": "8798f472-5a7f-442b-880e-3bffe3597d0b",
"name": "GET CURRENT BACKUPS",
"type": "n8n-nodes-base.dropbox",
"onError": "continueRegularOutput",
"position": [
1100,
40
],
"parameters": {
"path": "={{ $('DESTINATION FOLDER').last().json.folder }}",
"limit": 250,
"filters": {},
"resource": "folder",
"operation": "list",
"authentication": "oAuth2"
},
"credentials": {
"dropboxOAuth2Api": {
"id": "28",
"name": "Dropbox account"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "b524ac5f-08bf-4c87-9c53-8e9150068690",
"name": "IGNORE FOLDERS",
"type": "n8n-nodes-base.filter",
"position": [
1300,
40
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "a13e9fd6-ef31-4e23-bde6-955ffab5849b",
"operator": {
"type": "string",
"operation": "notEquals"
},
"leftValue": "={{ $json.type }}",
"rightValue": "folder"
}
]
}
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "7ca4c3d3-93dc-4da0-a4d0-c9282d0e7689",
"name": "MOVE INTO OLD FOLDER",
"type": "n8n-nodes-base.dropbox",
"onError": "continueRegularOutput",
"position": [
1520,
40
],
"parameters": {
"path": "={{ $json.pathDisplay }}",
"toPath": "={{ $('DESTINATION FOLDER').last().json.folder }}old/{{ $json.name }}_{{ $('GET CURRENT DATE').last().json.formattedDate }}.json",
"operation": "move",
"authentication": "oAuth2"
},
"credentials": {
"dropboxOAuth2Api": {
"id": "28",
"name": "Dropbox account"
}
},
"executeOnce": false,
"notesInFlow": true,
"retryOnFail": false,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "60505840-821b-43e1-8aa0-6478955c5f3a",
"name": "LIST OLD BACKUPS",
"type": "n8n-nodes-base.dropbox",
"onError": "continueRegularOutput",
"position": [
1100,
460
],
"parameters": {
"path": "={{ $('DESTINATION FOLDER').last().json.folder }}old",
"limit": 500,
"filters": {},
"resource": "folder",
"operation": "list",
"authentication": "oAuth2"
},
"credentials": {
"dropboxOAuth2Api": {
"id": "28",
"name": "Dropbox account"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "ffab6a02-a9f9-4a91-b4f1-dbc157d079e7",
"name": "CHECK DATES",
"type": "n8n-nodes-base.if",
"position": [
1300,
460
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "e0aa83a7-a65b-4008-9010-bf4f14c0c398",
"operator": {
"type": "dateTime",
"operation": "before"
},
"leftValue": "={{ $json.lastModifiedServer }}",
"rightValue": "={{ $('PURGE DAYS').item.json.newDate }}"
}
]
}
},
"typeVersion": 2
},
{
"id": "6bb40592-b599-4511-9e29-fdb1d374053f",
"name": "GET CURRENT DATE",
"type": "n8n-nodes-base.dateTime",
"position": [
900,
40
],
"parameters": {
"date": "={{ $now }}",
"format": "=yyyy-MM-dd_HHmm",
"options": {},
"operation": "formatDate"
},
"typeVersion": 2
}
],
"pinData": {},
"connections": {
"PURGE DAYS": {
"main": [
[
{
"node": "LIST OLD BACKUPS",
"type": "main",
"index": 0
}
]
]
},
"CHECK DATES": {
"main": [
[
{
"node": "DELETE OLD BACKUPS",
"type": "main",
"index": 0
}
]
]
},
"GET WORKFLOWS": {
"main": [
[
{
"node": "MAKE JSON FILES",
"type": "main",
"index": 0
}
]
]
},
"IGNORE FOLDERS": {
"main": [
[
{
"node": "MOVE INTO OLD FOLDER",
"type": "main",
"index": 0
}
]
]
},
"MAKE JSON FILES": {
"main": [
[
{
"node": "UPLOAD WORKFLOWS",
"type": "main",
"index": 0
}
]
]
},
"GET CURRENT DATE": {
"main": [
[
{
"node": "GET CURRENT BACKUPS",
"type": "main",
"index": 0
}
]
]
},
"LIST OLD BACKUPS": {
"main": [
[
{
"node": "CHECK DATES",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "DESTINATION FOLDER",
"type": "main",
"index": 0
}
]
]
},
"DESTINATION FOLDER": {
"main": [
[
{
"node": "GET CURRENT DATE",
"type": "main",
"index": 0
},
{
"node": "WAIT FOR MOVE TO FINISH",
"type": "main",
"index": 1
},
{
"node": "PURGE DAYS",
"type": "main",
"index": 0
}
]
]
},
"GET CURRENT BACKUPS": {
"main": [
[
{
"node": "IGNORE FOLDERS",
"type": "main",
"index": 0
}
]
]
},
"MOVE INTO OLD FOLDER": {
"main": [
[
{
"node": "WAIT FOR MOVE TO FINISH",
"type": "main",
"index": 0
}
]
]
},
"WAIT FOR MOVE TO FINISH": {
"main": [
[
{
"node": "GET WORKFLOWS",
"type": "main",
"index": 0
}
]
]
}
}
}

View File

@@ -0,0 +1,553 @@
{
"nodes": [
{
"id": "a39274d0-6709-4e66-95a7-8c0fc4c0e8b1",
"name": "if after unsnooze date",
"type": "n8n-nodes-base.if",
"position": [
1840,
500
],
"parameters": {
"conditions": {
"dateTime": [
{
"value1": "={{ DateTime.now() }}",
"value2": "={{ $json.unsnoozeDate }}"
}
]
}
},
"typeVersion": 1
},
{
"id": "a4e2d915-4714-41ea-8995-76b7198df675",
"name": "at 5am",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
780,
500
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 5
}
]
}
},
"typeVersion": 1.1
},
{
"id": "7ad8e2f6-0499-4537-8325-9dffc2d7ea3c",
"name": "every 5 min",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
780,
280
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "370f380a-923b-4e4f-b025-9e7723662083",
"name": "Get snoozed tasks",
"type": "n8n-nodes-base.todoist",
"position": [
980,
500
],
"parameters": {
"filters": {
"projectId": "2325216129"
},
"operation": "getAll",
"returnAll": true
},
"credentials": {
"todoistApi": {
"id": "1",
"name": "Todoist account"
}
},
"retryOnFail": true,
"typeVersion": 2,
"waitBetweenTries": 5000
},
{
"id": "f239a87d-0229-4964-bca0-75bbf371626b",
"name": "if task is not a subtask",
"type": "n8n-nodes-base.if",
"position": [
1200,
500
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.parent_id }}",
"operation": "isEmpty"
}
]
}
},
"typeVersion": 1
},
{
"id": "b9b29371-254f-45d1-846c-c2db7efae907",
"name": "If task has due date",
"type": "n8n-nodes-base.if",
"position": [
1420,
500
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ !$json.due }}"
}
]
}
},
"typeVersion": 1
},
{
"id": "1d1fe683-68b5-4a9c-af29-b20a01c2473b",
"name": "Get date to unsnooze",
"type": "n8n-nodes-base.dateTime",
"position": [
1640,
500
],
"parameters": {
"options": {
"includeInputFields": true
},
"duration": 3,
"magnitude": "={{ $json.due.date }}",
"operation": "subtractFromDate",
"outputFieldName": "unsnoozeDate"
},
"typeVersion": 2
},
{
"id": "9e0e3241-d2fd-4bc4-9273-aa5237cbeaa4",
"name": "Get inbox tasks to snooze",
"type": "n8n-nodes-base.todoist",
"position": [
980,
280
],
"parameters": {
"filters": {
"projectId": "938017196"
},
"operation": "getAll",
"returnAll": true
},
"credentials": {
"todoistApi": {
"id": "1",
"name": "Todoist account"
}
},
"retryOnFail": true,
"typeVersion": 2,
"waitBetweenTries": 5000
},
{
"id": "90e83f5f-dd9f-431d-92b5-cd52a792dee2",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1220,
220
],
"parameters": {
"color": 5,
"width": 390.83694011071975,
"height": 182.09360845495712,
"content": "### 👨‍🎤 Setup\n1. Add your Todoist creds\n2. Create a Todoist project called `snoozed`\n3. Set the project ids in the relevant nodes\n4. Add due dates to your tasks in Inbox. Watch them disappear to `snoozed`. Set their date to tomorrow, watch it return to inbox."
},
"typeVersion": 1
},
{
"id": "c7a6b401-f518-45ba-a185-c8bf0cd92394",
"name": "Set inbox project id",
"type": "n8n-nodes-base.set",
"position": [
2060,
420
],
"parameters": {
"fields": {
"values": [
{
"name": "target_project_id",
"type": "numberValue",
"numberValue": "2329427682"
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "22982318-5036-490a-ba3c-d40db8c3dc89",
"name": "If not same project",
"type": "n8n-nodes-base.filter",
"position": [
2280,
500
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ parseInt($json.target_project_id) }}",
"value2": "={{ parseInt($json.project_id) }}",
"operation": "notEqual"
}
]
}
},
"typeVersion": 1
},
{
"id": "62009b22-d0e3-40a0-b7f9-88dc2ec02284",
"name": "Set args to move",
"type": "n8n-nodes-base.set",
"position": [
2480,
500
],
"parameters": {
"fields": {
"values": [
{
"name": "args",
"type": "objectValue",
"objectValue": "={ id: {{ $json.id }}, project_id: {{ $json.target_project_id }} }"
},
{
"name": "type",
"stringValue": "item_move"
}
]
},
"include": "none",
"options": {}
},
"typeVersion": 3.2
},
{
"id": "4d628334-12a3-451f-b49e-ce749241e411",
"name": "Generate unique uuid for move",
"type": "n8n-nodes-base.crypto",
"position": [
2680,
500
],
"parameters": {
"action": "generate",
"dataPropertyName": "uuid"
},
"typeVersion": 1
},
{
"id": "8b6bf7ae-6d15-473d-8f00-5aaa4ea7d2f3",
"name": "Merge all items into a list",
"type": "n8n-nodes-base.itemLists",
"position": [
2880,
500
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData",
"operation": "concatenateItems",
"destinationFieldName": "commands"
},
"typeVersion": 3.1
},
{
"id": "7882c3c6-0d24-4fe2-99b6-3e878e4d0dea",
"name": "Move the tasks",
"type": "n8n-nodes-base.httpRequest",
"position": [
3080,
500
],
"parameters": {
"url": "https://api.todoist.com/sync/v9/sync",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "form-urlencoded",
"authentication": "predefinedCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "commands",
"value": "={{ JSON.stringify($json.commands) }}"
}
]
},
"nodeCredentialType": "todoistApi"
},
"credentials": {
"todoistApi": {
"id": "1",
"name": "Todoist account"
}
},
"typeVersion": 4.1
},
{
"id": "259c337b-38f6-4c2a-8e23-9fe5d154a2aa",
"name": "Set snoozed project id",
"type": "n8n-nodes-base.set",
"position": [
2060,
600
],
"parameters": {
"fields": {
"values": [
{
"name": "target_project_id",
"type": "numberValue",
"numberValue": "2329427688"
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "2795502f-cdeb-4b94-a6fe-ef3657bdc091",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
2080,
780
],
"parameters": {
"color": 7,
"width": 202,
"height": 100,
"content": "👆 Set `snoozed` project id here. You can find it in the URL. "
},
"typeVersion": 1
},
{
"id": "ef6c23d5-386e-48c2-a2ed-eea67fe1f117",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
2060,
260
],
"parameters": {
"color": 7,
"width": 202,
"height": 100,
"content": "👇🏽 Set `inbox` project id here. You can find it in the URL. "
},
"typeVersion": 1
},
{
"id": "6727670f-b340-47cd-b86a-632ef29e2135",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1660,
660
],
"parameters": {
"color": 7,
"width": 202,
"height": 100,
"content": "👆🏽 Adjust here the timeline to return tasks to Inbox (here set to 3 days before due date)"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"at 5am": {
"main": [
[
{
"node": "Get snoozed tasks",
"type": "main",
"index": 0
}
]
]
},
"every 5 min": {
"main": [
[
{
"node": "Get inbox tasks to snooze",
"type": "main",
"index": 0
}
]
]
},
"Set args to move": {
"main": [
[
{
"node": "Generate unique uuid for move",
"type": "main",
"index": 0
}
]
]
},
"Get snoozed tasks": {
"main": [
[
{
"node": "if task is not a subtask",
"type": "main",
"index": 0
}
]
]
},
"If not same project": {
"main": [
[
{
"node": "Set args to move",
"type": "main",
"index": 0
}
]
]
},
"Get date to unsnooze": {
"main": [
[
{
"node": "if after unsnooze date",
"type": "main",
"index": 0
}
]
]
},
"If task has due date": {
"main": [
[
{
"node": "Get date to unsnooze",
"type": "main",
"index": 0
}
]
]
},
"Set inbox project id": {
"main": [
[
{
"node": "If not same project",
"type": "main",
"index": 0
}
]
]
},
"Set snoozed project id": {
"main": [
[
{
"node": "If not same project",
"type": "main",
"index": 0
}
]
]
},
"if after unsnooze date": {
"main": [
[
{
"node": "Set inbox project id",
"type": "main",
"index": 0
}
],
[
{
"node": "Set snoozed project id",
"type": "main",
"index": 0
}
]
]
},
"if task is not a subtask": {
"main": [
[
{
"node": "If task has due date",
"type": "main",
"index": 0
}
]
]
},
"Get inbox tasks to snooze": {
"main": [
[
{
"node": "if task is not a subtask",
"type": "main",
"index": 0
}
]
]
},
"Merge all items into a list": {
"main": [
[
{
"node": "Move the tasks",
"type": "main",
"index": 0
}
]
]
},
"Generate unique uuid for move": {
"main": [
[
{
"node": "Merge all items into a list",
"type": "main",
"index": 0
}
]
]
}
}
}

View File

@@ -0,0 +1,372 @@
{
"meta": {
"instanceId": "03e9d14e9196363fe7191ce21dc0bb17387a6e755dcc9acc4f5904752919dca8"
},
"nodes": [
{
"id": "93963e3d-bd30-4a0f-ba56-7896cd19d2ae",
"name": "When clicking Test workflow",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-660,
160
],
"parameters": {},
"typeVersion": 1
},
{
"id": "c459e403-01b8-43dd-8065-1f8dcb77bcc0",
"name": "Run Every 5 Minutes",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-660,
-40
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "7cabd06a-7898-4789-9671-78f0b6fcac2a",
"name": "Get 5 Minute Ago Timestamp",
"type": "n8n-nodes-base.dateTime",
"position": [
-320,
40
],
"parameters": {
"options": {},
"duration": 5,
"timeUnit": "minutes",
"magnitude": "={{ $now.toUTC() }}",
"operation": "subtractFromDate",
"outputFieldName": "queryDate"
},
"typeVersion": 2
},
{
"id": "5f21f279-3608-41bf-8986-47832aa0f1f2",
"name": "Get Incidents from ServiceNow",
"type": "n8n-nodes-base.serviceNow",
"onError": "continueErrorOutput",
"position": [
-100,
40
],
"parameters": {
"options": {
"sysparm_query": "=sys_created_on>={{ $json.queryDate }}",
"sysparm_display_value": "true"
},
"resource": "incident",
"operation": "getAll",
"authentication": "basicAuth"
},
"credentials": {
"serviceNowBasicApi": {
"id": "wjkWiUNQxo5PzTIb",
"name": "ServiceNow Basic Auth account"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "19fc7c77-e2b0-495d-bb7b-7bc7a7d87805",
"name": "Check if New Incidents",
"type": "n8n-nodes-base.if",
"position": [
160,
-40
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "09750510-4604-4372-9cdc-d8055adae12a",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.sys_id }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "53e120d8-3022-46c0-8524-2c14f30d2c1a",
"name": "Post Error Message if Error with ServiceNow",
"type": "n8n-nodes-base.slack",
"position": [
480,
760
],
"webhookId": "0fba7a73-b273-4d52-863f-9a1b3ff75266",
"parameters": {
"text": "🚨 Issue connecting to ServiceNow. Please investigate error in n8n. 🚨",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C086LRRQZQB",
"cachedResultName": "incident-notifications"
},
"otherOptions": {
"mrkdwn": true,
"includeLinkToWorkflow": false
}
},
"credentials": {
"slackApi": {
"id": "K04E2FxPZozHux9J",
"name": "ServiceNow Bot"
}
},
"typeVersion": 2.2
},
{
"id": "0784e71c-208d-4442-b355-3f1f076d9846",
"name": "Sort Incidents in Ascending Order",
"type": "n8n-nodes-base.sort",
"position": [
511,
-271
],
"parameters": {
"options": {},
"sortFieldsUi": {
"sortField": [
{
"fieldName": "number"
}
]
}
},
"typeVersion": 1
},
{
"id": "8435a455-0ea3-4443-8370-ec2e4c392e2f",
"name": "Post Incident Details to Slack Channel",
"type": "n8n-nodes-base.slack",
"position": [
731,
-271
],
"webhookId": "245d019e-7762-4e4a-861e-6181f1dcc7f2",
"parameters": {
"select": "channel",
"blocksUi": "={\n\t\"blocks\": [\n\t\t{\n\t\t\t\"type\": \"header\",\n\t\t\t\"text\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"ServiceNow Incident Notification\",\n\t\t\t\t\"emoji\": true\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"section\",\n\t\t\t\"fields\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Incident ID:*\\n{{ $('Get Incidents from ServiceNow').item.json.number }}\"\n\t\t\t\t},\n{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Description:*\\n{{ $('Get Incidents from ServiceNow').item.json.short_description }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Severity:*\\n{{ $('Get Incidents from ServiceNow').item.json.severity }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Caller:*\\n{{ $('Get Incidents from ServiceNow').item.json.caller_id.display_value }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Priority:*\\n{{ $('Get Incidents from ServiceNow').item.json.priority }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*State:*\\n{{ $('Get Incidents from ServiceNow').item.json.incident_state }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Category:*\\n{{ $('Get Incidents from ServiceNow').item.json.category }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Date Opened:*\\n{{ $('Get Incidents from ServiceNow').item.json.opened_at }}\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"type\": \"actions\",\n\t\t\t\"elements\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"button\",\n\t\t\t\t\t\"text\": {\n\t\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\t\"text\": \"View Incident\",\n\t\t\t\t\t\t\"emoji\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"url\": \"https://dev206761.service-now.com/nav_to.do?uri=incident.do?sys_id={{ $('Get Incidents from ServiceNow').item.json.sys_id }}\",\n\t\t\t\t\t\"action_id\": \"view_incident\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C086LRRQZQB",
"cachedResultName": "incident-notifications"
},
"messageType": "block",
"otherOptions": {
"includeLinkToWorkflow": false
}
},
"credentials": {
"slackApi": {
"id": "K04E2FxPZozHux9J",
"name": "ServiceNow Bot"
}
},
"typeVersion": 2.2
},
{
"id": "aa526b18-d259-4304-9faa-4375bee83c50",
"name": "No Incidents, Do Nothing",
"type": "n8n-nodes-base.noOp",
"position": [
500,
200
],
"parameters": {},
"typeVersion": 1
},
{
"id": "2798711d-1788-4126-a576-cdef6c495bd7",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
400,
-720
],
"parameters": {
"color": 7,
"width": 543.0448479049971,
"height": 635.2493225262418,
"content": "![Slack](https://uploads.n8n.io/templates/slack.png)\n## Sorting and Posting Incident Details to Slack\n\nThis section begins with the `Sort Incidents in Ascending Order` node, which organizes the retrieved ServiceNow incidents by their incident number in ascending order. This ensures that incidents are processed and displayed in a logical sequence. The sorted incidents are then passed to the `Post Incident Details to Slack Channel` node, which formats and sends a detailed message to a designated Slack channel. The message includes key information such as the incident ID, description, severity, caller, priority, state, category, and the date the incident was opened. A \"View Incident\" button is also provided, linking directly to the ServiceNow record for quick access. This section ensures clear, organized communication of incident details, enabling efficient team collaboration and resolution."
},
"typeVersion": 1
},
{
"id": "499f5f1e-617b-429d-9760-dc264870e269",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-400,
-416.5936589599954
],
"parameters": {
"color": 7,
"width": 792.7994376824845,
"height": 651.0105345024904,
"content": "![Servicenow](https://uploads.n8n.io/templates/servicenow.png)\n## Fetching and Checking New Incidents\n\nThis section begins with the `Get 5 Minute Ago Timestamp` node, which calculates a timestamp exactly 5 minutes prior to the current time. This timestamp is used as a reference point for querying incidents created within the last 5 minutes. The `Get Incidents from ServiceNow` node then fetches all incidents created after the calculated timestamp from the ServiceNow system, ensuring only the most recent incidents are retrieved. Finally, the `Check if New Incidents` node evaluates whether any incidents were returned by checking if the `sys_id` field exists in the response. This logic helps determine the next steps in the workflow, ensuring actions are taken only when new incidents are detected."
},
"typeVersion": 1
},
{
"id": "c6f1dd80-ed5b-4e29-add1-a38a46338150",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
400,
380
],
"parameters": {
"color": 7,
"width": 540.6200460624971,
"height": 560.0562505318285,
"content": "![Slack](https://uploads.n8n.io/templates/slack.png)\n## Error Notification to Slack\n\nThis section handles error reporting using the `Post Error Message if Error with ServiceNow` node. If the workflow encounters any issues connecting to ServiceNow, this node sends a predefined error message to a specified Slack channel. Usually this is triggered by expired credentials. The message alerts the team to investigate the issue in n8n, ensuring prompt attention and troubleshooting. By proactively notifying the team of connection errors, this section helps maintain the reliability of the workflow and minimizes disruptions in incident monitoring and reporting."
},
"typeVersion": 1
},
{
"id": "1ea0684a-9d7e-4f47-a7b0-9cb22bb6b934",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-800,
-420
],
"parameters": {
"color": 7,
"width": 382.98284329874696,
"height": 746.70974187249,
"content": "![n8n](https://uploads.n8n.io/templates/n8n.png)\n## Run Every 5 Minutes\n\nThe `Schedule Trigger` node is configured to automatically execute the workflow every 5 minutes. This setup ensures consistent and timely monitoring for new incidents in ServiceNow without requiring manual input. The selected interval strikes a balance between responsiveness and efficient resource usage, making it ideal for real-time incident management workflows."
},
"typeVersion": 1
},
{
"id": "1a3e7b4c-60ce-449c-9f6a-2a1bc42b748d",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
400,
-80
],
"parameters": {
"color": 7,
"width": 540.5949630612389,
"height": 442.9500589573929,
"content": "![n8n](https://uploads.n8n.io/templates/n8n.png)\n## No New Incidents Found, Do Nothing\n\nIf a ServiceNow system ID is not found in the ServiceNow node output, it will route to this node which effectively ends the process without doing anything. "
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"Run Every 5 Minutes": {
"main": [
[
{
"node": "Get 5 Minute Ago Timestamp",
"type": "main",
"index": 0
}
]
]
},
"Check if New Incidents": {
"main": [
[
{
"node": "Sort Incidents in Ascending Order",
"type": "main",
"index": 0
}
],
[
{
"node": "No Incidents, Do Nothing",
"type": "main",
"index": 0
}
]
]
},
"Get 5 Minute Ago Timestamp": {
"main": [
[
{
"node": "Get Incidents from ServiceNow",
"type": "main",
"index": 0
}
]
]
},
"Get Incidents from ServiceNow": {
"main": [
[
{
"node": "Check if New Incidents",
"type": "main",
"index": 0
}
],
[
{
"node": "Post Error Message if Error with ServiceNow",
"type": "main",
"index": 0
}
]
]
},
"Sort Incidents in Ascending Order": {
"main": [
[
{
"node": "Post Incident Details to Slack Channel",
"type": "main",
"index": 0
}
]
]
},
"When clicking Test workflow": {
"main": [
[
{
"node": "Get 5 Minute Ago Timestamp",
"type": "main",
"index": 0
}
]
]
}
}
}

View File

@@ -0,0 +1,482 @@
{
"id": 65,
"meta": {
"instanceId": "104a4d08d8897b8bdeb38aaca515021075e0bd8544c983c2bb8c86e6a8e6081c"
},
"name": "Two Way Sync Pipedrive and MySQL",
"tags": [],
"nodes": [
{
"id": "7355c5ac-a9a6-4fa5-8036-71fd09e95cd4",
"name": "Compare Datasets",
"type": "n8n-nodes-base.compareDatasets",
"position": [
1220,
480
],
"parameters": {
"options": {},
"resolve": "includeBoth",
"mergeByFields": {
"values": [
{
"field1": "email",
"field2": "email"
}
]
}
},
"typeVersion": 1
},
{
"id": "7a422493-94d4-4f94-b39c-f6c3980a967c",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
800,
320
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1
},
{
"id": "b3a0e831-7030-43dd-863a-0c2a4697a14d",
"name": "MySQL",
"type": "n8n-nodes-base.mySql",
"position": [
1000,
320
],
"parameters": {
"query": "SELECT id, name, email, phone, updated_on FROM contact",
"operation": "executeQuery"
},
"credentials": {
"mySql": {
"id": "23",
"name": "MySQL account"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "a3a64bb5-8a6f-4011-bc2d-3996a823012c",
"name": "Pipedrive",
"type": "n8n-nodes-base.pipedrive",
"position": [
800,
620
],
"parameters": {
"resource": "person",
"operation": "getAll",
"additionalFields": {}
},
"credentials": {
"pipedriveApi": {
"id": "29",
"name": "Pipedrive account"
}
},
"typeVersion": 1
},
{
"id": "089e91df-abf7-4de9-b088-357cffce6949",
"name": "Create Person",
"type": "n8n-nodes-base.pipedrive",
"position": [
1420,
300
],
"parameters": {
"name": "={{ $json[\"name\"] }}",
"resource": "person",
"additionalFields": {
"email": [
"={{ $json[\"email\"] }}"
],
"phone": [
"={{ $json[\"phone\"] }}"
]
}
},
"credentials": {
"pipedriveApi": {
"id": "29",
"name": "Pipedrive account"
}
},
"typeVersion": 1
},
{
"id": "a99c3242-8263-4a92-a1f2-dcce7a9a6d81",
"name": "Create Contact",
"type": "n8n-nodes-base.mySql",
"position": [
1420,
620
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "contact",
"cachedResultName": "contact"
},
"columns": "name, email, phone",
"options": {}
},
"credentials": {
"mySql": {
"id": "23",
"name": "MySQL account"
}
},
"typeVersion": 1
},
{
"id": "7697d03a-7bc4-40b3-9e06-e38c13ccaaf3",
"name": "Date & Time",
"type": "n8n-nodes-base.dateTime",
"position": [
1760,
460
],
"parameters": {
"value": "={{ $json[\"different\"][\"updated_on\"][\"input1\"] }}",
"custom": true,
"options": {},
"toFormat": "YYYY-MM-DD HH:mm:ss",
"dataPropertyName": "different.updated_on.input1"
},
"typeVersion": 1
},
{
"id": "f882a2e7-a8cf-4683-abe3-77a5b7376bb2",
"name": "Update Contact",
"type": "n8n-nodes-base.mySql",
"position": [
2340,
620
],
"parameters": {
"query": "=UPDATE contact\nSET name = '{{$json[\"name\"]}}', phone= '{{$json[\"phone\"]}}'\nWHERE id = {{$json[\"id\"]}};",
"operation": "executeQuery"
},
"credentials": {
"mySql": {
"id": "23",
"name": "MySQL account"
}
},
"typeVersion": 1
},
{
"id": "d7549678-5d35-4a8a-b440-5c347b4434f4",
"name": "Set Input2",
"type": "n8n-nodes-base.set",
"position": [
2120,
620
],
"parameters": {
"values": {
"string": [
{
"name": "id",
"value": "={{ $json[\"different\"][\"id\"] ? $json[\"different\"][\"id\"][\"input1\"] : $json[\"same\"][\"id\"] }}"
},
{
"name": "name",
"value": "={{ $json[\"different\"][\"name\"] ? $json[\"different\"][\"name\"][\"input2\"] : $json[\"same\"][\"name\"] }}"
},
{
"name": "phone",
"value": "={{ $json[\"different\"][\"phone\"] ? $json[\"different\"][\"phone\"][\"input2\"] : $json[\"same\"][\"phone\"] }}"
}
]
},
"options": {}
},
"typeVersion": 1
},
{
"id": "0018751e-c295-4f8d-b9df-257b9538eedc",
"name": "Set Input1",
"type": "n8n-nodes-base.set",
"position": [
2120,
300
],
"parameters": {
"values": {
"string": [
{
"name": "id",
"value": "={{ $json[\"different\"][\"id\"] ? $json[\"different\"][\"id\"][\"input2\"] : $json[\"same\"][\"id\"] }}"
},
{
"name": "name",
"value": "={{ $json[\"different\"][\"name\"] ? $json[\"different\"][\"name\"][\"input1\"] : $json[\"same\"][\"name\"] }}"
},
{
"name": "phone",
"value": "={{ $json[\"different\"][\"phone\"] ? $json[\"different\"][\"phone\"][\"input1\"] : $json[\"same\"][\"phone\"] }}"
}
]
},
"options": {}
},
"typeVersion": 1
},
{
"id": "89af3385-4788-4693-ad02-917b927e7384",
"name": "Update Person",
"type": "n8n-nodes-base.pipedrive",
"position": [
2340,
300
],
"parameters": {
"personId": "={{ $json[\"id\"] }}",
"resource": "person",
"operation": "update",
"updateFields": {
"name": "={{ $json[\"name\"] }}",
"phone": [
"={{ $json[\"phone\"] }}"
]
}
},
"credentials": {
"pipedriveApi": {
"id": "29",
"name": "Pipedrive account"
}
},
"typeVersion": 1
},
{
"id": "8ffbbb4b-7c2f-457e-ae73-464620aa1588",
"name": "IF Data Changed",
"type": "n8n-nodes-base.if",
"position": [
1560,
480
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ !!$json[\"different\"][\"name\"] || !!$json[\"different\"][\"phone\"] }}",
"value2": true
}
]
}
},
"typeVersion": 1
},
{
"id": "f8d60404-942d-4bb3-96e7-a247a9447a32",
"name": "IF Updated On",
"type": "n8n-nodes-base.if",
"position": [
1940,
460
],
"parameters": {
"conditions": {
"dateTime": [
{
"value1": "={{ $json[\"different\"][\"updated\"][\"input1\"] }} {{ $json[\"different\"][\"updated_on\"][\"input1\"] }}",
"value2": "={{ $json[\"different\"][\"updated\"][\"input2\"] }} {{ $json[\"different\"][\"updated_on\"][\"input2\"] }}"
}
]
}
},
"typeVersion": 1
},
{
"id": "6965e281-10bd-4e8a-b016-f788030a6d9f",
"name": "Set",
"type": "n8n-nodes-base.set",
"position": [
1000,
620
],
"parameters": {
"values": {
"string": [
{
"name": "id",
"value": "={{ $json[\"id\"] }}"
},
{
"name": "name",
"value": "={{ $json[\"name\"] }}"
},
{
"name": "email",
"value": "={{ $json[\"primary_email\"] }}"
},
{
"name": "phone",
"value": "={{ $json[\"phone\"][0][\"value\"] }}"
},
{
"name": "updated_on",
"value": "={{ $json[\"update_time\"] }}"
}
]
},
"options": {},
"keepOnlySet": true
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {},
"connections": {
"Set": {
"main": [
[
{
"node": "Compare Datasets",
"type": "main",
"index": 1
}
]
]
},
"MySQL": {
"main": [
[
{
"node": "Compare Datasets",
"type": "main",
"index": 0
}
]
]
},
"Pipedrive": {
"main": [
[
{
"node": "Set",
"type": "main",
"index": 0
}
]
]
},
"Set Input1": {
"main": [
[
{
"node": "Update Person",
"type": "main",
"index": 0
}
]
]
},
"Set Input2": {
"main": [
[
{
"node": "Update Contact",
"type": "main",
"index": 0
}
]
]
},
"Date & Time": {
"main": [
[
{
"node": "IF Updated On",
"type": "main",
"index": 0
}
]
]
},
"IF Updated On": {
"main": [
[
{
"node": "Set Input1",
"type": "main",
"index": 0
}
],
[
{
"node": "Set Input2",
"type": "main",
"index": 0
}
]
]
},
"IF Data Changed": {
"main": [
[
{
"node": "Date & Time",
"type": "main",
"index": 0
}
]
]
},
"Compare Datasets": {
"main": [
[
{
"node": "Create Person",
"type": "main",
"index": 0
}
],
[],
[
{
"node": "IF Data Changed",
"type": "main",
"index": 0
}
],
[
{
"node": "Create Contact",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "MySQL",
"type": "main",
"index": 0
}
]
]
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,717 @@
{
"id": "ATxZ5QYhdJq9mZDO",
"meta": {
"instanceId": "bdce9ec27bbe2b742054f01d034b8b468d2e7758edd716403ad5bd4583a8f649",
"templateCredsSetupCompleted": true
},
"name": "Parse DMARC reports",
"tags": [
{
"id": "w055QEEFrp6ZYNCr",
"name": "DevOps",
"createdAt": "2023-12-19T18:45:02.513Z",
"updatedAt": "2023-12-19T18:45:02.513Z"
}
],
"nodes": [
{
"id": "ce9ce59c-3cf6-45db-97fc-825cb8516da8",
"name": "Email Trigger (IMAP)",
"type": "n8n-nodes-base.emailReadImap",
"position": [
580,
300
],
"parameters": {
"options": {},
"downloadAttachments": true
},
"credentials": {
"imap": {
"id": "vx30lEB3JcemyffM",
"name": "IMAP account"
}
},
"typeVersion": 2
},
{
"id": "903f949d-ab1e-48ec-a903-a1ebde4cfbe9",
"name": "End date format",
"type": "n8n-nodes-base.dateTime",
"position": [
800,
880
],
"parameters": {
"date": "={{ $json.date_range_end.toDateTime('s') }}",
"format": "custom",
"options": {
"includeInputFields": true
},
"operation": "formatDate",
"customFormat": "yyyy-MM-dd hh:mm:ss",
"outputFieldName": "=date_range_end"
},
"typeVersion": 2
},
{
"id": "3303e551-8557-4220-ab24-48fcb0859a26",
"name": "If multiple records to parse",
"type": "n8n-nodes-base.if",
"position": [
560,
620
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "b809e758-c3d2-4cbf-bab8-54d278a435dd",
"operator": {
"type": "object",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.feedback.record[0] }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2
},
{
"id": "513864bc-c124-452d-8be3-44feb73454ed",
"name": "Map fields for DB input and parse",
"type": "n8n-nodes-base.set",
"position": [
1200,
660
],
"parameters": {
"options": {
"ignoreConversionErrors": true
},
"assignments": {
"assignments": [
{
"id": "621508ee-fbea-4233-aaf3-96b573a60bd5",
"name": "full_data",
"type": "object",
"value": "={{ $json.feedback }}"
},
{
"id": "d605e93a-0e0a-4584-aa1e-e38b49f264e7",
"name": "org_name",
"type": "string",
"value": "={{ $json.feedback.report_metadata.org_name }}"
},
{
"id": "604a5573-67db-4bb6-80d8-4421dce2406b",
"name": "date_range_begin",
"type": "string",
"value": "={{ $json.feedback.report_metadata.date_range.begin }}"
},
{
"id": "b9d7244f-9d58-43fc-a477-f0750c31e5e2",
"name": "date_range_end",
"type": "string",
"value": "={{ $json.feedback.report_metadata.date_range.end }}"
},
{
"id": "3570869a-9dc9-4b20-b48c-5f382825d021",
"name": "domain",
"type": "string",
"value": "={{ $json.feedback.policy_published.domain }}"
},
{
"id": "979e4eb4-6e39-4a3c-8f0a-21ecf8086a3c",
"name": "policy_published",
"type": "object",
"value": "={{ $json.feedback.policy_published }}"
},
{
"id": "91cdfa19-49c6-4e5d-a423-d76bbb61eddc",
"name": "source_ip",
"type": "string",
"value": "={{ $json['fbr'].row.source_ip }}"
},
{
"id": "2434b04e-3c5e-4e61-8be9-1f9c1ec2a6ce",
"name": "mail_count",
"type": "string",
"value": "={{ $json['fbr'].row.count }}"
},
{
"id": "09b73b84-0f6a-443b-8da0-c7ad9742a9c1",
"name": "evaluated_disposition",
"type": "string",
"value": "={{ $json['fbr'].row.policy_evaluated.disposition }}"
},
{
"id": "6c8e81ab-abc6-497c-8919-6b2e8008a1e8",
"name": "evaluated_dkim",
"type": "string",
"value": "={{ $json['fbr'].row.policy_evaluated.dkim }}"
},
{
"id": "fa8ca9d6-5e1b-402c-9afc-e6bf42e2c6ad",
"name": "evaluated_spf",
"type": "string",
"value": "={{ $json['fbr'].row.policy_evaluated.spf }}"
},
{
"id": "42f269c3-978a-45f6-bfe5-1fa1536500fb",
"name": "identifiers",
"type": "object",
"value": "={{ $json['fbr'].identifiers }}"
},
{
"id": "3375dc26-a739-4bf9-8a46-2f6739337921",
"name": "auth_results",
"type": "object",
"value": "={{ $json['fbr'].auth_results }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "00cca3ae-1f0a-4ea9-8fb7-ac52d35c261b",
"name": "Begin format date",
"type": "n8n-nodes-base.dateTime",
"position": [
560,
880
],
"parameters": {
"date": "={{ $json.date_range_begin.toDateTime('s') }}",
"format": "custom",
"options": {
"includeInputFields": true
},
"operation": "formatDate",
"customFormat": "yyyy-MM-dd hh:mm:ss",
"outputFieldName": "=date_range_begin"
},
"typeVersion": 2
},
{
"id": "18c2305a-db44-4e4d-97b9-1f04018085b0",
"name": "Input into database",
"type": "n8n-nodes-base.mySql",
"position": [
620,
1100
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "dmarc",
"cachedResultName": "dmarc"
},
"options": {
"detailedOutput": true
},
"dataMode": "defineBelow",
"valuesToSend": {
"values": [
{
"value": "={{ $json.full_data.toJsonString() }}",
"column": "full_data"
},
{
"value": "={{ $json.org_name }}",
"column": "org_name"
},
{
"value": "={{ $json.date_range_begin }}",
"column": "date_range_begin"
},
{
"value": "={{ $json.date_range_end }}",
"column": "date_range_end"
},
{
"value": "={{ $json.domain }}",
"column": "domain"
},
{
"value": "={{ $json.policy_published.toJsonString() }}",
"column": "policy_published"
},
{
"value": "={{ $json.source_ip }}",
"column": "source_ip"
},
{
"value": "={{ $json.mail_count }}",
"column": "mail_count"
},
{
"value": "={{ $json.evaluated_disposition }}",
"column": "evaluated_disposition"
},
{
"value": "={{ $json.evaluated_dkim }}",
"column": "evaluated_dkim"
},
{
"value": "={{ $json.evaluated_spf }}",
"column": "evaluated_spf"
},
{
"value": "={{ $json.identifiers == null ? null : $json.identifiers.toJsonString() }}",
"column": "identifiers"
},
{
"value": "={{ $json.auth_results == null ? null : $json.auth_results.toJsonString() }}",
"column": "auth_results"
}
]
}
},
"credentials": {
"mySql": {
"id": "HFwF4pL62FWEFHqR",
"name": "MySQL account"
}
},
"typeVersion": 2.4
},
{
"id": "c65c4cfb-3912-4b45-a5e0-3ab787e018c8",
"name": "If issue with DKIM or SPF",
"type": "n8n-nodes-base.if",
"position": [
580,
1260
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "818b461b-4bdc-4842-9f89-d1d8966b8c0a",
"operator": {
"type": "string",
"operation": "notEquals"
},
"leftValue": "={{ $json.evaluated_dkim }}",
"rightValue": "pass"
},
{
"id": "4322cb26-5ff1-4278-94ae-7ff278c61c6c",
"operator": {
"type": "string",
"operation": "notEquals"
},
"leftValue": "={{ $json.evaluated_spf }}",
"rightValue": "pass"
}
]
}
},
"typeVersion": 2
},
{
"id": "5d17bf15-ecef-40e8-acc4-6af5ad1c712d",
"name": "Rename Keys",
"type": "n8n-nodes-base.renameKeys",
"position": [
1000,
500
],
"parameters": {
"keys": {
"key": [
{
"newKey": "fbr",
"currentKey": "feedback.record"
}
]
},
"additionalOptions": {}
},
"typeVersion": 1
},
{
"id": "0e2b8c73-0f53-46f9-9692-cbe87c97862d",
"name": "Rename column for consistency",
"type": "n8n-nodes-base.set",
"position": [
800,
660
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f563d673-bc82-4863-b132-d431ebe8f651",
"name": "fbr",
"type": "object",
"value": "={{ $json.feedback.record }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "5796c124-645d-460e-88df-0a909a33b6b1",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
100,
300
],
"parameters": {
"width": 394.2691415313225,
"height": 304.36194895591655,
"content": "## How it works\n- monitor postmaster email for DKIM reprots\n- unpack report and parse XML\n- map and format fields for DB input\n\t- input into database\n\t- send notification on DKIM or SPF failure\n\n## Remember to set up\n- email input mailbox\n- notification channels"
},
"typeVersion": 1
},
{
"id": "1457272e-630e-44ee-bb18-ac650d192cbf",
"name": "Unzip File",
"type": "n8n-nodes-base.compression",
"position": [
800,
300
],
"parameters": {
"binaryPropertyName": "attachment_0"
},
"typeVersion": 1.1
},
{
"id": "89ade90c-c7e3-4c6f-89cf-0e7ce1e55333",
"name": "Extract XML data",
"type": "n8n-nodes-base.extractFromFile",
"position": [
1020,
300
],
"parameters": {
"options": {},
"operation": "xml",
"binaryPropertyName": "file_0"
},
"typeVersion": 1
},
{
"id": "8fd70f3c-53d5-4d99-ad2c-d526089fe0f5",
"name": "Parse XML data to JSON",
"type": "n8n-nodes-base.xml",
"position": [
1220,
300
],
"parameters": {
"options": {}
},
"typeVersion": 1
},
{
"id": "b17352d9-135a-4c26-993f-0c1fdafc1fa3",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1420,
300
],
"parameters": {
"width": 394.2691415313225,
"height": 159.80531276753783,
"content": "## Preparation\nThis line is responsible for taking data from email and parsing it into JSON understandable by n8n"
},
"typeVersion": 1
},
{
"id": "31d2f822-aea6-41b4-bb1e-25b48cb3e972",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1420,
500
],
"parameters": {
"width": 394.2691415313225,
"height": 316.3177609714967,
"content": "## Mapping\nThis line is responsible for treating cases when XML has multiple info for domain. One DMARC report can contain more than one entries.\n\nLast node is responsible for matching data with database structure"
},
"typeVersion": 1
},
{
"id": "e8fc0f91-1bdf-4bc5-b488-4f2c169da9c0",
"name": "Split Out For Separate Entries",
"type": "n8n-nodes-base.splitOut",
"position": [
800,
500
],
"parameters": {
"include": "allOtherFields",
"options": {},
"fieldToSplitOut": "feedback.record"
},
"typeVersion": 1
},
{
"id": "9ba7a0b8-80e6-4559-83ec-894533194dc7",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1420,
860
],
"parameters": {
"width": 394.2691415313225,
"height": 185.89072080153096,
"content": "## Date translate\nThis line is responsible for translating date format into understandable by MySQL/MariaDB\n\nIn next node data is being input into MySQL/MariaDB "
},
"typeVersion": 1
},
{
"id": "96461e30-87f0-48f1-a43f-60185ea1d835",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1420,
1180
],
"parameters": {
"width": 394.2691415313225,
"height": 320.66532897716223,
"content": "## Notifications\nLast two nodes are responsible for sending notifications in case IF inside DMARC report is reported any issue with SPF or DKIM"
},
"typeVersion": 1
},
{
"id": "192b95c6-cdfe-4b5e-94e1-94deb728b0e2",
"name": "Slack Post Message On Channel",
"type": "n8n-nodes-base.slack",
"disabled": true,
"position": [
1200,
1180
],
"parameters": {
"text": "=DMARC evaluation failed for {{ $json.domain }} on {{ $json.mail_count }} mails with disposition: {{ $json.evaluated_disposition }}. DKIM: {{ $json.evaluated_dkim }} SPF: {{ $json.evaluated_spf }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "CCGJA1F1N",
"cachedResultName": "powiadomienia"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "B0jUtT53pVAEPaQM",
"name": "Slack Oauth"
}
},
"typeVersion": 2.2
},
{
"id": "ce400c97-cae4-41db-ad8f-e678fc4a27fe",
"name": "Send Error Notification Email",
"type": "n8n-nodes-base.emailSend",
"disabled": true,
"position": [
1200,
1380
],
"parameters": {
"text": "DMARC evaluation failed for {{ $json.domain }} on {{ $json.mail_count }} mails with disposition: {{ $json.evaluated_disposition }}. DKIM: {{ $json.evaluated_dkim }} SPF: {{ $json.evaluated_spf }}",
"options": {},
"subject": "DMARC problem",
"emailFormat": "text"
},
"typeVersion": 2.1
}
],
"active": true,
"pinData": {},
"settings": {
"callerPolicy": "workflowsFromSameOwner",
"errorWorkflow": "5",
"executionOrder": "v1",
"saveManualExecutions": true,
"saveExecutionProgress": true,
"saveDataSuccessExecution": "all"
},
"versionId": "1add308c-4aef-4a83-a958-bc66dead234f",
"connections": {
"Unzip File": {
"main": [
[
{
"node": "Extract XML data",
"type": "main",
"index": 0
}
]
]
},
"Rename Keys": {
"main": [
[
{
"node": "Map fields for DB input and parse",
"type": "main",
"index": 0
}
]
]
},
"End date format": {
"main": [
[
{
"node": "Input into database",
"type": "main",
"index": 0
},
{
"node": "If issue with DKIM or SPF",
"type": "main",
"index": 0
}
]
]
},
"Extract XML data": {
"main": [
[
{
"node": "Parse XML data to JSON",
"type": "main",
"index": 0
}
]
]
},
"Begin format date": {
"main": [
[
{
"node": "End date format",
"type": "main",
"index": 0
}
]
]
},
"Email Trigger (IMAP)": {
"main": [
[
{
"node": "Unzip File",
"type": "main",
"index": 0
}
]
]
},
"Parse XML data to JSON": {
"main": [
[
{
"node": "If multiple records to parse",
"type": "main",
"index": 0
}
]
]
},
"If issue with DKIM or SPF": {
"main": [
[
{
"node": "Slack Post Message On Channel",
"type": "main",
"index": 0
},
{
"node": "Send Error Notification Email",
"type": "main",
"index": 0
}
]
]
},
"If multiple records to parse": {
"main": [
[
{
"node": "Split Out For Separate Entries",
"type": "main",
"index": 0
}
],
[
{
"node": "Rename column for consistency",
"type": "main",
"index": 0
}
]
]
},
"Rename column for consistency": {
"main": [
[
{
"node": "Map fields for DB input and parse",
"type": "main",
"index": 0
}
]
]
},
"Split Out For Separate Entries": {
"main": [
[
{
"node": "Rename Keys",
"type": "main",
"index": 0
}
]
]
},
"Map fields for DB input and parse": {
"main": [
[
{
"node": "Begin format date",
"type": "main",
"index": 0
}
]
]
}
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,316 @@
{
"id": "JIegnKLVXTkkTzfO",
"meta": {
"instanceId": "bdce9ec27bbe2b742054f01d034b8b468d2e7758edd716403ad5bd4583a8f649",
"templateCredsSetupCompleted": true
},
"name": "Daylight Saving Time Notification",
"tags": [],
"nodes": [
{
"id": "87b11535-a9ae-49d4-a33f-b895274643e5",
"name": "When clicking Test workflow",
"type": "n8n-nodes-base.manualTrigger",
"position": [
0,
0
],
"parameters": {},
"typeVersion": 1
},
{
"id": "d1cd9157-9948-43fd-a725-2a82a21a82c6",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
340,
-300
],
"parameters": {
"width": 394,
"height": 264,
"content": "## How it works\n- check list of timezones\n- check if any timezone switches from/to Daylight Saving Time\n- notify on Slack\n\n## Remember to set up\n- Add timezones to \"Timezones List\"\n- Slack notification channel\n"
},
"typeVersion": 1
},
{
"id": "0f4369fc-80b6-4fd6-8533-4aacbf4c9c65",
"name": "Timezones List",
"type": "n8n-nodes-base.code",
"position": [
220,
0
],
"parameters": {
"jsCode": "return [\n\t{\n timezone : \"America/New_York\"\n\t},\n\t{\n timezone : \"Europe/Warsaw\"\n\t},\n];"
},
"typeVersion": 2
},
{
"id": "3c1e6cd7-3812-4670-a53f-7270e29574f9",
"name": "Calculate Zone Date and Time",
"type": "n8n-nodes-base.set",
"position": [
440,
0
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "4e9f973f-a11f-474b-89ce-dac4a77a7c68",
"name": "datetime_zone",
"type": "string",
"value": "={{ $now.setZone( $json.timezone ) }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "7f49ac42-afcb-4552-84da-180bc65b84b0",
"name": "Check If Daylight Saving Time",
"type": "n8n-nodes-base.set",
"position": [
40,
280
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "4e9f973f-a11f-474b-89ce-dac4a77a7c68",
"name": "datetime_zone_dst",
"type": "string",
"value": "={{ $json.datetime_zone.toDateTime().setZone($json.timezone).isInDST }}"
},
{
"id": "ff13ee6d-c146-4dcb-98c4-6cb9b2474b1d",
"name": "datetime_zone_tomorrow_dst",
"type": "string",
"value": "={{ $json.datetime_zone_tomorrow.toDateTime().setZone($json.timezone).isInDST }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "f3596b52-03af-4a07-be04-a7300fc7b239",
"name": "Check If Change Tomorrow",
"type": "n8n-nodes-base.if",
"position": [
240,
280
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "1f49e05d-d36e-4652-8ad3-b2266d750d94",
"operator": {
"type": "boolean",
"operation": "notEquals"
},
"leftValue": "={{ $json.datetime_zone_dst }}",
"rightValue": "={{ $json.datetime_zone_tomorrow_dst }}"
}
]
},
"looseTypeValidation": true
},
"typeVersion": 2.2
},
{
"id": "612e2e06-0283-4acd-8d85-cba16acb7126",
"name": "Send Notification On Upcoming Change",
"type": "n8n-nodes-base.slack",
"position": [
660,
240
],
"webhookId": "871515be-56fc-4de7-835b-119d394fea47",
"parameters": {
"text": "=Tomorrow is Daylight Saving Time change in zone {{ $json.timezone }} - remember to adjust meeting times!",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": ""
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "B0jUtT53pVAEPaQM",
"name": "Slack Oauth"
}
},
"typeVersion": 2.3
},
{
"id": "d5e47ff8-d530-47ee-a98d-3a50a7054cb0",
"name": "Calculate Tomorrow's Date",
"type": "n8n-nodes-base.dateTime",
"position": [
660,
0
],
"parameters": {
"options": {
"includeInputFields": true
},
"duration": 1,
"magnitude": "={{ $json.datetime_zone }}",
"operation": "addToDate",
"outputFieldName": "datetime_zone_tomorrow"
},
"typeVersion": 2
},
{
"id": "5ae0aa75-515d-4025-901e-82693f697436",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
0,
-160
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.2
},
{
"id": "e233c67c-a79b-4c96-a172-0465021d3911",
"name": "Send Email On Upcoming Change",
"type": "n8n-nodes-base.emailSend",
"position": [
660,
420
],
"webhookId": "40cc0fc1-c135-44fc-b3cb-dfec6fc1ce75",
"parameters": {
"text": "=Tomorrow is Daylight Saving Time change in zone {{ $json.timezone }} - remember to adjust meeting times!",
"options": {},
"subject": "DST change tomorrow in {{ $json.timezone }}",
"emailFormat": "text"
},
"credentials": {
"smtp": {
"id": "tkdzDgcUAt04af3B",
"name": "SMTP account"
}
},
"typeVersion": 2.1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "7605726a-1a09-4564-b60f-aee3ac0b8c70",
"connections": {
"Timezones List": {
"main": [
[
{
"node": "Calculate Zone Date and Time",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Timezones List",
"type": "main",
"index": 0
}
]
]
},
"Check If Change Tomorrow": {
"main": [
[
{
"node": "Send Notification On Upcoming Change",
"type": "main",
"index": 0
},
{
"node": "Send Email On Upcoming Change",
"type": "main",
"index": 0
}
],
[]
]
},
"Calculate Tomorrow's Date": {
"main": [
[
{
"node": "Check If Daylight Saving Time",
"type": "main",
"index": 0
}
]
]
},
"Calculate Zone Date and Time": {
"main": [
[
{
"node": "Calculate Tomorrow's Date",
"type": "main",
"index": 0
}
]
]
},
"Check If Daylight Saving Time": {
"main": [
[
{
"node": "Check If Change Tomorrow",
"type": "main",
"index": 0
}
]
]
},
"When clicking Test workflow": {
"main": [
[
{
"node": "Timezones List",
"type": "main",
"index": 0
}
]
]
}
}
}

View File

@@ -0,0 +1,678 @@
{
"id": "WulUYgcXvako9hBy",
"meta": {
"instanceId": "d6b86682c7e02b79169c1a61ad0484dcda5bc8b0ea70f1a95dac239c2abfd057",
"templateCredsSetupCompleted": true
},
"name": "Testing Mulitple Local LLM with LM Studio",
"tags": [
{
"id": "RkTiZTdbLvr6uzSg",
"name": "Training",
"createdAt": "2024-06-18T16:09:35.806Z",
"updatedAt": "2024-06-18T16:09:35.806Z"
},
{
"id": "W3xdiSeIujD7XgBA",
"name": "Template",
"createdAt": "2024-06-18T22:15:34.874Z",
"updatedAt": "2024-06-18T22:15:34.874Z"
}
],
"nodes": [
{
"id": "08c457ef-5c1f-46d8-a53e-f492b11c83f9",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1600,
420
],
"parameters": {
"color": 6,
"width": 478.38709677419376,
"height": 347.82258064516134,
"content": "## 🧠Text Analysis\n### Readability Score Ranges:\nWhen testing model responses, readability scores can range across different levels. Heres a breakdown:\n\n- **90100**: Very easy to read (5th grade or below)\n- **8089**: Easy to read (6th grade)\n- **7079**: Fairly easy to read (7th grade)\n- **6069**: Standard (8th to 9th grade)\n- **5059**: Fairly difficult (10th to 12th grade)\n- **3049**: Difficult (College)\n- **029**: Very difficult (College graduate)\n- **Below 0**: Extremely difficult (Post-graduate level)\n"
},
"typeVersion": 1
},
{
"id": "7801734c-5eb9-4abd-b234-e406462931f7",
"name": "Get Models",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
20,
180
],
"parameters": {
"url": "http://192.168.1.179:1234/v1/models",
"options": {
"timeout": 10000,
"allowUnauthorizedCerts": false
}
},
"typeVersion": 4.2
},
{
"id": "5ee93d9a-ad2e-4ea9-838e-2c12a168eae6",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-140,
-100
],
"parameters": {
"width": 377.6129032258063,
"height": 264.22580645161304,
"content": "## ⚙️ 2. Update Local IP\nUpdate the **'Base URL'** `http://192.168.1.1:1234/v1/models` in the workflow to match the IP of your LM Studio server. (Running LM Server)[https://lmstudio.ai/docs/basics/server]\n\nThis node will query the LM Studio server to retrieve a list of all loaded model IDs at the time of the query. If you change or add models to LM Studio, youll need to rerun this node to get an updated list of active LLMs.\n"
},
"typeVersion": 1
},
{
"id": "f2b6a6ed-0ef1-4f2c-8350-9abd59d08e61",
"name": "When chat message received",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"position": [
-300,
180
],
"webhookId": "39c3c6d5-ea06-4faa-b0e3-4e77a05b0297",
"parameters": {
"options": {}
},
"typeVersion": 1.1
},
{
"id": "dbaf0ad1-9027-4317-a996-33a3fcc9e258",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-740,
200
],
"parameters": {
"width": 378.75806451612857,
"height": 216.12903225806457,
"content": "## 🛠1. Setup - LM Studio\nFirst, download and install [LM Studio](https://lmstudio.ai/). Identify which LLM models you want to use for testing.\n\nNext, the selected models are loaded into the server capabilities to prepare them for testing. For a detailed guide on how to set up multiple models, refer to the [LM Studio Basics](https://lmstudio.ai/docs/basics) documentation.\n"
},
"typeVersion": 1
},
{
"id": "36770fd1-7863-4c42-a68d-8d240ae3683b",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
360,
400
],
"parameters": {
"width": 570.0000000000002,
"height": 326.0645161290325,
"content": "## 3. 💡Update the LM Settings\n\nFrom here, you can modify the following\n parameters to fine-tune model behavior:\n\n- **Temperature**: Controls randomness. Higher values (e.g., 1.0) produce more diverse results, while lower values (e.g., 0.2) make responses more focused and deterministic.\n- **Top P**: Adjusts nucleus sampling, where the model considers only a subset of probable tokens. A lower value (e.g., 0.5) narrows the response range.\n- **Presence Penalty**: Penalizes new tokens based on their presence in the input, encouraging the model to generate more varied responses.\n"
},
"typeVersion": 1
},
{
"id": "6b36f094-a3bf-4ff7-9385-4f7a2c80d54f",
"name": "Get timeDifference",
"type": "n8n-nodes-base.dateTime",
"position": [
1600,
160
],
"parameters": {
"endDate": "={{ $json.endDateTime }}",
"options": {},
"operation": "getTimeBetweenDates",
"startDate": "={{ $('Capture Start Time').item.json.startDateTime }}"
},
"typeVersion": 2
},
{
"id": "a0b8f29d-2f2f-4fcf-a54a-dff071e321e5",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1900,
-260
],
"parameters": {
"width": 304.3225806451618,
"height": 599.7580645161281,
"content": "## 📊4. Create Google Sheet (Optional)\n1. First, create a Google Sheet with the following headers:\n - Prompt\n - Time Sent\n - Time Received\n - Total Time Spent\n - Model\n - Response\n - Readability Score\n - Average Word Length\n - Word Count\n - Sentence Count\n - Average Sentence Length\n2. After creating the sheet, update the corresponding Google Sheets node in the workflow to map the data fields correctly.\n"
},
"typeVersion": 1
},
{
"id": "d376a5fb-4e07-42a3-aa0c-8ccc1b9feeb7",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-760,
-200
],
"parameters": {
"color": 5,
"width": 359.2903225806448,
"height": 316.9032258064518,
"content": "## 🏗Setup Steps\n1. **Download and Install LM Studio**: Ensure LM Studio is correctly installed on your machine.\n2. **Update the Base URL**: Replace the base URL with the IP address of your LLM instance. Ensure the connection is established.\n3. **Configure LLM Settings**: Verify that your LLM models are properly set up and configured in LM Studio.\n4. **Create a Google Sheet**: Set up a Google Sheet with the necessary headers (Prompt, Time Sent, Time Received, etc.) to track your testing results.\n"
},
"typeVersion": 1
},
{
"id": "b21cad30-573e-4adf-a1d0-f34cf9628819",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
560,
-160
],
"parameters": {
"width": 615.8064516129025,
"height": 272.241935483871,
"content": "## 📖Prompting Multiple LLMs\n\nWhen testing for specific outcomes (such as conciseness or readability), you can add a **System Prompt** in the LLM Chain to guide the models' responses.\n\n**System Prompt Suggestion**:\n- Focus on ensuring that responses are concise, clear, and easily understandable by a 5th-grade reading level. \n- This prompt will help you compare models based on how well they meet readability standards and stay on point.\n \nAdjust the prompt to fit your desired testing criteria.\n"
},
"typeVersion": 1
},
{
"id": "dd5f7e7b-bc69-4b67-90e6-2077b6b93148",
"name": "Run Model with Dunamic Inputs",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1020,
400
],
"parameters": {
"model": "={{ $node['Extract Model IDsto Run Separately'].json.id }}",
"options": {
"topP": 1,
"baseURL": "http://192.168.1.179:1234/v1",
"timeout": 250000,
"temperature": 1,
"presencePenalty": 0
}
},
"credentials": {
"openAiApi": {
"id": "LBE5CXY4yeWrZCsy",
"name": "OpenAi account"
}
},
"typeVersion": 1
},
{
"id": "a0ee6c9a-cf76-4633-9c43-a7dc10a1f73e",
"name": "Analyze LLM Response Metrics",
"type": "n8n-nodes-base.code",
"position": [
2000,
160
],
"parameters": {
"jsCode": "// Get the input data from n8n\nconst inputData = items.map(item => item.json);\n\n// Function to count words in a string\nfunction countWords(text) {\n return text.trim().split(/\\s+/).length;\n}\n\n// Function to count sentences in a string\nfunction countSentences(text) {\n const sentences = text.match(/[^.!?]+[.!?]+/g) || [];\n return sentences.length;\n}\n\n// Function to calculate average sentence length\nfunction averageSentenceLength(text) {\n const sentences = text.match(/[^.!?]+[.!?]+/g) || [];\n const sentenceLengths = sentences.map(sentence => sentence.trim().split(/\\s+/).length);\n const totalWords = sentenceLengths.reduce((acc, val) => acc + val, 0);\n return sentenceLengths.length ? (totalWords / sentenceLengths.length) : 0;\n}\n\n// Function to calculate average word length\nfunction averageWordLength(text) {\n const words = text.trim().split(/\\s+/);\n const totalCharacters = words.reduce((acc, word) => acc + word.length, 0);\n return words.length ? (totalCharacters / words.length) : 0;\n}\n\n// Function to calculate Flesch-Kincaid Readability Score\nfunction fleschKincaidReadability(text) {\n // Split text into sentences (approximate)\n const sentences = text.match(/[^.!?]+[.!?]*[\\n]*/g) || [];\n // Split text into words\n const words = text.trim().split(/\\s+/);\n // Estimate syllable count by matching vowel groups\n const syllableCount = (text.toLowerCase().match(/[aeiouy]{1,2}/g) || []).length;\n\n const sentenceCount = sentences.length;\n const wordCount = words.length;\n\n // Avoid division by zero\n if (wordCount === 0 || sentenceCount === 0) return 0;\n\n const averageWordsPerSentence = wordCount / sentenceCount;\n const averageSyllablesPerWord = syllableCount / wordCount;\n\n // Flesch-Kincaid formula\n return 206.835 - (1.015 * averageWordsPerSentence) - (84.6 * averageSyllablesPerWord);\n}\n\n\n// Prepare the result array for n8n output\nconst resultArray = [];\n\n// Loop through the input data and analyze each LLM response\ninputData.forEach(item => {\n const llmResponse = item.llm_response;\n\n // Perform the analyses\n const wordCount = countWords(llmResponse);\n const sentenceCount = countSentences(llmResponse);\n const avgSentenceLength = averageSentenceLength(llmResponse);\n const readabilityScore = fleschKincaidReadability(llmResponse);\n const avgWordLength = averageWordLength(llmResponse);\n\n // Structure the output to include original input and new calculated values\n resultArray.push({\n json: {\n llm_response: item.llm_response,\n prompt: item.prompt,\n model: item.model,\n start_time: item.start_time,\n end_time: item.end_time,\n time_diff: item.time_diff,\n word_count: wordCount,\n sentence_count: sentenceCount,\n average_sent_length: avgSentenceLength,\n readability_score: readabilityScore,\n average_word_length: avgWordLength\n }\n });\n});\n\n// Return the result array to n8n\nreturn resultArray;\n"
},
"typeVersion": 2
},
{
"id": "adef5d92-cb7e-417e-acbb-1a5d6c26426a",
"name": "Save Results to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
2180,
160
],
"parameters": {
"columns": {
"value": {
"Model": "={{ $('Extract Model IDsto Run Separately').item.json.id }}",
"Prompt": "={{ $json.prompt }}",
"Response ": "={{ $('LLM Response Analysis').item.json.text }}",
"TIme Sent": "={{ $json.start_time }}",
"Word_count": "={{ $json.word_count }}",
"Sentence_count": "={{ $json.sentence_count }}",
"Time Recieved ": "={{ $json.end_time }}",
"Total TIme spent ": "={{ $json.time_diff }}",
"readability_score": "={{ $json.readability_score }}",
"Average_sent_length": "={{ $json.average_sent_length }}",
"average_word_length": "={{ $json.average_word_length }}"
},
"schema": [
{
"id": "Prompt",
"type": "string",
"display": true,
"required": false,
"displayName": "Prompt",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "TIme Sent",
"type": "string",
"display": true,
"required": false,
"displayName": "TIme Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Time Recieved ",
"type": "string",
"display": true,
"required": false,
"displayName": "Time Recieved ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total TIme spent ",
"type": "string",
"display": true,
"required": false,
"displayName": "Total TIme spent ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Model",
"type": "string",
"display": true,
"required": false,
"displayName": "Model",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Response ",
"type": "string",
"display": true,
"required": false,
"displayName": "Response ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "readability_score",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "readability_score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "average_word_length",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "average_word_length",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Word_count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Word_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Sentence_count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Sentence_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Average_sent_length",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Average_sent_length",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": []
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GdoTjKOrhWOqSZb-AoLNlXgRGBdXKSbXpy-EsZaPGvg/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1GdoTjKOrhWOqSZb-AoLNlXgRGBdXKSbXpy-EsZaPGvg",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GdoTjKOrhWOqSZb-AoLNlXgRGBdXKSbXpy-EsZaPGvg/edit?usp=drivesdk",
"cachedResultName": "Teacking LLM Success"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "DMnEU30APvssJZwc",
"name": "Google Sheets account"
}
},
"typeVersion": 4.5
},
{
"id": "2e147670-67af-4dde-8ba8-90b685238599",
"name": "Capture End Time",
"type": "n8n-nodes-base.dateTime",
"position": [
1380,
160
],
"parameters": {
"options": {},
"outputFieldName": "endDateTime"
},
"typeVersion": 2
},
{
"id": "5a8d3334-b7f8-4f14-8026-055db795bb1f",
"name": "Capture Start Time",
"type": "n8n-nodes-base.dateTime",
"position": [
520,
160
],
"parameters": {
"options": {},
"outputFieldName": "startDateTime"
},
"typeVersion": 2
},
{
"id": "c42d1748-a10d-4792-8526-5ea1c542eeec",
"name": "Prepare Data for Analysis",
"type": "n8n-nodes-base.set",
"position": [
1800,
160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "920ffdcc-2ae1-4ccb-bc54-049d9d84bd42",
"name": "llm_response",
"type": "string",
"value": "={{ $('LLM Response Analysis').item.json.text }}"
},
{
"id": "c3e70e1b-055c-4a91-aeb0-3d00d41af86d",
"name": "prompt",
"type": "string",
"value": "={{ $('When chat message received').item.json.chatInput }}"
},
{
"id": "cfa45a85-7e60-4a09-b1ed-f9ad51161254",
"name": "model",
"type": "string",
"value": "={{ $('Extract Model IDsto Run Separately').item.json.id }}"
},
{
"id": "a49758c8-4828-41d9-b1d8-4e64dc06920b",
"name": "start_time",
"type": "string",
"value": "={{ $('Capture Start Time').item.json.startDateTime }}"
},
{
"id": "6206be8f-f088-4c4d-8a84-96295937afe2",
"name": "end_time",
"type": "string",
"value": "={{ $('Capture End Time').item.json.endDateTime }}"
},
{
"id": "421b52f9-6184-4bfa-b36a-571e1ea40ce4",
"name": "time_diff",
"type": "string",
"value": "={{ $json.timeDifference.days }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "04679ba8-f13c-4453-99ac-970095bffc20",
"name": "Extract Model IDsto Run Separately",
"type": "n8n-nodes-base.splitOut",
"position": [
300,
160
],
"parameters": {
"options": {},
"fieldToSplitOut": "data"
},
"typeVersion": 1
},
{
"id": "97cdd050-5538-47e1-a67a-ea6e90e89b19",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
2240,
-160
],
"parameters": {
"width": 330.4677419354838,
"height": 182.9032258064516,
"content": "### Optional\nYou can just delete the google sheet node, and review the results by hand. \n\nUtilizing the google sheet, allows you to provide mulitple prompts and review the analysis against all of those runs."
},
"typeVersion": 1
},
{
"id": "5a1558ec-54e8-4860-b3db-edcb47c52413",
"name": "Add System Prompt",
"type": "n8n-nodes-base.set",
"position": [
740,
160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "fd48436f-8242-4c01-a7c3-246d28a8639f",
"name": "system_prompt",
"type": "string",
"value": "Ensure that messages are concise and to the point readable by a 5th grader."
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "74df223b-17ab-4189-a171-78224522e1c7",
"name": "LLM Response Analysis",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
1000,
160
],
"parameters": {
"text": "={{ $('When chat message received').item.json.chatInput }}",
"messages": {
"messageValues": [
{
"message": "={{ $json.system_prompt }}"
}
]
},
"promptType": "define"
},
"typeVersion": 1.4
},
{
"id": "65d8b0d3-7285-4c64-8ca5-4346e68ec075",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
380,
780
],
"parameters": {
"color": 3,
"width": 570.0000000000002,
"height": 182.91935483870984,
"content": "## 🚀Pro Tip \n\nIf you are getting strange results, ensure that you are Deleting the previous chat (next to the Chat Button) to ensure you aren't bleeding responses into the next chat. "
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"timezone": "America/Denver",
"callerPolicy": "workflowsFromSameOwner",
"executionOrder": "v1",
"saveManualExecutions": true
},
"versionId": "a80bee71-8e21-40ff-8803-42d38f316bfb",
"connections": {
"Get Models": {
"main": [
[
{
"node": "Extract Model IDsto Run Separately",
"type": "main",
"index": 0
}
]
]
},
"Capture End Time": {
"main": [
[
{
"node": "Get timeDifference",
"type": "main",
"index": 0
}
]
]
},
"Add System Prompt": {
"main": [
[
{
"node": "LLM Response Analysis",
"type": "main",
"index": 0
}
]
]
},
"Capture Start Time": {
"main": [
[
{
"node": "Add System Prompt",
"type": "main",
"index": 0
}
]
]
},
"Get timeDifference": {
"main": [
[
{
"node": "Prepare Data for Analysis",
"type": "main",
"index": 0
}
]
]
},
"LLM Response Analysis": {
"main": [
[
{
"node": "Capture End Time",
"type": "main",
"index": 0
}
]
]
},
"Prepare Data for Analysis": {
"main": [
[
{
"node": "Analyze LLM Response Metrics",
"type": "main",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "Get Models",
"type": "main",
"index": 0
}
]
]
},
"Analyze LLM Response Metrics": {
"main": [
[
{
"node": "Save Results to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Run Model with Dunamic Inputs": {
"ai_languageModel": [
[
{
"node": "LLM Response Analysis",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Extract Model IDsto Run Separately": {
"main": [
[
{
"node": "Capture Start Time",
"type": "main",
"index": 0
}
]
]
}
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,678 @@
{
"id": "WulUYgcXvako9hBy",
"meta": {
"instanceId": "d6b86682c7e02b79169c1a61ad0484dcda5bc8b0ea70f1a95dac239c2abfd057",
"templateCredsSetupCompleted": true
},
"name": "Testing Mulitple Local LLM with LM Studio",
"tags": [
{
"id": "RkTiZTdbLvr6uzSg",
"name": "Training",
"createdAt": "2024-06-18T16:09:35.806Z",
"updatedAt": "2024-06-18T16:09:35.806Z"
},
{
"id": "W3xdiSeIujD7XgBA",
"name": "Template",
"createdAt": "2024-06-18T22:15:34.874Z",
"updatedAt": "2024-06-18T22:15:34.874Z"
}
],
"nodes": [
{
"id": "08c457ef-5c1f-46d8-a53e-f492b11c83f9",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1600,
420
],
"parameters": {
"color": 6,
"width": 478.38709677419376,
"height": 347.82258064516134,
"content": "## \ud83e\udde0Text Analysis\n### Readability Score Ranges:\nWhen testing model responses, readability scores can range across different levels. Here\u2019s a breakdown:\n\n- **90\u2013100**: Very easy to read (5th grade or below)\n- **80\u201389**: Easy to read (6th grade)\n- **70\u201379**: Fairly easy to read (7th grade)\n- **60\u201369**: Standard (8th to 9th grade)\n- **50\u201359**: Fairly difficult (10th to 12th grade)\n- **30\u201349**: Difficult (College)\n- **0\u201329**: Very difficult (College graduate)\n- **Below 0**: Extremely difficult (Post-graduate level)\n"
},
"typeVersion": 1
},
{
"id": "7801734c-5eb9-4abd-b234-e406462931f7",
"name": "Get Models",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
20,
180
],
"parameters": {
"url": "http://192.168.1.179:1234/v1/models",
"options": {
"timeout": 10000,
"allowUnauthorizedCerts": false
}
},
"typeVersion": 4.2
},
{
"id": "5ee93d9a-ad2e-4ea9-838e-2c12a168eae6",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-140,
-100
],
"parameters": {
"width": 377.6129032258063,
"height": 264.22580645161304,
"content": "## \u2699\ufe0f 2. Update Local IP\nUpdate the **'Base URL'** `http://192.168.1.1:1234/v1/models` in the workflow to match the IP of your LM Studio server. (Running LM Server)[https://lmstudio.ai/docs/basics/server]\n\nThis node will query the LM Studio server to retrieve a list of all loaded model IDs at the time of the query. If you change or add models to LM Studio, you\u2019ll need to rerun this node to get an updated list of active LLMs.\n"
},
"typeVersion": 1
},
{
"id": "f2b6a6ed-0ef1-4f2c-8350-9abd59d08e61",
"name": "When chat message received",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"position": [
-300,
180
],
"webhookId": "39c3c6d5-ea06-4faa-b0e3-4e77a05b0297",
"parameters": {
"options": {}
},
"typeVersion": 1.1
},
{
"id": "dbaf0ad1-9027-4317-a996-33a3fcc9e258",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-740,
200
],
"parameters": {
"width": 378.75806451612857,
"height": 216.12903225806457,
"content": "## \ud83d\udee0\ufe0f1. Setup - LM Studio\nFirst, download and install [LM Studio](https://lmstudio.ai/). Identify which LLM models you want to use for testing.\n\nNext, the selected models are loaded into the server capabilities to prepare them for testing. For a detailed guide on how to set up multiple models, refer to the [LM Studio Basics](https://lmstudio.ai/docs/basics) documentation.\n"
},
"typeVersion": 1
},
{
"id": "36770fd1-7863-4c42-a68d-8d240ae3683b",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
360,
400
],
"parameters": {
"width": 570.0000000000002,
"height": 326.0645161290325,
"content": "## 3. \ud83d\udca1Update the LM Settings\n\nFrom here, you can modify the following\n parameters to fine-tune model behavior:\n\n- **Temperature**: Controls randomness. Higher values (e.g., 1.0) produce more diverse results, while lower values (e.g., 0.2) make responses more focused and deterministic.\n- **Top P**: Adjusts nucleus sampling, where the model considers only a subset of probable tokens. A lower value (e.g., 0.5) narrows the response range.\n- **Presence Penalty**: Penalizes new tokens based on their presence in the input, encouraging the model to generate more varied responses.\n"
},
"typeVersion": 1
},
{
"id": "6b36f094-a3bf-4ff7-9385-4f7a2c80d54f",
"name": "Get timeDifference",
"type": "n8n-nodes-base.dateTime",
"position": [
1600,
160
],
"parameters": {
"endDate": "={{ $json.endDateTime }}",
"options": {},
"operation": "getTimeBetweenDates",
"startDate": "={{ $('Capture Start Time').item.json.startDateTime }}"
},
"typeVersion": 2
},
{
"id": "a0b8f29d-2f2f-4fcf-a54a-dff071e321e5",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1900,
-260
],
"parameters": {
"width": 304.3225806451618,
"height": 599.7580645161281,
"content": "## \ud83d\udcca4. Create Google Sheet (Optional)\n1. First, create a Google Sheet with the following headers:\n - Prompt\n - Time Sent\n - Time Received\n - Total Time Spent\n - Model\n - Response\n - Readability Score\n - Average Word Length\n - Word Count\n - Sentence Count\n - Average Sentence Length\n2. After creating the sheet, update the corresponding Google Sheets node in the workflow to map the data fields correctly.\n"
},
"typeVersion": 1
},
{
"id": "d376a5fb-4e07-42a3-aa0c-8ccc1b9feeb7",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-760,
-200
],
"parameters": {
"color": 5,
"width": 359.2903225806448,
"height": 316.9032258064518,
"content": "## \ud83c\udfd7\ufe0fSetup Steps\n1. **Download and Install LM Studio**: Ensure LM Studio is correctly installed on your machine.\n2. **Update the Base URL**: Replace the base URL with the IP address of your LLM instance. Ensure the connection is established.\n3. **Configure LLM Settings**: Verify that your LLM models are properly set up and configured in LM Studio.\n4. **Create a Google Sheet**: Set up a Google Sheet with the necessary headers (Prompt, Time Sent, Time Received, etc.) to track your testing results.\n"
},
"typeVersion": 1
},
{
"id": "b21cad30-573e-4adf-a1d0-f34cf9628819",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
560,
-160
],
"parameters": {
"width": 615.8064516129025,
"height": 272.241935483871,
"content": "## \ud83d\udcd6Prompting Multiple LLMs\n\nWhen testing for specific outcomes (such as conciseness or readability), you can add a **System Prompt** in the LLM Chain to guide the models' responses.\n\n**System Prompt Suggestion**:\n- Focus on ensuring that responses are concise, clear, and easily understandable by a 5th-grade reading level. \n- This prompt will help you compare models based on how well they meet readability standards and stay on point.\n \nAdjust the prompt to fit your desired testing criteria.\n"
},
"typeVersion": 1
},
{
"id": "dd5f7e7b-bc69-4b67-90e6-2077b6b93148",
"name": "Run Model with Dunamic Inputs",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1020,
400
],
"parameters": {
"model": "={{ $node['Extract Model IDsto Run Separately'].json.id }}",
"options": {
"topP": 1,
"baseURL": "http://192.168.1.179:1234/v1",
"timeout": 250000,
"temperature": 1,
"presencePenalty": 0
}
},
"credentials": {
"openAiApi": {
"id": "LBE5CXY4yeWrZCsy",
"name": "OpenAi account"
}
},
"typeVersion": 1
},
{
"id": "a0ee6c9a-cf76-4633-9c43-a7dc10a1f73e",
"name": "Analyze LLM Response Metrics",
"type": "n8n-nodes-base.code",
"position": [
2000,
160
],
"parameters": {
"jsCode": "// Get the input data from n8n\nconst inputData = items.map(item => item.json);\n\n// Function to count words in a string\nfunction countWords(text) {\n return text.trim().split(/\\s+/).length;\n}\n\n// Function to count sentences in a string\nfunction countSentences(text) {\n const sentences = text.match(/[^.!?]+[.!?]+/g) || [];\n return sentences.length;\n}\n\n// Function to calculate average sentence length\nfunction averageSentenceLength(text) {\n const sentences = text.match(/[^.!?]+[.!?]+/g) || [];\n const sentenceLengths = sentences.map(sentence => sentence.trim().split(/\\s+/).length);\n const totalWords = sentenceLengths.reduce((acc, val) => acc + val, 0);\n return sentenceLengths.length ? (totalWords / sentenceLengths.length) : 0;\n}\n\n// Function to calculate average word length\nfunction averageWordLength(text) {\n const words = text.trim().split(/\\s+/);\n const totalCharacters = words.reduce((acc, word) => acc + word.length, 0);\n return words.length ? (totalCharacters / words.length) : 0;\n}\n\n// Function to calculate Flesch-Kincaid Readability Score\nfunction fleschKincaidReadability(text) {\n // Split text into sentences (approximate)\n const sentences = text.match(/[^.!?]+[.!?]*[\\n]*/g) || [];\n // Split text into words\n const words = text.trim().split(/\\s+/);\n // Estimate syllable count by matching vowel groups\n const syllableCount = (text.toLowerCase().match(/[aeiouy]{1,2}/g) || []).length;\n\n const sentenceCount = sentences.length;\n const wordCount = words.length;\n\n // Avoid division by zero\n if (wordCount === 0 || sentenceCount === 0) return 0;\n\n const averageWordsPerSentence = wordCount / sentenceCount;\n const averageSyllablesPerWord = syllableCount / wordCount;\n\n // Flesch-Kincaid formula\n return 206.835 - (1.015 * averageWordsPerSentence) - (84.6 * averageSyllablesPerWord);\n}\n\n\n// Prepare the result array for n8n output\nconst resultArray = [];\n\n// Loop through the input data and analyze each LLM response\ninputData.forEach(item => {\n const llmResponse = item.llm_response;\n\n // Perform the analyses\n const wordCount = countWords(llmResponse);\n const sentenceCount = countSentences(llmResponse);\n const avgSentenceLength = averageSentenceLength(llmResponse);\n const readabilityScore = fleschKincaidReadability(llmResponse);\n const avgWordLength = averageWordLength(llmResponse);\n\n // Structure the output to include original input and new calculated values\n resultArray.push({\n json: {\n llm_response: item.llm_response,\n prompt: item.prompt,\n model: item.model,\n start_time: item.start_time,\n end_time: item.end_time,\n time_diff: item.time_diff,\n word_count: wordCount,\n sentence_count: sentenceCount,\n average_sent_length: avgSentenceLength,\n readability_score: readabilityScore,\n average_word_length: avgWordLength\n }\n });\n});\n\n// Return the result array to n8n\nreturn resultArray;\n"
},
"typeVersion": 2
},
{
"id": "adef5d92-cb7e-417e-acbb-1a5d6c26426a",
"name": "Save Results to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
2180,
160
],
"parameters": {
"columns": {
"value": {
"Model": "={{ $('Extract Model IDsto Run Separately').item.json.id }}",
"Prompt": "={{ $json.prompt }}",
"Response ": "={{ $('LLM Response Analysis').item.json.text }}",
"TIme Sent": "={{ $json.start_time }}",
"Word_count": "={{ $json.word_count }}",
"Sentence_count": "={{ $json.sentence_count }}",
"Time Recieved ": "={{ $json.end_time }}",
"Total TIme spent ": "={{ $json.time_diff }}",
"readability_score": "={{ $json.readability_score }}",
"Average_sent_length": "={{ $json.average_sent_length }}",
"average_word_length": "={{ $json.average_word_length }}"
},
"schema": [
{
"id": "Prompt",
"type": "string",
"display": true,
"required": false,
"displayName": "Prompt",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "TIme Sent",
"type": "string",
"display": true,
"required": false,
"displayName": "TIme Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Time Recieved ",
"type": "string",
"display": true,
"required": false,
"displayName": "Time Recieved ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total TIme spent ",
"type": "string",
"display": true,
"required": false,
"displayName": "Total TIme spent ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Model",
"type": "string",
"display": true,
"required": false,
"displayName": "Model",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Response ",
"type": "string",
"display": true,
"required": false,
"displayName": "Response ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "readability_score",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "readability_score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "average_word_length",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "average_word_length",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Word_count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Word_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Sentence_count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Sentence_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Average_sent_length",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Average_sent_length",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": []
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GdoTjKOrhWOqSZb-AoLNlXgRGBdXKSbXpy-EsZaPGvg/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1GdoTjKOrhWOqSZb-AoLNlXgRGBdXKSbXpy-EsZaPGvg",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GdoTjKOrhWOqSZb-AoLNlXgRGBdXKSbXpy-EsZaPGvg/edit?usp=drivesdk",
"cachedResultName": "Teacking LLM Success"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "DMnEU30APvssJZwc",
"name": "Google Sheets account"
}
},
"typeVersion": 4.5
},
{
"id": "2e147670-67af-4dde-8ba8-90b685238599",
"name": "Capture End Time",
"type": "n8n-nodes-base.dateTime",
"position": [
1380,
160
],
"parameters": {
"options": {},
"outputFieldName": "endDateTime"
},
"typeVersion": 2
},
{
"id": "5a8d3334-b7f8-4f14-8026-055db795bb1f",
"name": "Capture Start Time",
"type": "n8n-nodes-base.dateTime",
"position": [
520,
160
],
"parameters": {
"options": {},
"outputFieldName": "startDateTime"
},
"typeVersion": 2
},
{
"id": "c42d1748-a10d-4792-8526-5ea1c542eeec",
"name": "Prepare Data for Analysis",
"type": "n8n-nodes-base.set",
"position": [
1800,
160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "920ffdcc-2ae1-4ccb-bc54-049d9d84bd42",
"name": "llm_response",
"type": "string",
"value": "={{ $('LLM Response Analysis').item.json.text }}"
},
{
"id": "c3e70e1b-055c-4a91-aeb0-3d00d41af86d",
"name": "prompt",
"type": "string",
"value": "={{ $('When chat message received').item.json.chatInput }}"
},
{
"id": "cfa45a85-7e60-4a09-b1ed-f9ad51161254",
"name": "model",
"type": "string",
"value": "={{ $('Extract Model IDsto Run Separately').item.json.id }}"
},
{
"id": "a49758c8-4828-41d9-b1d8-4e64dc06920b",
"name": "start_time",
"type": "string",
"value": "={{ $('Capture Start Time').item.json.startDateTime }}"
},
{
"id": "6206be8f-f088-4c4d-8a84-96295937afe2",
"name": "end_time",
"type": "string",
"value": "={{ $('Capture End Time').item.json.endDateTime }}"
},
{
"id": "421b52f9-6184-4bfa-b36a-571e1ea40ce4",
"name": "time_diff",
"type": "string",
"value": "={{ $json.timeDifference.days }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "04679ba8-f13c-4453-99ac-970095bffc20",
"name": "Extract Model IDsto Run Separately",
"type": "n8n-nodes-base.splitOut",
"position": [
300,
160
],
"parameters": {
"options": {},
"fieldToSplitOut": "data"
},
"typeVersion": 1
},
{
"id": "97cdd050-5538-47e1-a67a-ea6e90e89b19",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
2240,
-160
],
"parameters": {
"width": 330.4677419354838,
"height": 182.9032258064516,
"content": "### Optional\nYou can just delete the google sheet node, and review the results by hand. \n\nUtilizing the google sheet, allows you to provide mulitple prompts and review the analysis against all of those runs."
},
"typeVersion": 1
},
{
"id": "5a1558ec-54e8-4860-b3db-edcb47c52413",
"name": "Add System Prompt",
"type": "n8n-nodes-base.set",
"position": [
740,
160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "fd48436f-8242-4c01-a7c3-246d28a8639f",
"name": "system_prompt",
"type": "string",
"value": "Ensure that messages are concise and to the point readable by a 5th grader."
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "74df223b-17ab-4189-a171-78224522e1c7",
"name": "LLM Response Analysis",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
1000,
160
],
"parameters": {
"text": "={{ $('When chat message received').item.json.chatInput }}",
"messages": {
"messageValues": [
{
"message": "={{ $json.system_prompt }}"
}
]
},
"promptType": "define"
},
"typeVersion": 1.4
},
{
"id": "65d8b0d3-7285-4c64-8ca5-4346e68ec075",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
380,
780
],
"parameters": {
"color": 3,
"width": 570.0000000000002,
"height": 182.91935483870984,
"content": "## \ud83d\ude80Pro Tip \n\nIf you are getting strange results, ensure that you are Deleting the previous chat (next to the Chat Button) to ensure you aren't bleeding responses into the next chat. "
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"timezone": "America/Denver",
"callerPolicy": "workflowsFromSameOwner",
"executionOrder": "v1",
"saveManualExecutions": true
},
"versionId": "a80bee71-8e21-40ff-8803-42d38f316bfb",
"connections": {
"Get Models": {
"main": [
[
{
"node": "Extract Model IDsto Run Separately",
"type": "main",
"index": 0
}
]
]
},
"Capture End Time": {
"main": [
[
{
"node": "Get timeDifference",
"type": "main",
"index": 0
}
]
]
},
"Add System Prompt": {
"main": [
[
{
"node": "LLM Response Analysis",
"type": "main",
"index": 0
}
]
]
},
"Capture Start Time": {
"main": [
[
{
"node": "Add System Prompt",
"type": "main",
"index": 0
}
]
]
},
"Get timeDifference": {
"main": [
[
{
"node": "Prepare Data for Analysis",
"type": "main",
"index": 0
}
]
]
},
"LLM Response Analysis": {
"main": [
[
{
"node": "Capture End Time",
"type": "main",
"index": 0
}
]
]
},
"Prepare Data for Analysis": {
"main": [
[
{
"node": "Analyze LLM Response Metrics",
"type": "main",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "Get Models",
"type": "main",
"index": 0
}
]
]
},
"Analyze LLM Response Metrics": {
"main": [
[
{
"node": "Save Results to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Run Model with Dunamic Inputs": {
"ai_languageModel": [
[
{
"node": "LLM Response Analysis",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Extract Model IDsto Run Separately": {
"main": [
[
{
"node": "Capture Start Time",
"type": "main",
"index": 0
}
]
]
}
}
}