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