It’s no secret that I work with pfSense a lot, and a while back support was added to pfSense for Growl alerts over the network. Tired of being jealous of everyone else with a Mac (and even Windows!) who could get growl alerts, and not having any growl servers available for FreeBSD, I decided to dive in a little deeper.
After searches for a stand-alone growl server came up empty, I started looking for anyone who had implemented a server in another language like python, ruby or perl. Lo and behold, I found one in python! Just one problem: I use KDE, and that one was for gnome/dbus. Luckily the code is quite easy to follow and it was easy to modify. The kdialog program in KDE already supports growl style alerts by using kdialog –passivepopup, so it was just a matter of ripping out the gnome/dbus bits and replacing them with a call to kdialog.
Without further ado, I present: kdegrowl.py:
#!/usr/bin/env python """Growl 0.6 KDE kdialog bits""" __version__ = "0.1" __author__ = "Jim Pingle (http://pingle.org)" __copyright__ = "(C) 2011 Jim Pingle, original code (C) 2006 Rui Carmo. Code under BSD License." import sys, os from subprocess import call from regrowl import GrowlPacket from netgrowl import * from SocketServer import * password="password" class GrowlListener(UDPServer): """Growl Notification Listener""" # Hostname/IP to listen on. No automatic detection. hostname = '192.168.2.2' allow_reuse_address = True def __init__(self, inpassword = None, outpassword = None): """Initializes the relay and launches the resolver thread""" self.inpassword = inpassword self.outpassword = outpassword UDPServer.__init__(self,(self.hostname, GROWL_UDP_PORT), _RequestHandler) # end def def server_close(self): self.resolver.shutdown() # end def # end class class _RequestHandler(DatagramRequestHandler): """Processes and each incoming notification packet""" dialogtimeout = '5' kdialogpath = '/usr/local/kde4/bin/kdialog' def handle(self): """Handles each request""" p = GrowlPacket(self.rfile.read(), self.server.inpassword,self.server.outpassword) if p.type() == 'NOTIFY': notification,title,description,app = p.info() gtext = app + '\n' + notification + ': ' + description call([self.kdialogpath, '--title', title, '--passivepopup', gtext, self.dialogtimeout]) if __name__ == "__main__": r = GrowlListener(password,password) try: r.serve_forever() except KeyboardInterrupt: r.server_close()
In order to use it you’ll also need the following files:
When run, that script will listen on the IP configured inside, and will accept growl notifications over the network. You probably also want to change the password and perhaps the path to kdialog. I am aware there are a zillion ways to improve upon this, but this meets my needs for the moment. If someone wants to make a fancier version, that would be great!