aboutsummaryrefslogtreecommitdiffstats
path: root/mod/notification-telegram.rsc
diff options
context:
space:
mode:
Diffstat (limited to 'mod/notification-telegram.rsc')
-rw-r--r--mod/notification-telegram.rsc168
1 files changed, 112 insertions, 56 deletions
diff --git a/mod/notification-telegram.rsc b/mod/notification-telegram.rsc
index ea47b1a..5ef353b 100644
--- a/mod/notification-telegram.rsc
+++ b/mod/notification-telegram.rsc
@@ -1,59 +1,102 @@
#!rsc by RouterOS
# RouterOS script: mod/notification-telegram
-# Copyright (c) 2013-2023 Christian Hesse <mail@eworm.de>
-# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md
+# Copyright (c) 2013-2025 Christian Hesse <mail@eworm.de>
+# https://rsc.eworm.de/COPYING.md
+#
+# requires RouterOS, version=7.15
+# requires device-mode, fetch, scheduler
#
# send notifications via Telegram
-# https://git.eworm.de/cgit/routeros-scripts/about/doc/mod/notification-telegram.md
+# https://rsc.eworm.de/doc/mod/notification-telegram.md
:global FlushTelegramQueue;
+:global GetTelegramChatId;
:global NotificationFunctions;
:global PurgeTelegramQueue;
:global SendTelegram;
:global SendTelegram2;
# flush telegram queue
-:set FlushTelegramQueue do={
+:set FlushTelegramQueue do={ :do {
:global TelegramQueue;
+ :global TelegramMessageIDs;
:global IsFullyConnected;
- :global LogPrintExit2;
+ :global LogPrint;
:if ([ $IsFullyConnected ] = false) do={
- $LogPrintExit2 debug $0 ("System is not fully connected, not flushing.") false;
+ $LogPrint debug $0 ("System is not fully connected, not flushing.");
:return false;
}
:local AllDone true;
:local QueueLen [ :len $TelegramQueue ];
- :if ([ :len [ /system/scheduler/find where name=$0 ] ] > 0 && $QueueLen = 0) do={
- $LogPrintExit2 warning $0 ("Flushing Telegram messages from scheduler, but queue is empty.") false;
+ :if ([ :len [ /system/scheduler/find where name="_FlushTelegramQueue" ] ] > 0 && $QueueLen = 0) do={
+ $LogPrint warning $0 ("Flushing Telegram messages from scheduler, but queue is empty.");
}
:foreach Id,Message in=$TelegramQueue do={
:if ([ :typeof $Message ] = "array" ) do={
:do {
- /tool/fetch check-certificate=yes-without-crl output=none http-method=post \
+ :local Data ([ /tool/fetch check-certificate=yes-without-crl output=user http-method=post \
("https://api.telegram.org/bot" . ($Message->"tokenid") . "/sendMessage") \
- http-data=("chat_id=" . ($Message->"chatid") . \
- "&disable_notification=" . ($Message->"silent") . \
- "&reply_to_message_id=" . ($Message->"replyto") . \
- "&disable_web_page_preview=true&parse_mode=" . ($Message->"parsemode") . \
- "&text=" . ($Message->"text")) as-value;
+ http-data=($Message->"http-data") as-value ]->"data");
:set ($TelegramQueue->$Id);
+ :set ($TelegramMessageIDs->[ :tostr ([ :deserialize from=json value=$Data ]->"result"->"message_id") ]) 1;
} on-error={
- $LogPrintExit2 debug $0 ("Sending queued Telegram message failed.") false;
+ $LogPrint debug $0 ("Sending queued Telegram message failed.");
:set AllDone false;
}
}
}
:if ($AllDone = true && $QueueLen = [ :len $TelegramQueue ]) do={
- /system/scheduler/remove [ find where name=$0 ];
+ /system/scheduler/remove [ find where name="_FlushTelegramQueue" ];
:set TelegramQueue;
}
-}
+} on-error={
+ :global ExitError; $ExitError false $0;
+} }
+
+# get the chat id
+:set GetTelegramChatId do={ :do {
+ :global TelegramTokenId;
+
+ :global CertificateAvailable;
+ :global LogPrint;
+
+ :if ([ $CertificateAvailable "Go Daddy Root Certificate Authority - G2" ] = false) do={
+ $LogPrint warning $0 ("Downloading required certificate failed.");
+ :return false;
+ }
+
+ :local Data;
+ :do {
+ :set Data ([ /tool/fetch check-certificate=yes-without-crl output=user \
+ ("https://api.telegram.org/bot" . $TelegramTokenId . "/getUpdates?offset=0" . \
+ "&allowed_updates=%5B%22message%22%5D") as-value ]->"data");
+ } on-error={
+ $LogPrint warning $0 ("Fetching data failed!");
+ :return false;
+ }
+
+ :local JSON [ :deserialize from=json value=$Data ];
+ :local Count [ :len ($JSON->"result") ];
+
+ :if ($Count = 0) do={
+ $LogPrint info $0 ("No message received.");
+ :return false;
+ }
+
+ :local Message ($JSON->"result"->($Count - 1)->"message");
+ $LogPrint info $0 ("The chat id is: " . ($Message->"chat"->"id"));
+ :if (($Message->"is_topic_message") = true) do={
+ $LogPrint info $0 ("The thread id is: " . ($Message->"message_thread_id"));
+ }
+} on-error={
+ :global ExitError; $ExitError false $0;
+} }
# send notification via telegram - expects one array argument
:set ($NotificationFunctions->"telegram") do={
@@ -63,8 +106,10 @@
:global IdentityExtra;
:global TelegramChatId;
:global TelegramChatIdOverride;
- :global TelegramFixedWidthFont;
+ :global TelegramMessageIDs;
:global TelegramQueue;
+ :global TelegramThreadId;
+ :global TelegramThreadIdOverride;
:global TelegramTokenId;
:global TelegramTokenIdOverride;
@@ -72,51 +117,58 @@
:global CharacterReplace;
:global EitherOr;
:global IfThenElse;
- :global LogPrintExit2;
+ :global LogPrint;
+ :global ProtocolStrip;
:global SymbolForNotification;
:global UrlEncode;
:local EscapeMD do={
- :global TelegramFixedWidthFont;
+ :local Text [ :tostr $1 ];
+ :local Mode [ :tostr $2 ];
+ :local Excl [ :tostr $3 ];
:global CharacterReplace;
:global IfThenElse;
- :if ($TelegramFixedWidthFont != true) do={
- :return ($1 . [ $IfThenElse ($2 = "body") ("\n") "" ]);
- }
-
- :local Return $1;
:local Chars {
- "body"={ "\\"; "`" };
+ "body"={ "\\"; "`" };
"plain"={ "_"; "*"; "["; "]"; "("; ")"; "~"; "`"; ">";
"#"; "+"; "-"; "="; "|"; "{"; "}"; "."; "!" };
}
- :foreach Char in=($Chars->$2) do={
- :set Return [ $CharacterReplace $Return $Char ("\\" . $Char) ];
+ :foreach Char in=($Chars->$Mode) do={
+ :if ([ :typeof [ :find $Excl $Char ] ] = "nil") do={
+ :set Text [ $CharacterReplace $Text $Char ("\\" . $Char) ];
+ }
}
- :if ($2 = "body") do={
- :return ("```\n" . $Return . "\n```");
+ :if ($Mode = "body") do={
+ :return ("```\n" . $Text . "\n```");
}
- :return $Return;
+ :return $Text;
}
:local ChatId [ $EitherOr ($Notification->"chatid") \
[ $EitherOr ($TelegramChatIdOverride->($Notification->"origin")) $TelegramChatId ] ];
+ :local ThreadId [ $EitherOr ($Notification->"threadid") \
+ [ $EitherOr ($TelegramThreadIdOverride->($Notification->"origin")) \
+ [ $IfThenElse ([ :len ($TelegramChatIdOverride->($Notification->"origin")) ] = 0) $TelegramThreadId ] ] ];
:local TokenId [ $EitherOr ($TelegramTokenIdOverride->($Notification->"origin")) $TelegramTokenId ];
:if ([ :len $TokenId ] = 0 || [ :len $ChatId ] = 0) do={
:return false;
}
+ :if ([ :typeof $TelegramMessageIDs ] = "nothing") do={
+ :set TelegramMessageIDs ({});
+ }
+
:local Truncated false;
:local Text ("*__" . [ $EscapeMD ("[" . $IdentityExtra . $Identity . "] " . \
($Notification->"subject")) "plain" ] . "__*\n\n");
:local LenSubject [ :len $Text ];
:local LenMessage [ :len ($Notification->"message") ];
- :local LenLink [ :len ($Notification->"link") ];
+ :local LenLink ([ :len ($Notification->"link") ] * 2);
:local LenSum ($LenSubject + $LenMessage + $LenLink);
:if ($LenSum > 3968) do={
:set Text ($Text . [ $EscapeMD ([ :pick ($Notification->"message") 0 (3840 - $LenSubject - $LenLink) ] . "...") "body" ]);
@@ -125,39 +177,41 @@
:set Text ($Text . [ $EscapeMD ($Notification->"message") "body" ]);
}
:if ($LenLink > 0) do={
- :set Text ($Text . "\n" . [ $SymbolForNotification "link" ] . [ $EscapeMD ($Notification->"link") "plain" ]);
+ :set Text ($Text . "\n" . [ $SymbolForNotification "link" ] . \
+ "[" . [ $EscapeMD [ $ProtocolStrip ($Notification->"link") ] "plain" ] . "]" . \
+ "(" . [ $EscapeMD ($Notification->"link") "plain" ] . ")");
}
:if ($Truncated = true) do={
:set Text ($Text . "\n" . [ $SymbolForNotification "scissors" ] . \
- [ $EscapeMD ("The message was too long and has been truncated, cut off " . \
- (($LenSum - [ :len $Text ]) * 100 / $LenSum) . "%!") "plain" ]);
+ [ $EscapeMD ("The message was too long and has been truncated, cut off _" . \
+ (($LenSum - [ :len $Text ]) * 100 / $LenSum) . "%_!") "plain" "_" ]);
}
- :set Text [ $UrlEncode $Text ];
- :local ParseMode [ $IfThenElse ($TelegramFixedWidthFont = true) "MarkdownV2" "" ];
+ :local HTTPData ("chat_id=" . $ChatId . "&disable_notification=" . ($Notification->"silent") . \
+ "&reply_to_message_id=" . ($Notification->"replyto") . "&message_thread_id=" . $ThreadId . \
+ "&disable_web_page_preview=true&parse_mode=MarkdownV2");
:do {
- :if ([ $CertificateAvailable "Go Daddy Secure Certificate Authority - G2" ] = false) do={
- $LogPrintExit2 warning $0 ("Downloading required certificate failed.") true;
+ :if ([ $CertificateAvailable "Go Daddy Root Certificate Authority - G2" ] = false) do={
+ $LogPrint warning $0 ("Downloading required certificate failed.");
+ :error false;
}
- /tool/fetch check-certificate=yes-without-crl output=none http-method=post \
+ :local Data ([ /tool/fetch check-certificate=yes-without-crl output=user http-method=post \
("https://api.telegram.org/bot" . $TokenId . "/sendMessage") \
- http-data=("chat_id=" . $ChatId . "&disable_notification=" . ($Notification->"silent") . \
- "&reply_to_message_id=" . ($Notification->"replyto") . \
- "&disable_web_page_preview=true&parse_mode=" . $ParseMode . "&text=" . $Text) as-value;
+ http-data=($HTTPData . "&text=" . [ $UrlEncode $Text ]) as-value ]->"data");
+ :set ($TelegramMessageIDs->[ :tostr ([ :deserialize from=json value=$Data ]->"result"->"message_id") ]) 1;
} on-error={
- $LogPrintExit2 info $0 ("Failed sending telegram notification! Queuing...") false;
+ $LogPrint info $0 ("Failed sending Telegram notification! Queuing...");
:if ([ :typeof $TelegramQueue ] = "nothing") do={
:set TelegramQueue ({});
}
- :set Text ($Text . [ $UrlEncode ("\n" . [ $SymbolForNotification "alarm-clock" ] . \
- [ $EscapeMD ("This message was queued since " . [ /system/clock/get date ] . \
- " " . [ /system/clock/get time ] . " and may be obsolete.") "plain" ]) ]);
- :set ($TelegramQueue->[ :len $TelegramQueue ]) { chatid=$ChatId; tokenid=$TokenId;
- parsemode=$ParseMode; text=$Text; silent=($Notification->"silent");
- replyto=($Notification->"replyto") };
- :if ([ :len [ /system/scheduler/find where name="\$FlushTelegramQueue" ] ] = 0) do={
- /system/scheduler/add name="\$FlushTelegramQueue" interval=1m start-time=startup \
+ :set Text ($Text . "\n" . [ $SymbolForNotification "alarm-clock" ] . \
+ [ $EscapeMD ("This message was queued since _" . [ /system/clock/get date ] . \
+ " " . [ /system/clock/get time ] . "_ and may be obsolete.") "plain" "_" ]);
+ :set ($TelegramQueue->[ :len $TelegramQueue ]) { tokenid=$TokenId;
+ http-data=($HTTPData . "&text=" . [ $UrlEncode $Text ]) };
+ :if ([ :len [ /system/scheduler/find where name="_FlushTelegramQueue" ] ] = 0) do={
+ /system/scheduler/add name="_FlushTelegramQueue" interval=1m start-time=startup \
on-event=(":global FlushTelegramQueue; \$FlushTelegramQueue;");
}
}
@@ -167,16 +221,18 @@
:set PurgeTelegramQueue do={
:global TelegramQueue;
- /system/scheduler/remove [ find where name="\$FlushTelegramQueue" ];
+ /system/scheduler/remove [ find where name="_FlushTelegramQueue" ];
:set TelegramQueue;
}
# send notification via telegram - expects at least two string arguments
-:set SendTelegram do={
+:set SendTelegram do={ :do {
:global SendTelegram2;
- $SendTelegram2 ({ subject=$1; message=$2; link=$3; silent=$4 });
-}
+ $SendTelegram2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 });
+} on-error={
+ :global ExitError; $ExitError false $0;
+} }
# send notification via telegram - expects one array argument
:set SendTelegram2 do={