class Informer(Runnable): info_sites = [] sleep_time = 60 * 60 # every hour db = None api = None config = None def load_configs(self): for cfg in self.config.get_site_configs(): self.db.add_site_configuration(cfg) def __init__(self, config): Runnable.__init__(self) self.db = Database() self.config = config self.load_configs() self.api = API(callback_add=self.callback_add_info_site) self.driver = WebDriver.build(config) def callback_add_info_site(self, config): self.info_sites.append(config) # todo filter if not already in list return True def _run(self): for i in self.info_sites: i.check() def stop(self): self.api.stop()
def __init__(self, config): Runnable.__init__(self) self.db = Database() self.config = config self.load_configs() self.api = API(callback_add=self.callback_add_info_site) self.driver = WebDriver.build(config)
def __init__(self): """ initialize the instance """ self.plugins = {} self.pluginl = {} self.pluginm = {} self.pluginp = {} self.options = {} self.plugininfo = {} index = __file__.rfind(os.sep) if index == -1: self.basepath = "." + os.sep else: self.basepath = __file__[:index] self.api = API() self.savefile = os.path.join(self.api.BASEPATH, 'data', 'plugins', 'loadedplugins.txt') self.loadedplugins = PersistentDict(self.savefile, 'c') self.sname = 'plugins' self.lname = 'Plugin Manager' self.api.add(self.sname, 'isinstalled', self.api_isinstalled) self.api.add(self.sname, 'getp', self.api_getp) self.api.add(self.sname, 'module', self.api_getmodule) self.api.add(self.sname, 'allplugininfo', self.api_allplugininfo) self.api.add(self.sname, 'savestate', self.savestate)
def __init__(self, name, sname, modpath, basepath, fullimploc): # pylint: disable=too-many-arguments """ initialize the instance The following things should not be done in __init__ in a plugin Interacting with anything in the api except api.add, api.overload or dependency.add """ # Examples: # name : 'Actions' - from plugin file variable NAME (long name) # sname : 'actions' - from plugin file variable SNAME (short name) # modpath : '/client/actions.py' - path relative to the plugins directory # basepath : '/home/src/games/bastproxy/bp/plugins' - the full path to the # plugins directory # fullimploc : 'plugins.client.actions' - import location self.author = '' self.purpose = '' self.version = 0 self.priority = 100 self.name = name self.sname = sname self.dependencies = [] self.versionfuncs = {} self.reloaddependents = False self.summarytemplate = "%20s : %s" self.canreload = True self.canreset = True self.resetflag = True self.api = API() self.firstactiveprio = None self.loadedtime = time.time() self.savedir = os.path.join(self.api.BASEPATH, 'data', 'plugins', self.sname) try: os.makedirs(self.savedir) except OSError: pass self.savefile = os.path.join(self.api.BASEPATH, 'data', 'plugins', self.sname, 'settingvalues.txt') self.modpath = modpath self.basepath = basepath self.fullimploc = fullimploc self.pluginfile = os.path.join(basepath, modpath[1:]) self.pluginlocation = os.path.normpath( os.path.join(self.api.BASEPATH, 'plugins') + \ os.sep + os.path.dirname(self.modpath)) self.package = fullimploc.split('.')[1] self.settings = {} self.settingvalues = PersistentDictEvent(self, self.savefile, 'c') self._dump_shallow_attrs = ['api'] self.api.overload('dependency', 'add', self._api_dependencyadd) self.api.overload('setting', 'add', self._api_settingadd) self.api.overload('setting', 'gets', self._api_settinggets) self.api.overload('setting', 'change', self._api_settingchange) self.api.overload('api', 'add', self._api_add)
def api_sendpacket(self, message): """ send an A102 packet @Ymessage@w = the message to send Format: IAC SB A102 <atcp message text> IAC SE this function returns no values""" from libs.api import API api = API() api.get('events.eraise')('to_mud_event', {'data':'%s%s%s%s%s%s' % \ (IAC, SB, A102, message.replace(IAC, IAC+IAC), IAC, SE), 'raw':True, 'dtype':A102})
def __init__(self, name, sname, modpath, basepath, fullimploc): # pylint: disable=too-many-arguments """ initialize the instance The following things should not be done in __init__ in a plugin Interacting with anything in the api except api.add, api.overload or dependency.add """ self.author = '' self.purpose = '' self.version = 0 self.priority = 100 self.name = name self.sname = sname self.dependencies = [] self.versionfuncs = {} self.reloaddependents = False self.canreload = True self.resetflag = True self.api = API() self.loadedtime = time.time() self.savedir = os.path.join(self.api.BASEPATH, 'data', 'plugins', self.sname) try: os.makedirs(self.savedir) except OSError: pass self.savefile = os.path.join(self.api.BASEPATH, 'data', 'plugins', self.sname, 'settingvalues.txt') self.modpath = modpath self.basepath = basepath self.fullimploc = fullimploc self.pluginfile = os.path.join(basepath, modpath[1:]) self.pluginlocation = os.path.normpath( os.path.join(self.api.BASEPATH, 'plugins') + \ os.sep + os.path.dirname(self.modpath)) self.package = fullimploc.split('.')[1] self.settings = {} self.settingvalues = PersistentDictEvent(self, self.savefile, 'c') self._dump_shallow_attrs = ['api'] self.api.overload('dependency', 'add', self.api_dependencyadd) self.api.overload('setting', 'add', self.api_settingadd) self.api.overload('setting', 'gets', self.api_settinggets) self.api.overload('setting', 'change', self.api_settingchange) self.api.overload('api', 'add', self.api_add)
def __init__(self, sock, host, port): """ init the class """ Telnet.__init__(self, sock=sock) self.host = host self.port = port self.api = API() self.ttype = 'Client' self.connectedtime = None self.supports = {} self.pwtries = 0 self.banned = False self.viewonly = False if sock: self.connected = True self.connectedtime = time.mktime(time.localtime()) self.api('events.register')('to_client_event', self.addtooutbufferevent, prio=99) self.api('options.prepareclient')(self) self.state = PASSWORD self.addtooutbufferevent({ 'original': self.api('colors.convertcolors')( '@R#BP@w: @RPlease enter the proxy password:@w'), 'dtype': 'passwd' })
def __init__(self, host=None, port=0, sock=None): """ Constructor. When called without arguments, create an unconnected instance. With a hostname argument, it connects the instance; port number and timeout are optional. """ if sock: asyncore.dispatcher.__init__(self, sock) else: asyncore.dispatcher.__init__(self) self.sock = sock self.debuglevel = DEBUGLEVEL self.host = host self.port = port self.rawq = '' self.api = API() self.cookedq = '' self.eof = 0 self.sbdataq = '' self._sbdatabuffer = '' self.outbuffer = '' self.options = {} self.option_callback = self.handleopt self.option_handlers = {} self.connected = False self.ttype = 'Unknown' self.debug_types = []
def __init__(self, telnetobj, option): """ initalize the instance """ self.api = API() self.telnetobj = telnetobj self.option = option self.telnetobj.option_handlers[ord(self.option)] = self
def __init__(self, telnetobj, option, plugin): """ initalize the instance """ tapi = API() self.telnetobj = telnetobj self.option = option self.telnetobj.option_handlers[ord(self.option)] = self self.plugin = tapi('plugins.getp')(plugin)
def __init__(self): """ initialize the class """ self.currenttrace = None self.api = API() self.api('api.add')('send', 'msg', self._api_msg) self.api('api.add')('send', 'error', self._api_error) self.api('api.add')('send', 'traceback', self._api_traceback) self.api('api.add')('send', 'client', self._api_client) self.api('api.add')('send', 'mud', self._api_tomud) self.api('api.add')('send', 'execute', self._api_execute) self.api('managers.add')('io', self)
def __init__(self): """ init the class """ Telnet.__init__(self) self.username = None self.password = None self.api = API() self.lastmsg = '' self.clients = [] self.vclients = [] self.ttype = 'BastProxy' self.banned = {} self.connectedtime = None self.api('events.register')('to_mud_event', self.addtooutbuffer, prio=99) self.api('options.prepareserver')(self)
def __init__(self, filename, flag='c', mode=None, tformat='json', *args, **kwds): """ initialize the instance """ self._dump_shallow_attrs = ['api'] self.api = API() # r=readonly, c=create, or n=new self.flag = flag # None or an octal triple like 0644 self.mode = (stat.S_IWUSR | stat.S_IRUSR) or mode # 'csv', 'json', or 'pickle' self.format = tformat self.filename = filename self.pload() dict.__init__(self, *args, **kwds)
""" handle output and input functions, adds items under the send api """ import time import sys import traceback import re from libs.api import API as BASEAPI API = BASEAPI() # send a message def api_msg(tmsg, primary='default', secondary=None): """ send a message through the log plugin @Ymsg@w = This message to send @Yprimary@w = the primary datatype of the message (default: 'default') @Ysecondary@w = the secondary datatype of the message (default: 'None') this function returns no values""" if primary == 'default': try: primary = API('utils.funccallerplugin')() or primary except (AttributeError, RuntimeError): pass if not isinstance(secondary, list): tmpl = [] if secondary: tmpl.append(secondary)
class PluginMgr(object): # pylint: disable=too-many-public-methods """ a class to manage plugins """ def __init__(self): """ initialize the instance """ self.plugins = {} self.pluginl = {} self.pluginm = {} self.pluginp = {} self.options = {} self.plugininfo = {} index = __file__.rfind(os.sep) if index == -1: self.basepath = "." + os.sep else: self.basepath = __file__[:index] self.api = API() self.savefile = os.path.join(self.api.BASEPATH, 'data', 'plugins', 'loadedplugins.txt') self.loadedplugins = PersistentDict(self.savefile, 'c') self.sname = 'plugins' self.lname = 'Plugin Manager' self.api.add(self.sname, 'isinstalled', self.api_isinstalled) self.api.add(self.sname, 'getp', self.api_getp) self.api.add(self.sname, 'module', self.api_getmodule) self.api.add(self.sname, 'allplugininfo', self.api_allplugininfo) self.api.add(self.sname, 'savestate', self.savestate) # return the dictionary of all plugins def api_allplugininfo(self): """ return the plugininfo dictionary """ return self.plugininfo def findplugin(self, name): """ find a plugin file """ if '.' in name: tlist = name.split('.') name = tlist[-1] del tlist[-1] npath = os.sep.join(tlist) _module_list = find_files(self.basepath, name + ".py") if len(_module_list) == 1: return _module_list[0], self.basepath else: for i in _module_list: if npath in i: return i, self.basepath return '', '' def findloadedplugin(self, plugin): """ find a plugin """ if plugin and plugin in self.plugins: return plugin fullimploc = 'plugins.' + plugin for tplugin in self.plugins: if self.plugins[tplugin].fullimploc == fullimploc: return tplugin return None # get a plugin instance def api_getmodule(self, pluginname): """ returns the module of a plugin @Ypluginname@w = the plugin to check for""" if pluginname in self.pluginm: return self.pluginm[pluginname] return None # get a plugin instance def api_getp(self, pluginname): """ get a plugin instance @Ypluginname@w = the plugin to get for""" if isinstance(pluginname, basestring): if pluginname in self.plugins: return self.plugins[pluginname] if pluginname in self.pluginl: return self.pluginl[pluginname] if pluginname in self.pluginm: return self.pluginm[pluginname] if pluginname in self.pluginp: return self.pluginp[pluginname] elif isinstance(pluginname, BasePlugin): return pluginname return None # check if a plugin is installed def api_isinstalled(self, pluginname): """ check if a plugin is installed @Ypluginname@w = the plugin to check for""" if pluginname in self.plugins or pluginname in self.pluginl: return True return False def loaddependencies(self, pluginname, dependencies): """ load a list of modules """ for i in dependencies: if i in self.plugins or i in self.pluginl: continue self.api.get('send.msg')('%s: loading dependency %s' % (pluginname, i), pluginname) name, path = self.findplugin(i) if name: modpath = name.replace(path, '') self.load_module(modpath, path, force=True) def getnotloadedplugins(self): """ create a message of all not loaded plugins """ msg = [] badplugins = self.updateallplugininfo() for modpath in sorted(self.plugininfo.keys()): sname = self.plugininfo[modpath]['sname'] fullimploc = self.plugininfo[modpath]['fullimploc'] if sname not in self.plugins: msg.append("%-20s : %-25s %-10s %-5s %s@w" % \ (fullimploc.replace('plugins.', ''), self.plugininfo[modpath]['name'], self.plugininfo[modpath]['author'], self.plugininfo[modpath]['version'], self.plugininfo[modpath]['purpose'])) if len(msg) > 0: msg.insert(0, '-' * 75) msg.insert(0, "%-20s : %-25s %-10s %-5s %s@w" % \ ('Location', 'Name', 'Author', 'Vers', 'Purpose')) msg.insert(0, 'The following plugins are not loaded') if badplugins: msg.append('') msg.append('The following files would not import') for bad in badplugins: msg.append(bad.replace('plugins.', '')) return msg def getchangedplugins(self): """ create a message of plugins that are changed on disk """ msg = [] plugins = sorted(self.plugins.values(), key=operator.attrgetter('package')) packageheader = [] msg.append("%-10s : %-25s %-10s %-5s %s@w" % \ ('Short Name', 'Name', 'Author', 'Vers', 'Purpose')) msg.append('-' * 75) for tpl in plugins: if tpl.ischangedondisk(): if tpl.package not in packageheader: if len(packageheader) > 0: msg.append('') packageheader.append(tpl.package) limp = 'plugins.%s' % tpl.package mod = __import__(limp) try: desc = getattr(mod, tpl.package).DESCRIPTION except AttributeError: desc = '' msg.append('@GPackage: %s%s@w' % \ (tpl.package, ' - ' + desc if desc else '')) msg.append('@G' + '-' * 75 + '@w') msg.append("%-10s : %-25s %-10s %-5s %s@w" % \ (tpl.sname, tpl.name, tpl.author, tpl.version, tpl.purpose)) return msg def getpackageplugins(self, package): """ create a message of plugins in a package """ msg = [] plist = [] for plugin in self.plugins.values(): if plugin.package == package: plist.append(plugin) if len(plist) > 0: plugins = sorted(plist, key=operator.attrgetter('sname')) limp = 'plugins.%s' % package mod = __import__(limp) try: desc = getattr(mod, package).DESCRIPTION except AttributeError: desc = '' msg.append('@GPackage: %s%s@w' % \ (package, ' - ' + desc if desc else '')) msg.append('@G' + '-' * 75 + '@w') msg.append("%-10s : %-25s %-10s %-5s %s@w" % \ ('Short Name', 'Name', 'Author', 'Vers', 'Purpose')) msg.append('-' * 75) for tpl in plugins: msg.append("%-10s : %-25s %-10s %-5s %s@w" % \ (tpl.sname, tpl.name, tpl.author, tpl.version, tpl.purpose)) else: msg.append('That is not a valid package') return msg def getallplugins(self): """ create a message of all plugins """ msg = [] plugins = sorted(self.plugins.values(), key=operator.attrgetter('package')) packageheader = [] msg.append("%-10s : %-25s %-10s %-5s %s@w" % \ ('Short Name', 'Name', 'Author', 'Vers', 'Purpose')) msg.append('-' * 75) for tpl in plugins: if tpl.package not in packageheader: if len(packageheader) > 0: msg.append('') packageheader.append(tpl.package) limp = 'plugins.%s' % tpl.package mod = __import__(limp) try: desc = getattr(mod, tpl.package).DESCRIPTION except AttributeError: desc = '' msg.append('@GPackage: %s%s@w' % \ (tpl.package, ' - ' + desc if desc else '')) msg.append('@G' + '-' * 75 + '@w') msg.append("%-10s : %-25s %-10s %-5s %s@w" % \ (tpl.sname, tpl.name, tpl.author, tpl.version, tpl.purpose)) return msg def cmd_list(self, args): """ @G%(name)s@w - @B%(cmdname)s@w List plugins @CUsage@w: list """ msg = [] if args['notloaded']: msg.extend(self.getnotloadedplugins()) elif args['changed']: msg.extend(self.getchangedplugins()) elif args['package']: msg.extend(self.getpackageplugins(args['package'])) else: msg.extend(self.getallplugins()) return True, msg def cmd_load(self, args): """ @G%(name)s@w - @B%(cmdname)s@w Load a plugin @CUsage@w: load @Yplugin@w @Yplugin@w = the name of the plugin to load use the name without the .py """ tmsg = [] plugin = args['plugin'] if plugin: fname = plugin.replace('.', os.sep) _module_list = find_files(self.basepath, fname + ".py") if len(_module_list) > 1: tmsg.append('There is more than one module that matches: %s' % \ plugin) elif len(_module_list) == 0: tmsg.append('There are no modules that match: %s' % plugin) else: modpath = _module_list[0].replace(self.basepath, '') sname, reason = self.load_module(modpath, self.basepath, True) if sname: if reason == 'already': tmsg.append('Module %s is already loaded' % sname) else: tmsg.append('Load complete: %s - %s' % \ (sname, self.plugins[sname].name)) else: tmsg.append('Could not load: %s' % plugin) return True, tmsg else: return False, ['@Rplease specify a plugin@w'] def cmd_unload(self, args): """ @G%(name)s@w - @B%(cmdname)s@w unload a plugin @CUsage@w: unload @Yplugin@w @Yplugin@w = the shortname of the plugin to load """ tmsg = [] plugina = args['plugin'] if not plugina: return False, ['@Rplease specify a plugin@w'] plugin = self.findloadedplugin(plugina) if plugin and plugin in self.plugins: if self.plugins[plugin].canreload: if self.unload_module(self.plugins[plugin].fullimploc): tmsg.append("Unloaded: %s" % plugin) else: tmsg.append("Could not unload:: %s" % plugin) else: tmsg.append("That plugin can not be unloaded") return True, tmsg elif plugin: tmsg.append('plugin %s does not exist' % plugin) return True, tmsg return False, ['@Rplease specify a plugin@w'] def cmd_reload(self, args): """ @G%(name)s@w - @B%(cmdname)s@w reload a plugin @CUsage@w: reload @Yplugin@w @Yplugin@w = the shortname of the plugin to reload """ tmsg = [] plugina = args['plugin'] if not plugina: return False, ['@Rplease specify a plugin@w'] plugin = self.findloadedplugin(plugina) if plugin and plugin in self.plugins: if self.plugins[plugin].canreload: tret, _ = self.reload_module(plugin, True) if tret and tret != True: tmsg.append("Reload complete: %s" % self.plugins[tret].fullimploc) return True, tmsg else: tmsg.append("That plugin cannot be reloaded") return True, tmsg else: tmsg.append('plugin %s does not exist' % plugin) return True, tmsg return False, tmsg def load_modules(self, tfilter): """ load modules in all directories under plugins """ _module_list = find_files(self.basepath, tfilter) _module_list.sort() load = False for fullpath in _module_list: modpath = fullpath.replace(self.basepath, '') force = False if modpath in self.loadedplugins: force = True modname, dummy = self.load_module(modpath, self.basepath, force=force, runload=load) if modname == 'log': self.api.get('log.adddtype')(self.sname) self.api.get('log.console')(self.sname) self.api.get('log.adddtype')('upgrade') self.api.get('log.console')('upgrade') if not load: testsort = sorted(self.plugins.values(), key=operator.attrgetter('priority')) for i in testsort: try: #check dependencies here self.loadplugin(i) except Exception: # pylint: disable=broad-except self.api.get('send.traceback')( "load: had problems running the load method for %s." \ % i.fullimploc) del sys.modules[i.fullimploc] def updateallplugininfo(self): """ find plugins that are not in self.plugininfo """ _module_list = find_files(self.basepath, '*.py') _module_list.sort() self.plugininfo = {} badplugins = [] for fullpath in _module_list: modpath = fullpath.replace(self.basepath, '') imploc, modname = get_module_name(modpath) if not modname.startswith("_"): fullimploc = "plugins" + '.' + imploc if fullimploc in sys.modules: self.plugininfo[modpath] = {} self.plugininfo[modpath]['sname'] = self.pluginp[ modpath].sname self.plugininfo[modpath]['name'] = self.pluginp[ modpath].name self.plugininfo[modpath]['purpose'] = self.pluginp[ modpath].purpose self.plugininfo[modpath]['author'] = self.pluginp[ modpath].author self.plugininfo[modpath]['version'] = self.pluginp[ modpath].version self.plugininfo[modpath]['modpath'] = modpath self.plugininfo[modpath]['fullimploc'] = fullimploc else: try: _module = __import__(fullimploc) _module = sys.modules[fullimploc] self.plugininfo[modpath] = {} self.plugininfo[modpath]['sname'] = _module.SNAME self.plugininfo[modpath]['name'] = _module.NAME self.plugininfo[modpath]['purpose'] = _module.PURPOSE self.plugininfo[modpath]['author'] = _module.AUTHOR self.plugininfo[modpath]['version'] = _module.VERSION self.plugininfo[modpath]['modpath'] = modpath self.plugininfo[modpath]['fullimploc'] = fullimploc del sys.modules[fullimploc] except Exception: # pylint: disable=broad-except badplugins.append(fullimploc) return badplugins def load_module(self, modpath, basepath, force=False, runload=True): # pylint: disable=too-many-branches """ load a single module """ if basepath in modpath: modpath = modpath.replace(basepath, '') imploc, modname = get_module_name(modpath) if modname.startswith("_"): return False, 'dev' try: fullimploc = "plugins" + '.' + imploc if fullimploc in sys.modules: return sys.modules[fullimploc].SNAME, 'already' self.api.get('send.msg')('importing %s' % fullimploc, self.sname) _module = __import__(fullimploc) _module = sys.modules[fullimploc] self.api.get('send.msg')('imported %s' % fullimploc, self.sname) load = True if 'AUTOLOAD' in _module.__dict__ and not force: if not _module.AUTOLOAD: load = False elif 'AUTOLOAD' not in _module.__dict__: load = False if modpath not in self.plugininfo: self.plugininfo[modpath] = {} self.plugininfo[modpath]['sname'] = _module.SNAME self.plugininfo[modpath]['name'] = _module.NAME self.plugininfo[modpath]['purpose'] = _module.PURPOSE self.plugininfo[modpath]['author'] = _module.AUTHOR self.plugininfo[modpath]['version'] = _module.VERSION self.plugininfo[modpath]['modpath'] = modpath self.plugininfo[modpath]['fullimploc'] = fullimploc if load: if "Plugin" in _module.__dict__: self.add_plugin(_module, modpath, basepath, fullimploc, runload) else: self.api.get('send.msg')('Module %s has no Plugin class' % \ _module.NAME, self.sname) _module.__dict__["proxy_import"] = 1 return _module.SNAME, 'Loaded' else: if fullimploc in sys.modules: del sys.modules[fullimploc] self.api.get('send.msg')( 'Not loading %s (%s) because autoload is False' % \ (_module.NAME, fullimploc), self.sname) return True, 'not autoloaded' except Exception: # pylint: disable=broad-except if fullimploc in sys.modules: del sys.modules[fullimploc] self.api.get('send.traceback')( "Module '%s' refuses to import/load." % fullimploc) return False, 'error' def unload_module(self, fullimploc): """ unload a module """ if fullimploc in sys.modules: _module = sys.modules[fullimploc] try: if "proxy_import" in _module.__dict__: self.api.get('send.client')('unload: unloading %s' % fullimploc) if "unload" in _module.__dict__: try: _module.unload() except Exception: # pylint: disable=broad-except self.api.get('send.traceback')( "unload: module %s didn't unload properly." % fullimploc) if not self.remove_plugin(_module.SNAME): self.api.get('send.client')( 'could not remove plugin %s' % fullimploc) del sys.modules[fullimploc] self.api.get('send.client')("unload: unloaded %s." % fullimploc) except Exception: # pylint: disable=broad-except self.api.get('send.traceback')( "unload: had problems unloading %s." % fullimploc) return False return True def reload_module(self, modname, force=False): """ reload a module """ if modname in self.plugins: plugin = self.plugins[modname] fullimploc = plugin.fullimploc basepath = plugin.basepath modpath = plugin.modpath sname = plugin.sname try: reloaddependents = plugin.reloaddependents except Exception: # pylint: disable=broad-except reloaddependents = False plugin = None if not self.unload_module(fullimploc): return False, '' if modpath and basepath: retval = self.load_module(modpath, basepath, force) if retval and reloaddependents: self.reloaddependents(sname) return retval else: return False, '' def reloaddependents(self, reloadedplugin): """ reload all dependents """ testsort = sorted(self.plugins.values(), key=operator.attrgetter('priority')) for plugin in testsort: if plugin.sname != reloadedplugin: if reloadedplugin in plugin.dependencies: self.api.get('send.msg')('reloading dependent %s of %s' % \ (plugin.sname, reloadedplugin)) plugin.savestate() self.reload_module(plugin.sname, True) def loadplugin(self, plugin): """ check dependencies and run the load function """ self.api.get('send.msg')('loading dependencies for %s' % \ plugin.fullimploc, self.sname) self.loaddependencies(plugin.sname, plugin.dependencies) self.api.get('send.client')("load: loading %s with priority %s" % \ (plugin.fullimploc, plugin.priority)) self.api.get('send.msg')('loading %s (%s: %s)' % \ (plugin.fullimploc, plugin.sname, plugin.name), self.sname) plugin.load() self.api.get('send.client')("load: loaded %s" % plugin.fullimploc) self.api.get('send.msg')('loaded %s (%s: %s)' % \ (plugin.fullimploc, plugin.sname, plugin.name), self.sname) self.api.get('events.eraise')('%s_plugin_loaded' % plugin.sname, {}) self.api.get('events.eraise')('plugin_loaded', { 'plugin': plugin.sname }) def add_plugin(self, module, modpath, basepath, fullimploc, load=True): # pylint: disable=too-many-arguments """ add a plugin to be managed """ module.__dict__["lyntin_import"] = 1 plugin = module.Plugin(module.NAME, module.SNAME, modpath, basepath, fullimploc) plugin.author = module.AUTHOR plugin.purpose = module.PURPOSE plugin.version = module.VERSION try: plugin.priority = module.PRIORITY except AttributeError: pass if plugin.name in self.pluginl: self.api.get('send.msg')('Plugin %s already exists' % plugin.name, self.sname) return False if plugin.sname in self.plugins: self.api.get('send.msg')('Plugin %s already exists' % plugin.sname, self.sname) return False if load: try: #check dependencies here self.loadplugin(plugin) except Exception: # pylint: disable=broad-except self.api.get('send.traceback')( "load: had problems running the load method for %s." \ % fullimploc) del sys.modules[fullimploc] return False self.pluginl[plugin.name] = plugin self.plugins[plugin.sname] = plugin self.pluginm[plugin.sname] = module self.pluginp[modpath] = plugin self.loadedplugins[modpath] = True self.loadedplugins.sync() return True def remove_plugin(self, pluginname): """ remove a plugin """ plugin = None if pluginname in self.plugins: plugin = self.plugins[pluginname] try: plugin.unload() self.api.get('events.eraise')('%s_plugin_unload' % plugin.sname, {}) self.api.get('events.eraise')('plugin_unloaded', { 'name': plugin.sname }) self.api.get('send.msg')('Plugin %s unloaded' % plugin.sname, self.sname, plugin.sname) except Exception: # pylint: disable=broad-except self.api.get('send.traceback')( "unload: had problems running the unload method for %s." \ % plugin.sname) return False del self.plugins[plugin.sname] del self.pluginl[plugin.name] del self.pluginm[plugin.sname] del self.loadedplugins[plugin.modpath] self.loadedplugins.sync() plugin = None return True else: return False # save all plugins def savestate(self): """ save all plugins """ for i in self.plugins: self.plugins[i].savestate() def load(self): """ load various things """ self.load_modules("*.py") parser = argparse.ArgumentParser(add_help=False, description="list plugins") parser.add_argument('-n', "--notloaded", help="list plugins that are not loaded", action="store_true") parser.add_argument( '-c', "--changed", help="list plugins that are load but are changed on disk", action="store_true") parser.add_argument('package', help='the to list', default='', nargs='?') self.api.get('commands.add')('list', self.cmd_list, lname='Plugin Manager', parser=parser) parser = argparse.ArgumentParser(add_help=False, description="load a plugin") parser.add_argument('plugin', help='the plugin to load, don\'t include the .py', default='', nargs='?') self.api.get('commands.add')('load', self.cmd_load, lname='Plugin Manager', parser=parser) parser = argparse.ArgumentParser(add_help=False, description="unload a plugin") parser.add_argument('plugin', help='the plugin to unload', default='', nargs='?') self.api.get('commands.add')('unload', self.cmd_unload, lname='Plugin Manager', parser=parser) parser = argparse.ArgumentParser(add_help=False, description="reload a plugin") parser.add_argument('plugin', help='the plugin to reload', default='', nargs='?') self.api.get('commands.add')('reload', self.cmd_reload, lname='Plugin Manager', parser=parser) self.api.get('commands.default')('list', self.sname) self.api.get('events.register')('savestate', self.savestate, plugin=self.sname) self.api.get('timers.add')('save', self.savestate, 60, nodupe=True, log=False)
class BasePlugin(object): # pylint: disable=too-many-instance-attributes """ a base class for plugins """ def __init__(self, name, sname, modpath, basepath, fullimploc): # pylint: disable=too-many-arguments """ initialize the instance The following things should not be done in __init__ in a plugin Interacting with anything in the api except api.add, api.overload or dependency.add """ # Examples: # name : 'Actions' - from plugin file variable NAME (long name) # sname : 'actions' - from plugin file variable SNAME (short name) # modpath : '/client/actions.py' - path relative to the plugins directory # basepath : '/home/src/games/bastproxy/bp/plugins' - the full path to the # plugins directory # fullimploc : 'plugins.client.actions' - import location self.author = '' self.purpose = '' self.version = 0 self.priority = 100 self.name = name self.sname = sname self.dependencies = [] self.versionfuncs = {} self.reloaddependents = False self.summarytemplate = "%20s : %s" self.canreload = True self.canreset = True self.resetflag = True self.api = API() self.firstactiveprio = None self.loadedtime = time.time() self.savedir = os.path.join(self.api.BASEPATH, 'data', 'plugins', self.sname) try: os.makedirs(self.savedir) except OSError: pass self.savefile = os.path.join(self.api.BASEPATH, 'data', 'plugins', self.sname, 'settingvalues.txt') self.modpath = modpath self.basepath = basepath self.fullimploc = fullimploc self.pluginfile = os.path.join(basepath, modpath[1:]) self.pluginlocation = os.path.normpath( os.path.join(self.api.BASEPATH, 'plugins') + \ os.sep + os.path.dirname(self.modpath)) self.package = fullimploc.split('.')[1] self.settings = {} self.settingvalues = PersistentDictEvent(self, self.savefile, 'c') self._dump_shallow_attrs = ['api'] self.api.overload('dependency', 'add', self._api_dependencyadd) self.api.overload('setting', 'add', self._api_settingadd) self.api.overload('setting', 'gets', self._api_settinggets) self.api.overload('setting', 'change', self._api_settingchange) self.api.overload('api', 'add', self._api_add) def _loadcommands(self): """ load the commands """ parser = argp.ArgumentParser( add_help=False, formatter_class=argp.RawDescriptionHelpFormatter, description=textwrap.dedent(""" change a setting in the plugin if there are no arguments or 'list' is the first argument then it will list the settings for the plugin""")) parser.add_argument('name', help='the setting name', default='list', nargs='?') parser.add_argument('value', help='the new value of the setting', default='', nargs='?') self.api('commands.add')('set', self._cmd_set, parser=parser, group='Base', showinhistory=False) if self.canreset: parser = argp.ArgumentParser(add_help=False, description='reset the plugin') self.api('commands.add')('reset', self._cmd_reset, parser=parser, group='Base') parser = argp.ArgumentParser(add_help=False, description='save the plugin state') self.api('commands.add')('save', self._cmd_save, parser=parser, group='Base') parser = argp.ArgumentParser(add_help=False, description='show plugin stats') self.api('commands.add')('stats', self._cmd_stats, parser=parser, group='Base') parser = argp.ArgumentParser(add_help=False, description='inspect a plugin') parser.add_argument('-m', "--method", help="get code for a method", default='') parser.add_argument( '-o', "--object", help="show an object of the plugin, can be method or variable", default='') parser.add_argument('-s', "--simple", help="show a simple output", action="store_true") self.api('commands.add')('inspect', self._cmd_inspect, parser=parser, group='Base') parser = argp.ArgumentParser( add_help=False, description='show help info for this plugin') parser.add_argument('-a', "--api", help="show functions this plugin has in the api", action="store_true") parser.add_argument('-c', "--commands", help="show commands in this plugin", action="store_true") self.api('commands.add')('help', self._cmd_help, parser=parser, group='Base') parser = argp.ArgumentParser(add_help=False, description='list functions in the api') parser.add_argument('api', help='api to get details of', default='', nargs='?') self.api('commands.add')('api', self._cmd_api, parser=parser, group='Base') def load(self): """ load stuff, do most things here """ self.settingvalues.pload() if '_version' in self.settingvalues and \ self.settingvalues['_version'] != self.version: self._updateversion(self.settingvalues['_version'], self.version) self.api('log.adddtype')(self.sname) self._loadcommands() self.api('events.register')('%s_plugin_loaded' % self.sname, self.__afterload) self.api('events.register')('muddisconnect', self.__disconnect) self.api('events.register')('plugin_%s_savestate' % self.sname, self.__savestate) self.resetflag = False def _updateversion(self, oldversion, newversion): """ update plugin data """ if oldversion != newversion and newversion > oldversion: for i in range(oldversion + 1, newversion + 1): self.api('send.msg')('%s: upgrading to version %s' % (self.sname, i), secondary='upgrade') if i in self.versionfuncs: self.versionfuncs[i]() else: self.api('send.msg')( '%s: no function to upgrade to version %s' % (self.sname, i), secondary='upgrade') self.settingvalues.sync() def _cmd_inspect(self, args): # pylint: disable=too-many-branches """ show the plugin as it currently is in memory """ from libs.objectdump import dumps as dumper tmsg = [] if args['method']: try: tmeth = getattr(self, args['method']) tmsg.append(inspect.getsource(tmeth)) except AttributeError: tmsg.append('There is no method named %s' % args['method']) elif args['object']: tobj = args['object'] key = None if ':' in tobj: tobj, key = tobj.split(':') obj = getattr(self, tobj) if obj: if key: if key not in obj: try: key = int(key) except ValueError: pass if key in obj: obj = obj[key] if args['simple']: tvars = pprint.pformat(obj) else: tvars = dumper(obj) tmsg.append(tvars) else: if args['simple']: tvars = pprint.pformat(vars(self)) else: tvars = dumper(self) tmsg.append('@M' + '-' * 60 + '@x') tmsg.append('Variables') tmsg.append('@M' + '-' * 60 + '@x') tmsg.append(tvars) tmsg.append('@M' + '-' * 60 + '@x') tmsg.append('Methods') tmsg.append('@M' + '-' * 60 + '@x') tmsg.append( pprint.pformat(inspect.getmembers(self, inspect.ismethod))) return True, tmsg def _cmd_api(self, args): """ list functions in the api for a plugin """ tmsg = [] if args['api']: tmsg.extend( self.api('api.detail')("%s.%s" % (self.sname, args['api']))) else: apilist = self.api('api.list')(self.sname) if not apilist: tmsg.append('nothing in the api') else: tmsg.extend(apilist) return True, tmsg def __afterload(self, args): # pylint: disable=unused-argument """ do something after the load function is run """ # go through each variable and raise var_%s_changed self.settingvalues.raiseall() mud = self.api('managers.getm')('mud') if mud and mud.connected: if self.api('api.has')('connect.firstactive'): if self.api('connect.firstactive')(): self.afterfirstactive() else: self.api('events.register')('firstactive', self.afterfirstactive, prio=self.firstactiveprio) else: self.api('events.register')('firstactive', self.afterfirstactive, prio=self.firstactiveprio) def __disconnect(self, args=None): # pylint: disable=unused-argument """ re-register to firstactive on disconnect """ self.api('send.msg')('baseplugin, disconnect') self.api('events.register')('firstactive', self.afterfirstactive) def afterfirstactive(self, args=None): # pylint: disable=unused-argument """ if we are connected do """ self.api('send.msg')('baseplugin, firstactive') if self.api('events.isregistered')('firstactive', self.afterfirstactive): self.api('events.unregister')('firstactive', self.afterfirstactive) # get the vaule of a setting def _api_settinggets(self, setting): """ get the value of a setting @Ysetting@w = the setting value to get this function returns the value of the setting, None if not found""" try: return self.api('utils.verify')(self.settingvalues[setting], self.settings[setting]['stype']) except KeyError: return None # add a plugin dependency def _api_dependencyadd(self, dependency): """ add a depencency @Ydependency@w = the name of the plugin that will be a dependency this function returns no values""" if dependency not in self.dependencies: self.dependencies.append(dependency) # change the value of a setting def _api_settingchange(self, setting, value): """ change a setting @Ysetting@w = the name of the setting to change @Yvalue@w = the value to set it as this function returns True if the value was changed, False otherwise""" if value == 'default': value = self.settings[setting]['default'] if setting in self.settings: self.settingvalues[setting] = self.api('utils.verify')( value, self.settings[setting]['stype']) self.settingvalues.sync() return True return False def getstats(self): """ get the stats for the plugin """ stats = {} stats['Base Sizes'] = {} stats['Base Sizes']['showorder'] = ['Class', 'Variables', 'Api'] stats['Base Sizes']['Variables'] = '%s bytes' % \ sys.getsizeof(self.settingvalues) stats['Base Sizes']['Class'] = '%s bytes' % sys.getsizeof(self) stats['Base Sizes']['Api'] = '%s bytes' % sys.getsizeof(self.api) return stats def _cmd_stats(self, args=None): # pylint: disable=unused-argument """ @G%(name)s@w - @B%(cmdname)s@w show stats, memory, profile, etc.. for this plugin @CUsage@w: stats """ stats = self.getstats() tmsg = [] for header in stats: tmsg.append(self.api('utils.center')(header, '=', 60)) for subtype in stats[header]['showorder']: tmsg.append('%-20s : %s' % (subtype, stats[header][subtype])) return True, tmsg def unload(self, _=None): """ unload stuff """ self.api('send.msg')('unloading %s' % self.name) # remove anything out of the api self.api('api.remove')(self.sname) #save the state self.savestate() def __savestate(self, _=None): """ save the settings state """ self.settingvalues.sync() def savestate(self, _=None): """ save all settings for the plugin do not overload! attach to the plugin_<pluginname>_savestate event """ self.api('events.eraise')('plugin_%s_savestate' % self.sname) def _cmd_set(self, args): """ @G%(name)s@w - @B%(cmdname)s@w List or set vars @CUsage@w: var @Y<varname>@w @Y<varvalue>@w @Ysettingname@w = The setting to set @Ysettingvalue@w = The value to set it to if there are no arguments or 'list' is the first argument then it will list the settings for the plugin """ msg = [] if args['name'] == 'list': return True, self._listvars() elif args['name'] and args['value']: var = args['name'] val = args['value'] if var in self.settings: if 'readonly' in self.settings[var] \ and self.settings[var]['readonly']: return True, ['%s is a readonly setting' % var] else: try: self.api('setting.change')(var, val) tvar = self.settingvalues[var] if self.settings[var]['nocolor']: tvar = tvar.replace('@', '@@') elif self.settings[var]['stype'] == 'color': tvar = '%s%s@w' % (val, val.replace('@', '@@')) elif self.settings[var]['stype'] == 'timelength': tvar = self.api('utils.formattime')( self.api('utils.verify')(val, 'timelength')) return True, ['%s is now set to %s' % (var, tvar)] except ValueError: msg = ['Cannot convert %s to %s' % \ (val, self.settings[var]['stype'])] return True, msg return True, self._listvars() else: msg = ['plugin setting %s does not exist' % var] return False, msg def _cmd_save(self, args): # pylint: disable=unused-argument """ @G%(name)s@w - @B%(cmdname)s@w save plugin state @CUsage@w: save """ self.savestate() return True, ['Plugin settings saved'] def _cmd_help(self, args): """ test command """ msg = [] if '.__init__' in self.fullimploc: imploc = self.fullimploc.replace('.__init__', '') else: imploc = self.fullimploc msg.extend(sys.modules[imploc].__doc__.split('\n')) if args['commands']: cmdlist = self.api('commands.list')(self.sname) if cmdlist: msg.extend(self.api('commands.list')(self.sname)) msg.append('@G' + '-' * 60 + '@w') msg.append('') if args['api']: apilist = self.api('api.list')(self.sname) if apilist: msg.append('API functions in %s' % self.sname) msg.append('@G' + '-' * 60 + '@w') msg.extend(self.api('api.list')(self.sname)) return True, msg def _listvars(self): """ return a list of strings that list all settings """ tmsg = [] if not self.settingvalues: tmsg.append('There are no settings defined') else: tform = '%-15s : %-15s - %s' for i in self.settings: val = self.settingvalues[i] if 'nocolor' in self.settings[i] and self.settings[i][ 'nocolor']: val = val.replace('@', '@@') elif self.settings[i]['stype'] == 'color': val = '%s%s@w' % (val, val.replace('@', '@@')) elif self.settings[i]['stype'] == 'timelength': val = self.api('utils.formattime')( self.api('utils.verify')(val, 'timelength')) tmsg.append(tform % (i, val, self.settings[i]['help'])) return tmsg # add a setting to the plugin def _api_settingadd(self, name, default, stype, shelp, **kwargs): """ remove a command @Yname@w = the name of the setting @Ydefault@w = the default value of the setting @Ystype@w = the type of the setting @Yshelp@w = the help associated with the setting Keyword Arguments @Ynocolor@w = if True, don't parse colors when showing value @Yreadonly@w = if True, can't be changed by a client this function returns no values""" if 'nocolor' in kwargs: nocolor = kwargs['nocolor'] else: nocolor = False if 'readonly' in kwargs: readonly = kwargs['readonly'] else: readonly = False if name not in self.settingvalues: self.settingvalues[name] = default self.settings[name] = { 'default': default, 'help': shelp, 'stype': stype, 'nocolor': nocolor, 'readonly': readonly } def _cmd_reset(self, _=None): """ @G%(name)s@w - @B%(cmdname)s@w reset the plugin @CUsage@w: reset """ if self.canreset: self.reset() return True, ['Plugin reset'] return True, ['This plugin cannot be reset'] def ischangedondisk(self): """ check to see if the file this plugin is based on has changed on disk """ ftime = os.path.getmtime(self.pluginfile) if ftime > self.loadedtime: return True return False def reset(self): """ internal function to reset data """ if self.canreset: self.resetflag = True self.settingvalues.clear() for i in self.settings: self.settingvalues[i] = self.settings[i]['default'] self.settingvalues.sync() self.resetflag = False # add a function to the api def _api_add(self, name, func): """ add a command to the api """ # we call the non overloaded versions self.api.add(self.sname, name, func)
class BasePlugin(object): # pylint: disable=too-many-public-methods,too-many-instance-attributes """ a base class for plugins """ def __init__(self, name, sname, modpath, basepath, fullimploc): # pylint: disable=too-many-arguments """ initialize the instance The following things should not be done in __init__ in a plugin Interacting with anything in the api except api.add, api.overload or dependency.add """ self.author = '' self.purpose = '' self.version = 0 self.priority = 100 self.name = name self.sname = sname self.dependencies = [] self.versionfuncs = {} self.reloaddependents = False self.canreload = True self.resetflag = True self.api = API() self.loadedtime = time.time() self.savedir = os.path.join(self.api.BASEPATH, 'data', 'plugins', self.sname) try: os.makedirs(self.savedir) except OSError: pass self.savefile = os.path.join(self.api.BASEPATH, 'data', 'plugins', self.sname, 'settingvalues.txt') self.modpath = modpath self.basepath = basepath self.fullimploc = fullimploc self.pluginfile = os.path.join(basepath, modpath[1:]) self.pluginlocation = os.path.normpath( os.path.join(self.api.BASEPATH, 'plugins') + \ os.sep + os.path.dirname(self.modpath)) self.package = fullimploc.split('.')[1] self.settings = {} self.settingvalues = PersistentDictEvent(self, self.savefile, 'c') self._dump_shallow_attrs = ['api'] self.api.overload('dependency', 'add', self.api_dependencyadd) self.api.overload('setting', 'add', self.api_settingadd) self.api.overload('setting', 'gets', self.api_settinggets) self.api.overload('setting', 'change', self.api_settingchange) self.api.overload('api', 'add', self.api_add) def load(self): """ load stuff, do most things here """ self.settingvalues.pload() if '_version' in self.settingvalues and \ self.settingvalues['_version'] != self.version: self.updateversion(self.settingvalues['_version'], self.version) self.api.get('log.adddtype')(self.sname) parser = argparse.ArgumentParser( add_help=False, formatter_class=argparse.RawDescriptionHelpFormatter, description=textwrap.dedent(""" change a setting in the plugin if there are no arguments or 'list' is the first argument then it will list the settings for the plugin""")) parser.add_argument('name', help='the setting name', default='list', nargs='?') parser.add_argument('value', help='the new value of the setting', default='', nargs='?') self.api.get('commands.add')('set', self.cmd_set, parser=parser, group='Base', history=False) parser = argparse.ArgumentParser(add_help=False, description='reset the plugin') self.api.get('commands.add')('reset', self.cmd_reset, parser=parser, group='Base') parser = argparse.ArgumentParser(add_help=False, description='save the plugin state') self.api.get('commands.add')('save', self.cmd_save, parser=parser, group='Base') parser = argparse.ArgumentParser(add_help=False, description='show plugin stats') self.api.get('commands.add')('stats', self.cmd_stats, parser=parser, group='Base') parser = argparse.ArgumentParser(add_help=False, description='inspect a plugin') parser.add_argument('-m', "--method", help="get code for a method", default='') parser.add_argument('-o', "--object", help="show an object of the plugin, can be method or variable", default='') parser.add_argument('-s', "--simple", help="show a simple output", action="store_true") self.api.get('commands.add')('inspect', self.cmd_inspect, parser=parser, group='Base') parser = argparse.ArgumentParser(add_help=False, description='show help info for this plugin') parser.add_argument('-a', "--api", help="show functions this plugin has in the api", action="store_true") parser.add_argument('-c', "--commands", help="show commands in this plugin", action="store_true") self.api.get('commands.add')('help', self.cmd_help, parser=parser, group='Base') parser = argparse.ArgumentParser(add_help=False, description='list functions in the api') parser.add_argument('api', help='api to get details of', default='', nargs='?') self.api.get('commands.add')('api', self.cmd_api, parser=parser, group='Base') self.api.get('events.register')('%s_plugin_loaded' % self.sname, self.afterload) self.api.get('events.register')('muddisconnect', self.disconnect) self.resetflag = False def updateversion(self, oldversion, newversion): """ update plugin data """ if oldversion != newversion and newversion > oldversion: for i in range(oldversion + 1, newversion + 1): self.api.get('send.msg')( '%s: upgrading to version %s' % (self.sname, i), secondary='upgrade') if i in self.versionfuncs: self.versionfuncs[i]() else: self.api.get('send.msg')( '%s: no function to upgrade to version %s' % (self.sname, i), secondary='upgrade') self.settingvalues.sync() def cmd_inspect(self, args): # pylint: disable=too-many-branches """ show the plugin as it currently is in memory """ from libs.objectdump import dumps as dumper tmsg = [] if args['method']: try: tmeth = getattr(self, args['method']) tmsg.append(inspect.getsource(tmeth)) except AttributeError: tmsg.append('There is no method named %s' % args['method']) elif args['object']: tobj = args['object'] key = None if ':' in tobj: tobj, key = tobj.split(':') obj = getattr(self, tobj) if obj: if key: if key not in obj: try: key = int(key) except ValueError: pass if key in obj: obj = obj[key] if args['simple']: tvars = pprint.pformat(obj) else: tvars = dumper(obj) tmsg.append(tvars) else: if args['simple']: tvars = pprint.pformat(vars(self)) else: tvars = dumper(self) tmsg.append('@M' + '-' * 60 + '@x') tmsg.append('Variables') tmsg.append('@M' + '-' * 60 + '@x') tmsg.append(tvars) tmsg.append('@M' + '-' * 60 + '@x') tmsg.append('Methods') tmsg.append('@M' + '-' * 60 + '@x') tmsg.append(pprint.pformat(inspect.getmembers(self, inspect.ismethod))) return True, tmsg def cmd_api(self, args): """ list functions in the api for a plugin """ tmsg = [] if args['api']: tmsg.extend(self.api.get('api.detail')("%s.%s" % (self.sname, args['api']))) else: apilist = self.api.get('api.list')(self.sname) if not apilist: tmsg.append('nothing in the api') else: tmsg.extend(apilist) return True, tmsg def afterload(self, args): # pylint: disable=unused-argument """ do something after the load function is run """ proxy = self.api.get('managers.getm')('proxy') if proxy and proxy.connected: if self.api.get('api.has')('connect.firstactive'): if self.api.get('connect.firstactive')(): self.afterfirstactive() else: self.api.get('events.register')('firstactive', self.afterfirstactive) else: self.api.get('events.register')('firstactive', self.afterfirstactive) def disconnect(self, args=None): # pylint: disable=unused-argument """ re-register to firstactive on disconnect """ self.api.get('send.msg')('baseplugin, disconnect') self.api.get('events.register')('firstactive', self.afterfirstactive) # get the vaule of a setting def api_settinggets(self, setting): """ get the value of a setting @Ysetting@w = the setting value to get this function returns the value of the setting, None if not found""" try: return self.api.get('utils.verify')(self.settingvalues[setting], self.settings[setting]['stype']) except KeyError: return None # add a plugin dependency def api_dependencyadd(self, dependency): """ add a depencency @Ydependency@w = the name of the plugin that will be a dependency this function returns no values""" if dependency not in self.dependencies: self.dependencies.append(dependency) # change the value of a setting def api_settingchange(self, setting, value): """ change a setting @Ysetting@w = the name of the setting to change @Yvalue@w = the value to set it as this function returns True if the value was changed, False otherwise""" if value == 'default': value = self.settings[setting]['default'] if setting in self.settings: self.settingvalues[setting] = self.api.get('utils.verify')( value, self.settings[setting]['stype']) self.settingvalues.sync() return True return False def getstats(self): """ get the stats for the plugin """ stats = {} stats['Base Sizes'] = {} stats['Base Sizes']['showorder'] = ['Class', 'Variables', 'Api'] stats['Base Sizes']['Variables'] = '%s bytes' % \ sys.getsizeof(self.settingvalues) stats['Base Sizes']['Class'] = '%s bytes' % sys.getsizeof(self) stats['Base Sizes']['Api'] = '%s bytes' % sys.getsizeof(self.api) return stats def cmd_stats(self, args=None): # pylint: disable=unused-argument """ @G%(name)s@w - @B%(cmdname)s@w show stats, memory, profile, etc.. for this plugin @CUsage@w: stats """ stats = self.getstats() tmsg = [] for header in stats: tmsg.append(self.api.get('utils.center')(header, '=', 60)) for subtype in stats[header]['showorder']: tmsg.append('%-20s : %s' % (subtype, stats[header][subtype])) return True, tmsg def unload(self, _=None): """ unload stuff """ self.api.get('send.msg')('unloading %s' % self.name) # remove anything out of the api self.api.get('api.remove')(self.sname) #save the state self.savestate() def savestate(self): """ save the state """ self.settingvalues.sync() def cmd_set(self, args): """ @G%(name)s@w - @B%(cmdname)s@w List or set vars @CUsage@w: var @Y<varname>@w @Y<varvalue>@w @Ysettingname@w = The setting to set @Ysettingvalue@w = The value to set it to if there are no arguments or 'list' is the first argument then it will list the settings for the plugin """ msg = [] if args['name'] == 'list': return True, self.listvars() elif args['name'] and args['value']: var = args['name'] val = args['value'] if var in self.settings: if 'readonly' in self.settings[var] \ and self.settings[var]['readonly']: return True, ['%s is a readonly setting' % var] else: try: self.api.get('setting.change')(var, val) tvar = self.settingvalues[var] if self.settings[var]['nocolor']: tvar = tvar.replace('@', '@@') elif self.settings[var]['stype'] == 'color': tvar = '%s%s@w' % (val, val.replace('@', '@@')) elif self.settings[var]['stype'] == 'timelength': tvar = self.api.get('utils.formattime')( self.api.get('utils.verify')(val, 'timelength')) return True, ['%s is now set to %s' % (var, tvar)] except ValueError: msg = ['Cannot convert %s to %s' % \ (val, self.settings[var]['stype'])] return True, msg return True, self.listvars() else: msg = ['plugin setting %s does not exist' % var] return False, msg def cmd_save(self, args): # pylint: disable=unused-argument """ @G%(name)s@w - @B%(cmdname)s@w save plugin state @CUsage@w: save """ self.savestate() return True, ['Plugin settings saved'] def cmd_help(self, args): """ test command """ msg = [] msg.extend(sys.modules[self.fullimploc].__doc__.split('\n')) if args['commands']: cmdlist = self.api.get('commands.list')(self.sname) if cmdlist: msg.extend(self.api.get('commands.list')(self.sname)) msg.append('@G' + '-' * 60 + '@w') msg.append('') if args['api']: apilist = self.api.get('api.list')(self.sname) if apilist: msg.append('API functions in %s' % self.sname) msg.append('@G' + '-' * 60 + '@w') msg.extend(self.api.get('api.list')(self.sname)) return True, msg def listvars(self): """ return a list of strings that list all settings """ tmsg = [] if len(self.settingvalues) == 0: tmsg.append('There are no settings defined') else: tform = '%-15s : %-15s - %s' for i in self.settings: val = self.settingvalues[i] if 'nocolor' in self.settings[i] and self.settings[i]['nocolor']: val = val.replace('@', '@@') elif self.settings[i]['stype'] == 'color': val = '%s%s@w' % (val, val.replace('@', '@@')) elif self.settings[i]['stype'] == 'timelength': val = self.api.get('utils.formattime')( self.api.get('utils.verify')(val, 'timelength')) tmsg.append(tform % (i, val, self.settings[i]['help'])) return tmsg # add a setting to the plugin def api_settingadd(self, name, default, stype, shelp, **kwargs): """ remove a command @Yname@w = the name of the setting @Ydefault@w = the default value of the setting @Ystype@w = the type of the setting @Yshelp@w = the help associated with the setting Keyword Arguments @Ynocolor@w = if True, don't parse colors when showing value @Yreadonly@w = if True, can't be changed by a client this function returns no values""" if 'nocolor' in kwargs: nocolor = kwargs['nocolor'] else: nocolor = False if 'readonly' in kwargs: readonly = kwargs['readonly'] else: readonly = False if name not in self.settingvalues: self.settingvalues[name] = default self.settings[name] = { 'default':default, 'help':shelp, 'stype':stype, 'nocolor':nocolor, 'readonly':readonly } def cmd_reset(self, _=None): """ @G%(name)s@w - @B%(cmdname)s@w reset the plugin @CUsage@w: reset """ self.reset() return True, ['Plugin reset'] def ischangedondisk(self): """ check to see if the file this plugin is based on has changed on disk """ ftime = os.path.getmtime(self.pluginfile) if ftime > self.loadedtime: return True return False def reset(self): """ internal function to reset data """ self.resetflag = True self.settingvalues.clear() for i in self.settings: self.settingvalues[i] = self.settings[i]['default'] self.settingvalues.sync() self.resetflag = False def afterfirstactive(self, _=None): """ if we are connected do """ self.api.get('send.msg')('baseplugin, firstactive') self.api.get('events.unregister')('firstactive', self.afterfirstactive) # add a function to the api def api_add(self, name, func): """ add a command to the api """ # we call the non overloaded versions self.api.add(self.sname, name, func)
""" handle output and input functions, adds items under the send api """ import time import sys import traceback import re from libs.api import API as BASEAPI API = BASEAPI() # send a message def api_msg(tmsg, primary='default', secondary=None): """ send a message through the log plugin @Ymsg@w = This message to send @Yprimary@w = the primary datatype of the message (default: 'default') @Ysecondary@w = the secondary datatype of the message (default: 'None') this function returns no values""" if primary == 'default': try: primary = API('utils.funccallerplugin')() or primary except (AttributeError, RuntimeError): pass if not isinstance(secondary, list): tmpl = [] if secondary: tmpl.append(secondary) secondary = tmpl