Представляю переработанную на свой лад версию скрипта, позволяющую удалённо запускать скрипты Mikrotik через Телеграм. В скрипте использованы идеи и часть кода by Pepelxl, Virtue, GeXoGeN и Dimonw - большая им благодарность!
Для работы скрипта должны быть заранее известны BotID и ChatID.
Скрипт необходимо добавить в System/Sheduler и установить запуск с периодичностью не менее одного раза минуту.
Алгоритм работы следующий: каждый раз при активации скрипта запрашивается ПОСЛЕДНЕЕ сообщение в группе с указанным BotID и если разница между временем отправки сообщения в Телеграм и текущим временем на Mikrotik составляет менее 1 минуты, тогда производится запуск скрипта с именем, указанным в теле сообщения.
На что нужно обратить внимание:
1. Работа скрипта привязана к текущему времени, по этой причине на роутере должны быть правильно выставлены время и часовой пояс.
2. Сообщения для роутера должны начинаться с символа "/". Например, если нужно запустить скрипт с именем "wol", тогда в теле сообщения должно быть написано "/wol", при этом в System/Scripts заранее должен быть прописан скрипт с нужным именем (например: "wol").
3. Скрипт считывает ПОСЛЕДНЕЕ сообщение в группе и по этой причине не имеет смысла накидывать сразу много команд, в любом случае будет выполнена только последняя.
Ниже представлен код скрипта:
Код: Выделить всё
# Script remote activation script via Telegram by drPioneer
# https://forummikrotik.ru/viewtopic.php?p=78085
# tested on ROS 6.48
# updated 2021/04/05
:do {
:local botID "botXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
:local myChatID "-XXXXXXXXX";
# Telegram messenger response parsing function by Dimonw
# https://habr.com/ru/post/482802/
:local parse do={
:local variaMod ("\"".$variable);
:local startLoc ([:find $content $variaMod -1] + [:len $variaMod] + 2);
:local commaLoc ([:find $content "," $startLoc]);
:local brakeLoc ([:find $content "}" $startLoc]);
:local endLoc $commaLoc;
:local startSymbol [:pick $content $startLoc];
:if ($brakeLoc != 0 and ($commaLoc = 0 or $brakeLoc < $commaLoc)) do={ :set endLoc $brakeLoc; };
:if ($startSymbol = "{") do={ :set endLoc ($brakeLoc + 1); };
:if ($quotas = true) do={
:set startLoc ($startLoc + 1);
:set endLoc ($endLoc - 1);
}
:if ($endLoc < $startLoc) do={ :set endLoc ($startLoc + 1); };
:local message [:pick $content $startLoc $endLoc];
:return $message;
}
# UNIX time conversion function to normal view by Pepelxl
# https://forummikrotik.ru/viewtopic.php?t=11636
:local unixTime do={
:local dateY ($timeStamp / 31436000 + 1970);
:local dateM (($dateY - 1969) / 4);
:local dateD (($timeStamp / 86400 - $dateM) % 365);
:local days [:toarray (31,28,31,30,31,30,31,31,30,31,30,31)];
:local months [:toarray ("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec")];
:if ($dateY % 4 = 0) do={ :set ($days->1) 29; }
do {
:for i from=0 to=11 do={
:if (($days->$i) > $dateD) do={
:set $dateM ($i);
:set $dateD ($dateD + 1);
:break;
} else={ :set $dateD ($dateD - ($days->$i)); }
}
} on-error={}
:local timeS ($timeStamp % 86400);
:local timeH ($timeS / 3600);
:local timeM ($timeS % 3600 / 60);
:set $timeS ($timeS - $timeH * 3600 - $timeM * 60);
:local normalTime (($months->$dateM)."/");
:if ($dateD < 10) do={ :set $normalTime ($normalTime."0".[:tostr $dateD]."/"); } else={ :set $normalTime ($normalTime.[:tostr $dateD]."/"); }
:set $normalTime ($normalTime.[:tostr $dateY]." ");
:if ($timeH < 10) do={ :set $normalTime ($normalTime."0".[:tostr $timeH].":"); } else={ :set $normalTime ($normalTime.[:tostr $timeH].":"); }
:if ($timeM < 10) do={ :set $normalTime ($normalTime."0".[:tostr $timeM].":"); } else={ :set $normalTime ($normalTime.[:tostr $timeM].":"); }
:if ($timeS < 10) do={ :set $normalTime ($normalTime."0".[:tostr $timeS]); } else={ :set $normalTime ($normalTime.[:tostr $timeS]); }
:put ([:totime $normalTime]);
:return $normalTime;
}
# Main body of the script
:local nameID [ /system identity get name; ];
:local dateNow [ /system clock get date; ];
:local timeNow [ /system clock get time; ];
:local httpResponse [ /tool fetch url="https://api.telegram.org/$botID/getUpdates\?offset=-1&limit=1&allowed_updates=message&timeout=60" as-value output=user; ];
:local content ($httpResponse->"data");
:if ([:len $content] > 30) do={
:local msgId [$parse content=$content variable="update_id"];
:local message [$parse content=$content variable="text" quotas=true];
:set message ([:pick $message ([:find $message "/"] + 1) ([:len $message])]);
:local chat [$parse content=$content variable="chat"];
:local chatId [$parse content=$chat variable="id"];
:local userName [$parse content=$content variable="username"];
:local dateTime [$parse content=$content variable="date"];
:set dateTime ($dateTime + [ /system clock get gmt-offset; ]);
:local normTime [$unixTime timeStamp=$dateTime];
:put ("Current time on router:\t $dateNow $timeNow");
:put ("Last message from $userName: time=$normTime, id=$msgId, text=$message.");
:if (($normTime ~ $dateNow) && ([:totime [:pick $normTime ([:find $normTime " "] + 1) ([:find $normTime " "] + 9)]] > ($timeNow - 00:01:00))) do={
:put ("Right time to activation script.");
:if (($chatId = $myChatID) && ([/system script find name=$message] != "")) do={
:put ("Telegram user $userName activated script '$message'.");
:log warning ("Telegram user $userName activated script '$message'.");
/system script run $message;
/tool fetch keep-result=no url="https://api.telegram.org/$botID/sendmessage\?chat_id=$chatId&text=$nameID: '$message' command accepted.";
} else={ :put ("Not all conditions activation script are met."); }
} else={ :put ("Bad time to activation script."); }
}
} on-error={ :put ("Script error: 1 - message could have been sent a long time ago. 2 - check whether 'botID' & 'myChatID' variables are specified correctly."); }
Список использованной литературы:
- https://habr.com/ru/post/482802/
- https://habr.com/ru/post/314108/
- https://habr.com/ru/post/313794/
- viewtopic.php?p=73994
- viewtopic.php?t=11636
- viewtopic.php?p=71914
----------------------------
UPDATE of 12.2021: Скрипт развивается. Актуальную версию скрипта Вы можете найти в конце этой ветки форума.