{
  "id": "lNBuLeOYDLRMZhF0",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Url Shortner",
  "tags": [],
  "nodes": [
    {
      "id": "3699e2c1-9b17-4975-adfa-40c5955f1d51",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        0,
        -105
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ab26cb35-e5cd-4011-a2f1-3b3630155799",
      "name": "Insert shortCode",
      "type": "n8n-nodes-base.mongoDb",
      "position": [
        1460,
        220
      ],
      "parameters": {
        "fields": "=longUrl,shortUrl",
        "options": {},
        "operation": "insert",
        "collection": "url"
      },
      "credentials": {
        "mongoDb": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "0aa4998d-d44d-49ff-8620-ffc299a90a82",
      "name": "New link",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1680,
        220
      ],
      "parameters": {
        "text": "=Here is your Short URL : https://s.lamdi.id/{{ $('shortCode Data').item.json.shortUrl }}",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ce0adffc-a7cb-4d40-ba1a-312a817d1646",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -180
      ],
      "parameters": {
        "width": 1180,
        "height": 280,
        "content": "## Validating\n"
      },
      "typeVersion": 1
    },
    {
      "id": "591e81f5-d1ad-45dc-af47-6e94f1558315",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -480
      ],
      "parameters": {
        "color": 3,
        "width": 1180,
        "height": 280,
        "content": "## Link not valid\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "792a1a83-6c38-4d18-ab7e-45a54b7fe64c",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        120
      ],
      "parameters": {
        "color": 4,
        "width": 2000,
        "height": 280,
        "content": "## Creating new link\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "63434047-e655-4490-aac0-3f2a98461b3d",
      "name": "Exist?",
      "type": "n8n-nodes-base.mongoDb",
      "position": [
        440,
        220
      ],
      "parameters": {
        "query": "={\n\"shortUrl\": \"{{ $json.shortUrl }}\"\n}",
        "options": {
          "limit": 1
        },
        "collection": "url"
      },
      "credentials": {
        "mongoDb": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2,
      "alwaysOutputData": true
    },
    {
      "id": "035410fc-07fe-41ac-9acd-d8c7e86de9d5",
      "name": "no exist?",
      "type": "n8n-nodes-base.if",
      "position": [
        1020,
        220
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8ad72bb8-6b19-4a69-bc43-2d1d31fe4026",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.exist }}",
              "rightValue": "false"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "687c1422-6ade-4279-929e-05279d815d6e",
      "name": "exist?",
      "type": "n8n-nodes-base.set",
      "position": [
        660,
        220
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "36d39222-59ad-48ec-887f-ddb78a7f7239",
              "name": "exist",
              "type": "string",
              "value": "={{ !!$json._id }}"
            },
            {
              "id": "102add96-c1ac-4174-92c4-8d6608fedcd5",
              "name": "shortUrl",
              "type": "string",
              "value": "={{ $('Reply Data').item.json.shortUrl }}"
            },
            {
              "id": "bc5964bc-95ac-4e44-929c-264b3f71270a",
              "name": "longUrl",
              "type": "string",
              "value": "={{ $('Reply Data').item.json.longUrl }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "024156e2-423c-476d-bd74-6ad6b18631d3",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -20,
        640
      ],
      "parameters": {
        "path": "redirect",
        "options": {},
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "af608dbd-b6f4-47ea-8eb9-7c7095fcc72d",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        420
      ],
      "parameters": {
        "color": 5,
        "width": 1420,
        "height": 580,
        "content": "## Handle Redirects\n"
      },
      "typeVersion": 1
    },
    {
      "id": "aaa66b70-a6c4-472a-8ad5-78ddddaa6b60",
      "name": "Is it reply?",
      "type": "n8n-nodes-base.if",
      "position": [
        220,
        -100
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8b3fa1be-6cde-4ac6-95aa-969e84c035d5",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.message.reply_to_message }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "76ecf7ff-0ce6-4d0c-8f88-ccfe6b9c10ed",
      "name": "Reply Data",
      "type": "n8n-nodes-base.set",
      "position": [
        220,
        220
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "947ede9e-ddc8-4ed3-8edd-af0b03de78e2",
              "name": "longUrl",
              "type": "string",
              "value": "={{ $json.longUrl }}"
            },
            {
              "id": "41204ee4-cac2-4f1c-a95c-1af0cdded6dc",
              "name": "shortUrl",
              "type": "string",
              "value": "={{ $('Is it reply?').item.json.message.text }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "fd5152fa-fa5a-4408-be08-e1ae6c78c791",
      "name": "askShortCode",
      "type": "n8n-nodes-base.telegram",
      "position": [
        880,
        -100
      ],
      "parameters": {
        "text": "=Link detected: {{ $json.longUrl }} What code do you want to use?",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "forceReply": {
          "force_reply": true
        },
        "replyMarkup": "forceReply",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "3bc6b432-0e8b-49b8-89fa-4b232b6bd1b1",
      "name": "Clean Data",
      "type": "n8n-nodes-base.code",
      "position": [
        0,
        220
      ],
      "parameters": {
        "jsCode": "const urlRegex = /(https?:\\/\\/[^\\s]+)/g;\nconst text = $input.first().json.message.reply_to_message.text;\nconst urls = text.match(urlRegex);\n\nif (!urls || urls.length === 0) {\n    return {\n        json: {\n            error: \"There is not detected URL. Please input valid URL that start with http:// or https://\",\n            chat_id: $input.item.json.chat_id // Take chat_id for error message\n        }\n    };\n}\n\nconst longUrl = urls[0]; // Take first URL appear\n\n// Function for generate random URL\nfunction generateRandomCode(length = 7) {\n    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n    let result = '';\n    for (let i = 0; i < length; i++) {\n        result += characters.charAt(Math.floor(Math.random() * characters.length));\n    }\n    return result;\n}\n\nlet shortCode = generateRandomCode();\n\n// Prepare data for MongoDB\nreturn {\n    json: {\n        longUrl: longUrl,\n        shortCode: shortCode,\n        chat_id: $input.item.json.chat_id,\n        message_id: $input.item.json.message_id\n    }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "e6b64f7a-4f51-42b0-8c2e-1dff1e09defa",
      "name": "askShortCode1",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1240,
        -80
      ],
      "parameters": {
        "text": "=Short code existed! Try another one? (You must reply this message)",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "forceReply": {
          "force_reply": true
        },
        "replyMarkup": "forceReply",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e3dfe8fe-85a4-4682-b8d8-25f27f55d402",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1120,
        -180
      ],
      "parameters": {
        "color": 3,
        "width": 800,
        "height": 280,
        "content": "## Link exist, ask another one\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e3b0449e-d305-412c-8521-d395df67c329",
      "name": "Valid URL",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1080,
        540
      ],
      "parameters": {
        "options": {},
        "redirectURL": "={{ $('short code exist?1').item.json.longUrl }}",
        "respondWith": "redirect"
      },
      "typeVersion": 1.4
    },
    {
      "id": "7cd09931-b212-42f0-ae34-4fbb3c78b47e",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -740,
        -180
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 1180,
        "content": "## Workflow 1: Create Short URL\n\nI. Main Message & Reply Detection\n\n- Telegram Trigger: Receives all Telegram messages.\n- Is it Reply? (IF): Checks if message is a reply.\n- True: Reply (-> Code)\n- False: Initial message (-> Clean Data)\n\nII. Path: Initial Message (Long URL)\n\n- Clean Data (Function): Extracts and validates long URL.\n- Reply Data (Set): Stores URL/chat context for workflow.\n- Exist? (MongoDB - Find): Checks if long URL/short code exists.\n- exist? (Set): Flags if link exists (true/false).\n- no exist? (IF): Routes based on link existence.\n- True: Link exists (-> askShortCode1)\n- False: New link (-> Data)\n\nIII. Path: Existing Link / Ask Custom\n\n- askShortCode1 (Telegram Send Message): Notifies link exists, asks for custom code (Force Reply).\n\nIV. Path: Custom Code Submission & Validation\n\n- Code (Function): Validates custom short code format.\n- Not Valid? (IF): Checks custom code format validity.\n- True: Invalid format (-> Not Valid)\n- False: Valid format (-> connects to Exist? for existence check)\n- Not Valid (Telegram Send Message): Error: invalid code format.\n\nV. Path: Creating New Link (If Unique)\n\n- Data (Set): Prepares final link data for database insert.\n- Insert shortCode (MongoDB - Insert): Inserts new long/short URL pair.\n- New link (Telegram Send Message): Sends new short URL to user."
      },
      "typeVersion": 1
    },
    {
      "id": "3c327cb0-c695-4792-840b-4964cb1a3a6e",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1360,
        420
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 580,
        "content": "## Workflow 2: URL Redirect Handler\n\n- Webhook (Webhook Trigger): Receives short URL requests from web server.\n- Data2 (Set): Extracts short code from webhook URL.\nExist?2 (MongoDB - Find): Finds original long URL for given short code.\n- Exist?3 (Set): Extracts found long URL.\n- if (IF): Checks if long URL was found.\n- True: URL found (-> Valid URL)\n- False: URL not found (-> Not valid URL)\n- Valid URL (Respond to Webhook): Redirects to original long URL (HTTP 302).\n- Not valid URL (Respond to Webhook): Sends 404 Not Found response."
      },
      "typeVersion": 1
    },
    {
      "id": "721bf395-5f9c-406c-a734-682c6f5f4a97",
      "name": "take URL",
      "type": "n8n-nodes-base.code",
      "position": [
        440,
        -105
      ],
      "parameters": {
        "jsCode": "const urlRegex = /(https?:\\/\\/[^\\s]+)/g;\nconst text = $input.first().json.message.text;\nconst urls = text.match(urlRegex);\n\nif (!urls || urls.length === 0) {\n    return {\n        json: {\n            error: \"There is not detected URL. Please input valid URL that start with http:// or https://\",\n            chat_id: $input.item.json.chat_id // Take chat_id for error message\n        }\n    };\n}\n\nconst longUrl = urls[0]; // Take first URL appear\n\n// Function for generate random URL\nfunction generateRandomCode(length = 7) {\n    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n    let result = '';\n    for (let i = 0; i < length; i++) {\n        result += characters.charAt(Math.floor(Math.random() * characters.length));\n    }\n    return result;\n}\n\nlet shortCode = generateRandomCode();\n\n// Prepare data for MongoDB\nreturn {\n    json: {\n        longUrl: longUrl,\n        shortCode: shortCode,\n        chat_id: $input.item.json.chat_id,\n        message_id: $input.item.json.message_id\n    }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "2dfc05a3-b928-4277-ba3c-38e1fb7fd944",
      "name": "Not Valid URL?",
      "type": "n8n-nodes-base.if",
      "position": [
        660,
        -105
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "6d06a585-e477-45db-9a06-8f6faa151beb",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.error }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f38169f6-efdb-4e1a-b0b9-6740ef59f693",
      "name": "Not Valid URL1",
      "type": "n8n-nodes-base.telegram",
      "position": [
        440,
        -380
      ],
      "parameters": {
        "text": "Please input valid url (https://domain.com)",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e1e5911c-afae-4cdf-a043-01e3dad1f598",
      "name": "take short code",
      "type": "n8n-nodes-base.set",
      "position": [
        200,
        640
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "937b7cd7-77f7-4668-8d39-ba17a606b049",
              "name": "shortCode",
              "type": "string",
              "value": "={{ $json.query.code }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "daff4473-50f5-4cf2-8ae4-0734fb0523ca",
      "name": "short code exist?",
      "type": "n8n-nodes-base.mongoDb",
      "position": [
        420,
        640
      ],
      "parameters": {
        "query": "={\"shortUrl\":\"{{ $json.shortCode }}\"}",
        "options": {},
        "collection": "url"
      },
      "credentials": {
        "mongoDb": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2,
      "alwaysOutputData": true
    },
    {
      "id": "5102ca6d-e5d5-4828-88f0-4e761cd77825",
      "name": "short code exist?1",
      "type": "n8n-nodes-base.set",
      "position": [
        640,
        640
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "16a2153c-2115-42cd-bcce-e6d016c1588d",
              "name": "exist",
              "type": "string",
              "value": "={{ !!$json._id }}"
            },
            {
              "id": "382fc55c-6d4b-4a70-b087-7173165edea1",
              "name": "longUrl",
              "type": "string",
              "value": "={{ $json.longUrl }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "3cd11299-1aef-4b29-87e1-f6370e227056",
      "name": "If short code exist",
      "type": "n8n-nodes-base.if",
      "position": [
        860,
        640
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9e62aeda-3c42-4d30-a0f0-d64f34db5a94",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('short code exist?1').item.json.exist }}",
              "rightValue": "true"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a7649e38-53a9-4023-bfaf-433b6c7ec473",
      "name": "404 page",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1080,
        740
      ],
      "parameters": {
        "options": {},
        "redirectURL": "https://s3-cdn.cmlabs.co/page/2023/01/24/a-guideline-on-how-to-fix-error-404-not-found-effectively-519451.png",
        "respondWith": "redirect"
      },
      "typeVersion": 1.4
    },
    {
      "id": "2987203f-83e2-4fd7-abde-25916d7d73bb",
      "name": "shortCode Data",
      "type": "n8n-nodes-base.set",
      "position": [
        1240,
        220
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "5bbaa285-6b18-46bc-a547-8d1b999fd6c2",
              "name": "shortUrl",
              "type": "string",
              "value": "={{ $('exist?').item.json.shortUrl }}"
            },
            {
              "id": "a98b3245-9612-4b72-b844-7353c0941fb2",
              "name": "longUrl",
              "type": "string",
              "value": "={{ $('exist?').item.json.longUrl }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    }
  ],
  "active": true,
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "executionOrder": "v1",
    "saveDataSuccessExecution": "none"
  },
  "versionId": "e2b51546-52fa-494f-a544-99d99e93754a",
  "connections": {
    "Exist?": {
      "main": [
        [
          {
            "node": "exist?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "exist?": {
      "main": [
        [
          {
            "node": "no exist?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "take short code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "take URL": {
      "main": [
        [
          {
            "node": "Not Valid URL?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "no exist?": {
      "main": [
        [
          {
            "node": "shortCode Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "askShortCode1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean Data": {
      "main": [
        [
          {
            "node": "Reply Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Reply Data": {
      "main": [
        [
          {
            "node": "Exist?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is it reply?": {
      "main": [
        [
          {
            "node": "Clean Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "take URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "askShortCode": {
      "main": [
        []
      ]
    },
    "Not Valid URL?": {
      "main": [
        [
          {
            "node": "Not Valid URL1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "askShortCode",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "shortCode Data": {
      "main": [
        [
          {
            "node": "Insert shortCode",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "take short code": {
      "main": [
        [
          {
            "node": "short code exist?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert shortCode": {
      "main": [
        [
          {
            "node": "New link",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Is it reply?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "short code exist?": {
      "main": [
        [
          {
            "node": "short code exist?1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "short code exist?1": {
      "main": [
        [
          {
            "node": "If short code exist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If short code exist": {
      "main": [
        [
          {
            "node": "Valid URL",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "404 page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}