]> snippets.scripts.mit.edu Git - Scripts/git/.git/blame_incremental - barn-growl/barn-growl.py
Reuse an existing notification object if it exists (for pings).
[Scripts/git/.git] / barn-growl / barn-growl.py
... / ...
CommitLineData
1#!/usr/bin/env python
2
3"""
4Subscribes to zephyr via tzc and sends messages to notification drivers (growl or libnotify).
5"""
6
7import sexpr
8import os
9import subprocess
10import fcntl
11import select
12import sys
13from abstfilter import AbstractConsumer
14import optparse
15
16class Notifier(AbstractConsumer):
17 def __init__(self, usegrowl, usenotify, useprint):
18 self.usegrowl = usegrowl
19 self.usenotify = usenotify
20 if usenotify:
21 import pynotify
22 pynotify.init("Zephyr")
23 self.pings = {}
24 self.pynotify = pynotify
25 self.useprint = useprint
26 return
27 def feed(self, s):
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
40 if zop == 'ping':
41 header = '%s (%s)' % (id, zsender)
42 message = '...'
43 elif zop == 'nil':
44 header = '%s (%s)' % (id, len(zmessage) > 0 and zmessage[0] or zsender)
45 message = '%s' % (len(zmessage) > 1 and zmessage[1] or '')
46 else:
47 return
48 if self.useprint:
49 print (id, header)
50 print message
51 if self.usegrowl:
52 growlnotify = ['growlnotify', '-a', 'MacZephyr', '-n', 'zephyr', '-d', id, '-t', header]
53 g = subprocess.Popen(growlnotify, stdin=subprocess.PIPE)
54 g.stdin.write(message)
55 g.stdin.close()
56 if self.usenotify:
57 if idtuple in self.pings:
58 self.pings[idtuple].update(header, message)
59 self.pings[idtuple].show()
60 else:
61 n = self.pynotify.Notification(header, message)
62 n.show()
63 if zop == 'ping':
64 self.pings[idtuple] = n
65 self.pings = dict(filter(lambda ((c, i, s, time), v): time == idtuple[3], self.pings.items()))
66 def close(self):
67 return
68
69def main(argv):
70 parser = optparse.OptionParser(usage = '%prog [-s "username@machine"] (--growl | --notify | --print)',
71 description = __doc__.strip())
72 parser.add_option('-s', '--ssh',
73 type = 'string',
74 default = None,
75 dest = 'ssh',
76 help = 'optional remote host to run tzc')
77 parser.add_option('-g', '--growl',
78 action = 'store_true',
79 default = False,
80 dest = 'growl',
81 help = 'use growlnotify for output')
82 parser.add_option('-n', '--notify',
83 action = 'store_true',
84 default = False,
85 dest = 'notify',
86 help = 'use notify-send for output')
87 parser.add_option('-p', '--print',
88 action = 'store_true',
89 default = False,
90 dest = 'useprint',
91 help = 'use stdout for output')
92 opts, args = parser.parse_args()
93
94 usegrowl = opts.growl
95 usenotify = opts.notify
96 useprint = opts.useprint
97 if not usegrowl and not usenotify and not useprint:
98 parser.print_help(sys.stderr)
99 return 1
100 ssh = opts.ssh
101
102 if ssh is None:
103 retval = subprocess.call(['which', 'tzc'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
104 if retval:
105 print 'tzc not in path. Please add -s username@machine to specify remote host.'
106 return 1
107
108 if ssh is not None:
109 command = "ssh -K %s 'tzc -si'" % ssh
110 else:
111 command = "tzc -si"
112 p = os.popen(command)
113 r = sexpr.SExprReader(Notifier(usegrowl, usenotify, useprint))
114
115 flags = fcntl.fcntl(p, fcntl.F_GETFL)
116 fcntl.fcntl(p, fcntl.F_SETFL, flags | os.O_NONBLOCK)
117
118 try:
119 while 1:
120 [i,o,e] = select.select([p], [], [], 5)
121 if i: s = p.read(1024)
122 else: s = ''
123
124 if s != '':
125 r.feed(s)
126 except KeyboardInterrupt:
127 pass
128 return 0
129
130if __name__ == "__main__":
131 sys.exit(main(sys.argv))