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

Здесь выкладываем скрипты
Правила форума
Уважаемые Пользователи форума, обратите внимание!
Ни при каких обстоятельствах, Администрация форума, не несёт ответственности за какой-либо, прямой или косвенный, ущерб причиненный в результате использования материалов, взятых на этом Сайте или на любом другом сайте, на который имеется гиперссылка с данного Сайта. Возникновение неисправностей, потерю программ или данных в Ваших устройствах, даже если Администрация будет явно поставлена в известность о возможности такого ущерба.
Просим Вас быть предельно осторожными и внимательными, в использовании материалов раздела. Учитывать не только Ваши пожелания, но и границы возможностей вашего оборудования.
Ответить
Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

С удивлением обнаружил, что всё моё войско роутеров дружно перестало слать в телегу отчёты о своём самочувствии
Странно, а у меня Ваша предыдущая версия скрипта вроде нормально работает, судя по сообщениям в Телеграмм и в том числе 31 декабря и 1 января ...
Не могли бы Вы уточнить какую ошибку Вы исправили в скрипте и в каком месте ?!

С наступившим Новым Годом !


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

Sertik писал(а): 02 янв 2022, 19:35
С удивлением обнаружил, что всё моё войско роутеров дружно перестало слать в телегу отчёты о своём самочувствии
Странно, а у меня Ваша предыдущая версия скрипта вроде нормально работает, судя по сообщениям в Телеграмм и в том числе 31 декабря и 1 января ...
Не могли бы Вы уточнить какую ошибку Вы исправили в скрипте и в каком месте ?!
Приветствую!

Вместо тысячи слов я просто приведу в пример ТРИ(!!!) разных формата вывода времени журнала:

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

dec/31/2021 23:57:07 caps,info xx:xx:xx:62:77:82@cap1 disconnected, received deauth: sending station leaving (3), signal strength -62 
dec/31/2021 23:57:07 caps,info xx:xx:xx:62:77:82@cap1 connected, signal strength -60 
...
jan/01 00:11:49 caps,info xx:xx:xx:62:77:82@cap1 disconnected, received deauth: sending station leaving (3), signal strength -60 
jan/01 00:11:49 caps,info xx:xx:xx:62:77:82@cap1 connected, signal strength -58 
...
02:24:30 caps,info xx:xx:xx:62:77:82@cap1 disconnected, received disassoc: sending station leaving (8), signal strength -61 
02:39:09 caps,info xx:xx:xx:62:77:82@cap1 connected, signal strength -61 
Один из представленных форматов вывода времени до нового года скриптом не обрабатывался и скрипт об него спотыкался. Правки внесены в функцию преобразования времени в UNIX-время.


Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

ОК, спасибо за пояснение. А разный формат времени чем обусловлен - в разных версиях прошивок разный или в различных железках ? Или разные пакеты в лог пишут время по разному, например, capsman по своему, другой какой-то пакет по своему ?


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

Sertik писал(а): 02 янв 2022, 21:40 ...
А разный формат времени чем обусловлен - в разных версиях прошивок разный или в различных железках ? Или разные пакеты в лог пишут время по разному, например, capsman по своему, другой какой-то пакет по своему ?
Разный формат времени на мой взгляд обусловлен оригинальностью авторов ROS 6.xx :-)
Вы можете наблюдать всё разнообразие форматов времени в терминале своего устройства по команде log print.
Для событий младше 23:59:59 выводится только время.
После перехода через новые сутки выводится месяц, число и время.
После перехода через новый год выводится месяц, число, год и время.


Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

Чуть доработал Ваш скрипт (вот эти строки, см. ниже). Теперь Возможен не только запуск скриптов из репозитория, но и запуск функций, активных (установленных в окружение переменных, главная строка выделена жирным шрифтом).

:if (([/system script find name=$msgTxt] != "") or ([/system script environment find name=$msgTxt] !="")) do={
:if (($chatId = $myChatID) && ($timeAct < $timeStamp)) do={
:set timeAct ($timeStamp);
:put ("$timeStamp sec - activated script '$msgTxt' from user $userName.");
# :log warning ("Telegram user $userName activated script '$msgTxt' in $timeStamp sec.");
:if ([/system script environment find name=$msgTxt] !="") do={[:parse ":global $msgTxt; [\$$msgTxt]"]}
:if ([/system script find name=$msgTxt] != "") do={/system script run $msgTxt}

} else={ :put ("Nothing to activated."); }}
} else={ :put ("Completion of response from Telegram."); }
}

К сожалению, функции можно запускать только без параметров, т.к. парсер команд скрипта, считает, что команда для выполнения (скрипт или функция) это всё, что идет до пробела. /Functionname var1 var 2 ... varX
Вы лучше меня знаете свой скрипт-парсер команд. Поправьте, пожалуйста, где нужно - хорошая штука выйдет, всем пригодиться ... Самый смак был бы запускать функции с параметрами (хотя бы только позиционными, не надо может быть связываться с именованными). Носом теперь чую, что это возможно ...


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

Ещё доделал скрипт. Оказалось очень легко передать параметры функции. Вот кусок (выделен жирным шрифтом) позволяющий выделить параметры,
потом они передаются функции на выполнение вместе с объявлением функции через :parse (также выделено жирным шрифтом)

#seek parameters for functions
:local params
:if ([:len [:find $msgTxt " "]]!=0) do={:set params [:pick $msgTxt ([:find $msgTxt " "]+1) [:len $msgTxt]];
:set msgTxt [:pick $msgTxt 0 [:find $msgTxt " "]]
} else {:set params []}


:if (([/system script find name=$msgTxt] != "") or ([/system script environment find name=$msgTxt] !="")) do={
:if (($chatId = $myChatID) && ($timeAct < $timeStamp)) do={
:set timeAct ($timeStamp);
:put ("$timeStamp sec - activated script or function '$msgTxt' from user $userName.");
# :log warning ("Telegram user $userName activated script '$msgTxt' in $timeStamp sec.");
:if ([/system script environment find name=$msgTxt] !="") do={[:parse ":global $msgTxt; [\$$msgTxt $params]"]}
:if ([/system script find name=$msgTxt] != "") do={/system script run $msgTxt}

} else={ :put ("Nothing to activated."); }}
} else={ :put ("Completion of response from Telegram."); }
}

Теперь скрипт может запускать скрипты и функции (с параметрами и без) ! Параметры можно использовать как именованные так и позиционные так и их смесь
(по количеству не ограничены - ограничены только длиной строки).

Примеры обращения к функциям через Телеграмм (обратите внимание перед именем функции ставится только прямой слеш / (как и для запуска обычного скрипта), знак $ не ставится !:

/FuncMail Email=user@mail.ru MailText="Привет Мир" (используются именованные параметры)
/FuncArp - выполняем функцию без параметров
/MyFunc 5 mama - (используются позиционные параметры)
/MySuperFunc Var1=Hello 50 Var2=word - (смешанные, позиционный и именованные параметры)

Ещё момент - если у Вас в репозитории есть скрипт с таким же именем как активированная функция, то при вызове выполнен будет код обоих
(сначала функция, потом скрипт) !
Есть один минус - функции не могут напрямую возвращать результат работы в Телеграмм, это нужно прописывать уже в самой функции. Учитывая возможности скрипта относительно нотаций, функции могут просто сбросить результат своей работы в лог через :log warning или :log error - результат будет переслан в Ваш чат Телеграм нашим главным комбайн-скриптом.

Теперь он стал ещё "могучее" ! Даже у буржуинов нет такого скрипта, его сделали мы !


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

Sertik писал(а): 01 фев 2022, 14:12 Чуть доработал Ваш скрипт
...
Sertik писал(а): 01 фев 2022, 21:06 ...
Теперь скрипт может запускать скрипты и функции (с параметрами и без) !
...
Теперь он стал ещё "могучее" ! Даже у буржуинов нет такого скрипта, его сделали мы !
Добрый день.

Очень радует, что скрипт получает развитие благодаря стараниям активных пользователей этого форума :a_g_a:
Ниже представляю очередную версию полного кода скрипта с усовершенствованиями от многоуважаемого Sertik:

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




# Combined notification script and script launch via Telegram by drPioneer
# https://forummikrotik.ru/viewtopic.php?p=81945#p81945
# tested on ROS 6.49
# updated 2022/02/02

:do {
    :local botID    "botXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    :local myChatID "-XXXXXXXXX";

    # Function of searching comments for MAC-address by Virtue
    # https://forummikrotik.ru/viewtopic.php?p=73994#p73994
    :local FindMacAddr do={
        :if ($1 ~"[0-F][0-F]:[0-F][0-F]:[0-F][0-F]:[0-F][0-F]:[0-F][0-F]:[0-F][0-F]") do={
            :foreach idx in=[ /ip dhcp-server lease find dynamic=no disabled=no; ] do={
                :local mac  [ /ip dhcp-server lease get $idx mac-address; ];
                :if ($1 ~"$mac") do={ 
                    :return ("$1 [$[ /ip dhcp-server lease get $idx address; ]/\
                        $[ /ip dhcp-server lease get $idx comment; ]]."); 
                } 
            }
            :foreach idx in=[ /interface bridge host find; ] do={
                :local mac  [ /interface bridge host get $idx mac-address; ];
                :if ($1 ~"$mac") do={ :return ("$1 [$[ /interface bridge host get $idx on-interface; ]]."); }
            }
        }
        :return ($1);
    }

    # Function of converting CP1251 to UTF8 by Sertik
    # https://forummikrotik.ru/viewtopic.php?p=81457#p81457
    :local CP1251toUTF8 do={
        :local cp1251 [:toarray {"\20";"\01";"\02";"\03";"\04";"\05";"\06";"\07";"\08";"\09";"\0A";"\0B";"\0C";"\0D";"\0E";"\0F"; \
                                 "\10";"\11";"\12";"\13";"\14";"\15";"\16";"\17";"\18";"\19";"\1A";"\1B";"\1C";"\1D";"\1E";"\1F"; \
                                 "\21";"\22";"\23";"\24";"\25";"\26";"\27";"\28";"\29";"\2A";"\2B";"\2C";"\2D";"\2E";"\2F";"\3A"; \
                                 "\3B";"\3C";"\3D";"\3E";"\3F";"\40";"\5B";"\5C";"\5D";"\5E";"\5F";"\60";"\7B";"\7C";"\7D";"\7E"; \
                                 "\C0";"\C1";"\C2";"\C3";"\C4";"\C5";"\C7";"\C7";"\C8";"\C9";"\CA";"\CB";"\CC";"\CD";"\CE";"\CF"; \
                                 "\D0";"\D1";"\D2";"\D3";"\D4";"\D5";"\D6";"\D7";"\D8";"\D9";"\DA";"\DB";"\DC";"\DD";"\DE";"\DF"; \
                                 "\E0";"\E1";"\E2";"\E3";"\E4";"\E5";"\E6";"\E7";"\E8";"\E9";"\EA";"\EB";"\EC";"\ED";"\EE";"\EF"; \
                                 "\F0";"\F1";"\F2";"\F3";"\F4";"\F5";"\F6";"\F7";"\F8";"\F9";"\FA";"\FB";"\FC";"\FD";"\FE";"\FF"; \
                                 "\A8";"\B8";"\B9"}];
        :local utf8   [:toarray {"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"000A";"0020";"0020";"000D";"0020";"0020"; \
                                 "0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020"; \
                                 "0021";"0022";"0023";"0024";"0025";"0026";"0027";"0028";"0029";"002A";"002B";"002C";"002D";"002E";"002F";"003A"; \
                                 "003B";"003C";"003D";"003E";"003F";"0040";"005B";"005C";"005D";"005E";"005F";"0060";"007B";"007C";"007D";"007E"; \
                                 "D090";"D091";"D092";"D093";"D094";"D095";"D096";"D097";"D098";"D099";"D09A";"D09B";"D09C";"D09D";"D09E";"D09F"; \
                                 "D0A0";"D0A1";"D0A2";"D0A3";"D0A4";"D0A5";"D0A6";"D0A7";"D0A8";"D0A9";"D0AA";"D0AB";"D0AC";"D0AD";"D0AE";"D0AF"; \
                                 "D0B0";"D0B1";"D0B2";"D0B3";"D0B4";"D0B5";"D0B6";"D0B7";"D0B8";"D0B9";"D0BA";"D0BB";"D0BC";"D0BD";"D0BE";"D0BF"; \
                                 "D180";"D181";"D182";"D183";"D184";"D185";"D186";"D187";"D188";"D189";"D18A";"D18B";"D18C";"D18D";"D18E";"D18F"; \
                                 "D001";"D191";"2116"}];
        :local convStr ""; 
        :local code    "";
        :for i from=0 to=([:len $1]-1) do={
            :local symb [:pick $1 $i ($i+1)]; 
            :local idx  [:find $cp1251 $symb];
            :local key  ($utf8->$idx);
            :if ([:len $key] != 0) do={
                :set $code ("%$[:pick ($key) 0 2]%$[:pick ($key) 2 4]");
                :if ([pick $code 0 3] = "%00") do={ :set $code ([:pick $code 3 6]); }
            } else={ :set code ($symb); }; 
            :set $convStr ($convStr.$code);
        }
        :return ($convStr);
    }

    # Telegram messenger response parsing function by Dimonw
    # https://habr.com/ru/post/482802/
    :local MsgParser do={
        :local variaMod ("\"".$2);
        :local startLoc ([:find $1 $variaMod -1] + [:len $variaMod] + 2);
        :local commaLoc ([:find $1 "," $startLoc]);
        :local brakeLoc ([:find $1 "}" $startLoc]);
        :local endLoc $commaLoc;
        :local startSymbol [:pick $1 $startLoc]; 
        :if ($brakeLoc != 0 and ($commaLoc = 0 or $brakeLoc < $commaLoc)) do={ :set endLoc $brakeLoc; };
        :if ($startSymbol = "{") do={ :set endLoc ($brakeLoc + 1); };
        :if ($3 = true) do={
            :set startLoc ($startLoc + 1);
            :set endLoc   ($endLoc   - 1);
        }
        :if ($endLoc < $startLoc) do={ :set endLoc ($startLoc + 1); };
        :return ([:pick $1 $startLoc $endLoc]);
    }
    
    # Time translation function to UNIX-time by Jotne
    # https://forum.mikrotik.com/viewtopic.php?t=75555#p790745
    :local EpochTime do={
        :local ds [ /system clock get date; ];
        :local ts [ /system clock get time; ];
        :if ([:len $1] > 19) do={
            :set ds "$[:pick $1 0 11]";
            :set ts [:pick $1 12 20];
        }
        :if ([:len $1] > 8 && [:len $1] < 20) do={
            :set ds "$[:pick $1 0 6]/$[:pick $ds 7 11]";
            :set ts [:pick $1 7 15];
        }
        :local yesterday false;
        :if ([:len $1] = 8) do={
            :if ([:totime $1] > ts) do={ :set yesterday (true); }
            :set ts $1;
        }
        :local months;
        :if ((([:pick $ds 9 11]-1)/4) != (([:pick $ds 9 11])/4)) do={
            :set months {"an"=0;"eb"=31;"ar"=60;"pr"=91;"ay"=121;"un"=152;"ul"=182;"ug"=213;"ep"=244;"ct"=274;"ov"=305;"ec"=335};
        } else={
            :set months {"an"=0;"eb"=31;"ar"=59;"pr"=90;"ay"=120;"un"=151;"ul"=181;"ug"=212;"ep"=243;"ct"=273;"ov"=304;"ec"=334};
        }
        :set ds (([:pick $ds 9 11]*365)+(([:pick $ds 9 11]-1)/4)+($months->[:pick $ds 1 3])+[:pick $ds 4 6]);
        :set ts (([:pick $ts 0 2]*3600)+([:pick $ts 3 5]*60)+[:pick $ts 6 8]);
        :if (yesterday) do={ :set ds ($ds-1); }
        :return ($ds*86400 + $ts + 946684800 - [ /system clock get gmt-offset; ]);
    }

    # Main body of the script
    :global timeAct;
    :global timeLog;
    :local  nameID [ /system identity get name; ];
    :put ("$[$EpochTime] sec - current Unix-time of $nameID router.");
    if ([:len $timeAct] > 0) do={ :put ("$timeAct sec - time of checking the last script run."); }
    if ([:len $timeLog] > 0) do={ :put ("$timeLog sec - time of the last log check."); }

    # Part of the script body to run via Telegram of scripts and functions from drPioneer & Sertik
    # https://forummikrotik.ru/viewtopic.php?p=78085
    :local  timeStamp [$EpochTime];
    :local  urlString "https://api.telegram.org/$botID/getUpdates\?offset=-1&limit=1&allowed_updates=message";
    :put ("... Stage of running scripts via Telegram:");
    :if ([:len $timeAct] = 0) do={
        :put ("Time of the last script activation was not found.");
        :set timeAct $timeStamp;
    } else={
        :local httpResp [ /tool fetch url=$urlString as-value output=user; ];
        :local content ($httpResp->"data");
        :if ([:len $content] > 30) do={
            :local msgTxt   [$MsgParser $content "text" true];
            :set   msgTxt  ([:pick $msgTxt ([:find $msgTxt "/"] + 1) ([:len $msgTxt])]);
            :local chat     [$MsgParser $content "chat"];
            :local chatId   [$MsgParser $chat    "id"];
            :local userName [$MsgParser $content "username"];
            :set  timeStamp [$MsgParser $content "date"];
            :local params   [];
            :if ([:len [:find $msgTxt " "]] !=0) do={
                :set params [:pick $msgTxt  ([:find $msgTxt " "]+1) [:len $msgTxt]];
                :set msgTxt [:pick $msgTxt 0 [:find $msgTxt " "]];
            }
            :if (($chatId = $myChatID) && ($timeAct < $timeStamp)) do={
                :if (([/system script find name=$msgTxt] !="") or ([/system script environment find name=$msgTxt] !="")) do={
                    :set timeAct ($timeStamp);
                    :if ([/system script environment find name=$msgTxt;] !="") do={
                        :put ("$timeStamp sec - activated function '$msgTxt' from user $userName.");
                        :log warning ("Telegram user $userName activated function '$msgTxt' in $timeStamp sec.");
                        [:parse ":global $msgTxt; [\$$msgTxt $params]"];
                    }
                    :if ([/system script find name=$msgTxt;] != "") do={
                        :put ("$timeStamp sec - activated script '$msgTxt' from user $userName.");
                        :log warning ("Telegram user $userName activated script '$msgTxt' in $timeStamp sec.");
                        /system script run $msgTxt;
                    }
                }
            } else={ :put ("Nothing to activated."); }
        } else={ :put ("Completion of response from Telegram."); }
    }

    # Part of the script body for notifications in Telegram by Alice Tails
    # https://www.reddit.com/r/mikrotik/comments/onusoj/sending_log_alerts_to_telegram/
    :local outMsg "";
    :local logGet [ :toarray [ /log find ($topics ~"warning" || $topics ~"error" || $topics ~"critical" || $topics ~"caps" \
    || $topics ~"wireless" || $message ~"logged in"); ]];
    :local logCnt [ :len $logGet ];
    :put ("... Stage of sending notifications to Telegram:");
    :if ([:len $timeLog] = 0) do={ 
        :put ("Time of the last log entry was not found.");
        :set outMsg (">$[ /system clock get time; ] Telegram notification started.");
    }
    :if ($logCnt > 0) do={
        :local lastTime [$EpochTime [ /log get [:pick $logGet ($logCnt-1)] time; ]];
        :local index 0;
        :local tempTime;
        :local tempMessage;
        :local tempTopic;
        :local unixTime;
        :do {
            :set index        ($index + 1); 
            :set tempTime     [ /log get [:pick $logGet ($logCnt - $index)]    time; ];
            :set tempTopic    [ /log get [:pick $logGet ($logCnt - $index)]  topics; ];
            :set tempMessage  [ /log get [:pick $logGet ($logCnt - $index)] message; ];
            :set tempMessage  (">".$tempTime." ".$tempMessage);
            :local findMacMsg ([$FindMacAddr $tempMessage]);
            :set unixTime [$EpochTime $tempTime];
            :if (($unixTime > $timeLog) && (!(($tempTopic ~"caps" || $tempTopic ~"wireless" || $tempTopic ~"dhcp") \
            && ($tempMessage != $findMacMsg)))) do={
                :put $findMacMsg;
                :set outMsg ($findMacMsg."\n".$outMsg);
            }
        } while=(($unixTime > $timeLog) && ($index < $logCnt));
        :if (([:len $timeLog] < 1) || (([:len $timeLog] > 0) && ($timeLog != $lastTime) && ([:len $outMsg] > 8) )) do={
            :set timeLog $lastTime;
            if ([:len $outMsg] > 4096) do={ :set outMsg ([:pick $outMsg 0 4096]); }
            :set outMsg [$CP1251toUTF8 $outMsg];
            :local urlString ("https://api.telegram.org/$botID/sendmessage\?chat_id=$myChatID&text=$nameID:%0A$outMsg");
            :put ("Generated string for Telegram:\r\n".$urlString);
            /tool fetch url=$urlString as-value output=user;
        } else={ :put ("Nothing to send."); }
    } else={ :put ("Necessary log entries were not found."); }
} on-error={ :put ("Script error: something went wrong when sending a request to Telegram."); }



Предлагаю всем заинтересованным погонять эту версию скрипта.
Конструктивная критика и усовершенствования скрипта только приветствуются.


Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

Дорогой друг DrPioneer !

Во-первых спасибо за внесение моего дополнения в основной скрипт.

Во-вторых проверьте, пожалуйста, строки:

:log warning ("Telegram user $userName activated function '$msgTxt' in $timeStamp sec.");
:log warning ("Telegram user $userName activated script '$msgTxt' in $timeStamp sec.");

Там $userName какая-то порченная ... Надо подправить.


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

Ещё одна мысль посетила меня: мы можем исполнять скрипты по имени и функции по имени. А почему бы не разрешить ещё и выполнение команд РОС ?!!!! Простая вставка (выделена жирным шрифтом) позволяет это делать. Зачем ? спросите Вы - ну хотя бы можно непосредственно командой перезагрузить роутер, сбросить питание USB, положить роутер в shutdown, установить глобальные переменные флаги и т д...

:local params [];
:if ([:len [:find $msgTxt " "]] !=0) do={
:set params [:pick $msgTxt ([:find $msgTxt " "]+1) [:len $msgTxt]];
:set msgTxt [:pick $msgTxt 0 [:find $msgTxt " "]];
}
:if (($chatId = $myChatID) && ($timeAct < $timeStamp)) do={
:if (([/system script find name=$msgTxt] !="") or ([/system script environment find name=$msgTxt] !="")) do={
:set timeAct ($timeStamp);
:if ([/system script environment find name=$msgTxt;] !="") do={
:put ("$timeStamp sec - activated function '$msgTxt' from user $userName.");
:log warning ("Telegram user $userName activated function '$msgTxt' in $timeStamp sec.");
[:parse ":global $msgTxt; [\$$msgTxt $params]"];
}
:if ([/system script find name=$msgTxt;] != "") do={
:put ("$timeStamp sec - activated script '$msgTxt' from user $userName.");
:log warning ("Telegram user $userName activated script '$msgTxt' in $timeStamp sec.");
/system script run $msgTxt;
}
} else={:set timeAct ($timeStamp); do {[:parse "/$msgTxt $params"]} on-error={}}
} else={ :put ("Nothing to activated."); }

Если кто-то боится, что можно увести Бот и потом управлять роутером через этот скрипт - не проблема, можно сделать защиту ...
} else={ :put ("Completion of response from Telegram."); }
}

На всякий случай исполнение команды РОС заворачиваю в обработчик ошибок, чтобы скрипт не тормознул на попытке выполнения неправильной/отсутствующей команды. Кстати пробовал - исполняет и группу команд из строки, вероятно, возможны глюки при передаче кавычек и спецсимволов - такие вещи могут не работать ... Надо тестировать.

Проверил кое-что смог ... Нормально отрабатываются команды например типа /log warning [/system identity get name], log error [/pick mama 0 3] ... То есть нормально парсится и работают "вложенные конструкции", возможно не все, но основные работают !


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

Sertik писал(а): 03 фев 2022, 23:35 А почему бы не разрешить ещё и выполнение команд РОС ?
...
можно непосредственно командой перезагрузить роутер, сбросить питание USB, положить роутер в shutdown, установить глобальные переменные флаги и т д...
...
Добрый день.

При активном участии Sertik в скрипт добавлена возможность исполнения команд RouterOS. :bra_vo:
Попутно подлечены замеченные косяки.

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




# TLGRM - combined notifications script & launch of commands (scripts & functions) via Telegram
# Script uses ideas by Sertik, Virtue, Pepelxl, Dimonw, Jotne, Alice Tails, drPioneer, Chupakabra
# https://forummikrotik.ru/viewtopic.php?p=81945#p81945
# tested on ROS 6.49
# updated 2022/02/28

:do {
    :local botID    "botXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    :local myChatID "-XXXXXXXXX";

    :local launchScr true;
    :local launchFnc true;
    :local launchCmd true;

    # Function of searching comments for MAC-address
    # https://forummikrotik.ru/viewtopic.php?p=73994#p73994
    :local FindMacAddr do={
        :if ($1 ~"[0-F][0-F]:[0-F][0-F]:[0-F][0-F]:[0-F][0-F]:[0-F][0-F]:[0-F][0-F]") do={
            :foreach idx in=[ /ip dhcp-server lease find dynamic=no disabled=no; ] do={
                :local mac  [ /ip dhcp-server lease get $idx mac-address; ];
                :if ($1 ~"$mac") do={ 
                    :return ("$1 [$[ /ip dhcp-server lease get $idx address; ]/\
                        $[ /ip dhcp-server lease get $idx comment; ]]."); 
                } 
            }
            :foreach idx in=[ /interface bridge host find; ] do={
                :local mac  [ /interface bridge host get $idx mac-address; ];
                :if ($1 ~"$mac") do={ :return ("$1 [$[ /interface bridge host get $idx on-interface; ]]."); }
            }
        }
        :return ($1);
    }

    # Function of converting CP1251 to UTF8
    # https://forummikrotik.ru/viewtopic.php?p=81457#p81457
    :local CP1251toUTF8 do={
        :local cp1251 [:toarray {"\20";"\01";"\02";"\03";"\04";"\05";"\06";"\07";"\08";"\09";"\0A";"\0B";"\0C";"\0D";"\0E";"\0F"; \
                                 "\10";"\11";"\12";"\13";"\14";"\15";"\16";"\17";"\18";"\19";"\1A";"\1B";"\1C";"\1D";"\1E";"\1F"; \
                                 "\21";"\22";"\23";"\24";"\25";"\26";"\27";"\28";"\29";"\2A";"\2B";"\2C";"\2D";"\2E";"\2F";"\3A"; \
                                 "\3B";"\3C";"\3D";"\3E";"\3F";"\40";"\5B";"\5C";"\5D";"\5E";"\5F";"\60";"\7B";"\7C";"\7D";"\7E"; \
                                 "\C0";"\C1";"\C2";"\C3";"\C4";"\C5";"\C6";"\C7";"\C8";"\C9";"\CA";"\CB";"\CC";"\CD";"\CE";"\CF"; \
                                 "\D0";"\D1";"\D2";"\D3";"\D4";"\D5";"\D6";"\D7";"\D8";"\D9";"\DA";"\DB";"\DC";"\DD";"\DE";"\DF"; \
                                 "\E0";"\E1";"\E2";"\E3";"\E4";"\E5";"\E6";"\E7";"\E8";"\E9";"\EA";"\EB";"\EC";"\ED";"\EE";"\EF"; \
                                 "\F0";"\F1";"\F2";"\F3";"\F4";"\F5";"\F6";"\F7";"\F8";"\F9";"\FA";"\FB";"\FC";"\FD";"\FE";"\FF"; \
                                 "\A8";"\B8";"\B9"}];
        :local utf8   [:toarray {"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"000A";"0020";"0020";"000D";"0020";"0020"; \
                                 "0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020";"0020"; \
                                 "0021";"0022";"0023";"0024";"0025";"0026";"0027";"0028";"0029";"002A";"002B";"002C";"002D";"002E";"002F";"003A"; \
                                 "003B";"003C";"003D";"003E";"003F";"0040";"005B";"005C";"005D";"005E";"005F";"0060";"007B";"007C";"007D";"007E"; \
                                 "D090";"D091";"D092";"D093";"D094";"D095";"D096";"D097";"D098";"D099";"D09A";"D09B";"D09C";"D09D";"D09E";"D09F"; \
                                 "D0A0";"D0A1";"D0A2";"D0A3";"D0A4";"D0A5";"D0A6";"D0A7";"D0A8";"D0A9";"D0AA";"D0AB";"D0AC";"D0AD";"D0AE";"D0AF"; \
                                 "D0B0";"D0B1";"D0B2";"D0B3";"D0B4";"D0B5";"D0B6";"D0B7";"D0B8";"D0B9";"D0BA";"D0BB";"D0BC";"D0BD";"D0BE";"D0BF"; \
                                 "D180";"D181";"D182";"D183";"D184";"D185";"D186";"D187";"D188";"D189";"D18A";"D18B";"D18C";"D18D";"D18E";"D18F"; \
                                 "D001";"D191";"2116"}];
        :local convStr ""; 
        :local code    "";
        :for i from=0 to=([:len $1]-1) do={
            :local symb [:pick $1 $i ($i+1)]; 
            :local idx  [:find $cp1251 $symb];
            :local key  ($utf8->$idx);
            :if ([:len $key] != 0) do={
                :set $code ("%$[:pick ($key) 0 2]%$[:pick ($key) 2 4]");
                :if ([pick $code 0 3] = "%00") do={ :set $code ([:pick $code 3 6]); }
            } else={ :set code ($symb); }; 
            :set $convStr ($convStr.$code);
        }
        :return ($convStr);
    }

    # Telegram messenger response parsing function
    # https://habr.com/ru/post/482802/
    :local MsgParser do={
        :local variaMod ("\"".$2."\"");
        :if ([:len [:find $1 $variaMod -1]]=0) do={ :return ("'unknown'"); }
        :local startLoc ([:find $1 $variaMod -1] + [:len $variaMod] +1);
        :local commaLoc ([:find $1 "," $startLoc]);
        :local brakeLoc ([:find $1 "}" $startLoc]);
        :local endLoc $commaLoc;
        :local startSymbol [:pick $1 $startLoc];
        :if ($brakeLoc != 0 and ($commaLoc = 0 or $brakeLoc < $commaLoc)) do={ :set endLoc $brakeLoc; };
        :if ($startSymbol = "{") do={ :set endLoc ($brakeLoc + 1); };
        :if ($3 = true) do={
            :set startLoc ($startLoc + 1);
            :set endLoc   ($endLoc   - 1);
        }
        :if ($endLoc < $startLoc) do={ :set endLoc ($startLoc + 1); };
        :return ([:pick $1 $startLoc $endLoc]);
    }
    
    # Time translation function to UNIX-time
    # https://forum.mikrotik.com/viewtopic.php?t=75555#p790745
    # Usage: $EpochTime [time input]
    # Get current time: put [$EpochTime]
    # Read log time in one of three format: "hh:mm:ss", "mmm/dd hh:mm:ss" or "mmm/dd/yyyy hh:mm:ss"
    :local EpochTime do={
        :local ds [ /system clock get date; ];
        :local ts [ /system clock get time; ];
        :if ([:len $1] > 19) do={
            :set ds "$[:pick $1 0 11]";
            :set ts [:pick $1 12 20];
        }
        :if ([:len $1] > 8 && [:len $1] < 20) do={
            :set ds "$[:pick $1 0 6]/$[:pick $ds 7 11]";
            :set ts [:pick $1 7 15];
        }
        :local yesterday false;
        :if ([:len $1] = 8) do={
            :if ([:totime $1] > ts) do={ :set yesterday (true); }
            :set ts $1;
        }
        :local months;
        :if ((([:pick $ds 9 11]-1)/4) != (([:pick $ds 9 11])/4)) do={
            :set months {"an"=0;"eb"=31;"ar"=60;"pr"=91;"ay"=121;"un"=152;"ul"=182;"ug"=213;"ep"=244;"ct"=274;"ov"=305;"ec"=335};
        } else={
            :set months {"an"=0;"eb"=31;"ar"=59;"pr"=90;"ay"=120;"un"=151;"ul"=181;"ug"=212;"ep"=243;"ct"=273;"ov"=304;"ec"=334};
        }
        :set ds (([:pick $ds 9 11]*365)+(([:pick $ds 9 11]-1)/4)+($months->[:pick $ds 1 3])+[:pick $ds 4 6]);
        :set ts (([:pick $ts 0 2]*3600)+([:pick $ts 3 5]*60)+[:pick $ts 6 8]);
        :if (yesterday) do={ :set ds ($ds-1); }
        :return ($ds*86400 + $ts + 946684800 - [ /system clock get gmt-offset; ]);
    }

    # Time conversion function from UNIX-time
    # https://forummikrotik.ru/viewtopic.php?t=11636
    # usage: [$UnixTimeToFormat "timeStamp" "type"]
    # type: "unspecified" - month/dd/yyyy <only>    (Mikrotik sheduller format)
    #                   1 - yyyy/mm/dd hh:mm:ss
    #                   2 - dd:mm:yyyy hh:mm:ss
    #                   3 - dd month yyy hh mm ss
    #                   4 - yyyy month dd hh mm ss
    #                   5 - month/dd/yyyy-hh:mm:ss  (Mikrotik sheduller format)
    :local UnixTimeToFormat do={
        :local decodedLine "";
        :local timeStamp $1;
        :local timeS ($timeStamp % 86400);
        :local timeH ($timeS / 3600);
        :local timeM ($timeS % 3600 / 60);
        :set  $timeS ($timeS - $timeH * 3600 - $timeM * 60);
        :local dateD ($timeStamp / 86400);
        :local dateM 2;
        :local dateY 1970;
        :local leap false;
        :while (($dateD / 365) > 0) do={
            :set $dateD ($dateD - 365);
            :set $dateY ($dateY + 1);
            :set $dateM ($dateM + 1);
            :if ($dateM = 4) do={
                :set $dateM 0;
                :if (($dateY % 400 = 0) or ($dateY % 100 != 0)) do={
                    :set $leap true;
                    :set $dateD ($dateD - 1);
                }
            } else={ :set $leap false; }
        }
        :local months [:toarray (0,31,28,31,30,31,30,31,31,30,31,30,31)];
        :if (leap) do={
            :set $dateD ($dateD + 1);
            :set ($months->2) 29;
        }
        :do {
            :for i from=1 to=12 do={
                :if (($months->$i) > $dateD) do={
                    :set $dateM $i;
                    :set $dateD ($dateD + 1);
                    break;
                } else={ :set $dateD ($dateD - ($months->$i)); }
            }
        } on-error={}
        :local tmod;
        :if ([:len $2]!=0) do={ :set $tmod $2; } else={ :set $tmod (:nothing); }
        :local s "/";
        :local nf true;
        :local mstr {"jan";"feb";"mar";"apr";"may";"jun";"jul";"aug";"sep";"oct";"nov";"dec"};
        :local strY [:tostr $dateY];
        :local strMn;
        :local strD;
        :local strH;
        :local strM;
        :local strS;
        :if ($nf) do={
            :if ($dateM > 9) do={ :set $strMn [:tostr $dateM]; } else={ :set $strMn ("0".[:tostr $dateM]); }
            :if ($dateD > 9) do={ :set $strD  [:tostr $dateD]; } else={ :set $strD  ("0".[:tostr $dateD]); }
            :if ($timeH > 9) do={ :set $strH  [:tostr $timeH]; } else={ :set $strH  ("0".[:tostr $timeH]); }
            :if ($timeM > 9) do={ :set $strM  [:tostr $timeM]; } else={ :set $strM  ("0".[:tostr $timeM]); }
            :if ($timeS > 9) do={ :set $strS  [:tostr $timeS]; } else={ :set $strS  ("0".[:tostr $timeS]); }
        } else={
            :set strMn [:tostr $dateM];
            :set strD  [:tostr $dateD];
            :set strH  [:tostr $timeH];
            :set strM  [:tostr $timeM];
            :set strS  [:tostr $timeS];
        }
        :do {
            :if ([:len $tmod]=0) do={ :local mt ($mstr->($dateM - 1)); :set $decodedLine ("$mt/"."$strD/"."$strY"); break; }
            :if ($tmod = 1) do={ :set $decodedLine "$strY$s$strMn$s$strD $strH:$strM:$strS"; break; }
            :if ($tmod = 2) do={ :set $decodedLine "$strD$s$strMn$s$strY $strH:$strM:$strS"; break; }
            :if ($tmod = 3) do={ :set $decodedLine ("$strD ".($mstr->($dateM - 1))." $strY $strH:$strM:$strS"); break; }
            :if ($tmod = 4) do={ :set $decodedLine ("$strY ".($mstr->($dateM - 1))." $strD $strH:$strM:$strS"); break; }
            :if ($tmod = 5) do={ :local m ($mstr->($dateM - 1)); :set $decodedLine ("$m/"."$strD/"."$strY"."-$strH:$strM:$strS"); break; }
        } on-error={}
        :return ($decodedLine);
    }

    # Main body of the script
    :global timeAct;
    :global timeLog;
    :local  nameID [ /system identity get name; ];
    :local  timeOf [ /system clock get gmt-offset; ];
    :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Start of TLGRM-script on '$nameID' router.");
    :if ([:len $timeAct] > 0) do={ :put ("$[$UnixTimeToFormat ($timeAct + $timeOf) 1] - Time when the last command was launched."); }
    :if ([:len $timeLog] > 0) do={ :put ("$[$UnixTimeToFormat ($timeLog + $timeOf) 1] - Time when the log entries were last sent."); }

    # Part of the script body to launch via Telegram
    # https://forummikrotik.ru/viewtopic.php?p=78085
    :local  timeStamp [$EpochTime];
    :local  urlString "https://api.telegram.org/$botID/getUpdates\?offset=-1&limit=1&allowed_updates=message";
    :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - *** Stage of launch scripts, function & commands via Telegram:");
    :if ([:len $timeAct] = 0) do={
        :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Time of the last launch of the command was not found.");
        :set timeAct $timeStamp;
    } else={
        :local httpResp [ /tool fetch url=$urlString as-value output=user; ];
        :local content ($httpResp->"data");
        :if ([:len $content] > 30) do={
            :local msgTxt   [$MsgParser $content "text" true];
            :set   msgTxt  ([:pick $msgTxt  ([:find $msgTxt "/" -1] +1)  [:len $msgTxt]]);
            :local msgAddr ([:pick $msgTxt 0 [:find $msgTxt " " -1]]);
            :if ([:len [:find $msgTxt " "]]=0) do={ :set msgAddr ("$msgTxt "); }
            :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Recipient of the Telegram message: '$msgAddr'")
            :if ($msgAddr=$nameID or $msgAddr="forall") do={
                :set   msgTxt  ([:pick $msgTxt ([:find $msgTxt $msgAddr -1] + [:len $msgAddr] +1) [:len $msgTxt]]);
                :local chat     [$MsgParser $content "chat"];
                :local chatId   [$MsgParser $chat    "id"];
                :local userName [$MsgParser $content "username"];
                :set  timeStamp [$MsgParser $content "date"];
                :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Sender of the Telegram message: $userName")
                :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Command to execute: '$msgTxt'")
                :local restline [];
                :if ([:len [:find $msgTxt " "]] !=0) do={
                    :set restline [:pick $msgTxt  ([:find $msgTxt " "] +1) [:len $msgTxt]];
                    :set msgTxt [:pick $msgTxt 0 [:find $msgTxt " "]];
                }
                :if ($chatId=$myChatID && $timeAct<$timeStamp) do={
                    :set timeAct $timeStamp;
                    :if ([/system script environment find name=$msgTxt;]!="" && $launchFnc=true) do={   
                        :if (([/system script environment get [/system script environment find name=$msgTxt] value]="(code)") \
                            or  ([:len [:find [/system script environment get [/system script environment find name=$msgTxt;] value] "(eval"]]>0)) do={
                            :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Telegram user $userName launches function '$msgTxt'.");
                            :log warning ("Telegram user $userName launches function '$msgTxt'.");
                            [:parse ":global $msgTxt; [\$$msgTxt $restline]"];
                        } else={
                            :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - '$msgTxt' is a global variable and not a function - no execute.");
                            :log warning ("'$msgTxt' is a global variable and not a function - no execute.");
                        }
                    }
                    :if ([/system script find name=$msgTxt;]!="" && $launchScr=true) do={
                        :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Telegram user $userName activates script '$msgTxt'.");
                        :log warning ("Telegram user $userName activates script '$msgTxt'.");
                        [[:parse "[:parse [/system script get $msgTxt source]] $restline"]];
                    }
                    :if ([/system script find name=$msgTxt;]="" && [/system script environment find name=$msgTxt;]="" && $launchCmd=true) do={
                        :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Telegram user $userName is trying to execute command '$msgTxt'.");
                        :log warning ("Telegram user $userName is trying to execute command '$msgTxt'.");
                        :do {[:parse "/$msgTxt $restline"]} on-error={}
                    }
                } else={ :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Wrong time to launch."); }
            } else={ :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - No command found for this device."); }
        } else={ :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Completion of response from Telegram."); }
    }

    # Part of the script body for notifications in Telegram
    # https://www.reddit.com/r/mikrotik/comments/onusoj/sending_log_alerts_to_telegram/
    :local outMsg "";
    :local logGet [ :toarray [ /log find ($topics ~"warning" || $topics ~"error" || $topics ~"critical" || $topics ~"caps" \
    || $topics ~"wireless" || $message ~"logged in" || $message ~"TCP connection"); ]];
    :local logCnt [ :len $logGet ];
    :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - *** Stage of sending notifications to Telegram:");
    :if ([:len $timeLog] = 0) do={ 
        :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Time of the last log entry was not found.");
        :set outMsg (">$[ /system clock get time; ] Telegram notification started.");
    }
    :if ($logCnt > 0) do={
        :local lastTime [$EpochTime [ /log get [:pick $logGet ($logCnt-1)] time; ]];
        :local index 0;
        :local tempTime;
        :local tempMessage;
        :local tempTopic;
        :local unixTime;
        :do {
            :set index        ($index + 1); 
            :set tempTime     [ /log get [:pick $logGet ($logCnt - $index)]    time; ];
            :set tempTopic    [ /log get [:pick $logGet ($logCnt - $index)]  topics; ];
            :set tempMessage  [ /log get [:pick $logGet ($logCnt - $index)] message; ];
            :set tempMessage  (">".$tempTime." ".$tempMessage);
            :local findMacMsg ([$FindMacAddr $tempMessage]);
            :set unixTime [$EpochTime $tempTime];
            :if (($unixTime > $timeLog) && (!(($tempTopic ~"caps" || $tempTopic ~"wireless" || $tempTopic ~"dhcp") \
            && ($tempMessage != $findMacMsg)))) do={
                :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Found log entry: $findMacMsg");
                :set outMsg ($findMacMsg."\n".$outMsg);
            }
        } while=(($unixTime > $timeLog) && ($index < $logCnt));
        :if (([:len $timeLog] < 1) || (([:len $timeLog] > 0) && ($timeLog != $lastTime) && ([:len $outMsg] > 8) )) do={
            :set timeLog $lastTime;
            :if ([:len $outMsg] > 4096) do={ :set outMsg ([:pick $outMsg 0 4096]); }
            :set outMsg [$CP1251toUTF8 $outMsg];
            :local urlString ("https://api.telegram.org/$botID/sendmessage\?chat_id=$myChatID&text=$nameID:%0A$outMsg");
            :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Generated string for Telegram:\r\n".$urlString);
            /tool fetch url=$urlString as-value output=user;
        } else={ :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - There are no log entries to send."); }
    } else={ :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - Necessary log entries were not found."); }
    :put ("$[$UnixTimeToFormat ([$EpochTime] + $timeOf) 1] - End of TLGRM-script on '$nameID' router.");
} on-error={ 
    :put ("Script error: something didn't work when sending a request to Telegram.");
    :put ("*** First, check the correctness of the values of the variables botID & myChatID. ***"); 
}



Для тех, кто ещё не в теме кратко расскажу:

:men: TLGRM - комбинированный скрипт оповещения в Телеграм и удалённого запуска функций, скриптов и команд RouterOS.
В скрипте использованы идеи и часть кода by Sertik, Virtue, Pepelxl, Dimonw, Jotne, Alice Tails, drPioneer.
Для работы скрипта должны быть заранее известны и указаны BotID и ChatID.
Скрипт необходимо добавить в System/Sheduler и установить запуск с нужной периодичностью.
Суть работы скрипта сводится к выполнению двух основных задач:
  1. Чтение последнего сообщения в Телеграм-группе на предмет наличия адресованного послания. При наличии такого послания скрипт пытается его разобрать и исполнить.
  2. Поиск в журнале устройства сообщений о подозрительных событиях и их пересылка в Телеграм-группу.
Для отправки команды конкретному роутеру в Телеграм-группе, необходимо сформировать текстовое сообщение. Начало сообщения обозначается символом "/", затем указывается имя роутера (должно соответствовать записи в /system identity, при этом регистр букв имеет значение и не должно содержать пробелов), далее через пробел пишется команда.
Для отправки команды всем роутерам в Телеграм-группе вместо имени указывается 'forall'.
В качестве команды могут выступать: имя глобальной функции, имя скрипта или команда RouterOS. Например:

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

  /forall log warning [/system identity get name]
  /Mikrotik1 wol
Особенности работы скрипта:
  • поддерживается отправка сообщений в Телеграм-группу с кириллицей
  • непечатные символы при отправке в Телеграм-группу обрезаются
  • сообщение длиной более 4096 перед отправкой в Телеграм-группу обрезается до 4096 символов
  • скрипт читает только ПОСЛЕДНЕЕ сообщение в Телеграм-группе. По этой причине не имеет смысла накидывать сразу много команд, в любом случае будет выполнена только последняя.
  • поддерживается индивидуальная и групповая адресация команд
  • при запуске скрипта в терминале можно наблюдать за ходом его выполнения
Ну и как всегда конструктивная критика и усовершенствования только приветствуются! :a_g_a:
Последний раз редактировалось drpioneer 07 апр 2022, 09:05, всего редактировалось 6 раз.


Ответить