This commit is contained in:
s.mostryukov 2025-03-11 18:29:32 +03:00
parent db52020fa3
commit fc1e34e727
10 changed files with 192 additions and 5 deletions

View File

@ -4,6 +4,7 @@ CFG__LOG__LEVEL_TO_FILE=30
CFG__ZABBIX__URL=https://example.com CFG__ZABBIX__URL=https://example.com
CFG__ZABBIX__TOKEN=string CFG__ZABBIX__TOKEN=string
CFG__ZABBIX__MIN_SEVERITY=0 CFG__ZABBIX__MIN_SEVERITY=0
CFG__ZABBIX__UPD_INTERVAL=60
CFG__TGBOT__TOKEN=string CFG__TGBOT__TOKEN=string
CFG__TGBOT__CHAT_ID=00000000 CFG__TGBOT__CHAT_ID=00000000

View File

@ -34,10 +34,13 @@ class TelegramBotConfig(BaseModel):
chat_id: int chat_id: int
tread_id: int tread_id: int
class ZabbixConfig(BaseModel): class ZabbixConfig(BaseModel):
url: str url: str
token: str token: str
min_severity: int min_severity: int
upd_interval: int
class Settings(BaseSettings): class Settings(BaseSettings):
model_config = SettingsConfigDict( model_config = SettingsConfigDict(
@ -55,7 +58,6 @@ class Settings(BaseSettings):
zabbix: ZabbixConfig zabbix: ZabbixConfig
conf = Settings() conf = Settings()

19
main.py
View File

@ -1,11 +1,22 @@
import logging as log import logging as log
from zabbix import get_active_problems
from config import conf from config import conf
from time import sleep
def main():
print("Hello from zbx-tg-bot!") def main_loop():
active_alerts = get_active_problems()
for i in active_alerts:
print(i)
print(len(active_alerts))
if __name__ == "__main__": if __name__ == "__main__":
log.info("Starting app") log.info("Starting app")
main() try:
log.info("App stopped") while True:
main_loop()
sleep(conf.zabbix.upd_interval)
except KeyboardInterrupt:
log.info("Manual app stopped")
log.info("App stopped")

13
redis_db/__init__.py Normal file
View File

@ -0,0 +1,13 @@
from .crud import (
get_value,
set_value,
ping,
pop_value,
)
__all__ = [
"get_value",
"set_value",
"ping",
"pop_value",
]

33
redis_db/crud.py Normal file
View File

@ -0,0 +1,33 @@
import logging as log
from .r_helper import RedisManager
async def ping():
async with RedisManager() as redis_connect:
if redis_connect:
result = await redis_connect.client.ping()
log.info("Ping - %s", result)
return result
async def set_value(key, value):
async with RedisManager() as redis_connect:
if redis_connect:
await redis_connect.client.set(key, value)
log.info("Set %s = %s", key, value)
async def get_value(key):
async with RedisManager() as redis_connect:
if redis_connect:
value = await redis_connect.client.get(key)
log.info("Get %s = %s", key, value)
return value
async def pop_value(key):
async with RedisManager() as redis_connect:
if redis_connect:
value = await redis_connect.client.getdel(key)
log.info("Get and delete %s = %s", key, value)
return value

30
redis_db/r_helper.py Normal file
View File

@ -0,0 +1,30 @@
from redis.asyncio import Redis
from redis import ConnectionError
from config import conf
import logging as log
class RedisManager:
def __init__(self):
self.client = None
self.connect_params = {
"host": conf.redis.host,
"port": conf.redis.port,
}
if conf.redis.pwd:
self.connect_params["password"] = conf.redis.pwd
async def __aenter__(self):
self.client = Redis(**self.connect_params)
try:
await self.client.ping()
log.info("connected to Redis")
return self
except ConnectionError:
log.warning("failed to connect to Redis")
self.client = None
async def __aexit__(self, exc_type, exc_val, exc_tb):
if self.client:
await self.client.close()
log.info("closed connection to Redis")

52
telegram/message.py Normal file
View File

@ -0,0 +1,52 @@
import logging as log
import aiohttp
from config import conf
async def send_message(
message: str,
) -> dict | None:
url = f"https://api.telegram.org/bot{conf.tgbot.token}/sendMessage"
params = {
"chat_id": conf.tgbot.chat_id,
"message_thread_id": conf.tgbot.tread_id,
"text": message,
}
async with aiohttp.ClientSession() as session:
async with session.post(
url,
json=params,
) as response:
log.info(f"Response status: {response.status}")
resp = await response.json()
if response.status == 200:
log.info(f"Message with ID: {resp['result']['message_id']} send")
return {
"status": response.status,
"msg_id": resp["result"]["message_id"],
}
log.warning(f"Message not send. Response status: {response.status}")
async def del_message(
message_id: int,
) -> dict | None:
url = f"https://api.telegram.org/bot{conf.tgbot.token}/deleteMessage"
async with aiohttp.ClientSession() as session:
async with session.post(
url,
json={
"chat_id": conf.tgbot.chat_id,
"message_id": message_id,
},
) as response:
if response.status == 200:
log.info(f"Message ID {message_id} deleted")
return {
"status": response.status,
}
else:
log.warning(f"Response status: {response.status}")

6
zabbix/__init__.py Normal file
View File

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

39
zabbix/zabbix_api.py Normal file
View File

@ -0,0 +1,39 @@
import logging as log
from zabbix_utils import ZabbixAPI
from config import conf
def get_active_problems():
api = ZabbixAPI(url=conf.zabbix.url, token=conf.zabbix.token)
try:
problems = api.problem.get(
output=[
"eventid",
"suppressed",
"severity",
],
)
event_ids = []
for problem in problems:
if (
problem["suppressed"] == "0"
and int(problem["severity"]) >= conf.zabbix.min_severity
):
event_ids.append(problem["eventid"])
events = api.event.get(
selectHosts=["host"],
eventids=event_ids,
output=[
"eventid",
"name",
"severity",
],
)
for event in events:
event["host"] = event.pop("hosts", None)[0]["host"]
return events
except:
log.warning("Get event from zabbix error")