Oddaljeno vključevanje skriptov Mikrotik prek Telegrama

Na to realizacijo me je spodbudil Aleksej Korjukin GeXoGeN svojo objavo «Oddaljeno vključevanje računalnika brezplačno, brez SMS-ov in brez oblakov, s pomočjo Mikrotika«.

In komentar v eni od skupin VK Kirilla Kazakova:

Ja, res ni varno. Raje bi napisal Telegram bota, ki sprejema ukaze za vključitev samo z mojega računa.

Odločil sem se, da napišem takega bota.

Torej, prvo, kar je treba storiti – ustvariti bota v Telegramu.

  • V iskalniku najdemo račun z imenom @botfather
  • Pritisnemo gumb Start na dnu zaslona
  • Nato mu napišemo ukaz /newbot

Potem odgovorimo na 2 enostavni vprašanji:

  • Prvo vprašanje – ime ustvarjenega bota MyMikrotikROuter
  • Drugo vprašanje – vzdevek ustvarjenega bota (mora se končati z bot) MikrotikROuter_bot

V odgovor dobimo token našega bota, v mojem primeru je to:

Uporabite ta token za dostop do HTTP API: 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

Oddaljeno vključevanje skriptov Mikrotik prek Telegrama
Nato moramo poiskati našega bota po imenu @MikrotikROuter_bot in pritisniti gumb Start.

Nato odprite brskalnik in vnesite naslednjo vrstico:

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

Kjer je XXXXXXXXXXXXXXXXXX – token vašega bota.

Odprla se bo stran približno takšne oblike:

Oddaljeno vključevanje skriptov Mikrotik prek Telegrama

Na njej poiščite naslednje besedilo:

«chat»:{«id»:631290,

Torej, imamo vse potrebne informacije za pisanje skript za Mikrotik, natančneje:

Token bota: 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

ID chata, kamor naj piše: 631290

Za preverjanje lahko vstopimo prek brskalnika:

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

Dobili bi rezultat:

Oddaljeno vključevanje skriptov Mikrotik prek Telegrama

Za naše udobje takoj dodamo ukaze za bota:

Najdemo račun z imenom @botfather
Nato mu napišemo ukaz /setcommands

  • Vpraša, kateremu botu

Pišemo:
@MikrotikROuter_bot

Dodajamo ukaze:

  • helloworld< — Testna sporočilo za chat 1
  • itsworking — Testno sporočilo za chat 2
  • wolmypc — Prebudi moj računalnik

Zdaj, če v čatu vnesemo «/», bi morali dobiti:

Oddaljeno vključevanje skriptov Mikrotik prek Telegrama

Zdaj preidemo na MikroTik.

V RouterOS-u je konzolna orodje za kopiranje datotek preko ftp ali http/https, orodje se imenuje fetch, prav to bomo uporabili.

Odprite terminal in vnesite:

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

Upoštevajte, da je v MikroTik potrebno "" za zaščito znaka "?" v URL-ju.

Dobili bi rezultat:

Oddaljeno vključevanje skriptov Mikrotik prek Telegrama

Zdaj preidemo na skripte:

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

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-result
    t=no"

Ne pozabite navesti pravilen mac naslov in ime vmesnika, pa tudi bot-token in chat_id.

Zdaj bom malo pojasnil, kaj delajo:

Skripti «helloworld» pošljejo sporočilo: » Hello, world! » v naš klepet z botom.
Skripti «itsworking» pošljejo sporočilo: » Test OK, deluje! » v naš klepet z botom.
Ti skripti so namenjeni demonstraciji delovanja.
Skript «wolmypc» sem dodal kot eno od možnih rešitev.
Po izvedbi skripte bot v klepetu zapiše «wol OK».
V bistvu lahko zaženeš katerikoli skript.

Ustvarimo nalogo:

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

Berljiva oblikane razumem, zakaj, toda delovni skript ne razkrije globalnih podatkov, dodal sem skript pri zagonu sistema.
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") ;

Telegram

: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=Ne morem se pogovarjati s tabo. ") keep-result=no} ;
:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates?offset=$messageId") keep-result=no; 
} 

Kako to funkcionira

Nalagamo naša sporočila «getUpdates» vsakih 30 sekund, nato jih obdelamo, da ugotovimo update_id (številka sporočila) in text (naša navodila) in chat_id . Privzeto getUpdates izpiše od 1 do 100 sporočil, za udobje po prebranih ukazih sporočilo izbrišemo. V Telegram API je navedeno, da je za branje sporočila potrebno številko sporočila + 1.

/getUpdates?offset=update_id + 1

Vse je preizkušeno na Mikrotik rb915 RouterOS 6.37.1.
Če pošljete takoj veliko ukazov, se bodo vsi po vrsti izvajali s 30-sekundnim intervalom.

P.S. Iskrena hvala Kirillu Kazakovu za idejo in mojemu prijatelju Aleksandru za pomoč pri skriptih.

Povezave

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)

UPD

Нашли с 7Stuntman7 что файл с выше ~ 14 сообщений перестает обрабатываться командой find (ограничения Mikrotik). Поэтому в будущем скрипт переделаю на lua, спасибо. 7Stuntman7 за это, про lua не знал.

UPD 08.12.2016

в Telegram, видимо, немного изменили «выхлоп» getUpdate. Теперь в основном скрипте нужно поправить смещение сообщения с 2 на 1

spremembe

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

заменить на:

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

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster