class Pyrefly(Handler): def __init__(self, config): self.config = config self.client = Client(self.config.get("id")) self.client.addHandler(self) self.db = Db( "pyrefly", self.config.get("account", "db"), self.config.get("password", "db"), self.config.get("spreadsheet", "db"), ) self.plugins = {} self.pluginModules = {} self.dispatcher = Dispatcher() self.handlers = [Core(self), self.dispatcher] # Set up the import path for plugins myPath = os.path.abspath(__file__) pluginPath = os.path.join(myPath.rsplit(os.sep, 1)[0], "plugins") print "Path for plugins is: %s" % pluginPath sys.path.append(pluginPath) def connect(self): self.db.connect() result, err = self.client.connect(self.config.get("password"), "bot" + self.config.hash[:6]) if not result: print "Error connecting: %s" % err exit(1) def initialize(self): joinMap = {} table = self.db.table("rooms") if table is not None: rows = table.get({"autojoin": "y"}) for row in rows: joinMap[row["muc"]] = row for mucId in self.config.getRoomList(): if mucId not in joinMap: group = self.config.get("group", mucId) if not group: group = "global" nick = self.config.get("nick", mucId) name = mucId.split("@")[0] data = { "name": name, "muc": mucId, "nick": nick, "password": "", "group": group, "autojoin": "y", "control": "n", } joinMap[mucId] = data if table is not None: table.put(data) for mucToJoin in joinMap.values(): muc = self.join(mucToJoin["muc"], mucToJoin["nick"], password=mucToJoin["password"]) if muc is not None: muc.data = mucToJoin def join(self, muc, nick, password=""): return self.client.join(muc, nick, password=password) def process(self, timeout=0.1): self.client.process(timeout=timeout) return True def onMucMessage(self, *args, **kwargs): for handler in self.handlers: handler.onMucMessage(*args, **kwargs) def registerHandler(self, handler): self.handlers.append(handler) def unregisterHandler(self, handler): self.handlers.remove(handler) def loadPlugin(self, name): if name in self.plugins: return (False, "Plugin %s is already loaded" % name) source = None if name in self.pluginModules: source = "reloaded" reload(self.pluginModules[name]) else: importName = name.lower() source = "imported" try: self.pluginModules[name] = __import__(importName, globals(), locals(), [], 0) except ImportError: return (False, "No such module: %s" % importName) if not self.pluginModules[name]: del self.pluginModules[name] return (False, "Module not defined after import") try: clazz = getattr(self.pluginModules[name], name) except AttributeError: return (False, "Module has no class defined") if not clazz: return (False, "Class not defined after import") self.plugins[name] = clazz() self.plugins[name].onLoad(self) return (True, source) def unloadPlugin(self, name): if name not in self.plugins: return (False, None, "not loaded") toUnload = [] unloaded = [] for pluginName, plugin in self.plugins.items(): if name in plugin.getDependencies(): toUnload.append(pluginName) for pluginName in toUnload: result, extraUnloaded, err = self.unloadPlugin(pluginName) for unloadedName in extraUnloaded: unloaded.append(unloadedName) if not result: return (False, unloaded, err) unloaded.append(pluginName) self.plugins[name].onUnload() del self.plugins[name] return (True, unloaded, None) def reloadPlugin(self, name): if name not in self.plugins: return (False, "Not loaded") plugin = self.plugins[name] plugin.onUnload() reload(self.pluginModules[name]) try: clazz = getattr(self.pluginModules[name], name) except AttributeError: return (False, "Class no longer defined") self.plugins[name] = clazz() self.plugins[name].onLoad(self) for pluginName, plugin in self.plugins.items(): if name in plugin.getDependencies(): plugin.setDependency(pluginName, self.plugins[name]) return (True, None)
class Pyrefly(Handler): def __init__(self, config): self._config = config self._client = XmppClient(self._config.get('id')) self._db = Db('pyrefly', self._config.get('account', 'db'), self._config.get('password', 'db'), self._config.get('spreadsheet', 'db')) self._plugins = {} self._pluginModules = {} self._dispatcher = Dispatcher() self._broadcaster = EventBroadcaster() self._broadcaster.addHandler(Core(self)) self._broadcaster.addHandler(self._dispatcher) self._client.addHandler(self._broadcaster) # Set up the import path for plugins myPath = os.path.abspath(__file__) self._pluginPath = os.path.join(myPath.rsplit(os.sep, 1)[0], "plugins") print "Path for plugins is: %s" % self._pluginPath sys.path.append(self._pluginPath) def getDispatcher(self): return self._dispatcher def getDb(self): return self._db def getClient(self): return self._client def connect(self): self._db.connect() result, err = self._client.connect(self._config.get('password'), 'bot' + self._config.hash[:6]) if not result: print "Error connecting: %s" % err exit(1) print "Connected!" def initialize(self): joinMap = {} table = self._db.table('rooms') if table is not None: rows = table.get({'autojoin': 'y'}) for row in rows: joinMap[row['muc']] = row for mucId in self._config.getRoomList(): if mucId not in joinMap: group = self._config.get('group', mucId) if not group: group = 'global' nick = self._config.get('nick', mucId) name = mucId.split('@')[0] data = {'name': name, 'muc': mucId, 'nick': nick, 'password': '', 'group': group, 'autojoin': 'y', 'control': 'n'} joinMap[mucId] = data if table is not None: table.put(data) for mucToJoin in joinMap.values(): muc = self.join(mucToJoin['muc'], mucToJoin['nick'], password=mucToJoin['password']) if muc is not None: muc.data = mucToJoin def join(self, muc, nick, password=''): return self._client.join(muc, nick, password=password) def process(self, timeout=0.1): self._client.process(timeout=timeout) return True def registerHandler(self, handler): self._broadcaster.addHandler(handler) def unregisterHandler(self, handler): self._broadcaster.removeHandler(handler) def _tryCompile(self, pluginName): pluginPath = "%s/%s.py" % (self._pluginPath, pluginName) print "Compiling: %s" % pluginPath try: res = py_compile.compile(pluginPath, "%sc" % pluginPath, pluginPath, True) return None except py_compile.PyCompileError as err: return str(err.msg).strip() def loadPlugin(self, name): if name in self._plugins: return (False, "Plugin %s is already loaded" % name) source = None res = self._tryCompile(name.lower()) if res is not None: return (False, res) if name in self._pluginModules: source = "reloaded" reload(self._pluginModules[name]) else: importName = name.lower() source = "imported" try: self._pluginModules[name] = __import__(importName, globals(), locals(), [], 0) except ImportError: return (False, "No such module: %s" % importName) if not self._pluginModules[name]: del self._pluginModules[name] return (False, "Module not defined after import") try: clazz = getattr(self._pluginModules[name], name) except AttributeError: return (False, "Module has no class defined") if not clazz: return (False, "Class not defined after import") try: self._plugins[name] = clazz() self._plugins[name].onLoad(self) except Exception as err: if name in self._plugins: del self._plugins[name] return (False, str(err).strip()) return (True, source) def unloadPlugin(self, name): if name not in self._plugins: return (False, None, "not loaded") toUnload = [] unloaded = [] for pluginName, plugin in self._plugins.items(): if name in plugin.getDependencies(): toUnload.append(pluginName) for pluginName in toUnload: result, extraUnloaded, err = self.unloadPlugin(pluginName) for unloadedName in extraUnloaded: unloaded.append(unloadedName) if not result: return (False, unloaded, err) unloaded.append(pluginName) self._plugins[name].onUnload() del self._plugins[name] return (True, unloaded, None) def reloadPlugin(self, name): if name not in self._plugins: return (False, "Not loaded") res = self._tryCompile(name.lower()) if res is not None: return (False, res) plugin = self._plugins[name] plugin.onUnload() reload(self._pluginModules[name]) try: clazz = getattr(self._pluginModules[name], name) except AttributeError: return (False, "Class no longer defined") try: self._plugins[name] = clazz() self._plugins[name].onLoad(self) except Exception as err: if name in self._plugins: del self._plugins[name] return (False, str(err).strip()) for pluginName, plugin in self._plugins.items(): if name in plugin.getDependencies(): plugin.setDependency(pluginName, self._plugins[name]) return (True, None)