Всех с прошедшим праздником. Данная тема является более лучшей версией того, что я писал в далеком 2016 тут.
В целом принцип работы не изменился, с той лишь разницей, что теперь он отрабатывает мгновенно без задержек.
Закидываем скрипт в Mikrotik, меняем BotID и ChatID на свои и создаем на него schedule. Ставим параметр «Start Time» на startup (Запуск скрипта при старте.)
«Interval»: 00:00:00
В остальном все как и было.
За пару лет пользования был выявлен баг, по непонятным причинам слабенькие Mikrotik почему то останавливают скрипт, на более мощных работает без остановок.
Для этих целей накидал костыль WatchDog. тут меняем имя скрипта на то какое указывали выше. и ставим интервал перезапуска 5 минут. Каждые 5 минут наша «смотрящая собака» будет проверять скрипт, и если он не работает, то запустит его.
Ну и на десерт, скрипт взят с форума Mikrotik.
Отправляет важные топики из лога нам в телегу.
Закидываем скрипт в schedule и указываем интервал перезапуска каждые 5 минут, меняем BotID и ChatID на свои.
Получим результат:
В целом принцип работы не изменился, с той лишь разницей, что теперь он отрабатывает мгновенно без задержек.
Закидываем скрипт в Mikrotik, меняем BotID и ChatID на свои и создаем на него schedule. Ставим параметр «Start Time» на startup (Запуск скрипта при старте.)
«Interval»: 00:00:00
В остальном все как и было.
Telegram-v2
:delay 10
:global mtIdentity [/system identity get name];
:global botID "botXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXX" ;
:global myChatID "YYYYYY" ;
:local chatId 0;
:local messageId 0;
:local parse do={
:local startLoc ([:find $content $variable -1] + [:len $variable] + 2);
:local commaLoc ([:find $content "," $startLoc] - 1 + 1);
:local braceLoc ([:find $content "}" $startLoc] - 1 + 1);
:local endLoc $commaLoc;
:local startSymbol [:pick $content $startLoc]
:if ($braceLoc != 0 and ($commaLoc = 0 or $braceLoc < $commaLoc)) do={
:set endLoc $braceLoc;
};
:if ($startSymbol = "{") do={
:set endLoc ($braceLoc + 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]
#:log info $message;
:return $message;
}
:while ( true ) do={
:do {
#:log info "https://api.telegram.org/$botID/getUpdates\?offset=$messageId&limit=1&allowed_updates=message&timeout=60";
:tool fetch url=("https://api.telegram.org/$botID/getUpdates\?offset=$messageId&limit=1&allowed_updates=message&timeout=60") dst-path="getUpdates";
:local content [/file get [/file find name=getUpdates] contents] ;
#:log info $content;
:if ([:len $content] > 30) do={
:set messageId ([$parse content=$content variable="update_id"] + 1)
:local message [$parse content=$content variable="text" quotas=true]
:local chat [$parse content=$content variable="chat"]
:local chatId [$parse content=$chat variable="id"]
:if (($chatId = $myChatID) and ([/system script find name=$message] != "")) do={
:system script run $message;
} else={
:tool fetch url=("https://api.telegram.org/$botID/sendmessage\?chat_id=$chatId&text=$mtIdentity: Unknown command: $message") keep-result=no
}
}
} on-error={}
};
За пару лет пользования был выявлен баг, по непонятным причинам слабенькие Mikrotik почему то останавливают скрипт, на более мощных работает без остановок.
Для этих целей накидал костыль WatchDog. тут меняем имя скрипта на то какое указывали выше. и ставим интервал перезапуска 5 минут. Каждые 5 минут наша «смотрящая собака» будет проверять скрипт, и если он не работает, то запустит его.
WatchDogT.me
:global scriptname "t.me"
:if ([:len [/system script job find script=$"scriptname"]] > 0) do={
:log info "$scriptname Already Running - killing old script before continuing"
:foreach counter in=[/system script job find script=$"scriptname"] do={
/system script job remove $counter
}
}
/system script run $scriptname
Ну и на десерт, скрипт взят с форума Mikrotik.
Отправляет важные топики из лога нам в телегу.
Закидываем скрипт в schedule и указываем интервал перезапуска каждые 5 минут, меняем BotID и ChatID на свои.
Notify-log
:global lastTime
:global output
:global mtIdentity [/system identity get name];
:global botID "botXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXX" ;
:global myChatID "YYYYYY" ;
:local LogGet [ :toarray [ /log find topics~"critical" || message~"login failure" || message~"[Ff]ailure" ] ] ;
:local LogtLineCount [ :len $LogGet ] ;
if ($LogtLineCount > 0) do={
:local currentTime "$[ /log get [ :pick $LogGet ($LogtLineCount -1) ] time ]";
:if ([:len $currentTime] = 10 ) do={
:set currentTime [ :pick $currentTime 0 10 ];
}
:set output "$currentTime - $[/log get [ :pick $LogGet ($LogtLineCount-1) ] message ]";
:if (([:len $lastTime] < 1) || (([:len $lastTime] > 0) && ($lastTime != $currentTime))) do={
:set lastTime $currentTime ;
:tool fetch url=("https://api.telegram.org/$botID/sendmessage\?chat_id=$myChatID&text=\"$mtIdentity\" : $output") keep-result=no
}
}
Получим результат:
NeoBeZ
не поехало, проверял на двух микротиках, первый домашний hex s, второй CHR поднятый у AWS. Тестил скрипт Notify-log, BotID\MyChatID поменял.
отправка сообщений через tool fetch проходит успешно, в чём затык?
dimonw Автор
ну если fetch проходит. должно быть все ок. вы после того как скрипт закидываете.
создаете какой то прецедент, который вам должно отправить? попробуйте подключиться с заведомо неверными логин паролем к примеру.
NeoBeZ
dimonw Автор
кавычки не те :) при вставке кода видимо заменило. сейчас исправлю.
проверьте должны быть такие и дальше по коду аналогично.
NeoBeZ
поехало! спасибо!
Вообще конечно хорошая фича.
soyu22
Подскажите а как при этом решаете проблему доступа к api.telegram.org а то он вроде как заблокирован.
dimonw Автор
Ну по началу пока провайдер не научился нормально блокировать, отшибал их заглушку и все замечательно работало. Но через пол года они начали как то жестко блокать, (даже переписал скрипты под SLACK. Но не весь функционал получился нормальным) разбираться уже не стал, просто кинул FreeVpn, чисто для телеги на Mikrotik. Работает все отлично.
soyu22
Если не затруднит не подскажете какой бесплатный VPN вы используете?
NeoBeZ
dimonw Автор
Ну CHR это я так понимаю VPN сервер на AWS ?).
Я не стал заморачиваться, пользую халявный.
NeoBeZ
так же пользую халявный))
AWS на год халявный, потом перерегать и залить конфиг не долго.
dimonw Автор
я слишком ленивый. :) этож через год какие то манипуляции делать надо будет. Но спасибо за инфо, надо будет посмотреть :) давно хотел познакомиться с AWS.
bewza
ИМХО использование
:while ( true )
без задержки — лишняя нагрузка на ваш роутер и потеря встроенного функционала scheduler, но каждому своё.В любом случае, если вы решили использовать этот подход — лучше не писать response на диск, учитывая что у вас там одно короткое сообщение.
:local httpResponse [:tool fetch url=$requestUrl as-value output=user]
:local content ($httpResponse->"data");
NeoBeZ
Попробовал немного изменить код скрипта, в результате теперь приходят уведомления о логине на устройство и о подключении юзеров по vpn, но failure-сообщения отвалились, что я делаю не так?
:global output
:global mtIdentity [/system identity get name];
:global botID «botXXXXXXXX:YYYYYYYYYYYYYYYYY»;
:global myChatID «ZZZZZZZZZ»;
:local LogGet [ :toarray [ /log find topics~«critical» || message~«login failure» || message~"[Ff]ailure" ] ];
:local LogGet [ :toarray [ /log find topics~«account» || message~«logged» || message~"[Ll]ogged" ] ];
:local LogGet [ :toarray [ /log find topics~«account» || message~«connected» || message~"[Cc]onnected" ] ];
:local LogtLineCount [ :len $LogGet ];
if ($LogtLineCount > 0) do={
:local currentTime "$[ /log get [ :pick $LogGet ($LogtLineCount -1) ] time ]";
:if ([:len $currentTime] = 10 ) do={
:set currentTime [ :pick $currentTime 0 10 ];
}
:set output "$currentTime — $[/log get [ :pick $LogGet ($LogtLineCount-1) ] message ]";
:if (([:len $lastTime] < 1) || (([:len $lastTime] > 0) && ($lastTime != $currentTime))) do={
:set lastTime $currentTime;
:tool fetch url=(«api.telegram.org$botID/sendmessage\?chat_id=$myChatID&text=\»$mtIdentity\": $output") keep-result=no
}
}
Raivon
Вы переменной LogGet три раза подряд присваиваете разные значения. LogGet будет содержать значение, присвоенное последним. Не нашел в мануале функций для работы с массивами, поэтому придётся использовать три разные переменные — свою для каждой выборки из лога.
NeoBeZ
Согласен, но почему тогда обрабатываются вот эти две строчки?
:local LogGet [ :toarray [ /log find topics~«account» || message~«connected» || message~"[Cc]onnected" ] ];
haos
Можно добавить искомые строки logged и connected в одну переменную: