AutomationFlowsSlack & Telegram › N8n Complete Final

N8n Complete Final

N8N Complete Final. Uses telegramTrigger, dataTable, telegram, mqtt. Event-driven trigger; 58 nodes.

Event trigger★★★★★ complexity58 nodesTelegram TriggerData TableTelegramMqttMqtt TriggerHTTP Request
Slack & Telegram Trigger: Event Nodes: 58 Complexity: ★★★★★ Added:

This workflow follows the Datatable → HTTP Request 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
{
  "nodes": [
    {
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "id": "478bb0b5-6c0e-43a3-85a3-ba60bb4f6b8a",
      "name": "Telegram Command",
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.2,
      "position": [
        -2320,
        11824
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "leftValue": "={{ $json.message.from.id }}",
              "rightValue": 123456789,
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "id": "4e8fc8f8-e228-4719-98ad-f16db0a1c9e3"
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "bed2ef3d-ff94-4013-a44c-b31eeff51513",
      "name": "Is Owner?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -2112,
        11824
      ]
    },
    {
      "parameters": {
        "jsCode": "const text = $input.item.json.message.text || \"\";\n// Regex matches /command target extra (ignores spaces)\nconst match = text.match(/^\\/([a-zA-Z0-9_]+)(?:\\s+(.*))?/);\n\nlet command = \"unknown\";\nlet target = \"\";\nlet extra = \"\";\n\nif (match) {\n    command = match[1].toLowerCase();\n    const args = (match[2] || \"\").trim();\n    if (args) {\n        const parts = args.split(/\\s+/);\n        target = parts[0];\n        \n        // Normalize MAC address to uppercase to prevent DB duplicates\n        if (/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/i.test(target)) {\n            target = target.toUpperCase();\n        }\n        \n        extra = parts.slice(1).join(\" \");\n    }\n}\n\nreturn [{ json: { command, target, extra, original_text: text } }];"
      },
      "id": "d2931bbb-ca28-426d-8fc5-dbc8de5536ec",
      "name": "Parse Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1888,
        11824
      ]
    },
    {
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "network_devices"
        },
        "filters": {
          "conditions": []
        },
        "returnAll": true
      },
      "id": "c7f029fe-7466-4af9-9fb4-ea1c72aafc05",
      "name": "Get Devices (Resolver)",
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        -1360,
        11200
      ]
    },
    {
      "parameters": {
        "jsCode": "const parseData = $node[\"Parse Message\"].json;\nconst target = parseData.target;\nconst command = parseData.command;\n\nif (!target) {\n    return [{ json: { resolved: false, reason: `\u26a0\ufe0f Please specify a target for /${command}.\\n\\nExample: /${command} MyPC` } }];\n}\n\nconst devices = $input.all().map(i => i.json);\n\n// Regex patterns for raw MAC and IP detection\nconst isMac = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/i.test(target);\nconst isIp = /^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$/.test(target);\n\nlet mac = isMac ? target : null;\nlet ip = isIp ? target : null;\n\nif (isMac) {\n    // Try to find the corresponding IP in the DB\n    const found = devices.find(d => d.mac && d.mac.toLowerCase() === target.toLowerCase());\n    if (found && found.ip) ip = found.ip;\n} else if (isIp) {\n    // Try to find the corresponding MAC in the DB\n    const found = devices.find(d => d.ip === target);\n    if (found && found.mac) mac = found.mac;\n} else {\n    // It's an alias, search the database\n    const found = devices.find(d => d.name && d.name.toLowerCase() === target.toLowerCase());\n    if (found) {\n        mac = found.mac;\n        ip = found.ip;\n    } else {\n        return [{ json: { resolved: false, reason: `\u274c Target '<b>${target}</b>' not found.\\nPlease provide a valid MAC, IP, or saved Alias.` } }];\n    }\n}\n\n// Final Command Validations\nif (command === \"wake\" && !mac) {\n    return [{ json: { resolved: false, reason: `\u274c Could not resolve a MAC address for '<b>${target}</b>'. Wake-on-LAN requires a MAC.\\n\\n<i>Tip: Check if the device is correctly saved via /list</i>` } }];\n}\nif (command === \"ping\" && !ip) {\n    return [{ json: { resolved: false, reason: `\u274c Could not resolve an IP address for '<b>${target}</b>'. Ping requires an IP.\\n\\n<i>Tip: Try running /scan while the device is awake so the bot can learn its IP!</i>` } }];\n}\n\nreturn [{ json: { resolved: true, mac: mac, ip: ip, target: target, command: command } }];"
      },
      "id": "dc95bfb1-c491-42ce-8eb5-ddd3a75e1e3a",
      "name": "Resolve Target",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1136,
        11200
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "leftValue": "={{ $json.resolved }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "id": "d6da4a90-bc26-4a84-8a7f-e9f6a4318dd6"
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "2684bbe9-233d-4d0a-9a0b-6467c9273172",
      "name": "Is Resolved?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -912,
        11200
      ]
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "={{ $json.reason }}",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "a7d66ee1-367a-4d50-a572-69bd65b143c3",
      "name": "Resolution Error Reply",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -688,
        11328
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "topic": "home/wol/command",
        "sendInputData": false,
        "message": "={{ JSON.stringify({ \"cmd\": \"wake\", \"mac\": $json.mac }) }}",
        "options": {}
      },
      "id": "c652aa86-3a6e-4884-b701-3b02c79d2845",
      "name": "MQTT Wake",
      "type": "n8n-nodes-base.mqtt",
      "typeVersion": 1,
      "position": [
        -400,
        10944
      ],
      "credentials": {
        "mqtt": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "topic": "home/wol/command",
        "sendInputData": false,
        "message": "={{ JSON.stringify({ \"cmd\": \"ping\", \"ip\": $json.ip }) }}",
        "options": {}
      },
      "id": "d1b4e7aa-763b-4f85-a5fc-98d3f492af1b",
      "name": "MQTT Ping",
      "type": "n8n-nodes-base.mqtt",
      "typeVersion": 1,
      "position": [
        -400,
        11104
      ],
      "credentials": {
        "mqtt": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\u2705 <b>Magic Packet Sent</b>\n\u2514 Target: <code>{{ $json.mac }}</code>",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "5eb6e25a-35ef-4b52-8298-98bf51d05d22",
      "name": "Wake Success",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -176,
        10944
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\u2705 <b>Ping Command Sent</b>\n\u2514 Target: <code>{{ $json.ip }}</code>",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "29e98f9c-dd20-4f56-bea9-6a783cb79d76",
      "name": "Ping Success",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -176,
        11104
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "\u26a0\ufe0f <b>Invalid Format</b>\n\nTo save an alias, use:\n<code>/name [MAC_Address] [Alias]</code>\n\nExample: <code>/name AA:BB:CC:11:22 Desktop</code>",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "aecba982-701a-41b6-95ed-bd7014f85da0",
      "name": "Format Error Reply",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1136,
        11808
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "upsert",
        "dataTableId": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "network_devices"
        },
        "filters": {
          "conditions": [
            {
              "keyName": "mac",
              "keyValue": "={{ $json.target }}"
            }
          ]
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "mac": "={{ $node[\"Parse Message\"].json.target }}",
            "name": "={{ $node[\"Parse Message\"].json.extra }}",
            "is_known": true
          },
          "matchingColumns": [
            "mac"
          ],
          "schema": [
            {
              "id": "mac",
              "displayName": "mac",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "name",
              "displayName": "name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "owner",
              "displayName": "owner",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "is_known",
              "displayName": "is_known",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "boolean",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "last_seen",
              "displayName": "last_seen",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "ip",
              "displayName": "ip",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "e5cd3d3d-5b9e-40ad-b98f-6181d5f5ee45",
      "name": "Save Alias",
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        -1136,
        11648
      ]
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\u2705 <b>Alias Saved</b>\n\u2514 <code>{{ $json.name }}</code> mapped to <code>{{ $json.mac }}</code>",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "4a197ce9-da1a-4055-82f8-1eacf4987d98",
      "name": "Confirm Alias",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -912,
        11648
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "\u23f3 <b>Starting Network Scan...</b>\n\u2514 ESP32 is probing the subnet.",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "de29d329-c8c4-4163-9028-1078785f9ccc",
      "name": "Scan Feedback",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1360,
        12000
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "topic": "home/wol/command",
        "sendInputData": false,
        "message": "{\"cmd\": \"scan\"}",
        "options": {}
      },
      "id": "f4cf34f8-4822-4741-a035-07ee9f8a8298",
      "name": "MQTT Trigger Scan",
      "type": "n8n-nodes-base.mqtt",
      "typeVersion": 1,
      "position": [
        -928,
        12000
      ],
      "credentials": {
        "mqtt": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "af473ca0-c25e-40e4-bf9c-c93aef77378b",
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "owner",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "wake",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "6064c447-d06a-4c13-b3e5-de0b28b7bc05"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "42aed3f3-81fc-4b1b-93f7-723f3a03a0ba",
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "ping",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "27ab125d-3e1b-4bce-ac0e-10dbf5b6bde2",
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "list",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "06bd6d49-ef9d-45bf-962b-27ca4ab58177",
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "name",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "1486f22a-e21e-44d1-8933-d45a820d5a7f",
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "scan",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "d6f013f5-3562-490e-9786-b2b3d446dcea",
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "help",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "31675b2e-d418-4960-aba8-1a2ae338f1c6",
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "presence",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "e7086c4c-0073-4df6-845e-b7cea79fe6f2",
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "settings",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        -1616,
        11776
      ],
      "id": "b5d20cb1-ef84-48db-bd27-75ffb301c893",
      "name": "Bot Command Switch"
    },
    {
      "parameters": {
        "jsCode": "const parseData = $node[\"Parse Message\"].json;\n// Default to bylastseen if no parameter is provided\nconst listParam = (parseData.target || \"bylastseen\").toLowerCase();\n\nlet devices = $input.all().map(i => i.json);\n\n// 1. Sort the devices based on the parameter\nif (listParam === \"byowner\") {\n    devices.sort((a, b) => {\n        const ownerA = a.owner || \"ZZZ_Unowned\"; \n        const ownerB = b.owner || \"ZZZ_Unowned\";\n        return ownerA.localeCompare(ownerB);\n    });\n} else {\n    // Default: Sort by last_seen descending\n    devices.sort((a, b) => {\n        const dateA = new Date(a.last_seen || 0);\n        const dateB = new Date(b.last_seen || 0);\n        return dateB - dateA;\n    });\n}\n\n// 2. Build the output chunks (safe for Telegram's character limits)\nconst chunks = [];\nlet currentChunk = `\ud83d\udccb <b>Device List (Sorted ${listParam}):</b>\\n\\n`;\nconst MAX_LENGTH = 3900; \n\nfor (const d of devices) {\n    const name = d.name || 'Unnamed Device';\n    const mac = d.mac || 'Unknown MAC';\n    const vendor = d.vendor ? ` [<i>${d.vendor}</i>]` : '';\n    const owner = d.owner ? ` \ud83d\udc64 ${d.owner}` : '';\n    \n    const line = `\u2022 ${name}${vendor}${owner} (<code>${mac}</code>)\\n`;\n\n    if (currentChunk.length + line.length > MAX_LENGTH) {\n        chunks.push({ json: { text: currentChunk } });\n        currentChunk = \"\ud83d\udccb <b>Device List (Cont.):</b>\\n\\n\" + line;\n    } else {\n        currentChunk += line;\n    }\n}\n\n// 3. CORRECTED CHECK: Check 'devices.length' instead of 'chunks.length'\nif (devices.length === 0) {\n    chunks.push({ json: { text: \"\ud83d\udccb <b>No devices found in the database.</b>\" } });\n} else {\n    // Push whatever is left in the currentChunk bucket\n    chunks.push({ json: { text: currentChunk } });\n}\n\nreturn chunks;"
      },
      "id": "a77d593d-3293-4d7c-9477-4ac90e287bae",
      "name": "Format and Chunk List",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1120,
        11424
      ]
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "={{ $json.text }}",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "0a04b658-4aa0-4dc5-a71f-6a45f9765b52",
      "name": "Send List1",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -896,
        11424
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\ud83e\udd16 <b>Network Monitor Bot Guide</b>\n\nHere are the commands you can use:\n\n\u26a1\ufe0f <b>Core Commands</b>\n\u2022 <code>/wake [MAC/IP/Alias]</code> - Wake up a device\n\u2022 <code>/ping [MAC/IP/Alias]</code> - Check if a device is online\n\u2022 <code>/scan</code> - Trigger a manual network scan\n\n\ud83d\udcca <b>Dashboards & Tracking</b>\n\u2022 <code>/presence</code> - View who is currently home\n\u2022 <code>/list</code> - List devices (add <code>byowner</code> or <code>bylastseen</code> to sort)\n\n\ud83d\udccb <b>Device Management</b>\n\u2022 <code>/name [MAC] [Alias]</code> - Save a short name for a MAC address\n\u2022 <code>/owner [MAC/IP/Alias] [Name]</code> - Assign a device to a person\n\n\u2699\ufe0f <b>Configuration</b>\n\u2022 <code>/settings network_monitor [key] [value]</code> - Update a system setting (e.g., notify_scan_complete false)\n\n\ud83d\udca1 <i>Tip: You can use a saved Alias (like 'MyPC') instead of a MAC/IP for the wake, ping, and owner commands!</i>",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "759ca4b4-2499-421b-864c-d8b82cc710d6",
      "name": "Send Help",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1360,
        12224
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "wake",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "ba431029-50ad-464d-9c36-551eefd832e4"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "aa61e43c-06d3-4e15-af8e-7dfe6825c199",
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "ping",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "965b0d0e-8c24-4970-a3dc-134829a7d45f",
                    "leftValue": "={{ $json.command }}",
                    "rightValue": "owner",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        -688,
        11104
      ],
      "id": "af1b7f4d-3101-45f6-8fed-f836a8167da1",
      "name": "Action Switch"
    },
    {
      "parameters": {
        "topics": "home/wol/status",
        "options": {}
      },
      "id": "fcea398c-6e82-4dee-ab21-90776c704dd2",
      "name": "On Ping Result",
      "type": "n8n-nodes-base.mqttTrigger",
      "typeVersion": 1,
      "position": [
        -2320,
        12928
      ],
      "credentials": {
        "mqtt": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const results = [];\n\nfor (const item of $input.all()) {\n    // Extract the payload\n    let payload = item.json.message !== undefined ? item.json.message : item.json;\n    \n    // If n8n received it as a string, parse it\n    if (typeof payload === 'string') {\n        try {\n            payload = JSON.parse(payload);\n        } catch(e) {\n            continue;\n        }\n    }\n\n    // Pass the cleaned payload forward\n    if (payload) {\n        results.push({ json: payload });\n    }\n}\n\nreturn results;"
      },
      "id": "dbcbeaf5-73ad-4c35-a00f-ebed9efcb478",
      "name": "Parse Ping Status",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -2112,
        12928
      ]
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\ud83d\udcf6 <b>Ping Result</b>\n\u2514 IP: <code>{{ $json.ip }}</code>\n\u2514 Status: {{ $json.online ? '\ud83d\udfe2 Online' : '\ud83d\udd34 Offline' }}{{ $json.online ? `\\n\u2514 Latency: ${$json.latency}ms` : '' }}",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "c40a810d-5123-4b50-893a-687d99317fe6",
      "name": "Send Ping Result",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1888,
        12928
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "d31941a6-7d3c-4699-8613-41637aae1e92",
              "leftValue": "={{ $json.target }}",
              "rightValue": "=^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$",
              "operator": {
                "type": "string",
                "operation": "regex"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -1360,
        11744
      ],
      "id": "1677bc65-3a8e-4c62-8a4a-bec899e65c24",
      "name": "Validate /name Format"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 10
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        -1152,
        12096
      ],
      "id": "d12f6c1b-914b-467f-9f65-f66d8e1ff94c",
      "name": "Schedule Trigger"
    },
    {
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "network_devices"
        },
        "returnAll": true
      },
      "id": "e3714a4d-115f-4563-84bd-5845e6a9c20a",
      "name": "Get Device List",
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        -1360,
        11424
      ]
    },
    {
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "network_devices"
        },
        "returnAll": true,
        "orderBy": true,
        "orderByColumn": "last_seen"
      },
      "id": "14f5c35b-c096-4626-9a5e-cea5f06b5c8c",
      "name": "Get Device List (presence)",
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        -1360,
        12448
      ]
    },
    {
      "parameters": {
        "jsCode": "const devices = $input.all().map(i => i.json);\n\n// Configuration: How many minutes until a device is considered \"Away\"?\nconst OFFLINE_MINUTES = 60;\nconst thresholdTime = new Date(Date.now() - (OFFLINE_MINUTES * 60 * 1000));\n\nconst owners = {};\nlet hasAnyOwner = false;\n\n// 1. Group devices by Owner and check presence\nfor (const d of devices) {\n    if (!d.owner) continue; // Skip unowned devices for the presence dashboard\n    \n    hasAnyOwner = true;\n    \n    if (!owners[d.owner]) {\n        owners[d.owner] = { isHome: false, devices: [] };\n    }\n\n    const lastSeen = new Date(d.last_seen || 0);\n    const isOnline = lastSeen > thresholdTime;\n\n    // If even one device is online, the owner is marked as Home\n    if (isOnline) {\n        owners[d.owner].isHome = true;\n    }\n\n    // Optional: Calculate friendly \"seen X mins ago\" string\n    const diffMins = Math.floor((Date.now() - lastSeen.getTime()) / 60000);\n    const seenText = diffMins < 1 ? \"Just now\" : `${diffMins}m ago`;\n\n    owners[d.owner].devices.push({\n        name: d.name || d.mac,\n        isOnline: isOnline,\n        seenText: seenText\n    });\n}\n\n// 2. Error Logic: If no owners are set in the database\nif (!hasAnyOwner) {\n    return [{ json: { \n        text: \"\u26a0\ufe0f <b>No Owners Configured</b>\\n\\nYou haven't assigned any devices to an owner yet in your database.\\n\\n<i>To use the Presence dashboard, manually add names to the 'owner' column in your Data Table for your known devices!</i>\" \n    }}];\n}\n\n// 3. Format the Dashboard\nlet outputText = \"\ud83c\udfe0 <b>Network Presence Report</b>\\n\\n\";\n\n// Sort owners alphabetically\nconst sortedOwners = Object.keys(owners).sort();\n\nfor (const ownerName of sortedOwners) {\n    const data = owners[ownerName];\n    const statusIcon = data.isHome ? \"\ud83d\udfe2 HOME\" : \"\ud83d\udd34 AWAY\";\n    \n    outputText += `\ud83d\udc64 <b>${ownerName}</b>: ${statusIcon}\\n`;\n    \n    // List their specific devices underneath\n    for (const dev of data.devices) {\n        const devIcon = dev.isOnline ? \"\ud83d\udcf1\" : \"\ud83d\udcf4\";\n        outputText += `  \u2514 ${devIcon} ${dev.name} <i>(Seen: ${dev.seenText})</i>\\n`;\n    }\n    outputText += \"\\n\";\n}\n\nreturn [{ json: { text: outputText.trim() } }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1152,
        12448
      ],
      "id": "bbcf3e74-3cf0-49d9-aa58-ced173edc01f",
      "name": "Find offline devices"
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "={{ $json.text }}",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -944,
        12448
      ],
      "id": "57ac9b14-f446-4560-921b-d76bc2e67a3b",
      "name": "Send a text message",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "cccc9a8b-e925-4cb3-b29c-30cb48267b2d",
              "leftValue": "={{ $node[\"Parse Message\"].json.extra }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -400,
        11280
      ],
      "id": "01acaef5-726c-4cbf-b1ce-e035f7c4070c",
      "name": "Validate format"
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\u26a0\ufe0f <b>Invalid Format</b>\n\nPlease specify an owner name to assign to this device.\nFormat: <code>/owner [MAC/IP/Alias] [OwnerName]</code>\n\nExample: <code>/owner MyPC Bernard</code>",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "fda302a4-dc6c-4843-b980-5bd229f96d91",
      "name": "Invalid Format Reply",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -176,
        11456
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "topics": "home/wol/heartbeat",
        "options": {}
      },
      "id": "1247923b-770a-450d-aa0c-b5efc4568d47",
      "name": "On Heartbeat",
      "type": "n8n-nodes-base.mqttTrigger",
      "typeVersion": 1,
      "position": [
        -2320,
        13152
      ],
      "credentials": {
        "mqtt": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "topics": "home/wol/scan/result",
        "options": {}
      },
      "id": "14a4b9b1-8d14-43fb-9218-8fc5ad1ca693",
      "name": "On Scan Result",
      "type": "n8n-nodes-base.mqttTrigger",
      "typeVersion": 1,
      "position": [
        -2320,
        13696
      ],
      "credentials": {
        "mqtt": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const results = [];\n\nfor (const item of $input.all()) {\n    // Extract the payload (handles differences between raw MQTT and wrapped JSON)\n    let payload = item.json.message !== undefined ? item.json.message : item.json;\n    \n    // If n8n received it as a string, parse it\n    if (typeof payload === 'string') {\n        try {\n            payload = JSON.parse(payload);\n        } catch(e) {\n            continue; // Skip if it's not valid JSON\n        }\n    }\n\n    // Skip utility events like {\"event\": \"scan_started\"}\n    if (!payload || payload.event) {\n        continue;\n    }\n\n    // Normalize MAC address to uppercase to prevent DB duplicates\n    if (payload.mac) {\n        payload.mac = String(payload.mac).toUpperCase().trim();\n    }\n    \n    results.push({ json: payload });\n}\n\nreturn results;"
      },
      "id": "16c948ed-69bc-404b-b8a6-a159b8c959e6",
      "name": "Filter Scan Data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1824,
        13856
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "4ed791c2-ace7-4d6b-9724-007ae155ad5f",
              "leftValue": "={{ $json.vendor }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -1392,
        13856
      ],
      "id": "5e472900-b820-4794-b0b9-1ba01bcca961",
      "name": "If"
    },
    {
      "parameters": {
        "url": "=https://api.macvendors.com/v1/lookup/{{ encodeURIComponent($json.mac) }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        -1120,
        13840
      ],
      "id": "3bb35561-9b70-47e0-83c7-b4971f0bdb62",
      "name": "HTTP Request",
      "alwaysOutputData": false,
      "retryOnFail": true,
      "waitBetweenTries": 2000,
      "maxTries": 5,
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\ud83c\udd95 <b>New Device Detected!</b>\n\u2514 MAC: <code>{{ $json.mac }}</code>\n\u2514 IP: <code>{{ $json.ip }}</code>\n\u2514 Vendor: <b>{{ $json.vendor || 'Unknown Vendor' }}</b>",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "bc2528dc-ed7d-4c4a-b050-d5110706571f",
      "name": "Notify Unknown",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -656,
        13888
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ JSON.parse($json.message).event }}",
                    "rightValue": "scan_started",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "029909b1-9047-4246-b02a-faf21363ce49"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "57caf04b-eb22-492e-94d8-f1e0c9155b4a",
                    "leftValue": "={{ JSON.parse($json.message).event }}",
                    "rightValue": "scan_rejected",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "3c10cab9-b06a-4c05-8f2e-4a738cf8e538",
                    "leftValue": "={{ JSON.parse($json.message).event }}",
                    "rightValue": "scan_complete",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        -2112,
        13664
      ],
      "id": "de3495ab-1e75-43b6-82d2-e5d6998f2f3c",
      "name": "Switch"
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\u26a0\ufe0f The ESP32 is already performing a background scan. Please try again in a moment.",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "98743b45-79d6-4457-a88f-0faa30448bb2",
      "name": "Notify Rejected",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1824,
        13504
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        -1824,
        13344
      ],
      "id": "290ea1d2-05ab-4394-b066-25fc6d4a40cb",
      "name": "No Operation, do nothing"
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\u26a0\ufe0f ESP32 Gateway just rebooted! Current WiFi Signal: {{ JSON.parse($json.message).rssi }}dBm",
        "additionalFields": {}
      },
      "id": "939e2dfe-4177-47c8-a55e-e8985ec2b01c",
      "name": "Send downtime update",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1872,
        13152
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "2df2f71a-d7ba-4831-8626-8b56d7be291a",
              "leftValue": "={{ JSON.parse($json.message).uptime }}",
              "rightValue": 65,
              "operator": {
                "type": "number",
                "operation": "lt"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -2112,
        13152
      ],
      "id": "63488352-093f-430a-895b-8498318a5959",
      "name": "If downed"
    },
    {
      "parameters": {
        "operation": "upsert",
        "dataTableId": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "network_devices"
        },
        "filters": {
          "conditions": [
            {
              "keyName": "mac",
              "keyValue": "={{ $json.mac }}"
            }
          ]
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "is_known": false,
            "mac": "={{ $json.mac }}",
            "owner": "={{ $node[\"Parse Message\"].json.extra }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "mac",
              "displayName": "mac",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "name",
              "displayName": "name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "owner",
              "displayName": "owner",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "is_known",
              "displayName": "is_known",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "boolean",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "last_seen",
              "displayName": "last_seen",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "ip",
              "displayName": "ip",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "vendor",
              "displayName": "vendor",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        -176,
        11264
      ],
      "id": "2d785db4-27ea-4c8d-8a5f-1ed1d3503ddb",
      "name": "Upsert: owner update"
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\u2705 <b>Owner Assigned</b>\n\u2514 Device: <code>{{ $json.mac }}</code>\n\u2514 Owner: <b>{{ $json.owner }}</b>",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "178eb213-739c-4158-ab06-46697a7cca07",
      "name": "Owner success",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        48,
        11264
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "upsert",
        "dataTableId": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "network_devices"
        },
        "filters": {
          "conditions": [
            {
              "keyName": "mac",
              "keyValue": "={{ $json.mac }}"
            }
          ]
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "mac": "={{ $json.mac }}",
            "last_seen": "={{ $now }}",
            "ip": "={{ $json.ip }}",
            "sweep_found": "={{ $json.sweep }}"
          },
          "matchingColumns": [
            "mac"
          ],
          "schema": [
            {
              "id": "mac",
              "displayName": "mac",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "name",
              "displayName": "name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "owner",
              "displayName": "owner",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "is_known",
              "displayName": "is_known",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "boolean",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "last_seen",
              "displayName": "last_seen",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "ip",
              "displayName": "ip",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "vendor",
              "displayName": "vendor",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "sweep_found",
              "displayName": "sweep_found",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "readOnly": false,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "299bf5e5-a7fb-4909-873b-68e8172b940a",
      "name": "Sync Device",
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        -1600,
        13856
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "4ed791c2-ace7-4d6b-9724-007ae155ad5f",
              "leftValue": "={{ $json.value }}",
              "rightValue": "false",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -1616,
        13696
      ],
      "id": "d078db67-9627-41df-8d80-12bc15e01428",
      "name": "If notify_scan_complete"
    },
    {
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "global_settings"
        },
        "matchType": "allConditions",
        "filters": {
          "conditions": [
            {
              "keyName": "namespace",
              "keyValue": "network_monitor"
            },
            {
              "keyName": "key",
              "keyValue": "notify_scan_complete"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        -1824,
        13696
      ],
      "id": "9f5816c6-eef5-4d2d-b69e-a6dded87e46e",
      "name": "Get notification settings"
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\u2705 Scan complete! Found {{ JSON.parse($('On Scan Result').item.json.message).total_found }} devices.",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "id": "b5ddd2a5-115a-4336-ae29-2f2730c49b61",
      "name": "Notify Completed",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1344,
        13712
      ],
      "alwaysOutputData": false,
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "f0f8364d-c0aa-46fa-89ec-3939a073e734",
              "leftValue": "={{ $json.target }}",
              "rightValue": "network_monitor",
              "operator": {
                "type": "string",
                "operation": "equals",
                "name": "filter.operator.equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -1360,
        12672
      ],
      "id": "83ab5dc1-2deb-40e8-a5ae-3b4de8389877",
      "name": "If network_monitor"
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\u26a0\ufe0f Unknown settings namespace: {{ $json.target }}",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1152,
        12816
      ],
      "id": "c1e45411-9106-4ab8-8db9-27286f2d42cf",
      "name": "Send unknown settings",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Grab the leftover text from your main parser\nconst extraText = $input.item.json.extra || \"\";\n\n// Split the text by spaces\nconst parts = extraText.trim().split(/\\s+/);\n\n// The first word is the key, everything after is the value\nconst key = parts[0] ? parts[0].toLowerCase() : null;\nconst value = parts.length > 1 ? parts.slice(1).join(\" \") : null;\n\n// Pass everything forward, adding our new clean variables\nreturn [{ \n    json: { \n        ...$input.item.json, \n        setting_key: key, \n        setting_value: value \n    } \n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1152,
        12656
      ],
      "id": "2b4753b7-bbb0-4bc4-92d5-0f09c0c351b3",
      "name": "Parse settings"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "f0f8364d-c0aa-46fa-89ec-3939a073e734",
              "leftValue": "={{ $json.setting_key }}",
              "rightValue": "network_monitor",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            },
            {
              "id": "2faa5d54-b8da-4176-ac01-c63a98ee7b45",
              "leftValue": "={{ $json.setting_value }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -944,
        12656
      ],
      "id": "a79e2cef-e902-42e4-89b7-49f0a9a647fd",
      "name": "If valid extra"
    },
    {
      "parameters": {
        "chatId": "123456789",
        "text": "=\u26a0\ufe0f <b>Invalid Settings Format</b>\n\nPlease provide both a setting key and a value.\nFormat: <code>/settings network_monitor [key] [value]</code>\n\nExample: <code>/settings network_monitor notify_scan_complete off</code>",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -768,
        12816
      ],
      "id": "b2e86342-c533-41f4-9055-c334b9cb2e42",
      "name": "Send settings format",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "upsert",
        "dataTableId": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "global_settings"
        },
        "matchType": "allConditions",
        "filters": {
          "conditions": [
            {
              "keyName": "namespace",
              "keyValue": "={{ $json.target }}"
            },
            {
              "keyName": "=key",
              "keyValue": "={{ $json.setting_key }}"
            }
          ]
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "value": "={{ $json.setting_value }}",
            "namespace": "={{ $json.target }}",
            "key": "={{ $json.setting_key }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "namespace",
              "displayName": "namespace",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "key",
              "displayName": "key",
            

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

N8N Complete Final. Uses telegramTrigger, dataTable, telegram, mqtt. Event-driven trigger; 58 nodes.

Source: https://github.com/KazeFreeze/esp32-network-monitor-gateway/blob/25457a614dffbebad48f3960da9427f5a6e137ed/n8n/n8n_complete_final.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

TextMain. Uses telegramTrigger, stopAndError, telegram, httpRequest. Event-driven trigger; 56 nodes.

Telegram Trigger, Stop And Error, Telegram +2
Slack & Telegram

Pede Ai. Uses httpRequest, telegram, postgres, telegramTrigger. Event-driven trigger; 53 nodes.

HTTP Request, Telegram, Postgres +1
Slack & Telegram

📄 Documentation: Notion Guide

Telegram Trigger, @Blotato/N8N Nodes Blotato, Telegram +1
Slack & Telegram

Telegram Wait. Uses stickyNote, httpRequest, redis, noOp. Event-driven trigger; 36 nodes.

HTTP Request, Redis, Telegram +1
Slack & Telegram

This n8n workflow turns your Telegram bot into a powerful AI photo enhancer! Whether users send a photo or a link, it processes the image by: 📥 Receiving the input (photo or link) 🧠 Upscaling quality

Telegram, AWS S3, HTTP Request +1