Отдалечено включване на скриптове Mikrotik от Telegram

Тази реализация беше провокирана от Александр Корюкин GeXoGeN с публикацията му "Дистанционно включване на компютър безплатно, без SMS и без облаци, с помощта на Mikrotik«.

И коментар в една от групите на ВК на Кирил Казаков:

Така е, не е много сигурно. По-добре бих направил телеграм бот, който приема команди само от моя акаунт за включване.

Реших да напиша такъв бот.

И така, първото нещо, което трябва да направим, е да създадем бот в Telegram.

  • Намираме акаунт с името @botfather
  • Натискаме бутона Start в долната част на екрана
  • След това пишем командата /newbot

После отговаряме на два несложни въпроса:

  • Първият въпрос е името на създаваното бота MyMikrotikROuter
  • Вторият въпрос е никнейм на създаваното бота (требва да завършва на bot) MikrotikROuter_bot

В отговор ще получим токена на бота ни, в моя случай това е:

Използвайте този токен за достъп до HTTP API: 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

Отдалечено включване на скриптове Mikrotik от Telegram
След това трябва да намерим бота ни в търсене по име @MikrotikROuter_bot и натиснете бутона Start.

След това трябва да отворим браузъра и да въведем следната строка:

 https://api.telegram.org/botXXXXXXXXXXXXXXXXXX/getUpdates

Където XXXXXXXXXXXXXXXXXX е токена на вашия бот.

Ще се отвори страница със следния вид:

Отдалечено включване на скриптове Mikrotik от Telegram

Намираме следния текст на нея:

"chat":{ "id":631290,

И така, имаме цялата необходима информация за написването на скриптове за Mikrotik, а именно:

Токен на бота: 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

ID на чата, в който той трябва да пише: 631290

За проверка можем да влезем през браузъра:

https://api.telegram.org/bot265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4/sendmessage?chat_id=631290&text=test

Трябва да получим резултата:

Отдалечено включване на скриптове Mikrotik от Telegram

За наше удобство, веднага добавяме команди за бота:

Намираме акаунт с името @botfather
След което пишем команда на него /setcommands

  • Той ще попита за кой бот

Записваме:
@MikrotikROuter_bot

Добавяме команди:

  • helloworld< — Тестово съобщение в чат 1
  • itsworking — Тестово съобщение в чат 2
  • wolmypc — събуди моя компютър

Сега ако напишете в чата " /", трябва да получите:

Отдалечено включване на скриптове Mikrotik от Telegram

Сега преминаваме към MikroTik.

В RouterOS има конзолна утилита за копиране на файлове чрез ftp или http/https, утилитата се нарича fetch, именно нея ще използваме.

Отваряме terminal и въвеждаме:

/tool fetch url="https://api.telegram.org/bot265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4/sendmessage?chat_id=631290&text=test " keep-result=no

Обърнете внимание, че в MikroTik е необходим "" за екраниране на знака "?" в URL.

Трябва да получим резултата:

Отдалечено включване на скриптове Mikrotik от Telegram

Сега преминаваме към скриптовете:

helloworld

system script add name="helloworld" policy=read source={/tool fetch url="https://api.telegram.org/bot265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4/sendmessage?chat_id=631290&text=Hello,world! " keep-result=no}

itsworking

system script add name="itsworking" policy=read source={/tool fetch url="https://api.telegram.org/bot265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4/sendmessage?chat_id=631290&text=Test OK, it's Working " keep-result=no}

wolmypc

системен скрипт добавя име="wolmypc" политика=четене източник="/tool wol mac=XX:XX:XX:XX:XX:XX интерфейс=ifnamer
    n/tool fetch url="https://api.telegram.org/boXXXXXXXXXXXXXXXXXXX?chat_id=631290&text=wol OK" запази-резултат
    =не"

Не забравяйте да посочите правилния mac и името на интерфейса, както и bot-token и chat_id.

Сега ще обясня какво правят:

Скриптът «helloworld» изпраща съобщение: » Здравей, свят!» в нашия чат с бота.
Скриптът «itsworking» изпраща съобщение: » Тест OK, работи!» в нашия чат с бота.
Тези скриптове са за демонстрация на работа.
Скриптът «wolmypc» добавих като една от възможните реализации.
След изпълнението на скрипта ботът ще напише в чата «wol OK».
Всъщност, можете да стартирате абсолютно всеки скрипт.

Създаваме задача:

Telegram.src

/system scheduler
add interval=30s name=Telegram on-event=":tool fetch url=("https://api.telegr
    am.org/".$botID."/getUpdates") ;r
    n:global content [/file get [/file find name=getUpdates] contents] ;r
    n:global startLoc 0;r
    n:global endLoc 0;r
    nr
    n:if ( [/file get [/file find name=getUpdates] size] > 50 ) do={r
    nr
    n:set startLoc  [:find $content "update_id" $lastEnd ] ;r
    n:set startLoc ( $startLoc + 11 ) ;r
    n:local endLoc [:find $content "," $startLoc] ;r
    n:local messageId ([:pick $content $startLoc $endLoc] + (1));r
    n:put [$messageId] ;r
    n:#log info message="updateID $messageId" ;r
    nr
    n:set startLoc  [:find $content "text" $lastEnd ] ;r
    n:set startLoc ( $startLoc  + 7 ) ;r
    n:local endLoc [:find $content "," ($startLoc)] ;r
    n:set endLoc ( $endLoc - 1 ) ;r
    n:local message [:pick $content ($startLoc + 2) $endLoc] ;r
    n:put [$message] ;r
    n:#log info message="message $message ";r
    nr
    n:set startLoc  [:find $content "chat" $lastEnd ] ;r
    n:set startLoc ( $startLoc + 12 ) ;r
    n:local endLoc [:find $content "," $startLoc] ;r
    n:local chatId ([:pick $content $startLoc $endLoc]);r
    n:put [$chatId] ;r
    n:#log info message="chatID $chatId ";r
    nr
    n:if (($chatId = $myChatID) and (:put [/system script find name=$messa
    ge] != "")) do={r
    n:system script run $message} else={:tool fetch url=("https://api.teleg
    ram.org/".$botID."/sendmessage?chat_id=".$chatId."&text=I can't t
    alk with you. ") keep-result=no} ;r
    n:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates?
    offset=$messageId") keep-result=no; r
    n} r
    n" policy=
    ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon 
    start-date=nov/02/2010 start-time=00:00:00
	
add name=Telegram-startup on-event=":delay 5r
    n:global botID "botXXXXXXXXXXXXXXXXXX" ;r
    n:global myChatID "631290" ;r
    n:global startLoc 0;r
    n:global endLoc 0;r
    n:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates") 
    ;" policy=
    ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon 
    start-time=startup

Читаем виднеясно защо, но от работещия скрипт не се излагат глобалните данни, добавих скрипта при зареждане на системата.
Telegram-startup

:забавяне 5
:глобален botID "botXXXXXXXXXXXXXXXXXX" ;   token bot
:глобален myChatID "xxxxxx" ;                               chat_id
:глобален startLoc 0;
:глобален endLoc 0;
:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates") ;

Телеграм

:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates") ;
:глобален content [/file get [/file find name=getUpdates] съдържание] ;
:глобален startLoc 0;
:глобален endLoc 0;

:ако ( [/file get [/file find name=getUpdates] размер] > 50 ) направи={

:постави startLoc  [:find $content "update_id" $lastEnd ] ;
:постави startLoc ( $startLoc + 11 ) ;
:локален endLoc [:find $content "," $startLoc] ;
:локален messageId ([:pick $content $startLoc $endLoc] + (1));
:постави [$messageId] ;
#:log info message="updateID $messageId" ;

:постави startLoc  [:find $content "text" $lastEnd ] ;
:постави startLoc ( $startLoc  + 7 ) ;
:локален endLoc [:find $content "," ($startLoc)] ;
:постави endLoc ( $endLoc - 1 ) ;
:локален message [:pick $content ($startLoc + 2) $endLoc] ;
:постави [$message] ;
#:log info message="message $message ";

:постави startLoc  [:find $content "chat" $lastEnd ] ;
:постави startLoc ( $startLoc + 12 ) ;
:локален endLoc [:find $content "," $startLoc] ;
:локален chatId ([:pick $content $startLoc $endLoc]);
:постави [$chatId] ;
#:log info message="chatID $chatId ";

:ако (($chatId = $myChatID) и (:постави [/system script find name=$message] != "")) направи={
:system script run $message} иначе={:tool fetch url=("https://api.telegram.org/".$botID."/sendmessage?chat_id=".$chatId."&text=Не мога да говоря с вас.") запази-резултат=не} ;
:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates?offset=$messageId") запази-резултат=не;
} 

Как работи това

Сваляме нашите съобщения «getUpdates» на всеки 30 сек., след това парсим, за да разберем update_id (номер на съобщението) и text (нашите команди) и chat_id . По подразбиране getUpdates извежда от 1 до 100 съобщения, за удобство след прочитането на командата, съобщението се изтрива. В Telegram api е посочено, че за да прочетете съобщение, число на съобщението + 1

/getUpdates?offset=update_id + 1

Всичко е проверено на Mikrotik rb915 RouterOS 6.37.1
Ако изпратите веднага много команди, те ще бъдат изпълнявани последователно на интервали от 30 сек.

P.S. Огромно благодаря на Кирил Казаков за идеята и на моя приятел Александър за помощта със скриптовете.

Връзки

habrahabr.ru/post/313794
1spla.ru/index.php/blog/telegram_bot_for_mikrotik
core.telegram.org/bots/api
wiki.mikrotik.com/wiki/Manual:Скриптинг

ъпд:

03:11:16

Обновил скриптовете:

Добавих проверка за chat_id
Проверка за ловкост, ако някой напише на нашия бот, той ще му отговори: » Не мога да говоря с теб. «, подобно ще отговори и на нас, ако не разпознае командата.
След изпълнение на командата, ботът отписва в чата (вж. Скрипт wolmypc)

UPD

Намерихме с 7Stuntman7 че файлът с над ~ 14 съобщения спира да се обработва от командата find (ограничения на Mikrotik). Затова в бъдеще ще преработя скрипта на lua благодаря 7Stuntman7 за това, не знаех за lua.

ЪПД 08.12.2016

в Telegram явно малко промениха „изхода“ getUpdate. Сега в основния скрипт е необходимо да коригирате изместването на съобщението от 2 на 1

промени

:local message [:pick $content ($startLoc + 2) $endLoc] ;

заменете с:

:local message [:pick $content ($startLoc + 1) $endLoc] ;

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster