vagrik
July 22, 2025, 2:39pm
1
I have prepared a script that notifies me via Telegram when the ping route fails.
{
:local telegramBotToken "XXXXXXX";
:local telegramChatID "XXXXX";
:local routerIdentity [/system identity get name];
:local currentDate [/system clock get date];
:local currentTime [/system clock get time];
:global lastGatewayIPs;
:global lastGatewayStatuses;
:if ([:typeof $lastGatewayIPs] = "nothing") do={
:set lastGatewayIPs ([:toarray ""]);
:set lastGatewayStatuses ([:toarray ""]);
:set lastGatewayIPs [:remove $lastGatewayIPs 0];
:set lastGatewayStatuses [:remove $lastGatewayStatuses 0];
}
:local currentGatewayIPs;
:local currentGatewayStatuses;
:local routesToMonitor [/ip route find check-gateway!=none];
:local counter 0;
:foreach routeId in=$routesToMonitor do={
:local routeDetails [/ip route get $routeId as-value];
:if ([:typeof $routeDetails] = "nothing") do={
:continue;
}
:local routeDst "";
:if ([:has $routeDetails "dst-address"]) do={
:set routeDst ($routeDetails->"dst-address");
}
:local routeGateway "";
:if ([:has $routeDetails "gateway"]) do={
:set routeGateway ($routeDetails->"gateway");
} else={
:continue;
}
:local checkGatewayType ($routeDetails->"check-gateway");
:local gatewayStatus "";
:if ($checkGatewayType = "ping" || $checkGatewayType = "arp") do={
:if ([:has $routeDetails "check-gateway-status"]) do={
:set gatewayStatus ($routeDetails->"check-gateway-status");
} else={
:continue;
}
} else if ($checkGatewayType = "dhcp-ping") do={
:if ([:has $routeDetails "dhcp-ping-status"]) do={
:set gatewayStatus ($routeDetails->"dhcp-ping-status");
} else={
:continue;
}
} else={
:continue;
}
:set ($currentGatewayIPs->$counter) $routeGateway;
:set ($currentGatewayStatuses->$counter) $gatewayStatus;
:set counter ($counter + 1);
:local foundIndex -1;
:for i from=0 to=([:len $lastGatewayIPs] - 1) do={
:if ([:pick $lastGatewayIPs $i] = $routeGateway) do={
:set foundIndex $i;
:break;
}
}
:if ($foundIndex = -1) do={
:set ($lastGatewayIPs->[:len $lastGatewayIPs]) $routeGateway;
:set ($lastGatewayStatuses->[:len $lastGatewayStatuses]) $gatewayStatus;
} else={
:local prevStatus [:pick $lastGatewayStatuses $foundIndex];
:if ($gatewayStatus != $prevStatus) do={
:local alertMessage "";
:if ($gatewayStatus = "reachable") do={
:set alertMessage ("Gateway " . $routeGateway . " (for " . $routeDst . ") is UP again on " . $routerIdentity . " at " . $currentDate . " " . $currentTime);
} else={
:set alertMessage ("Gateway " . $routeGateway . " (for " . $routeDst . ") is DOWN (" . $gatewayStatus . ") on " . $routerIdentity . " at " . $currentDate . " " . $currentTime);
}
/tool fetch url=("https://api.telegram.org/bot" . $telegramBotToken . "/sendMessage?chat_id=" . $telegramChatID . "&text=" . [:url-encode $alertMessage]) keep-result=no;
:set ($lastGatewayStatuses->$foundIndex) $gatewayStatus;
}
}
}
:local i 0;
:while ($i < [:len $lastGatewayIPs]) do={
:local oldGatewayIP [:pick $lastGatewayIPs $i];
:local foundInCurrent false;
:for j from=0 to=([:len $currentGatewayIPs] - 1) do={
:if ([:pick $currentGatewayIPs $j] = $oldGatewayIP) do={
:set foundInCurrent true;
:break;
}
}
:if ($foundInCurrent = false) do={
:set lastGatewayIPs [:remove $lastGatewayIPs $i];
:set lastGatewayStatuses [:remove $lastGatewayStatuses $i];
} else={
:set i ($i + 1);
}
}
}
But unfortunately, this script gives this error at the end:
expected closing brace (line 111 column 2)
If it says so, then there is a need for the closin brace
I suggest you to do /system/script/print from cli in Winbox to see what&where is the problem.
1 Like
Amm0
July 22, 2025, 2:50pm
3
What LLM did you use? Was this ChatGPT or Gemini or something else?
1 Like
vagrik
July 22, 2025, 3:14pm
5
{
:local telegramBotToken "XXXX";
:local telegramChatID "XXXX";
:local routerIdentity [/system identity get name];
:local currentDate [/system clock get date];
:local currentTime [/system clock get time];
:global lastGatewayIPs;
:global lastGatewayStatuses;
:if ([:typeof $lastGatewayIPs] = "nothing") do={
:set lastGatewayIPs ([:toarray ""]);
:set lastGatewayStatuses ([:toarray ""]);
:set lastGatewayIPs [:remove $lastGatewayIPs 0];
:set lastGatewayStatuses [:remove $lastGatewayStatuses 0];
}
:local currentGatewayIPs;
:local currentGatewayStatuses;
:local routesToMonitor [/ip route find check-gateway!=none];
:local counter 0;
:foreach routeId in=$routesToMonitor do={
:local routeDetails [/ip route get $routeId as-value];
}
:if ([:typeof $routeDetails] = "nothing") do={
:continue;
}
:local routeDst "";
:if ([:has $routeDetails "dst-address"]) do={
:set routeDst ($routeDetails->"dst-address");
}
:local routeGateway "";
:if ([:has $routeDetails "gateway"]) do={
:set routeGateway ($routeDetails->"gateway");
} else={
:continue;
}
:local checkGatewayType ($routeDetails->"check-gateway");
:local gatewayStatus "";
:if ($checkGatewayType = "ping" || $checkGatewayType = "arp") do={
:if ([:has $routeDetails "check-gateway-status"]) do={
:set gatewayStatus ($routeDetails->"check-gateway-status");
} else={
:continue;
}
} else={ :if ($checkGatewayType = "dhcp-ping") do={
:if ([:has $routeDetails "dhcp-ping-status"]) do={
:set gatewayStatus ($routeDetails->"dhcp-ping-status");
} else={
:continue;
}
} else={
:continue;
}
:set ($currentGatewayIPs->$counter) $routeGateway;
:set ($currentGatewayStatuses->$counter) $gatewayStatus;
:set counter ($counter + 1);
:local foundIndex -1;
:for i from=0 to=([:len $lastGatewayIPs] - 1) do={
:if ([:pick $lastGatewayIPs $i] = $routeGateway) do={
:set foundIndex $i;
:break;
}
}
:if ($foundIndex = -1) do={
:set ($lastGatewayIPs->[:len $lastGatewayIPs]) $routeGateway;
:set ($lastGatewayStatuses->[:len $lastGatewayStatuses]) $gatewayStatus;
} else={
:local prevStatus [:pick $lastGatewayStatuses $foundIndex];
:if ($gatewayStatus != $prevStatus) do={
:local alertMessage "";
:if ($gatewayStatus = "reachable") do={
:set alertMessage ("Gateway " . $routeGateway . " (for " . $routeDst . ") is UP again on " . $routerIdentity . " at " . $currentDate . " " . $currentTime);
} else={
:set alertMessage ("Gateway " . $routeGateway . " (for " . $routeDst . ") is DOWN (" . $gatewayStatus . ") on " . $routerIdentity . " at " . $currentDate . " " . $currentTime);
}
/tool fetch url=("https://api.telegram.org/bot" . $telegramBotToken . "/sendMessage?chat_id=" . $telegramChatID . "&text=" . [:url-encode $alertMessage]) keep-result=no;
:set ($lastGatewayStatuses->$foundIndex) $gatewayStatus;
}
}
}
:local i 0;
:while ($i < [:len $lastGatewayIPs]) do={
:local oldGatewayIP [:pick $lastGatewayIPs $i];
:local foundInCurrent false;
:for j from=0 to=([:len $currentGatewayIPs] - 1) do={
:if ([:pick $currentGatewayIPs $j] = $oldGatewayIP) do={
:set foundInCurrent true;
:break;
}
}
:if ($foundInCurrent = false) do={
:set lastGatewayIPs [:remove $lastGatewayIPs $i];
:set lastGatewayStatuses [:remove $lastGatewayStatuses $i];
} else={
:set i ($i + 1);
}
}
}
New Error:
input does not match any value of value-name (/ip/route/get (value-name); line 26)
vagrik
July 22, 2025, 3:15pm
6
ChatGPT & Gemini… both!
vagrik
July 22, 2025, 3:17pm
8
I created the script via Wiki, then Gemini said it was wrong and corrected it! I saw how much it was corrected!
Do not believe LLM. It ouputs just an aproximation of the expected result.
1 Like
vagrik
July 22, 2025, 3:21pm
10
Where do you think I went wrong?
Do you have a solution?
The problem is assuming that AI is a solution.
The solution is to write the script yourself or copy/adapt working one. Try to search the forum for countless topics on Telegram.
Amm0
July 22, 2025, 3:24pm
12
There is a whole video on sending notifications using Telegram on MikroTik’s YouTube. And if you search on forum, I suspect you’ll find something closer.
But first it was making up “continue”, “else-if”, “has”, now it’s using “:remove” and making up attributes. You can try using /system/script/edit from CLI which will show errors like print. But it’s not just syntax error that are the problems here (what’s attributes it’s reading, and looks like other logic errors).
1 Like
vagrik
July 22, 2025, 3:26pm
13
By the way, I’ve been reading and participating in various forums for almost two months now.
And I’m not sure about artificial intelligence myself.
You just misjudged!
vagrik
July 22, 2025, 3:27pm
14
Amm0:
There is a whole video on sending notifications using Telegram on MikroTik’s YouTube. And if you search on forum, I suspect you’ll find something closer.
But first it was making up “continue”, “else-if”, “has”, now it’s using “:remove” and making up attributes. You can try using /system/script/edit from CLI which will show errors like print. But it’s not just syntax error that are the problems here (what’s attributes it’s reading, and looks like other logic errors).
Thanks, I search it (again).
Amm0
July 22, 2025, 3:30pm
15
Wasn’t trying to be mean. More that it’s some of the scripting errors are pretty obvious, other are not. And telegram notifications script are a repeated topic over the years. There is no need for re-invention.
1 Like
vagrik
July 22, 2025, 3:34pm
16
I haven’t seen the script I want anywhere. I have a lot of different routes that are checked via ping. If a route is disabled, it will be transferred to another route.
Now I want a script that will send me a message on Telegram if there is a change in the routing.
Amm0
July 22, 2025, 3:47pm
18
I know LLMs do not understand how to use RouterOS’s [find]. And that’s what you need to find the check-gateway failing routes. Now not sure what you’re looking for there, so hard to suggest. But :if ([:len [/ip/route/find ...]] > 0)
, then you send notification (which there are examples).
@vagrik
In fact, the real problem isn’t artificial intelligence, but rather the people who write these posts without specifying that the garbage script they post is generated by a chatbot, just for the sake of small talk, so nothing tested or proven.
You and the others who do this on the forum are a nuisance plague, for two reasons:
first, because you discourage me and others from helping because you’re just wasting our time with made-up garbage that you don’t specify;
second, because the artificial intelligences trained on what’s written on the forum then take that script as valid and invent even more garbage.
Then I’d like to know where the chatbots first saw
:set lastGatewayIPs ([:toarray “”]);
:set lastGatewayIPs [:remove $lastGatewayIPs 0];
to insult the person who wrote that…
(I’m having a hard time not swearing)
(for the record, is just :set lastGatewayIPs [:toarray ""]
)
2 Likes
vagrik
July 30, 2025, 11:14am
20
I didn’t mean to offend anyone.
Anyway, I used the usual method.
I solved this problem to some extent through Netwatch.
Example:
/tool netwatch
add disabled=yes down-script="/tool fetch url=\"https://api.telegram.org/ggg:ggg/editMessageText\?chat_id=@ggg&message_id=11&text=<b>TUNNEL001</b> %0A %0A<b>Status:</b>\F0\9F\94\B4 OFFLINE! %0A<b>Tunnel Number:</b> <code>001</code> %0A<b>Location</b>: DE (Germany) %0A<b>GW</b>: <code>xxx.xxx.151.2</code> %0A<b>For Services</b>: safeNET ECO %0A<b>Services TAG</b>: %23ECO%40ggg &parse_mode=html\" keep-result=no\n" host=192.168.151.2 http-codes="" interval=10s name="TUNNEL 001" port=123456 startup-delay=1m test-script="" timeout=5s type=simple up-script="/tool fetch url=\"https://api.telegram.org/ggg:ggg/editMessageText\?chat_id=@ggg&message_id=11&text=<b>TUNNEL001</b> %0A %0A<b>Status:</b> \F0\9F\9F\A2 ONLINE! %0A<b>Tunnel Number:</b> <code>001</code> %0A<b>Location</b>: DE (Germany) %0A<b>GW</b>: <code>xxx.xxx.151.2</code> %0A<b>For Services</b>: SERVICE NAME %0A<b>Services TAG</b>: %23ECO%40channelName &parse_mode=html\" keep-result=no\n"
vagrik
July 30, 2025, 11:17am
21
Make sure you don’t waste your time on this nonsense!
At least people like me are sure that AI is wrong most of the time!
So, stay calm. I was a forum moderator for many years and gave advice to everyone.