AutomationFlowsSlack & Telegram › Telegram Free Trial Handler

Telegram Free Trial Handler

Telegram Free Trial Handler. Uses postgres, executeCommand, telegram. Webhook trigger; 21 nodes.

Webhook trigger★★★★☆ complexity21 nodesPostgresExecute CommandTelegram
Slack & Telegram Trigger: Webhook Nodes: 21 Complexity: ★★★★☆ Added:

This workflow follows the Postgres → Telegram 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": "Telegram Free Trial Handler",
  "tags": [
    "telegram",
    "free-trial",
    "customer"
  ],
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "telegram-free-trial",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "tgft-trigger",
      "name": "Telegram Free Trial Trigger",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Extract message from Telegram update\nconst data = $input.item.json;\nconst message = (data.message?.text || '').toLowerCase().trim();\nconst chatId = data.message?.chat?.id?.toString() || '';\nconst firstName = data.message?.chat?.first_name || 'there';\nconst updateId = data.update_id?.toString() || '';\n\n// Keywords\nconst trialKeywords = ['free trial', 'free plan', 'trial', 'try free', 'demo'];\nconst doneKeywords = ['done', 'completed', 'done!', 'finished', 'working'];\n\nconst isTrialRequest = trialKeywords.some(k => message.includes(k));\nconst isDoneReply = doneKeywords.some(k => message.includes(k));\n\nreturn {\n  json: {\n    chatId,\n    firstName,\n    message,\n    updateId,\n    is_trial_request: isTrialRequest,\n    is_done_reply: isDoneReply\n  }\n};"
      },
      "id": "tgft-parse",
      "name": "Parse Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        470,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "cond-trial-req",
              "leftValue": "={{$json.is_trial_request}}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ]
        },
        "options": {}
      },
      "id": "tgft-if-trial",
      "name": "If Trial Request",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        690,
        200
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "cond-done-reply",
              "leftValue": "={{$json.is_done_reply}}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ]
        },
        "options": {}
      },
      "id": "tgft-if-done",
      "name": "If DONE Reply",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        690,
        420
      ]
    },
    {
      "parameters": {
        "jsCode": "// Count pending (uncredited) surveys for this customer\nconst chatId = $('Parse Message').first().json.chatId;\n\nreturn { json: { chatId } };"
      },
      "id": "tgft-count-prep",
      "name": "Prep Survey Count",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        910,
        420
      ]
    },
    {
      "parameters": {
        "command": "SELECT COUNT(*) AS survey_count FROM pending_trial_surveys WHERE platform_user_id = '{{$json.chatId}}' AND platform = 'telegram' AND credited = FALSE;",
        "options": {}
      },
      "id": "tgft-count-surveys",
      "name": "Count Pending Surveys",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 1,
      "position": [
        1130,
        420
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false
          },
          "conditions": [
            {
              "id": "cond-has-surveys",
              "leftValue": "={{ $json.survey_count }}",
              "rightValue": 0,
              "operator": {
                "type": "number",
                "operation": "gt"
              }
            }
          ]
        },
        "options": {}
      },
      "id": "tgft-if-has-surveys",
      "name": "If Has Surveys",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1350,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// No surveys completed yet\nconst firstName = $('Parse Message').first().json.firstName;\n\nconst message = `\u23f3 You no complete any survey yet.\\n\\nTo get your free proxy:\\n1. Click the survey link I sent earlier\\n2. Complete the survey\\n3. Come back and tell me \"done\"\\n\\nYou fit do as many surveys as you want \u2014 each one give you 2 more hours!\\nCome back when you don complete at least one survey. \ud83d\udc4b`;\n\nreturn { json: { message } };"
      },
      "id": "tgft-no-surveys",
      "name": "Generate No Surveys Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1350,
        550
      ]
    },
    {
      "parameters": {
        "jsCode": "// Calculate hours and check cap\nconst surveyCountRaw = $input.item.json.survey_count;\nconst surveyCount = parseInt(surveyCountRaw, 10);\n\nconst MAX_SURVEYS = 12;\nconst HOURS_PER_SURVEY = 2;\nconst MAX_HOURS = MAX_SURVEYS * HOURS_PER_SURVEY; // 24\n\nconst cappedCount = Math.min(surveyCount, MAX_SURVEYS);\nconst totalHours = cappedCount * HOURS_PER_SURVEY;\nconst hitCap = surveyCount >= MAX_SURVEYS;\n\nreturn {\n  json: {\n    survey_count: surveyCount,\n    total_hours: totalHours,\n    hit_cap: hitCap,\n    port: 8001 + Math.floor(Math.random() * 99) // Random port 8001-8100 \u2014 TODO: query active ports for availability\n  }\n};"
      },
      "id": "tgft-calc",
      "name": "Calculate Hours + Cap",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1570,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false
          },
          "conditions": [
            {
              "id": "cond-slot-check",
              "leftValue": "={{$json.port}}",
              "rightValue": 0,
              "operator": {
                "type": "number",
                "operation": "gt"
              }
            }
          ]
        },
        "options": {}
      },
      "id": "tgft-if-slot-ok",
      "name": "If Slot Available",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1790,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Generate trial credentials\nconst crypto = require('crypto');\n\nconst chatId = $('Parse Message').first().json.chatId;\nconst totalHours = parseInt($input.item.json.total_hours);\nconst port = parseInt($input.item.json.port);\n\nconst userId = 'trial_' + crypto.randomBytes(4).toString('hex');\nconst password = crypto.randomBytes(8).toString('base64').replace(/[+/=]/g, '').substring(0, 16);\n\nconst expiresAt = new Date(Date.now() + totalHours * 60 * 60 * 1000).toISOString();\nconst expiresDisplay = new Date(Date.now() + totalHours * 60 * 60 * 1000)\n  .toLocaleString('en-GB', { hour: '2-digit', minute: '2-digit', day: '2-digit', month: 'short' });\n\nconst remaining = Math.max(0, 12 - Math.floor(totalHours / 2));\n\nreturn {\n  json: {\n    chatId,\n    user_id: userId,\n    password,\n    port,\n    expires_at: expiresAt,\n    expires_display: expiresDisplay,\n    total_hours: totalHours,\n    remaining_surveys: remaining,\n    survey_count: Math.floor(totalHours / 2)\n  }\n};"
      },
      "id": "tgft-gen-creds",
      "name": "Generate Trial Credentials",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2010,
        200
      ]
    },
    {
      "parameters": {
        "command": "/usr/local/bin/manage-3proxy-trial.sh add {{$json.user_id}} '{{$json.password}}' {{$json.port}}",
        "options": {}
      },
      "id": "tgft-3proxy-add",
      "name": "Add 3proxy User",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        2230,
        200
      ]
    },
    {
      "parameters": {
        "operation": "update",
        "schema": "public",
        "table": "pending_trial_surveys",
        "columns": "credited",
        "additionalFields": "credited = TRUE",
        "options": {}
      },
      "id": "tgft-mark-credited",
      "name": "Mark Surveys Credited",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 1,
      "position": [
        2450,
        200
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Compose success message\nconst c = $input.item.json;\nconst totalHours = parseInt(c.total_hours);\nconst remaining = Math.max(0, 12 - parseInt(c.survey_count));\nconst hitCap = parseInt(c.survey_count) >= 12;\n\nlet hoursLine = `${totalHours} hours`;\nif (hitCap) hoursLine = '24 hours (maximum!)';\n\nconst message = `\ud83c\udf89 Your proxy don ready!\\n\\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\\n\ud83c\udf10 STYXPROXY TRIAL PROXY\\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\\n\\n\ud83d\udd17 IP: proxy.styxproxy.com\\n\ud83d\udd0c Port: ${c.port}\\n\ud83d\udc64 User: ${c.user_id}\\n\ud83d\udd11 Pass: ${c.password}\\n\\n\u23f0 Duration: ${hoursLine}\\n\ud83d\udcca Surveys completed: ${c.survey_count}/12\\n\\n\u26a0\ufe0f Shared proxy \u2014 other trial users share this IP.\\nFor private/production use, upgrade to a paid plan.\\n\\n\ud83d\udca1 Want more time? You fit do up to ${remaining} more surveys!\\nJust come back and tell me \"done\" again when you ready. \ud83d\ude0a`;\n\nreturn { json: { message, chatId: c.chatId } };"
      },
      "id": "tgft-gen-success",
      "name": "Generate Success Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2670,
        200
      ]
    },
    {
      "parameters": {
        "chatId": "={{$json.chatId}}",
        "message": "={{$json.message}}",
        "options": {}
      },
      "id": "tgft-send-creds",
      "name": "Send Credentials via Telegram",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        2890,
        200
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Slots busy message\nconst chatId = $('Parse Message').first().json.chatId;\nconst message = `\u26a0\ufe0f All trial slots busy for now.\\n\\nOur free trial proxy dey full \u2014 e go free up within 30 minutes.\\nMake you no go anywhere o! As e free, I go send you your proxy details. \ud83d\ude0a\\n\\nOr if you no want wait, you fit order paid proxy now:\\n\u2022 ISP UK: \u20a66,500/mo\\n\u2022 Residential: from \u20a61,950/GB\\n\\nJust tell me \"I want to order\"!`;\n\nreturn { json: { message, chatId } };"
      },
      "id": "tgft-busy-msg",
      "name": "Generate Busy Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2010,
        420
      ]
    },
    {
      "parameters": {
        "chatId": "={{$json.chatId}}",
        "message": "={{$json.message}}",
        "options": {}
      },
      "id": "tgft-send-busy",
      "name": "Send Busy Message",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        2230,
        420
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Generate disclaimer + survey link message\nconst firstName = $('Parse Message').first().json.firstName;\nconst surveyLink = process.env.THEOREM_REACH_SURVEY_URL || 'https://theoremreach.com/survey/XXXXX';\n\nconst message = `\ud83c\udf81 FREE TRIAL \u2014 DISCLAIMER\\n\\nBefore we send your free IP, please read:\\n\\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\\n\u26a0\ufe0f FREE TRIAL TERMS \u26a0\ufe0f\\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\\n\\nThis free trial uses a Styxproxy-hosted proxy\\nshared with other trial users. By accepting, you agree:\\n\\n\u274c NOT for production/critical use\\n\u274c Not guaranteed private (shared with other trials)\\n\u274c IP shared = if one user misbehaves, IP could get flagged\\n\u274c No replacement if proxy dies or expires\\n\u274c Used entirely at YOUR OWN RISK\\n\\n\u2705 Styxproxy-hosted proxy \u2014 generally reliable\\n\u2705 Auto-expires based on how many surveys you complete\\n\u2705 For testing our service only\\n\u2705 Upgrade to paid plan for reliability + privacy\\n\\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\\n\\nHow e go work:\\n1. Complete surveys to earn proxy time\\n2. Each survey = 2 hours of proxy access\\n3. Do up to 12 surveys = up to 24 hours free!\\n4. When you ready, tell me \"done\" and I go send your proxy details\\n\\nComplete ONE survey to start:\\n${surveyLink}\\n\\nAfter completing, come back and tell me \"done\"\\nYou fit do more surveys to get more time! \ud83d\udc47`;\n\nreturn { json: { message } };"
      },
      "id": "tgft-gen-disc",
      "name": "Generate Disclaimer Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        910,
        200
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $('Parse Message').first().json.chatId }}",
        "message": "={{$json.message}}",
        "options": {}
      },
      "id": "tgft-send-disc",
      "name": "Send Disclaimer + Survey Link",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        1130,
        200
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $('Parse Message').first().json.chatId }}",
        "message": "={{$json.message}}",
        "options": {}
      },
      "id": "tgft-send-no-surveys",
      "name": "Send No Surveys Message",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        1570,
        550
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "{\"status\":\"ok\"}",
        "options": {
          "responseCode": 200
        }
      },
      "id": "tgft-respond-200",
      "name": "Respond 200 OK",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        3110,
        300
      ]
    }
  ],
  "connections": {
    "Telegram Free Trial Trigger": {
      "main": [
        [
          {
            "node": "Parse Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Message": {
      "main": [
        [
          {
            "node": "If Trial Request",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "If DONE Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Trial Request": {
      "main": [
        [
          {
            "node": "Generate Disclaimer Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If DONE Reply": {
      "main": [
        [
          {
            "node": "Prep Survey Count",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prep Survey Count": {
      "main": [
        [
          {
            "node": "Count Pending Surveys",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Count Pending Surveys": {
      "main": [
        [
          {
            "node": "If Has Surveys",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Has Surveys": {
      "main": [
        [
          {
            "node": "Calculate Hours + Cap",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate No Surveys Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate No Surveys Message": {
      "main": [
        [
          {
            "node": "Send No Surveys Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send No Surveys Message": {
      "main": [
        [
          {
            "node": "Respond 200 OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Hours + Cap": {
      "main": [
        [
          {
            "node": "If Slot Available",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Slot Available": {
      "main": [
        [
          {
            "node": "Generate Trial Credentials",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate Busy Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Busy Message": {
      "main": [
        [
          {
            "node": "Send Busy Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Busy Message": {
      "main": [
        [
          {
            "node": "Respond 200 OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Trial Credentials": {
      "main": [
        [
          {
            "node": "Add 3proxy User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add 3proxy User": {
      "main": [
        [
          {
            "node": "Mark Surveys Credited",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Surveys Credited": {
      "main": [
        [
          {
            "node": "Generate Success Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Success Message": {
      "main": [
        [
          {
            "node": "Send Credentials via Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Credentials via Telegram": {
      "main": [
        [
          {
            "node": "Respond 200 OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Disclaimer Message": {
      "main": [
        [
          {
            "node": "Send Disclaimer + Survey Link",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Disclaimer + Survey Link": {
      "main": [
        [
          {
            "node": "Respond 200 OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}

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

Telegram Free Trial Handler. Uses postgres, executeCommand, telegram. Webhook trigger; 21 nodes.

Source: https://github.com/sonnyagent30-beep/bunche/blob/e991131928c348097e3fb411d5caa3b0466900f8/.n8n/workflows/telegram-free-trial.json — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

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

Slack & Telegram

Telegram Free Trial Handler. Uses postgres, executeCommand, telegram. Webhook trigger; 21 nodes.

Postgres, Execute Command, Telegram
Slack & Telegram

Telegram Free Trial Handler. Uses postgres, executeCommand, telegram. Webhook trigger; 21 nodes.

Postgres, Execute Command, Telegram
Slack & Telegram

03 - Command Handler. Uses executeWorkflowTrigger, telegram, executeCommand, postgres. Event-driven trigger; 53 nodes.

Execute Workflow Trigger, Telegram, Execute Command +2
Slack & Telegram

Admin Handler. Uses telegram, postgres. Webhook trigger; 50 nodes.

Telegram, Postgres
Slack & Telegram

Admin Handler. Uses telegram, postgres. Webhook trigger; 50 nodes.

Telegram, Postgres