Выдаленае ўключэнне скрыптоў Mikrotik з Telegram

На дадзеную рэалізацыю мяне падштурхнуў Аляксандр Карукін. GeXoGeN сваёй публікацыяй «Выдаленае ўключэнне кампутара бясплатна, без SMS і без аблокаў, з дапамогай Mikrotik«.

І каментар у адной з груп ВК Кірыла Казакова:

Ды ўжо, зусім не сек'юрна. Я б лепш напісаў тэлеграм бота, які прымае толькі з майго акаўнта каманды на ўключэнне.

Я вырашыў напісаць такога робата.

Такім чынам, першае, што трэба зрабіць - гэта стварыць робата ў telegram.

  • Знаходзім у пошуку акаўнт з імем @botfather
  • Націскаем на кнопку Start у ніжняй частцы экрана
  • Пасля чаго пішам яму каманду /newbot

Потым адказваем на 2 нескладаныя пытанні:

  • Першае пытанне – імя стваранага робата MyMikrotikROuter
  • Другое пытанне – нік ствараемага робата (павінен заканчвацца на bot) MikrotikROuter_bot

У адказ атрымаем токен нашага робата, у маім выпадку гэта:

З дапамогай гэтага тэку Access 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< — Test message on chat 1
  • itsworking - Test Message on chat 2
  • wolmypc - wake Up my PC

Цяпер калі набраць у чаце "/", то павінны атрымаць:

Выдаленае ўключэнне скрыптоў Mikrotik з Telegram

Цяпер пераходзім да MikroTik.

У RouterOS ёсць кансольная ўтыліта для капіявання файлаў праз ftp ці http/https, утыліта завецца fetch, менавіта ёй мы і будзем карыстацца.

Адчыняны тэрмінал і ўводзім:

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

Звярніце ўвагу ў MikroTik неабходны» для экранавання знака «?» у URL.

Павінны атрымаць вынік:

Выдаленае ўключэнне скрыптоў Mikrotik з Telegram

Цяпер пераходзім да срыптаў:

Прывітанне Сусвет

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

system script add name="wolmypc" policy=read source="/tool wol mac=XX:XX:XX:XX:XX:XX interface=ifnamer
    n/tool fetch url="https://api.telegram.org/boXXXXXXXXXXXXXXXXXXX?chat_id=631290&text=wol OK" keep-resul
    t=no"

Не забываем паказаць правільны mac і імя інтэрфейс, а таксама bot-token і chat_id.

Цяпер крыху растлумачу што яны раблю:

Скрыпт "helloworld" адпраўляе паведамленне: » Hello,world!» у наш чат з ботам.
Скрыпт "itsworking" адпраўляе паведамленне: » Test OK, it's Working!» у наш чат з ботам.
Дадзеныя скрыпты для дэманстрацыі працы.
Скрыпт "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

:delay 5
:global botID "botXXXXXXXXXXXXXXXXXX" ;   token bot
:global myChatID "xxxxxx" ;                               chat_id
:global startLoc 0;
:global endLoc 0;
:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates") ;

Тэлеграма

:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates") ;
:global content [/file get [/file find name=getUpdates] contents] ;
:global startLoc 0;
:global endLoc 0;

:if ( [/file get [/file find name=getUpdates] size] > 50 ) do={

:set startLoc  [:find $content "update_id" $lastEnd ] ;
: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" $lastEnd ] ;
:set startLoc ( $startLoc  + 7 ) ;
:local endLoc [:find $content "," ($startLoc)] ;
:set endLoc ( $endLoc - 1 ) ;
:local message [:pick $content ($startLoc + 2) $endLoc] ;
:put [$message] ;
#:log info message="message $message ";

:set startLoc  [:find $content "chat" $lastEnd ] ;
: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; 
} 

Як гэта працуе

Спампоўваем нашы паведамленні «getUpdates» кожныя 30 сек., затым парысім, каб пазнаць update_id (нумар паведамлення) і тэкст (нашы каманды) і chat_id . Па змаўчанні getUpdates выводзіць ад 1 да 100 паведамленняў, для зручнасці пасля прачытання каманды, паведамленне выдаляем. у Telegram api сказана, каб прачытаць паведамленне неабходна нумар паведамлення + 1

/getUpdates?offset=update_id + 1

Усё праверана на Mikrotik rb915 RouterOS 6.37.1
Калі адправіць адразу шмат каманд, яны ўсё па чарзе будуць выконвацца з інтэрвалам 30 сек.

PS Вялікі дзякуй Кірылу Казакову за ідэю і майму сябру Аляксандру за дапамогу са скрыптамі.

Спасылкі

habrahabr.ru/post/313794
1spla.ru/index.php/blog/telegram_bot_for_mikrotik
core.telegram.org/bots/api
wiki.mikrotik.com/wiki/Manual:Scripting

upd:

03:11:16

Дапрацаваў скрыпты:

Дадаў праверку на chat_id
Праверка на дурня, калі хтосьці напіша нашаму робату, ён адкажа яму: » I can't talk with you. «, аналагічна адкажа нам, калі не распазнае каманду.
Па выкананні каманды, бот адпісваецца ў чат (гл. Скрыпт wolmypc)

ДУП

Знайшлі з 7Stuntman7 што файл з вышэй ~ 14 паведамленняў, перастае апрацоўвацца камандай find (абмежаванні Mikrotik). Таму ў будучыні скрыпт перараблю на lua дзякуй 7Stuntman7 за гэта, пра lua не ведаў.

UPD 08.12.2016

у Telegram мабыць трохі змянілі "выхлап" getUpdate. зараз у асноўным скрыпце трэба паправіць зрушэнне паведамлення з 2 на 1

змены

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

заменить на :

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

Крыніца: habr.com