001 import pygtk
002 pygtk.require('2.0')
003 import gtk
004 import socket
005 import sys
006 import pynotify
007 
008 def check_port(host, port):
009     socket.setdefaulttimeout(2.0)
010     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
011     try:
012         s.connect((host, port))
013         s.shutdown(2)
014         return True
015     except:
016         return False
017 
018 # list to check; url:port, active - is this record used?, success - result of the last check
019 # the optional string 'alias' defines the name to show in the menu instead of url:port
020 sites = [{'url': 'localhost', 'port': 80, 'alias': 'localhost', 'active': True, 'success': None}]
021 
022 # how often should we check, in sec
023 check_every = 30.0
024 
025 class PortsCheckerTray:
026     def __init__(self):
027         if not pynotify.init("Ports checker"):
028             sys.exit(1)
029 
030         self.statusIcon = gtk.StatusIcon()
031         self.menu = gtk.Menu()
032 
033         self.last_result = None
034         self.check_ports_cb()
035 
036         self.statusIcon.connect('popup-menu', self.popup_menu_cb, self.menu)
037         self.statusIcon.set_visible(True)
038 
039         gtk.main()
040 
041     def set_icon(self, success):
042         if success:
043             self.statusIcon.set_from_stock(gtk.STOCK_APPLY)
044         else:
045             self.statusIcon.set_from_stock(gtk.STOCK_STOP)
046         # count up/down numbers
047         up_cnt = 0
048         down_cnt = 0
049         for d in sites:
050             if not d['active']:
051                 continue
052             if d['success']:
053                 up_cnt = up_cnt + 1
054             else:
055                 down_cnt = down_cnt + 1
056         self.statusIcon.set_visible(True)
057         self.statusIcon.set_tooltip("Ports checker [" + str(up_cnt) + " up, " + str(down_cnt) + " down]")
058 
059     def get_name(self, site_dict):
060         if 'alias' in site_dict:
061             return site_dict['alias']
062         else:
063             return site_dict['url'] + ":" + str(site_dict['port'])
064 
065     def populate_menu(self):
066         for mi in self.menu.get_children():        # just remove all items from menu, repopulate from scratch
067             self.menu.remove(mi)
068         for d in sites:
069             if d['active'] != True:
070                 continue
071             name = self.get_name(d)
072             if d['success']:
073                 self.menuItem = gtk.MenuItem("up: " + name)
074             else:
075                 self.menuItem = gtk.MenuItem("DOWN: " + name)
076             self.menu.append(self.menuItem)
077             self.menuItem.show()
078         self.menuItem = gtk.SeparatorMenuItem()
079         self.menu.append(self.menuItem)
080         self.menuItem.show()
081         self.menuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
082         self.menuItem.connect('activate', self.quit_cb, self.statusIcon)
083         self.menu.append(self.menuItem)
084 
085     def notify_about(self, changed):
086         nots = []
087         for d in changed:
088             if d['success']:
089                 msg = self.get_name(d) + " is online."
090             else:
091                 msg = self.get_name(d) + " is OFFLINE."
092             nots.append(msg)
093         n = pynotify.Notification("Ports checker", "\n".join(nots))
094         return n.show()
095 
096     def check_ports_cb(self):
097         global sites
098         #for d in sites:
099         #    print d
100         changed = []
101         all_passed = True
102         for d in sites:
103             if d['active'] != True:
104                 continue
105             ret = check_port(d['url'], d['port'])
106             if d['success'] != ret:
107                 d['success'] = ret
108                 changed.append(d)
109             if ret == False:
110                 all_passed = False
111 
112         # create list of checked sites in the menu, based on the results
113         if changed != []:
114             self.populate_menu()
115             self.notify_about(changed)
116 
117         # update the status icon if the overall result changed
118         if self.last_result != all_passed:
119             self.set_icon(all_passed)
120             self.last_result = all_passed
121 
122         self.statusIcon.connect('popup-menu', self.popup_menu_cb, self.menu)
123         self.statusIcon.set_visible(True)
124 
125         # we're ready for another round of checks in 5 secs
126         global check_every
127         gtk.timeout_add(int(check_every * 1000), self.check_ports_cb)
128 
129     def quit_cb(self, widget, data = None):
130         gtk.main_quit()
131 
132     def popup_menu_cb(self, widget, button, time, data = None):
133         if button == 3:
134             if data:
135                 data.show_all()
136                 data.popup(None, None, gtk.status_icon_position_menu,
137                         3, time, self.statusIcon)
138 
139 if __name__ == "__main__":
140     portsChecker = PortsCheckerTray()
141 
© 2011 Josef Nygrin - paskvil.com