From a1aed9f721982f1afd89d5f7ac0f0641599f91a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20M=C3=BCller?= Date: Wed, 10 Mar 2021 22:07:52 +0100 Subject: [PATCH] Initial commit --- SQLConnectionHandler.py | 32 ++++++++++++ ServerPingService.py | 14 ++++++ TelegramHandler.py | 17 +++++++ WebsitePingService.py | 17 +++++++ main.py | 108 ++++++++++++++++++++++++++++++++++++++++ requirements.txt | 4 ++ 6 files changed, 192 insertions(+) create mode 100644 SQLConnectionHandler.py create mode 100644 ServerPingService.py create mode 100644 TelegramHandler.py create mode 100644 WebsitePingService.py create mode 100644 main.py create mode 100644 requirements.txt diff --git a/SQLConnectionHandler.py b/SQLConnectionHandler.py new file mode 100644 index 0000000..f12375b --- /dev/null +++ b/SQLConnectionHandler.py @@ -0,0 +1,32 @@ +import pymysql +import os +import logging + +def getConnection() -> pymysql.Connection: + """ + Get a connection to SQL. + This function is used on the vServer for local testing + @return: pymysql connection object + """ + try: + if os.getenv('IS_RASPI'): + conn = pymysql.connect( + user=os.environ['VSERVER_SQL_USER'], + password=os.environ['VSERVER_SQL_PASSWORD'], + host=os.environ['VSERVER_SQL_SERVER'], + port=3306, + database='ServerDowntimeMonitoring' + ) + else: + conn = pymysql.connect( + user=os.environ['PADDY_SQL_USER'], + password=os.environ['PADDY_SQL_PASSWORD'], + host=os.environ['SQL_SERVER'], + port=3306, + database='ServerDowntimeMonitoring' + ) + + return conn + except pymysql.Error as e: + logging.error('SQL Connection error: %s', e) + return None diff --git a/ServerPingService.py b/ServerPingService.py new file mode 100644 index 0000000..10cd54c --- /dev/null +++ b/ServerPingService.py @@ -0,0 +1,14 @@ +import ping3 + + +def ping(host: str) -> int: + """ + Pings the given host and returns the time the ping took ins ms or -1 if the ping was not successful + :param host: + :return: + """ + res = ping3.ping(dest_addr=host, unit='ms') + if res: + return int(res) + else: + return -1 diff --git a/TelegramHandler.py b/TelegramHandler.py new file mode 100644 index 0000000..0a9d947 --- /dev/null +++ b/TelegramHandler.py @@ -0,0 +1,17 @@ +import os +import telegram +import logging + + +class TelegramHandler: + def __init__(self): + token = os.environ['TELEGRAM_PLUTO_BOT_TOKEN'] + if not token: + logging.error('The TELEGRAM_TOKEN must be set') + raise NotImplementedError + + self.bot = telegram.Bot(token=token) + + + def sendMessage(self, recipient: str, message: str): + self.bot.sendMessage(chat_id=recipient, text=message) diff --git a/WebsitePingService.py b/WebsitePingService.py new file mode 100644 index 0000000..21ac161 --- /dev/null +++ b/WebsitePingService.py @@ -0,0 +1,17 @@ +import requests + +def ping(url: str) -> int: + """ + Makes a GET request to the given website and returns the HTTP status code or -1 in case of failure + :param url: The URL of the website to ping + :return: The HTTP status code + """ + try: + res = requests.get(url) + except: + return -1 + + if res: + return res.status_code + else: + return -1 \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..22222af --- /dev/null +++ b/main.py @@ -0,0 +1,108 @@ +import pymysql + +import ServerPingService +import WebsitePingService +import SQLConnectionHandler +import TelegramHandler + +def runPings(): + telegram = TelegramHandler.TelegramHandler() + conn = SQLConnectionHandler.getConnection() + + # Get data from SQL + users = getUsers(conn) + servers = getServersToPing(conn) + websites = getWebsitesToPing(conn) + + # Lists of tuples to write results back to SQL + serverPingResults = [] + websitePingResults = [] + + for server in servers: + ping = ServerPingService.ping(server['hostname']) + if ping != -1: + resTuple = (server['server_id'], True, ping) + else: + resTuple = (server['server_id'], False, None) + telegram.sendMessage(users[server['admin_id']]['telegram_id'], ( + 'Your server {} ({}) is not reachable at the moment. Maybe give it a check.' + ).format(server['name'], server['hostname'])) + serverPingResults.append(resTuple) + + for website in websites: + statusCode = WebsitePingService.ping(website['url']) + if statusCode == 200: + resTuple = (website['website_id'], True, statusCode) + else: + resTuple = (website['website_id'], False, statusCode) + telegram.sendMessage(users[website['admin_id']]['telegram_id'], ( + 'Your website {} ({}) is not reachable at the moment. Maybe give it a check.' + ).format(website['name'], website['url'])) + websitePingResults.append(resTuple) + + cur = conn.cursor() + # Insert server ping results + cur.executemany('INSERT INTO server_pings (server_id, success, milliseconds) VALUES (%s, %s, %s)', serverPingResults) + + # Insert website ping results + cur.executemany('INSERT INTO website_pings (website_id, success, responsecode) VALUES (%s, %s, %s)', websitePingResults) + + conn.commit() + conn.close() + + +def getUsers(conn: pymysql.Connection) -> {}: + cur = conn.cursor() + cur.execute("SELECT user_id, name, telegram_id FROM users") + results = cur.fetchall() + users = {} + cur.close() + + for res in results: + user = {} + user['user_id'] = res[0] + user['name'] = res[1] + user['telegram_id'] = res[2] + users[res[0]] = user + + return users + + +def getServersToPing(conn: pymysql.Connection) -> [{}]: + cur = conn.cursor() + cur.execute("SELECT server_id, admin_id, name, hostname FROM servers") + results = cur.fetchall() + servers = [] + cur.close() + + for res in results: + server = {} + server['server_id'] = res[0] + server['admin_id'] = res[1] + server['name'] = res[2] + server['hostname'] = res[3] + servers.append(server) + + return servers + + +def getWebsitesToPing(conn: pymysql.Connection) -> [{}]: + cur = conn.cursor() + cur.execute("SELECT website_id, admin_id, name, url FROM websites") + results = cur.fetchall() + websites = [] + cur.close() + + for res in results: + website = {} + website['website_id'] = res[0] + website['admin_id'] = res[1] + website['name'] = res[2] + website['url'] = res[3] + websites.append(website) + + return websites + + +if __name__ == '__main__': + runPings() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..113950d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +python-telegram-bot +pymysql +ping3 +requests \ No newline at end of file