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