Какое-то время назад меня посетила идея скрещивания скриптов оповещения ( viewtopic.php?p=81726#p81726 ) и удалённого запуска ( viewtopic.php?p=78085#p78085 ) в Телеграм в один могучий скрипт-комбайн, который объединил бы в себе возможности обоих скриптов.
Попытался воплотить идею в жизнь.
Вот что из этого получилось:
Код: Выделить всё
# Combined notification script and script launch via Telegram by drPioneer
# https://forummikrotik.ru/viewtopic.php?p=81726#p81726
# tested on ROS 6.49
# updated 2021/10/25
:do {
:local botID "botXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
:local myChatID "-XXXXXXXXX";
# 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);
}
# Function of converting SPACE to CODE by Sertik
# https://forummikrotik.ru/viewtopic.php?p=81481#p81481
:local SpaceToCode do={
:local char "";
:local string "";
:for idx from=0 to=([len $1]-1) do={
:set $char [:pick $1 $idx]
:if ($char=" ") do={ :set $char "%20"; }
:if ($char="\a" || $char="\b" || $char="\f" || $char="\n" || $char="\r" || $char="\t" || $char="\v") do={ :set $char ""; }
:set $string ($string.$char);
}
:return ($string);
}
# Telegram messenger response parsing function by Dimonw
# https://habr.com/ru/post/482802/
:local RespParser do={
:local variaMod ("\"".$2);
:local startLoc ([:find $1 $variaMod -1] + [:len $variaMod] + 2);
:local commaLoc ([:find $1 "," $startLoc]);
:local brakeLoc ([:find $1 "}" $startLoc]);
:local endLoc $commaLoc;
:local startSymbol [:pick $1 $startLoc];
:if ($brakeLoc != 0 and ($commaLoc = 0 or $brakeLoc < $commaLoc)) do={ :set endLoc $brakeLoc; };
:if ($startSymbol = "{") do={ :set endLoc ($brakeLoc + 1); };
:if ($3 = true) do={
:set startLoc ($startLoc + 1);
:set endLoc ($endLoc - 1);
}
:if ($endLoc < $startLoc) do={ :set endLoc ($startLoc + 1); };
:return ([:pick $1 $startLoc $endLoc]);
}
# Time translation function to UNIX-time by Jotne
# https://forum.mikrotik.com/viewtopic.php?t=75555#p790745
: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]*3600)+([:pick $ts 3 5]*60)+[:pick $ts 6 8]);
:if (yesterday) do={ :set ds ($ds-1); }
:return ($ds*86400 + $ts + 946684800 - [ /system clock get gmt-offset; ]);
}
# Main body of the script
:global timeAct;
:global timeLog;
:local nameID [ /system identity get name; ];
:put ("$[$EpochTime] sec - current Unix-time of $nameID router.");
if ([:len $timeAct] > 0) do={ :put ("$timeAct sec - time of checking the last script run."); }
if ([:len $timeLog] > 0) do={ :put ("$timeLog sec - time of the last log check."); }
# Part of the script body for running scripts via Telegram by drPioneer
# https://forummikrotik.ru/viewtopic.php?p=78085
:local timeStamp [$EpochTime];
:local urlString "";
:put ("... Stage of running scripts via Telegram:");
:if ([:len $timeAct] > 0) do={
:set urlString ("https://api.telegram.org/$botID/getUpdates\?offset=-1&limit=1&allowed_updates=message");
:local httpResp [ /tool fetch url=$urlString as-value output=user; ];
:local content ($httpResp->"data");
:if ([:len $content] > 30) do={
:local msgTxt [$RespParser $content "text" true];
:set msgTxt ([:pick $msgTxt ([:find $msgTxt "/"] + 1) ([:len $msgTxt])]);
:local chat [$RespParser $content "chat"];
:local chatId [$RespParser $chat "id"];
:local userName [$RespParser $content "username"];
:set timeStamp [$RespParser $content "date"];
:if (($chatId = $myChatID) && ($timeAct < $timeStamp) && ([ /system script find name=$msgTxt; ] != "")) do={
:put (">Found command '$msgTxt' from user $userName in $timeStamp sec.");
:set timeAct ($timeStamp);
:log warning ("Telegram user $userName activated script '$msgTxt' in $timeStamp sec.");
/system script run $msgTxt;
} else={ :put ("Nothing to run."); }
} else={ :put ("No response from Telegram."); }
} else={
:put ("Time of the last script activation was not found. Forced to generate.");
:set timeAct [$EpochTime];
}
# Part of the script body for notifications in Telegram by Alice Tails
# https://www.reddit.com/r/mikrotik/comments/onusoj/sending_log_alerts_to_telegram/
:local outMsg "";
:local logGet [ :toarray [ /log find ($topics ~"warning" || $topics ~"error" || $topics ~"critical" || $topics ~"caps" || $topics ~"wireless" || $message ~"logged in"); ]];
:local logCnt [ :len $logGet ];
:put ("... Stage of sending notifications to Telegram:");
:if ([:len $timeLog] < 1) do={
:put ("Time of the last log entry was not found. Forced to generate.");
:set outMsg (">$[ /system clock get time; ] Telegram 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 > $timeLog) && (!(($tempTopic ~"caps" || $tempTopic ~"wireless" || $tempTopic ~"dhcp") && ($tempMessage != $findMacMsg)))) do={
:put $findMacMsg;
:set outMsg ($findMacMsg."%0A".$outMsg);
}
} while=(($unixTime > $timeLog) && ($index < $logCnt));
:if (([:len $timeLog] < 1) || (([:len $timeLog] > 0) && ($timeLog != $lastTime) && ([:len $outMsg] > 8) )) do={
:set timeLog $lastTime;
:local urlString ("https://api.telegram.org/$botID/sendmessage\?chat_id=$myChatID&text=$nameID:%0A$outMsg");
:set urlString [$SpaceToCode $urlString];
:put ("Generated string for Telegram:\r\n".$urlString);
/tool fetch url=$urlString as-value output=user;
} else={ :put ("Nothing to send."); }
} else={ :put ("Necessary log entries were not found."); }
} on-error={ :put ("Script error: something went wrong when sending a request to Telegram."); }
Уверен, что в коде ещё таятся косяки и недоработки.
Предлагаю заинтересованным погонять этот скрипт и сообщить о найденных проблемах.
Как всегда, конструктивная критика и усовершенствования только приветствуются.