]> sipb.mit.edu Git - snippets/.git/blobdiff - barn-growl/barn-growl.py
apt-zephyr: Make pre_install_pkgs a function.
[snippets/.git] / barn-growl / barn-growl.py
index 6930f36990bfd06ed2ec242123e4bbfc8e695c6f..e36f7198b6de0ccae5874285779f3c649bd2d3e9 100755 (executable)
@@ -1,18 +1,32 @@
 #!/usr/bin/env python
 
+"""
+Subscribes to zephyr via tzc and sends messages to notification drivers (growl or libnotify).
+"""
+
 import sexpr
 import os
+import subprocess
 import fcntl
 import select
 import sys
 from abstfilter import AbstractConsumer
+import optparse
+import time
 
-class Growler(AbstractConsumer):
-    def __init__(self):
+class Notifier(AbstractConsumer):
+    def __init__(self, usegrowl, usenotify, useprint):
+        self.usegrowl = usegrowl
+        self.usenotify = usenotify
+        if usenotify:
+            import pynotify
+            pynotify.init("Zephyr")
+            self.pings = {}
+            self.pynotify = pynotify
+        self.useprint = useprint
         return
     def feed(self, s):
         if s is None or type(s) is type(''): return
-        print repr(s)
         d = dict([(ss[0], len(ss) > 2 and ss[2] or None) for ss in s])
         if d['tzcspew'] == 'message':
             zclass = d['class'].lower()
@@ -20,49 +34,98 @@ class Growler(AbstractConsumer):
             zop = d['opcode'].lower()
             zsender = d['sender'].lower()
             zauth = d['auth'].lower() == 'yes'
-            ztime = ':'.join(d['time'].split(' ')[3].split(':')[0:2])
+            ztime = "%02d:%02d" % time.strptime(d['time'])[3:5]
             zmessage = d['message']
-            id = '%s/\n%s/\n%s\n %s' % (zclass, zinstance, zsender, ztime)
+            idtuple = (zclass, zinstance, zsender, ztime)
+            id = '%s/\n%s/\n%s\n %s' % idtuple
             if zop == 'ping':
                 header = '%s (%s)' % (id, zsender)
                 message = '...'
             elif zop == 'nil':
-                header = '%s (%s)' % (id, zmessage[0])
-                message = '%s' % zmessage[1]
+                header = '%s (%s)' % (id, len(zmessage) > 0 and zmessage[0] or zsender)
+                message = '%s' % (len(zmessage) > 1 and zmessage[1] or '')
             else:
                 return
-            g = os.popen("growlnotify -a MacZephyr -n zephyr -d '%s' -t '%s'" % (id, header), 'w')
-            g.write(message)
-            g.close()
+            if self.useprint:
+                print (id, header)
+                print message
+            if self.usegrowl:
+                growlnotify = ['growlnotify', '-H', 'localhost', '-a', 'MacZephyr', '-n', 'zephyr', '-d', id, '-t', header]
+                g = subprocess.Popen(growlnotify, stdin=subprocess.PIPE)
+                g.stdin.write(message)
+                g.stdin.close()
+            if self.usenotify:
+                if idtuple in self.pings:
+                    self.pings[idtuple].update(header, message)
+                    self.pings[idtuple].show()
+                else:
+                    n = self.pynotify.Notification(header, message)
+                    n.show()
+                    if zop == 'ping':
+                        self.pings[idtuple] = n
+                self.pings = dict(filter(lambda ((c, i, s, time), v): time == idtuple[3], self.pings.items()))
     def close(self):
         return
 
 def main(argv):
-    if len(argv) < 2:
-        print """barn-growl v.0.0.1
+    parser = optparse.OptionParser(usage = '%prog [-s "username@machine"] (--growl | --notify | --print)',
+            description = __doc__.strip())
+    parser.add_option('-s', '--ssh',
+            type = 'string',
+            default = None,
+            dest = 'ssh',
+            help = 'optional remote host to run tzc')
+    parser.add_option('-g', '--growl',
+            action = 'store_true',
+            default = False,
+            dest = 'growl',
+            help = 'use growlnotify for output')
+    parser.add_option('-n', '--notify',
+            action = 'store_true',
+            default = False,
+            dest = 'notify',
+            help = 'use notify-send for output')
+    parser.add_option('-p', '--print',
+            action = 'store_true',
+            default = False,
+            dest = 'useprint',
+            help = 'use stdout for output')
+    opts, args = parser.parse_args()
+
+    usegrowl = opts.growl
+    usenotify = opts.notify
+    useprint = opts.useprint
+    if not usegrowl and not usenotify and not useprint:
+        parser.print_help(sys.stderr)
+        return 1
+    ssh = opts.ssh
 
-Usage:
-barn-growl USERNAME"""
-        return 0
+    if ssh is None:
+        retval = subprocess.call(['which', 'tzc'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+        if retval:
+            print 'tzc not in path.  Please add -s username@machine to specify remote host.'
+            return 1
 
-    username = argv[1]
-    principal = username
-    if principal.find("@") == -1:
-        principal += '@ATHENA.MIT.EDU'
-    bash = "/bin/bash -lc \"kdo %s ssh %s@linerva.mit.edu 'tzc -si'\" 2>/dev/null </dev/null" % (principal, username)
-    p = os.popen(bash)
-    r = sexpr.SExprReader(Growler())
+    if ssh is not None:
+        command = "ssh -o GSSAPIAuthentication=yes -o GSSAPIDelegateCredentials=yes -o GSSAPIKeyExchange=yes %s 'tzc -si'" % ssh
+    else:
+        command = "tzc -si"
+    p = os.popen(command)
+    r = sexpr.SExprReader(Notifier(usegrowl, usenotify, useprint))
 
     flags = fcntl.fcntl(p, fcntl.F_GETFL)
     fcntl.fcntl(p, fcntl.F_SETFL, flags | os.O_NONBLOCK)
 
-    while 1:
-        [i,o,e] = select.select([p], [], [], 5)
-        if i: s = p.read(1024)
-        else: s = ''
+    try:
+        while 1:
+            [i,o,e] = select.select([p], [], [], 5)
+            if i: s = p.read(1024)
+            else: s = ''
 
-        if s != '':
-            r.feed(s)
+            if s != '':
+                r.feed(s)
+    except KeyboardInterrupt:
+        pass
     return 0
 
 if __name__ == "__main__":