4 Subscribes to zephyr via tzc and sends messages to notification drivers (growl or libnotify).
13 from abstfilter import AbstractConsumer
16 class Notifier(AbstractConsumer):
17 def __init__(self, usegrowl, usenotify, useprint):
18 self.usegrowl = usegrowl
19 self.usenotify = usenotify
22 pynotify.init("Zephyr")
24 self.pynotify = pynotify
25 self.useprint = useprint
28 if s is None or type(s) is type(''): return
29 d = dict([(ss[0], len(ss) > 2 and ss[2] or None) for ss in s])
30 if d['tzcspew'] == 'message':
31 zclass = d['class'].lower()
32 zinstance = d['instance'].lower()
33 zop = d['opcode'].lower()
34 zsender = d['sender'].lower()
35 zauth = d['auth'].lower() == 'yes'
36 ztime = ':'.join(d['time'].split(' ')[3].split(':')[0:2])
37 zmessage = d['message']
38 idtuple = (zclass, zinstance, zsender, ztime)
39 id = '%s/\n%s/\n%s\n %s' % idtuple
41 header = '%s (%s)' % (id, zsender)
44 header = '%s (%s)' % (id, len(zmessage) > 0 and zmessage[0] or zsender)
45 message = '%s' % (len(zmessage) > 1 and zmessage[1] or '')
52 growlnotify = ['growlnotify', '-a', 'MacZephyr', '-n', 'zephyr', '-d', id, '-t', header]
53 g = subprocess.Popen(growlnotify, stdin=subprocess.PIPE)
54 g.stdin.write(message)
57 if idtuple in self.pings:
58 self.pings[idtuple].update(header, message)
59 self.pings[idtuple].show()
61 n = self.pynotify.Notification(header, message)
64 self.pings[idtuple] = n
65 self.pings = dict(filter(lambda ((c, i, s, time), v): time == idtuple[3], self.pings.items()))
70 parser = optparse.OptionParser(usage = '%prog [-s "username@machine"] (--growl | --notify | --print)',
71 description = __doc__.strip())
72 parser.add_option('-s', '--ssh',
76 help = 'optional remote host to run tzc')
77 parser.add_option('-g', '--growl',
78 action = 'store_true',
81 help = 'use growlnotify for output')
82 parser.add_option('-n', '--notify',
83 action = 'store_true',
86 help = 'use notify-send for output')
87 parser.add_option('-p', '--print',
88 action = 'store_true',
91 help = 'use stdout for output')
92 opts, args = parser.parse_args()
95 usenotify = opts.notify
96 useprint = opts.useprint
97 if not usegrowl and not usenotify and not useprint:
98 parser.print_help(sys.stderr)
103 retval = subprocess.call(['which', 'tzc'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
105 print 'tzc not in path. Please add -s username@machine to specify remote host.'
109 command = "ssh -K %s 'tzc -si'" % ssh
112 p = os.popen(command)
113 r = sexpr.SExprReader(Notifier(usegrowl, usenotify, useprint))
115 flags = fcntl.fcntl(p, fcntl.F_GETFL)
116 fcntl.fcntl(p, fcntl.F_SETFL, flags | os.O_NONBLOCK)
120 [i,o,e] = select.select([p], [], [], 5)
121 if i: s = p.read(1024)
126 except KeyboardInterrupt:
130 if __name__ == "__main__":
131 sys.exit(main(sys.argv))