оповещение в телегу

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

Согласен с Вами, вероятно эти строчки не нужны совсем. Не знаю зачем они были введены создателем скрипта.
Спасибо, что заметили ! Уберем их - скрипт будет ещё короче !

Или надо ставить :if ([:len $currentTime] > 8 ) do={
:set currentTime [ :pick $currentTime 0 7 ];


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

Попробовал Ваш скрипт:

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

# Telegram notification script by drPioneer
# https://forummikrotik.ru/viewtopic.php?p=81685#p81685
# tested on ROS 6.48.3
# updated 2021/10/01

:global oldString;

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

    # Function of converting UTF8 to codes by Sertik
    # https://forummikrotik.ru/viewtopic.php?p=81457#p81457
    :local Utf8Converter do={
        :local rsimv [:toarray {"А"="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"; "№"="0023"; " "="0020"; "^"="005E"}]
        :local convertString ""; 
        :local code          "";
        :for i from=0 to=([:len $1]-1) do={
            :local keys [:pick $1 $i (1+$i)]; 
            :local key ($rsimv->$keys); 
            if ([:len $key]!=0) do={
                :set $code ("%"."$[:pick ($rsimv->$keys) 0 2]"."%"."$[:pick ($rsimv->$keys) 2 4]");
                :if ([pick $code 0 3] ="%00") do={ :set $code ([:pick $code 3 6]); }
            } else={ :set code ($keys); }; 
        :set $convertString ($convertString.$code);
        }
    return $convertString;
    }

    # Main body of Telegram notification script by Virtue
    # https://forummikrotik.ru/viewtopic.php?p=73994#p73994
    :local nameID  [ /system identity get name; ];
    :local timeNow [ /system clock    get time; ];
    :local logs "";
    :if ([:pick $timeNow 0 2] < 03) do={
        :local date [ /system clock get date; ];
        :foreach h in=[ /log find; ] do={
            :local htime [ /log get $h time; ];
            :if (($htime ~[:pick $date 0 6]) && ([:pick $htime 7 15] > ($timeNow - 00:01:00))) do={ :set logs ($logs, $h); }
        }
    } else={ :set logs [ /log find time >= ($timeNow - 00:01:00) ]; }
    :if ([:len $logs] > 0 ) do={
        :local message "";
        :local presence false;
        :foreach i in=$logs do={
            :local imessage [ /log get $i message; ];
            :local topics   [ /log get $i topics; ];
            :if ($imessage ~"telnet" && $imessage ~"logged in") do={ } else={
                :if ($topics ~"caps" || $topics ~"wireless") do={
                    :if ($imessage ~"[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 k  in=[ /ip dhcp-server lease find dynamic=no disabled=no; ] do={
                            :local mac [ /ip dhcp-server lease get $k mac-address; ];
                            :if ($imessage ~"$mac") do={ :set presence true; }
                        }
                    }
                    :if (presence = false) do={
                        :local currentTime [ /log get $i time; ];
                        :set message ($message.$currentTime." ".$imessage."%0A%0A");
                    }
                }
                :if ($topics ~"warning" || $topics ~"error" || $topics ~"critical" || $imessage ~"logged in") do={
                    :if ($imessage ~"[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 k  in=[ /ip dhcp-server lease find dynamic=no disabled=no; ] do={
                            :local mac [ /ip dhcp-server lease get $k mac-address; ];
                            :if ($imessage ~"$mac") do={ :set imessage ($imessage." / ".[ /ip dhcp-server lease get $k comment; ]); }
                        }
                    }
                :local currentTime [ /log get $i time; ];
                :set message ($message.$currentTime." ".$imessage."%0A%0A");
                }
            }
        }
        :if ([:len $message] > 0 ) do={
            :local urlString ("https://api.telegram.org/$botID/sendmessage\?chat_id=$myChatID&text=$nameID:%0A$message");
            :set urlString [$Utf8Converter $urlString];
            :if ($urlString != $oldString) do={
                :put ("Generated string for Telegram:\r\n".$urlString);
                :set oldString ($urlString);
                /tool fetch keep-result=no url=$urlString;
            } else={ :put ("Message has already been sent."); }
        } else={ :put ("No necessary conditions for generating a message."); }
    } else={ :put ("No new log entries found."); }
}

почему то он у меня совсем не работает ... :ne_vi_del: В чём может быть проблема ?
Да, и у меня Чат ID без минуса. Может в этом дело ? Минус даётся если чат в группу добавлен или как ?


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

Добрый день.
Sertik писал(а): 04 окт 2021, 13:31 1. Зачем в скрипте моя функция конвертер русского текста для Телеграмм ?
........

2. Однако у меня очень давно на всех роутерах стоит вот такой скрипт оповещения событий роутера в Телеграмм, добытый где-то на просторах интернет. К сожалению не знаю автора, но скрипт работает чудесно, ни разу не подводил и сам очень короткий. Вот такой:
........
1. Согласен. Тут я, пожалуй, переборщил. Не нужна она там.

2. Скрипт интересен и лаконичен. Кстати он имеет автора - AliceTails и представлен вот здесь: https://www.reddit.com/r/mikrotik/comme ... _telegram/

Такими мне видятся его сильные и слабые стороны:
+ лаконично описана логика
+ не привязан к интервалу времени запуска и помнит время последней отправленной записи
- не умеет слать пачку записей, шлёт только последнюю найденную запись
- рассылает много ненужного (спамит)

А вот сильные и слабые стороны скрипта от Virtue:
+ не спамит (выбирает только важные для меня записи)
+ умеет присовокуплять к записям комментарии из DHCP
+ умеет слать пачку записей, если таковые имеются
- жестко привязан к периоду времени запуска и не запоминает последнюю отправленную запись

И вот у меня зачесались руки попытаться сделать скрипт, собравший в себе лучшее от этих двух... Интересно же...

Из скрипта Virtue дёрнул часть кода, прилепляющую к сообщениям комментарии из DHCP-lease и оформил её в функцию FindMacAddr. На вход этой функции прилетает строка. Функция производит поиск MAC-адреса и если таковой имеется, пытается подставить соответствующий ему комментарий из DHCP-lease. Плюс прикрутил поиск MAC-адреса в списке Bridge/Hosts с подстановкой соответствующего имени интерфейса. На выход функция отправляет эту же строку с найденным комментарием или без оного.

Для корректного взаимодействия с Telegram я задействовал предложенную во всеобщее пользование функцию SpaceToCode от Sertik, которая заменяет пробелы на "%20".

Для корректной работы с временными интервалами использовал функцию EpochTime от Jotne ( https://forum.mikrotik.com/viewtopic.ph ... 55#p790745 ), преобразующую дату и время Mikrotik в UNIX-time.

А дальше правка логики работы скрипта от AliceTails...

Получилась такая портянка:

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



# Telegram notification script by drPioneer
# https://forummikrotik.ru/viewtopic.php?p=81726#p81726
# tested on ROS 6.48.3
# updated 2021/10/14

: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 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 SPACE to CODE by Sertik
    # https://forummikrotik.ru/viewtopic.php?p=81481#p81481
    :local SpaceToCode do={
        :local char   "";
        :local string "";
        :for idx from=0 to=([len $1]-1) do={
            :set $char [:pick $1 $idx]
            :if ($char=" ") do={ :set $char "%20"; }
            :set $string ($string.$char);
        }
        :return ($string);
    }
    
    # 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] > 8) 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 Telegram notification script by AliceTails
    # https://www.reddit.com/r/mikrotik/comments/onusoj/sending_log_alerts_to_telegram/
    :global lastTimeLog;
    
    :local outMsg "";
    :local nameID [ /system identity get name; ];
    :local logGet [ :toarray [ /log find ($topics ~"warning" || $topics ~"error" || $topics ~"critical" || $topics ~"caps" || $topics ~"wireless" || $message ~"logged in"); ]];
    :local logCnt [ :len $logGet ];
    if ([:len $lastTimeLog] < 1) 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 > $lastTimeLog) && (!(($tempTopic ~"caps" || $tempTopic ~"wireless" || $tempTopic ~"dhcp") && ($tempMessage != $findMacMsg)))) do={
                    :put $findMacMsg;
                    :set outMsg ($findMacMsg."%0A".$outMsg);
            }
        } while=(($unixTime > $lastTimeLog) && ($index < $logCnt));
        :if (([:len $lastTimeLog] < 1) || (([:len $lastTimeLog] > 0) && ($lastTimeLog != $lastTime) && ([:len $outMsg] > 8) )) do={
            :set lastTimeLog $lastTime;
            :local urlString ("https://api.telegram.org/$botID/sendmessage\?chat_id=$myChatID&text=$nameID:%0A$outMsg");
            :set urlString [$SpaceToCode $urlString];
            :put ("Generated string for Telegram:\r\n".$urlString);
            /tool fetch keep-result=no url=$urlString;
        } else={ :put ("Nothing to send."); }
    } else={ :put ("Necessary log entries were not found."); }
} on-error={ :put ("Script error: check whether 'botID' & 'myChatID' variables are specified correctly."); }



Вкратце пробегусь по коду:

1. В $logGet закидываются все потенциально интересные нам записи из LOGа. Если таких записей не нашлось, тогда работа скрипта завершается.
2. Циклично перебираются найденные записи журнала пока их время свежЕе, чем время последнего сообщения, отправленного в Telegram.
3. В теле цикла каждая запись прогоняется через функцию FindMacAddr, которая по необходимости прилепляет к ней комментарий.
4. В теле цикла также производится дополнительная фильтрация записей, чтобы рассылать меньше спама.
5. По окончании работы цикла будет сгенерировано сообщение, состоящее из нескольких выбранных и прокомментированных записей журнала, если таковые имелись.
6. Если есть что отправлять, тогда формируется строка для отправки в Telegram с попутным задействованием функции SpaceToCode и собственно производится отправка. Плюс к этому в $lastTimeLog запоминается время последней отправки.
7. Вся работа скрипта со временем производится через функцию EpochTime от Jotne, исключающую проблемы при начале новых суток.
8. В процессе работы скрипт выводит информацию для облегчения понимания происходящего.

Примерно так...
Не претендую на совершенство кода. Допускаю ошибки и недоработки. Путаю педали. Все замечания и конструктивная критика приветствуются.
Последний раз редактировалось drpioneer 14 окт 2021, 17:05, всего редактировалось 31 раз.


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

Вопрос. Можно ли запускать Ваш логгер быстрее, скажем не раз в минуту, а раз в 15 секунд ?


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

Sertik писал(а): 06 окт 2021, 13:11 Вопрос. Можно ли запускать Ваш логгер быстрее, скажем не раз в минуту, а раз в 15 секунд ?
Версия скрипта, сочетающая в себе достоинства обоих скриптов ( viewtopic.php?p=81726#p81726 ) не привязана ко времени запуска - запускайте, как вам вздумается.


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

Приветствую!

Обнаружился косяк в работе скрипта при переходе через 00ч 00м 00с.
Причина кроется в том, что для записей журнала свежее 24 часов отображается только время, а для записей старше 24 часов отображается месяц, число и время...
И отсюда, кстати, растут ноги ранее обсуждаемого куска кода:

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

:if ([ :len $lastTime ] > 10 ) do={ :set lastTime [:pick $lastTime 0 10]; }
Но и этот кусок кода не решает всей проблемы времени в журнале Mikrotik.
Проблему удалось исправить путём преобразования времени в UNIX-time, для этого была применена функция EpochTime от Jotne, честно скопипащенная с: https://forum.mikrotik.com/viewtopic.ph ... 55#p790745

В результате, код скрипта немного подрос: viewtopic.php?p=81726#p81726

Проверяйте...


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

drpioneer писал(а): 07 окт 2021, 10:13 Приветствую!
здрасте..

1. код был не > 10 а = 10

2. при любом раскладе, лог гет тайм выдает либо 8, либо 15 знаков

Изображение

3. из выше сказанного остается непонятным вырезание от 0 до 10


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

Virtue писал(а): 07 окт 2021, 16:09 1. код был не > 10 а = 10

2. при любом раскладе, лог гет тайм выдает либо 8, либо 15 знаков

Изображение

3. из выше сказанного остается непонятным вырезание от 0 до 10
Чуть выше мы уже определились, что этот кусок кода написан с косяками...
Я лишь могу предположить, что в конечном варианте автор хотел изобразить следующее:
- если в строке со временем, помимо времени оказалась дата, тогда дату нужно отрезать.
На мой взгляд, такое предположение вписывается в логику работы его кода.
Видимо он упустил этот момент и забыл это подправить в конечном варианте.


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

drpioneer писал(а): 07 окт 2021, 10:13 Обнаружился косяк в работе скрипта при переходе через 00ч 00м 00с.
Причина кроется в том, что для записей журнала свежее 24 часов отображается только время, а для записей старше 24 часов отображается месяц, число и время...
.............
Проблему удалось исправить путём преобразования времени в UNIX-time, для этого была применена функция EpochTime от Jotne, честно скопипащенная с: https://forum.mikrotik.com/viewtopic.ph ... 55#p790745

В результате, код скрипта немного подрос: viewtopic.php?p=81726#p81726
Нашёл и исправил ещё один косяк со временем в теле функции EpochTime. Код скрипта обновил.
Перед запуском скрипта нужно удалить переменную 'lastTimeLog' из System/Scripts/Enviroment.


iBuddha
Сообщения: 1
Зарегистрирован: 17 окт 2021, 05:46

drpioneer писал(а): 12 окт 2021, 15:02
drpioneer писал(а): 07 окт 2021, 10:13 Обнаружился косяк в работе скрипта при переходе через 00ч 00м 00с.
Причина кроется в том, что для записей журнала свежее 24 часов отображается только время, а для записей старше 24 часов отображается месяц, число и время...
.............
Проблему удалось исправить путём преобразования времени в UNIX-time, для этого была применена функция EpochTime от Jotne, честно скопипащенная с: https://forum.mikrotik.com/viewtopic.ph ... 55#p790745

В результате, код скрипта немного подрос: viewtopic.php?p=81726#p81726
Нашёл и исправил ещё один косяк со временем в теле функции EpochTime. Код скрипта обновил.
Перед запуском скрипта нужно удалить переменную 'lastTimeLog' из System/Scripts/Enviroment.
Добрый день!
Большое спасибо за готовый скрипт :bra_vo: С последним исправлением времени - все отлично работает.
Блуждая по интернетам нашел еще один простенький скрипт для DHCP сервера

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

:if ($leaseBound = "1") do={
/ip dhcp-server lease 
:log info ("Device: ". "$[get [find active-mac-address=$leaseActMAC] host-name] ". "$[get [find active-mac-address=$leaseActMAC] comment]"."  was given an address "."$[get [find active-mac-address=$leaseActMAC] address]")
}
Он делает лог с выдачей адресов чуть более читабельным (для меня), например:
script, info Device: yandex-station-lite was given an address 192.168.88.19
Собственно вопрос: можно ли ваш скрипт переориентировать с MAC на IP?


Ответить