Add
This commit is contained in:
674
alertsscript/zbxTelegram.py
Normal file
674
alertsscript/zbxTelegram.py
Normal file
@@ -0,0 +1,674 @@
|
||||
#!/usr/lib/zabbix/alertscripts/venv/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
########################
|
||||
# Sokolov Dmitry #
|
||||
# xx.sokolov@gmail.com #
|
||||
# https://t.me/ZbxNTg #
|
||||
########################
|
||||
# https://github.com/xxsokolov/Zabbix-Notification-Telegram
|
||||
__author__ = "Sokolov Dmitry"
|
||||
__maintainer__ = "Sokolov Dmitry"
|
||||
__license__ = "MIT"
|
||||
import telebot
|
||||
from telebot import apihelper
|
||||
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton, InputMediaPhoto
|
||||
from zbxTelegram_files.classes.argparser import ArgParsing
|
||||
import xmltodict
|
||||
from zbxTelegram_config import *
|
||||
import requests
|
||||
import urllib3
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
import io
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import json
|
||||
from errno import ENOENT
|
||||
import logging
|
||||
import html
|
||||
|
||||
|
||||
class System:
|
||||
def __init__(self, debug=False):
|
||||
# configuring log
|
||||
if debug:
|
||||
self.log_level = logging.DEBUG
|
||||
else:
|
||||
self.log_level = logging.INFO
|
||||
|
||||
log_format = logging.Formatter(
|
||||
'[%(asctime)s] - PID:%(process)s - %(funcName)s() - %(filename)s:%(lineno)d - %(levelname)s: %(message)s')
|
||||
self.log = logging.getLogger()
|
||||
self.log.setLevel(self.log_level)
|
||||
|
||||
# writing to stdout
|
||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||
# stdout_handler = logging.StreamHandler(codecs.getwriter("utf-8")(sys.stdout.detach()))
|
||||
stdout_handler.setLevel(self.log_level)
|
||||
stdout_handler.setFormatter(log_format)
|
||||
# writing to file
|
||||
file_handler = logging.FileHandler(filename=config_log_file, mode='a')
|
||||
file_handler.setLevel(self.log_level)
|
||||
file_handler.setFormatter(log_format)
|
||||
|
||||
self.log.addHandler(stdout_handler)
|
||||
self.log.addHandler(file_handler)
|
||||
|
||||
|
||||
class FailSafeDict(dict):
|
||||
def __missing__(self, key):
|
||||
return '{{key not found: {}}}'.format(key)
|
||||
|
||||
|
||||
args = ArgParsing().create_parser().parse_args(sys.argv[1:])
|
||||
loggings = System(config_debug_mode if not args.debug else True).log
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
bot = telebot.TeleBot(args.token if args.token else tg_token)
|
||||
if tg_proxy:
|
||||
apihelper.proxy = tg_proxy_server
|
||||
|
||||
|
||||
def xml_parsing(data):
|
||||
try:
|
||||
data = dict(xmltodict.parse(data, process_namespaces=True)['root'])
|
||||
|
||||
message = data['body']['messages']
|
||||
|
||||
settings_graphs_bool = data['settings']['graphs']
|
||||
settings_graphlinks_bool = data['settings']['graphlinks']
|
||||
settings_triggerlinks_bool = data['settings']['triggerlinks']
|
||||
settings_hostlinks_bool = data['settings']['hostlinks']
|
||||
settings_acklinks_bool = data['settings']['acklinks']
|
||||
settings_eventlinks_bool = data['settings']['eventlinks']
|
||||
|
||||
settings_eventtag_bool = data['settings']['eventtag']
|
||||
settings_eventidtag_bool = data['settings']['eventidtag']
|
||||
settings_itemidtag_bool = data['settings']['itemidtag']
|
||||
settings_triggeridtag_bool = data['settings']['triggeridtag']
|
||||
settings_actionidtag_bool = data['settings']['actionidtag']
|
||||
settings_hostidtag_bool = data['settings']['hostidtag']
|
||||
settings_zntsettingstag_bool = data['settings']['zntsettingstag']
|
||||
|
||||
settings_mentions_bool = data['settings']['zntmentions']
|
||||
|
||||
settings_keyboard = data['settings']['keyboard']
|
||||
|
||||
settings_graphs_period = data['settings']['graphs_period']
|
||||
settings_host = data['settings']['host']
|
||||
settings_itemid = data['settings']['itemid']
|
||||
settings_triggerid = data['settings']['triggerid']
|
||||
settings_eventid = data['settings']['eventid']
|
||||
settings_actionid = data['settings']['actionid']
|
||||
settings_hostid = data['settings']['hostid']
|
||||
settings_title = data['settings']['title']
|
||||
settings_trigger_url = data['settings']['triggerurl']
|
||||
|
||||
settings_eventtags = data['settings']['eventtags']
|
||||
|
||||
return dict(title=settings_title, message=message, eventtags=settings_eventtags,
|
||||
settings_graphs_bool=eval(settings_graphs_bool.capitalize()),
|
||||
settings_graphlinks_bool=eval(settings_graphlinks_bool.capitalize()),
|
||||
settings_triggerlinks_bool=eval(settings_triggerlinks_bool.capitalize()),
|
||||
settings_hostlinks_bool=eval(settings_hostlinks_bool.capitalize()),
|
||||
settings_acklinks_bool=eval(settings_acklinks_bool.capitalize()),
|
||||
settings_eventlinks_bool=eval(settings_eventlinks_bool.capitalize()),
|
||||
settings_eventtag_bool=eval(settings_eventtag_bool.capitalize()),
|
||||
settings_eventidtag_bool=eval(settings_eventidtag_bool.capitalize()),
|
||||
settings_itemidtag_bool=eval(settings_itemidtag_bool.capitalize()),
|
||||
settings_triggeridtag_bool=eval(settings_triggeridtag_bool.capitalize()),
|
||||
settings_actionidtag_bool=eval(settings_actionidtag_bool.capitalize()),
|
||||
settings_hostidtag_bool=eval(settings_hostidtag_bool.capitalize()),
|
||||
settings_zntsettingstag_bool=eval(settings_zntsettingstag_bool.capitalize()),
|
||||
settings_zntmentions_bool=eval(settings_mentions_bool.capitalize()),
|
||||
settings_keyboard_bool=eval(settings_keyboard.capitalize()),
|
||||
graphs_period=settings_graphs_period, host=settings_host, itemid=settings_itemid,
|
||||
triggerid=settings_triggerid, triggerurl=settings_trigger_url, eventid=settings_eventid,
|
||||
actionid=settings_actionid, hostid=settings_hostid)
|
||||
|
||||
except Exception as err:
|
||||
loggings.error("Exception occurred: No XML in zabbix actions or it's not valid (xml parsing error). XML: {} ".format(
|
||||
err), exc_info=config_exc_info), exit(1)
|
||||
|
||||
|
||||
def watermark_text(img):
|
||||
img = io.BytesIO(img)
|
||||
img = Image.open(img)
|
||||
if img.height < watermark_minimal_height:
|
||||
loggings.info("Cannot set watermark text, img height {} (min. {})".format(img.height, watermark_minimal_height))
|
||||
return False
|
||||
font = ImageFont.truetype(watermark_font, 14)
|
||||
|
||||
line_height = sum(font.getmetrics())
|
||||
|
||||
fontimage = Image.new('L', (font.getsize(watermark_label)[0], line_height))
|
||||
ImageDraw.Draw(fontimage).text((0, 0), watermark_label, fill=watermark_fill, font=font)
|
||||
fontimage = fontimage.rotate(watermark_rotate, resample=Image.BICUBIC, expand=True)
|
||||
|
||||
img_size = img.crop().size
|
||||
size = (img_size[0]-fontimage.size[0]-5, img_size[1]-fontimage.size[1]-10)
|
||||
|
||||
img.paste(watermark_text_color, box=size, mask=fontimage)
|
||||
|
||||
img_byte_arr = io.BytesIO()
|
||||
img.save(img_byte_arr, format=img.format)
|
||||
img_byte_arr = img_byte_arr.getvalue()
|
||||
|
||||
return img_byte_arr
|
||||
|
||||
|
||||
def get_cookie():
|
||||
data_api = {"name": zabbix_api_login,"password": zabbix_api_pass,"enter": "Sign in"}
|
||||
req_cookie = requests.post(zabbix_api_url, data=data_api, verify=False)
|
||||
cookie = req_cookie.cookies
|
||||
req_cookie.close()
|
||||
if not any(_ in cookie for _ in ['zbx_session', 'zbx_sessionid']):
|
||||
loggings.error(
|
||||
'User authorization failed: {} ({})'.format('Login name or password is incorrect.', zabbix_api_url))
|
||||
return False
|
||||
return cookie
|
||||
|
||||
|
||||
def get_chart_png(itemid, graff_name, period=None):
|
||||
try:
|
||||
cookies = get_cookie()
|
||||
if cookies:
|
||||
response = requests.get(zabbix_graph_chart.format(
|
||||
name=graff_name,
|
||||
itemid=itemid,
|
||||
zabbix_server=zabbix_api_url,
|
||||
range_time=period),
|
||||
cookies=cookies,
|
||||
verify=False)
|
||||
|
||||
if watermark:
|
||||
wmt = watermark_text(response.content)
|
||||
if wmt:
|
||||
return dict(img=wmt, url=response.url)
|
||||
else:
|
||||
return dict(img=response.content, url=response.url)
|
||||
else:
|
||||
return dict(img=response.content, url=response.url)
|
||||
else:
|
||||
return dict(img=None, url=None)
|
||||
except Exception as err:
|
||||
loggings.error("Exception occurred: {}".format(err), exc_info=config_exc_info), exit(1)
|
||||
|
||||
|
||||
def create_tags_list(_bool=False, tag=None, _type=None, zntsettingstag=False):
|
||||
tags_list = []
|
||||
settings_list = []
|
||||
try:
|
||||
if _bool:
|
||||
if tag and (re.search(r'\w', tag)):
|
||||
for tags in tag.split(', '):
|
||||
if tags:
|
||||
if not zntsettingstag:
|
||||
if tags.find(':') != -1:
|
||||
tag, value = re.split(r':+',tags, maxsplit=1)
|
||||
if tag != trigger_settings_tag and tag != trigger_info_mentions_tag:
|
||||
tags_list.append('#{tag}_{value}'.format(
|
||||
tag=_type + re.sub(r"\W+", "_", tag) if _type else re.sub(r"\W+", "_", tag),
|
||||
value=re.sub(r"\W+", "_", value)))
|
||||
else:
|
||||
continue
|
||||
else:
|
||||
if len(tags.split()) > 0:
|
||||
for tg_s in tags.split():
|
||||
tags_list.append('#{tag}'.format(
|
||||
tag=_type + re.sub(r"\W+", "_", tg_s) if _type else re.sub(r"\W+", "_", tg_s)))
|
||||
else:
|
||||
tags_list.append('#{tag}'.format(
|
||||
tag=_type + re.sub(r"\W+", "_", tags) if _type else re.sub(r"\W+", "_", tags)))
|
||||
else:
|
||||
if tags.find(':') != -1:
|
||||
tag, value = re.split(r':+',tags, maxsplit=1)
|
||||
if tag == trigger_settings_tag:
|
||||
tags_list.append('#{tag}_{value}'.format(
|
||||
tag=_type + re.sub(r"\W+", "_", tag) if _type else re.sub(r"\W+", "_", tag),
|
||||
value=re.sub(r"\W+", "_", value)))
|
||||
settings_list.append(value)
|
||||
else:
|
||||
continue
|
||||
else:
|
||||
continue
|
||||
else:
|
||||
tags_list.append(body_messages_tags_no)
|
||||
else:
|
||||
tags_list.append(body_messages_tags_no)
|
||||
else:
|
||||
return False
|
||||
|
||||
except ValueError:
|
||||
tags_list.append(body_messages_tags_no)
|
||||
else:
|
||||
return body_messages_tags_delimiter.join(tags_list) if not zntsettingstag else {
|
||||
'tags': body_messages_tags_delimiter.join(tags_list),
|
||||
trigger_settings_tag: settings_list}
|
||||
|
||||
|
||||
def create_mentions_list(_bool=False, mentions=None):
|
||||
mentions_list = []
|
||||
try:
|
||||
if _bool and mentions:
|
||||
for tags in mentions.split(', '):
|
||||
if tags.find(':') != -1:
|
||||
tag, value = re.split(r':+',tags, maxsplit=1)
|
||||
if tag == trigger_info_mentions_tag:
|
||||
for username in value.split():
|
||||
mentions_list.append(username)
|
||||
return mentions_list
|
||||
else:
|
||||
return False
|
||||
except Exception as err:
|
||||
loggings.error("Exception occurred: {}".format(err), exc_info=config_exc_info), exit(1)
|
||||
|
||||
|
||||
def create_links_list(_bool=None, url=None, _type=None, url_list=None):
|
||||
try:
|
||||
if _bool:
|
||||
if url and (re.search(r'\w', url)):
|
||||
return body_messages_url_template.format(url=url, icon=_type)
|
||||
else:
|
||||
return body_messages_url_emoji_no_url
|
||||
elif url_list:
|
||||
return url_list
|
||||
else:
|
||||
return False
|
||||
except ValueError:
|
||||
return body_messages_url_emoji_no_url
|
||||
|
||||
|
||||
def get_cache(title):
|
||||
read_cache = None
|
||||
try:
|
||||
if not os.path.exists(config_cache_file):
|
||||
raise IOError(ENOENT, 'No such file or directory', config_cache_file)
|
||||
except Exception as err:
|
||||
loggings.error("Exception occurred: {}".format(err), exc_info=config_exc_info)
|
||||
open(config_cache_file, 'a').close()
|
||||
loggings.info("Cache file created in {}".format(config_cache_file))
|
||||
else:
|
||||
read_cache = open(config_cache_file, 'r').read()
|
||||
|
||||
if read_cache:
|
||||
cache = json.loads(read_cache)
|
||||
|
||||
for name, value in cache.items():
|
||||
if title == name:
|
||||
return value['id']
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def set_cache(title, send_id, sent_type, cache=None, update=None):
|
||||
f = open(config_cache_file, 'r+')
|
||||
r = f.read()
|
||||
if r:
|
||||
cache = json.loads(r)
|
||||
if not cache:
|
||||
cache = {title: dict(type=str(sent_type), id=str(send_id))}
|
||||
else:
|
||||
if not update:
|
||||
cache[title] = dict(type=str(sent_type), id=str(send_id))
|
||||
else:
|
||||
cache[title] = dict(type=str(sent_type), id=str(send_id), old=str(update))
|
||||
f.seek(0)
|
||||
f.write(json.dumps(cache,sort_keys=True, ensure_ascii=False, indent=4))
|
||||
f.close()
|
||||
if update:
|
||||
loggings.info("Updated id for {} ({}): old '{}' -> new '{}' in cache file".format(
|
||||
title, sent_type, update, send_id))
|
||||
else:
|
||||
loggings.info("Add new id {} for {} ({}) in cache file".format(send_id, title, sent_type))
|
||||
return True
|
||||
|
||||
|
||||
def migrate_group_id(sent_to, sent_id, err):
|
||||
for key, value in json.loads(err.result.text).items():
|
||||
if key == 'parameters' and value['migrate_to_chat_id']:
|
||||
loggings.warning("Group chat was upgraded to a supergroup chat ({})".format(value['migrate_to_chat_id']),
|
||||
exc_info=config_exc_info)
|
||||
set_cache(sent_to, value['migrate_to_chat_id'], 'supergroup', update=sent_id)
|
||||
|
||||
|
||||
def get_send_id(send_to):
|
||||
try:
|
||||
chat = None
|
||||
if re.search('^[0-9]+$', send_to) or re.search('^-[0-9]+$', send_to):
|
||||
return send_to
|
||||
elif re.search('^@+[a-zA-Z0-9_]{5,}$', send_to):
|
||||
send_to = send_to.replace("@", "")
|
||||
elif not send_to:
|
||||
raise ValueError('Username or groupname is not specified. You can use for username '
|
||||
'@[a-z,A-Z,0-9 and underscores] and for groupname any characters. ')
|
||||
|
||||
send_id = get_cache(send_to)
|
||||
|
||||
if send_id:
|
||||
return send_id
|
||||
|
||||
loggings.info("Telegram API: method getUpdate: started")
|
||||
get_updates_list = bot.get_updates(timeout=10)
|
||||
sum_del_update_id = 0
|
||||
while len([value.update_id for value in get_updates_list]) >= 100:
|
||||
sum_del_update_id += len([value.update_id for value in get_updates_list])
|
||||
get_updates_list = bot.get_updates(timeout=10, offset=max([value.update_id for value in get_updates_list]))
|
||||
|
||||
if sum_del_update_id > 0:
|
||||
loggings.info("In getUpdate list was cleared {} messages. Submitted for processing {}.".format(
|
||||
sum_del_update_id, len([value.update_id for value in get_updates_list])))
|
||||
|
||||
for line in get_updates_list:
|
||||
if line.message:
|
||||
chat = line.message.chat
|
||||
elif line.edited_message:
|
||||
chat = line.edited_message.chat
|
||||
elif line.channel_post:
|
||||
chat = line.channel_post.chat
|
||||
|
||||
if chat.type in ["group", "supergroup"] and chat.title and chat.title == send_to:
|
||||
if not send_id:
|
||||
set_cache(send_to, chat.id, chat.type)
|
||||
bot.get_updates(timeout=10, offset=-1)
|
||||
return chat.id
|
||||
|
||||
if chat.type in ["channel"] and chat.title and chat.title == send_to:
|
||||
if not send_id:
|
||||
set_cache(send_to, chat.id, chat.type)
|
||||
bot.get_updates(timeout=10, offset=-1)
|
||||
return chat.id
|
||||
|
||||
if chat.type in ["private"] and chat.username == send_to.replace("@", ""):
|
||||
if not send_id:
|
||||
set_cache(send_to, chat.id, chat.type)
|
||||
bot.get_updates(timeout=10, offset=-1)
|
||||
return chat.id
|
||||
|
||||
raise ValueError('Username or groupname not found in the cache file. No access occurred or bot is not added to '
|
||||
'group "{sendto}" (Add bot group and/or send message to {bot})'.format(
|
||||
bot=bot.get_me().username,
|
||||
sendto=send_to))
|
||||
except Exception as err:
|
||||
loggings.error("Exception occurred: {}".format(err), exc_info=config_exc_info), exit(1)
|
||||
|
||||
|
||||
def gen_markup(eventid):
|
||||
markup = InlineKeyboardMarkup()
|
||||
markup.row_width = zabbix_keyboard_row_width
|
||||
markup.add(
|
||||
InlineKeyboardButton(zabbix_keyboard_button_message,
|
||||
callback_data='{}'.format(json.dumps(dict(action="messages", eventid=eventid)))),
|
||||
InlineKeyboardButton(zabbix_keyboard_button_acknowledge,
|
||||
callback_data='{}'.format(json.dumps(dict(action="acknowledge", eventid=eventid)))),
|
||||
InlineKeyboardButton(zabbix_keyboard_button_history,
|
||||
callback_data='{}'.format(json.dumps(dict(action="history", eventid=eventid)))),
|
||||
InlineKeyboardButton(zabbix_keyboard_button_history,
|
||||
callback_data='{}'.format(json.dumps(dict(action="last value", eventid=eventid)))),
|
||||
InlineKeyboardButton(zabbix_keyboard_button_history,
|
||||
callback_data='{}'.format(json.dumps(dict(action="graphs", eventid=eventid)))))
|
||||
return markup
|
||||
|
||||
|
||||
def send_messages(sent_to, message, graphs_png, eventid=None, settings_keyboard=None, disable_notification=False):
|
||||
try:
|
||||
sent_id = get_send_id(sent_to)
|
||||
if message and sent_to:
|
||||
if graphs_png and isinstance(graphs_png, list):
|
||||
try:
|
||||
graphs_png[0].caption = message
|
||||
graphs_png[0].parse_mode = "HTML"
|
||||
bot.send_media_group(chat_id=sent_id, message_thread_id=tg_message_thread_id, media=graphs_png, disable_notification=disable_notification)
|
||||
except apihelper.ApiException as err:
|
||||
if 'migrate_to_chat_id' in err.result.text:
|
||||
migrate_group_id(sent_to, sent_id, err)
|
||||
send_messages(sent_to, message, graphs_png, settings_keyboard)
|
||||
else:
|
||||
loggings.error("Exception occurred in Api Telegram: {}".format(err), exc_info=config_exc_info),
|
||||
exit(1)
|
||||
except Exception as err:
|
||||
loggings.error("Exception occurred: {}".format(err), exc_info=config_exc_info),exit(1)
|
||||
else:
|
||||
loggings.info('Bot @{busername}({bid}) send media group to "{sent_to}" ({sent_id}).'.format(
|
||||
sent_to=sent_to, sent_id=sent_id, busername=bot.get_me().username, bid=bot.get_me().id))
|
||||
exit(0)
|
||||
elif graphs_png and graphs_png.get('img'):
|
||||
try:
|
||||
bot.send_photo(chat_id=sent_id, message_thread_id=tg_message_thread_id, photo=graphs_png.get('img'), caption=message, parse_mode="HTML",
|
||||
reply_markup=gen_markup(eventid) if zabbix_keyboard and settings_keyboard else None,
|
||||
disable_notification=disable_notification)
|
||||
except apihelper.ApiException as err:
|
||||
if 'migrate_to_chat_id' in err.result.text:
|
||||
migrate_group_id(sent_to, sent_id, err)
|
||||
send_messages(sent_to, message, graphs_png, settings_keyboard, disable_notification)
|
||||
elif 'IMAGE_PROCESS_FAILED' in err.result.text:
|
||||
bot.send_photo(chat_id=sent_id, message_thread_id=tg_message_thread_id, photo=open(
|
||||
file='{0}/zbxTelegram_files/error_send_photo.png'.format(
|
||||
os.path.dirname(os.path.realpath(__file__))),
|
||||
mode='rb').read(), caption=message, parse_mode="HTML",
|
||||
reply_markup=gen_markup(
|
||||
eventid) if zabbix_keyboard and settings_keyboard else None,
|
||||
disable_notification=disable_notification)
|
||||
else:
|
||||
loggings.error("Exception occurred in Api Telegram: {}".format(err), exc_info=config_exc_info),
|
||||
exit(1)
|
||||
except Exception as err:
|
||||
loggings.error("Exception occurred: {}".format(err), exc_info=config_exc_info),exit(1)
|
||||
else:
|
||||
loggings.info('Bot @{busername}({bid}) send photo to "{sent_to}" ({sent_id}).'.format(
|
||||
sent_to=sent_to, sent_id=sent_id, busername=bot.get_me().username, bid=bot.get_me().id))
|
||||
else:
|
||||
try:
|
||||
bot.send_message(chat_id=sent_id, message_thread_id=tg_message_thread_id, text=message, parse_mode="HTML", disable_web_page_preview=True,
|
||||
reply_markup=gen_markup(eventid) if zabbix_keyboard and settings_keyboard
|
||||
else None,
|
||||
disable_notification=disable_notification)
|
||||
except apihelper.ApiException as err:
|
||||
if 'migrate_to_chat_id' in json.loads(err.result.text).get('parameters'):
|
||||
migrate_group_id(sent_to, sent_id, err)
|
||||
send_messages(sent_to, message, graphs_png, settings_keyboard, disable_notification)
|
||||
else:
|
||||
loggings.error("Exception occurred in Api Telegram: {}".format(err), exc_info=config_exc_info)
|
||||
exit(1)
|
||||
except Exception as err:
|
||||
loggings.error("Exception occurred: {}".format(err), exc_info=config_exc_info), exit(1)
|
||||
else:
|
||||
loggings.info('Bot @{busername}({bid}) send message to "{sent_to}" ({sent_id}).'.format(
|
||||
sent_to=sent_to, sent_id=sent_id, busername=bot.get_me().username, bid=bot.get_me().id))
|
||||
exit(0)
|
||||
except Exception as err:
|
||||
loggings.error("Exception occurred: {}".format(err), exc_info=config_exc_info), exit(1)
|
||||
|
||||
|
||||
def set_period_day_hour(seconds):
|
||||
seconds = int(seconds)
|
||||
days, seconds = divmod(seconds, 86400)
|
||||
hours, seconds = divmod(seconds, 3600)
|
||||
minutes, seconds = divmod(seconds, 60)
|
||||
if days > 0:
|
||||
return '{}d {}h'.format(days, hours) if hours > 0 else '{}d'.format(days)
|
||||
elif hours > 0:
|
||||
return '{}h {}m'.format(hours, minutes) if minutes > 0 else '{}h'.format(hours)
|
||||
elif minutes > 0:
|
||||
return '{}m'.format(minutes)
|
||||
|
||||
|
||||
def main():
|
||||
graph_period = None
|
||||
graph_period_raw = None
|
||||
loggings.info("Send to {} action: {}".format(args.username, args.subject))
|
||||
loggings.debug("sys.argv: {}".format(sys.argv[1:]))
|
||||
loggings.debug("Send to {}\naction: {}\nxml: {}".format(args.username, args.subject, args.messages))
|
||||
|
||||
if args.subject in ['Test subject', 'test', 'Тестовая тема'] or args.messages in \
|
||||
['This is the test message from Zabbix', 'test', 'Это тестовое сообщение от Zabbix']:
|
||||
if get_cookie():
|
||||
loggings.info('Connection check passed ({})'.format(zabbix_api_url))
|
||||
test_graph_file = '{0}/zbxTelegram_files/test.png'
|
||||
error_code = 0
|
||||
else:
|
||||
test_graph_file = '{0}/zbxTelegram_files/error_send_photo.png'
|
||||
error_code = 1
|
||||
|
||||
send_messages(sent_to=args.username, message='🚨 Test 🚽💩: Test message\n'
|
||||
'Host: testhost [192.168.0.0]\n'
|
||||
'Last value: test (10:00:00)\n'
|
||||
'Duration: 1m\n'
|
||||
'Description: This message is generated with test data. '
|
||||
'specify as the topic and / or zabbix\n\n'
|
||||
'#Test, #eid_130144443, #iid_60605, #tid_39303, #aid_22',
|
||||
graphs_png=dict(
|
||||
img=open(
|
||||
file=test_graph_file.format(os.path.dirname(os.path.realpath(__file__))),
|
||||
mode='rb').read()))
|
||||
exit(error_code)
|
||||
|
||||
data_zabbix = xml_parsing(args.messages)
|
||||
|
||||
event_tags = create_tags_list(
|
||||
_bool=True if data_zabbix.get('settings_eventtag_bool') and body_messages_tags_event else False,
|
||||
tag=data_zabbix['eventtags'], _type=None)
|
||||
eventid_tags = create_tags_list(
|
||||
_bool=True if data_zabbix.get('settings_eventidtag_bool') and body_messages_tags_eventid else False,
|
||||
tag=data_zabbix['eventid'], _type=body_messages_tags_prefix_eventid)
|
||||
itemid_tags = create_tags_list(
|
||||
_bool=True if data_zabbix.get('settings_itemidtag_bool') and body_messages_tags_itemid else False,
|
||||
tag=' '.join([item_id for item_id in data_zabbix['itemid'].split() if re.findall(r"\d+", item_id)]),
|
||||
_type=body_messages_tags_prefix_itemid)
|
||||
triggerid_tags = create_tags_list(
|
||||
_bool=True if data_zabbix.get('settings_triggeridtag_bool') and body_messages_tags_triggerid else False,
|
||||
tag=data_zabbix['triggerid'], _type=body_messages_tags_prefix_triggerid)
|
||||
actionid_tags = create_tags_list(
|
||||
_bool=True if data_zabbix.get('settings_actionidtag_bool') and body_messages_tags_actionid else False,
|
||||
tag=data_zabbix['actionid'], _type=body_messages_tags_prefix_actionid)
|
||||
hostid_tags = create_tags_list(
|
||||
_bool=True if data_zabbix.get('settings_hostidtag_bool') and body_messages_tags_hostid else False,
|
||||
tag=data_zabbix['hostid'], _type=body_messages_tags_prefix_hostid)
|
||||
zntsettings_tags = create_tags_list(
|
||||
_bool=True if data_zabbix.get('settings_zntsettingstag_bool') and body_messages_tags_trigger_settings
|
||||
else False,
|
||||
tag=data_zabbix['eventtags'], _type=None, zntsettingstag=True)
|
||||
|
||||
mentions = create_mentions_list(
|
||||
_bool=True if data_zabbix.get('settings_zntmentions_bool') and body_messages_mentions_settings else False,
|
||||
mentions=data_zabbix['eventtags'])
|
||||
|
||||
tags_list = []
|
||||
if isinstance(zntsettings_tags, dict) and len(zntsettings_tags[trigger_settings_tag]) > 0:
|
||||
loggings.info("Found settings tag: {}: {}".format(trigger_settings_tag,
|
||||
', '.join(zntsettings_tags[trigger_settings_tag])))
|
||||
tags_list.append(zntsettings_tags['tags']) if zntsettings_tags['tags'] else None
|
||||
if trigger_settings_tag_no_alert in zntsettings_tags[trigger_settings_tag]:
|
||||
loggings.info("Message sending canceled: {}:{}".format(trigger_settings_tag, trigger_settings_tag_no_alert))
|
||||
exit(1)
|
||||
|
||||
tags_list.append(event_tags) if event_tags else None
|
||||
tags_list.append(eventid_tags) if eventid_tags else None
|
||||
tags_list.append(itemid_tags) if itemid_tags else None
|
||||
tags_list.append(triggerid_tags) if triggerid_tags else None
|
||||
tags_list.append(actionid_tags) if actionid_tags else None
|
||||
tags_list.append(hostid_tags) if hostid_tags else None
|
||||
|
||||
|
||||
trigger_url = create_links_list(
|
||||
_bool=True if data_zabbix.get('settings_triggerlinks_bool') and body_messages_url_notes else False,
|
||||
url=data_zabbix.get('triggerurl'),
|
||||
_type=body_messages_url_emoji_notes)
|
||||
|
||||
host_url = create_links_list(
|
||||
_bool=True if data_zabbix.get('settings_hostlinks_bool') and body_messages_url_host else False,
|
||||
url=zabbix_host_link.format(zabbix_server=zabbix_api_url, host=data_zabbix.get('host')),
|
||||
_type=body_messages_url_emoji_host)
|
||||
|
||||
ack_url = create_links_list(
|
||||
_bool=True if data_zabbix.get('settings_acklinks_bool') and body_messages_url_ack else False,
|
||||
url=zabbix_ack_link.format(zabbix_server=zabbix_api_url, eventid=data_zabbix.get('eventid')),
|
||||
_type=body_messages_url_emoji_ack)
|
||||
|
||||
event_url = create_links_list(
|
||||
_bool=True if data_zabbix.get('settings_eventlinks_bool') and body_messages_url_event else False,
|
||||
url=zabbix_event_link.format(zabbix_server=zabbix_api_url, eventid=data_zabbix.get('eventid'),
|
||||
triggerid=data_zabbix.get('triggerid')), _type=body_messages_url_emoji_event)
|
||||
|
||||
if isinstance(zntsettings_tags, dict) and not all(settings.find(trigger_settings_tag_graph_period) and len(settings) > 0 for settings in zntsettings_tags[trigger_settings_tag]):
|
||||
try:
|
||||
graph_period_raw = [settings if settings.find(trigger_settings_tag_graph_period) == 0 else False for
|
||||
settings in zntsettings_tags['ZNTSettings']][0]
|
||||
graph_period = int(graph_period_raw.split('=')[1])
|
||||
except Exception as err:
|
||||
loggings.error("Exception occurred: {}:{}, {}".format(
|
||||
trigger_settings_tag, graph_period_raw, err), exc_info=config_exc_info), exit(1)
|
||||
elif data_zabbix['graphs_period'] != 'default':
|
||||
graph_period = data_zabbix['graphs_period']
|
||||
else:
|
||||
graph_period = zabbix_graph_period_default
|
||||
|
||||
url_list = []
|
||||
url_list.append(trigger_url) if trigger_url else None
|
||||
for item_id in list(set([x for x in data_zabbix.get('itemid').split()])):
|
||||
if re.findall(r"\d+", item_id):
|
||||
items_link = create_links_list(
|
||||
_bool=True if data_zabbix.get('settings_graphlinks_bool') and body_messages_url_graphs else False,
|
||||
url=zabbix_graph_link.format(zabbix_server=zabbix_api_url, itemid=item_id,
|
||||
range_time=data_zabbix['graphs_period']),
|
||||
_type=body_messages_url_emoji_graphs
|
||||
)
|
||||
url_list.append(items_link) if items_link else None
|
||||
url_list.append(event_url) if event_url else None
|
||||
url_list.append(ack_url) if ack_url else None
|
||||
url_list.append(host_url) if host_url else None
|
||||
|
||||
graphs_name = body_messages_title.format(
|
||||
title=data_zabbix['title'],
|
||||
period_time=set_period_day_hour(graph_period))
|
||||
|
||||
if (data_zabbix.get('settings_graphs_bool') and zabbix_graph) and trigger_settings_tag_no_graph not in zntsettings_tags[trigger_settings_tag]:
|
||||
num_items_id = [item_id for item_id in data_zabbix['itemid'].split() if re.findall(r"\d+", item_id)]
|
||||
if len(num_items_id) == 1:
|
||||
graphs_png = get_chart_png(itemid=num_items_id[0],
|
||||
graff_name=graphs_name,
|
||||
period=graph_period)
|
||||
else:
|
||||
graphs_png_group = []
|
||||
# get the unique itemid
|
||||
for item_id in list(set([x for x in data_zabbix.get('itemid').split()])):
|
||||
if re.findall(r"\d+", item_id):
|
||||
graphs_png_group.append(InputMediaPhoto(get_chart_png(
|
||||
itemid=item_id,
|
||||
graff_name=graphs_name,
|
||||
period=graph_period).get('img')))
|
||||
graphs_png = graphs_png_group
|
||||
else:
|
||||
graphs_png = False
|
||||
|
||||
subject = html.escape(args.subject.format_map(FailSafeDict(zabbix_status_emoji_map)))
|
||||
|
||||
if body_messages_cut_symbol and len(data_zabbix['message']) > body_messages_max_symbol:
|
||||
truncated = True
|
||||
loggings.info("Message truncated to {} characters".format(body_messages_max_symbol))
|
||||
else:
|
||||
truncated = False
|
||||
|
||||
body = '{} <a href="{}">...</a>'.format(
|
||||
html.escape(data_zabbix['message'])[:body_messages_max_symbol],
|
||||
zabbix_event_link.format(
|
||||
zabbix_server=zabbix_api_url, eventid=data_zabbix.get('eventid'),
|
||||
triggerid=data_zabbix.get('triggerid'))) if truncated else html.escape(data_zabbix['message'])
|
||||
|
||||
links = body_messages_url_delimiter.join(url_list) if body_messages_url and len(url_list) != 0 else ''
|
||||
|
||||
tags = body_messages_tags_delimiter.join(tags_list) if body_messages_tags and len(tags_list) != 0 else ''
|
||||
|
||||
mentions = ' '.join(mentions) if not isinstance(mentions, bool) and body_messages_mentions_settings and len(mentions) != 0 else ''
|
||||
|
||||
message = body_messages.format(subject=subject, body='\n\n'+body if body else '',
|
||||
links='\n'+links if links else '', tags='\n\n'+tags if tags else '',
|
||||
mentions='\n\n'+mentions if mentions else '')
|
||||
|
||||
send_messages(args.username, message, graphs_png, data_zabbix['eventid'], data_zabbix.get('settings_keyboard_bool'),
|
||||
disable_notification=True if isinstance(zntsettings_tags, dict) and trigger_settings_tag_not_notify in zntsettings_tags[trigger_settings_tag]
|
||||
else False)
|
||||
exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user