Удаленный запуск скриптов через Телеграм

Здесь выкладываем скрипты
Правила форума
Уважаемые Пользователи форума, обратите внимание!
Ни при каких обстоятельствах, Администрация форума, не несёт ответственности за какой-либо, прямой или косвенный, ущерб причиненный в результате использования материалов, взятых на этом Сайте или на любом другом сайте, на который имеется гиперссылка с данного Сайта. Возникновение неисправностей, потерю программ или данных в Ваших устройствах, даже если Администрация будет явно поставлена в известность о возможности такого ущерба.
Просим Вас быть предельно осторожными и внимательными, в использовании материалов раздела. Учитывать не только Ваши пожелания, но и границы возможностей вашего оборудования.
Ответить
Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

Добрый день.

Представляю переработанную на свой лад версию скрипта, позволяющую удалённо запускать скрипты Mikrotik через Телеграм. В скрипте использованы идеи и часть кода by Pepelxl, Virtue, GeXoGeN и Dimonw - большая им благодарность!
Для работы скрипта должны быть заранее известны BotID и ChatID.
Скрипт необходимо добавить в System/Sheduler и установить запуск с периодичностью не менее одного раза минуту.
Алгоритм работы следующий: каждый раз при активации скрипта запрашивается ПОСЛЕДНЕЕ сообщение в группе с указанным BotID и если разница между временем отправки сообщения в Телеграм и текущим временем на Mikrotik составляет менее 1 минуты, тогда производится запуск скрипта с именем, указанным в теле сообщения.

На что нужно обратить внимание:
1. Работа скрипта привязана к текущему времени, по этой причине на роутере должны быть правильно выставлены время и часовой пояс.
2. Сообщения для роутера должны начинаться с символа "/". Например, если нужно запустить скрипт с именем "wol", тогда в теле сообщения должно быть написано "/wol", при этом в System/Scripts заранее должен быть прописан скрипт с нужным именем (например: "wol").
3. Скрипт считывает ПОСЛЕДНЕЕ сообщение в группе и по этой причине не имеет смысла накидывать сразу много команд, в любом случае будет выполнена только последняя.

Ниже представлен код скрипта:

Код: Выделить всё


# Script remote activation script via Telegram by drPioneer
# https://forummikrotik.ru/viewtopic.php?p=78085
# tested on ROS 6.48
# updated 2021/04/05

:do {
    :local botID    "botXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    :local myChatID "-XXXXXXXXX";
    
    # Telegram messenger response parsing function by Dimonw
    # https://habr.com/ru/post/482802/
    :local parse do={
        :local variaMod ("\"".$variable);
        :local startLoc ([:find $content $variaMod -1] + [:len $variaMod] + 2);
        :local commaLoc ([:find $content "," $startLoc]);
        :local brakeLoc ([:find $content "}" $startLoc]);
        :local endLoc $commaLoc;
        :local startSymbol [:pick $content $startLoc]; 
        :if ($brakeLoc != 0 and ($commaLoc = 0 or $brakeLoc < $commaLoc)) do={ :set endLoc $brakeLoc; };
        :if ($startSymbol = "{") do={ :set endLoc ($brakeLoc + 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];
        :return $message;
    }

    # UNIX time conversion function to normal view by Pepelxl
    # https://forummikrotik.ru/viewtopic.php?t=11636
    :local unixTime do={
        :local dateY  ($timeStamp / 31436000 + 1970);
        :local dateM (($dateY - 1969) / 4);
        :local dateD (($timeStamp / 86400 - $dateM) % 365);
        :local days   [:toarray (31,28,31,30,31,30,31,31,30,31,30,31)];
        :local months [:toarray ("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec")];
        :if ($dateY % 4 = 0) do={ :set ($days->1) 29; }
        do {
            :for i from=0 to=11 do={ 
                :if (($days->$i) > $dateD) do={ 
                    :set $dateM ($i); 
                    :set $dateD ($dateD + 1); 
                    :break;
                } else={ :set $dateD ($dateD - ($days->$i)); } 
            }
        } on-error={}
        :local timeS ($timeStamp % 86400);
        :local timeH ($timeS / 3600);
        :local timeM ($timeS % 3600 / 60);
        :set  $timeS ($timeS - $timeH * 3600 - $timeM * 60);
        :local normalTime (($months->$dateM)."/");
        :if ($dateD < 10) do={ :set $normalTime ($normalTime."0".[:tostr $dateD]."/"); } else={ :set $normalTime ($normalTime.[:tostr $dateD]."/"); }
        :set $normalTime ($normalTime.[:tostr $dateY]." ");   
        :if ($timeH < 10) do={ :set $normalTime ($normalTime."0".[:tostr $timeH].":"); } else={ :set $normalTime ($normalTime.[:tostr $timeH].":"); }
        :if ($timeM < 10) do={ :set $normalTime ($normalTime."0".[:tostr $timeM].":"); } else={ :set $normalTime ($normalTime.[:tostr $timeM].":"); }
        :if ($timeS < 10) do={ :set $normalTime ($normalTime."0".[:tostr $timeS]); }     else={ :set $normalTime ($normalTime.[:tostr $timeS]); }
        :put ([:totime $normalTime]);
        :return $normalTime;
    }
    
    # Main body of the script
    :local nameID   [ /system identity get name; ];
    :local dateNow  [ /system clock    get date; ];
    :local timeNow  [ /system clock    get time; ];
    :local httpResponse [ /tool fetch url="https://api.telegram.org/$botID/getUpdates\?offset=-1&limit=1&allowed_updates=message&timeout=60" as-value output=user; ];
    :local content ($httpResponse->"data");
    :if ([:len $content] > 30) do={
        :local msgId    [$parse content=$content variable="update_id"];
        :local message  [$parse content=$content variable="text" quotas=true];
        :set   message ([:pick $message ([:find $message "/"] + 1) ([:len $message])]);
        :local chat     [$parse content=$content variable="chat"];
        :local chatId   [$parse content=$chat    variable="id"];
        :local userName [$parse content=$content variable="username"];
        :local dateTime [$parse content=$content variable="date"];
        :set   dateTime ($dateTime + [ /system clock get gmt-offset; ]);
        :local normTime [$unixTime timeStamp=$dateTime];
        :put ("Current time on router:\t $dateNow $timeNow");
        :put ("Last message from $userName: time=$normTime, id=$msgId, text=$message.");
        :if (($normTime ~ $dateNow) && ([:totime [:pick $normTime ([:find $normTime " "] + 1) ([:find $normTime " "] + 9)]] > ($timeNow - 00:01:00))) do={
            :put ("Right time to activation script.");
            :if (($chatId = $myChatID) && ([/system script find name=$message] != "")) do={
                :put ("Telegram user $userName activated script '$message'.");
                :log warning ("Telegram user $userName activated script '$message'.");                 
                /system script run $message;
                /tool fetch keep-result=no url="https://api.telegram.org/$botID/sendmessage\?chat_id=$chatId&text=$nameID: '$message' command accepted.";
            } else={ :put ("Not all conditions activation script are met."); }
        } else={ :put ("Bad time to activation script."); }
    }
} on-error={ :put ("Script error: 1 - message could have been sent a long time ago. 2 - check whether 'botID' & 'myChatID' variables are specified correctly."); }


Конструктивная критика и усовершенствования приветствуются .

Список использованной литературы:
- https://habr.com/ru/post/482802/
- https://habr.com/ru/post/314108/
- https://habr.com/ru/post/313794/
- viewtopic.php?p=73994
- viewtopic.php?t=11636
- viewtopic.php?p=71914

----------------------------
UPDATE of 12.2021: Скрипт развивается. Актуальную версию скрипта Вы можете найти в конце этой ветки форума.
Последний раз редактировалось drpioneer 11 дек 2021, 10:58, всего редактировалось 11 раз.


pepelxl
Сообщения: 161
Зарегистрирован: 23 июл 2013, 18:47

Функция времени с косяком , потеряет сутки в високосные года.


Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

pepelxl писал(а): 16 мар 2021, 19:34 Функция времени с косяком , потеряет сутки в високосные года.
Спасибо. Исправил. :-ok-:


Аватара пользователя
Virtue
Сообщения: 142
Зарегистрирован: 07 мар 2014, 10:17

drpioneer писал(а): 15 мар 2021, 21:21 Ниже представлен код скрипта:
уух как всё сложно... :hi_hi_hi:
скажите, а данный скрипт управляет только одним микротиком? ну тоесть не получится дать команду сразу нескольким, как в моей версии?


Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

Virtue писал(а): 16 мар 2021, 23:06 данный скрипт управляет только одним микротиком? ну тоесть не получится дать команду сразу нескольким, как в моей версии?
Скрипт корректно работает с группой роутеров :men: .


Аватара пользователя
podarok66
Модератор
Сообщения: 4355
Зарегистрирован: 11 фев 2012, 18:49
Откуда: МО

На самом деле, по теме вопросы на форуме достаточно регулярны. Спасибо, ТС. Теперь все подобные вопросы направляем сюда


Мануалы изучил и нигде не ошибся? Фаервол отключил? Очереди погасил? Витая пара проверена? ... Тогда Netinstal'ом железку прошей и настрой ее заново. Что, все равно не фурычит? Тогда к нам. Если не подскажем, хоть посочувствуем...
Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

Всех приветствую!

В продолжение к теме прилагаю пример скрипта "wol" (Wake On Lan), предназначенный для пробуждения компьютеров в локальной сети.

Код: Выделить всё


# Script wake up computers on lan by drPioneer
# https://forummikrotik.ru/viewtopic.php?p=78085
# tested on ROS 6.48
# updated 2021/03/16

:do {
    :local localMac {"XX:XX:XX:XX:XX:XX";"YY:YY:YY:YY:YY:YY";"ZZ:ZZ:ZZ:ZZ:ZZ:ZZ"};

    :foreach mac in=$localMac do={
        :do {
            :local localIp      [ /ip dhcp-server lease get [find mac-address=$mac] address;   ];
            :local localComment [ /ip dhcp-server lease get [find mac-address=$mac] comment;   ];
            :local serverDhcp   [ /ip dhcp-server lease get [find mac-address=$mac] server;    ];
            :local serverIf     [ /ip dhcp-server       get [find name=$serverDhcp] interface; ];

            # Activation command of wakeup computer by GeXoGeN
            # https://habr.com/ru/post/313794/
            /tool wol mac=$mac interface=$serverIf;
            
            :put ("Wakeup of computer '$localComment' on $localIp (MAC=$mac If=$serverIf)");
            :log warning ("Wakeup of computer '$localComment' on $localIp (MAC=$mac If=$serverIf)");
        } on-error={ 
            :put ("Wakeup script error: MAC=$mac not found in DHCP-server leases."); 
            :log warning ("Wakeup script error: MAC=$mac not found in DHCP-server leases."); 
        }
    }
} on-error={ :log warning ("Error wakeup computers on the local network."); }


В localMac необходимо заранее указать MAC-адреса нужных компьютеров.

Использованные ресурсы: https://habr.com/ru/post/313794/


aleksey.yakushev
Сообщения: 3
Зарегистрирован: 01 апр 2021, 15:02

Здравствуйте!
ув. drpioneer,  большое спасибо за скрипт. очень выручает.

Сегодня 1 апреля ))) перестали запускаться скрипты. Начал выяснять. Оказалось причина в дате.

Выводит mar/32/2021 14:56:13

Можно это как-то поправить?

Заранее спасибо!


Изображение


Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

aleksey.yakushev писал(а): 01 апр 2021, 15:31 Сегодня 1 апреля ))) перестали запускаться скрипты. Начал выяснять. Оказалось причина в дате.
Выводит mar/32/2021 14:56:13
Можно это как-то поправить?
Здравствуйте!

Нарочно не придумаешь - выстрелило в правильный день! :hi_hi_hi:
Спасибо за обратную связь. Код поправил (обновил в первом сообщении этой темы). Пользуйтесь на здоровье...
Для вывода текущей отладочной информации (чтобы понять почему скрипт не срабатывает) достаточно просто запустить скрипт в терминале.

Конструктивная критика и замечания приветствуются.

С днём смеха!


aleksey.yakushev
Сообщения: 3
Зарегистрирован: 01 апр 2021, 15:02

drpioneer писал(а): 01 апр 2021, 21:51 Код поправил (обновил в первом сообщении этой темы). Пользуйтесь на здоровье...
Спасибо за оперативность. Все работает.


Ответить