# Node-Red to join Telegram messages

**URL:** https://discourse.nodered.org/t/node-red-to-join-telegram-messages/44770
**Category:** General
**Created:** [26 April 2021 16:51 UTC](https://discourse.nodered.org/t/node-red-to-join-telegram-messages/44770 "2021-04-26T16:51:24Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Broutech](https://avatars.discourse-cdn.com/v4/letter/b/e0b2c6/32.png) [@Broutech](https://discourse.nodered.org/u/Broutech)
#### Post date: [26 April 2021 16:51 UTC](https://discourse.nodered.org/t/node-red-to-join-telegram-messages/44770/1 "2021-04-26T16:51:24Z")

</div>

Good day,

Very recently I embarked on finding a way to ping network devices from a database or list. While pinging and a device appears offline, i then wanted to post that "offline" device to Telegram.

A member on the group was brilliant at assisting me and I was able to achieve exactly what was described above. Truly magic member.

Getting to the point: Each failed device will send a separate message and the Bot does not like being bombarded with messages and at some point give up and does not report all failures.

So now I am looking for a way to join or wait a certain time and then send as one combined message.

An example of the offline devices attached picture and the bottom part is the result that I am after, one combined message.

Thank you for looking.

 ![Telegram](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/d/cd09f1d7538067220f8b3f4bc61d43e9f7aa4978.png)

```auto
[
    {
        "id": "337047ad.fcb858",
        "type": "tab",
        "label": "Flow 1",
        "disabled": false,
        "info": ""
    },
    {
        "id": "d901eeaa.d0d01",
        "type": "debug",
        "z": "337047ad.fcb858",
        "name": "Query DB",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 600,
        "y": 180,
        "wires": []
    },
    {
        "id": "dc501b75.0d31d8",
        "type": "ping",
        "z": "337047ad.fcb858",
        "mode": "triggered",
        "name": "",
        "host": "",
        "timer": "1",
        "inputs": 1,
        "x": 590,
        "y": 220,
        "wires": [
            [
                "d901eeaa.d0d01",
                "2e4bb18e.82e07e"
            ]
        ]
    },
    {
        "id": "db694dbc.960ca",
        "type": "function",
        "z": "337047ad.fcb858",
        "name": "Prepare telegram message (if offline)",
        "func": "if(msg.payload===false)\n{\n msg.payload = {};\n msg.payload.type = 'message';\n msg.payload.content = `${msg.ping.name} (${msg.ping.host}) seems to be OFFLINE`;\n msg.payload.chatId = xxxxxxx\n return msg;\n}\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 1010,
        "y": 400,
        "wires": [
            [
                "37286037.e03f9"
            ]
        ]
    },
    {
        "id": "33fa1e6a.529bf2",
        "type": "debug",
        "z": "337047ad.fcb858",
        "name": "Query DB",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 580,
        "y": 360,
        "wires": []
    },
    {
        "id": "2e4bb18e.82e07e",
        "type": "function",
        "z": "337047ad.fcb858",
        "name": "Prepare telegram message",
        "func": "const chatId = xxxxxxxx; // << update this\n\nif (!msg.ping.host) return null; //ensure host has a value\n\nvar pingMonitor = flow.get(\"pingMonitor\") || {};//get lookup object ||or|| a new empty object\nvar pingPrev = pingMonitor[msg.ping.host] || {};//this ping monitor object ||or|| a new empty object\nvar sendTelegram = false;\n\n//if ping is good, you get a number in payload...\nif (typeof msg.payload == \"number\" && pingPrev.status === \"bad\" ) {\n pingPrev.status = \"good\";\n msg.payload = {};\n msg.payload.type = 'message';\n msg.payload.content = `${msg.ping.name} (${msg.ping.host}) is now back online & operational!`;\n msg.payload.chatId = chatId;\n sendTelegram = true;\n} else if (msg.payload === false && (pingPrev.status === \"good\" || !pingPrev.status)) {\n pingPrev.status = \"bad\";\n msg.payload = {};\n msg.payload.type = 'message';\n msg.payload.content = `${msg.ping.name} (${msg.ping.host}) seems to be OFFLINE`;\n msg.payload.chatId = chatId;\n sendTelegram = true;\n}\n\n//update context\npingPrev.datetime = new Date();\npingPrev.host = msg.ping.host;\npingPrev.name = msg.ping.name;\npingMonitor[msg.ping.host] = pingPrev;\nflow.set(\"pingMonitor\", pingMonitor);\n\nif (sendTelegram) return msg;\n\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 900,
        "y": 220,
        "wires": [
            [
                "37286037.e03f9"
            ]
        ]
    },
    {
        "id": "fb4b47cd.fa82a8",
        "type": "ping",
        "z": "337047ad.fcb858",
        "mode": "triggered",
        "name": "",
        "host": "",
        "timer": "20",
        "inputs": 1,
        "x": 750,
        "y": 400,
        "wires": [
            [
                "db694dbc.960ca"
            ]
        ]
    },
    {
        "id": "7e6ffb57.605f54",
        "type": "telegram command",
        "z": "337047ad.fcb858",
        "name": "",
        "command": "/ping",
        "bot": "d918e20d.f9968",
        "strict": false,
        "hasresponse": true,
        "useregex": true,
        "removeregexcommand": false,
        "outputs": 2,
        "x": 210,
        "y": 400,
        "wires": [
            [
                "f52ae2a8.a3715"
            ],
            []
        ]
    },
    {
        "id": "4b93459e.23e3cc",
        "type": "comment",
        "z": "337047ad.fcb858",
        "name": "Network Offline Devices",
        "info": "",
        "x": 260,
        "y": 320,
        "wires": []
    },
    {
        "id": "8e959977.43e508",
        "type": "Stackhero-MySQL",
        "z": "337047ad.fcb858",
        "server": "2fad9f54.9ef47",
        "name": "",
        "x": 450,
        "y": 220,
        "wires": [
            [
                "dc501b75.0d31d8"
            ]
        ]
    },
    {
        "id": "721b196e.c93328",
        "type": "function",
        "z": "337047ad.fcb858",
        "name": "",
        "func": "msg.topic = 'SELECT * FROM host WHERE active = 1';\nmsg.payload = {\"action\": \"Q\", \"query\" : \"SELECT * FROM host WHERE active = 1\"};\nreturn msg;\n\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 280,
        "y": 220,
        "wires": [
            [
                "8e959977.43e508"
            ]
        ]
    },
    {
        "id": "13abd7df.36a758",
        "type": "inject",
        "z": "337047ad.fcb858",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "30",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 250,
        "y": 140,
        "wires": [
            [
                "721b196e.c93328"
            ]
        ]
    },
    {
        "id": "f52ae2a8.a3715",
        "type": "function",
        "z": "337047ad.fcb858",
        "name": "",
        "func": "msg.topic = 'SELECT * FROM host WHERE active = 1';\nmsg.payload = {\"action\": \"Q\", \"query\" : \"SELECT * FROM host WHERE active = 1\"};\nreturn msg;\n\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 420,
        "y": 400,
        "wires": [
            [
                "296abbe8.a435d4"
            ]
        ]
    },
    {
        "id": "296abbe8.a435d4",
        "type": "Stackhero-MySQL",
        "z": "337047ad.fcb858",
        "server": "2fad9f54.9ef47",
        "name": "",
        "x": 570,
        "y": 400,
        "wires": [
            [
                "fb4b47cd.fa82a8",
                "33fa1e6a.529bf2"
            ]
        ]
    },
    {
        "id": "595da70a.e1c328",
        "type": "inject",
        "z": "337047ad.fcb858",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 250,
        "y": 360,
        "wires": [
            [
                "f52ae2a8.a3715"
            ]
        ]
    },
    {
        "id": "679da82f.ed7be8",
        "type": "comment",
        "z": "337047ad.fcb858",
        "name": "Set ping timer",
        "info": "",
        "x": 230,
        "y": 100,
        "wires": []
    },
    {
        "id": "37286037.e03f9",
        "type": "telegram sender",
        "z": "337047ad.fcb858",
        "name": "",
        "bot": "",
        "haserroroutput": false,
        "outputs": 1,
        "x": 1420,
        "y": 320,
        "wires": [
            []
        ]
    },
    {
        "id": "d918e20d.f9968",
        "type": "telegram bot",
        "botname": "@xxxxxxbot",
        "usernames": "",
        "chatids": "xxxxxxxxxx",
        "baseapiurl": "",
        "updatemode": "polling",
        "pollinterval": "300",
        "usesocks": false,
        "sockshost": "",
        "socksport": "",
        "socksusername": "",
        "sockspassword": "",
        "bothost": "",
        "botpath": "",
        "localbotport": "",
        "publicbotport": "",
        "privatekey": "",
        "certificate": "",
        "useselfsignedcertificate": false,
        "sslterminated": false,
        "verboselogging": false
    },
    {
        "id": "2fad9f54.9ef47",
        "type": "Stackhero-MySQL-Server",
        "name": "",
        "host": "192.168.1.250",
        "port": "3308",
        "tls": false,
        "database": "pinger"
    }
]

```

---

<div class="post-metadata">

### Author: ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)
#### Post date: [26 April 2021 19:48 UTC](https://discourse.nodered.org/t/node-red-to-join-telegram-messages/44770/2 "2021-04-26T19:48:26Z")

</div>

Try something like this,  
move the payload and ping so they are in the payload, then join all messages into an array, passing on the joined messages after a certain amount of time, in the example the join is set to 10 seconds. Then in the function loop through array of responses and create the texted for the chat.

```auto
[{"id":"13abd7df.36a758","type":"inject","z":"337047ad.fcb858","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"host\":\"192.168.1.100\",\"name\":\"one\"},{\"host\":\"192.168.1.43\",\"name\":\"two\"},{\"host\":\"192.168.1.44\",\"name\":\"three\"}]","payloadType":"json","x":230,"y":180,"wires":[["dc501b75.0d31d8"]]},{"id":"dc501b75.0d31d8","type":"ping","z":"337047ad.fcb858","mode":"triggered","name":"","host":"","timer":"1","inputs":1,"x":350,"y":180,"wires":[["6c16cfc9.56cee8"]]},{"id":"6c16cfc9.56cee8","type":"change","z":"337047ad.fcb858","name":"","rules":[{"t":"set","p":"hold","pt":"msg","to":"{}","tot":"json"},{"t":"move","p":"payload","pt":"msg","to":"hold.time","tot":"msg"},{"t":"move","p":"ping","pt":"msg","to":"hold.ping","tot":"msg"},{"t":"move","p":"hold","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":180,"wires":[["c1caf483.74453"]]},{"id":"c1caf483.74453","type":"join","z":"337047ad.fcb858","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"payload.ping.name","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"10","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":710,"y":180,"wires":[["2e4bb18e.82e07e"]]},{"id":"2e4bb18e.82e07e","type":"function","z":"337047ad.fcb858","name":"Prepare telegram message","func":"const chatId = \"xxxxxxxx\"; // << update this\nvar sendTelegram = false;\nvar text =\"\";\nfor (const element of msg.payload){\nif (!element.ping.host) return null; //ensure host has a value\n\nvar pingMonitor = flow.get(\"pingMonitor\") || {};//get lookup object ||or|| a new empty object\nvar pingPrev = pingMonitor[element.ping.host] || {};//this ping monitor object ||or|| a new empty object\n\n\n//if ping is good, you get a number in payload...\nif (typeof element.time == \"number\" && pingPrev.status === \"bad\" ) {\n pingPrev.status = \"good\";\n text += `${element.ping.name} (${element.ping.host}) is now back online & operational!\\n`;\n sendTelegram = true;\n} else if (element.time === false && (pingPrev.status === \"good\" || !pingPrev.status)) {\n pingPrev.status = \"bad\";\n text += `${element.ping.name} (${element.ping.host}) seems to be OFFLINE\\n`;\n sendTelegram = true;\n}\n\n//update context\npingPrev.datetime = new Date();\npingPrev.host = element.ping.host;\npingPrev.name = element.ping.name;\npingMonitor[element.ping.host] = pingPrev;\nflow.set(\"pingMonitor\", pingMonitor);\n}\nif (sendTelegram) {\n msg.payload = {};\n msg.payload.type = 'message';\n msg.payload.content = text;\n msg.payload.chatId = chatId; \n \n return msg;\n}\n\nreturn null;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":920,"y":180,"wires":[["d901eeaa.d0d01"]]},{"id":"d901eeaa.d0d01","type":"debug","z":"337047ad.fcb858","name":"Query DB","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1050,"y":120,"wires":[]}]

```

 ![Screenshot_20210426-204443](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/b/4bf5bab4bfa34ae37321081628b647e5a46562c0.png)

---

<div class="post-metadata">

### Author: ![Broutech](https://avatars.discourse-cdn.com/v4/letter/b/e0b2c6/32.png) [@Broutech](https://discourse.nodered.org/u/Broutech)
#### Post date: [26 April 2021 21:16 UTC](https://discourse.nodered.org/t/node-red-to-join-telegram-messages/44770/3 "2021-04-26T21:16:19Z")

</div>

> [@E1cid](#):
>
> the payload and ping so they are in the payload, then join all messages into an array, passing on the joined messages after a certain amount of time, in the example the join is set to 10 seconds. Then in the function loop through array of responses and create the texted for the chat.
> 
> ```auto
> [{"id":"13abd7df.36a758","type":"inject","z":"337047ad.fcb85
> 
> ```

Thank you again for your assistance.

It works really well!

 ![Telegram_2](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/d/0da61484be687a7306d93e48afc8d65ef93acccd.png)

Just one snag, when I manually inject or Telegram command ask what is "offline or online / status" I get no reply. I would like the system to tell me in one message what is online and what is offline depending on the ask: A - Online B - Offline, if that makes any sense.

Thank you again for looking into this.

---

<div class="post-metadata">

### Author: ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)
#### Post date: [26 April 2021 21:29 UTC](https://discourse.nodered.org/t/node-red-to-join-telegram-messages/44770/4 "2021-04-26T21:29:20Z")

</div>

The pingMonitor Context store holds all the states. In the function you should grab the data and then create a message from it.

---

<div class="post-metadata">

### Author: ![Broutech](https://avatars.discourse-cdn.com/v4/letter/b/e0b2c6/32.png) [@Broutech](https://discourse.nodered.org/u/Broutech)
#### Post date: [27 April 2021 08:08 UTC](https://discourse.nodered.org/t/node-red-to-join-telegram-messages/44770/5 "2021-04-27T08:08:35Z")

</div>

> [@E1cid](#):
>
> ngMonitor Context store holds all the states

LOL, thank you, really appreciate that.

I just have no idea of how to do it 🙂

---

<div class="post-metadata">

### Author: ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)
#### Post date: [27 April 2021 08:48 UTC](https://discourse.nodered.org/t/node-red-to-join-telegram-messages/44770/6 "2021-04-27T08:48:41Z")

</div>

something like this

```auto
[{"id":"d901eeaa.d0d01","type":"debug","z":"bd180d69.a493b","name":"Query DB","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":770,"y":260,"wires":[]},{"id":"2d12ae50.e71a3a","type":"function","z":"bd180d69.a493b","name":"","func":"var text = \"\";\nfor (const element of msg.payload){\n text += `${element.datetime} - ${element.name} is ${element.status}\\n`;\n}\nmsg.payload =text;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":500,"y":260,"wires":[["d901eeaa.d0d01"]]},{"id":"f91c22c9.8a239","type":"change","z":"bd180d69.a493b","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$flowContext(\"pingMonitor\").[$.*]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":300,"y":260,"wires":[["2d12ae50.e71a3a"]]},{"id":"ac13358a.68dbf8","type":"inject","z":"bd180d69.a493b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":260,"wires":[["f91c22c9.8a239"]]}]

```

[edit] you will need to set a status on all hosts so add else statment to add ping.ststus.

```auto
var sendTelegram = false;
var text ="";
for (const element of msg.payload){
if (!element.ping.host) return null; //ensure host has a value

var pingMonitor = flow.get("pingMonitor") || {};//get lookup object ||or|| a new empty object
var pingPrev = pingMonitor[element.ping.host] || {};//this ping monitor object ||or|| a new empty object

//if ping is good, you get a number in payload...
if (typeof element.time == "number" && pingPrev.status === "bad" ) {
    pingPrev.status = "good";
    text += `${element.ping.name} (${element.ping.host}) is now back online & operational!\n`;
    sendTelegram = true;
} else if (element.time === false && (pingPrev.status === "good" || !pingPrev.status)) {
    pingPrev.status = "bad";
    text += `${element.ping.name} (${element.ping.host}) seems to be OFFLINE\n`;
    sendTelegram = true;
} else{
    pingPrev.status = "good";
}

//update context
pingPrev.datetime = new Date();
pingPrev.host = element.ping.host;
pingPrev.name = element.ping.name;
pingMonitor[element.ping.host] = pingPrev;
flow.set("pingMonitor", pingMonitor);
}
if (sendTelegram) {
    msg.payload = {};
    msg.payload.type = 'message';
    msg.payload.content = text;
    msg.payload.chatId = chatId;    
    
    return msg;
}

return null;

```

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [26 June 2021 08:48 UTC](https://discourse.nodered.org/t/node-red-to-join-telegram-messages/44770/7 "2021-06-26T08:48:51Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
