""" Dispatch - accept messages and route them to notification channels Copyright (C) 2012 Brian S. Stephan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ import MySQLdb as mdb import os from extlib import irclib from Module import Module class Dispatch(Module): """Accept messages via XML-RPC, send them to the configured IRC channel. """ def db_init(self): """Set up the database tables, if they don't exist.""" try: db = self.get_db() version = self.db_module_registered(self.__class__.__name__) if version is None: version = 1 cur = db.cursor(mdb.cursors.DictCursor) cur.execute(''' CREATE TABLE dispatch_item ( key_ VARCHAR(255) NOT NULL, dest VARCHAR(255) NOT NULL, PRIMARY KEY (key_) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci ''') db.commit() self.db_register_module_version(self.__class__.__name__, version) if version == 1: version = 2 cur = db.cursor(mdb.cursors.DictCursor) cur.execute(''' ALTER TABLE dispatch_item DROP PRIMARY KEY, ADD PRIMARY KEY (key_, dest) ''') db.commit() self.db_register_module_version(self.__class__.__name__, version) except mdb.Error as e: db.rollback() self.log.error("database error trying to create tables") self.log.exception(e) raise finally: cur.close() def xmlrpc_init(self): """Expose dispatching interface.""" self.irc.xmlrpc_register_function(self.dispatch_message, "dispatch") def register_handlers(self): """Hook handler functions into the IRC library.""" pass def unregister_handlers(self): """Unhook handler functions from the IRC library.""" pass def dispatch_message(self, key, message): """Send a message, of the given type, to the configured channel. Args: key the type of message. this will be converted uppercase message the message to send to the channel Returns: list of all notified targets """ notified = [] for key, dest in self._get_key_and_destination(key): if irclib.is_channel(dest): msg = "[{0:s}] {1:s}".format(key, message.encode('utf-8', 'ignore')) self.sendmsg(dest, msg) notified.append(dest) elif dest.find('FILE:') == 0: filename = dest.replace('FILE:', '') filename = os.path.abspath(filename) self.log.info("filename: {0:s}".format(filename)) msg = "[{0:s}] {1:s}\n".format(key, message.encode('utf-8', 'ignore')) with open(filename, 'w') as f: f.write(msg) return notified def _get_key_and_destination(self, key): """Retrieve the configured channel for the given key. Args: key the type of message. this will be converted uppercase Returns: list of tuple of strings: (the key, the destination channel) """ targets = [] db = self.get_db() try: cur = db.cursor(mdb.cursors.DictCursor) query = ''' SELECT key_, dest FROM dispatch_item WHERE key_ = %s ''' cur.execute(query, (key.upper(),)) results = cur.fetchall() for result in results: targets.append((result['key_'], result['dest'])) return targets except mdb.Error as e: self.log.error("database error while getting destination") self.log.exception(e) raise finally: cur.close() # vi:tabstop=4:expandtab:autoindent