From 36ecdd5ba95d032199fe47d4aa0a2d00389d89ce Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Wed, 4 Feb 2026 21:33:23 -0500 Subject: [PATCH] feat(10.1-04): integrate confirmation sub-workflow in main workflow - Removed 19 single-container confirmation nodes - Added 9 integration nodes (net -10 nodes: 178->168) - Route Callback[9,10] (confirm/cancelConfirm) -> Execute Confirmation - Route Action Type[2,3] (stop/update) -> Execute Confirmation - Route Confirmation Result handles show/stop_result/confirm_update/cancel/expired - Added TODO_DEPLOY_CONFIRMATION_WORKFLOW placeholder Co-Authored-By: Claude Opus 4.5 --- n8n-workflow.json | 1002 ++++++++++++++++++--------------------------- 1 file changed, 389 insertions(+), 613 deletions(-) diff --git a/n8n-workflow.json b/n8n-workflow.json index c9c86f1..075085c 100644 --- a/n8n-workflow.json +++ b/n8n-workflow.json @@ -2272,354 +2272,6 @@ } } }, - { - "parameters": { - "jsCode": "// Build Stop Confirmation dialog with timestamp for 30-second timeout\nconst data = $('Parse Callback Data').item.json;\nconst containerName = data.containerName;\nconst chatId = data.chatId;\nconst messageId = data.messageId;\nconst timestamp = Math.floor(Date.now() / 1000); // Unix timestamp\n\nconst keyboard = {\n inline_keyboard: [\n [\n { text: '\\u2705 Yes, Stop', callback_data: `confirm:stop:${containerName}:${timestamp}` },\n { text: '\\u274C Cancel', callback_data: `cancel:${containerName}` }\n ]\n ]\n};\n\nconst text = `\\u26A0\\uFE0F Stop ${containerName}?\\n\\nThis will stop the container immediately.\\n\\nConfirmation expires in 30 seconds.`;\n\nreturn {\n json: {\n chatId,\n messageId,\n text,\n reply_markup: keyboard\n }\n};" - }, - "id": "code-build-stop-confirmation", - "name": "Build Stop Confirmation", - "type": "n8n-nodes-base.code", - "typeVersion": 2, - "position": [ - 1780, - 1400 - ] - }, - { - "parameters": { - "method": "POST", - "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/editMessageText", - "sendBody": true, - "specifyBody": "json", - "jsonBody": "={{ JSON.stringify({ chat_id: $json.chatId, message_id: $json.messageId, text: $json.text, parse_mode: 'HTML', reply_markup: $json.reply_markup }) }}", - "options": {} - }, - "id": "http-send-stop-confirmation", - "name": "Send Stop Confirmation", - "type": "n8n-nodes-base.httpRequest", - "typeVersion": 4.2, - "position": [ - 2000, - 1400 - ], - "credentials": { - "telegramApi": { - "id": "I0xTTiASl7C1NZhJ", - "name": "Telegram account" - } - } - }, - { - "parameters": { - "jsCode": "// Build Update Confirmation dialog with timestamp for 30-second timeout\nconst data = $('Parse Callback Data').item.json;\nconst containerName = data.containerName;\nconst chatId = data.chatId;\nconst messageId = data.messageId;\nconst timestamp = Math.floor(Date.now() / 1000); // Unix timestamp\n\nconst keyboard = {\n inline_keyboard: [\n [\n { text: '\\u2705 Yes, Update', callback_data: `confirm:update:${containerName}:${timestamp}` },\n { text: '\\u274C Cancel', callback_data: `cancel:${containerName}` }\n ]\n ]\n};\n\nconst text = `\\u26A0\\uFE0F Update ${containerName}?\\n\\nThis will pull the latest image and recreate the container.\\n\\nConfirmation expires in 30 seconds.`;\n\nreturn {\n json: {\n chatId,\n messageId,\n text,\n reply_markup: keyboard\n }\n};" - }, - "id": "code-build-update-confirmation", - "name": "Build Update Confirmation", - "type": "n8n-nodes-base.code", - "typeVersion": 2, - "position": [ - 1780, - 1500 - ] - }, - { - "parameters": { - "method": "POST", - "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/editMessageText", - "sendBody": true, - "specifyBody": "json", - "jsonBody": "={{ JSON.stringify({ chat_id: $json.chatId, message_id: $json.messageId, text: $json.text, parse_mode: 'HTML', reply_markup: $json.reply_markup }) }}", - "options": {} - }, - "id": "http-send-update-confirmation", - "name": "Send Update Confirmation", - "type": "n8n-nodes-base.httpRequest", - "typeVersion": 4.2, - "position": [ - 2000, - 1500 - ], - "credentials": { - "telegramApi": { - "id": "I0xTTiASl7C1NZhJ", - "name": "Telegram account" - } - } - }, - { - "parameters": { - "method": "POST", - "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/answerCallbackQuery", - "sendBody": true, - "specifyBody": "json", - "jsonBody": "={{ JSON.stringify({ callback_query_id: $json.queryId }) }}", - "options": {} - }, - "id": "http-answer-confirm-callback", - "name": "Answer Confirm Callback", - "type": "n8n-nodes-base.httpRequest", - "typeVersion": 4.2, - "position": [ - 1340, - 1600 - ], - "credentials": { - "telegramApi": { - "id": "I0xTTiASl7C1NZhJ", - "name": "Telegram account" - } - } - }, - { - "parameters": { - "conditions": { - "options": { - "caseSensitive": true, - "leftValue": "", - "typeValidation": "strict" - }, - "conditions": [ - { - "id": "check-expired", - "leftValue": "={{ $('Parse Callback Data').item.json.expired }}", - "rightValue": true, - "operator": { - "type": "boolean", - "operation": "equals" - } - } - ], - "combinator": "and" - }, - "options": {} - }, - "id": "if-confirm-expired", - "name": "Check Confirm Expired", - "type": "n8n-nodes-base.if", - "typeVersion": 2, - "position": [ - 1560, - 1600 - ] - }, - { - "parameters": { - "jsCode": "// Confirmation expired - return to submenu\nconst data = $('Parse Callback Data').item.json;\nconst containerName = data.containerName;\nconst chatId = data.chatId;\nconst messageId = data.messageId;\n\n// Build keyboard for expired message\nconst keyboard = {\n inline_keyboard: [\n [\n { text: '\\u25C0\\uFE0F Back to List', callback_data: 'list:0' }\n ]\n ]\n};\n\nreturn {\n json: {\n chatId,\n messageId,\n text: `\\u23F0 Confirmation for ${containerName} has expired.\\n\\nPlease try again.`,\n reply_markup: keyboard\n }\n};" - }, - "id": "code-handle-confirm-expired", - "name": "Handle Confirm Expired", - "type": "n8n-nodes-base.code", - "typeVersion": 2, - "position": [ - 1780, - 1700 - ] - }, - { - "parameters": { - "method": "POST", - "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/editMessageText", - "sendBody": true, - "specifyBody": "json", - "jsonBody": "={{ JSON.stringify({ chat_id: $json.chatId, message_id: $json.messageId, text: $json.text, parse_mode: 'HTML', reply_markup: $json.reply_markup }) }}", - "options": {} - }, - "id": "http-send-expired-confirm", - "name": "Send Expired Confirm", - "type": "n8n-nodes-base.httpRequest", - "typeVersion": 4.2, - "position": [ - 2000, - 1700 - ], - "credentials": { - "telegramApi": { - "id": "I0xTTiASl7C1NZhJ", - "name": "Telegram account" - } - } - }, - { - "parameters": { - "rules": { - "values": [ - { - "id": "confirm-stop", - "conditions": { - "options": { - "caseSensitive": true, - "typeValidation": "loose" - }, - "conditions": [ - { - "id": "is-stop-confirm", - "leftValue": "={{ $('Parse Callback Data').item.json.confirmAction }}", - "rightValue": "stop", - "operator": { - "type": "string", - "operation": "equals" - } - } - ], - "combinator": "and" - }, - "renameOutput": true, - "outputKey": "stop" - }, - { - "id": "confirm-update", - "conditions": { - "options": { - "caseSensitive": true, - "typeValidation": "loose" - }, - "conditions": [ - { - "id": "is-update-confirm", - "leftValue": "={{ $('Parse Callback Data').item.json.confirmAction }}", - "rightValue": "update", - "operator": { - "type": "string", - "operation": "equals" - } - } - ], - "combinator": "and" - }, - "renameOutput": true, - "outputKey": "update" - } - ] - }, - "options": { - "fallbackOutput": "none" - } - }, - "id": "switch-route-confirm-action", - "name": "Route Confirm Action", - "type": "n8n-nodes-base.switch", - "typeVersion": 3.2, - "position": [ - 1780, - 1600 - ] - }, - { - "parameters": { - "jsCode": "// Prepare stop action from confirmation\nconst data = $('Parse Callback Data').item.json;\nreturn {\n json: {\n containerName: data.containerName,\n chatId: data.chatId,\n messageId: data.messageId\n }\n};" - }, - "id": "code-prepare-confirmed-stop", - "name": "Prepare Confirmed Stop", - "type": "n8n-nodes-base.code", - "typeVersion": 2, - "position": [ - 2000, - 1550 - ] - }, - { - "parameters": { - "method": "GET", - "url": "=http://docker-socket-proxy:2375/containers/json?all=true", - "options": {} - }, - "id": "http-get-container-for-stop", - "name": "Get Container For Stop", - "type": "n8n-nodes-base.httpRequest", - "typeVersion": 4.2, - "position": [ - 2220, - 1550 - ] - }, - { - "parameters": { - "jsCode": "// Find container and build stop command\nconst containers = $input.all().map(item => item.json);\nconst prevData = $('Prepare Confirmed Stop').item.json;\nconst containerName = prevData.containerName.toLowerCase();\nconst chatId = prevData.chatId;\nconst messageId = prevData.messageId;\n\n// Function to normalize container names\nfunction normalizeName(name) {\n return name\n .replace(/^\\//, '')\n .replace(/^(linuxserver[-_]|binhex[-_])/i, '')\n .toLowerCase();\n}\n\n// Find the matching container\nconst container = containers.find(c => normalizeName(c.Names[0]) === containerName);\n\nif (!container) {\n return {\n json: {\n error: true,\n chatId,\n messageId,\n text: `Container \"${containerName}\" not found`\n }\n };\n}\n\nconst containerId = container.Id;\n\nreturn {\n json: {\n cmd: `curl -s -o /dev/null -w \"%{http_code}\" --max-time 15 -X POST 'http://docker-socket-proxy:2375/v1.47/containers/${containerId}/stop?t=10'`,\n containerId,\n containerName: normalizeName(container.Names[0]),\n chatId,\n messageId\n }\n};" - }, - "id": "code-build-confirmed-stop-cmd", - "name": "Build Confirmed Stop Command", - "type": "n8n-nodes-base.code", - "typeVersion": 2, - "position": [ - 2440, - 1550 - ] - }, - { - "parameters": { - "command": "={{ $json.cmd }}", - "options": {} - }, - "id": "exec-confirmed-stop", - "name": "Execute Confirmed Stop", - "type": "n8n-nodes-base.executeCommand", - "typeVersion": 1, - "position": [ - 2660, - 1550 - ] - }, - { - "parameters": { - "jsCode": "// Build stop completion message (success shows back only, error shows retry + back)\nconst stdout = $input.item.json.stdout;\nconst prevData = $('Build Confirmed Stop Command').item.json;\nconst containerName = prevData.containerName;\nconst chatId = prevData.chatId;\nconst messageId = prevData.messageId;\n\nconst statusCode = parseInt(stdout.trim());\n\n// 204: Success, 304: Already stopped\nconst success = statusCode === 204 || statusCode === 304;\n\nlet text;\nlet keyboard;\n\nif (success) {\n text = `\\u23F9\\uFE0F ${containerName} stopped`;\n // Success: only back button\n keyboard = {\n inline_keyboard: [\n [{ text: '\\u25C0\\uFE0F Back to Containers', callback_data: 'list:0' }]\n ]\n };\n} else {\n text = `\\u274C Failed to stop ${containerName}`;\n // Error: retry and back buttons\n const timestamp = Math.floor(Date.now() / 1000);\n keyboard = {\n inline_keyboard: [\n [{ text: '\\u{1F504} Try Again', callback_data: `confirm:stop:${containerName}:${timestamp}` }],\n [{ text: '\\u25C0\\uFE0F Back to Containers', callback_data: 'list:0' }]\n ]\n };\n}\n\nreturn {\n json: {\n chatId,\n messageId,\n text,\n reply_markup: keyboard\n }\n};" - }, - "id": "code-format-confirmed-stop-result", - "name": "Format Confirmed Stop Result", - "type": "n8n-nodes-base.code", - "typeVersion": 2, - "position": [ - 2880, - 1550 - ] - }, - { - "parameters": { - "method": "POST", - "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/editMessageText", - "sendBody": true, - "specifyBody": "json", - "jsonBody": "={{ JSON.stringify({ chat_id: $json.chatId, message_id: $json.messageId, text: $json.text, parse_mode: 'HTML', reply_markup: $json.reply_markup }) }}", - "options": {} - }, - "id": "http-send-confirmed-stop-result", - "name": "Send Confirmed Stop Result", - "type": "n8n-nodes-base.httpRequest", - "typeVersion": 4.2, - "position": [ - 3100, - 1550 - ], - "credentials": { - "telegramApi": { - "id": "I0xTTiASl7C1NZhJ", - "name": "Telegram account" - } - } - }, - { - "parameters": { - "method": "POST", - "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/answerCallbackQuery", - "sendBody": true, - "specifyBody": "json", - "jsonBody": "={{ JSON.stringify({ callback_query_id: $json.queryId }) }}", - "options": {} - }, - "id": "http-answer-cancel-confirm-callback", - "name": "Answer Cancel Confirm Callback", - "type": "n8n-nodes-base.httpRequest", - "typeVersion": 4.2, - "position": [ - 1340, - 1800 - ], - "credentials": { - "telegramApi": { - "id": "I0xTTiASl7C1NZhJ", - "name": "Telegram account" - } - } - }, { "parameters": { "jsCode": "// Cancel confirmation - return to container submenu\nconst data = $(\"Parse Callback Data\").item.json;\nreturn {\n json: {\n containerName: data.containerName,\n chatId: data.chatId,\n messageId: data.messageId\n }\n};" @@ -4076,54 +3728,6 @@ 1200 ] }, - { - "parameters": { - "jsCode": "// Prepare input for container actions sub-workflow from confirmed stop\nconst containers = $input.all().map(item => item.json);\nconst prevData = $('Prepare Confirmed Stop').item.json;\nconst containerName = prevData.containerName.toLowerCase();\nconst chatId = prevData.chatId;\nconst messageId = prevData.messageId;\n\n// Function to normalize container names\nfunction normalizeName(name) {\n return name\n .replace(/^\\//, '')\n .replace(/^(linuxserver[-_]|binhex[-_])/i, '')\n .toLowerCase();\n}\n\n// Find the matching container\nconst container = containers.find(c => normalizeName(c.Names[0]) === containerName);\n\nif (!container) {\n return {\n json: {\n error: true,\n chatId,\n messageId,\n text: 'Container not found'\n }\n };\n}\n\nreturn {\n json: {\n containerId: container.Id,\n containerName: normalizeName(container.Names[0]),\n action: 'stop',\n chatId: chatId,\n messageId: messageId,\n responseMode: 'inline'\n }\n};" - }, - "id": "code-prepare-confirmed-stop-vt9cw9tl", - "name": "Prepare Confirmed Stop Input", - "type": "n8n-nodes-base.code", - "typeVersion": 2, - "position": [ - 2440, - 1650 - ] - }, - { - "parameters": { - "source": "database", - "workflowId": { - "__rl": true, - "mode": "list", - "value": "fYSZS5PkH0VSEaT5" - }, - "mode": "once", - "options": { - "waitForSubWorkflow": true - } - }, - "id": "exec-confirmed-stop-sub-qmm011fk", - "name": "Execute Confirmed Stop Action", - "type": "n8n-nodes-base.executeWorkflow", - "typeVersion": 1.2, - "position": [ - 2660, - 1650 - ] - }, - { - "parameters": { - "jsCode": "// Handle sub-workflow result for confirmed stop path\nconst result = $input.item.json;\nconst success = result.success;\nconst message = result.message;\nconst containerName = result.containerName;\nconst chatId = result.chatId;\nconst messageId = result.messageId;\n\n// Build keyboard based on result\nlet keyboard;\nif (success) {\n // Success: only back button\n keyboard = {\n inline_keyboard: [\n [{ text: '\\u25C0\\uFE0F Back to Containers', callback_data: 'list:0' }]\n ]\n };\n} else {\n // Error: retry and back buttons\n const timestamp = Math.floor(Date.now() / 1000);\n keyboard = {\n inline_keyboard: [\n [{ text: '\\u{1F504} Try Again', callback_data: 'confirm:stop:' + containerName + ':' + timestamp }],\n [{ text: '\\u25C0\\uFE0F Back to Containers', callback_data: 'list:0' }]\n ]\n };\n}\n\nreturn {\n json: {\n chatId,\n messageId,\n text: message,\n reply_markup: keyboard\n }\n};" - }, - "id": "code-handle-confirmed-stop-f2r86fwr", - "name": "Handle Confirmed Stop Result", - "type": "n8n-nodes-base.code", - "typeVersion": 2, - "position": [ - 2880, - 1650 - ] - }, { "parameters": { "jsCode": "// Prepare input for Container Update sub-workflow\nconst data = $('Build Progress Message').item.json;\nconst container = data.container;\n\n// Extract container info\nconst containerId = container.id || container.Id || '';\nconst containerName = container.name || container.Name || '';\n\nreturn {\n json: {\n containerId: containerId,\n containerName: containerName,\n chatId: data.chatId,\n messageId: data.progressMessageId || 0,\n responseMode: \"inline\"\n }\n};" @@ -4806,6 +4410,295 @@ 1780, 1100 ] + }, + { + "parameters": { + "jsCode": "// Prepare input for confirmation sub-workflow\nconst data = $('Parse Callback Data').item.json;\n\n// Determine action based on callback type\nlet action = 'confirm'; // Default\nif (data.isCancelConfirm) {\n action = 'cancel';\n} else if (data.isConfirm && data.expired) {\n action = 'expired';\n} else if (data.isConfirm) {\n action = 'confirm';\n}\n\nreturn {\n json: {\n chatId: data.chatId,\n messageId: data.messageId,\n action: action,\n containerId: data.containerId || '',\n containerName: data.containerName,\n confirmAction: data.confirmAction || '',\n confirmationToken: data.timestamp || '',\n expired: data.expired || false,\n responseMode: 'inline'\n }\n};" + }, + "id": "code-prepare-confirm-input", + "name": "Prepare Confirm Input", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1340, + 1550 + ] + }, + { + "parameters": { + "jsCode": "// Prepare input for showing stop confirmation dialog\nconst data = $('Parse Callback Data').item.json;\n\nreturn {\n json: {\n chatId: data.chatId,\n messageId: data.messageId,\n action: 'show_stop',\n containerId: data.containerId || '',\n containerName: data.containerName,\n responseMode: 'inline'\n }\n};" + }, + "id": "code-prepare-show-stop", + "name": "Prepare Show Stop Input", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1780, + 1350 + ] + }, + { + "parameters": { + "jsCode": "// Prepare input for showing update confirmation dialog\nconst data = $('Parse Callback Data').item.json;\n\nreturn {\n json: {\n chatId: data.chatId,\n messageId: data.messageId,\n action: 'show_update',\n containerId: data.containerId || '',\n containerName: data.containerName,\n responseMode: 'inline'\n }\n};" + }, + "id": "code-prepare-show-update", + "name": "Prepare Show Update Input", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1780, + 1450 + ] + }, + { + "parameters": { + "source": "database", + "workflowId": { + "__rl": true, + "mode": "id", + "value": "TODO_DEPLOY_CONFIRMATION_WORKFLOW" + }, + "mode": "once", + "options": { + "waitForSubWorkflow": true + } + }, + "id": "exec-confirmation-workflow", + "name": "Execute Confirmation", + "type": "n8n-nodes-base.executeWorkflow", + "typeVersion": 1.2, + "position": [ + 2000, + 1500 + ] + }, + { + "parameters": { + "rules": { + "values": [ + { + "id": "show-dialog", + "conditions": { + "options": { + "caseSensitive": true, + "typeValidation": "loose" + }, + "conditions": [ + { + "id": "is-show", + "leftValue": "={{ $json.action }}", + "rightValue": "show_", + "operator": { + "type": "string", + "operation": "startsWith" + } + } + ], + "combinator": "and" + }, + "renameOutput": true, + "outputKey": "show" + }, + { + "id": "confirm-stop-result", + "conditions": { + "options": { + "caseSensitive": true, + "typeValidation": "loose" + }, + "conditions": [ + { + "id": "is-stop-result", + "leftValue": "={{ $json.action }}", + "rightValue": "confirm_stop_result", + "operator": { + "type": "string", + "operation": "equals" + } + } + ], + "combinator": "and" + }, + "renameOutput": true, + "outputKey": "stop_result" + }, + { + "id": "confirm-update", + "conditions": { + "options": { + "caseSensitive": true, + "typeValidation": "loose" + }, + "conditions": [ + { + "id": "is-confirm-update", + "leftValue": "={{ $json.action }}", + "rightValue": "confirm_update", + "operator": { + "type": "string", + "operation": "equals" + } + } + ], + "combinator": "and" + }, + "renameOutput": true, + "outputKey": "confirm_update" + }, + { + "id": "cancel", + "conditions": { + "options": { + "caseSensitive": true, + "typeValidation": "loose" + }, + "conditions": [ + { + "id": "is-cancel", + "leftValue": "={{ $json.action }}", + "rightValue": "cancel", + "operator": { + "type": "string", + "operation": "equals" + } + } + ], + "combinator": "and" + }, + "renameOutput": true, + "outputKey": "cancel" + }, + { + "id": "expired", + "conditions": { + "options": { + "caseSensitive": true, + "typeValidation": "loose" + }, + "conditions": [ + { + "id": "is-expired", + "leftValue": "={{ $json.action }}", + "rightValue": "expired", + "operator": { + "type": "string", + "operation": "equals" + } + } + ], + "combinator": "and" + }, + "renameOutput": true, + "outputKey": "expired" + } + ] + }, + "options": { + "fallbackOutput": "none" + } + }, + "id": "switch-confirm-result", + "name": "Route Confirmation Result", + "type": "n8n-nodes-base.switch", + "typeVersion": 3.2, + "position": [ + 2220, + 1500 + ] + }, + { + "parameters": { + "operation": "editMessageText", + "messageId": "={{ $json.messageId }}", + "chatId": "={{ $json.chatId }}", + "text": "={{ $json.text }}", + "replyMarkup": "inlineKeyboard", + "inlineKeyboard": "={{ JSON.stringify($json.reply_markup) }}", + "additionalFields": { + "parse_mode": "HTML" + } + }, + "id": "http-send-confirm-dialog", + "name": "Send Confirmation Dialog", + "type": "n8n-nodes-base.telegram", + "typeVersion": 1.2, + "position": [ + 2440, + 1400 + ], + "credentials": { + "telegramApi": { + "id": "I0xTTiASl7C1NZhJ", + "name": "Telegram account" + } + } + }, + { + "parameters": { + "operation": "editMessageText", + "messageId": "={{ $json.messageId }}", + "chatId": "={{ $json.chatId }}", + "text": "={{ $json.text }}", + "replyMarkup": "inlineKeyboard", + "inlineKeyboard": "={{ JSON.stringify($json.reply_markup) }}", + "additionalFields": { + "parse_mode": "HTML" + } + }, + "id": "http-send-stop-result", + "name": "Send Stop Result", + "type": "n8n-nodes-base.telegram", + "typeVersion": 1.2, + "position": [ + 2440, + 1500 + ], + "credentials": { + "telegramApi": { + "id": "I0xTTiASl7C1NZhJ", + "name": "Telegram account" + } + } + }, + { + "parameters": { + "operation": "editMessageText", + "messageId": "={{ $json.messageId }}", + "chatId": "={{ $json.chatId }}", + "text": "={{ $json.text }}", + "replyMarkup": "inlineKeyboard", + "inlineKeyboard": "={{ JSON.stringify($json.reply_markup) }}", + "additionalFields": { + "parse_mode": "HTML" + } + }, + "id": "http-send-expired-msg", + "name": "Send Expired Message", + "type": "n8n-nodes-base.telegram", + "typeVersion": 1.2, + "position": [ + 2440, + 1700 + ], + "credentials": { + "telegramApi": { + "id": "I0xTTiASl7C1NZhJ", + "name": "Telegram account" + } + } + }, + { + "parameters": { + "jsCode": "// Prepare cancel return data from confirmation result\nconst result = $input.item.json;\n\nreturn {\n json: {\n containerName: result.containerName,\n chatId: result.chatId,\n messageId: result.messageId\n }\n};" + }, + "id": "code-prepare-cancel-from-confirm", + "name": "Prepare Cancel From Confirm", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2440, + 1600 + ] } ], "connections": { @@ -4929,23 +4822,17 @@ "index": 0 } ], + [], [ { - "node": "Answer Confirm Callback", + "node": "Prepare Confirm Input", "type": "main", "index": 0 } ], [ { - "node": "Answer Cancel Confirm Callback", - "type": "main", - "index": 0 - } - ], - [ - { - "node": "Answer Batch Stop Confirm", + "node": "Prepare Confirm Input", "type": "main", "index": 0 } @@ -5660,14 +5547,14 @@ ], [ { - "node": "Build Stop Confirmation", + "node": "Prepare Show Stop Input", "type": "main", "index": 0 } ], [ { - "node": "Build Update Confirmation", + "node": "Prepare Show Update Input", "type": "main", "index": 0 } @@ -5736,152 +5623,6 @@ ] ] }, - "Build Stop Confirmation": { - "main": [ - [ - { - "node": "Send Stop Confirmation", - "type": "main", - "index": 0 - } - ] - ] - }, - "Build Update Confirmation": { - "main": [ - [ - { - "node": "Send Update Confirmation", - "type": "main", - "index": 0 - } - ] - ] - }, - "Answer Confirm Callback": { - "main": [ - [ - { - "node": "Check Confirm Expired", - "type": "main", - "index": 0 - } - ] - ] - }, - "Check Confirm Expired": { - "main": [ - [ - { - "node": "Handle Confirm Expired", - "type": "main", - "index": 0 - } - ], - [ - { - "node": "Route Confirm Action", - "type": "main", - "index": 0 - } - ] - ] - }, - "Handle Confirm Expired": { - "main": [ - [ - { - "node": "Send Expired Confirm", - "type": "main", - "index": 0 - } - ] - ] - }, - "Route Confirm Action": { - "main": [ - [ - { - "node": "Prepare Confirmed Stop", - "type": "main", - "index": 0 - } - ], - [ - { - "node": "Prepare Callback Update Input", - "type": "main", - "index": 0 - } - ] - ] - }, - "Prepare Confirmed Stop": { - "main": [ - [ - { - "node": "Get Container For Stop", - "type": "main", - "index": 0 - } - ] - ] - }, - "Get Container For Stop": { - "main": [ - [ - { - "node": "Prepare Confirmed Stop Input", - "type": "main", - "index": 0 - } - ] - ] - }, - "Build Confirmed Stop Command": { - "main": [ - [ - { - "node": "Execute Confirmed Stop", - "type": "main", - "index": 0 - } - ] - ] - }, - "Execute Confirmed Stop": { - "main": [ - [ - { - "node": "Format Confirmed Stop Result", - "type": "main", - "index": 0 - } - ] - ] - }, - "Format Confirmed Stop Result": { - "main": [ - [ - { - "node": "Send Confirmed Stop Result", - "type": "main", - "index": 0 - } - ] - ] - }, - "Answer Cancel Confirm Callback": { - "main": [ - [ - { - "node": "Prepare Cancel Return", - "type": "main", - "index": 0 - } - ] - ] - }, "Prepare Cancel Return": { "main": [ [ @@ -6331,39 +6072,6 @@ ] ] }, - "Prepare Confirmed Stop Input": { - "main": [ - [ - { - "node": "Execute Confirmed Stop Action", - "type": "main", - "index": 0 - } - ] - ] - }, - "Execute Confirmed Stop Action": { - "main": [ - [ - { - "node": "Handle Confirmed Stop Result", - "type": "main", - "index": 0 - } - ] - ] - }, - "Handle Confirmed Stop Result": { - "main": [ - [ - { - "node": "Send Confirmed Stop Result", - "type": "main", - "index": 0 - } - ] - ] - }, "Prepare Batch Update Input": { "main": [ [ @@ -6602,33 +6310,7 @@ ] }, "Route Status Result": { - "list": [ - [ - { - "node": "Send Container List", - "type": "main", - "index": 0 - } - ] - ], - "status_direct": [ - [ - { - "node": "Send Container Submenu Direct", - "type": "main", - "index": 0 - } - ] - ], - "error": [ - [ - { - "node": "Send Container List", - "type": "main", - "index": 0 - } - ] - ] + "main": [] }, "Answer Select Callback": { "main": [ @@ -6728,6 +6410,100 @@ } ] ] + }, + "Prepare Confirm Input": { + "main": [ + [ + { + "node": "Execute Confirmation", + "type": "main", + "index": 0 + } + ] + ] + }, + "Prepare Show Stop Input": { + "main": [ + [ + { + "node": "Execute Confirmation", + "type": "main", + "index": 0 + } + ] + ] + }, + "Prepare Show Update Input": { + "main": [ + [ + { + "node": "Execute Confirmation", + "type": "main", + "index": 0 + } + ] + ] + }, + "Execute Confirmation": { + "main": [ + [ + { + "node": "Route Confirmation Result", + "type": "main", + "index": 0 + } + ] + ] + }, + "Route Confirmation Result": { + "main": [ + [ + { + "node": "Send Confirmation Dialog", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Send Stop Result", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Prepare Callback Update Input", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Prepare Cancel From Confirm", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Send Expired Message", + "type": "main", + "index": 0 + } + ] + ] + }, + "Prepare Cancel From Confirm": { + "main": [ + [ + { + "node": "Get Container For Cancel", + "type": "main", + "index": 0 + } + ] + ] } }, "pinData": {},