В дуде событие
:global dName "[Device.Name]";
:global pName "[Probe.Name]";
:global sStatus "[Service.Status]";
:global nMap "[Device.NetMaps]";
/system script run send_dude_alert;
Скрипт на сервере Dude
{
:global dName; :global pName; :global sStatus; :global nMap;
:local encode do={
:local raw [:tostr $1]; :local res "";
:for i from=0 to=([:len $raw] - 1) do={
:local c [:pick $raw $i ($i + 1)];
:if ($c = " ") do={:set c "%20"} else={
:if ($c = ".") do={:set c "%2E"} else={
:if ($c = ",") do={:set c "%2C"} else={
:if ($c = "(") do={:set c "%28"} else={
:if ($c = ")") do={:set c "%29"} else={
:if ($c = "'") do={:set c "%27"} else={
:if ($c = "\"") do={:set c "%22"} else={
:if ($c = "/") do={:set c "%2F"} else={
:if ($c = "№") do={:set c "%E2%84%96"}
}}}}}}}}
:set res ($res . $c);
}
:return $res;
}
:local dC [$encode $dName];
:local pC [$encode $pName];
:local sC [$encode $sStatus];
:local mC [$encode $nMap];
:local msg ("Service%20" . $pC . "%20on%20" . $dC . "%20(" . $mC . ")%20is%20now%20" . $sC);
# Собираем URL по частям, чтобы Платформа и MikroTik его не обрезали
:local url "http://ip сервера xmpp:8080/";
:set url ($url . "?token=токен");
:set url ($url . "&to=ГРУППА");
:set url ($url . "&msg=" . $msg);
:log info "DUDE_SENDING: $url";
/tool fetch url="$url" keep-result=no;
}
Python bot на сервере xmpp
import asyncio
import urllib.parse
from http.server import BaseHTTPRequestHandler, HTTPServer
from slixmpp import ClientXMPP
# --- НАСТРОЙКИ ---
BOT_JID = "jid бота"
BOT_PASS = "пароль аккаунта бота"
TOKEN = "токен"
async def send_msg(to, text):
xmpp = ClientXMPP(BOT_JID, BOT_PASS)
# Определяем, группа это или личка
# В Snikket группы обычно содержат 'groups' или 'muc'
is_group = "groups" in to or "muc" in to
mtype = 'groupchat' if is_group else 'chat'
if is_group:
xmpp.register_plugin('xep_0045') # Плагин для работы с группами
async def start(event):
xmpp.send_presence()
if is_group:
# Заходим в группу под ником "bot"
xmpp.plugin['xep_0045'].join_muc(to, "bot")
# Ждем 2 секунды, чтобы сервер Snikket нас "принял"
await asyncio.sleep(2)
xmpp.send_message(mto=to, mbody=text, mtype=mtype)
# Небольшая пауза, чтобы пакет успел уйти в сеть
await asyncio.sleep(1)
xmpp.disconnect()
xmpp.add_event_handler("session_start", start)
# Подключаемся к локальному серверу Snikket
if xmpp.connect(('127.0.0.1', 5222)):
await xmpp.disconnected
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
# MikroTik шлет путь в сырых байтах. Декодируем его принудительно в utf-8.
# Это лечит "кракозябры" и ошибки 403/400.
try:
raw_path = self.path.encode('iso-8859-1').decode('utf-8')
except:
raw_path = self.path
url_parts = urllib.parse.urlparse(raw_path)
params = urllib.parse.parse_qs(url_parts.query)
# 1. Проверка токена
incoming_token = params.get('token', [''])[0]
if incoming_token != TOKEN:
print(f"Forbidden: wrong token {incoming_token}")
self.send_response(403)
self.end_headers()
self.wfile.write(b"Forbidden")
return
# 2. Получение данных
to = params.get('to', [''])[0]
msg = params.get('msg', [''])[0]
if to and msg:
try:
# В Python 3.7+ лучше использовать существующий цикл или новый поток
# для запуска асинхронной функции из синхронного хендлера
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(send_msg(to, msg))
loop.close()
self.send_response(200)
self.end_headers()
self.wfile.write(b"OK")
except Exception as e:
print(f"Error sending message: {e}")
self.send_response(500)
self.end_headers()
self.wfile.write(str(e).encode())
else:
self.send_response(400)
self.end_headers()
self.wfile.write(b"Missing params")
if __name__ == "__main__":
print("Шлюз запущен на порту 8080...")
HTTPServer(('0.0.0.0', 8080), Handler).serve_forever()
Сервер сникет свой