paskvil

portcheck.py

python/portcheck.py download

import pygtk
pygtk.require('2.0')
import gtk
import socket
import sys
import pynotify

def check_port(host, port):
    socket.setdefaulttimeout(2.0)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        s.connect((host, port))
        s.shutdown(2)
        return True
    except:
        return False

# list to check; url:port, active - is this record used?, success - result of the last check
# the optional string 'alias' defines the name to show in the menu instead of url:port
sites = [{'url': 'localhost', 'port': 80, 'alias': 'localhost', 'active': True, 'success': None}]

# how often should we check, in sec
check_every = 30.0

class PortsCheckerTray:
    def __init__(self):
        if not pynotify.init("Ports checker"):
            sys.exit(1)

        self.statusIcon = gtk.StatusIcon()
        self.menu = gtk.Menu()

        self.last_result = None
        self.check_ports_cb()

        self.statusIcon.connect('popup-menu', self.popup_menu_cb, self.menu)
        self.statusIcon.set_visible(True)

        gtk.main()

    def set_icon(self, success):
        if success:
            self.statusIcon.set_from_stock(gtk.STOCK_APPLY)
        else:
            self.statusIcon.set_from_stock(gtk.STOCK_STOP)
        # count up/down numbers
        up_cnt = 0
        down_cnt = 0
        for d in sites:
            if not d['active']:
                continue
            if d['success']:
                up_cnt = up_cnt + 1
            else:
                down_cnt = down_cnt + 1
        self.statusIcon.set_visible(True)
        self.statusIcon.set_tooltip("Ports checker [" + str(up_cnt) + " up, " + str(down_cnt) + " down]")

    def get_name(self, site_dict):
        if 'alias' in site_dict:
            return site_dict['alias']
        else:
            return site_dict['url'] + ":" + str(site_dict['port'])

    def populate_menu(self):
        for mi in self.menu.get_children():        # just remove all items from menu, repopulate from scratch
            self.menu.remove(mi)
        for d in sites:
            if d['active'] != True:
                continue
            name = self.get_name(d)
            if d['success']:
                self.menuItem = gtk.MenuItem("up: " + name)
            else:
                self.menuItem = gtk.MenuItem("DOWN: " + name)
            self.menu.append(self.menuItem)
            self.menuItem.show()
        self.menuItem = gtk.SeparatorMenuItem()
        self.menu.append(self.menuItem)
        self.menuItem.show()
        self.menuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
        self.menuItem.connect('activate', self.quit_cb, self.statusIcon)
        self.menu.append(self.menuItem)

    def notify_about(self, changed):
        nots = []
        for d in changed:
            if d['success']:
                msg = self.get_name(d) + " is online."
            else:
                msg = self.get_name(d) + " is OFFLINE."
            nots.append(msg)
        n = pynotify.Notification("Ports checker", "\n".join(nots))
        return n.show()

    def check_ports_cb(self):
        global sites
        #for d in sites:
        #    print d
        changed = []
        all_passed = True
        for d in sites:
            if d['active'] != True:
                continue
            ret = check_port(d['url'], d['port'])
            if d['success'] != ret:
                d['success'] = ret
                changed.append(d)
            if ret == False:
                all_passed = False

        # create list of checked sites in the menu, based on the results
        if changed != []:
            self.populate_menu()
            self.notify_about(changed)

        # update the status icon if the overall result changed
        if self.last_result != all_passed:
            self.set_icon(all_passed)
            self.last_result = all_passed

        self.statusIcon.connect('popup-menu', self.popup_menu_cb, self.menu)
        self.statusIcon.set_visible(True)

        # we're ready for another round of checks in 5 secs
        global check_every
        gtk.timeout_add(int(check_every * 1000), self.check_ports_cb)

    def quit_cb(self, widget, data = None):
        gtk.main_quit()

    def popup_menu_cb(self, widget, button, time, data = None):
        if button == 3:
            if data:
                data.show_all()
                data.popup(None, None, gtk.status_icon_position_menu,
                        3, time, self.statusIcon)

if __name__ == "__main__":
    portsChecker = PortsCheckerTray()