send MikroTik Notification via WhatsApp

I have implemented it, but this is not an official whatsapp bot

FYI I’ve just started kind of related topic http://forum.mikrotik.com/t/script-healthchecks-notification/150198/1 about https://healthchecks.io/ (or its selfhosted version) which provides over dozen pre-defined integrations to many messangers (virtually any webhook service integration can be used).

CallMeBot also added signal support recently

# function FuncWhatsAppSender. Аllows you to send messages in national languages.
# by Sertik & DrPioneer 02/11/2022 https://forummikrotik.ru/viewtopic.php?f=14&t=14087
# ---------------------------------------------
# https://api.callmebot.com/whatsapp.php?phone=[phone_number]&text=[message]&apikey=[your_apikey]

:global FuncWhatsAppSender
:if (!any $FuncWhatsAppSender) do={ :global FuncWhatsAppSender do={
:if ([:len $0]!=0) do={
:local Emoji "%F0%9F%A7%9A"
:local WhatsAppPhone 7XXXXXXXXXX
:local WhatsAppApiKey YYYYYY
:if ([:len $2]=0) do={

# Function of converting CP1251 to UTF8
    # https://forummikrotik.ru/viewtopic.php?p=81457#p81457
    :local FuncCP1251toUTF8 do={
        :local cp1251 [:toarray {"\20";"\01";"\02";"\03";"\04";"\05";"\06";"\07";"\08";"\09";"\0A";"\0B";"\0C";"\0D";"\0E";"\0F"; \
                                 "\10";"\11";"\12";"\13";"\14";"\15";"\16";"\17";"\18";"\19";"\1A";"\1B";"\1C";"\1D";"\1E";"\1F"; \
                                 "\21";"\22";"\23";"\24";"\25";"\26";"\27";"\28";"\29";"\2A";"\2B";"\2C";"\2D";"\2E";"\2F";"\3A"; \
                                 "\3B";"\3C";"\3D";"\3E";"\3F";"\40";"\5B";"\5C";"\5D";"\5E";"\5F";"\60";"\7B";"\7C";"\7D";"\7E"; \
                                 "\C0";"\C1";"\C2";"\C3";"\C4";"\C5";"\C6";"\C7";"\C8";"\C9";"\CA";"\CB";"\CC";"\CD";"\CE";"\CF"; \
                                 "\D0";"\D1";"\D2";"\D3";"\D4";"\D5";"\D6";"\D7";"\D8";"\D9";"\DA";"\DB";"\DC";"\DD";"\DE";"\DF"; \
                                 "\E0";"\E1";"\E2";"\E3";"\E4";"\E5";"\E6";"\E7";"\E8";"\E9";"\EA";"\EB";"\EC";"\ED";"\EE";"\EF"; \
                                 "\F0";"\F1";"\F2";"\F3";"\F4";"\F5";"\F6";"\F7";"\F8";"\F9";"\FA";"\FB";"\FC";"\FD";"\FE";"\FF"; \
                                 "\A8";"\B8";"\B9";"\8D"}];
        :local utf8   [:toarray {"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"000A";"0020";"0020";"000A";"0020";"0020"; \
                                 "0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020"; \
                                 "0021";"0022";"0023";"0024";"0025";"0026";"0027";"0028";"0029";"002A";"002B";"002C";"002D";"002E";"002F";"003A"; \
                                 "003B";"003C";"003D";"003E";"003F";"0040";"005B";"005C";"005D";"005E";"005F";"0060";"007B";"007C";"007D";"007E"; \
                                 "D090";"D091";"D092";"D093";"D094";"D095";"D096";"D097";"D098";"D099";"D09A";"D09B";"D09C";"D09D";"D09E";"D09F"; \
                                 "D0A0";"D0A1";"D0A2";"D0A3";"D0A4";"D0A5";"D0A6";"D0A7";"D0A8";"D0A9";"D0AA";"D0AB";"D0AC";"D0AD";"D0AE";"D0AF"; \
                                 "D0B0";"D0B1";"D0B2";"D0B3";"D0B4";"D0B5";"D0B6";"D0B7";"D0B8";"D0B9";"D0BA";"D0BB";"D0BC";"D0BD";"D0BE";"D0BF"; \
                                 "D180";"D181";"D182";"D183";"D184";"D185";"D186";"D187";"D188";"D189";"D18A";"D18B";"D18C";"D18D";"D18E";"D18F"; \
                                 "D001";"D191";"2116";"000A"}];
        :local convStr ""; 
        :local code    "";
        :for i from=0 to=([:len $1]-1) do={
            :local symb [:pick $1 $i ($i+1)]; 
            :local idx  [:find $cp1251 $symb];
            :local key  ($utf8->$idx);
            :if ([:len $key] != 0) do={
                :set $code ("%$[:pick ($key) 0 2]%$[:pick ($key) 2 4]");
                :if ([pick $code 0 3] = "%00") do={:set $code ([:pick $code 3 6])}
            } else={:set code ($symb)}; 
            :set $convStr ($convStr.$code);
        }
        :return ($convStr);
    }

:local StrWS [$FuncCP1251toUTF8 $1]

:set StrWS ("$Emoji"."%20"."$[/system identity get name]"."%0A"."$StrWS")
do {/tool fetch url="https://api.callmebot.com/whatsapp.php\?phone=$WhatsAppPhone&text=$StrWS&apikey=$WhatsAppApiKey" keep-result=no; :return "Done"
} on-error={:log info; :log error "Error function $0 fetch"; :log info ""; :return "Error fetch"}
    } else={:log info; log error "Parametrs function $0 mismatch"; :log info ""; :return "Error parametrs mismatch"}
   }
  }
}

# WhatsApp notification script by Sertik,drPioneer
# https://forummikrotik.ru/viewtopic.php?p=81726#p81726
# tested on ROS 6.2 and old
# updated 2022/11/11

:global FuncWhatsAppSender; 
 :if (!any $FuncWhatsAppSender) do={
     :if ([:len [/system script find name="Func_WhatsAppSender"]]!=0) do={
         /system script run Func_WhatsAppSender}
  }
:if (any $FuncWhatsAppSender) do={
 
:global lastTimeLogWS;

:do {
    # Function of searching comments for MAC-address by Virtue
    # https://forummikrotik.ru/viewtopic.php?p=73994#p73994
    :local FindMacAddr do={
        :if ($1 ~"[0-F][0-F]:[0-F][0-F]:[0-F][0-F]:[0-F][0-F]:[0-F][0-F]:[0-F][0-F]") do={
            :foreach idx in=[ /ip dhcp-server lease find dynamic=no disabled=no; ] do={
                :local mac  [ /ip dhcp-server lease get $idx mac-address; ];
                :if ($1 ~"$mac") do={ :return ($1." [".[ /ip dhcp-server lease get $idx comment; ]."]."); } 
            }
            :foreach idx in=[ /interface bridge host find; ] do={
                :local mac  [ /interface bridge host get $idx mac-address; ];
                :if ($1 ~"$mac") do={ :return ($1." [".[ /interface bridge host get $idx on-interface; ]."]."); }
            }
        }
        :return ($1);
    }

    # Time translation function to UNIX-time by Jotne
    # http://forum.mikrotik.com/t/i-did-it-script-to-compute-unix-time/68576/1
    :local EpochTime do={
        :local ds [/system clock get date];
        :local ts [/system clock get time];
        if ([:len $1] > 8) do={
            :set ds "$[:pick $1 0 6]/$[:pick $ds 7 11]";
            :set ts [:pick $1 7 15];
        }
        :local yesterday false;
        if ([:len $1] = 8) do={
            if ([:totime $1] > ts) do={ :set yesterday (true); }
            :set ts $1;
        }
        :local months;
        :if ((([:pick $ds 9 11]-1)/4) != (([:pick $ds 9 11])/4)) do={
            :set months {"an"=0;"eb"=31;"ar"=60;"pr"=91;"ay"=121;"un"=152;"ul"=182;"ug"=213;"ep"=244;"ct"=274;"ov"=305;"ec"=335};
        } else={
            :set months {"an"=0;"eb"=31;"ar"=59;"pr"=90;"ay"=120;"un"=151;"ul"=181;"ug"=212;"ep"=243;"ct"=273;"ov"=304;"ec"=334};
        }
        :set ds (([:pick $ds 9 11]*365)+(([:pick $ds 9 11]-1)/4)+($months->[:pick $ds 1 3])+[:pick $ds 4 6]);
        :set ts (([:pick $ts 0 2]*60*60)+([:pick $ts 3 5]*60)+[:pick $ts 6 8]);
        if (yesterday) do={ :set ds ($ds-1); }
        :return ($ds*24*60*60 + $ts + 946684800 - [/system clock get gmt-offset]);
    }

    # Main body of WS notification script
    :local outMsg "";
    :local nameID [ /system identity get name; ];
    :local logGet [ :toarray [ /log find ($topics ~"warning" || $topics ~"error" || $topics ~"critical" || $topics ~"caps" || $topics ~"wireless" || $message ~"logged in"); ]];
    :local logCnt [ :len $logGet ];
    if ([:len $lastTimeLogWS] < 1) do={ 
        :put ("Time of the last log entry was not found.");
        :set outMsg (">$[ /system clock get time; ] WhatsApp notification started.");
    }
    if ($logCnt > 0) do={
        :local lastTime [$EpochTime [ /log get [:pick $logGet ($logCnt-1)] time; ]];
        :local index 0;
        :local tempTime;
        :local tempMessage;
        :local tempTopic;
        :local unixTime;
        :do {
            :set index  ($index + 1); 
            :set tempTime    [ /log get [:pick $logGet ($logCnt - $index)]    time; ];
            :set tempTopic   [ /log get [:pick $logGet ($logCnt - $index)]  topics; ];
            :set tempMessage [ /log get [:pick $logGet ($logCnt - $index)] message; ];
            :set tempMessage (">".$tempTime." ".$tempMessage);
            :local findMacMsg ([$FindMacAddr $tempMessage]);
            :set unixTime [$EpochTime $tempTime];
            if (($unixTime > $lastTimeLogWS) && (!(($tempTopic ~"caps" || $tempTopic ~"wireless") && ($tempMessage != $findMacMsg)))) do={
                    :put $findMacMsg;
                    :set outMsg ($findMacMsg."%0A".$outMsg);
            }
        } while=(($unixTime > $lastTimeLogWS) && ($index < $logCnt));
        :if (([:len $lastTimeLogWS] < 1) || (([:len $lastTimeLogWS] > 0) && ($lastTimeLogWS != $lastTime) && ([:len $outMsg] > 8) )) do={
            :set lastTimeLogWS $lastTime;
            [$FuncWhatsAppSender $outMsg]
            :put ("Generated and send string for WhatsApp:\r\n".$outMsg);
        } else={ :put ("No log entries suitable for sending were found."); }
    } else={ :put ("Necessary log entries were not found."); }
} on-error={ :put ("Script error: check FuncWhatsAppSender are specified correctly."); }
}

Can I also be notified if in the log e.g. a Mikrotik reboots or someone logs in failure 10 times?

You can. Use our function and log parser in the post above.

Is there a way to convert CP1252 to UTF8?

Replace the function FuncCP1251toUTF8 with this:

:global ASCIItoCP1252toUTF8 do={
    :local ascii "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\
                  \10\11\12\13\14\15\16\17\18\19\1A\1B\1C\1D\1E\1F\
                  \20\21\22\23\24\25\26\27\28\29\2A\2B\2C\2D\2E\2F\
                  \30\31\32\33\34\35\36\37\38\39\3A\3B\3C\3D\3E\3F\
                  \40\41\42\43\44\45\46\47\48\49\4A\4B\4C\4D\4E\4F\
                  \50\51\52\53\54\55\56\57\58\59\5A\5B\5C\5D\5E\5F\
                  \60\61\62\63\64\65\66\67\68\69\6A\6B\6C\6D\6E\6F\
                  \70\71\72\73\74\75\76\77\78\79\7A\7B\7C\7D\7E\7F\
                  \80\81\82\83\84\85\86\87\88\89\8A\8B\8C\8D\8E\8F\
                  \90\91\92\93\94\95\96\97\98\99\9A\9B\9C\9D\9E\9F\
                  \A0\A1\A2\A3\A4\A5\A6\A7\A8\A9\AA\AB\AC\AD\AE\AF\
                  \B0\B1\B2\B3\B4\B5\B6\B7\B8\B9\BA\BB\BC\BD\BE\BF\
                  \C0\C1\C2\C3\C4\C5\C6\C7\C8\C9\CA\CB\CC\CD\CE\CF\
                  \D0\D1\D2\D3\D4\D5\D6\D7\D8\D9\DA\DB\DC\DD\DE\DF\
                  \E0\E1\E2\E3\E4\E5\E6\E7\E8\E9\EA\EB\EC\ED\EE\EF\
                  \F0\F1\F2\F3\F4\F5\F6\F7\F8\F9\FA\FB\FC\FD\FE\FF"
    :local CP1252toUTF8 {"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"09";"0A";"EFBFBD";"0A";"0A";"EFBFBD";"EFBFBD";
                         "EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";"EFBFBD";
                         "20";"21";"22";"23";"24";"25";"26";"27";"28";"29";"2A";"2B";"2C";"2D";"2E";"2F";
                         "30";"31";"32";"33";"34";"35";"36";"37";"38";"39";"3A";"3B";"3C";"3D";"3E";"3F";
                         "40";"41";"42";"43";"44";"45";"46";"47";"48";"49";"4A";"4B";"4C";"4D";"4E";"4F";
                         "50";"51";"52";"53";"54";"55";"56";"57";"58";"59";"5A";"5B";"5C";"5D";"5E";"5F";
                         "60";"61";"62";"63";"64";"65";"66";"67";"68";"69";"6A";"6B";"6C";"6D";"6E";"6F";
                         "70";"71";"72";"73";"74";"75";"76";"77";"78";"79";"7A";"7B";"7C";"7D";"7E";"7F";
                         "E282AC";"EFBFBD";"E2809A";"C692";"E2809E";"E280A6";"E280A0";"E280A1";"CB86";"E280B0";"C5A0";"E280B9";"C592";"EFBFBD";"C5BD";"EFBFBD";
                         "EFBFBD";"E28098";"E28099";"E2809C";"E2809D";"E280A2";"E28093";"E28094";"CB9C";"E284A2";"C5A1";"E280BA";"C593";"EFBFBD";"C5BE";"C5B8";
                         "C2A0";"C2A1";"C2A2";"C2A3";"C2A4";"C2A5";"C2A6";"C2A7";"C2A8";"C2A9";"C2AA";"C2AB";"C2AC";"C2AD";"C2AE";"C2AF";
                         "C2B0";"C2B1";"C2B2";"C2B3";"C2B4";"C2B5";"C2B6";"C2B7";"C2B8";"C2B9";"C2BA";"C2BB";"C2BC";"C2BD";"C2BE";"C2BF";
                         "C380";"C381";"C382";"C383";"C384";"C385";"C386";"C387";"C388";"C389";"C38A";"C38B";"C38C";"C38D";"C38E";"C38F";
                         "C390";"C391";"C392";"C393";"C394";"C395";"C396";"C397";"C398";"C399";"C39A";"C39B";"C39C";"C39D";"C39E";"C39F";
                         "C3A0";"C3A1";"C3A2";"C3A3";"C3A4";"C3A5";"C3A6";"C3A7";"C3A8";"C3A9";"C3AA";"C3AB";"C3AC";"C3AD";"C3AE";"C3AF";
                         "C3B0";"C3B1";"C3B2";"C3B3";"C3B4";"C3B5";"C3B6";"C3B7";"C3B8";"C3B9";"C3BA";"C3BB";"C3BC";"C3BD";"C3BE";"C3BF"
                        }
    :local string $1
    :if (([:typeof $string] != "str") or ($string = "")) do={ :return "" }
    :local lenstr [:len $string]
    :local constr ""
    :for pos from=0 to=($lenstr - 1) do={
        :local utf ($CP1252toUTF8->[:find $ascii [:pick $string $pos ($pos + 1)] -1])
        :local sym ""
        :if ([:len $utf] = 2) do={:set sym "%$[:pick $utf 0 2]" }
        :if ([:len $utf] = 4) do={:set sym "%$[:pick $utf 0 2]%$[:pick $utf 2 4]" }
        :if ([:len $utf] = 6) do={:set sym "%$[:pick $utf 0 2]%$[:pick $utf 2 4]%$[:pick $utf 4 6]" }
        :set constr "$constr$sym"
    }
    :return $constr
}

:put [$ASCIItoCP1252toUTF8 "test"]

For whatsapp only:
from 0x00 to 0x1F (control characters unsupported on whatsapp) except 0x09, 0x0A, 0x0C and 0x0D => %EF%BF%BD REPLACEMENT CHARACTER �
0x09 (TAB) => %09 (TAB)
0x0A (new line), 0x0C (form feed) and 0x0D (carriage return) => %0A (new line)
0x81, 0x8F, 0x8D, 0x90, 0x9D (not assigned on CP1252 and unsupported on whatsapp) => %EF%BF%BD REPLACEMENT CHARACTER �

(this version is for whatsapp only, for generic CP1252 to UTF-8 see my snippet http://forum.mikrotik.com/t/rextended-fragments-of-snippets/151033/1 )

I understand something like “/system/export”

but what kind of ASCI order is that? What is this needed for? or can you translate that too?
\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F

what does that have to do with logging in?
Can someone please provide a complete script?

there is not a direct function to obtain ascii value from a character,
like A = 65, 2 = 50, “space” = 32
the array from 00 to FF (all possible 1 byte values) is needed to have the position,
and the other array have, for same position the translated value.
for example “A” still “A” on UTF-8 but € for example is 3 byte on UTF-8: E2 82 AC, and À is 2 byte: C2 A0


Logging in where?
The function is called ASCIItoCP1252toUTF8 (default Windows Latin alphabet) and is a replacement of FuncCP1251toUTF8 (Cyrillic alphabet)
Because who write the function to send message on whatsapp with mikrotik script need a way to send Cyrillic characters by one OS that support only 7-bit alphabet,
instead the user @dadaniel need a way to send Latin characters like "perché, straße, françoise, ¿question?, mūžīgi MikroTik, € symbol, etc.)


For… what?



P.S.:
Mūžīgi MikroTik need conversion from codepage 1257 to be correctly writed on UTF-8

Thank you :smiley:
Now I understand the problem. That’s why I prefer to always stick to the 27 letters of the alphabet and don’t use any special characters.

I wanted to have a script that sends me a push message, e.g. with 10 failed logins.

Friend @Rextended, I want to receive messages from my RB via WHATSAPP on my cell phone, but your rule currently doesn't work, could you help me. Thanks.

I plan to use it here

{
:local intGoff [:tonum [/system clock get gmt-offset]]
:if ($intGoff > 86400) do={:set intGoff ($intGoff - 4294967296)}
:local epochNow (([/tool fetch url="https://api.kangarie.com/time/str/now" as-value output=user])->"data")
# not needed for this url, but is better keep it # :set epochNow [:pick $epochNow 1 ([:len $epochNow] - 1)]
:local upTime [/system resource get uptime]
:local wPos   [:find $upTime "w" -1]
:local dPos   [:find $upTime "d" -1]
:local utLen  [:len $upTime]
:local utSec  [:pick $upTime ($utLen - 2) $utLen]
:local utMin  [:pick $upTime ($utLen - 5) ($utLen - 3)]
:local utHou  [:pick $upTime ($utLen - 8) ($utLen - 6)]
:local utDay  0
:local utWee  0
:if (([:typeof $wPos] = "nil") and ([:typeof $dPos] = "num")) do={:set utDay [:pick $upTime 0 $dPos] }
:if (([:typeof $wPos] = "num") and ([:typeof $dPos] = "num")) do={:set utDay [:pick $upTime ($wPos + 1) $dPos] }
:if ([:typeof $wPos] = "num") do={:set utWee [:pick $upTime 0 $wPos] }
:local totUtSec ($utSec + (60 * $utMin) + (60 * 60 * $utHou) + (60 * 60 * 24 * $utDay) + (60 * 60 * 24 * 7 * $utWee))
:local epochStart ($epochNow - $totUtSec + $intGoff)
:local datetimeStart (([/tool fetch url="https://api.kangarie.com/time/str/$epochStart" as-value output=user])->"data")
# not needed for this url, but is better keep it # :set datetimeStart [:pick $datetimeStart 1 ([:len $datetimeStart] - 1)]
[/tool fetch url="https://api.callmebot.com/whatsapp.php\?phone=+5XXXXXXXXXX&text=$datetimeStart&apikey=25XXXX" mode=http keep-result=no];
}
{
/system clock
:local itime [get time]
[/tool fetch url="https://api.callmebot.com/whatsapp.php\?phone=+5xxxxxxxxxxx&text=$itime&apikey=2xxxxx" mode=http keep-result=no];
}

Here if it works.
What am I doing wrong?

no, how does it work with signal?

I du use PushBulllet to send notification to phone or chrome

With Pushbullet happens the same as with whatsapp, when I want to forward content of a received SMS, the Fetch gives error.

I guess it is because of the conversion problem from GSM7 to UTF-8 characters.

BR.

Twilio WhatsApp example:
https://github.com/zainarbani/mikrotik-script/blob/main/twilio.rsc

[quote=Ariana11 post_id=996578 time=1681569708 user_id=215707]
[quote=alisc post_id=611128 time=1501652467 user_id=49470]
hi all

good time



how to send MikriTik Message ( Notifications ) via WhatsApp ?

example : <LINK_TEXT text=“https://wiki.mikrotik.com/wiki/Manual:T … am_Example”>https://wiki.mikrotik.com/wiki/Manual:The_Dude_v6/Dude_Telegram_Example</LINK_TEXT>



best regards
[/quote]
Hi there!

To send MikroTik notifications via WhatsApp, you’ll need to follow these steps:


  1. Set up a WhatsApp Business Account: To send messages via WhatsApp, you’ll need a WhatsApp Business Account. You can create one by downloading the WhatsApp Business app from the app store and following the setup instructions.


  2. Obtain a WhatsApp Business API: To use the WhatsApp Business API, you’ll need to apply for access through the WhatsApp Business API official website. Follow the application process and obtain the necessary API credentials.


  3. Configure MikroTik Notifications: MikroTik devices can send notifications using various methods, such as email, SMS, and scripts. You can configure MikroTik notifications to trigger a script that sends a message to the WhatsApp Business API using the obtained API credentials.


  4. Develop a Script to Send WhatsApp Message: You’ll need to develop a script that sends a message to the WhatsApp Business API using the API credentials and the appropriate API endpoints. You can use a programming language such as Python or PHP to develop the script.


  5. Test and Deploy: Once the script is developed, you can test it to ensure that it sends messages correctly to the WhatsApp Business API. Once tested and working correctly, you can deploy the script to your MikroTik device and configure it to trigger notifications as needed.



    It’s important to note that sending messages via WhatsApp using the API requires compliance with WhatsApp’s terms of service and guidelines. Make sure to review and adhere to their policies to avoid any violations.
    [/quote]

Example??



..