From 8375673d93d5481cc575dcb61825eba9b08c1515 Mon Sep 17 00:00:00 2001 From: Michael Gisbers Date: Fri, 28 May 2021 17:30:37 +0200 Subject: global-functions: implement notifications via Matrix Matrix is an open network for secure, decentralized communication - and it has a web api. A warning on message type: Using 'm.notice' breaks rendering on Element for Android (no fixed width font) and does not pop up desktop notification. Thus we use 'm.text'. Should be safe as we do not send the messages in response to other messages. https://matrix.org/ --- global-functions.d/notification-matrix | 157 +++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 global-functions.d/notification-matrix (limited to 'global-functions.d/notification-matrix') diff --git a/global-functions.d/notification-matrix b/global-functions.d/notification-matrix new file mode 100644 index 0000000..962924e --- /dev/null +++ b/global-functions.d/notification-matrix @@ -0,0 +1,157 @@ +#!rsc by RouterOS +# RouterOS script: global-functions.d/notification-matrix +# Copyright (c) 2013-2021 Michael Gisbers +# Christian Hesse +# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md + +:global FlushMatrixQueue; +:global NotificationFunctions; +:global SendMatrix; +:global SendMatrix2; + +# flush Matrix queue +:set FlushMatrixQueue do={ + :global MatrixQueue; + + :global LogPrintExit2; + + :local AllDone true; + :local QueueLen [ :len $MatrixQueue ]; + + :if ([ :len [ / system scheduler find where name="FlushMatrixQueue" ] ] > 0 && $QueueLen = 0) do={ + $LogPrintExit2 warning $0 ("Flushing Matrix messages from scheduler, but queue is empty.") false; + } + + :foreach Id,Message in=$MatrixQueue do={ + :if ([ :typeof $Message ] = "array" ) do={ + :do { + / tool fetch check-certificate=yes-without-crl output=none http-method=post \ + ("https://" . $Message->"homeserver" . "/_matrix/client/r0/rooms/" . $Message->"room" . \ + "/send/m.room.message?access_token=" . $Message->"accesstoken") \ + http-data=("{ \"msgtype\": \"m.text\", \"body\": \"" . $Message->"plain" . "\"," . \ + "\"format\": \"org.matrix.custom.html\", \"formatted_body\": \"" . \ + $Message->"formatted" . "\" }") as-value; + :set ($MatrixQueue->$Id); + } on-error={ + $LogPrintExit2 debug $0 ("Sending queued Matrix message failed.") false; + :set AllDone false; + } + } + } + + :if ($AllDone = true && $QueueLen = [ :len $MatrixQueue ]) do={ + / system scheduler remove [ find where name="FlushMatrixQueue" ]; + :set MatrixQueue; + } +} + +# send notification via Matrix - expects one array argument +:set ($NotificationFunctions->"matrix") do={ + :local Notification $1; + + :global Identity; + :global MatrixAccessToken; + :global MatrixAccessTokenOverride; + :global MatrixHomeServer; + :global MatrixHomeServerOverride; + :global MatrixQueue; + :global MatrixRoom; + :global MatrixRoomOverride; + + :global EitherOr; + :global LogPrintExit2; + :global SymbolForNotification; + + :local PrepareText do={ + :local Input [ :tostr $1 ]; + + :if ([ :len $Input ] = 0) do={ + :return ""; + } + + :local Return ""; + :local Chars { + "plain"={ "\\"; "\""; "\n" }; + "format"={ "\\"; "\""; "\n"; "&"; "<"; ">" }; + } + :local Subs { + "plain"={ "\\\\"; "\\\""; "\\n" }; + "format"={ "\\\\"; """; "
"; "&"; "<"; ">" }; + } + + :for I from=0 to=([ :len $Input ] - 1) do={ + :local Char [ :pick $Input $I ]; + :local Replace [ :find ($Chars->$2) $Char ]; + + :if ([ :typeof $Replace ] = "num") do={ + :set Char ($Subs->$2->$Replace); + } + :set Return ($Return . $Char); + } + + :return $Return; + } + + :local AccessToken [ $EitherOr ($MatrixAccessTokenOverride->($Notification->"origin")) $MatrixAccessToken ]; + :local HomeServer [ $EitherOr ($MatrixHomeServerOverride->($Notification->"origin")) $MatrixHomeServer ]; + :local Room [ $EitherOr ($MatrixRoomOverride->($Notification->"origin")) $MatrixRoom ]; + + :if ([ :len $AccessToken ] = 0 || [ :len $HomeServer ] = 0 || [ :len $Room ] = 0) do={ + :return false; + } + + :local Plain [ $PrepareText ("## [" . $Identity . "] " . ($Notification->"subject") . "\n```\n" . \ + ($Notification->"message") . "\n```") "plain" ]; + :local Formatted ("

" . [ $PrepareText ("[" . $Identity . "] " . ($Notification->"subject")) "format" ] . "

" . \ + "
" . [ $PrepareText ($Notification->"message") "format" ] . "
"); + :if ([ :len ($Notification->"link") ] > 0) do={ + :set Plain ($Plain . "\\n" . [ $SymbolForNotification "link" ] . \ + [ $PrepareText ("[" . $Notification->"link" . "](" . $Notification->"link" . ")") "plain" ]); + :set Formatted ($Formatted . "
" . [ $SymbolForNotification "link" ] . \ + ""link") "format" ] . "\\\">" . \ + [ $PrepareText ($Notification->"link") "format" ] . ""); + } + + :do { + / tool fetch check-certificate=yes-without-crl output=none http-method=post \ + ("https://" . $HomeServer . "/_matrix/client/r0/rooms/" . $Room . \ + "/send/m.room.message?access_token=" . $AccessToken) \ + http-data=("{ \"msgtype\": \"m.text\", \"body\": \"" . $Plain . "\"," . \ + "\"format\": \"org.matrix.custom.html\", \"formatted_body\": \"" . \ + $Formatted . "\" }") as-value; + } on-error={ + $LogPrintExit2 info $0 ("Failed sending Matrix notification! Queuing...") false; + + :if ([ :typeof $MatrixQueue ] = "nothing") do={ + :set MatrixQueue [ :toarray "" ]; + } + :local Text ([ $SymbolForNotification "alarm-clock" ] . \ + "This message was queued since " . [ / system clock get date ] . \ + " " . [ / system clock get time ] . " and may be obsolete."); + :set Plain ($Plain . "\\n" . $Text); + :set Formatted ($Formatted . "
" . $Text); + :set ($MatrixQueue->[ :len $MatrixQueue ]) { room=$Room; \ + accesstoken=$AccessToken; homeserver=$HomeServer; \ + plain=$Plain; formatted=$Formatted }; + :if ([ :len [ / system scheduler find where name="FlushMatrixQueue" ] ] = 0) do={ + / system scheduler add name=FlushMatrixQueue interval=1m start-time=startup \ + on-event=":global FlushMatrixQueue; \$FlushMatrixQueue;"; + } + } +} + +# send notification via Matrix - expects at lease two string arguments +:set SendMatrix do={ + :global SendMatrix2; + + $SendMatrix2 ({ subject=$1; message=$2; link=$3 }); +} + +# send notification via Matrix - expects one array argument +:set SendMatrix2 do={ + :local Notification $1; + + :global NotificationFunctions; + + ($NotificationFunctions->"matrix") ("\$NotificationFunctions->\"matrix\"") $Notification; +} -- cgit v1.2.3-54-g00ecf