Здравствуйте. Статья не полностью претендует на право быть оригинальной — скорее, это усовершенствование скрипта, описанного в статье dimonw Удалённое включение скриптов Mikrotik из Telegram.
В общем, сделал себе бота по примеру в вышеуказанной статье. Но меня жутко напрягал тот момент, что постоянно fetch'ем скачивается файл на драгоценную флешку, и потом парсится.
Поэтому, немного покурил Wiki/Scripting, и у меня получилось обойтись без файла.
Принципиальные изменения внесены в самом начале скрипта — вместо того, чтобы скачивать fetch'ем файл, и потом его парсить, как в оригинальном скрипте:
воспользуемся нововведением RoS 6.43
и напишем команду, которая загоняет данные напрямую в переменную content, без скачивания файла на флешку:
Но имеем один неприятный момент. Функция fetch, в нашем случае, отдаёт результат в виде массива, то есть
а нам нужно проверить длину полученного сообщения на предмет того, поступала роутеру какая-нибудь команда, или нет, то есть длину поля data. В оригинальном скрипте это делается командой
но мы же решили, что никакие файлы на флешку писаться не будут.
Воспользуемся командой len — но она нам отдаёт размер массива. То есть, для команды
она вернёт значение 5 — количество элементов массива. Ну, ничего страшного — переприсвоим переменной content значение одного только поля data:
Теперь у нас в переменной content находится не массив
а строка
что нам и нужно. Теперь можем писать условие:
23 — потому что длина строки, которую нам возвращает Telegram, в случае, если боту не поступила ни одна команда —
Ещё, в сравнении с оригинальным скриптом, изменена строка
и выброшена ненужная переменная $lastEnd, вместо неё используется параметр -1, как и положено по документации.
В результате, всё работает, как задумано, но без скачивания файла и израсходования ресурса флешки.
Попутно, как довольно-таки приятный бонус, отсутствует так ранее напрягавший спам в логе каждых 10-20-30 секунд (или какой там у вас интервал опроса Телеграма) в виде:
Скрипт целиком у меня выглядит так:
Имейте в виду, что здесь описана лишь модификация части скрипта; за полной инструкцией по созданию Telegram-бота обращайтесь к оригинальной статье.
В общем, сделал себе бота по примеру в вышеуказанной статье. Но меня жутко напрягал тот момент, что постоянно fetch'ем скачивается файл на драгоценную флешку, и потом парсится.
Поэтому, немного покурил Wiki/Scripting, и у меня получилось обойтись без файла.
Принципиальные изменения внесены в самом начале скрипта — вместо того, чтобы скачивать fetch'ем файл, и потом его парсить, как в оригинальном скрипте:
:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates") ;
:global content [/file get [/file find name=getUpdates] contents] ;
воспользуемся нововведением RoS 6.43
Since RouterOS v6.43 it is possible to save the result of fetch command to a variable.
и напишем команду, которая загоняет данные напрямую в переменную content, без скачивания файла на флешку:
:global content [/tool fetch url=("https://api.telegram.org/".$botID."/getUpdates") as-value output=user];
Но имеем один неприятный момент. Функция fetch, в нашем случае, отдаёт результат в виде массива, то есть
data={"ok":true,"result":[]};
downloaded=0;
duration=00:00:01;
status=finished;
total=0
а нам нужно проверить длину полученного сообщения на предмет того, поступала роутеру какая-нибудь команда, или нет, то есть длину поля data. В оригинальном скрипте это делается командой
:if ( [/file get [/file find name=getUpdates] size] > 50 ) do={
но мы же решили, что никакие файлы на флешку писаться не будут.
Воспользуемся командой len — но она нам отдаёт размер массива. То есть, для команды
/tool fetch url=("https://api.telegram.org/".$botID."/getUpdates")
она вернёт значение 5 — количество элементов массива. Ну, ничего страшного — переприсвоим переменной content значение одного только поля data:
:set content ($content ->"data")
Теперь у нас в переменной content находится не массив
data={"ok":true,"result":[]};
downloaded=0;
duration=00:00:01;
status=finished;
total=0
а строка
{"ok":true,"result":[]};
что нам и нужно. Теперь можем писать условие:
:if ([:len $content] > 23 ) do={
23 — потому что длина строки, которую нам возвращает Telegram, в случае, если боту не поступила ни одна команда —
{"ok":true,"result":[]}
— составляет как раз 23 символа.Ещё, в сравнении с оригинальным скриптом, изменена строка
:local message [:pick $content ($startLoc + 1) $endLoc] ;
и выброшена ненужная переменная $lastEnd, вместо неё используется параметр -1, как и положено по документации.
В результате, всё работает, как задумано, но без скачивания файла и израсходования ресурса флешки.
Попутно, как довольно-таки приятный бонус, отсутствует так ранее напрягавший спам в логе каждых 10-20-30 секунд (или какой там у вас интервал опроса Телеграма) в виде:
22:33:09 info fetch: file "getUpdates" downloaded
Скрипт целиком у меня выглядит так:
Тело скрипта
:global content [/tool fetch url=("https://api.telegram.org/".$botID."/getUpdates") as-value output=user];
:set content ($content ->"data")
:global startLoc 0;
:global endLoc 0;
:if ([:len $content] > 23 ) do={
:set startLoc [:find $content "update_id" -1 ] ;
:set startLoc ( $startLoc + 11 ) ;
:local endLoc [:find $content "," $startLoc] ;
:local messageId ([:pick $content $startLoc $endLoc] + (1));
:put [$messageId] ;
:#log info message="updateID $messageId" ;
:set startLoc [:find $content "text" -1 ] ;
:set startLoc ( $startLoc + 7 ) ;
:local endLoc [:find $content "," ($startLoc)] ;
:set endLoc ( $endLoc - 1 ) ;
:local message [:pick $content ($startLoc + 1) $endLoc] ;
:put [$message] ;
:log warn message="Command $message received";
:set startLoc [:find $content "chat" -1 ] ;
:set startLoc ( $startLoc + 12 ) ;
:local endLoc [:find $content "," $startLoc] ;
:local chatId ([:pick $content $startLoc $endLoc]);
:put [$chatId] ;
:#log info message="chatID $chatId ";
:if (($chatId = $myChatID) and (:put [/system script find name=$message] != "")) do={
:system script run $message} else={:tool fetch url=("https://api.telegram.org/".$botID."/sendmessage\?chat_id=".$chatId."&text=I can't talk with you. ") keep-result=no};
:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates\?offset=$messageId") keep-result=no;
Имейте в виду, что здесь описана лишь модификация части скрипта; за полной инструкцией по созданию Telegram-бота обращайтесь к оригинальной статье.
Manual:Scripting
habr.com/ru/post/314108