{ "name": "Reply with a Random Cocktail Photo", "nodes": [ { "name": "Telegram Trigger", "type": "n8n-nodes-base.telegramTrigger", "position": [ 570, 260 ], "parameters": { "updates": [ "message" ], "additionalFields": {} }, "typeVersion": 1, "id": "reply-with-a-random-cocktail-photo-0" }, { "name": "HTTP Request", "type": "n8n-nodes-base.httpRequest", "position": [ 770, 260 ], "parameters": { "method": "GET", "url": "https://www.thecocktaildb.com/api/json/v1/1/random.php", "options": { "timeout": 30000, "response": { "response": { "responseFormat": "json" } } } }, "typeVersion": 4.2, "id": "reply-with-a-random-cocktail-photo-1" }, { "name": "Telegram", "type": "n8n-nodes-base.telegram", "position": [ 970, 260 ], "parameters": { "resource": "message", "operation": "sendPhoto", "chatId": "={{ $json.chatId }}", "binaryData": false, "file": "={{ $json.photo }}", "replyMarkup": "none", "additionalFields": "={{ {caption:$json.caption,reply_to_message_id:$json.replyToMessageId} }}" }, "typeVersion": 1, "id": "reply-with-a-random-cocktail-photo-2" }, { "id": "reply-with-a-random-cocktail-photo-check", "name": "Validate the cocktail reply", "type": "n8n-nodes-base.code", "typeVersion": 2, "parameters": { "mode": "runOnceForAllItems", "jsCode": " function validUrl(value) {\n if (typeof value !== 'string' || /[\\s\\x00-\\x1f\\x7f\\\\]/.test(value) || /%(?![0-9a-f]{2})/i.test(value)) return false;\n const match = /^https?:\\/\\/([^/?#]+)(?:[/?#].*)?$/i.exec(value);\n if (!match || match[1].includes('@')) return false;\n const authority = match[1];\n let host, port;\n if (authority.startsWith('[')) {\n const parts = /^\\[([0-9a-f:]+)\\](?::(\\d+))?$/i.exec(authority);\n if (!parts) return false;\n host = parts[1]; port = parts[2];\n const halves = host.split('::');\n if (halves.length > 2) return false;\n const groups = halves.flatMap(part => part ? part.split(':') : []);\n if (groups.some(group => !/^[0-9a-f]{1,4}$/i.test(group))) return false;\n if (halves.length === 1 ? groups.length !== 8 : groups.length >= 8) return false;\n } else {\n const parts = /^([^:]+)(?::(\\d+))?$/.exec(authority);\n if (!parts) return false;\n host = parts[1]; port = parts[2];\n if (host.length > 253) return false;\n const labels = host.replace(/\\.$/, '').split('.');\n if (!labels.every(label => label.length > 0 && label.length <= 63 && /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(label))) return false;\n if (labels.every(label => /^\\d+$/.test(label)) && (labels.length !== 4 || labels.some(label => Number(label) > 255))) return false;\n }\n return port === undefined || (port.length <= 5 && Number(port) <= 65535);\n }\n\nfunction identity({body}){const message=body?.message,id=message?.chat?.id,reply=message?.message_id;if(!Number.isSafeInteger(id)||id===0||!Number.isSafeInteger(reply)||reply<=0)throw Error('Telegram message has no valid chat or message ID');return{chatId:String(id),replyToMessageId:reply};}\n\nconst event=$('Telegram Trigger').item.json,who=identity({body:event}),drink=$input.first().json.drinks?.[0];if(typeof drink?.strDrink!=='string'||!drink.strDrink||!validUrl(drink.strDrinkThumb))throw Error('Missing cocktail name or photo');if(drink.strDrink.length>1024)throw Error('Cocktail caption exceeds Telegram limit');return [{json:{...who,photo:drink.strDrinkThumb,caption:drink.strDrink}}];" } } ], "active": false, "settings": {}, "connections": { "HTTP Request": { "main": [ [ { "node": "Validate the cocktail reply", "type": "main", "index": 0 } ] ] }, "Telegram Trigger": { "main": [ [ { "node": "HTTP Request", "type": "main", "index": 0 } ] ] }, "Validate the cocktail reply": { "main": [ [ { "node": "Telegram", "type": "main", "index": 0 } ] ] } }, "pinData": {} }