├── slackmonitor.JPG ├── certificateexpiration.py ├── README.md └── uptimemonitor.py /slackmonitor.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndreiD/SlackUptimeMonitor/HEAD/slackmonitor.JPG -------------------------------------------------------------------------------- /certificateexpiration.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | import datetime 6 | import ssl 7 | import OpenSSL 8 | import socket 9 | 10 | """Checks server SSL certificate for expiry.""" 11 | 12 | 13 | def check(): 14 | hostname = "your_server.com" 15 | port = 443 16 | 17 | num_days = 7 18 | cert = ssl.get_server_certificate( 19 | (hostname, port), ssl_version=ssl.PROTOCOL_TLSv1) 20 | x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert) 21 | expiry_date = x509.get_notAfter() 22 | print(str(expiry_date)) 23 | assert expiry_date, "Cert doesn't have an expiry date." 24 | 25 | ssl_date_fmt = r'%Y%m%d%H%M%SZ' 26 | expires = datetime.datetime.strptime(str(expiry_date)[2:-1], ssl_date_fmt) 27 | remaining = (expires - datetime.datetime.utcnow()).days 28 | 29 | if remaining <= num_days: 30 | print("ALERTING!") 31 | else: 32 | print("Not alerting. You have " + str(remaining) + " days") 33 | 34 | 35 | check() 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Website Down Notifier on Slack 2 | 3 | 4 | slack website up down notifier uptime ping 5 | 6 | #### A simple, one file script that notifies you on slack when your website is down. 7 | 8 | ## Configuration 9 | 10 | ### Step 1 - Get the script 11 | 12 | Simply copy paste the script uptimemonitor.py into your server. After you test it add it to cron with your preferred check interval 13 | 14 | Example for checks every minute 15 | ~~~~ 16 | $crontab -e 17 | * * * * * /home/uptimemonitor/uptimemonitor.py > /root/uptimenotifier.log 18 | $service cron restart 19 | $tail -f /root/uptimenotifier.log 20 | ~~~~ 21 | 22 | Note that the script is written in Python3.5. 23 | 24 | ### Step 2 - Setup the config variables 25 | 26 | 27 | URLS_TO_CHECK = ["http://facebook.com", 28 | "https://youtube.com:9540"] 29 | 30 | #### You have to have a token so you can send messages to a slack channel! Get one here 31 | https://api.slack.com/docs/oauth-test-tokens 32 | 33 | You need then to export it as an environmental variable or hardcoded 34 | 35 | ~~~~ 36 | export SLACK_TOKEN = 'your_token_here' 37 | ~~~~ 38 | 39 | SLACK_TOKEN = os.environ.get('SLACK_TOKEN') 40 | 41 | #### Where you want to receive your notifications ? 42 | 43 | you can get it using list_channels and channel_info or click on the channel name 44 | 45 | click on add app or integration and you can view it's id in the webpage redirection (you have to be fast because it redirects it to another page) 46 | 47 | ~~~~ 48 | CHANNEL_ID = "G2LCBCXGF" 49 | ~~~~ 50 | 51 | 52 | ### Step 3 - ??? 53 | 54 | ### Step 4 - Profit 55 | 56 | ### Remember to star this repository and fork it. 57 | 58 | #### Bugs / Issues / Suggestions -> write me a message on "Issues" 59 | 60 | 61 | -------------------------------------------------------------------------------- /uptimemonitor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | #-*- coding: utf-8 -*- 3 | from slackclient import SlackClient 4 | import requests 5 | import datetime 6 | import pickle 7 | 8 | # ================== CONFIGURATION ================== 9 | 10 | URLS_TO_CHECK = ["http://example.com", 11 | "https://anotherone.net:1337"] 12 | 13 | 14 | # You have to have a token so you can send messages to a slack channel! 15 | # https://api.slack.com/docs/oauth-test-tokens 16 | SLACK_TOKEN = "YOUR_TOKEN_HERE" 17 | 18 | # Where you want to receive your notifications ? 19 | 20 | # you can get it using list_channels and channel_info or click on the channel name 21 | # click on add app or integration and you can view it's id in the webpage redirection (you have to be fast because it redirects it to another page) 22 | CHANNEL_ID = "G2LCBCXGF" 23 | 24 | # ================== END CONFIGURATION ================== 25 | 26 | slack_client = SlackClient(SLACK_TOKEN) 27 | 28 | 29 | # ================== SLACK FUNCTIONS ================== 30 | def list_channels(): 31 | channels_call = slack_client.api_call("channels.list") 32 | if channels_call['ok']: 33 | return channels_call['channels'] 34 | return None 35 | 36 | 37 | def channel_info(channel_id): 38 | channel_info = slack_client.api_call("channels.info", channel=channel_id) 39 | if channel_info: 40 | return channel_info['channel'] 41 | return None 42 | 43 | 44 | def send_message(channel_id, message): 45 | response = slack_client.api_call( 46 | "chat.postMessage", 47 | channel=channel_id, 48 | text=message, 49 | username='UptimeMonitor', 50 | icon_emoji=':robot_face:' 51 | ) 52 | if not response['ok']: 53 | print("Error sending notification to Slack -------> " + response['error']) 54 | 55 | 56 | # ================== NOTIFY FUNCTIONS ================== 57 | def down_notifier(the_url): 58 | try: 59 | old_status_file = pickle.load(open("status.p", "rb")) 60 | except Exception as ex: 61 | print("The status.p file was not found. it will be recreated." + str(ex)) 62 | send_message(CHANNEL_ID, ":no_entry: " + the_url + " is down.") 63 | return 64 | 65 | # in case we just added the url to our database 66 | if the_url not in old_status_file: 67 | send_message(CHANNEL_ID, ":no_entry: " + the_url + " is down.") 68 | return 69 | 70 | # if it's already in the database and last status was up 71 | if (the_url in old_status_file) and (old_status_file[the_url]['status'] == "up"): 72 | send_message(CHANNEL_ID, ":no_entry: " + the_url + " is down.") 73 | else: 74 | print("already down. skip notifying") 75 | 76 | 77 | # if it was previously down, notify that it's back online 78 | def back_online_notifier(the_url): 79 | print("found " + the_url + " back online.") 80 | try: 81 | old_status_file = pickle.load(open("status.p", "rb")) 82 | except Exception as ex: 83 | print("The status.p file was not found. it will be recreated." + str(ex)) 84 | return 85 | 86 | if (the_url in old_status_file) and (old_status_file[the_url]['status'] == "down"): 87 | it_was_down_time = old_status_file[the_url]['time'] 88 | current_time = datetime.datetime.now().replace(microsecond=0) 89 | send_message(CHANNEL_ID, ":herb: " + the_url + " is back online. It was down for " + str(current_time - it_was_down_time)) 90 | else: 91 | print("skipping notifying that the url is online") 92 | 93 | 94 | # --- getting only the head --- 95 | def get_status_code(xurl): 96 | try: 97 | response = requests.head(xurl, allow_redirects=False, timeout=3) 98 | return response.status_code 99 | except: 100 | return -1 101 | 102 | 103 | # ~~~~~~~~~~~~~~~~~~~~~~~~ THE MAIN ~~~~~~~~~~~~~~~~~~~~~~~~ 104 | if __name__ == '__main__': 105 | 106 | # First test if you have the correct token 107 | # print(slack_client.api_call("auth.test")) 108 | 109 | status_file = {} 110 | 111 | for url in URLS_TO_CHECK: 112 | if get_status_code(url) != 200: 113 | print(url + " is down.") 114 | down_notifier(url) 115 | status_file[url] = {'status': "down", 'time': datetime.datetime.now().replace(microsecond=0)} 116 | else: 117 | back_online_notifier(url) 118 | status_file[url] = {'status': "up", 'time': datetime.datetime.now().replace(microsecond=0)} 119 | 120 | pickle.dump(status_file, open("status.p", "wb")) 121 | --------------------------------------------------------------------------------