4 Subscribes to zephyr via tzc and sends messages to notification drivers (growl or libnotify).
13 from abstfilter import AbstractConsumer
17 class Notifier(AbstractConsumer):
18 def __init__(self, usegrowl, usenotify, useprint):
19 self.usegrowl = usegrowl
20 self.usenotify = usenotify
23 pynotify.init("Zephyr")
25 self.pynotify = pynotify
26 self.useprint = useprint
29 if s is None or type(s) is type(''): return
30 d = dict([(ss[0], len(ss) > 2 and ss[2] or None) for ss in s])
31 if d['tzcspew'] == 'message':
32 zclass = d['class'].lower()
33 zinstance = d['instance'].lower()
34 zop = d['opcode'].lower()
35 zsender = d['sender'].lower()
36 zauth = d['auth'].lower() == 'yes'
37 ztime = "%02d:%02d" % time.strptime(d['time'])[3:5]
38 zmessage = d['message']
39 idtuple = (zclass, zinstance, zsender, ztime)
40 id = '%s/\n%s/\n%s\n %s' % idtuple
42 header = '%s (%s)' % (id, zsender)
45 header = '%s (%s)' % (id, len(zmessage) > 0 and zmessage[0] or zsender)
46 message = '%s' % (len(zmessage) > 1 and zmessage[1] or '')
53 growlnotify = ['growlnotify', '-H', 'localhost', '-a', 'MacZephyr', '-n', 'zephyr', '-d', id, '-t', header]
54 g = subprocess.Popen(growlnotify, stdin=subprocess.PIPE)
55 g.stdin.write(message)
58 if idtuple in self.pings:
59 self.pings[idtuple].update(header, message)
60 self.pings[idtuple].show()
62 n = self.pynotify.Notification(header, message)
65 self.pings[idtuple] = n
66 self.pings = dict(filter(lambda ((c, i, s, time), v): time == idtuple[3], self.pings.items()))
71 parser = optparse.OptionParser(usage = '%prog [-s "username@machine"] (--growl | --notify | --print)',
72 description = __doc__.strip())
73 parser.add_option('-s', '--ssh',
77 help = 'optional remote host to run tzc')
78 parser.add_option('-g', '--growl',
79 action = 'store_true',
82 help = 'use growlnotify for output')
83 parser.add_option('-n', '--notify',
84 action = 'store_true',
87 help = 'use notify-send for output')
88 parser.add_option('-p', '--print',
89 action = 'store_true',
92 help = 'use stdout for output')
93 opts, args = parser.parse_args()
96 usenotify = opts.notify
97 useprint = opts.useprint
98 if not usegrowl and not usenotify and not useprint:
99 parser.print_help(sys.stderr)
104 retval = subprocess.call(['which', 'tzc'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
106 print 'tzc not in path. Please add -s username@machine to specify remote host.'
110 command = "ssh -o GSSAPIAuthentication=yes -o GSSAPIDelegateCredentials=yes -o GSSAPIKeyExchange=yes %s 'tzc -si'" % ssh
113 p = os.popen(command)
114 r = sexpr.SExprReader(Notifier(usegrowl, usenotify, useprint))
116 flags = fcntl.fcntl(p, fcntl.F_GETFL)
117 fcntl.fcntl(p, fcntl.F_SETFL, flags | os.O_NONBLOCK)
121 [i,o,e] = select.select([p], [], [], 5)
122 if i: s = p.read(1024)
127 except KeyboardInterrupt:
131 if __name__ == "__main__":
132 sys.exit(main(sys.argv))