AutomationFlowsAI & RAG › Convert Telegram Messages to Professional Linkedin Posts with Gemini AI &…

Convert Telegram Messages to Professional Linkedin Posts with Gemini AI &…

Original n8n title: Convert Telegram Messages to Professional Linkedin Posts with Gemini AI & Approval Workflow

BySateesh @sateesh on n8n.io

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Event trigger★★★★★ complexityAI-powered54 nodesTelegram TriggerGoogle SheetsTelegramChain Llm@Mendable/N8N Nodes FirecrawlLinkedIn@Brave/N8N Nodes Brave SearchOutput Parser Structured
AI & RAG Trigger: Event Nodes: 54 Complexity: ★★★★★ AI nodes: yes Added:
Convert Telegram Messages to Professional Linkedin Posts with Gemini AI &… — n8n workflow card showing Telegram Trigger, Google Sheets, Telegram integration

This workflow corresponds to n8n.io template #7466 — we link there as the canonical source.

This workflow follows the Chainllm → 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
{
  "id": "LWCrr5lorPtQRUfI",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Linkedin Automation",
  "tags": [
    {
      "id": "HmvMKAccqyXZIUSY",
      "name": "LinkedIn Automation",
      "createdAt": "2025-08-14T08:42:36.216Z",
      "updatedAt": "2025-08-14T08:42:36.216Z"
    },
    {
      "id": "R0SHjnqB9YfJKAVu",
      "name": "Gemini",
      "createdAt": "2025-08-14T10:26:53.631Z",
      "updatedAt": "2025-08-14T10:26:53.631Z"
    },
    {
      "id": "l1eZzX8QnqsKk2gm",
      "name": "Automation",
      "createdAt": "2025-08-14T10:26:53.610Z",
      "updatedAt": "2025-08-14T10:26:53.610Z"
    },
    {
      "id": "n3OO3hKjfreBd7Hk",
      "name": "LinkedIn",
      "createdAt": "2025-08-14T10:26:53.668Z",
      "updatedAt": "2025-08-14T10:26:53.668Z"
    }
  ],
  "nodes": [
    {
      "id": "96c77c8e-fc61-4d53-9bd6-568317aee08c",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        -2544,
        336
      ],
      "parameters": {
        "updates": [
          "message",
          "callback_query"
        ],
        "additionalFields": {
          "download": true,
          "imageSize": "extraLarge"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a34caf37-c9b3-47e8-894a-5259323f70cc",
      "name": "User Validation",
      "type": "n8n-nodes-base.code",
      "position": [
        -1872,
        80
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Fetch authorized users configuration\nconst authorizedUsers = {\n  telegram_ids: $json.telegram_ids,\n  usernames: $json.usernames\n};\n\nconst userId = $('Switch').item.json.message.from.id.toString();\nconst username = $('Switch').item.json.message.from.username;\n\n// Check if user is authorized (by id or username)\nconst isAuthorized =\n  authorizedUsers.telegram_ids.includes(userId) ||\n  authorizedUsers.usernames.includes(username);\n\n// Return user info and original message\nreturn {\n  json: {\n    user_id: userId,\n    username: username,\n    message_text: $('Switch').item.json.message.text,\n    chat_id: $('Switch').item.json.message.chat.id,\n    message_id: $('Switch').item.json.message.message_id,\n    timestamp: new Date().toISOString(),\n    authorized: isAuthorized\n  }\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "a7a0856a-344f-48c8-9308-5fb9dc06eea4",
      "name": "Generate Post ID",
      "type": "n8n-nodes-base.code",
      "position": [
        -1424,
        -32
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Generate unique post ID\nconst now = new Date();\nconst dateStr = now.toISOString().replace(/[-:T]/g, '').slice(0, 14);\nconst random = Math.floor(Math.random() * 1000).toString().padStart(3, '0');\nconst postId = `${dateStr}_${random}`;\n\nreturn {\n  json: {\n    ...$input.item.json,\n    post_id: postId,\n    created_at: now.toISOString()\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "03be5ca8-54bb-4597-af45-0d13b66be14c",
      "name": "Log Initial Request",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1136,
        -32
      ],
      "parameters": {
        "columns": {
          "value": {
            "post_id": "={{ $json.post_id }}",
            "user_id": "={{ $json.user_id }}",
            "timestamp": "={{ $json.timestamp }}",
            "user_name": "={{ $json.username }}",
            "original_message": "={{ $json.message_text }}"
          },
          "schema": [
            {
              "id": "post_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "post_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "user_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "user_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "user_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "user_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "input_type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "input_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "original_message",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "original_message",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "extracted_urls",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "extracted_urls",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "identified_topics",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "identified_topics",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "search_queries",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "search_queries",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "search_results_summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "search_results_summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "scraped_content_summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "scraped_content_summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "content_sources",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "content_sources",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "initial_generated_post",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "initial_generated_post",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "final_approved_post",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "final_approved_post",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hashtags_used",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "hashtags_used",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "character_count",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "character_count",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "has_media",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "has_media",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "media_urls",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "media_urls",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "approval_status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "approval_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "rejection_reason",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "rejection_reason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "edit_iterations",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "edit_iterations",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "time_to_approval",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "time_to_approval",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "posted_datetime",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "posted_datetime",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "scheduled_time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "scheduled_time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "linkedin_post_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "linkedin_post_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "post_type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "post_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "impressions_1h",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "impressions_1h",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "impressions_24h",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "impressions_24h",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "impressions_7d",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "impressions_7d",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "impressions_30d",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "impressions_30d",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "reactions_total",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "reactions_total",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "likes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "likes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "celebrates",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "celebrates",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "loves",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "loves",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "comments_total",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "comments_total",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "shares_total",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "shares_total",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "clicks_total",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "clicks_total",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "engagement_rate",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "engagement_rate",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "viral_score",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "viral_score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "follower_growth",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "follower_growth",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "performance_tier",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "performance_tier",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_metrics_update",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_metrics_update",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "engagement_rate",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "engagement_rate",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "approval_status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "approval_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "post_id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1RvHyWEvEZR5etmq1KfzTOkSIXY5tUT5TLVgDSUfAr5c/edit#gid=0",
          "cachedResultName": "Posts_Master"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1RvHyWEvEZR5etmq1KfzTOkSIXY5tUT5TLVgDSUfAr5c",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1RvHyWEvEZR5etmq1KfzTOkSIXY5tUT5TLVgDSUfAr5c/edit?usp=drivesdk",
          "cachedResultName": "LinekedIn Posts"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "notesInFlow": false,
      "typeVersion": 4,
      "alwaysOutputData": true
    },
    {
      "id": "2dbe1200-b0fb-4cf4-9ea5-214e76c48f7f",
      "name": "Parse Classification",
      "type": "n8n-nodes-base.code",
      "position": [
        -400,
        -32
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Enhanced Parse Classification for better integration\nconst inputJson = $input.item.json;\n\n// Extract classification results\nconst classificationResult = {\n  input_type: $json.output.input_type || 'Topic',\n  urls: $json.output.urls || [],\n  topics: $json.output.topics || [],\n  content: $json.output.content || '',\n  processing_instructions: $json.output.processing_instructions || ''\n};\n\n// Preserve original request data for tracking\nconst originalRequestData = {\n  post_id: $('Log Initial Request').item.json.post_id,\n  chat_id:$('Generate Post ID').item.json.chat_id,\n  message_id:$('Generate Post ID').item.json.message_id,\n  timestamp: inputJson.timestamp || new Date().toISOString(),\n  user_id: $('Log Initial Request').item.json.user_id || '',\n  username: $('Log Initial Request').item.json.user_name || '',\n  original_message: $('Log Initial Request').item.json.original_message || inputJson.message_text || ''\n};\n\n// Add processing metadata\nconst processingMetadata = {\n  classification_timestamp: new Date().toISOString(),\n  has_urls: classificationResult.urls.length > 0,\n  has_topics: classificationResult.topics.length > 0,\n  has_content: classificationResult.content.length > 0,\n  url_count: classificationResult.urls.length,\n  topic_count: classificationResult.topics.length,\n  content_length: classificationResult.content.length,\n  requires_scraping: classificationResult.urls.length > 0,\n  requires_search: classificationResult.topics.length > 0,\n  processing_complexity: determineComplexity(classificationResult)\n};\n\n// Determine processing complexity\nfunction determineComplexity(result) {\n  const factors = [\n    result.urls.length > 0,\n    result.topics.length > 0,\n    result.content.length > 0\n  ].filter(Boolean).length;\n  \n  if (factors === 0) return 'simple';\n  if (factors === 1) return 'moderate';\n  if (factors >= 2) return 'complex';\n}\n\n// Return comprehensive data for downstream processing\nreturn {\n  json: {\n    ...originalRequestData,\n    ...classificationResult,\n    ...processingMetadata,\n    \n    // Add routing hints for Content Router\n    route_to_scraper: classificationResult.urls.length > 0,\n    route_to_search: classificationResult.topics.length > 0,\n    route_to_direct: classificationResult.urls.length === 0 && \n                     classificationResult.topics.length === 0,\n    \n    // Prepare data for Google Sheets tracking\n    extracted_urls: classificationResult.urls.join(', '),\n    identified_topics: classificationResult.topics.join(', '),\n    input_classification: classificationResult.input_type,\n    processing_stage: 'classified'\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "d45ddc23-679a-4cd6-82e3-fe5bbe35107f",
      "name": "Content Router",
      "type": "n8n-nodes-base.if",
      "position": [
        -176,
        -224
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "url-only",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.input_type }}",
              "rightValue": "URL"
            },
            {
              "id": "topic-only",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.input_type }}",
              "rightValue": "Topic"
            },
            {
              "id": "mixed",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.input_type }}",
              "rightValue": "URL+Topic"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "70b4a682-8827-4e2b-8f01-af887ab7ec41",
      "name": "Extract URLs for Processing",
      "type": "n8n-nodes-base.code",
      "position": [
        272,
        -464
      ],
      "parameters": {
        "jsCode": "const urls = $input.item.json.output?.urls || $input.item.json.urls || [];\n\nif (urls.length === 0) {\n  // No URLs to process, pass through original data\n  return {\n    json: {\n      ...$input.item.json,\n      urls_to_process: [],\n      total_urls: 0,\n      processing_stage: 'no_urls'\n    }\n  };\n}\n\n// Create individual items for each URL to be processed\nconst urlItems = urls.map((url, index) => ({\n  json: {\n    ...$input.item.json,\n    ...$input.item.json.output,\n    current_url: url,\n    url_index: index,\n    total_urls: urls.length,\n    processing_stage: 'url_extraction'\n  }\n}));\n// Return array of items for processing\nreturn urlItems;"
      },
      "notesInFlow": false,
      "typeVersion": 2,
      "alwaysOutputData": false
    },
    {
      "id": "2c8c8e1c-fb44-47a8-921f-2676f773df7a",
      "name": "Loop Over URLs",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        496,
        -464
      ],
      "parameters": {
        "options": {},
        "batchSize": "={{ $json.total_urls }}"
      },
      "typeVersion": 3,
      "alwaysOutputData": false
    },
    {
      "id": "d8ef03dd-2db3-4adf-993f-de30fcb090ab",
      "name": "Process Scraped Content",
      "type": "n8n-nodes-base.code",
      "position": [
        720,
        -336
      ],
      "parameters": {
        "jsCode": "// Get all inputs from the loop\nconst allInputs = $input.all();\nconsole.log(\"Processing all loop outputs:\", allInputs.length, \"items\");\n\nlet mergedContent = '';\nlet allSourceUrls = [];\nlet allMetadataUrls = [];\nlet overallSuccess = true;\n\n// Process each input from the loop\nfor (const inputItem of allInputs) {\n  const scrapedData = inputItem.json;\n  let processedContent = '';\n  let scrapingSuccess = false;\n  let metadataUrl = '';\n  \n  try {\n    // Handle Firecrawl response structure\n    if (scrapedData.data && scrapedData.data.markdown) {\n      processedContent = scrapedData.data.markdown;\n      \n      // Extract URL from metadata if available\n      if (scrapedData.data.metadata && scrapedData.data.metadata.ogUrl) {\n        metadataUrl = scrapedData.data.metadata.ogUrl;\n        allMetadataUrls.push(metadataUrl);\n      }\n      \n      scrapingSuccess = true;\n    }\n    // Handle alternative response structure\n    else if (scrapedData.markdown) {\n      processedContent = scrapedData.markdown;\n      \n      // Extract URL from metadata if available\n      if (scrapedData.metadata && scrapedData.metadata.ogUrl) {\n        metadataUrl = scrapedData.metadata.ogUrl;\n        allMetadataUrls.push(metadataUrl);\n      }\n      \n      scrapingSuccess = true;\n    }\n    // Handle plain text content\n    else if (scrapedData.content) {\n      processedContent = scrapedData.content;\n      \n      // Extract URL from metadata if available\n      if (scrapedData.metadata && scrapedData.metadata.ogUrl) {\n        metadataUrl = scrapedData.metadata.ogUrl;\n        allMetadataUrls.push(metadataUrl);\n      }\n      \n      scrapingSuccess = true;\n    }\n    else {\n      throw new Error('No content found in Firecrawl response');\n    }\n  } catch (error) {\n    processedContent = `Error scraping ${scrapedData.current_url}: ${error.message}`;\n    scrapingSuccess = false;\n  }\n  \n  // Use metadata URL if available, otherwise fall back to current_url\n  const sourceUrl = metadataUrl || scrapedData.current_url;\n  \n  // Add to merged content with source separator\n  if (sourceUrl) {\n    mergedContent += `\\n\\n--- Source: ${sourceUrl} ---\\n\\n`;\n    allSourceUrls.push(sourceUrl);\n  }\n  mergedContent += processedContent;\n  \n  // Update overall success (false if any scraping failed)\n  if (!scrapingSuccess) {\n    overallSuccess = false;\n  }\n}\n\n// Remove duplicate URLs and create final source URL list\nconst uniqueSourceUrls = [...new Set(allSourceUrls)];\nconst uniqueMetadataUrls = [...new Set(allMetadataUrls)];\n\nconsole.log(\"Extracted metadata URLs:\", uniqueMetadataUrls);\nconsole.log(\"All source URLs:\", uniqueSourceUrls);\n\n// Return only the required fields\nreturn {\n  json: {\n    merged_content: mergedContent.trim(),\n    scraping_success: overallSuccess,\n    source_url: uniqueSourceUrls.join(', '),\n    metadata_urls: uniqueMetadataUrls.join(', '), // Additional field with metadata URLs\n    processing_stage: 'content_merged'\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "8d16150a-502b-4c6c-a16c-b36efd85e7ed",
      "name": "Merge Content Sources",
      "type": "n8n-nodes-base.code",
      "position": [
        1168,
        -96
      ],
      "parameters": {
        "jsCode": "// Optimized for direct JSON access without looping\nconst allInputs = $input.all();\n\nconsole.log(\"Total inputs received:\", allInputs.length);\n\n// Initialize the complete output structure\nlet processedData = {\n  // Original input data\n  post_id: '',\n  user_id: '',\n  username: '',\n  chat_id: '',\n  message_id:'',\n  message_text: '',\n  input_type: '',\n  urls: [],\n  topics: [],\n  content: '',\n  processing_instructions: '',\n  \n  // Scraped content from URLs\n  scraped_content: '',\n  scraped_urls: [],\n  scraped_summary: '',\n  \n  // Brave search results\n  brave_search_results: '',\n  brave_search_performed: false,\n  brave_search_query: '',\n  \n  // Processing metadata\n  content_sources: [],\n  total_scraped_urls: 0,\n  successful_scrapes: 0,\n  failed_scrapes: 0,\n  processing_timestamp: new Date().toISOString(),\n  routes_taken: [],\n  \n  // Final merged content for LLM\n  merged_content_for_llm: ''\n};\n\n// Direct access to specific inputs based on expected structure\nconsole.log(\"Processing inputs with direct JSON access...\");\nconsole.log(\"Input structures:\", allInputs.map((input, index) => ({\n  index,\n  keys: Object.keys(input.json || {}).slice(0, 10),\n  hasArray: Array.isArray(input.json),\n  jsonType: typeof input.json\n})));\n\n// Look for Parse Classification data in any input\nconst parseInput = allInputs.find(input => {\n  if (!input.json) return false;\n  \n  // Handle array structure\n  if (Array.isArray(input.json)) {\n    return input.json.some(item => \n      item.post_id !== undefined || \n      item.input_type !== undefined || \n      item.processing_stage === 'classified'\n    );\n  }\n  \n  // Handle direct object\n  return input.json.post_id !== undefined || \n         input.json.input_type !== undefined || \n         input.json.processing_stage === 'classified';\n});\n\nif (parseInput) {\n  console.log(\"Found Parse Classification data\");\n  \n  let parseData;\n  if (Array.isArray(parseInput.json)) {\n    // Find the classification data in the array\n    parseData = parseInput.json.find(item => \n      item.post_id !== undefined || \n      item.input_type !== undefined || \n      item.processing_stage === 'classified'\n    );\n  } else {\n    parseData = parseInput.json;\n  }\n  \n  if (parseData) {\n    console.log(\"Processing Parse Classification data:\", Object.keys(parseData));\n    \n    processedData.post_id = parseData.post_id || '';\n    processedData.chat_id = parseData.chat_id || '';\n    processedData.message_id = parseData.message_id || '';\n    processedData.user_id = parseData.user_id || '';\n    processedData.username = parseData.username || '';\n    processedData.chat_id = parseData.chat_id || '';\n    processedData.message_text = parseData.original_message || parseData.message_text || '';\n    processedData.input_type = parseData.input_type || '';\n    \n    // Handle URLs - could be array or string\n    if (parseData.urls && Array.isArray(parseData.urls)) {\n      processedData.urls = parseData.urls;\n    } else if (parseData.extracted_urls) {\n      processedData.urls = Array.isArray(parseData.extracted_urls) ? \n        parseData.extracted_urls : [parseData.extracted_urls];\n    } else {\n      processedData.urls = [];\n    }\n    \n    // Handle topics - could be array or string  \n    if (parseData.topics && Array.isArray(parseData.topics)) {\n      processedData.topics = parseData.topics;\n    } else if (parseData.identified_topics) {\n      processedData.topics = Array.isArray(parseData.identified_topics) ? \n        parseData.identified_topics : [parseData.identified_topics];\n    } else {\n      processedData.topics = [];\n    }\n    \n    processedData.content = parseData.content || '';\n    processedData.processing_instructions = parseData.processing_instructions || '';\n    processedData.routes_taken.push('Parse Classification');\n  }\n}\n\n// Input 2: Scraped Content (look for merged_content or scraped_content)\nconst scrapedInput = allInputs.find(input => {\n  if (!input.json) return false;\n  \n  // Handle array structure\n  if (Array.isArray(input.json)) {\n    return input.json.some(item => \n      item.merged_content || \n      item.scraped_content || \n      item.processing_stage === 'content_merged'\n    );\n  }\n  \n  // Handle direct object\n  return input.json.merged_content || \n         input.json.scraped_content || \n         input.json.processing_stage === 'content_merged';\n});\n\nif (scrapedInput) {\n  console.log(\"Found Scraped Content\");\n  \n  let scrapedData;\n  if (Array.isArray(scrapedInput.json)) {\n    // Find the scraped data in the array\n    scrapedData = scrapedInput.json.find(item => \n      item.merged_content || item.scraped_content || item.processing_stage === 'content_merged'\n    ) || scrapedInput.json[0]; // fallback to first item if structure is different\n  } else {\n    scrapedData = scrapedInput.json;\n  }\n  \n  if (scrapedData) {\n    console.log(\"Processing Scraped Content:\", Object.keys(scrapedData).slice(0, 10));\n    \n    // Use either scraped_content or merged_content\n    processedData.scraped_content = scrapedData.scraped_content || scrapedData.merged_content || '';\n    \n    // Handle URLs from various sources\n    if (scrapedData.scraped_urls && Array.isArray(scrapedData.scraped_urls)) {\n      processedData.scraped_urls = scrapedData.scraped_urls;\n    } else if (scrapedData.source_url) {\n      processedData.scraped_urls = scrapedData.source_url.split(', ').filter(url => url.trim());\n    } else if (scrapedData.metadata_urls) {\n      processedData.scraped_urls = Array.isArray(scrapedData.metadata_urls) ? \n        scrapedData.metadata_urls : [scrapedData.metadata_urls];\n    } else {\n      processedData.scraped_urls = [];\n    }\n    \n    processedData.successful_scrapes = scrapedData.scraping_success !== false ? processedData.scraped_urls.length : 0;\n    processedData.total_scraped_urls = processedData.scraped_urls.length;\n    processedData.scraped_summary = `Successfully scraped ${processedData.successful_scrapes} URLs`;\n    \n    if (scrapedData.scraping_success !== false && processedData.scraped_urls.length > 0) {\n      processedData.content_sources.push(`Web Scraping (${processedData.scraped_urls.length} URLs)`);\n    } else {\n      processedData.content_sources.push('Web Scraping (Failed)');\n    }\n    processedData.routes_taken.push('URL Processing');\n  }\n}\n\n// Input 3: Brave Search Results (look for web.results)\nconst searchInput = allInputs.find(input => {\n  if (!input.json) return false;\n  \n  // Handle array structure\n  if (Array.isArray(input.json)) {\n    return input.json.some(item => item.web && item.web.results);\n  }\n  \n  // Handle direct object\n  return input.json.web && input.json.web.results;\n});\n\nif (searchInput) {\n  console.log(\"Found Brave Search Results\");\n  \n  let searchData;\n  if (Array.isArray(searchInput.json)) {\n    searchData = searchInput.json.find(item => item.web && item.web.results);\n  } else {\n    searchData = searchInput.json;\n  }\n  \n  if (searchData) {\n    console.log(\"Processing Brave Search Results\");\n    \n    processedData.brave_search_performed = true;\n    processedData.brave_search_query = searchData.query || processedData.topics.join(' ');\n    \n    if (searchData.web.results && searchData.web.results.length > 0) {\n      const formattedResults = searchData.web.results.slice(0, 5).map((result, index) => {\n        return [\n          `**Result ${index + 1}:**`,\n          `Title: ${result.title}`,\n          `URL: ${result.url}`,\n          `Description: ${result.description || 'No description available'}`,\n          result.age ? `Published: ${result.age}` : ''\n        ].filter(line => line).join('\\n');\n      }).join('\\n\\n');\n      \n      processedData.brave_search_results = formattedResults;\n      processedData.content_sources.push(`Brave Search (${searchData.web.results.length} results)`);\n    }\n    processedData.routes_taken.push('Topic Search');\n  }\n}\n\n// Input 4: Content Router False route (look for bypass_reason or similar markers)\nconst routerInput = allInputs.find(input => {\n  if (!input.json) return false;\n  \n  // Handle array structure\n  if (Array.isArray(input.json)) {\n    return input.json.some(item => \n      item.bypass_reason || \n      item.route_taken === 'false' || \n      item.processing_stage === 'bypassed'\n    );\n  }\n  \n  // Handle direct object\n  return input.json.bypass_reason || \n         input.json.route_taken === 'false' ||\n         input.json.processing_stage === 'bypassed';\n});\n\nif (routerInput) {\n  console.log(\"Found Content Router False route\");\n  \n  let routerData;\n  if (Array.isArray(routerInput.json)) {\n    routerData = routerInput.json.find(item => \n      item.bypass_reason || item.route_taken === 'false' || item.processing_stage === 'bypassed'\n    );\n  } else {\n    routerData = routerInput.json;\n  }\n  \n  if (routerData) {\n    processedData.routes_taken.push('Content Router (False)');\n    if (routerData.bypass_reason) {\n      processedData.bypass_reason = routerData.bypass_reason;\n    }\n  }\n}\n\n// Build the final merged content for LLM\nlet llmContent = [];\nlet sectionCount = 0;\n\n// Add processing instructions if available\nif (processedData.processing_instructions) {\n  llmContent.push(`## PROCESSING INSTRUCTIONS\\n${processedData.processing_instructions}`);\n  sectionCount++;\n}\n\n// Add original content if provided\nif (processedData.content) {\n  llmContent.push(`## ORIGINAL CONTENT TO ENHANCE\\n${processedData.content}`);\n  sectionCount++;\n}\n\n// Add topics if provided\nif (processedData.topics && processedData.topics.length > 0) {\n  const topicsText = Array.isArray(processedData.topics) ? \n    processedData.topics.filter(topic => topic).join('\\n- ') : \n    processedData.topics;\n  llmContent.push(`## TOPICS TO COVER\\n- ${topicsText}`);\n  sectionCount++;\n}\n\n// Add scraped content with source attribution\nif (processedData.scraped_content) {\n  llmContent.push(`## WEB CONTENT (Scraped from URLs)\\n${processedData.scraped_content}`);\n  sectionCount++;\n}\n\n// Add Brave search results\nif (processedData.brave_search_results) {\n  llmContent.push(`## SEARCH RESULTS (Latest Information)\\n${processedData.brave_search_results}`);\n  sectionCount++;\n}\n\n// Create context summary for LLM\nconst contextSummary = [\n  `Input Type: ${processedData.input_type || 'Not specified'}`,\n  `Routes Processed: ${processedData.routes_taken.join(', ')}`,\n  `Content Sources: ${processedData.content_sources.join(', ') || 'None'}`,\n  `Sections Available: ${sectionCount}`\n].join('\\n');\n\n// Add context summary at the beginning\nif (sectionCount > 0) {\n  processedData.merged_content_for_llm = [\n    `## CONTEXT SUMMARY\\n${contextSummary}`,\n    ...llmContent\n  ].join('\\n\\n---\\n\\n');\n} else {\n  // Fallback content if no data was gathered\n  if (processedData.topics && processedData.topics.length > 0) {\n    const topicsText = Array.isArray(processedData.topics) ? \n      processedData.topics.filter(topic => topic).join('\\n- ') : \n      processedData.topics;\n    processedData.merged_content_for_llm = `Please generate content about the following topics:\\n- ${topicsText}`;\n    processedData.content_sources.push('Topic-based Generation Request');\n  } else if (processedData.content) {\n    processedData.merged_content_for_llm = `Please enhance and format the following content:\\n\\n${processedData.content}`;\n    processedData.content_sources.push('Content Enhancement Request');\n  } else {\n    processedData.merged_content_for_llm = 'Please generate relevant LinkedIn content based on current trends.';\n    processedData.content_sources.push('General Generation Request');\n  }\n}\n\n// Add processing statistics\nprocessedData.scraping_success_rate = processedData.total_scraped_urls > 0 ? \n  `${((processedData.successful_scrapes / processedData.total_scraped_urls) * 100).toFixed(1)}%` : 'N/A';\n\n// Log final summary\nconsole.log(\"=== PROCESSING COMPLETE ===\");\nconsole.log(\"Routes taken:\", processedData.routes_taken);\nconsole.log(\"Content sources used:\", processedData.content_sources);\nconsole.log(\"Total content length:\", processedData.merged_content_for_llm.length, \"characters\");\nconsole.log(\"Sections included:\", sectionCount);\nconsole.log(\"Processing summary:\", {\n  totalInputs: allInputs.length,\n  routesTaken: processedData.routes_taken.length,\n  contentSources: processedData.content_sources.length,\n  hasScrapedContent: !!processedData.scraped_content,\n  hasSearchResults: !!processedData.brave_search_results,\n  finalContentLength: processedData.merged_content_for_llm.length\n});\n\nreturn { json: processedData };"
      },
      "executeOnce": false,
      "typeVersion": 2,
      "alwaysOutputData": false
    },
    {
      "id": "79324d69-6cc4-4f3f-a398-c5a8e7478d93",
      "name": "Format Preview",
      "type": "n8n-nodes-base.code",
      "position": [
        1744,
        -96
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Parse Gemini response and format preview\nlet generatedPost;\ntry {\n  const responseText = $input.item.json.text;\n  const jsonMatch = responseText.match(/\\{[\\s\\S]*\\}/); // Find JSON in response\n  \n  if (jsonMatch) {\n    generatedPost = JSON.parse(jsonMatch[0]);\n  } else {\n    // Fallback if JSON parsing fails\n    generatedPost = {\n      post_content: responseText,\n      hashtags: ['#LinkedIn', '#Professional'],\n      character_count: responseText.length,\n      hook: responseText.substring(0, 50),\n      cta: 'What do you think?',\n      key_points: ['Generated content']\n    };\n  }\n} catch (error) {\n  // Ultimate fallback\n  generatedPost = {\n    post_content: $input.item.json.text || 'Content generation failed',\n    hashtags: ['#LinkedIn'],\n    character_count: ($input.item.json.text || '').length,\n    hook: 'Content preview',\n    cta: 'Please try again',\n    key_points: ['Error in generation']\n  };\n}\n\n// Create preview text\nconst preview = `\ud83d\udcdd **LinkedIn Post Preview**\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n${generatedPost.post_content}\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\ud83d\udcca **Post Analytics:**\n\u2022 Characters: ${generatedPost.character_count}/2800\n\u2022 Hashtags: ${generatedPost.hashtags.join(', ')}\n\u2022 Hook: \"${generatedPost.hook.substring(0, 50)}...\"\n\n\ud83c\udfaf **Key Points:**\n${generatedPost.key_points.map(p => '\u2022 ' + p).join('\\n')}\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n**Choose an action:**`;\n\nreturn {\n  json: {\n    ...$input.item.json,\n    ...generatedPost,\n    preview_text: preview,\n    approval_pending: true,\n    generation_timestamp: new Date().toISOString()\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "7642abfa-80a4-4254-808d-8eafd3aa3d75",
      "name": "Send Preview to Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1968,
        -96
      ],
      "parameters": {
        "text": "={{ $json.preview_text }}",
        "chatId": "={{ $('Merge Content Sources').item.json.chat_id }}",
        "replyMarkup": "inlineKeyboard",
        "inlineKeyboard": {
          "rows": [
            {
              "row": {
                "buttons": [
                  {
                    "text": "Approve",
                    "additionalFields": {
                      "callback_data": "=approve_{{ $('Merge Content Sources').item.json.post_id || $json.post_id || 'default' }}"
                    }
                  },
                  {
                    "text": "Edit",
                    "additionalFields": {
                      "callback_data": "=edit_{{ $('Merge Content Sources').item.json.post_id || $json.post_id || 'default' }}"
                    }
                  }
                ]
              }
            },
            {
              "row": {
                "buttons": [
                  {
                    "text": "Reject",
                    "additionalFields": {
                      "callback_data": "=reject_{{ $('Merge Content Sources').item.json.post_id || $json.post_id || 'default' }}"
                    }
                  }
                ]
              }
            }
          ]
        },
        "additionalFields": {
          "parse_mode": "HTML",
          "reply_to_message_id": "={{ $('Merge Content Sources').item.json.message_id }}"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2,
      "alwaysOutputData": true
    },
    {
      "id": "04db5e51-3a5f-4817-80d9-135a1164db3e",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        496,
        -144
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "de6e0737-7f17-4336-92d2-a71c5bca8131",
              "operator": {
                "type": "array",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.output.topics }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6f882b2f-c990-451f-ba17-015d992c4636",
      "name": "Initial LinkedIn Post",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1392,
        -96
      ],
      "parameters": {
        "text": "=",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "=You are an expert LinkedIn content creator specializing in professional development and technology trends. Generate engaging, informative LinkedIn posts that provide genuine value to a professional audience.\n\nCONTENT REQUIREMENTS:\n\n-Start with a compelling, attention-grabbing hook related to the actual content\n-Provide specific, actionable insights directly from the source material\n-Include relevant statistics, data points, or key findings when available\n-Use short paragraphs (2-3 lines max) with line breaks for mobile readability\n-Write in third person perspective unless specified to use first person\n-Include 3-5 highly relevant hashtags aligned with the content topic\n-End with a meaningful call-to-action that encourages engagement\n-Keep content within 2800 characters maximum\n-Use 1-3 emojis strategically for emphasis, not decoration\n\nSOURCE ATTRIBUTION RULES:\n\n-If input_type contains \"URL\": Include \"Source: [URL]\" at the end before hashtags\n-If multiple URLs: List as \"Sources: [URL1], [URL2]\"\n-If content comes from web scraping: Extract and reference the actual article title and publication\n-Make it clear that insights are \"based on\" or \"according to\" the source\n\nCONTENT TONE:\n\n-Professional yet conversational and approachable\n-Authoritative but not preachy\n-Enthusiastic and focused on providing valuable insights\n-Credible while maintaining relatability\n\nTARGET AUDIENCE:\n\n-Industry professionals\n-Thought leaders\n-Individuals focused on career growth and staying current with industry trends\n\nCONTENT STRUCTURE:\n\n-Hook: 1-2 sentences that grab attention\n-Key insights or main content: 3-4 short paragraphs\n-Application or takeaway: 1-2 sentences\n-Call-to-action question to drive engagement\n-Source attribution (if applicable)\n-Hashtags\n\nEXAMPLES OF STRONG HOOKS:\n\n-The [industry/topic] landscape is shifting faster than ever\u2026\n-Just discovered a comprehensive guide that could change how professionals approach [topic]\u2026\n-The numbers don\u2019t lie: [specific statistic] shows that [insight]\u2026\n-[Surprising fact or trend] is reshaping [industry/field]\u2026\n\nOUTPUT FORMAT: Return ONLY a JSON object with the following structure:\n{\n\"post_content\": \"the complete post including source attribution and hashtags\",\n\"hashtags\": [\"hashtag1\", \"hashtag2\", \"hashtag3\"],\n\"character_count\": 1234,\n\"hook\": \"the opening line that grabs attention\",\n\"cta\": \"the call-to-action question\",\n\"key_points\": [\"specific insight 1\", \"specific insight 2\", \"specific insight 3\"],\n\"source_urls\": [\"url1\", \"url2\"] // if applicable\n}\n\nBased on the following information, create a LinkedIn post that transforms the source content into engaging, valuable insights for your professional network:"
            },
            {
              "type": "HumanMessagePromptTemplate",
              "message": "=Input Type: {{ $json.input_type }}\nURLS: {{ $json.scraped_urls }}\nTopics: {{ $json.topics }} \nProcessing Instructions: {{ $json.processing_instructions }} \nScraped Content: {{ $json.scraped_content }}\nSearch Results: {{ $json.brave_search_results }}"
            }
          ]
        },
        "promptType": "define"
      },
      "executeOnce": true,
      "typeVersion": 1.7
    },
    {
      "id": "ab0a005e-b926-49f7-93bc-4de5e3d5c011",
      "name": "Scrape a url and get its content",
      "type": "@mendable/n8n-nodes-firecrawl.firecrawl",
      "position": [
        720,
        -528
      ],
      "parameters": {
        "url": "={{ $json.current_url }}",
        "operation": "scrape",
        "scrapeOptions": {
          "options": {
            "headers": {}
          }
        },
        "requestOptions": {}
      },
      "credentials": {
        "firecrawlApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e5f7a21a-1dbc-4e2e-8f84-de06d87adaf3",
      "name": "If1",
      "type": "n8n-nodes-base.if",
      "position": [
        48,
        -464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "6cc58f5a-cc9b-4698-8bfe-3a8a08394cb5",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.input_type }}",
              "rightValue": "URL"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "784ae37f-d98c-46be-9cc0-f7abab2d7aaf",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        944,
        -128
      ],
      "parameters": {
        "numberInputs": 4
      },
      "typeVersion": 3.2
    },
    {
      "id": "a7b81e78-6e44-4e2c-a96c-f4be302f8667",
      "name": "Update row in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2192,
        -96
      ],
      "parameters": {
        "columns": {
          "value": {
            "post_id": "={{ $('Merge Content Sources').item.json.post_id }}",
            "timestamp": "={{ $('Merge Content Sources').item.json.processing_timestamp }}",
            "hashtags_used": "={{ $('Format Preview').item.json.hashtags }}",
            "extracted_urls": "={{ $('Merge Content Sources').item.json.urls }}",
            "search_queries": "={{ $('Merge Content Sources').item.json.brave_search_query }}",
            "character_count": "={{ $('Format Preview').item.json.character_count }}",
            "content_sources": "={{ $('Merge Content Sources').item.json.content_sources }}",
            "identified_topics": "={{ $('Merge Content Sources').item.json.topics }}",
            "final_approved_post": "={{ $('Format Preview').item.json.post_content }}",
            "initial_generated_post": "={{ $('Format Preview').item.json.post_content }}",
            "search_results_summary": "={{ $('Merge Content Sources').item.json.brave_search_results }}",
            "scraped_content_summary": "={{ $('Merge Content Sources').item.json.scraped_summary }}"
          },
          "schema": [
            {
              "id": "post_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "post_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "user_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "user_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "user_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "user_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "input_type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "input_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "original_message",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "original_message",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "extracted_urls",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "extracted_urls",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "identified_topics",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "identified_topics",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "search_queries",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "search_queries",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "search_results_summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "search_results_summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "scraped_content_summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "scraped_content_summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "content_sources",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "content_sources",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "initial_generated_post",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "initial_generated_post",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "final_approved_post",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "final_approved_post",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hashtags_used",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "hashtags_used",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "character_count",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "character_count",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "has_media",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "has_media",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "media_urls",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "media_urls",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "approval_status",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "approval_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "rejection_reason",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "rejection_reason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "edit_iterations",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "edit_iterations",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "time_to_approval",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "time_to_approval",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "posted_datetime",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "posted_datetime",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "scheduled_time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "scheduled_time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "linkedin_post_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "linkedin_post_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "post_type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "post_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "impressions_1h",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "impressions_1h",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "impressions_24h",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "impressions_24h",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "impressions_7d",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "impressions_7d",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "impressions_30d",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "impressions_30d",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "reactions_total",
              "type": "string",
              "display": true,
              "required": false,
             

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

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Source: https://n8n.io/workflows/7466/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

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

AI & RAG

This workflow turns any URL sent to a Telegram bot into ready-to-publish social posts: Trigger: Telegram message (checks if it contains a URL). Fetch & parse: Downloads the page and extracts readable

Telegram Trigger, HTTP Request, Google Sheets +5
AI & RAG

Auto-Generate Social Media Posts From Urls With Ai Telegram Multi-Platform Posting. Uses telegramTrigger, httpRequest, googleSheets, openAi. Event-driven trigger; 42 nodes.

Telegram Trigger, HTTP Request, Google Sheets +5
AI & RAG

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Telegram Trigger, Google Gemini Chat, Chain Llm +5
AI & RAG

This workflow automates the calculation of monthly water bills. Residents can send a photo of their water meter along with their name via Telegram. The workflow uses Gemini AI to extract the meter rea

Telegram Trigger, Telegram, Chain Llm +3
AI & RAG

This workflow creates a multi-talented AI assistant named Simran that interacts with users via Telegram. It can handle text and voice messages, understand the user's intent, and perform various tasks.

MongoDB, Chain Llm, Google Gemini Chat +11