{ "name": "Container Update", "nodes": [ { "parameters": { "inputSource": "passthrough", "schema": { "schemaType": "fromFields", "fields": [ { "fieldName": "containerId", "fieldType": "string" }, { "fieldName": "containerName", "fieldType": "string" }, { "fieldName": "chatId", "fieldType": "number" }, { "fieldName": "messageId", "fieldType": "number" }, { "fieldName": "responseMode", "fieldType": "string" }, { "fieldName": "correlationId", "fieldType": "string" } ] } }, "id": "sub-trigger", "name": "When executed by another workflow", "type": "n8n-nodes-base.executeWorkflowTrigger", "typeVersion": 1.1, "position": [ 240, 300 ] }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "typeValidation": "loose" }, "conditions": [ { "id": "has-container-id", "leftValue": "={{ $json.containerId }}", "rightValue": "", "operator": { "type": "string", "operation": "notEquals" } } ], "combinator": "and" } }, "id": "if-has-id", "name": "Has Container ID?", "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 400, 300 ] }, { "parameters": { "method": "POST", "url": "={{ $env.UNRAID_HOST }}/graphql", "authentication": "none", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "application/json" }, { "name": "x-api-key", "value": "={{ $env.UNRAID_API_KEY }}" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\"query\": \"query { docker { containers { id names state image imageId } } }\"}", "options": { "timeout": 15000 } }, "id": "http-query-containers", "name": "Query All Containers", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 560, 400 ], "onError": "continueRegularOutput" }, { "parameters": { "jsCode": "// GraphQL Response Normalizer - Transform Unraid GraphQL to Docker API contract\n// Input: $input.item.json = raw GraphQL response\n// Output: Array of normalized containers\n\nconst response = $input.item.json;\n\n// Validation: Check for GraphQL errors\nif (response.errors && response.errors.length > 0) {\n const messages = response.errors.map(e => e.message).join('; ');\n throw new Error(`GraphQL error: ${messages}`);\n}\n\n// Validation: Check response structure\nif (!response.data?.docker?.containers) {\n throw new Error('Invalid GraphQL response structure: missing data.docker.containers');\n}\n\n// State mapping: Unraid UPPERCASE -> Docker lowercase\nconst stateMap = {\n 'RUNNING': 'running',\n 'STOPPED': 'exited', // Docker convention: stopped = exited\n 'PAUSED': 'paused'\n};\n\nfunction normalizeState(unraidState) {\n return stateMap[unraidState] || unraidState.toLowerCase();\n}\n\n// Transform each container\nconst containers = response.data.docker.containers;\nconst normalized = containers.map(container => {\n const dockerState = normalizeState(container.state);\n \n return {\n // Core fields matching Docker API contract\n Id: container.id, // Keep full PrefixedID (registry handles translation)\n Names: container.names, // Already has '/' prefix (Phase 14 verified)\n State: dockerState, // Normalized lowercase state\n Status: dockerState, // Docker has separate Status field\n Image: '', // Not available in basic query\n \n // Debug field: preserve original Unraid ID\n _unraidId: container.id\n };\n});\n\n// Return as array of items (n8n multi-item output format)\nreturn normalized.map(container => ({ json: container }));\n" }, "id": "code-normalize-response", "name": "Normalize GraphQL Response", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 720, 400 ] }, { "id": "code-update-registry", "name": "Update Container ID Registry", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 880, 400 ], "parameters": { "mode": "runOnceForAllItems", "jsCode": "// Container ID Registry - Update action only\nconst registry = $getWorkflowStaticData('global');\nif (!registry._containerIdMap) {\n registry._containerIdMap = JSON.stringify({});\n}\n\nconst containers = $input.all().map(item => item.json);\nconst containerMap = JSON.parse(registry._containerIdMap);\n\n// Update map from normalized containers\nfor (const container of containers) {\n const name = (container.Names?.[0] || '').replace(/^\\//, '').toLowerCase();\n if (name && container.Id) {\n containerMap[name] = {\n name: name,\n unraidId: container.Id,\n timestamp: Date.now()\n };\n }\n}\n\nregistry._containerIdMap = JSON.stringify(containerMap);\nregistry._lastRefresh = Date.now();\n\n// Pass through all containers\nreturn containers.map(c => ({ json: c }));\n" } }, { "parameters": { "jsCode": "// Find container by name and resolve ID\nconst triggerData = $('When executed by another workflow').item.json;\nconst containerName = triggerData.containerName;\nconst containers = $input.all();\n\n// Normalize function to strip leading slash\nconst normalizeName = (name) => name.replace(/^\\//, '').toLowerCase();\nconst searchName = normalizeName(containerName);\n\n// Find matching container\nlet matched = null;\nfor (const item of containers) {\n const c = item.json;\n if (c.Names && c.Names.length > 0) {\n const cName = normalizeName(c.Names[0]);\n if (cName === searchName || cName.includes(searchName)) {\n matched = c;\n break;\n }\n }\n}\n\nif (!matched) {\n throw new Error(`Container '${containerName}' not found`);\n}\n\nreturn {\n json: {\n ...triggerData,\n containerId: matched.Id,\n unraidId: matched.Id, // Full PrefixedID for GraphQL mutation\n currentImageId: matched.imageId || '', // For later comparison\n currentImage: matched.image || ''\n }\n};\n" }, "id": "code-resolve-id", "name": "Resolve Container ID", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1040, 400 ] }, { "parameters": { "method": "POST", "url": "={{ $env.UNRAID_HOST }}/graphql", "authentication": "none", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "application/json" }, { "name": "x-api-key", "value": "={{ $env.UNRAID_API_KEY }}" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ {\"query\": \"query { docker { containers(filter: { id: \\\"\" + $json.containerId + \"\\\" }) { id names state image imageId } } }\"} }}", "options": { "timeout": 15000 } }, "id": "http-query-single", "name": "Query Single Container", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 560, 300 ], "onError": "continueRegularOutput" }, { "parameters": { "jsCode": "// GraphQL Response Normalizer - Transform Unraid GraphQL to Docker API contract\n// Input: $input.item.json = raw GraphQL response\n// Output: Array of normalized containers\n\nconst response = $input.item.json;\n\n// Validation: Check for GraphQL errors\nif (response.errors && response.errors.length > 0) {\n const messages = response.errors.map(e => e.message).join('; ');\n throw new Error(`GraphQL error: ${messages}`);\n}\n\n// Validation: Check response structure\nif (!response.data?.docker?.containers) {\n throw new Error('Invalid GraphQL response structure: missing data.docker.containers');\n}\n\n// State mapping: Unraid UPPERCASE -> Docker lowercase\nconst stateMap = {\n 'RUNNING': 'running',\n 'STOPPED': 'exited', // Docker convention: stopped = exited\n 'PAUSED': 'paused'\n};\n\nfunction normalizeState(unraidState) {\n return stateMap[unraidState] || unraidState.toLowerCase();\n}\n\n// Transform each container\nconst containers = response.data.docker.containers;\nconst normalized = containers.map(container => {\n const dockerState = normalizeState(container.state);\n \n return {\n // Core fields matching Docker API contract\n Id: container.id, // Keep full PrefixedID (registry handles translation)\n Names: container.names, // Already has '/' prefix (Phase 14 verified)\n State: dockerState, // Normalized lowercase state\n Status: dockerState, // Docker has separate Status field\n Image: '', // Not available in basic query\n \n // Debug field: preserve original Unraid ID\n _unraidId: container.id\n };\n});\n\n// Return as array of items (n8n multi-item output format)\nreturn normalized.map(container => ({ json: container }));\n" }, "id": "code-normalize-single", "name": "Normalize Single Container", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 720, 300 ] }, { "parameters": { "jsCode": "// Capture pre-update state from input\nconst data = $input.item.json;\nconst triggerData = $('When executed by another workflow').item.json;\n\n// Check if we have container data already (from Resolve path) or need to extract (from direct ID path)\nlet unraidId, containerName, currentImageId, currentImage;\n\nif (data.unraidId) {\n // From Resolve Container ID path\n unraidId = data.unraidId;\n containerName = data.containerName;\n currentImageId = data.currentImageId;\n currentImage = data.currentImage;\n} else if (data.Id) {\n // From Query Single Container path (normalized)\n unraidId = data.Id;\n containerName = (data.Names?.[0] || '').replace(/^\\//, '');\n currentImageId = data.imageId || '';\n currentImage = data.image || '';\n} else {\n throw new Error('No container data found');\n}\n\nreturn {\n json: {\n unraidId,\n containerName,\n currentImageId,\n currentImage,\n chatId: triggerData.chatId,\n messageId: triggerData.messageId,\n responseMode: triggerData.responseMode,\n correlationId: triggerData.correlationId || ''\n }\n};\n" }, "id": "code-capture-state", "name": "Capture Pre-Update State", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 920, 300 ] }, { "parameters": { "jsCode": "// Build GraphQL updateContainer mutation\nconst data = $input.item.json;\nreturn {\n json: {\n ...data,\n query: `mutation { docker { updateContainer(id: \"${data.unraidId}\") { id state image imageId } } }`\n }\n};\n" }, "id": "code-build-mutation", "name": "Build Update Mutation", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1120, 300 ] }, { "parameters": { "method": "POST", "url": "={{ $env.UNRAID_HOST }}/graphql", "authentication": "none", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "application/json" }, { "name": "x-api-key", "value": "={{ $env.UNRAID_API_KEY }}" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ {\"query\": $json.query} }}", "options": { "timeout": 60000 } }, "id": "http-update-container", "name": "Update Container", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1320, 300 ], "onError": "continueRegularOutput" }, { "parameters": { "jsCode": "// Handle updateContainer mutation response\nconst response = $input.item.json;\nconst prevData = $('Capture Pre-Update State').item.json;\n\n// Check for GraphQL errors\nif (response.errors) {\n const error = response.errors[0];\n return {\n json: {\n success: false,\n error: true,\n errorMessage: error.message || 'Update failed',\n ...prevData\n }\n };\n}\n\n// Extract updated container from response\nconst updated = response.data?.docker?.updateContainer;\nif (!updated) {\n return {\n json: {\n success: false,\n error: true,\n errorMessage: 'No response from update mutation',\n ...prevData\n }\n };\n}\n\n// Compare imageId to determine if update happened\nconst newImageId = updated.imageId || '';\nconst oldImageId = prevData.currentImageId || '';\nconst wasUpdated = (newImageId !== oldImageId);\n\nreturn {\n json: {\n success: true,\n needsUpdate: wasUpdated,\n updated: wasUpdated,\n containerName: prevData.containerName,\n currentVersion: prevData.currentImage,\n newVersion: updated.image,\n currentImageId: oldImageId,\n newImageId: newImageId,\n chatId: prevData.chatId,\n messageId: prevData.messageId,\n responseMode: prevData.responseMode,\n correlationId: prevData.correlationId\n }\n};\n" }, "id": "code-handle-response", "name": "Handle Update Response", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1520, 300 ] }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" }, "conditions": [ { "id": "is-success", "leftValue": "={{ $json.error }}", "rightValue": true, "operator": { "type": "boolean", "operation": "notEquals" } } ], "combinator": "and" }, "options": {} }, "id": "if-update-success", "name": "Check Update Success", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [ 1720, 300 ] }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" }, "conditions": [ { "id": "was-updated", "leftValue": "={{ $json.needsUpdate }}", "rightValue": true, "operator": { "type": "boolean", "operation": "equals" } } ], "combinator": "and" }, "options": {} }, "id": "if-was-updated", "name": "Check If Updated", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [ 1920, 200 ] }, { "parameters": { "jsCode": "// Format update success result\nconst data = $('Handle Update Response').item.json;\nconst containerName = data.containerName;\nconst currentVersion = data.currentVersion;\nconst newVersion = data.newVersion;\n\nconst message = `${containerName} updated: ${currentVersion} \\u2192 ${newVersion}`;\n\nreturn {\n json: {\n success: true,\n updated: true,\n message,\n oldDigest: currentVersion,\n newDigest: newVersion,\n chatId: data.chatId,\n messageId: data.messageId,\n responseMode: data.responseMode,\n containerName: containerName,\n correlationId: data.correlationId || ''\n }\n};\n" }, "id": "code-format-success", "name": "Format Update Success", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1960, 200 ] }, { "parameters": { "rules": { "values": [ { "id": "is-inline", "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" }, "conditions": [ { "id": "inline-check", "leftValue": "={{ $json.responseMode }}", "rightValue": "inline", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "and" }, "outputKey": "inline" }, { "id": "is-batch", "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" }, "conditions": [ { "id": "batch-check", "leftValue": "={{ $json.responseMode }}", "rightValue": "batch", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "and" }, "outputKey": "batch" } ] }, "options": { "fallbackOutput": "extra" } }, "id": "if-response-mode-success", "name": "Check Response Mode (Success)", "type": "n8n-nodes-base.switch", "typeVersion": 3.2, "position": [ 2180, 200 ] }, { "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: '\\u2705 ' + $json.message, parse_mode: 'HTML', reply_markup: { inline_keyboard: [[{ text: '\\u25C0\\uFE0F Back to Containers', callback_data: 'list:0' }]] } }) }}", "options": {} }, "id": "http-send-inline-success", "name": "Send Inline Success", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 2400, 100 ] }, { "parameters": { "resource": "message", "operation": "sendMessage", "chatId": "={{ $json.chatId }}", "text": "={{ $json.message }}", "additionalFields": { "parse_mode": "HTML" } }, "id": "telegram-send-text-success", "name": "Send Text Success", "type": "n8n-nodes-base.telegram", "typeVersion": 1.2, "position": [ 2400, 300 ], "credentials": { "telegramApi": { "id": "I0xTTiASl7C1NZhJ", "name": "Telegram account" } } }, { "parameters": { "jsCode": "// Return final success result\nconst data = $('Format Update Success').item.json;\nreturn {\n json: {\n success: true,\n updated: true,\n message: data.message,\n oldDigest: data.oldDigest,\n newDigest: data.newDigest,\n correlationId: data.correlationId || ''\n }\n};" }, "id": "code-return-success", "name": "Return Success", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2620, 200 ] }, { "parameters": { "jsCode": "// Format 'already up to date' result\nconst data = $('Handle Update Response').item.json;\nconst containerName = data.containerName;\n\nconst message = `${containerName} is already up to date`;\n\nreturn {\n json: {\n success: true,\n updated: false,\n message,\n chatId: data.chatId,\n messageId: data.messageId,\n responseMode: data.responseMode,\n containerName: containerName,\n correlationId: data.correlationId || ''\n }\n};\n" }, "id": "code-format-no-update", "name": "Format No Update Needed", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1960, 400 ] }, { "parameters": { "rules": { "values": [ { "id": "is-inline-no-update", "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" }, "conditions": [ { "id": "inline-check", "leftValue": "={{ $json.responseMode }}", "rightValue": "inline", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "and" }, "outputKey": "inline" }, { "id": "is-batch-no-update", "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" }, "conditions": [ { "id": "batch-check", "leftValue": "={{ $json.responseMode }}", "rightValue": "batch", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "and" }, "outputKey": "batch" } ] }, "options": { "fallbackOutput": "extra" } }, "id": "if-response-mode-no-update", "name": "Check Response Mode (No Update)", "type": "n8n-nodes-base.switch", "typeVersion": 3.2, "position": [ 2180, 400 ] }, { "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: '\\u2705 ' + $json.message, parse_mode: 'HTML', reply_markup: { inline_keyboard: [[{ text: '\\u25C0\\uFE0F Back to Containers', callback_data: 'list:0' }]] } }) }}", "options": {} }, "id": "http-send-inline-no-update", "name": "Send Inline No Update", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 2400, 400 ] }, { "parameters": { "resource": "message", "operation": "sendMessage", "chatId": "={{ $json.chatId }}", "text": "={{ $json.message }}", "additionalFields": { "parse_mode": "HTML" } }, "id": "telegram-send-text-no-update", "name": "Send Text No Update", "type": "n8n-nodes-base.telegram", "typeVersion": 1.2, "position": [ 2400, 500 ], "credentials": { "telegramApi": { "id": "I0xTTiASl7C1NZhJ", "name": "Telegram account" } } }, { "parameters": { "jsCode": "// Return no update result\nconst data = $('Format No Update Needed').item.json;\nreturn {\n json: {\n success: true,\n updated: false,\n message: data.message,\n correlationId: data.correlationId || ''\n }\n};" }, "id": "code-return-no-update", "name": "Return No Update", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2620, 400 ] }, { "parameters": { "jsCode": "// Format update error result\nconst data = $('Handle Update Response').item.json;\nconst containerName = data.containerName;\nconst errorMessage = data.errorMessage;\n\nconst message = `Failed to update ${containerName}: ${errorMessage}`;\n\nreturn {\n json: {\n success: false,\n updated: false,\n message,\n error: {\n workflow: 'n8n-update',\n node: 'Update Container',\n message: errorMessage,\n httpCode: null,\n rawResponse: errorMessage\n },\n correlationId: data.correlationId || '',\n chatId: data.chatId,\n messageId: data.messageId,\n responseMode: data.responseMode,\n containerName: containerName\n }\n};\n" }, "id": "code-format-pull-error", "name": "Format Update Error", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1540, 500 ] }, { "parameters": { "rules": { "values": [ { "id": "is-inline-error", "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" }, "conditions": [ { "id": "inline-check", "leftValue": "={{ $json.responseMode }}", "rightValue": "inline", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "and" }, "outputKey": "inline" }, { "id": "is-batch-error", "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" }, "conditions": [ { "id": "batch-check", "leftValue": "={{ $json.responseMode }}", "rightValue": "batch", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "and" }, "outputKey": "batch" } ] }, "options": { "fallbackOutput": "extra" } }, "id": "if-response-mode-error", "name": "Check Response Mode (Error)", "type": "n8n-nodes-base.switch", "typeVersion": 3.2, "position": [ 1760, 500 ] }, { "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: '\\u274C ' + $json.message, parse_mode: 'HTML', reply_markup: { inline_keyboard: [[{ text: '\\u25C0\\uFE0F Back to Containers', callback_data: 'list:0' }]] } }) }}", "options": {} }, "id": "http-send-inline-error", "name": "Send Inline Error", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1980, 500 ] }, { "parameters": { "resource": "message", "operation": "sendMessage", "chatId": "={{ $json.chatId }}", "text": "={{ $json.message }}", "additionalFields": { "parse_mode": "HTML" } }, "id": "telegram-send-text-error", "name": "Send Text Error", "type": "n8n-nodes-base.telegram", "typeVersion": 1.2, "position": [ 1980, 600 ], "credentials": { "telegramApi": { "id": "I0xTTiASl7C1NZhJ", "name": "Telegram account" } } }, { "parameters": { "jsCode": "// Return error result\nconst data = $('Format Pull Error').item.json;\nreturn {\n json: {\n success: false,\n updated: false,\n message: data.message\n }\n};" }, "id": "code-return-error", "name": "Return Error", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2200, 500 ] } ], "connections": { "When executed by another workflow": { "main": [ [ { "node": "Has Container ID?", "type": "main", "index": 0 } ] ] }, "Has Container ID?": { "main": [ [ { "node": "Query Single Container", "type": "main", "index": 0 } ], [ { "node": "Query All Containers", "type": "main", "index": 0 } ] ] }, "Query Single Container": { "main": [ [ { "node": "Normalize Single Container", "type": "main", "index": 0 } ] ] }, "Normalize Single Container": { "main": [ [ { "node": "Capture Pre-Update State", "type": "main", "index": 0 } ] ] }, "Query All Containers": { "main": [ [ { "node": "Normalize GraphQL Response", "type": "main", "index": 0 } ] ] }, "Normalize GraphQL Response": { "main": [ [ { "node": "Update Container ID Registry", "type": "main", "index": 0 } ] ] }, "Update Container ID Registry": { "main": [ [ { "node": "Resolve Container ID", "type": "main", "index": 0 } ] ] }, "Resolve Container ID": { "main": [ [ { "node": "Capture Pre-Update State", "type": "main", "index": 0 } ] ] }, "Capture Pre-Update State": { "main": [ [ { "node": "Build Update Mutation", "type": "main", "index": 0 } ] ] }, "Build Update Mutation": { "main": [ [ { "node": "Update Container", "type": "main", "index": 0 } ] ] }, "Update Container": { "main": [ [ { "node": "Handle Update Response", "type": "main", "index": 0 } ] ] }, "Handle Update Response": { "main": [ [ { "node": "Check Update Success", "type": "main", "index": 0 } ] ] }, "Check If Updated": { "main": [ [ { "node": "Format Update Success", "type": "main", "index": 0 } ], [ { "node": "Format No Update Needed", "type": "main", "index": 0 } ] ] }, "Format Update Success": { "main": [ [ { "node": "Check Response Mode (Success)", "type": "main", "index": 0 } ] ] }, "Check Response Mode (Success)": { "main": [ [ { "node": "Send Inline Success", "type": "main", "index": 0 } ], [ { "node": "Return Success", "type": "main", "index": 0 } ], [ { "node": "Send Text Success", "type": "main", "index": 0 } ] ] }, "Send Inline Success": { "main": [ [ { "node": "Return Success", "type": "main", "index": 0 } ] ] }, "Send Text Success": { "main": [ [ { "node": "Return Success", "type": "main", "index": 0 } ] ] }, "Format No Update Needed": { "main": [ [ { "node": "Check Response Mode (No Update)", "type": "main", "index": 0 } ] ] }, "Check Response Mode (No Update)": { "main": [ [ { "node": "Send Inline No Update", "type": "main", "index": 0 } ], [ { "node": "Return No Update", "type": "main", "index": 0 } ], [ { "node": "Send Text No Update", "type": "main", "index": 0 } ] ] }, "Send Inline No Update": { "main": [ [ { "node": "Return No Update", "type": "main", "index": 0 } ] ] }, "Send Text No Update": { "main": [ [ { "node": "Return No Update", "type": "main", "index": 0 } ] ] }, "Format Update Error": { "main": [ [ { "node": "Check Response Mode (Error)", "type": "main", "index": 0 } ] ] }, "Check Response Mode (Error)": { "main": [ [ { "node": "Send Inline Error", "type": "main", "index": 0 } ], [ { "node": "Return Error", "type": "main", "index": 0 } ], [ { "node": "Send Text Error", "type": "main", "index": 0 } ] ] }, "Send Inline Error": { "main": [ [ { "node": "Return Error", "type": "main", "index": 0 } ] ] }, "Send Text Error": { "main": [ [ { "node": "Return Error", "type": "main", "index": 0 } ] ] }, "Check Update Success": { "main": [ [ { "node": "Check If Updated", "type": "main", "index": 0 } ], [ { "node": "Format Update Error", "type": "main", "index": 0 } ] ] } }, "settings": { "executionOrder": "v1" } }