Script Error!

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 :slight_smile:

I suggest you to do /system/script/print from cli in Winbox to see what&where is the problem.

1 Like

What LLM did you use? Was this ChatGPT or Gemini or something else?

1 Like
{
    :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)

ChatGPT & Gemini… both!

So ask them for help.

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

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.

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

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! :slight_smile:

Thanks, I search it (again). :slight_smile:

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

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.

1 Like

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

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"

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.