This commit is contained in:
s.mostryukov 2025-03-13 18:10:30 +03:00
parent 96929c25bc
commit 3ec90da1e0
7 changed files with 123 additions and 12 deletions

View File

@ -9,7 +9,7 @@ services:
command: [redis-server, --protected-mode yes, --port 6379, --requirepass, P@ssw0rd!] command: [redis-server, --protected-mode yes, --port 6379, --requirepass, P@ssw0rd!]
tg-bot: tg-bot:
image: git.sm8255082.ru/osnova/zbx-tg-bot:1.0.0 image: git.sm8255082.ru/osnova/zbx-tg-bot:1.1.0
restart: always restart: always
depends_on: depends_on:
- redis - redis

22
main.py
View File

@ -1,7 +1,6 @@
import logging as log import logging as log
from zabbix import get_active_problems from zabbix import get_active_problems
from config import conf, icon_dict from config import conf, icon_dict
from time import sleep
from redis_db import ( from redis_db import (
get_all_keys, get_all_keys,
get_value, get_value,
@ -9,10 +8,10 @@ from redis_db import (
del_value, del_value,
) )
import asyncio import asyncio
from telegram import del_message, send_message from telegram import del_message, send_message, start_bot
async def main_loop(): async def dashboard():
active_alerts = get_active_problems() active_alerts = get_active_problems()
if active_alerts is None: if active_alerts is None:
return return
@ -38,7 +37,7 @@ async def main_loop():
+ f"{active_alerts[new_alert]['host']}\n" + f"{active_alerts[new_alert]['host']}\n"
+ f"{active_alerts[new_alert]['name']}" + f"{active_alerts[new_alert]['name']}"
) )
msg_id = await send_message(message) msg_id = await send_message(message=message, event_id=new_alert)
if msg_id["status"] == 200: if msg_id["status"] == 200:
await set_value(key=new_alert, value=msg_id["msg_id"]) await set_value(key=new_alert, value=msg_id["msg_id"])
@ -53,12 +52,21 @@ async def main_loop():
await del_value(closed_alert) await del_value(closed_alert)
async def dashboard_loop():
log.info("Dashboard loop started")
while True:
await dashboard()
await asyncio.sleep(conf.zabbix.upd_interval)
async def main():
await asyncio.gather(dashboard_loop(), start_bot())
if __name__ == "__main__": if __name__ == "__main__":
log.info("Starting app") log.info("Starting app")
try: try:
while True: asyncio.run(main())
asyncio.run(main_loop())
sleep(conf.zabbix.upd_interval)
except KeyboardInterrupt: except KeyboardInterrupt:
log.info("Manual app stopped") log.info("Manual app stopped")
log.info("App stopped") log.info("App stopped")

View File

@ -2,8 +2,10 @@ from .message import (
send_message, send_message,
del_message, del_message,
) )
from .bot import start_bot
__all__ = [ __all__ = [
"send_message", "send_message",
"del_message", "del_message",
"start_bot",
] ]

52
telegram/bot.py Normal file
View File

@ -0,0 +1,52 @@
from config import conf
from aiogram import Bot, Dispatcher, types
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram import F
from zabbix import event_acknowledge, event_close
import logging as log
tg_bot = Bot(token=conf.tgbot.token)
storage = MemoryStorage()
dp = Dispatcher(storage=storage)
@dp.callback_query(F.data.startswith("h"))
async def handle_mute_1h(callback_query: types.CallbackQuery):
if event_acknowledge(int(callback_query.data[1:]), 1):
new_text = (
callback_query.message.text
+ "\n"
+ callback_query.from_user.username
+ " Замьютил на час"
)
await callback_query.message.edit_text(new_text)
@dp.callback_query(F.data.startswith("d"))
async def handle_mute_1d(callback_query: types.CallbackQuery):
if event_acknowledge(int(callback_query.data[1:]), 24):
new_text = (
callback_query.message.text
+ "\n"
+ callback_query.from_user.username
+ " Замьютил на сутки"
)
await callback_query.message.edit_text(new_text)
@dp.callback_query(F.data.startswith("c"))
async def handle_close(callback_query: types.CallbackQuery):
if event_close(int(callback_query.data[1:])):
new_text = (
callback_query.message.text
+ "\n"
+ callback_query.from_user.username
+ " Закрыл"
)
await callback_query.message.edit_text(new_text)
async def start_bot():
log.info("Telegram bot loop started")
await dp.start_polling(tg_bot)

View File

@ -2,16 +2,25 @@ import logging as log
import aiohttp import aiohttp
from config import conf from config import conf
import json
async def send_message( async def send_message(message: str, event_id: int) -> dict:
message: str,
) -> dict:
url = f"https://api.telegram.org/bot{conf.tgbot.token}/sendMessage" url = f"https://api.telegram.org/bot{conf.tgbot.token}/sendMessage"
inline_buttons = [
[
{"text": "🛠 на 1 час", "callback_data": f"h{event_id}"},
{"text": "🛠 на 1 день", "callback_data": f"d{event_id}"},
{"text": "✅ Закрыть", "callback_data": f"c{event_id}"},
],
]
reply_markup = {"inline_keyboard": inline_buttons}
params = { params = {
"chat_id": conf.tgbot.chat_id, "chat_id": conf.tgbot.chat_id,
"message_thread_id": conf.tgbot.tread_id, "message_thread_id": conf.tgbot.tread_id,
"text": message, "text": message,
"reply_markup": json.dumps(reply_markup),
} }
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:

View File

@ -1,6 +1,8 @@
from .zabbix_api import get_active_problems from .zabbix_api import get_active_problems, event_acknowledge, event_close
__all__ = [ __all__ = [
"get_active_problems", "get_active_problems",
"event_acknowledge",
"event_close",
] ]

View File

@ -4,6 +4,8 @@ from zabbix_utils import ZabbixAPI
from config import conf from config import conf
from datetime import datetime, timedelta
def get_active_problems() -> dict: def get_active_problems() -> dict:
api = ZabbixAPI(url=conf.zabbix.url, token=conf.zabbix.token) api = ZabbixAPI(url=conf.zabbix.url, token=conf.zabbix.token)
@ -40,3 +42,39 @@ def get_active_problems() -> dict:
return events_dict return events_dict
except: except:
log.warning("Get event from zabbix error") log.warning("Get event from zabbix error")
def event_acknowledge(event_id: int, mute_time: int):
api = ZabbixAPI(url=conf.zabbix.url, token=conf.zabbix.token)
if mute_time == 0:
mute_to = 0
else:
mute_to = int((datetime.now() + timedelta(hours=mute_time)).timestamp())
try:
response = api.event.acknowledge(
eventids=event_id,
action=34,
suppress_until=mute_to,
)
if response:
log.info(f"Event {event_id} acknowledged")
return True
except:
log.warning(f"Acknowledge event {event_id} from zabbix error")
return False
def event_close(event_id: int):
api = ZabbixAPI(url=conf.zabbix.url, token=conf.zabbix.token)
try:
response = api.event.acknowledge(
eventids=event_id,
action=1,
)
print(response)
if response:
log.info(f"Event {event_id} closed")
return True
except:
log.warning(f"Closed event {event_id} from zabbix error")
return False