Группа :: Мониторинг
Пакет: zabbix-in-telegram
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: zabbix-in-telegram-20200425-alt1.patch
Скачать
Скачать
.gear/rules | 3 +
.gear/tags/list | 1 +
.gear/zabbix-in-telegram.spec | 65 +++
LICENSE.txt | 2 +-
README.md | 51 +--
ZbxTgDaemon.py | 174 ++++++++
bash-old-version/tg_vars.cfg.example | 11 +
bash-old-version/zbxtg.sh | 142 +++++++
requirements.txt | 3 +
tg_vars.cfg.example | 10 -
zbxtg.py | 747 +++++++++++++++++++++++++++++------
zbxtg.sh | 111 ------
zbxtg_settings.example.py | 57 ++-
13 files changed, 1094 insertions(+), 283 deletions(-)
diff --git a/.gear/rules b/.gear/rules
new file mode 100644
index 0000000..2319eee
--- /dev/null
+++ b/.gear/rules
@@ -0,0 +1,3 @@
+tar: upstream:.
+diff: upstream:. .
+spec: .gear/zabbix-in-telegram.spec
diff --git a/.gear/tags/list b/.gear/tags/list
new file mode 100644
index 0000000..71c721b
--- /dev/null
+++ b/.gear/tags/list
@@ -0,0 +1 @@
+c23673b50fa2f10c40ee53ad5cad6f90212a071a upstream
diff --git a/.gear/zabbix-in-telegram.spec b/.gear/zabbix-in-telegram.spec
new file mode 100644
index 0000000..90270c3
--- /dev/null
+++ b/.gear/zabbix-in-telegram.spec
@@ -0,0 +1,65 @@
+%define z_dir %_sysconfdir/zabbix/alertscripts
+
+Name: zabbix-in-telegram
+Version: 20200425
+Release: alt1
+
+Summary: Zabbix Notifications with graphs in Telegram
+
+License: MIT
+Group: Monitoring
+URL: https://github.com/ableev/Zabbix-in-Telegram
+
+BuildArch: noarch
+
+# Source-git: https://github.com/ableev/Zabbix-in-Telegram.git
+Source: %name-%version.tar
+Patch: %name-%version-%release.patch
+
+BuildRequires(pre): rpm-build-python3
+BuildRequires(pre): rpm-build-intro
+
+Requires: zabbix-server-common > 3.0.0
+
+%add_python3_req_skip zbxtg_settings
+
+# generated by 'epm restore --dry-run' from zabbix-in-telegram/requirements.txt
+%py3_use socks >= 1.6.8
+%py3_use requests >= 2.20.0
+%py3_use requests-oauthlib >= 0.6.2
+
+%description
+Zabbix Notifications with graphs in Telegram.
+
+%prep
+%setup
+sed -i 's|#!/usr/bin/env python|#!/usr/bin/env python3|' \
+ $(find ./ -name '*.py')
+
+%build
+
+%install
+mkdir -p %buildroot%z_dir
+install -p -m 755 zbxtg.py %buildroot%z_dir/zbxtg.py
+install -p -m 644 zbxtg_settings.example.py %buildroot%z_dir/zbxtg_settings.py
+
+%files
+%z_dir/zbxtg.py
+%config(noreplace) %z_dir/zbxtg_settings.py
+%doc README.md LICENSE.txt
+
+
+%changelog
+* Sat Jul 03 2021 Vitaly Lipatov <lav@altlinux.ru> 20200425-alt1
+- update to 4ca3585b4b568060370f17a864a8cbceb14438ca
+- add requires
+
+* Fri Nov 15 2019 Andrey Bychkov <mrdrew@altlinux.org> 20160607-alt3
+- python2 -> python3
+
+* Tue Jun 7 2016 Terechkov Evgenii <evg@altlinux.org> 20160607-alt2
+- c23673b
+
+* Tue Jun 7 2016 Terechkov Evgenii <evg@altlinux.org> 20160607-alt1
+- Initial build for ALT Linux Sisyphus (77e163b)
+
diff --git a/LICENSE.txt b/LICENSE.txt
index 10a8634..d3023c7 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2016 Ilya Ableev
+Copyright (c) 2019 Ilya Ableev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 0147ae7..193d3b2 100644
--- a/README.md
+++ b/README.md
@@ -1,36 +1,39 @@
# Zabbix-in-Telegram
Zabbix Notifications with graphs in Telegram
-Join us in our **Telegram group** via this link: https://telegram.me/ZbxTg
+Join us in our **Telegram group** via this link: https://t.me/ZbxTg
-Subscribe to our channel: https://telegram.me/Zabbix_in_Telegram
+Subscribe to our channel: https://t.me/Zabbix_in_Telegram
Rate on [share.zabbix.com](https://share.zabbix.com): https://share.zabbix.com/cat-notifications/zabbix-in-telegram
### Features
- [x] Graphs based on latest data are sent directly to your messenger
-- [x] You can send messages both in private and group chats
-- [x] Channels support
+- [x] You can send messages both in private and group/supergroup chats
+- [x] Channels support (only public, but you can do it for private as well with dirty hack)
- [x] Saves chatid as a temporary file
- [x] Simple markdown and HTML are supported
-- [x] Emoji in messages
+- [x] Emoji (you can use emoji instead of severity, see [the wiki article](https://github.com/ableev/Zabbix-in-Telegram/wiki/Trigger-severity-as-Emoji)) (zabbix doesn't support utf8mb4 encoding yet)
+- [x] Location map
### TODOs
-- Simple zabbix's management via bot's commands
+- Simple zabbix's management via bot's commands Б─⌠ in dev state
- Ability to send complex graph or part of screen
### Configuration / Installation
-**First of all**: You need to install the `requests` module for python, this is required for operation! </br>
- To do so, enter `pip install requests` in your commandline!
+**READ WIKI IF YOU HAVE PROBLEM WITH SOMETHING**: https://github.com/ableev/Zabbix-in-Telegram/wiki
- * Put `zbxtg.py` in your `AlertScriptsPath` directory, the path is set inside your zabbix_server.conf
- * Put `zbxtg_group.py` in the same location if you want to send messages to the group chat
- * Create `zbxtg_settings.py` with your settings and save them in the same directory as the script, see example for layout
- * Create a bot in Telegram and get API key
- * Create readonly user in Zabbix (for getting graphs images from zabbix)
- * Set proxy host:port in `zbxtg_settings.py` if you need an internet proxy
+**First of all**: You need to install the appropriate modules for python, this is required for operation! </br>
+ To do so, enter `pip install -r requirements.txt` in your commandline!
+
+ * Put `zbxtg.py` in your `AlertScriptsPath` directory, the path is set inside your `zabbix_server.conf`
+ * Put `zbxtg_group.py` in the same location if you want to send messages to the group chat (if you are using Zabbix 2.x version)
+ * Create `zbxtg_settings.py` (copy it from `zbxtg_settings.example.py`) with your settings and save them in the same directory as the script, see example for layout
+ * Create a bot in Telegram and get API key: https://core.telegram.org/bots#creating-a-new-bot
+ * Create readonly user in Zabbix web interface (for getting graphs from zabbix)
+ * Set proxy host:port in `zbxtg_settings.py` if you need an internet proxy (socks5 supported as well, the wiki will help you)
* Add new media for Telegram in Zabbix web interface with these settings:
<img src="https://i.imgur.com/Ytrbe4S.png" width="400px">
@@ -41,7 +44,7 @@ Rate on [share.zabbix.com](https://share.zabbix.com): https://share.zabbix.com/c
* **Note that Zabbix 3.0 has different settings for that step, see it there**: https://github.com/ableev/Zabbix-in-Telegram/wiki/Working-with-Zabbix-3.0
* Send a message to your bot via Telegram, e.g. "/start"
- * If you are in group chat, just mention your bot, e.g. `@ZbxTgDevBot ping`
+ * If you are in a group chat, start a conversation with your bot: `/start@ZbxTgDevBot`
* Create a new action like this:
```
Last value: {ITEM.LASTVALUE1} ({TIME})
@@ -55,8 +58,9 @@ zbxtg;title:{HOST.HOST} - {TRIGGER.NAME}
* Add the appropriate Media Type to your user
* The username is **CASE-SENSITIVE**
+ * If you don't have a username, you can use your chatid directly (and you need to google how to get it)
* Group chats don't have URLs, so you need to put group's name in media type
- * Messages for channels should be sent as for private chats
+ * Messages for channels should be sent as for private chats (simply add bot to your channel first and use channel's username as if it was a real user)
* Private:
@@ -73,9 +77,12 @@ zbxtg;graphs_period=10800 -- set graphs period (default - 3600 seconds)
zbxtg;graphs_width=700 -- set graphs width (default - 900px)
zbxtg;graphs_height=300 -- set graphs height (default - 300px)
zbxtg;itemid:{ITEM.ID1} -- define itemid (from trigger) for attach
-zbxtg;title:{HOST.HOST} - {TRIGGER.NAME} -- graph title
+zbxtg;itemid:{ITEM.ID1},{ITEM.ID2},{ITEM.ID3} -- same, but if you want to send two or more graphs, use complex trigger
+zbxtg;title:{HOST.HOST} - {TRIGGER.NAME} -- graph's title
zbxtg;debug -- enables debug mode, some logs and images will be saved in the tmp dir (temporary doesn't affect python version)
zbxtg;channel -- enables sending to channels
+zbxtg;to:username1,username2,username3 -- now you don't need to create dedicated profiles and add media for them, use this option in action to send messages to those user(s)
+zbxtg;to_group:Group Name One,Group Name Two -- the same but for groups
```
You can use markdown or html formatting in your action: https://core.telegram.org/bots/api#markdown-style + https://core.telegram.org/bots/api#html-style.
@@ -83,10 +90,10 @@ You can use markdown or html formatting in your action: https://core.telegram.or
#### Debug
* You can use the following command to send a message from your command line: </br>
-`./zbxtg.py "<username>" "<message_subject>" "<message_body>" --debug`
- * For `<username>` substitute your Telegram username, NOT that of your bot (case-sensitive)
- * For `<message_subject>` and `<message_body>` just substitute something like "test" "test" (for Telegram it's doesn't matter between subject and body
- * You can omit the `"`, these are optional
+`./zbxtg.py "@username" "first part of a message" "second part of a message" --debug`
+ * For `@username` substitute your Telegram username, **NOT that of your bot** (case-sensitive) OR chatid
+ * For `first part of a message` and `second part of a message` just substitute something like "test" "test" (for Telegram it's doesn't matter between subject and body)
+ * You can skip the `"` if it's one word for every parameter, these are optional
---
@@ -99,5 +106,5 @@ You can use markdown or html formatting in your action: https://core.telegram.or
If you see this error, it means that you rich the limit of caption with 200 symbols in it (Telegram API's limitaion).
Such captions will be automatically cut to 200 symbols.
-#### Zabbix 3.0
+#### Zabbix 3.0 and higher (3.2, 3.4, 4.0, 4.2, 4.4)
https://github.com/ableev/Zabbix-in-Telegram/wiki/Working-with-Zabbix-3.0
diff --git a/ZbxTgDaemon.py b/ZbxTgDaemon.py
new file mode 100644
index 0000000..d18a4d0
--- /dev/null
+++ b/ZbxTgDaemon.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+import sys
+import os
+import hashlib
+import re
+import time
+from os.path import dirname
+import zbxtg_settings
+import zbxtg
+from pyzabbix import ZabbixAPI, ZabbixAPIException
+
+
+class zabbixApi():
+ def __init__(self, server, user, password):
+ self.api = ZabbixAPI(server)
+ self.user = user
+ self.password = password
+
+ def login(self):
+ self.api.login(self.user, self.password)
+
+ def triggers_active(self):
+ return self.api.trigger.get(output="extend", monitored=True, filter={"value": 1}, sortfield="priority", sortorder="DESC",
+ selectHosts="extend")
+
+
+
+def print_message(string):
+ string = str(string) + "\n"
+ filename = sys.argv[0].split("/")[-1]
+ sys.stderr.write(filename + ": " + string)
+
+
+def file_write(filename, text):
+ with open(filename, "w") as fd:
+ fd.write(str(text))
+ return True
+
+
+def file_read(filename):
+ with open(filename, 'r') as fd:
+ text = fd.readlines()
+ return text
+
+
+def main():
+ TelegramAPI = zbxtg.TelegramAPI
+ ZabbixWeb = zbxtg.ZabbixWeb
+ tmp_dir = zbxtg_settings.zbx_tg_tmp_dir
+
+ if not zbxtg_settings.zbx_tg_daemon_enabled:
+ print("You should enable daemon by adding 'zbx_tg_remote_control' in the configuration file")
+ sys.exit(1)
+
+ tmp_uids = tmp_dir + "/uids.txt"
+ tmp_ts = {
+ "message_id": tmp_dir + "/daemon_message_id.txt",
+ "update_offset": tmp_dir + "/update_offset.txt",
+ }
+
+ for i, v in tmp_ts.iteritems():
+ if not os.path.exists(v):
+ print_message("{0} doesn't exist, creating new one...".format(v))
+ file_write(v, "0")
+ print_message("{0} successfully created".format(v))
+
+ message_id_last = file_read(tmp_ts["message_id"])[0].strip()
+ if message_id_last:
+ message_id_last = int(message_id_last)
+
+ update_id = file_read(tmp_ts["update_offset"])
+
+ tg = TelegramAPI(key=zbxtg_settings.tg_key)
+ if zbxtg_settings.proxy_to_tg:
+ proxy_to_tg = zbxtg_settings.proxy_to_tg
+ if not proxy_to_tg.find("http") and not proxy_to_tg.find("socks"):
+ proxy_to_tg = "https://" + proxy_to_tg
+ tg.proxies = {
+ "https": "{0}".format(zbxtg_settings.proxy_to_tg),
+ }
+ zbx = ZabbixWeb(server=zbxtg_settings.zbx_server, username=zbxtg_settings.zbx_api_user,
+ password=zbxtg_settings.zbx_api_pass)
+ if zbxtg_settings.proxy_to_zbx:
+ zbx.proxies = {"http": "http://{0}/".format(zbxtg_settings.proxy_to_zbx)}
+
+ try:
+ zbx_api_verify = zbxtg_settings.zbx_api_verify
+ zbx.verify = zbx_api_verify
+ except:
+ pass
+
+ zbxapi = zabbixApi(zbxtg_settings.zbx_server, zbxtg_settings.zbx_api_user, zbxtg_settings.zbx_api_pass)
+ zbxapi.login()
+
+ print(tg.get_me())
+
+ #hosts = zbxdb.db_query("SELECT hostid, host FROM hosts")
+
+ commands = [
+ "/triggers",
+ "/help",
+ # "/graph",
+ # "/history",
+ # "/screen"
+ ]
+
+ def md5(fname):
+ hash_md5 = hashlib.md5()
+ with open(fname, "rb") as f:
+ for chunk in iter(lambda: f.read(4096), b""):
+ hash_md5.update(chunk)
+ return hash_md5.hexdigest()
+
+ md5sum = md5("ZbxTgDaemon.py")
+ print md5sum
+
+ try:
+ while True:
+ time.sleep(1)
+ md5sum_new = md5("ZbxTgDaemon.py")
+ if md5sum != md5sum_new:
+ sys.exit(1)
+ tg.update_offset = update_id
+ updates = tg.get_updates()
+ if not updates["result"]:
+ continue
+ for m in updates["result"]:
+ if "message" not in m:
+ continue
+ update_id_last = m["update_id"]
+ tg.update_offset = update_id_last
+ if m["message"]["from"]["id"] not in zbxtg_settings.zbx_tg_daemon_enabled_ids:
+ file_write(tmp_ts["update_offset"], update_id_last)
+ continue
+ print("Fuck this shit, I'm not going to answer to someone not from the whitelist")
+ else:
+ if not "text" in m["message"]:
+ continue
+ text = m["message"]["text"]
+ to = m["message"]["from"]["id"]
+ reply_text = list()
+ if m["message"]["message_id"] > message_id_last:
+ if re.search(r"^/(start|help)", text):
+ reply_text.append("Hey, this is ZbxTgDaemon bot.")
+ reply_text.append("https://github.com/ableev/Zabbix-in-Telegram")
+ reply_text.append("If you need help, you can ask it in @ZbxTg group\n")
+ reply_text.append("Available commands:")
+ reply_text.append("\n".join(commands))
+ tg.disable_web_page_preview = True
+ if re.search(r"^/triggers", text):
+ triggers = zbxapi.triggers_active()
+ if triggers:
+ for t in triggers:
+ reply_text.append("Severity: {0}, Host: {1}, Trigger: {2}".format(
+ t["priority"], t["hosts"][0]["host"].encode('utf-8'), t["description"].encode('utf-8')
+ ))
+ else:
+ reply_text.append("There are no triggers, have a nice day!")
+ if not reply_text:
+ reply_text = ["I don't know what to do about it"]
+ if tg.send_message(to, reply_text):
+ with open(tmp_ts["message_id"], "w") as message_id_file:
+ message_id_file.write(str(m["message"]["message_id"]))
+ message_id_last = m["message"]["message_id"]
+ tg.disable_web_page_preview = False
+ file_write(tmp_ts["update_offset"], update_id_last)
+ except KeyboardInterrupt:
+ print("Exiting...")
+
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/bash-old-version/tg_vars.cfg.example b/bash-old-version/tg_vars.cfg.example
new file mode 100644
index 0000000..6494278
--- /dev/null
+++ b/bash-old-version/tg_vars.cfg.example
@@ -0,0 +1,11 @@
+TG_KEY="000:AAAAA_bbbb"
+
+ZBX_TG_PREFIX="zbxtg" # variable for separating text from script info
+ZBX_TG_SIGN="TRUE"
+
+ZBX_SERVER="http://zabbix.local" # zabbix server url
+ZBX_API_USER="api" # zabbix user; user must have at least read access to get graphs
+ZBX_API_PASS="apisecret"
+
+CURL="curl -s" # if you are using proxy server, it's time to add it right here
+# CURL="curl -x proxy.local:3128 -s"
diff --git a/bash-old-version/zbxtg.sh b/bash-old-version/zbxtg.sh
new file mode 100755
index 0000000..6afad26
--- /dev/null
+++ b/bash-old-version/zbxtg.sh
@@ -0,0 +1,142 @@
+#!/bin/bash
+
+. $(dirname "$0")/tg_vars.cfg
+
+CURL_TG="${CURL} https://api.telegram.org/bot${TG_KEY}"
+
+TMP_DIR="/tmp/${ZBX_TG_PREFIX}"
+[ ! -d "${TMP_DIR}" ] && (mkdir -p ${TMP_DIR} || TMP_DIR="/tmp")
+TMP_COOKIE="${TMP_DIR}/cookie.txt"
+TMP_UIDS="${TMP_DIR}/uids.txt"
+
+TS="`date +%s_%N`_$RANDOM"
+LOG="/dev/null"
+
+IS_DEBUG () {
+ if [ "${ISDEBUG}" == "TRUE" ]
+ then
+ return 0
+ else
+ return 1
+ fi
+}
+
+
+login() {
+ # grab cookie for downloading image
+ IS_DEBUG && echo "${CURL} --cookie-jar ${TMP_COOKIE} --request POST --data \"name=${ZBX_API_USER}&password=${ZBX_API_PASS}&enter=Sign%20in\" ${ZBX_SERVER}/" >>${LOG}
+ ${CURL} --cookie-jar ${TMP_COOKIE} --request POST --data "name=${ZBX_API_USER}&password=${ZBX_API_PASS}&enter=Sign%20in" ${ZBX_SERVER}/
+}
+
+get_image() {
+ URL=$1
+ URL=$(echo "${URL}" | sed -e 's/\ /%20/g')
+ IMG_NAME=$2
+ # downloads png graph and saves it to temporary path
+ IS_DEBUG && echo "${CURL} --cookie ${TMP_COOKIE} --globoff \"${URL}\" -o ${IMG_NAME}" >>${LOG}
+ ${CURL} --cookie ${TMP_COOKIE} --globoff "${URL}" -o ${IMG_NAME}
+}
+
+TO=$1
+SUBJECT=$2
+BODY=$3
+
+TG_GROUP=0 # send message to chat or to private chat to user
+TG_CHANNEL=0 # send message to channel
+METHOD="txt" # sendMessage (simple text) or sendPhoto (attached image)
+
+echo "${BODY}" | grep -q "${ZBX_TG_PREFIX};graphs" && METHOD="image"
+echo "${BODY}" | grep -q "${ZBX_TG_PREFIX};chat" && TG_GROUP=1
+echo "${BODY}" | grep -q "${ZBX_TG_PREFIX};group" && TG_GROUP=1
+echo "${BODY}" | grep -q "${ZBX_TG_PREFIX};debug" && ISDEBUG="TRUE"
+echo "${BODY}" | grep -q "${ZBX_TG_PREFIX};channel" && TG_CHANNEL=1
+
+IS_DEBUG && LOG="${TMP_DIR}/debug.${TS}.log"
+IS_DEBUG && echo -e "TMP_DIR=${TMP_DIR}\nTMP_COOKIE=${TMP_COOKIE}\nTMP_UIDS=${TMP_UIDS}" >>${LOG}
+
+if [ "${TG_GROUP}" -eq 1 ]
+then
+ TG_CONTACT_TYPE="group"
+else
+ TG_CONTACT_TYPE="private"
+fi
+
+TG_CHAT_ID=$(cat ${TMP_UIDS} | awk -F ';' '{if ($1 == "'${TO}'" && $2 == "'${TG_CONTACT_TYPE}'") print $3}' | tail -1)
+
+if [ "${TG_CHANNEL}" -eq 1 ]
+then
+ TG_CHAT_ID="${TO}"
+fi
+
+if [ -z "${TG_CHAT_ID}" ]
+then
+ TG_UPDATES=$(${CURL_TG}/getUpdates | sed -e 's/},{/\n/')
+ for (( idx=${#TG_UPDATES[@]}-1 ; idx>=0 ; idx-- ))
+ do
+ UPDATE="${TG_UPDATES[idx]}"
+ echo "${UPDATE}"
+ if [ "${TG_GROUP}" -eq 1 ]
+ then
+ TG_CHAT_ID=$(echo "${UPDATE}" | sed -e 's/["}{]//g' | awk -F ',' '{if ($8 == "type:group" && $7 == "title:'${TO}'") {gsub("chat:id:", "", $6); print $6}}' | tail -1)
+ if [ "$(echo ${TG_CHAT_ID} | grep -Eq '\-[0-9]+' && echo 1 || echo 0)" -eq 1 ]
+ then
+ break
+ fi
+ else
+ TG_CHAT_ID=$(echo "${UPDATE}" | sed -e 's/["}{]//g' | awk -F ',' '{if ($10 == "type:private" && $5 == "username:'${TO}'") {gsub("chat:id:", "", $6); print $6}}' | tail -1)
+ if [ "$(echo ${TG_CHAT_ID} | grep -Eq '[0-9]+' && echo 1 || echo 0)" -eq 1 ]
+ then
+ break
+ fi
+ fi
+ done
+ echo "${TO};${TG_CONTACT_TYPE};${TG_CHAT_ID}" >>${TMP_UIDS}
+fi
+
+IS_DEBUG && echo "TG_CHAT_ID: ${TG_CHAT_ID}" >>${LOG}
+
+TG_TEXT=$(echo "${BODY}" | grep -vE "^${ZBX_TG_PREFIX};")
+if [ "${ZBX_TG_SIGN}" != "FALSE" ]
+then
+ TG_TEXT=$(echo ${TG_TEXT}; echo "--"; echo "${ZBX_SERVER}")
+fi
+
+case "${METHOD}" in
+
+ "txt")
+ TG_MESSAGE=$(echo -e "${SUBJECT}\n${TG_TEXT}")
+ IS_DEBUG && echo "${CURL_TG}/sendMessage -F \"chat_id=${TG_CHAT_ID}\" -F \"text=${TG_MESSAGE}\"" >>${LOG}
+ ANSWER=$(${CURL_TG}/sendMessage?chat_id=${TG_CHAT_ID} --form "text=${TG_MESSAGE}" 2>&1)
+ if [ "$(echo "${ANSWER}" | grep -Ec 'migrated.*supergroup')" -eq 1 ]
+ then
+ migrate_to_chat_id=$(echo "${ANSWER}" | sed -e 's/["}{]//g' | grep -Eo '\-[0-9]+$')
+ echo "${TO};${TG_CONTACT_TYPE};${migrate_to_chat_id}" >>${TMP_UIDS}
+ ANSWER=$(${CURL_TG}/sendMessage?chat_id=${migrate_to_chat_id} --form "text=${TG_MESSAGE}" 2>&1)
+ fi
+ ;;
+
+ "image")
+ PERIOD=3600 # default period
+ echo "${BODY}" | grep -q "^${ZBX_TG_PREFIX};graphs_period" && PERIOD=$(echo "${BODY}" | awk -F "${ZBX_TG_PREFIX};graphs_period=" '{if ($2 != "") print $2}' | tail -1 | grep -Eo '[0-9]+' || echo 3600)
+ ZBX_ITEMID=$(echo "${BODY}" | awk -F "${ZBX_TG_PREFIX};itemid:" '{if ($2 != "") print $2}' | tail -1 | grep -Eo '[0-9]+')
+ ZBX_TITLE=$(echo "${BODY}" | awk -F "${ZBX_TG_PREFIX};title:" '{if ($2 != "") print $2}' | tail -1)
+ URL="${ZBX_SERVER}/chart3.php?period=${PERIOD}&name=${ZBX_TITLE}&width=900&height=200&graphtype=0&legend=1&items[0][itemid]=${ZBX_ITEMID}&items[0][sortorder]=0&items[0][drawtype]=5&items[0][color]=00CC00"
+ IS_DEBUG && echo "Zabbix graph URL: ${URL}" >> ${LOG}
+ login
+ CACHE_IMAGE="${TMP_DIR}/graph.${ZBX_ITEMID}.png"
+ IS_DEBUG && echo "Image cached to ${CACHE_IMAGE} and wasn't deleted" >> ${LOG}
+ get_image "${URL}" ${CACHE_IMAGE}
+ TG_CAPTION_ORIG=$(echo -e "${SUBJECT}\n${TG_TEXT}")
+ TG_CAPTION=$(echo -e $(echo "${TG_CAPTION_ORIG}" | sed ':a;N;$!ba;s/\n/\\n/g' | awk '{print substr( $0, 0, 200 )}'))
+ if [ "${TG_CAPTION}" != "${TG_CAPTION_ORIG}" ]
+ then
+ echo "${ZBX_TG_PREFIX}: probably you will see MEDIA_CAPTION_TOO_LONG error, the message has been cut to 200 symbols, https://github.com/ableev/Zabbix-in-Telegram/issues/9#issuecomment-166895044"
+ fi
+ IS_DEBUG && echo "${CURL_TG}/sendPhoto?chat_id=${TG_CHAT_ID}\" --form \"caption=${TG_CAPTION}\" -F \"photo=@${CACHE_IMAGE}\"" >>${LOG}
+ ANSWER=$(${CURL_TG}/sendPhoto?chat_id=${TG_CHAT_ID} --form "caption=${TG_CAPTION}" -F "photo=@${CACHE_IMAGE}")
+ IS_DEBUG || rm ${CACHE_IMAGE}
+ ;;
+
+esac
+
+echo >>${LOG}
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..63b178b
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,3 @@
+PySocks==1.6.8
+requests==2.20.0
+requests-oauthlib==0.6.2
diff --git a/tg_vars.cfg.example b/tg_vars.cfg.example
deleted file mode 100644
index 938ab1d..0000000
--- a/tg_vars.cfg.example
+++ /dev/null
@@ -1,10 +0,0 @@
-TG_KEY="000:AAAAA_bbbb"
-
-ZBX_TG_PREFIX="zbxtg" # variable for separating text from script info
-
-ZBX_SERVER="http://zabbix.local" # zabbix server url
-ZBX_API_USER="api" # zabbix user; user must have at least read access to get graphs
-ZBX_API_PASS="apisecret"
-
-CURL="curl -s" # if you are using proxy server, it's time to add it right here
-# CURL="curl -x proxy.local:3128 -s"
diff --git a/zbxtg.py b/zbxtg.py
index 5099de9..3689ab5 100755
--- a/zbxtg.py
+++ b/zbxtg.py
@@ -5,22 +5,34 @@ import sys
import os
import time
import random
+import string
import requests
import json
import re
import stat
+import hashlib
+import subprocess
+#import sqlite3
from os.path import dirname
import zbxtg_settings
-class TelegramAPI():
+class Cache:
+ def __init__(self, database):
+ self.database = database
+
+ def create_db(self, database):
+ pass
+
+
+class TelegramAPI:
tg_url_bot_general = "https://api.telegram.org/bot"
def http_get(self, url):
- res = requests.get(url, proxies=self.proxies)
- answer = res.text
- answer_json = json.loads(answer.decode('utf8'))
- return answer_json
+ answer = requests.get(url, proxies=self.proxies)
+ self.result = answer.json()
+ self.ok_update()
+ return self.result
def __init__(self, key):
self.debug = False
@@ -32,7 +44,15 @@ class TelegramAPI():
self.disable_web_page_preview = False
self.disable_notification = False
self.reply_to_message_id = 0
+ self.tmp_dir = None
self.tmp_uids = None
+ self.location = {"latitude": None, "longitude": None}
+ self.update_offset = 0
+ self.image_buttons = False
+ self.result = None
+ self.ok = None
+ self.error = None
+ self.get_updates_from_file = False
def get_me(self):
url = self.tg_url_bot_general + self.key + "/getMe"
@@ -41,17 +61,19 @@ class TelegramAPI():
def get_updates(self):
url = self.tg_url_bot_general + self.key + "/getUpdates"
+ params = {"offset": self.update_offset}
if self.debug:
print_message(url)
- updates = self.http_get(url)
+ answer = requests.post(url, params=params, proxies=self.proxies)
+ self.result = answer.json()
+ if self.get_updates_from_file:
+ print_message("Getting updated from file getUpdates.txt")
+ self.result = json.loads("".join(file_read("getUpdates.txt")))
if self.debug:
print_message("Content of /getUpdates:")
- print_message(updates)
- if not updates["ok"]:
- print_message(updates)
- return updates
- else:
- return updates
+ print_message(json.dumps(self.result))
+ self.ok_update()
+ return self.result
def send_message(self, to, message):
url = self.tg_url_bot_general + self.key + "/sendMessage"
@@ -69,19 +91,50 @@ class TelegramAPI():
print_message("Trying to /sendMessage:")
print_message(url)
print_message("post params: " + str(params))
- res = requests.post(url, params=params, proxies=self.proxies)
- answer = res.text
- answer_json = json.loads(answer.decode('utf8'))
- if not answer_json["ok"]:
- print_message(answer_json)
- return answer_json
+ answer = requests.post(url, params=params, proxies=self.proxies)
+ if answer.status_code == 414:
+ self.result = {"ok": False, "description": "414 URI Too Long"}
else:
- return answer_json
+ self.result = answer.json()
+ self.ok_update()
+ return self.result
+
+ def update_message(self, to, message_id, message):
+ url = self.tg_url_bot_general + self.key + "/editMessageText"
+ message = "\n".join(message)
+ params = {"chat_id": to, "message_id": message_id, "text": message,
+ "disable_web_page_preview": self.disable_web_page_preview,
+ "disable_notification": self.disable_notification}
+ if self.markdown or self.html:
+ parse_mode = "HTML"
+ if self.markdown:
+ parse_mode = "Markdown"
+ params["parse_mode"] = parse_mode
+ if self.debug:
+ print_message("Trying to /editMessageText:")
+ print_message(url)
+ print_message("post params: " + str(params))
+ answer = requests.post(url, params=params, proxies=self.proxies)
+ self.result = answer.json()
+ self.ok_update()
+ return self.result
def send_photo(self, to, message, path):
url = self.tg_url_bot_general + self.key + "/sendPhoto"
message = "\n".join(message)
- params = {"chat_id": to, "caption": message, "disable_notification": self.disable_notification}
+ if self.image_buttons:
+ reply_markup = json.dumps({"inline_keyboard": [[
+ {"text": "R", "callback_data": "graph_refresh"},
+ {"text": "1h", "callback_data": "graph_period_3600"},
+ {"text": "3h", "callback_data": "graph_period_10800"},
+ {"text": "6h", "callback_data": "graph_period_21600"},
+ {"text": "12h", "callback_data": "graph_period_43200"},
+ {"text": "24h", "callback_data": "graph_period_86400"},
+ ], ]})
+ else:
+ reply_markup = json.dumps({})
+ params = {"chat_id": to, "caption": message, "disable_notification": self.disable_notification,
+ "reply_markup": reply_markup}
if self.reply_to_message_id:
params["reply_to_message_id"] = self.reply_to_message_id
files = {"photo": open(path, 'rb')}
@@ -90,14 +143,34 @@ class TelegramAPI():
print_message(url)
print_message(params)
print_message("files: " + str(files))
- res = requests.post(url, params=params, files=files, proxies=self.proxies)
- answer = res.text
- answer_json = json.loads(answer.decode('utf8'))
- if not answer_json["ok"]:
- print_message(answer_json)
- return answer_json
+ answer = requests.post(url, params=params, files=files, proxies=self.proxies)
+ self.result = answer.json()
+ self.ok_update()
+ return self.result
+
+ def send_txt(self, to, text, text_name=None):
+ path = self.tmp_dir + "/" + "zbxtg_txt_"
+ url = self.tg_url_bot_general + self.key + "/sendDocument"
+ text = "\n".join(text)
+ if not text_name:
+ path += "".join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10))
else:
- return answer_json
+ path += text_name
+ path += ".txt"
+ file_write(path, text)
+ params = {"chat_id": to, "caption": path.split("/")[-1], "disable_notification": self.disable_notification}
+ if self.reply_to_message_id:
+ params["reply_to_message_id"] = self.reply_to_message_id
+ files = {"document": open(path, 'rb')}
+ if self.debug:
+ print_message("Trying to /sendDocument:")
+ print_message(url)
+ print_message(params)
+ print_message("files: " + str(files))
+ answer = requests.post(url, params=params, files=files, proxies=self.proxies)
+ self.result = answer.json()
+ self.ok_update()
+ return self.result
def get_uid(self, name):
uid = 0
@@ -109,21 +182,28 @@ class TelegramAPI():
chat = m["message"]["chat"]
elif "edited_message" in m:
chat = m["edited_message"]["chat"]
+ else:
+ continue
if chat["type"] == self.type == "private":
if "username" in chat:
if chat["username"] == name:
uid = chat["id"]
if (chat["type"] == "group" or chat["type"] == "supergroup") and self.type == "group":
if "title" in chat:
- if chat["title"] == name.decode("utf-8"):
- uid = chat["id"]
+ if sys.version_info[0] < 3:
+ if chat["title"] == name.decode("utf-8"):
+ uid = chat["id"]
+ else:
+ if chat["title"] == name:
+ uid = chat["id"]
return uid
def error_need_to_contact(self, to):
if self.type == "private":
print_message("User '{0}' needs to send some text bot in private".format(to))
if self.type == "group":
- print_message("You need to mention your bot in '{0}' group chat (i.e. type @YourBot)".format(to))
+ print_message("You need start a conversation with your bot first in '{0}' group chat, type '/start@{1}'"
+ .format(to, self.get_me()["result"]["username"]))
def update_cache_uid(self, name, uid, message="Add new string to cache file"):
cache_string = "{0};{1};{2}\n".format(name, self.type, str(uid).rstrip())
@@ -132,22 +212,68 @@ class TelegramAPI():
print_message("{0}: {1}".format(message, cache_string))
with open(self.tmp_uids, "a") as cache_file_uids:
cache_file_uids.write(cache_string)
+ return True
def get_uid_from_cache(self, name):
+ if self.debug:
+ print_message("Trying to read cached uid for {0}, {1}, from {2}".format(name, self.type, self.tmp_uids))
uid = 0
if os.path.isfile(self.tmp_uids):
with open(self.tmp_uids, 'r') as cache_file_uids:
cache_uids_old = cache_file_uids.readlines()
-
for u in cache_uids_old:
u_splitted = u.split(";")
if name == u_splitted[0] and self.type == u_splitted[1]:
uid = u_splitted[2]
-
return uid
+ def send_location(self, to, coordinates):
+ url = self.tg_url_bot_general + self.key + "/sendLocation"
+ params = {"chat_id": to, "disable_notification": self.disable_notification,
+ "latitude": coordinates["latitude"], "longitude": coordinates["longitude"]}
+ if self.reply_to_message_id:
+ params["reply_to_message_id"] = self.reply_to_message_id
+ if self.debug:
+ print_message("Trying to /sendLocation:")
+ print_message(url)
+ print_message("post params: " + str(params))
+ answer = requests.post(url, params=params, proxies=self.proxies)
+ self.result = answer.json()
+ self.ok_update()
+ return self.result
+
+ def answer_callback_query(self, callback_query_id, text=None):
+ url = self.tg_url_bot_general + self.key + "/answerCallbackQuery"
+ if not text:
+ params = {"callback_query_id": callback_query_id}
+ else:
+ params = {"callback_query_id": callback_query_id, "text": text}
+ answer = requests.post(url, params=params, proxies=self.proxies)
+ self.result = answer.json()
+ self.ok_update()
+ return self.result
+
+ def ok_update(self):
+ self.ok = self.result["ok"]
+ if self.ok:
+ self.error = None
+ else:
+ self.error = self.result["description"]
+ print_message(self.error)
+ return True
+
+
+def markdown_fix(message, offset, emoji=False):
+ offset = int(offset)
+ if emoji: # https://github.com/ableev/Zabbix-in-Telegram/issues/152
+ offset -= 2
+ message = "\n".join(message)
+ message = message[:offset] + message[offset+1:]
+ message = message.split("\n")
+ return message
-class ZabbixAPI():
+
+class ZabbixWeb:
def __init__(self, server, username, password):
self.debug = False
self.server = server
@@ -156,16 +282,19 @@ class ZabbixAPI():
self.proxies = {}
self.verify = True
self.cookie = None
+ self.basic_auth_user = None
+ self.basic_auth_pass = None
+ self.tmp_dir = None
def login(self):
-
if not self.verify:
requests.packages.urllib3.disable_warnings()
data_api = {"name": self.username, "password": self.password, "enter": "Sign in"}
- req_cookie = requests.post(self.server + "/", data=data_api, proxies=self.proxies, verify=self.verify)
- cookie = req_cookie.cookies
- if len(req_cookie.history) > 1 and req_cookie.history[0].status_code == 302:
+ answer = requests.post(self.server + "/", data=data_api, proxies=self.proxies, verify=self.verify,
+ auth=requests.auth.HTTPBasicAuth(self.basic_auth_user, self.basic_auth_pass))
+ cookie = answer.cookies
+ if len(answer.history) > 1 and answer.history[0].status_code == 302:
print_message("probably the server in your config file has not full URL (for example "
"'{0}' instead of '{1}')".format(self.server, self.server + "/zabbix"))
if not cookie:
@@ -174,26 +303,49 @@ class ZabbixAPI():
self.cookie = cookie
- def graph_get(self, itemid, period, title, width, height, tmp_dir):
- file_img = tmp_dir + "/{0}.png".format(itemid)
+ def graph_get(self, itemid, period, title, width, height, version=3):
+ file_img = "{0}/{1}.png".format(self.tmp_dir,
+ "".join(random.choice(string.ascii_letters) for e in range(10)))
title = requests.utils.quote(title)
- zbx_img_url = self.server + "/chart3.php?period={1}&name={2}" \
- "&width={3}&height={4}&graphtype=0&legend=1" \
- "&items[0][itemid]={0}&items[0][sortorder]=0" \
- "&items[0][drawtype]=5&items[0][color]=00CC00".format(itemid, period, title,
- width, height)
+ colors = {
+ 0: "00CC00",
+ 1: "CC0000",
+ 2: "0000CC",
+ 3: "CCCC00",
+ 4: "00CCCC",
+ 5: "CC00CC",
+ }
+
+ drawtype = 5
+ if len(itemid) > 1:
+ drawtype = 2
+
+ zbx_img_url_itemids = []
+ for i in range(0, len(itemid)):
+ itemid_url = "&items[{0}][itemid]={1}&items[{0}][sortorder]={0}&" \
+ "items[{0}][drawtype]={3}&items[{0}][color]={2}".format(i, itemid[i], colors[i], drawtype)
+ zbx_img_url_itemids.append(itemid_url)
+
+ zbx_img_url = self.server + "/chart3.php?"
+ if version < 4:
+ zbx_img_url += "period={0}".format(period)
+ else:
+ zbx_img_url += "from=now-{0}&to=now".format(period)
+ zbx_img_url += "&name={0}&width={1}&height={2}&graphtype=0&legend=1".format(title, width, height)
+ zbx_img_url += "".join(zbx_img_url_itemids)
+
if self.debug:
print_message(zbx_img_url)
- res = requests.get(zbx_img_url, cookies=self.cookie, proxies=self.proxies, verify=self.verify)
- res_code = res.status_code
- if res_code == 404:
+ answer = requests.get(zbx_img_url, cookies=self.cookie, proxies=self.proxies, verify=self.verify,
+ auth=requests.auth.HTTPBasicAuth(self.basic_auth_user, self.basic_auth_pass))
+ status_code = answer.status_code
+ if status_code == 404:
print_message("can't get image from '{0}'".format(zbx_img_url))
return False
- res_img = res.content
- with open(file_img, 'wb') as fp:
- fp.write(res_img)
+ res_img = answer.content
+ file_bwrite(file_img, res_img)
return file_img
def api_test(self):
@@ -205,16 +357,15 @@ class ZabbixAPI():
return api.text
-def print_message(string):
- string = str(string) + "\n"
+def print_message(message):
+ message = str(message) + "\n"
filename = sys.argv[0].split("/")[-1]
- sys.stderr.write(filename + ": " + string)
+ sys.stderr.write(filename + ": " + message)
def list_cut(elements, symbols_limit):
symbols_count = symbols_count_now = 0
elements_new = []
- element_last = None
element_last_list = []
for e in elements:
symbols_count_now = symbols_count + len(e)
@@ -238,9 +389,93 @@ def list_cut(elements, symbols_limit):
return elements_new, True
+class Maps:
+ # https://developers.google.com/maps/documentation/geocoding/intro
+ def __init__(self):
+ self.key = None
+ self.proxies = {}
+
+ def get_coordinates_by_address(self, address):
+ coordinates = {"latitude": 0, "longitude": 0}
+ url_api = "https://maps.googleapis.com/maps/api/geocode/json?key={0}&address={1}".format(self.key, address)
+ url = url_api
+ answer = requests.get(url, proxies=self.proxies)
+ result = answer.json()
+ try:
+ coordinates_dict = result["results"][0]["geometry"]["location"]
+ except:
+ if "error_message" in result:
+ print_message("[" + result["status"] + "]: " + result["error_message"])
+ return coordinates
+ coordinates = {"latitude": coordinates_dict["lat"], "longitude": coordinates_dict["lng"]}
+ return coordinates
+
+
+def file_write(filename, text):
+ with open(filename, "w") as fd:
+ fd.write(str(text))
+ return True
+
+
+def file_bwrite(filename, data):
+ with open(filename, "wb") as fd:
+ fd.write(data)
+ return True
+
+
+def file_read(filename):
+ with open(filename, "r") as fd:
+ text = fd.readlines()
+ return text
+
+
+def file_append(filename, text):
+ with open(filename, "a") as fd:
+ fd.write(str(text))
+ return True
+
+
+def external_image_get(url, tmp_dir, timeout=6):
+ image_hash = hashlib.md5()
+ image_hash.update(url.encode())
+ file_img = tmp_dir + "/external_{0}.png".format(image_hash.hexdigest())
+ try:
+ answer = requests.get(url, timeout=timeout, allow_redirects=True)
+ except requests.exceptions.ReadTimeout as ex:
+ print_message("Can't get external image from '{0}': timeout".format(url))
+ return False
+ status_code = answer.status_code
+ if status_code == 404:
+ print_message("Can't get external image from '{0}': HTTP 404 error".format(url))
+ return False
+ answer_image = answer.content
+ file_bwrite(file_img, answer_image)
+ return file_img
+
+
+def age2sec(age_str):
+ age_sec = 0
+ age_regex = "([0-9]+d)?\s?([0-9]+h)?\s?([0-9]+m)?"
+ age_pattern = re.compile(age_regex)
+ intervals = age_pattern.match(age_str).groups()
+ for i in intervals:
+ if i:
+ metric = i[-1]
+ if metric == "d":
+ age_sec += int(i[0:-1])*86400
+ if metric == "h":
+ age_sec += int(i[0:-1])*3600
+ if metric == "m":
+ age_sec += int(i[0:-1])*60
+ return age_sec
+
+
def main():
tmp_dir = zbxtg_settings.zbx_tg_tmp_dir
+ if tmp_dir == "/tmp/" + zbxtg_settings.zbx_tg_prefix:
+ print_message("WARNING: it is strongly recommended to change `zbx_tg_tmp_dir` variable in config!!!")
+ print_message("https://github.com/ableev/Zabbix-in-Telegram/wiki/Change-zbx_tg_tmp_dir-in-settings")
tmp_cookie = tmp_dir + "/cookie.py.txt"
tmp_uids = tmp_dir + "/uids.txt"
@@ -252,28 +487,150 @@ def main():
log_file = "/dev/null"
- zbx_to = sys.argv[1]
- zbx_subject = sys.argv[2]
- zbx_body = sys.argv[3]
+ args = sys.argv
+
+ settings = {
+ "zbxtg_itemid": "0", # itemid for graph
+ "zbxtg_title": None, # title for graph
+ "zbxtg_image_period": None,
+ "zbxtg_image_age": "3600",
+ "zbxtg_image_width": "900",
+ "zbxtg_image_height": "200",
+ "tg_method_image": False, # if True - default send images, False - send text
+ "tg_chat": False, # send message to chat or in private
+ "tg_group": False, # send message to chat or in private
+ "is_debug": False,
+ "is_channel": False,
+ "disable_web_page_preview": False,
+ "location": None, # address
+ "lat": 0, # latitude
+ "lon": 0, # longitude
+ "is_single_message": False,
+ "markdown": False,
+ "html": False,
+ "signature": None,
+ "signature_disable": False,
+ "graph_buttons": False,
+ "extimg": None,
+ "to": None,
+ "to_group": None,
+ "forked": False,
+ }
+
+ url_github = "https://github.com/ableev/Zabbix-in-Telegram"
+ url_wiki_base = "https://github.com/ableev/Zabbix-in-Telegram/wiki"
+ url_tg_group = "https://t.me/ZbxTg"
+ url_tg_channel = "https://t.me/Zabbix_in_Telegram"
+
+ settings_description = {
+ "itemid": {"name": "zbxtg_itemid", "type": "list",
+ "help": "script will attach a graph with that itemid (could be multiple)", "url": "Graphs"},
+ "title": {"name": "zbxtg_title", "type": "str", "help": "title for attached graph", "url": "Graphs"},
+ "graphs_period": {"name": "zbxtg_image_period", "type": "int", "help": "graph period", "url": "Graphs"},
+ "graphs_age": {"name": "zbxtg_image_age", "type": "str", "help": "graph period as age", "url": "Graphs"},
+ "graphs_width": {"name": "zbxtg_image_width", "type": "int", "help": "graph width", "url": "Graphs"},
+ "graphs_height": {"name": "zbxtg_image_height", "type": "int", "help": "graph height", "url": "Graphs"},
+ "graphs": {"name": "tg_method_image", "type": "bool", "help": "enables graph sending", "url": "Graphs"},
+ "chat": {"name": "tg_chat", "type": "bool", "help": "deprecated, don't use it, see 'group'",
+ "url": "How-to-send-message-to-the-group-chat"},
+ "group": {"name": "tg_group", "type": "bool", "help": "sends message to a group",
+ "url": "How-to-send-message-to-the-group-chat"},
+ "debug": {"name": "is_debug", "type": "bool", "help": "enables 'debug'",
+ "url": "How-to-test-script-in-command-line"},
+ "channel": {"name": "is_channel", "type": "bool", "help": "sends message to a channel",
+ "url": "Channel-support"},
+ "disable_web_page_preview": {"name": "disable_web_page_preview", "type": "bool",
+ "help": "disable web page preview", "url": "Disable-web-page-preview"},
+ "location": {"name": "location", "type": "str", "help": "address of location", "url": "Location"},
+ "lat": {"name": "lat", "type": "str", "help": "specify latitude (and lon too!)", "url": "Location"},
+ "lon": {"name": "lon", "type": "str", "help": "specify longitude (and lat too!)", "url": "Location"},
+ "single_message": {"name": "is_single_message", "type": "bool", "help": "do not split message and graph",
+ "url": "Why-am-I-getting-two-messages-instead-of-one"},
+ "markdown": {"name": "markdown", "type": "bool", "help": "markdown support", "url": "Markdown-and-HTML"},
+ "html": {"name": "html", "type": "bool", "help": "markdown support", "url": "Markdown-and-HTML"},
+ "signature": {"name": "signature", "type": "str",
+ "help": "bot's signature", "url": "Bot-signature"},
+ "signature_disable": {"name": "signature_disable", "type": "bool",
+ "help": "enables/disables bot's signature", "url": "Bot-signature"},
+ "graph_buttons": {"name": "graph_buttons", "type": "bool",
+ "help": "activates buttons under graph, could be using in ZbxTgDaemon",
+ "url": "Interactive-bot"},
+ "external_image": {"name": "extimg", "type": "str",
+ "help": "should be url; attaches external image from different source",
+ "url": "External-image-as-graph"},
+ "to": {"name": "to", "type": "str", "help": "rewrite zabbix username, use that instead of arguments",
+ "url": "Custom-to-and-to_group"},
+ "to_group": {"name": "to_group", "type": "str",
+ "help": "rewrite zabbix username, use that instead of arguments", "url": "Custom-to-and-to_group"},
+ "forked": {"name": "forked", "type": "bool", "help": "internal variable, do not use it. Ever.", "url": ""},
+ }
+
+ if len(args) < 4:
+ do_not_exit = False
+ if "--features" in args:
+ print(("List of available settings, see {0}/Settings\n---".format(url_wiki_base)))
+ for sett, proprt in list(settings_description.items()):
+ print(("{0}: {1}\ndoc: {2}/{3}\n--".format(sett, proprt["help"], url_wiki_base, proprt["url"])))
+
+ elif "--show-settings" in args:
+ do_not_exit = True
+ print_message("Settings: " + str(json.dumps(settings, indent=2)))
+
+ else:
+ print(("Hi. You should provide at least three arguments.\n"
+ "zbxtg.py [TO] [SUBJECT] [BODY]\n\n"
+ "1. Read main page and/or wiki: {0} + {1}\n"
+ "2. Public Telegram group (discussion): {2}\n"
+ "3. Public Telegram channel: {3}\n"
+ "4. Try dev branch for test purposes (new features, etc): {0}/tree/dev"
+ .format(url_github, url_wiki_base, url_tg_group, url_tg_channel)))
+ if not do_not_exit:
+ sys.exit(0)
+
+
+ zbx_to = args[1]
+ zbx_subject = args[2]
+ zbx_body = args[3]
tg = TelegramAPI(key=zbxtg_settings.tg_key)
+ tg.tmp_dir = tmp_dir
tg.tmp_uids = tmp_uids
if zbxtg_settings.proxy_to_tg:
+ proxy_to_tg = zbxtg_settings.proxy_to_tg
+ if not proxy_to_tg.find("http") and not proxy_to_tg.find("socks"):
+ proxy_to_tg = "https://" + proxy_to_tg
tg.proxies = {
- "http": "http://{0}/".format(zbxtg_settings.proxy_to_tg),
- "https": "https://{0}/".format(zbxtg_settings.proxy_to_tg)
- }
+ "https": "{0}".format(proxy_to_tg),
+ }
- zbx = ZabbixAPI(server=zbxtg_settings.zbx_server, username=zbxtg_settings.zbx_api_user,
+ zbx = ZabbixWeb(server=zbxtg_settings.zbx_server, username=zbxtg_settings.zbx_api_user,
password=zbxtg_settings.zbx_api_pass)
+ zbx.tmp_dir = tmp_dir
+
+ # workaround for Zabbix 4.x
+ zbx_version = 3
+
+ try:
+ zbx_version = zbxtg_settings.zbx_server_version
+ except:
+ pass
+
if zbxtg_settings.proxy_to_zbx:
zbx.proxies = {
"http": "http://{0}/".format(zbxtg_settings.proxy_to_zbx),
"https": "https://{0}/".format(zbxtg_settings.proxy_to_zbx)
- }
+ }
+
+ # https://github.com/ableev/Zabbix-in-Telegram/issues/55
+ try:
+ if zbxtg_settings.zbx_basic_auth:
+ zbx.basic_auth_user = zbxtg_settings.zbx_basic_auth_user
+ zbx.basic_auth_pass = zbxtg_settings.zbx_basic_auth_pass
+ except:
+ pass
try:
zbx_api_verify = zbxtg_settings.zbx_api_verify
@@ -281,42 +638,38 @@ def main():
except:
pass
+ map = Maps()
+ # api key to resolve address to coordinates via google api
+ try:
+ if zbxtg_settings.google_maps_api_key:
+ map.key = zbxtg_settings.google_maps_api_key
+ if zbxtg_settings.proxy_to_tg:
+ map.proxies = {
+ "http": "http://{0}/".format(zbxtg_settings.proxy_to_tg),
+ "https": "https://{0}/".format(zbxtg_settings.proxy_to_tg)
+ }
+ except:
+ pass
+
zbxtg_body = (zbx_subject + "\n" + zbx_body).splitlines()
zbxtg_body_text = []
- settings = {
- "zbxtg_itemid": "0", # itemid for graph
- "zbxtg_title": None, # title for graph
- "zbxtg_image_period": "3600",
- "zbxtg_image_width": "900",
- "zbxtg_image_height": "200",
- "tg_method_image": False, # if True - default send images, False - send text
- "tg_chat": False, # send message to chat or in private
- "is_debug": False,
- "is_channel": False,
- "disable_web_page_preview": False,
- }
- settings_description = {
- "itemid": {"name": "zbxtg_itemid", "type": "int"},
- "title": {"name": "zbxtg_title", "type": "str"},
- "graphs_period": {"name": "zbxtg_image_period", "type": "int"},
- "graphs_width": {"name": "zbxtg_image_width", "type": "int"},
- "graphs_height": {"name": "zbxtg_image_height", "type": "int"},
- "graphs": {"name": "tg_method_image", "type": "bool"},
- "chat": {"name": "tg_chat", "type": "bool"},
- "debug": {"name": "is_debug", "type": "bool"},
- "channel": {"name": "is_channel", "type": "bool"},
- "disable_web_page_preview": {"name": "disable_web_page_preview", "type": "bool"},
- }
-
for line in zbxtg_body:
if line.find(zbxtg_settings.zbx_tg_prefix) > -1:
- setting = re.split("[\s\:\=]+", line, maxsplit=1)
+ setting = re.split("[\s:=]+", line, maxsplit=1)
key = setting[0].replace(zbxtg_settings.zbx_tg_prefix + ";", "")
- if len(setting) > 1 and len(setting[1]) > 0:
+ if key not in settings_description:
+ if "--debug" in args:
+ print_message("[ERROR] There is no '{0}' method, use --features to get help".format(key))
+ continue
+ if settings_description[key]["type"] == "list":
+ value = setting[1].split(",")
+ elif len(setting) > 1 and len(setting[1]) > 0:
value = setting[1]
- else:
+ elif settings_description[key]["type"] == "bool":
value = True
+ else:
+ value = settings[settings_description[key]["name"]]
if key in settings_description:
settings[settings_description[key]["name"]] = value
else:
@@ -324,16 +677,19 @@ def main():
tg_method_image = bool(settings["tg_method_image"])
tg_chat = bool(settings["tg_chat"])
+ tg_group = bool(settings["tg_group"])
is_debug = bool(settings["is_debug"])
is_channel = bool(settings["is_channel"])
disable_web_page_preview = bool(settings["disable_web_page_preview"])
+ is_single_message = bool(settings["is_single_message"])
# experimental way to send message to the group https://github.com/ableev/Zabbix-in-Telegram/issues/15
- if sys.argv[0].split("/")[-1] == "zbxtg_group.py" or "--group" in sys.argv or tg_chat:
+ if args[0].split("/")[-1] == "zbxtg_group.py" or "--group" in args or tg_chat or tg_group:
tg_chat = True
+ tg_group = True
tg.type = "group"
- if "--debug" in sys.argv or is_debug:
+ if "--debug" in args or is_debug:
is_debug = True
tg.debug = True
zbx.debug = True
@@ -342,20 +698,41 @@ def main():
log_file = tmp_dir + ".debug." + hash_ts + ".log"
#print_message(log_file)
- if "--markdown" in sys.argv:
+ if "--markdown" in args or settings["markdown"]:
tg.markdown = True
- if "--html" in sys.argv:
+ if "--html" in args or settings["html"]:
tg.html = True
- if "--channel" in sys.argv or is_channel:
+ if "--channel" in args or is_channel:
tg.type = "channel"
- if "--disable_web_page_preview" in sys.argv or disable_web_page_preview:
+ if "--disable_web_page_preview" in args or disable_web_page_preview:
if is_debug:
print_message("'disable_web_page_preview' option has been enabled")
tg.disable_web_page_preview = True
+ if "--graph_buttons" in args or settings["graph_buttons"]:
+ tg.image_buttons = True
+
+ if "--forked" in args:
+ settings["forked"] = True
+
+ if "--tg-key" in args:
+ tg.key = args[args.index("--tg-key") + 1]
+
+ location_coordinates = {"latitude": None, "longitude": None}
+ if settings["lat"] > 0 and settings["lat"] > 0:
+ location_coordinates = {"latitude": settings["lat"], "longitude": settings["lon"]}
+ tg.location = location_coordinates
+ else:
+ if settings["location"]:
+ location_coordinates = map.get_coordinates_by_address(settings["location"])
+ if location_coordinates:
+ settings["lat"] = location_coordinates["latitude"]
+ settings["lon"] = location_coordinates["longitude"]
+ tg.location = location_coordinates
+
if not os.path.isdir(tmp_dir):
if is_debug:
print_message("Tmp dir doesn't exist, creating new one...")
@@ -369,13 +746,62 @@ def main():
if is_debug:
print_message("Using {0} as a temporary dir".format(tmp_dir))
+ done_all_work_in_the_fork = False
+ # issue75
+
+ to_types = ["to", "to_group", "to_channel"]
+ to_types_to_telegram = {"to": "private", "to_group": "group", "to_channel": "channel"}
+ multiple_to = {}
+ for i in to_types:
+ multiple_to[i]=[]
+
+ for t in to_types:
+ try:
+ if settings[t] and not settings["forked"]:
+ # zbx_to = settings["to"]
+ multiple_to[t] = re.split(",", settings[t])
+ except KeyError:
+ pass
+
+ # example:
+ # {'to_channel': [], 'to': ['usr1', 'usr2', 'usr3'], 'to_group': []}
+
+ if (sum([len(v) for k, v in list(multiple_to.items())])) == 1:
+ # if we have only one recipient, we don't need fork to send message, just re-write "to" vaiable
+ tmp_max = 0
+ for t in to_types:
+ if len(multiple_to[t]) > tmp_max:
+ tmp_max = len(multiple_to[t])
+ tg.type = to_types_to_telegram[t]
+ zbx_to = multiple_to[t][0]
+ else:
+ for t in to_types:
+ for i in multiple_to[t]:
+ args_new = list(args)
+ args_new[1] = i
+ if t == "to_group":
+ args_new.append("--group")
+ args_new.append("--forked")
+ args_new.insert(0, sys.executable)
+ if is_debug:
+ print_message("Fork for custom recipient ({1}), new args: {0}".format(args_new,
+ to_types_to_telegram[t]))
+ subprocess.call(args_new)
+ done_all_work_in_the_fork = True
+
+ if done_all_work_in_the_fork:
+ sys.exit(0)
+
uid = None
if tg.type == "channel":
uid = zbx_to
- else:
+ if tg.type == "private":
zbx_to = zbx_to.replace("@", "")
+ if zbx_to.isdigit():
+ uid = zbx_to
+
if not uid:
uid = tg.get_uid_from_cache(zbx_to)
@@ -395,59 +821,120 @@ def main():
# add signature, turned off by default, you can turn it on in config
try:
- if zbxtg_settings.zbx_tg_signature:
+ if "--signature" in args or settings["signature"] or zbxtg_settings.zbx_tg_signature\
+ and not "--signature_disable" in args and not settings["signature_disable"]:
+ if "--signature" in args:
+ settings["signature"] = args[args.index("--signature") + 1]
+ if not settings["signature"]:
+ settings["signature"] = zbxtg_settings.zbx_server
zbxtg_body_text.append("--")
- zbxtg_body_text.append(zbxtg_settings.zbx_server)
+ zbxtg_body_text.append(settings["signature"])
except:
pass
# replace text with emojis
+ internal_using_emoji = False # I hate that, but... https://github.com/ableev/Zabbix-in-Telegram/issues/152
if hasattr(zbxtg_settings, "emoji_map"):
zbxtg_body_text_emoji_support = []
for l in zbxtg_body_text:
l_new = l
- for k, v in zbxtg_settings.emoji_map.iteritems():
+ for k, v in list(zbxtg_settings.emoji_map.items()):
l_new = l_new.replace("{{" + k + "}}", v)
zbxtg_body_text_emoji_support.append(l_new)
+ if len("".join(zbxtg_body_text)) - len("".join(zbxtg_body_text_emoji_support)):
+ internal_using_emoji = True
zbxtg_body_text = zbxtg_body_text_emoji_support
- if not tg_method_image:
- result = tg.send_message(uid, zbxtg_body_text)
- if not result["ok"]:
- if result["description"] == "[Error]: Bad Request: group chat is migrated to supergroup chat":
- migrate_to_chat_id = result["parameters"]["migrate_to_chat_id"]
- tg.update_cache_uid(zbx_to, uid, message="Group chat is migrated to supergroup, updating cache file")
+ if not is_single_message:
+ tg.send_message(uid, zbxtg_body_text)
+ if not tg.ok:
+ # first case Б─⌠ if group has been migrated to a supergroup, we need to update chat_id of that group
+ if tg.error.find("migrated") > -1 and tg.error.find("supergroup") > -1:
+ migrate_to_chat_id = tg.result["parameters"]["migrate_to_chat_id"]
+ tg.update_cache_uid(zbx_to, migrate_to_chat_id, message="Group chat is migrated to supergroup, "
+ "updating cache file")
uid = migrate_to_chat_id
- result = tg.send_message(uid, zbxtg_body_text)
- else:
+ tg.send_message(uid, zbxtg_body_text)
+
+ # another case if markdown is enabled and we got parse error, try to remove "bad" symbols from message
+ if tg.markdown and tg.error.find("Can't find end of the entity starting at byte offset") > -1:
+ markdown_warning = "Original message has been fixed due to {0}. " \
+ "Please, fix the markdown, it's slowing down messages sending."\
+ .format(url_wiki_base + "/" + settings_description["markdown"]["url"])
+ markdown_fix_attempts = 0
+ while not tg.ok and markdown_fix_attempts != 3:
+ offset = re.search("Can't find end of the entity starting at byte offset ([0-9]+)", tg.error).group(1)
+ zbxtg_body_text = markdown_fix(zbxtg_body_text, offset, emoji=internal_using_emoji) + \
+ ["\n"] + [markdown_warning]
+ tg.disable_web_page_preview = True
+ tg.send_message(uid, zbxtg_body_text)
+ markdown_fix_attempts += 1
+ if tg.ok:
+ print_message(markdown_warning)
+
+ if is_debug:
+ print((tg.result))
+
+ if settings["zbxtg_image_age"]:
+ age_sec = age2sec(settings["zbxtg_image_age"])
+ if age_sec > 0 and age_sec > 3600:
+ settings["zbxtg_image_period"] = age_sec
+
+ message_id = 0
+ if tg_method_image:
zbx.login()
if not zbx.cookie:
- print_message("Login to Zabbix web UI has failed, check manually...")
+ text_warn = "Login to Zabbix web UI has failed (web url, user or password are incorrect), "\
+ "unable to send graphs check manually"
+ tg.send_message(uid, [text_warn])
+ print_message(text_warn)
else:
- zbxtg_file_img = zbx.graph_get(settings["zbxtg_itemid"], settings["zbxtg_image_period"],
- settings["zbxtg_title"], settings["zbxtg_image_width"],
- settings["zbxtg_image_height"], tmp_dir)
- #zbxtg_body_text, is_modified = list_cut(zbxtg_body_text, 200)
- result = tg.send_message(uid, zbxtg_body_text)
- message_id = result["result"]["message_id"]
+ if not settings["extimg"]:
+ zbxtg_file_img = zbx.graph_get(settings["zbxtg_itemid"], settings["zbxtg_image_period"],
+ settings["zbxtg_title"], settings["zbxtg_image_width"],
+ settings["zbxtg_image_height"], version=zbx_version)
+ else:
+ zbxtg_file_img = external_image_get(settings["extimg"], tmp_dir=zbx.tmp_dir)
+ zbxtg_body_text, is_modified = list_cut(zbxtg_body_text, 200)
+ if tg.ok:
+ message_id = tg.result["result"]["message_id"]
tg.reply_to_message_id = message_id
- tg.disable_notification = True
if not zbxtg_file_img:
- tg.send_message(uid, ["Can't get graph image, check script manually, see logs, or disable graphs"])
- print_message("Can't get image, check URL manually")
+ text_warn = "Can't get graph image, check script manually, see logs, or disable graphs"
+ tg.send_message(uid, [text_warn])
+ print_message(text_warn)
else:
-
- zbxtg_body_text = ""
- """
- if is_modified:
- print_message("probably you will see MEDIA_CAPTION_TOO_LONG error, "
- "the message has been cut to 200 symbols, "
- "https://github.com/ableev/Zabbix-in-Telegram/issues/9"
- "#issuecomment-166895044")
- """
- if tg.send_photo(uid, zbxtg_body_text, zbxtg_file_img):
+ if not is_single_message:
+ zbxtg_body_text = ""
+ else:
+ if is_modified:
+ text_warn = "probably you will see MEDIA_CAPTION_TOO_LONG error, "\
+ "the message has been cut to 200 symbols, "\
+ "https://github.com/ableev/Zabbix-in-Telegram/issues/9"\
+ "#issuecomment-166895044"
+ print_message(text_warn)
+ if not is_single_message:
+ tg.disable_notification = True
+ tg.send_photo(uid, zbxtg_body_text, zbxtg_file_img)
+ if tg.ok:
+ settings["zbxtg_body_text"] = zbxtg_body_text
os.remove(zbxtg_file_img)
-
+ else:
+ if tg.error.find("PHOTO_INVALID_DIMENSIONS") > -1:
+ if not tg.disable_web_page_preview:
+ tg.disable_web_page_preview = True
+ text_warn = "Zabbix user couldn't get graph (probably has no rights to get data from host), " \
+ "check script manually, see {0}".format(url_wiki_base + "/" +
+ settings_description["graphs"]["url"])
+ tg.send_message(uid, [text_warn])
+ print_message(text_warn)
+ if tg.location and location_coordinates["latitude"] and location_coordinates["longitude"]:
+ tg.reply_to_message_id = message_id
+ tg.disable_notification = True
+ tg.send_location(to=uid, coordinates=location_coordinates)
+
+ if "--show-settings" in args:
+ print_message("Settings: " + str(json.dumps(settings, indent=2)))
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff --git a/zbxtg.sh b/zbxtg.sh
deleted file mode 100755
index f9c9663..0000000
--- a/zbxtg.sh
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/bin/bash
-
-. $(dirname "$0")/tg_vars.cfg
-
-CURL_TG="${CURL} https://api.telegram.org/bot${TG_KEY}"
-
-TMP_DIR="/tmp/${ZBX_TG_PREFIX}"
-[ ! -d "${TMP_DIR}" ] && (mkdir -p ${TMP_DIR} || TMP_DIR="/tmp")
-TMP_COOKIE="${TMP_DIR}/cookie.txt"
-TMP_UIDS="${TMP_DIR}/uids.txt"
-
-TS="`date +%s_%N`_$RANDOM"
-LOG="/dev/null"
-
-IS_DEBUG () {
- if [ "${ISDEBUG}" == "TRUE" ]
- then
- return 0
- else
- return 1
- fi
-}
-
-
-login() {
- # grab cookie for downloading image
- IS_DEBUG && echo "${CURL} --cookie-jar ${TMP_COOKIE} --request POST --data \"name=${ZBX_API_USER}&password=${ZBX_API_PASS}&enter=Sign%20in\" ${ZBX_SERVER}/" >>${LOG}
- ${CURL} --cookie-jar ${TMP_COOKIE} --request POST --data "name=${ZBX_API_USER}&password=${ZBX_API_PASS}&enter=Sign%20in" ${ZBX_SERVER}/
-}
-
-get_image() {
- URL=$1
- URL=$(echo "${URL}" | sed -e 's/\ /%20/g')
- IMG_NAME=$2
- # downloads png graph and saves it to temporary path
- IS_DEBUG && echo "${CURL} --cookie ${TMP_COOKIE} --globoff \"${URL}\" -o ${IMG_NAME}" >>${LOG}
- ${CURL} --cookie ${TMP_COOKIE} --globoff "${URL}" -o ${IMG_NAME}
-}
-
-TO=$1
-SUBJECT=$2
-BODY=$3
-
-TG_CHAT=0 # send message to chat or to private chat to user
-METHOD="txt" # sendMessage (simple text) or sendPhoto (attached image)
-
-echo "${BODY}" | grep -q "${ZBX_TG_PREFIX};graphs" && METHOD="image"
-echo "${BODY}" | grep -q "${ZBX_TG_PREFIX};chat" && TG_CHAT=1
-echo "${BODY}" | grep -q "${ZBX_TG_PREFIX};debug" && ISDEBUG="TRUE"
-
-IS_DEBUG && LOG="${TMP_DIR}/debug.${TS}.log"
-IS_DEBUG && echo -e "TMP_DIR=${TMP_DIR}\nTMP_COOKIE=${TMP_COOKIE}\nTMP_UIDS=${TMP_UIDS}" >>${LOG}
-
-if [ "${TG_CHAT}" -eq 1 ]
-then
- TG_CONTACT_TYPE="chat"
-else
- TG_CONTACT_TYPE="user"
-fi
-
-TG_CHAT_ID=$(cat ${TMP_UIDS} | awk -F ';' '{if ($1 == "'${TO}'" && $2 == "'${TG_CONTACT_TYPE}'") print $3}' | tail -1)
-
-if [ -z "${TG_CHAT_ID}" ]
-then
- TG_UPDATES=$(${CURL_TG}/getUpdates)
- if [ "${TG_CHAT}" -eq 1 ]
- then
- TG_CHAT_ID=$(echo "${TG_UPDATES}" | sed -e 's/["}{]//g' | awk -F ',' '{if ($8 == "type:group" && $7 == "title:'${TO}'") {gsub("chat:id:", "", $6); print $6}}' | tail -1)
- else
- TG_CHAT_ID=$(echo "${TG_UPDATES}" | sed -e 's/["}{]//g' | awk -F ',' '{if ($10 == "type:private" && $5 == "username:'${TO}'") {gsub("chat:id:", "", $6); print $6}}' | tail -1)
- fi
- echo "${TO};${TG_CONTACT_TYPE};${TG_CHAT_ID}" >>${TMP_UIDS}
-fi
-
-IS_DEBUG && echo "TG_CHAT_ID: ${TG_CHAT_ID}" >>${LOG}
-
-TG_TEXT=$(echo "${BODY}" | grep -vE "^${ZBX_TG_PREFIX};"; echo "--"; echo "${ZBX_SERVER}")
-
-case "${METHOD}" in
-
- "txt")
- TG_MESSAGE=$(echo -e "${SUBJECT}\n${TG_TEXT}")
- IS_DEBUG && echo "${CURL_TG}/sendMessage -F \"chat_id=${TG_CHAT_ID}\" -F \"text=${TG_MESSAGE}\"" >>${LOG}
- ${CURL_TG}/sendMessage -F "chat_id=${TG_CHAT_ID}" -F "text=${TG_MESSAGE}" >>${LOG} 2>&1
- ;;
-
- "image")
- PERIOD=3600 # default period
- echo "${BODY}" | grep -q "^${ZBX_TG_PREFIX};graphs_period" && PERIOD=$(echo "${BODY}" | awk -F "${ZBX_TG_PREFIX};graphs_period=" '{if ($2 != "") print $2}' | tail -1 | grep -Eo '[0-9]+' || echo 3600)
- ZBX_ITEMID=$(echo "${BODY}" | awk -F "${ZBX_TG_PREFIX};itemid:" '{if ($2 != "") print $2}' | tail -1 | grep -Eo '[0-9]+')
- ZBX_TITLE=$(echo "${BODY}" | awk -F "${ZBX_TG_PREFIX};title:" '{if ($2 != "") print $2}' | tail -1)
- URL="${ZBX_SERVER}/chart3.php?period=${PERIOD}&name=${ZBX_TITLE}&width=900&height=200&graphtype=0&legend=1&items[0][itemid]=${ZBX_ITEMID}&items[0][sortorder]=0&items[0][drawtype]=5&items[0][color]=00CC00"
- IS_DEBUG && echo "Zabbix graph URL: ${URL}" >> ${LOG}
- login
- CACHE_IMAGE="${TMP_DIR}/graph.${ZBX_ITEMID}.png"
- IS_DEBUG && echo "Image cached to ${CACHE_IMAGE} and wasn't deleted" >> ${LOG}
- get_image "${URL}" ${CACHE_IMAGE}
- TG_CAPTION_ORIG=$(echo -e "${SUBJECT}\n${TG_TEXT}")
- TG_CAPTION=$(echo -e $(echo "${TG_CAPTION_ORIG}" | sed ':a;N;$!ba;s/\n/\\n/g' | awk '{print substr( $0, 0, 200 )}'))
- if [ "${TG_CAPTION}" != "${TG_CAPTION_ORIG}" ]
- then
- echo "${ZBX_TG_PREFIX}: probably you will see MEDIA_CAPTION_TOO_LONG error, the message has been cut to 200 symbols, https://github.com/ableev/Zabbix-in-Telegram/issues/9#issuecomment-166895044"
- fi
- IS_DEBUG && echo "${CURL_TG}/sendPhoto -F \"chat_id=${TG_CHAT_ID}\" -F \"caption=${TG_CAPTION}\" -F \"photo=@${CACHE_IMAGE}\"" >>${LOG}
- ${CURL_TG}/sendPhoto -F "chat_id=${TG_CHAT_ID}" -F "caption=${TG_CAPTION}" -F "photo=@${CACHE_IMAGE}" >>${LOG} 2>&1
- IS_DEBUG || rm ${CACHE_IMAGE}
- ;;
-
-esac
-
-echo >>${LOG}
diff --git a/zbxtg_settings.example.py b/zbxtg_settings.example.py
index 4b313df..4b9e656 100644
--- a/zbxtg_settings.example.py
+++ b/zbxtg_settings.example.py
@@ -3,27 +3,66 @@
tg_key = "XYZ" # telegram bot api key
zbx_tg_prefix = "zbxtg" # variable for separating text from script info
-zbx_tg_tmp_dir = "/tmp/" + zbx_tg_prefix # directory for saving caches, uids, cookies, etc.
+zbx_tg_tmp_dir = "/var/tmp/" + zbx_tg_prefix # directory for saving caches, uids, cookies, etc.
zbx_tg_signature = False
-zbx_server = "http://localhost" # zabbix server full url
+zbx_tg_update_messages = True
+zbx_tg_matches = {
+ "problem": "PROBLEM: ",
+ "ok": "OK: "
+}
+
+zbx_server = "http://127.0.0.1/zabbix/" # zabbix server full url
zbx_api_user = "api"
zbx_api_pass = "api"
zbx_api_verify = True # True - do not ignore self signed certificates, False - ignore
+#zbx_server_version = 2 # for Zabbix 2.x version
+zbx_server_version = 3 # for Zabbix 3.x version, by default, not everyone updated to 4.x yet
+#zbx_server_version = 4 # for Zabbix 4.x version, default will be changed in the future with this
+
+zbx_basic_auth = False
+zbx_basic_auth_user = "zabbix"
+zbx_basic_auth_pass = "zabbix"
+
proxy_to_zbx = None
proxy_to_tg = None
-#proxy_to_zbx = "proxy.local:3128"
-#proxy_to_tg = "proxy.local:3128"
+# proxy_to_zbx = "http://proxy.local:3128"
+# proxy_to_tg = "https://proxy.local:3128"
+
+# proxy_to_tg = "socks5://user1:password2@hostname:port" # socks5 with username and password
+# proxy_to_tg = "socks5://hostname:port" # socks5 without username and password
+# proxy_to_tg = "socks5h://hostname:port" # hostname resolution on SOCKS proxy.
+ # This helps when internet provider alter DNS queries.
+ # Found here: https://stackoverflow.com/a/43266186/957508
+
+google_maps_api_key = None # get your key, see https://developers.google.com/maps/documentation/geocoding/intro
+
+zbx_tg_daemon_enabled = False
+zbx_tg_daemon_enabled_ids = [6931850, ]
+zbx_tg_daemon_enabled_users = ["ableev", ]
+zbx_tg_daemon_enabled_chats = ["Zabbix in Telegram Script", ]
+
+zbx_db_host = "localhost"
+zbx_db_database = "zabbix"
+zbx_db_user = "zbxtg"
+zbx_db_password = "zbxtg"
+
emoji_map = {
- "ok": "Б°┘",
- "problem": "Б²≈",
+ "Disaster": "П÷■╔",
+ "High": "П÷⌡▒",
+ "Average": "Б²≈",
+ "Warning": "Б ═О╦▐",
+ "Information": "Б└╧О╦▐",
+ "Not classified": "П÷■≤",
+ "OK": "Б°┘",
+ "PROBLEM": "Б²≈",
"info": "Б└╧О╦▐",
- "warning": "Б ═О╦▐",
- "disaster": "Б²▄",
+ "WARNING": "Б ═О╦▐",
+ "DISASTER": "Б²▄",
"bomb": "П÷▓ё",
"fire": "П÷■╔",
"hankey": "П÷▓╘",
-}
\ No newline at end of file
+}