Скрипты через Telegram

Здесь выкладываем скрипты
Правила форума
Уважаемые Пользователи форума, обратите внимание!
Ни при каких обстоятельствах, Администрация форума, не несёт ответственности за какой-либо, прямой или косвенный, ущерб причиненный в результате использования материалов, взятых на этом Сайте или на любом другом сайте, на который имеется гиперссылка с данного Сайта. Возникновение неисправностей, потерю программ или данных в Ваших устройствах, даже если Администрация будет явно поставлена в известность о возможности такого ущерба.
Просим Вас быть предельно осторожными и внимательными, в использовании материалов раздела. Учитывать не только Ваши пожелания, но и границы возможностей вашего оборудования.
Ответить
-13-
Сообщения: 124
Зарегистрирован: 18 мар 2021, 12:45

Всем привет.

Есть у меня некоторое количество устройств MikroTik (пополняемое), на которые прикрутил ботов от телеграм.
Скрипты есть мои и чужие (авторство не указано, но некоторые из них "допиливал" под себя).
Боты у меня сидят в групповых чатах, работу в приватных не проверял (вроде должно работать).

И так начнем... при старте системы отрабатывает scheduler, запускаем один раз при старте, разрешения (read, write, policy, test)
 Startup RB - scheduler

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

# Name: -Startup RB
# Description: Run startup script "-Startup RB"

delay 30s
system script run "Global Environment"

delay 10s
local startUp [parse [system script get "-Startup RB" source]]
$startUp

# End


Скрипты...

глобальные переменные, разрешения (read, write, policy, test)
 Global Environment - script

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

# Name: Global Environment
# Description: botInfo && functions 

## Telgram info
global botID "вписать свой bot id"
global myChat "вписать свой chat id"

## Functions
/system script {

## Send message
:global fnSend [:parse [get "fnSend" source]]

## Get ISP status
:local fnCheckISP [:parse [get "fnCheckISP" source]]
:global ISP1 ([$fnCheckISP i="ether4_ISP1"])
:global ISP2 ([$fnCheckISP i="ether3_ISP2"])

}
## End functions

# End Script

сообщение о старте системы, разрешения (все выключаем, включаем "dont require permissions")
 Startup RB - script

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

# Name: -Startup RB
# Description: Send info, if RB started or reboot

global fnSend
global myChat

local syName [system identity get name]
local cuDate ([system clock get date]." - ".[system clock get time])
local cuUptime [system resource get uptime]
local listISP [[parse [system script get "fnListISP" source]]]

local text \
  "\"$syName\": RB start%0A\
  $cuDate%0A\
  UpTime - $cuUptime%0A\
  $listISP"

$fnSend chatid=$myChat text=$text

# End script

скрипт для отправки сообщений, разрешения (все выключаем, включаем "dont require permissions")
 fnSend - script

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

# Name: fnSend
# Description: Send message (function)

global botID
local apiTg "https://api.telegram.org/bot"
local fetchSend ("/sendmessage?chat_id=" . $chatid . "&text=" . $text)
set fetchSend ($apiTg . $botID . $fetchSend)

tool fetch url=$fetchSend output=none

# End script
Последний раз редактировалось -13- 13 апр 2022, 17:12, всего редактировалось 1 раз.


-13-
Сообщения: 124
Зарегистрирован: 18 мар 2021, 12:45

Следующий этап.
Создаем в scheduler, разрешения (read, write, policy, test), задаем нужный интервал, у меня стоит раз в 1 минуту
 Check botChat - scheduler

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

# Name: Check botChat
# Description: Start script "Check botChat", w/WatchDog

local jobScript "Check botChat"
if ([len [system script job find script=$"jobScript"]] !=0) do={
} else={
system script run $jobScript
}

# End

Собственно сам скрипт (не мой, немного модифицировал), разрешения (read, write, policy, test).
Распознает чаты, свой-чужой.
В ROS6 отваливался с ошибкой через 5 минут работы после старта системы, дальше работал без ошибок.
В ROS7 пока не наблюдал подобного, но "WatchDog" оставил.
 Check botChat - script

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

# Name: Check botChat
# Description: Check message to botTelegram

global botID
global myChat
global fnSend

local apiTg "https://api.telegram.org/bot"
local messageId 0

local parse do={
  local startLoc ([find $content $variable -1] + [len $variable] + 2)
  local commaLoc ([find $content "," $startLoc] - 1 + 1)
  local braceLoc ([find $content "}" $startLoc] - 1 + 1)
  local endLoc $commaLoc
  local startSymbol [pick $content $startLoc]
  if ($braceLoc != 0 and ($commaLoc = 0 or $braceLoc < $commaLoc)) do={
    set endLoc $braceLoc
  }
  if ($startSymbol = "{") do={
    set endLoc ($braceLoc + 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
}


while ( true ) do={
  do {
    local fetchCheck ("/getUpdates\?offset=$messageId&limit=1&allowed_updates=message&timeout=60")
    set fetchCheck ($apiTg . $botID . $fetchCheck)
    local content ([tool fetch url=$fetchCheck as-value output=user]->"data")

    if ([:len $content] > 30) do={
      set messageId ([$parse content=$content variable="update_id"] + 1)
      local message [$parse content=$content variable="text" quotas=true]
      local chat [$parse content=$content variable="chat"]
      local chatid [$parse content=$chat variable="id"]

## Chat authentication.
    if ($chatid = $myChat) do={
      local fnChat [parse [system script get "fnChat" source]]
      $fnChat message=$message chatid=$chatid
      } else={
      local text "No one's home."
      local fetchLeave ("/leaveChat\?chat_id=" . $chatid)
      set fetchLeave ($apiTg . $botID . $fetchLeave)
      $fnSend chatid=$chatid text=$text
      tool fetch url=$fetchLeave output=none
      }
    }
  } on-error={}
}

# End script


-13-
Сообщения: 124
Зарегистрирован: 18 мар 2021, 12:45

Продолжаем..
Если чат наш, отрабатывает следующий скрипт, разрешения (все выключаем, включаем "dont require permissions")
 fnChat - script

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

# Name: fnChat
# Description: Identification message (function)

global fnSend
local cmd 0

if ($message ~"@") do={
set $message [pick $message 0 [find $message "@"]]
}

## Identification get message
if [system script find name=$message] do={set cmd 1
  local fnScript [parse [system script get $message source]]
  $fnScript chatid=$chatid
}

if [interface l2tp-client find name=[:pick $message 1 [:len $message]]] do={set cmd 1
  local fnOnVPN [parse [system script get "fnOnVPN" source]]
  $fnOnVPN chatid=$chatid message=[pick $message 1 [len $message]]
}

if ($message ~"/OFF_vpn") do={set cmd 1
  local fnOffVPN [parse [system script get "fnOffVPN" source]]
  $fnOffVPN chatid=$chatid
}

if ($message ~"^/ping") do={set cmd 1
  local fnPing [parse [system script get "fnPing" source]]
  $fnPing chatid=$chatid message=$message
}

if ($message ~"^/homeip") do={set cmd 1
  local fnHomeipVPN [parse [system script get "fnHomeipVPN" source]]
  $fnHomeipVPN chatid=$chatid message=$message
}

if ($cmd = 0) do={
  set $text "unknow cmd - $message"
  $fnSend chatid=$chatid text=$text
}

# End script


Основной скрипт-команда, указанный отцу ботов, разрешения (все выключаем, включаем "dont require permissions").
Естественно отцу пишем без "/", этот скрипт обычно называю по имени устройства/бота, здесь будет просто "/check".
Этот использую на домашнем роутере, выдает нужные мне параметры и команды.
 /check - script

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

# Name: /check
# Description: Check and Commands 'HomeRB'

global fnSend

local syName [system identity get name]
local cuDate ([system clock get date]." - ".[system clock get time])
local cuUptime [system resource get uptime]
local cuHealth ([system health get value-name=value [find type=C]]."%C2%B0C, ".[system health get value-name=value [find type=V]]."V")

local listISP [[parse [system script get "fnListISP" source]]]

## Check L2TP-Server current status
if ([interface l2tp-server server get enabled]=true) do={
  set $cuL2TP "ON"
  } else={
  set $cuL2TP "OFF"
}

## Get all commands for botTelegram
foreach Cmd in=[system script find name~"^/"] do={
  set $listCmd ($listCmd."".[system script get $Cmd name])
  set $listCmd ($listCmd." - ".[system script get $Cmd comment]."%0A")
}

## Send to Telegram
set $text \
  "\"$syName\"%0A\
  $cuDate%0A\
  UpTime: $cuUptime%0A\
  Health: $cuHealth%0A\
  L2TP Server: $cuL2TP%0A\
  $listISP%0A\
  $listCmd"

$fnSend chatid=$chatid text=$text

# End script

Список IP адресов выдаваемых провайдерами, в скрипте 2шт, разрешения (все выключаем, включаем "dont require permissions")
Для основного скрипта команды "/check".
 fnListISP - script

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

# Name: fnListISP
# Description: get ISP name&status

foreach i in=[ip dhcp-client find] do={
  set $etherISP [ip dhcp-client get $i interface]
  set $nameISP [ip dhcp-client get $i comment]
  set $statusISP ([ip dhcp-client get $i]->"status")
    if ([len $statusISP]=0) do={
    set $statusISP ([interface ethernet monitor $etherISP once as-value]->"status")
    }
  set $ipISP [ip dhcp-client get $i addr]
    if ([len $ipISP]!=0) do={
    set $ipISP [pick [ip dhcp-client get $i addr] 0 [find [ip dhcp-client get $i addr] "/"]]
    } else={
    set $ipISP "\"$statusISP\""
    }
  set $listISP ($listISP."".$nameISP." - ".$ipISP."%0A")
}

return $listISP

# End



Пара команд-скриптов, разрешения (все выключаем, включаем "dont require permissions").
Включают и отключаю L2TP-server и соответствующие правила Firewall.

 /vpnON - script

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

# Name: /vpnON
# Description: L2TP-Server ON

global fnSend

local syName [system identity get name]
local cuDate ([system clock get date]." - ".[system clock get time])
local text "\"$syName\"%0A$cuDate%0AL2TP Server: "

if ([interface l2tp-server server get enabled]=false) do={
  interface l2tp-server server set enabled=yes
  ip firewall filter set [find comment~"IPsec"] disabled=no
  set $cuL2TP "ON"
} else={
  set $cuL2TP "enabled already"
}
set text ($text . $cuL2TP)

$fnSend chatid=$chatid text=$text

# End script

 /vpnOFF - script

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

# Name: /vpnOFF
# Description: L2TP-Server OFF

global fnSend

local syName [system identity get name]
local cuDate ([system clock get date]." - ".[system clock get time])
local text "\"$syName\"%0A$cuDate%0AL2TP Server: "

if ([interface l2tp-server server get enabled]=true) do={
  interface l2tp-server server set enabled=no
  ip firewall filter set [find comment~"IPsec"] disabled=yes
  set $cuL2TP "OFF"
} else={
  set $cuL2TP "disabled already"
}
set text ($text . $cuL2TP)

$fnSend chatid=$chatid text=$text

# End script
Последний раз редактировалось -13- 26 мар 2022, 18:33, всего редактировалось 2 раза.


-13-
Сообщения: 124
Зарегистрирован: 18 мар 2021, 12:45

Пингуем, разрешения (все выключаем, включаем "dont require permissions")
 fnPing - script

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

# Name: fnPing
# Description: Ping any address (function)

global fnSend

## Identification pinghost
set $pinghost [pick $message 6 [len $message]]
if ([len $pinghost]=0) do={
set $text "impossible ping the nothing"
} else={
do {
if ($pinghost ~ "[a-z | A-Z]") do={
  set $pingaddr [resolve $pinghost]
  } else={
  set $pingaddr "$pinghost"
  }
} on-error={
set $pingaddr "$pinghost"
}

## Ping address
do {
  tool flood-ping count=4 $pingaddr do={
    :set $text ("pong: Max " .$"max-rtt". "ms from " .$pinghost. " with " .$received. "/" .$sent)
  }
} on-error={
set $text ("pong: No response from $pinghost")
}
}

$fnSend chatid=$chatid text=$text

# End

Провайдер дает белый IP, а за статику платить не хочется? Скрипты наше всё...
Скрипт меняет L2TP-клиенту адрес, разрешения (все выключаем, включаем "dont require permissions").
 fnHomeip - script

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

# Name: fnHomeip
# Description: Change IP to HomeVPN

global fnSend

local homeip [pick $message 8 [len $message]]
local VPNtoHome [interface l2tp-client set [find comment="L2TP to Home"] connect-to=$homeip]
  
local text "VPN to 'Home' ip set "

$VPNtoHome
set text ($text . $homeip)

$fnSend chatid=$chatid text=$text

# End


-13-
Сообщения: 124
Зарегистрирован: 18 мар 2021, 12:45

Основной скрипт-команда, но используется на микротиках за NAT, для удаленного подключения последних к серверу L2TP.
Опять же, называю именем устройства.
 /bot1

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

# Name: /bot1
# Description:

global fnSend

local syName [system identity get name]
local cuDate ([system clock get date]." - ".[system clock get time])
local cuUptime [system resource get uptime]
local cuIP [ip dhcp-client get [find comment="GET from DHCP"] addr]
local cuGW [ip dhcp-client get [find comment="GET from DHCP"] gateway]

local text "\"$syName\" - I'm work%0A\
                 $cuDate%0A\
                 uptime: $cuUptime%0A\
                 IP: $cuIP%0A\
                 GW: $cuGW%0A%0A\
                 List VPN - ON/OFF and Status%0A"

local StatusVPN [[parse [system script get "fnStatusVPN" source]]]

## Get all commands for botTelegram
foreach Cmd in=[system script find name ~"^/"] do={
  set $ListCmd ($ListCmd . [system script get $Cmd name])
  set $ListCmd ($ListCmd." - ".[system script get $Cmd comment]."%0A")
}

set $text ($text.\
               $StatusVPN.\
               "/OFF_vpn - OFF all VPN-clients%0A%0A".\
               $ListCmd)

$fnSend chatid=$chatid text=$text

# End Script


К нему идут еще 3 скрипта

Список L2TP-клиентов, который по совместительству еще и включает нужный клиент с помощью следующего скрипта
 fnStatusVPN - script

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

# Name: fnStatusVPN
# Description: Get L2TP-Clients name&status

foreach VPN in=[interface l2tp-client find] do={
  set $nameVPN ("".[interface l2tp-client get $VPN name])
  set $cuStatusVPN ([interface l2tp-client monitor $VPN once as-value]->"status")
    if ([$cuStatusVPN] ~"terminating") do={
    set $cuStatusVPN "disabled"
    }
  set $StatusVPN ($StatusVPN . "/$nameVPN - $cuStatusVPN%0A")
}

return $StatusVPN

# End

Включаем клиента
 fnOnVPN

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

# Name: fnOnVPN
# Description: ON VPN-client 

global fnSend

local syName [system identity get name]
local cuDate ([system clock get date]." - ".[system clock get time])
local nameVPN "$message"
local cuStatusVPN ([interface l2tp-client monitor $nameVPN once as-value]->"status")
local text "\"$syName\":%0A$cuDate%0A"

if ([$cuStatusVPN] = "connected") do={
  set text "already connected"
} else={
  interface l2tp-client disable [find name]
  delay 1
  interface l2tp-client enable $nameVPN
  set text ($text . "VPN status: wait...")
}

$fnSend chatid=$chatid text=$text

# End Script

Выключаем всех клиентов
 fnOffVPN - script

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

# Name: fnOffVPN
# Description: OFF all VPN-clients

interface l2tp-client disable [find name]

global fnSend

local syName [system identity get name]
local cuDate ([system clock get date]." - ".[system clock get time])
local StatusVPN [[parse [system script get "fnStatusVPN" source]]]
local text "\"$syName\":%0A$cuDate%0A%0A"

set text ($text . $StatusVPN)

delay 3
$fnSend chatid=$chatid text=$text

# End Script


-13-
Сообщения: 124
Зарегистрирован: 18 мар 2021, 12:45

Вопросы и критику приветствую.
Возможно будет продолжение...


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

Написано красиво, профессионально, но гемморойно в установке. Нельзя ли сделать один файл-установщик в шапке которого можно было бы настроить необходимые параметры, а дальше он сам всё бы разрулил ? Думаю вполне реально. И в файле основном-командере зачем проверять на каждую команду с помощью :if do else ? Можно занести все команды в массив и в нём искать, если найдено - исполнить, если нет - выдать ошибку ... + нет возможностей запуска команд-функций. Это не сложно сделать ...


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
-13-
Сообщения: 124
Зарегистрирован: 18 мар 2021, 12:45

Sertik писал(а): 29 мар 2022, 15:01 Написано красиво, профессионально, но гемморойно в установке. Нельзя ли сделать один файл-установщик в шапке которого можно было бы настроить необходимые параметры, а дальше он сам всё бы разрулил ? Думаю вполне реально. И в файле основном-командере зачем проверять на каждую команду с помощью :if do else ? Можно занести все команды в массив и в нём искать, если найдено - исполнить, если нет - выдать ошибку ... + нет возможностей запуска команд-функций. Это не сложно сделать ...
Я не волшебник, я пока еще только учусь :-):

По порядку:

1 - Файл-установщик нужен, может как-нибудь осилю, пока что у меня конфиги типовые, и там я меняю только "botID" и идентификатор устройства, заливаю весь конфиг разом через терминал. Но универсальный установщик скриптов нужен...
Опять же, если в терминале не указывать разрешения для скрипта, он ставит галки на все, как это обойти пока не нашел...

2 - Основной командер - это какой? "fnChat - script" про него речь?
 изящный код

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

:global selector do={
  :if ($1 = "A") do={
    ...
    :return a
  }
  :if ($1 ="B") do={
    ...
    :return b
  }
  :if ($1 = "C") do={
    ...
    :return c
  }
}
источник - https://habr.com/ru/post/650795/
Думаю про это, как красивее использовать...

3 - Запуск команд-функций для чего? На то они и функции... Ну или поясните на примере что хотелось бы запускать?


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

1. Вы согласны - это хорошо, будем ждать версию с установщиком.

2. Да это про него, можно сделать нагляднее, удобнее для внесения новых команд, когда они появятся, потом кину Вам пример в личку.

3. Насчёт функций: функции могут иметь параметры и возвращать результат. Собственно скриптам параметры тоже можно передать, есть хитрость одна. Функции должны находиться "в режиме готовности" - висеть в окружении, как глобал-переменные. Кто-то боится, что это занимает память. Да, занимает, но проблем в работе от этого у меня никогда не было, хотя в памяти различных по архитектуре роутеров "висит" обычно 50, а где то и 150 ... функций в окружении.
Если Ваш скрипт запускает команды, то использовать их с параметрами даёт больше возможностей при минимуме имён команд.
Например, у Вас есть команда ну скажем UserPass, которая без параметров выдает в Телеграмм список всех пользователей роутера и их паролей. А использованная с параметрами, например, как UserPass newUser newPass, добавляет пользователя роутера с указанным паролем, а скажем UserPass nameUser del - удаляет указанного пользователя из /system user. (Всё это приведено для примера). Получается команда одна, а функций у неё несколько.
Возврат результатов из функции в Телеграмм тоже возможен, если дополнительно прикручен "уведомитель".

Наша версия всего этого представлена здесь: viewtopic.php?f=14&t=12659
И описана здесь https://habr.com/ru/post/650563/

Но Ваш вариант очень симпатичен и безусловно "имеет право на жизнь". Думаю, если его немного "подразвить" - будет альтернативным нашему.
P/S Надеюсь в пределах недели выйдет новая версия нашего TLGRM и библиотеки команд SATELLITE (Спутник) к нему.


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
-13-
Сообщения: 124
Зарегистрирован: 18 мар 2021, 12:45

Продолжаем...

Домой заходят два провайдера (резервирование при помощи рекурсивной маршрутизации), и все чаще по очереди безобразничают...
Чтобы оперативно видеть, что кто-то отвалился и пинать провайдера, написал пару скриптов.

Создаем задачу в scheduler, запускаю раз в 1 минуту, разрешения (read, write, policy, test)
 -Check ISP - scheduler

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

# Name: -Check ISP
# Description: check ISP status

:local checkEth [:parse [/system script get "-Check ISP" source]]
$checkEth

# End


Скрипт-функция, получаем IP или статус порта, разрешения (все выключаем, включаем "dont require permissions")
 fnCheckISP - script

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

# Name: fnCheckISP
# Description: get ISP status (function)

/ip dhcp-client {
  :set $statusISP ([get $i]->"status")
  :if ([:len $statusISP]=0) do={
    /interface ethernet monitor $i once do={
    :set $statusISP ($"status")
    }
  }
  :set $ipISP [get $i address]
  :if ([:len $ipISP]!=0) do={
    :set $ipISP [:pick [get $i address] 0 [:find [get $i address] "/"]]
  } else={
    :set $ipISP ("\"$statusISP\"")
  }
}

:return $ipISP

# End

Скрипт проверяющий порты (добавляем свои названия интерфейсов), разрешения (все выключаем, включаем "dont require permissions")
 -Check ISP - script

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

# Name: -Check ISP
# Description: check ISP status

:global fnSend
:global myChat
:global ISP1
:global ISP2

:local syName [/system identity get name]
:local cuDate ([/system clock get date] . " - " . [/system clock get time])
:local fnCheckISP [:parse [/system script get "fnCheckISP" source]]
:local text ("\"$syName\"%0A\
                  $cuDate%0A%0A")

:set $cuISP1 ([$fnCheckISP i="Сюда пишем имя интерфейса, ниже мое название, как образец"])
:set $cuISP2 ([$fnCheckISP i="ether3_ISP2"])

:if (($ISP1 != $cuISP1) or ($ISP2 != $cuISP2)) do={
  :if ($ISP1 != $cuISP1) do={
    :set ISP1 ($cuISP1)
    :set text ($text . "ISP1: $ISP1%0A")
  }
  :if ($ISP2 != $cuISP2) do={
    :set ISP2 ($cuISP2)
    :set text ($text . "ISP2: $ISP2%0A")
  }
  $fnSend chatid=$myChat text=$text
}

# End


Ответить