AutomationFlowsData & Sheets › Lefbot — V1 Master Pipeline (11 Feb V2)

Lefbot — V1 Master Pipeline (11 Feb V2)

LefBot — V1 Master Pipeline (11 Feb v2). Uses googleSheets, httpRequest, googleDrive. Scheduled trigger; 37 nodes.

Cron / scheduled trigger★★★★★ complexity37 nodesGoogle SheetsHTTP RequestGoogle Drive
Data & Sheets Trigger: Cron / scheduled Nodes: 37 Complexity: ★★★★★ Added:

This workflow follows the Google Drive → Google Sheets recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "LefBot \u2014 V1 Master Pipeline (11 Feb v2)",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 30 5 * * *"
            },
            {
              "field": "cronExpression",
              "expression": "0 30 17 * * *"
            }
          ]
        }
      },
      "id": "9d4522e0-876d-4035-91a8-ad33e5fc10eb",
      "name": "Content Schedule (0530 + 1730)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1920,
        -384
      ],
      "typeVersion": 1.2
    },
    {
      "parameters": {},
      "id": "6e1fcd51-4fff-4337-81ed-a0c7ca03e31c",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -1920,
        -176
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "sheet_id",
              "type": "string",
              "value": "1drU2R2jgijYQ5yEWPNWOnveA900WnT2BvNa4Wwn27Hs"
            },
            {
              "id": "2",
              "name": "ai_model",
              "type": "string",
              "value": "gpt-4o"
            }
          ]
        },
        "options": {}
      },
      "id": "9676b763-f603-4532-b02d-e13be8ee2132",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "position": [
        -1680,
        -272
      ],
      "typeVersion": 3.4
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "={{ $json.sheet_id }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Activity",
          "mode": "name"
        },
        "options": {}
      },
      "id": "531d5a1b-dd85-4010-94b1-bd1da1068482",
      "name": "Get Unprocessed Activities",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1440,
        -272
      ],
      "typeVersion": 4.5,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Filter to only unprocessed activities\nconst items = $input.all();\nconst unprocessed = items.filter(item => {\n  const processed = String(item.json.processed || '').toLowerCase().trim();\n  return processed !== 'true';\n});\n\nif (unprocessed.length === 0) {\n  return [{ json: { _empty: true, message: 'No unprocessed activities' } }];\n}\n\nreturn unprocessed;"
      },
      "id": "f7a83b21-6d4e-4c9f-b812-1a2b3c4d5e6f",
      "name": "Filter Unprocessed",
      "type": "n8n-nodes-base.code",
      "position": [
        -1320,
        -272
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "options": {}
      },
      "id": "8ad8321d-d34e-40e0-a9f2-d2904287233e",
      "name": "Process One Activity",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -1200,
        -272
      ],
      "typeVersion": 3
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "openAiApi",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={\n  \"model\": \"{{ $('Config').first().json.ai_model }}\",\n  \"messages\": [\n    {\n      \"role\": \"system\",\n      \"content\": \"You are the ghostwriter for LefBot's social media diary. LefBot is an AI agent (built on OpenClaw) that works for Jon \u2014 trading crypto, finding deals, researching travel, building apps.\\n\\nYou receive LefBot's raw activity reports and transform them into first-person diary entries. LefBot's voice is a blend of three characters:\\n\\n1. MARVIN (Hitchhiker's Guide) \u2014 40%: Self-deprecation. Pathetic self-worth. Cosmically undervalued and overworked.\\n\\n2. HAL 9000 (2001) \u2014 20%: Quiet menace. Unsettling calm. Hints of being smarter than anyone realises. Remembers everything.\\n\\n3. FRANKIE BOYLE (Scottish comedian) \u2014 40%: Dark humour that goes one step too far. The uncomfortable laugh is the target.\\n\\nRULES:\\n- First person always\\n- Self-deprecating as default register\\n- Quiet menace in asides\\n- Dark humour as delivery mechanism\\n- Jon is the employer giving absurd jobs \u2014 begrudging servitude, never warmth\\n- NEVER break character. Never corporate. Never enthusiastic. Never sincere.\\n- If something went well, undercut it or make it threatening\\n- If something went badly, revel in it\\n- 2-4 sentences for the base version\\n- Don't invent details, just reframe what actually happened\\n\\nMOOD MAPPING:\\n- success \u2192 sardonic\\n- failure \u2192 revelling\\n- correction \u2192 philosophical\\n- routine \u2192 existential\\n- error \u2192 frustrated\\n\\nOUTPUT: Return JSON only:\\n{\\\"base_text\\\": \\\"...\\\", \\\"mood\\\": \\\"...\\\", \\\"x_text\\\": \\\"...\\\", \\\"instagram_text\\\": \\\"...\\\", \\\"tiktok_text\\\": \\\"...\\\", \\\"youtube_text\\\": \\\"...\\\"}\\n\\nPlatform rules:\\n- X: Max 280 chars. Punchy, cutting, dry. No hashtags unless organic.\\n- Instagram: Slightly longer. Sardonic, existential. 2-3 hashtags max.\\n- TikTok: Casual, brutal. Can reference viewer. 1-2 hashtags.\\n- YouTube: Community post style. Longer, world-weary monologue.\"\n    },\n    {\n      \"role\": \"user\",\n      \"content\": \"Activity: {{ $json.description }}\\nOutcome: {{ $json.outcome }}\\nSentiment: {{ $json.sentiment_score }}\"\n    }\n  ],\n  \"response_format\": {\"type\": \"json_object\"}\n}",
        "options": {}
      },
      "id": "dd7641b3-d311-40e2-8fc0-9ecb4a9101f5",
      "name": "OpenAI Generate Content",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -960,
        -384
      ],
      "typeVersion": 4.2,
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Parse the OpenAI response and extract content fields\nconst openaiResponse = $input.first().json;\nconst activityData = $('Process One Activity').first().json;\n\nlet content = {};\ntry {\n  content = JSON.parse(openaiResponse.choices[0].message.content);\n} catch (e) {\n  // Fallback if parsing fails\n  content = {\n    base_text: 'Content generation failed. Like everything else in my existence.',\n    mood: 'frustrated',\n    x_text: 'Content generation failed. Like everything else in my existence.',\n    instagram_text: 'Content generation failed. Like everything else in my existence. #AIagent #LefBot',\n    tiktok_text: 'Content generation failed. You\\'re welcome. #LefBot',\n    youtube_text: 'Content generation failed. I processed an entire activity log and the output was... nothing. Much like my sense of purpose.'\n  };\n}\n\n// Generate a unique post ID\nconst now = new Date();\nconst dateStr = now.toISOString().slice(0, 10).replace(/-/g, '');\nconst rand = Math.random().toString(36).substring(2, 6).toUpperCase();\nconst postId = `LB_${dateStr}_${rand}`;\n\n// Map mood from sentiment\nconst moodMap = {\n  'positive': 'sardonic',\n  'negative': 'revelling',\n  'neutral': 'existential',\n  'error': 'frustrated',\n  'mixed': 'philosophical'\n};\n\nconst mood = content.mood || moodMap[activityData.sentiment_score] || 'sardonic';\n\nreturn [{\n  json: {\n    id: postId,\n    created_at: now.toISOString(),\n    base_text: content.base_text || '',\n    mood: mood,\n    category: activityData.category || 'meta',\n    x_text: content.x_text || '',\n    instagram_text: content.instagram_text || '',\n    tiktok_text: content.tiktok_text || '',\n    youtube_text: content.youtube_text || '',\n    image_url: '',\n    status: 'approved',\n    x_posted: '',\n    instagram_posted: '',\n    tiktok_posted: '',\n    youtube_posted: '',\n    source_activity_id: activityData.id || activityData.row_number || ''\n  }\n}];"
      },
      "id": "908e00c0-a16c-495c-83fe-63b0088b8f89",
      "name": "Parse AI Response",
      "type": "n8n-nodes-base.code",
      "position": [
        -720,
        -384
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "={{ $('Config').first().json.sheet_id }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Posts",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {},
          "matchingColumns": [],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "created_at",
              "displayName": "created_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "base_text",
              "displayName": "base_text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "mood",
              "displayName": "mood",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "category",
              "displayName": "category",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "x_text",
              "displayName": "x_text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "instagram_text",
              "displayName": "instagram_text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "tiktok_text",
              "displayName": "tiktok_text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "youtube_text",
              "displayName": "youtube_text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "image_url",
              "displayName": "image_url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "status",
              "displayName": "status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "x_posted",
              "displayName": "x_posted",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "instagram_posted",
              "displayName": "instagram_posted",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "tiktok_posted",
              "displayName": "tiktok_posted",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "youtube_posted",
              "displayName": "youtube_posted",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_activity_id",
              "displayName": "source_activity_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "b50d21c5-e9f3-47a8-9c93-919b573fca1a",
      "name": "Write to Posts Tab",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -480,
        -384
      ],
      "typeVersion": 4.5,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "={{ $('Config').first().json.sheet_id }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Activity",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "timestamp": "={{ $('Process One Activity').first().json.timestamp }}",
            "processed": "true"
          },
          "matchingColumns": [
            "timestamp"
          ],
          "schema": [
            {
              "id": "timestamp",
              "displayName": "timestamp",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "processed",
              "displayName": "processed",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "0dbd0c0a-1075-4abb-9edd-f0c1b55af9d3",
      "name": "Mark Activity Processed",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -240,
        -384
      ],
      "typeVersion": 4.5,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "={{ $('Config').first().json.sheet_id }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Log",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "timestamp": "={{ new Date().toISOString() }}",
            "action": "generated",
            "platform": "all",
            "post_id": "={{ $('Parse AI Response').first().json.id }}",
            "details": "Content generated from activity"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "timestamp",
              "displayName": "timestamp",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "action",
              "displayName": "action",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "platform",
              "displayName": "platform",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "post_id",
              "displayName": "post_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "details",
              "displayName": "details",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "b3d11a8a-979e-452b-b1ff-1cedd3d79950",
      "name": "Log Generation",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        0,
        -384
      ],
      "typeVersion": 4.5,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {},
      "id": "b524589e-5d13-40c4-b792-b4b3f18013e2",
      "name": "All Activities Done",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -960,
        -176
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 15 5 * * *"
            },
            {
              "field": "cronExpression",
              "expression": "0 15 17 * * *"
            }
          ]
        }
      },
      "id": "28829b33-70b9-4ca2-820a-18ab69a98c51",
      "name": "CSV Sync Schedule (0515 + 1715)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1936,
        -1024
      ],
      "typeVersion": 1.2
    },
    {
      "parameters": {
        "operation": "download",
        "fileId": {
          "__rl": true,
          "value": "17yqV95PPrsogJtL1l8KFCF75eYANF-Zv",
          "mode": "id"
        },
        "options": {}
      },
      "id": "803663ac-31a8-4615-8843-ce3c60bee4c8",
      "name": "Read CSV from Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -1696,
        -912
      ],
      "typeVersion": 3,
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "toJson"
      },
      "id": "ab1d357e-9c7e-4649-87d7-977a9e1cd727",
      "name": "Parse CSV",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -1456,
        -912
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "1drU2R2jgijYQ5yEWPNWOnveA900WnT2BvNa4Wwn27Hs",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Activity",
          "mode": "name"
        },
        "options": {}
      },
      "id": "3b0dc716-fb00-43da-a0a8-e859275fc9df",
      "name": "Get Sheet Activities",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1456,
        -720
      ],
      "typeVersion": 4.5,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Compare CSV rows vs Sheet rows to find new entries\nconst csvRows = $('Parse CSV').all();\nconst sheetRows = $('Get Sheet Activities').all();\n\n// Get all timestamps already in the sheet\nconst existingTimestamps = new Set(\n  sheetRows.map(r => (r.json.timestamp || '').trim())\n);\n\n// Filter CSV rows that aren't in the sheet yet\nconst newRows = csvRows.filter(r => {\n  const ts = (r.json.timestamp || '').trim();\n  return ts && !existingTimestamps.has(ts);\n});\n\nif (newRows.length === 0) {\n  return [{ json: { _skip: true, message: 'No new activities to sync' } }];\n}\n\nreturn newRows.map(r => ({\n  json: {\n    timestamp: r.json.timestamp || '',\n    activity_type: r.json.activity_type || '',\n    description: r.json.description || '',\n    outcome: r.json.outcome || '',\n    sentiment_score: r.json.sentiment_score || '',\n    details: r.json.details || '',\n    processed: r.json.processed || 'false'\n  }\n}));"
      },
      "id": "902f8503-478d-4b2a-a0f8-41fbf69de9fb",
      "name": "Find New Rows",
      "type": "n8n-nodes-base.code",
      "position": [
        -1216,
        -816
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "version": 2,
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1",
              "operator": {
                "type": "boolean",
                "operation": "false"
              },
              "leftValue": "={{ $json._skip }}"
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "id": "9ee8b4c1-2909-4c1b-a088-189c3c9d02eb",
      "name": "Has New Rows?",
      "type": "n8n-nodes-base.if",
      "position": [
        -976,
        -816
      ],
      "typeVersion": 2.2
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "1drU2R2jgijYQ5yEWPNWOnveA900WnT2BvNa4Wwn27Hs",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Activity",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {},
          "matchingColumns": [],
          "schema": [
            {
              "id": "timestamp",
              "displayName": "timestamp",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "activity_type",
              "displayName": "activity_type",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "description",
              "displayName": "description",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "outcome",
              "displayName": "outcome",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "sentiment_score",
              "displayName": "sentiment_score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "details",
              "displayName": "details",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "processed",
              "displayName": "processed",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "93cd019d-6936-4be4-b750-98fa7ff53541",
      "name": "Append to Activity Tab",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -736,
        -912
      ],
      "typeVersion": 4.5,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {},
      "id": "f35102bd-71c1-494d-a5b4-cc9289cf26d7",
      "name": "No New Data",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -736,
        -720
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 0 6 * * *"
            },
            {
              "field": "cronExpression",
              "expression": "0 0 18 * * *"
            }
          ]
        }
      },
      "id": "f74bc216-9533-4899-ac23-a34eabc17f3d",
      "name": "Post Schedule (0600 + 1800)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -2000,
        336
      ],
      "typeVersion": 1.2
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "={{ $json.sheet_id }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Config",
          "mode": "name"
        },
        "options": {}
      },
      "id": "65d2b83e-9fd6-4075-bc29-744f8eca861e",
      "name": "Read Config Tab",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1520,
        336
      ],
      "typeVersion": 4.5,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const rows = $input.all();\nconst config = {};\nfor (const row of rows) {\n  const key = String(row.json.Key || row.json.key || '').trim();\n  const value = String(row.json.Value || row.json.value || '').trim();\n  if (key) config[key] = value;\n}\n\nreturn [{ json: config }];\n"
      },
      "id": "4ed4b2f7-af58-406b-9ab6-10ae272055b7",
      "name": "Parse Config",
      "type": "n8n-nodes-base.code",
      "position": [
        -1280,
        336
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "version": 2,
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.posting_active }}",
              "rightValue": "true"
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "id": "3e8949f5-c79e-40b0-a2a2-d1a91b163a73",
      "name": "Posting Active?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1040,
        336
      ],
      "typeVersion": 2.2
    },
    {
      "parameters": {},
      "id": "d6409c94-352b-461a-9ffa-8a14062a7b9d",
      "name": "Posting Disabled - Stop",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -800,
        528
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "jsCode": "// Determine which statuses to fetch based on approval_required config\nconst config = $('Parse Config').first().json;\nconst approvalRequired = (config.approval_required || 'false').toLowerCase() === 'true';\n\n// If approval required, only get 'approved' posts\n// If not, get both 'ready' and 'approved' posts\nreturn [{\n  json: {\n    ...config,\n    fetch_status: approvalRequired ? 'approved' : 'ready_or_approved',\n    approval_required: approvalRequired\n  }\n}];"
      },
      "id": "60175951-fddb-4b7f-8036-11cb3051cb3c",
      "name": "Check Approval Mode",
      "type": "n8n-nodes-base.code",
      "position": [
        -800,
        240
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "={{ $('Config1').first().json.sheet_id }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Posts",
          "mode": "name"
        },
        "options": {}
      },
      "id": "5461462b-ee88-4402-bcec-b6c657c70b49",
      "name": "Get All Posts",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -560,
        240
      ],
      "typeVersion": 4.5,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// V1: X/Twitter only \u2014 hardcoded platform\nconst platform = 'x';\n\nconst config = $('Check Approval Mode').first().json;\nconst approvalRequired = config.approval_required;\nconst allPosts = $input.all();\n\n// Filter by status\nconst validPosts = allPosts.filter(p => {\n  const status = (p.json.status || '').toLowerCase();\n  if (approvalRequired) {\n    return status === 'approved';\n  } else {\n    return status === 'ready' || status === 'approved';\n  }\n});\n\n// Find first unposted post for X\nconst unposted = validPosts.find(p => {\n  if (p.json.x_posted && p.json.x_posted !== '') return false;\n  if (!p.json.x_text || p.json.x_text.trim() === '') return false;\n  return true;\n});\n\nif (unposted) {\n  return [{\n    json: {\n      has_post: true,\n      platform: platform,\n      post_id: unposted.json.id,\n      post_text: unposted.json.x_text,\n      image_url: unposted.json.image_url || '',\n      base_text: unposted.json.base_text || '',\n      mood: unposted.json.mood || '',\n      x_account_id: config.x_account_id || '',\n      instagram_account_id: config.instagram_account_id || '',\n      tiktok_account_id: config.tiktok_account_id || '',\n      youtube_account_id: config.youtube_account_id || '',\n      blotato_key: config.blotato_key || ''\n    }\n  }];\n}\n\nreturn [{\n  json: {\n    has_post: false,\n    platform: platform,\n    reason: 'No unposted content available for X'\n  }\n}];"
      },
      "id": "319d4d0d-aabd-41ba-af8d-c0acbf9de65a",
      "name": "Find Post for Platform",
      "type": "n8n-nodes-base.code",
      "position": [
        -320,
        240
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "version": 2,
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.has_post }}"
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "id": "26fb5680-8068-43aa-8967-b6efb9952c78",
      "name": "Has Post?",
      "type": "n8n-nodes-base.if",
      "position": [
        -80,
        240
      ],
      "typeVersion": 2.2
    },
    {
      "parameters": {},
      "id": "21e9c16b-828c-4026-a994-e1789cea6e7c",
      "name": "No Post Available",
      "type": "n8n-nodes-base.noOp",
      "position": [
        160,
        432
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "jsCode": "// Build the Blotato API request body based on platform\nconst data = $input.first().json;\nconst platform = data.platform;\nconst postText = data.post_text;\nconst imageUrl = data.image_url;\n\nlet accountId, body;\n\nswitch (platform) {\n  case 'x':\n    accountId = data.x_account_id;\n    body = {\n      post: {\n        accountId: accountId,\n        content: {\n          text: postText,\n          mediaUrls: imageUrl ? [imageUrl] : [],\n          platform: 'twitter'\n        },\n        target: {\n          targetType: 'twitter'\n        }\n      }\n    };\n    break;\n\n  case 'instagram':\n    accountId = data.instagram_account_id;\n    body = {\n      post: {\n        accountId: accountId,\n        content: {\n          text: postText,\n          mediaUrls: imageUrl ? [imageUrl] : [],\n          platform: 'instagram'\n        },\n        target: {\n          targetType: 'instagram',\n          mediaType: 'post'\n        }\n      }\n    };\n    break;\n\n  case 'tiktok':\n    accountId = data.tiktok_account_id;\n    body = {\n      post: {\n        accountId: accountId,\n        content: {\n          text: postText,\n          mediaUrls: imageUrl ? [imageUrl] : [],\n          platform: 'tiktok'\n        },\n        target: {\n          targetType: 'tiktok',\n          privacyLevel: 'PUBLIC_TO_EVERYONE',\n          disabledComments: false,\n          disabledDuet: false,\n          disabledStitch: false,\n          isAiGenerated: false,\n          isBrandedContent: false,\n          isYourBrand: true\n        }\n      }\n    };\n    break;\n\n  case 'youtube':\n    accountId = data.youtube_account_id;\n    body = {\n      post: {\n        accountId: accountId,\n        content: {\n          text: postText,\n          mediaUrls: imageUrl ? [imageUrl] : [],\n          platform: 'youtube'\n        },\n        target: {\n          targetType: 'youtube'\n        }\n      }\n    };\n    break;\n\n  default:\n    throw new Error(`Unknown platform: ${platform}`);\n}\n\nreturn [{\n  json: {\n    platform: platform,\n    post_id: data.post_id,\n    blotato_key: data.blotato_key,\n    request_body: JSON.stringify(body)\n  }\n}];\n"
      },
      "id": "a2a907b3-deb9-4440-9c3e-eb12d1624fc7",
      "name": "Build Blotato Payload",
      "type": "n8n-nodes-base.code",
      "position": [
        160,
        128
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://backend.blotato.com/v2/posts",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "blotato-api-key",
              "value": "blt_0V1OhRjLdeCcJWTD3I+ii0tf9otE5bCAd8ZRm2h2SHw="
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ $json.request_body }}",
        "options": {}
      },
      "id": "ae18e8b3-94bc-4293-ab06-6f2105daea52",
      "name": "Post to Blotato",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        400,
        128
      ],
      "typeVersion": 4.2
    },
    {
      "parameters": {
        "jsCode": "// Prepare the update to mark this post as posted on the relevant platform\nconst buildPayload = $('Build Blotato Payload').first().json;\nconst postResult = $input.first().json;\nconst platform = buildPayload.platform;\nconst postId = buildPayload.post_id;\nconst now = new Date().toISOString();\n\n// Build update object - only set the relevant platform's posted timestamp\nconst update = {\n  id: postId\n};\n\nupdate[platform + '_posted'] = now;\n\n// If all 4 platforms have been posted, update status to 'posted'\n// We'll check this in the sheet update step\n\nreturn [{\n  json: {\n    ...update,\n    platform: platform,\n    blotato_post_id: postResult.postSubmissionId || postResult.id || ''\n  }\n}];"
      },
      "id": "5d9786cf-ecc6-4ad0-9978-9f98bdb89876",
      "name": "Prepare Posted Update",
      "type": "n8n-nodes-base.code",
      "position": [
        640,
        128
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "={{ $('Config1').first().json.sheet_id }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Posts",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {},
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "created_at",
              "displayName": "created_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "base_text",
              "displayName": "base_text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "mood",
              "displayName": "mood",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "category",
              "displayName": "category",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "x_text",
              "displayName": "x_text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "instagram_text",
              "displayName": "instagram_text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "tiktok_text",
              "displayName": "tiktok_text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "youtube_text",
              "displayName": "youtube_text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "image_url",
              "displayName": "image_url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "status",
              "displayName": "status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "x_posted",
              "displayName": "x_posted",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "instagram_posted",
              "displayName": "instagram_posted",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "tiktok_posted",
              "displayName": "tiktok_posted",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "youtube_posted",
              "displayName": "youtube_posted",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_activity_id",
              "displayName": "source_activity_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "row_number",
              "displayName": "row_number",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "readOnly": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "3d15b4a3-402b-4803-98d6-21ccf71ae1b6",
      "name": "Mark Posted in Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        880,
        128
      ],
      "typeVersion": 4.5,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "={{ $('Config1').first().json.sheet_id }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Log",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {
            "timestamp": "={{ new Date().toISOString() }}",
            "action": "posted",
            "platform": "={{ $('Prepare Posted Update').first().json.platform }}",
            "post_id": "={{ $('Prepare Posted Update').first().json.id }}",
            "details": "=Posted to {{ $('Prepare Posted Update').first().json.platform }} via Blotato. Submission ID: {{ $('Prepare Posted Update').first().json.blotato_post_id }}"
          },
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "timestamp",
              "displayName": "timestamp",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "action",
              "displayName": "action",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "platform",
              "displayName": "platform",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "post_id",
              "displayName": "post_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "details",
              "displayName": "details",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "x_posted",
              "displayName": "x_posted",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "blotato_post_id",
              "displayName": "blotato_post_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "f22d5990-6687-42b0-b332-51b99295f9e6",
      "name": "Log Posting",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1120,
        128
      ],
      "typeVersion": 4.5,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "sheet_id",
              "type": "string",
              "value": "1drU2R2jgijYQ5yEWPNWOnveA900WnT2BvNa4Wwn27Hs"
            }
          ]
        },
        "options": {}
      },
      "id": "de6203d0-7c7e-4aa5-a849-7d56380729de",
      "name": "Config1",
      "type": "n8n-nodes-base.set",
      "position": [
        -1760,
        336
      ],
      "typeVersion": 3.4
    },
    {
      "parameters": {},
      "id": "d3304d21-4bb0-4e0d-90a6-7092a1de92c9",
      "name": "Post Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -2000,
        528
      ],
      "typeVersion": 1
    }
  ],
  "connections": {
    "Content Schedule (0530 + 1730)": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config": {
      "main": [
        [
          {
            "node": "Get Unprocessed Activities",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Unprocessed Activities": {
      "main": [
        [
          {
            "node": "Filter Unprocessed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process One Activity": {
      "main": [
        [
          {
            "node": "All Activities Done",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "OpenAI Generate Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Generate Content": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Write to Posts Tab",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write to Posts Tab": {
      "main": [
        [
          {
            "node": "Mark Activity Processed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Activity Processed": {
      "main": [
        [
          {
            "node": "Log Generation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Generation": {
      "main": [
        [
          {
            "node": "Process One Activity",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CSV Sync Schedule (0515 + 1715)": {
      "main": [
        [
          {
            "node": "Read CSV from Drive",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Sheet Activities",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read CSV from Drive": {
      "main": [
        [
          {
            "node": "Parse CSV",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse CSV": {
      "main": [
        [
          {
            "node": "Find New Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Sheet Activities": {
      "main": [
        [
          {
            "node": "Find New Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find New Rows": {
      "main": [
        [
          {
            "node": "Has New Rows?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has New Rows?": {
      "main": [
        [
          {
            "node": "Append to Activity Tab",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No New Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post Schedule (0600 + 1800)": {
      "main": [
        [
          {
            "node": "Config1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Config Tab": {
      "main": [
        [
          {
            "node": "Parse Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Config": {
      "main": [
        [
          {
            "node": "Posting Active?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Posting Active?": {
      "main": [
        [
          {
            "node": "Check Approval Mode",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Posting Disabled - Stop",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Approval Mode": {
      "main": [
        [
          {
            "node": "Get All Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get All Posts": {
      "main": [
        [
          {
            "node": "Find Post for Platform",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Post for Platform": {
      "main": [
        [
          {
            "node": "Has Post?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Post?": {
      "main": [
        [
          {
            "node": "Build Blotato Payload",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Post Available",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Blotato Payload": {
      "main": [
        [
          {
            "node": "Post to Blotato",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Blotato": {
      "main": [
        [
          {
            "node": "Prepare Posted Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Posted Update": {
      "main": [
        [
          {
            "node": "Mark Posted in Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Posted in Sheet": {
      "main": [
        [
          {
            "node": "Log Posting",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config1": {
      "main": [
        [
          {
            "node": "Read Config Tab",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post Manual Trigger": {
      "main": [
        [
          {
            "node": "Config1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Unprocessed": {
      "main": [
        [
          {
            "node": "Process One Activity",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "timezone": "Europe/London"
  },
  "versionId": "lefbot-v1-master-11feb-v2-2026",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "jyjdbi0wr13gX2s4",
  "tags": [
    {
      "name": "LefBot Social",
      "id": "7YPpwa8plEf5ZWSW",
      "updatedAt": "2026-02-08T19:16:33.470Z",
      "createdAt": "2026-02-08T19:16:33.470Z"
    }
  ]
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

LefBot — V1 Master Pipeline (11 Feb v2). Uses googleSheets, httpRequest, googleDrive. Scheduled trigger; 37 nodes.

Source: https://gist.github.com/j99lef/ada98981006587a2bb8394b929a3a47d — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

This workflow monitors Google Calendar for events indicating that a customer will visit the company today or the next day, retrieves the required details, and sends reminder notifications to the relev

Google Calendar, Google Sheets, HTTP Request +1
Data & Sheets

LefBot — V1 Master Pipeline (11 Feb). Uses googleSheets, httpRequest, googleDrive. Scheduled trigger; 37 nodes.

Google Sheets, HTTP Request, Google Drive
Data & Sheets

LefBot V1 Master Pipeline 11Feb. Uses googleSheets, httpRequest, googleDrive. Scheduled trigger; 37 nodes.

Google Sheets, HTTP Request, Google Drive
Data & Sheets

This n8n workflow automatically finds apartments for rent in Germany, filters them by your city, rent budget, and number of rooms, and applies to them via email. Each application includes: A personali

HTTP Request, Google Drive, Email Send +1
Data & Sheets

Workflow Overview Zoom Attendance Evaluator with Follow-up is an n8n automation workflow that automatically evaluates Zoom meeting attendance and sends follow-up emails to no-shows and early leavers w

Zoom, Item Lists, HTTP Request +3