Fernaktivierung von Mikrotik-Skripten über Telegram

Alexander Koryukin hat mich zu dieser Umsetzung gedrängt GeXoGeN mit seiner VeröffentlichungKostenloses Ferneinschalten des Computers, ohne SMS und ohne Clouds, mit Mikrotik«.

Und ein Kommentar in einer der VK-Gruppen von Kirill Kazakov:

Ja, es ist überhaupt nicht sicher. Ich würde lieber einen Telegram-Bot schreiben, der nur Aktivierungsbefehle von meinem Konto akzeptiert.

Ich habe beschlossen, einen solchen Bot zu schreiben.

Als erstes müssen Sie also einen Bot in Telegram erstellen.

  • Wir finden in der Suche ein Konto namens @botfather
  • Klicken Sie unten auf dem Bildschirm auf die Schaltfläche „Start“.
  • Dann schreiben wir ihm den Befehl /newbot

Dann beantworten wir 2 einfache Fragen:

  • Die erste Frage ist der Name des zu erstellenden Bots. MyMikrotikRouter
  • Die zweite Frage ist der Spitzname des zu erstellenden Bots (sollte mit „bot“ enden) MikrotikROuter_bot

Als Antwort erhalten wir den Token unseres Bots, in meinem Fall ist es:

Verwenden Sie dieses Token, um auf die HTTP-API zuzugreifen: 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

Fernaktivierung von Mikrotik-Skripten über Telegram
Dann müssen Sie unseren Bot in der Suche nach Namen finden @MikrotikROuter_bot und drücken Sie die Start-Taste.

Danach müssen Sie den Browser öffnen und die folgende Zeile eingeben:

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

Wobei XXXXXXXXXXXXXXXXXX das Token Ihres Bots ist.

Es öffnet sich eine Seite ähnlich der folgenden:

Fernaktivierung von Mikrotik-Skripten über Telegram

Darauf finden wir folgenden Text:

"chat":{"id":631290,

Wir haben also alle notwendigen Informationen zum Schreiben von Skripten für Mikrotik, nämlich:

Bot-Token: 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

Chat-ID, wo er schreiben soll: 631290

Zur Überprüfung können wir den Browser durchgehen:

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

Sollte das Ergebnis erhalten:

Fernaktivierung von Mikrotik-Skripten über Telegram

Der Einfachheit halber werden wir sofort Befehle für den Bot hinzufügen:

Ein Konto mit einem Namen finden @ botfather
Dann schreiben wir ihm einen Befehl / setcommands

  • Er wird fragen, welcher Bot

Wir schreiben:
@MikrotikROuter_bot

Befehle hinzufügen:

  • helloworld< – Testnachricht in Chat 1
  • itsworking-Test-Nachricht in Chat 2
  • wolmypc-wecke meinen PC auf

Wenn Sie nun im Chat „/“ eingeben, sollten Sie Folgendes erhalten:

Fernaktivierung von Mikrotik-Skripten über Telegram

Kommen wir nun zu MikroTik.

RouterOS verfügt über ein Konsolendienstprogramm zum Kopieren von Dateien über FTP oder http/https. Das Dienstprogramm heißt fetch und wird von uns verwendet.

Öffnen Terminal und geben Sie ein:

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

Bitte beachten Sie, dass MikroTik „» dem Zeichen entkommen «?' in der URL.

Sollte das Ergebnis erhalten:

Fernaktivierung von Mikrotik-Skripten über Telegram

Kommen wir nun zu den Skripten:

Hallo Welt

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}

es funktioniert

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"

Vergessen Sie nicht, den korrekten Mac- und Schnittstellennamen sowie Bot-Token und Chat-ID anzugeben.

Jetzt werde ich ein wenig erklären, was sie tun:

Das „helloworld“-Skript sendet eine Nachricht: „Hello, world!“ zu unserem Chat mit dem Bot.
Das „itsworking“-Skript sendet eine Nachricht: „Test OK, es funktioniert!“ zu unserem Chat mit dem Bot.
Diese Skripte dienen Demonstrationszwecken.
Ich habe das Skript „wolmypc“ als eine der möglichen Implementierungen hinzugefügt.
Nach der Ausführung des Skripts schreibt der Bot „wol OK“ in den Chat.
Tatsächlich können Sie absolut jedes Skript ausführen.

Erstellen Sie eine Aufgabe:

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

Lesbare AnsichtEs ist nicht klar, warum, aber aus dem Arbeitsskript geht hervor, dass keine globalen Daten offengelegt werden. Das Skript wurde beim Systemstart hinzugefügt.
Telegram-Start

: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=I can't talk with you. ") keep-result=no} ;
:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates?offset=$messageId") keep-result=no; 
} 

Wie funktioniert das

Laden Sie alle 30 Sekunden unsere „getUpdates“-Nachrichten herunter und analysieren Sie sie, um es herauszufinden update_id (Nachrichtennummer) und Text (unsere Teams) und chat_id . Standardmäßig zeigt getUpdates 1 bis 100 Nachrichten an. Der Einfachheit halber löschen wir die Nachricht nach dem Lesen des Befehls. Die Telegram-API sagt, dass Sie zum Lesen einer Nachricht die Nachrichtennummer + 1 benötigen

/getUpdates?offset=update_id + 1

Alles getestet auf Mikrotik rb915 RouterOS 6.37.1
Wenn Sie viele Befehle gleichzeitig senden, werden diese alle nacheinander im Abstand von 30 Sekunden ausgeführt.

PS: Vielen Dank an Kirill Kazakov für die Idee und an meinen Freund Alexander für die Hilfe bei den Drehbüchern.

Referenzen

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

upd:

03:11:16

Verbesserte Skripte:

Überprüfung für chat_id hinzugefügt
Wenn jemand unserem Bot schreibt, wird er ihm antworten: „Ich kann nicht mit dir reden.“ “, wird uns ebenfalls antworten, wenn es den Befehl nicht erkennt.
Nach Ausführung des Befehls meldet sich der Bot vom Chat ab (siehe wolmypc-Skript)

UPD

Gefunden mit 7Stuntman7 dass eine Datei mit mehr als ~14 Nachrichten nicht mehr vom Suchbefehl verarbeitet wird (Mikrotik-Einschränkungen). Daher werde ich das Skript in Zukunft auf Lua ändern, danke 7Stuntman7 Dafür wusste ich nichts über Lua.

UPD 08.12.2016

In Telegram haben sie offenbar den „Auspuff“ von getUpdate leicht geändert. Jetzt müssen Sie im Hauptskript den Nachrichtenoffset von 2 auf 1 korrigieren

Veränderungen

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

заменить на :

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

Source: habr.com