Example #1
0
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    AardwolfBasePlugin.__init__(self, *args, **kwargs)
    self.saveskillfile = os.path.join(self.savedir, 'skills.txt')
    self.skills = PersistentDict(self.saveskillfile, 'c')
    self.skillsnamelookup = {}
    for i in self.skills:
      self.skillsnamelookup[self.skills[i]['name']] = i

    self.saverecovfile = os.path.join(self.savedir, 'recoveries.txt')
    self.recoveries = PersistentDict(self.saverecovfile, 'c')
    self.recoveriesnamelookup = {}
    for i in self.recoveries:
      self.recoveriesnamelookup[self.recoveries[i]['name']] = i

    self.current = ''
    self.isuptodatef = False

    self.cmdqueue = None

    self.api.get('dependency.add')('cmdq')

    self.api.get('api.add')('gets', self.api_getskill)
    self.api.get('api.add')('isspellup', self.api_isspellup)
    self.api.get('api.add')('getspellups', self.api_getspellups)
    self.api.get('api.add')('sendcmd', self.api_sendcmd)
    self.api.get('api.add')('isaffected', self.api_isaffected)
    self.api.get('api.add')('isblockedbyrecovery',
                                        self.api_isblockedbyrecovery)
    self.api.get('api.add')('ispracticed', self.api_ispracticed)
    self.api.get('api.add')('canuse', self.api_canuse)
    self.api.get('api.add')('isuptodate', self.api_isuptodate)
    self.api.get('api.add')('isbad', self.api_isbad)
Example #2
0
  def __init__(self, *args, **kwargs):
    """
    init the class
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.canreload = False

    self.cmds = {}
    self.nomultiplecmds = {}

    self.savehistfile = os.path.join(self.savedir, 'history.txt')
    self.cmdhistorydict = PersistentDict(self.savehistfile, 'c')
    if 'history' not in self.cmdhistorydict:
      self.cmdhistorydict['history'] = []
    self.cmdhistory = self.cmdhistorydict['history']

    self.api.get('api.add')('add', self.api_addcmd)
    self.api.get('api.add')('remove', self.api_removecmd)
    self.api.get('api.add')('change', self.api_changecmd)
    self.api.get('api.add')('default', self.api_setdefault)
    self.api.get('api.add')('removeplugin', self.api_removeplugin)
    self.api.get('api.add')('list', self.api_listcmds)
    self.api.get('api.add')('run', self.api_run)
    self.api.get('api.add')('cmdhelp', self.api_cmdhelp)
Example #3
0
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        AardwolfBasePlugin.__init__(self, *args, **kwargs)
        self.saveskillfile = os.path.join(self.savedir, 'skills.txt')
        self.skills = PersistentDict(self.saveskillfile, 'c')
        self.skillsnamelookup = {}
        for i in self.skills:
            self.skillsnamelookup[self.skills[i]['name']] = i

        self.saverecovfile = os.path.join(self.savedir, 'recoveries.txt')
        self.recoveries = PersistentDict(self.saverecovfile, 'c')
        self.recoveriesnamelookup = {}
        for i in self.recoveries:
            self.recoveriesnamelookup[self.recoveries[i]['name']] = i

        self.current = ''
        self.isuptodatef = False

        self.cmdqueue = None

        self.api.get('dependency.add')('cmdq')

        self.api.get('api.add')('gets', self.api_getskill)
        self.api.get('api.add')('isspellup', self.api_isspellup)
        self.api.get('api.add')('getspellups', self.api_getspellups)
        self.api.get('api.add')('sendcmd', self.api_sendcmd)
        self.api.get('api.add')('isaffected', self.api_isaffected)
        self.api.get('api.add')('isblockedbyrecovery',
                                self.api_isblockedbyrecovery)
        self.api.get('api.add')('ispracticed', self.api_ispracticed)
        self.api.get('api.add')('canuse', self.api_canuse)
        self.api.get('api.add')('isuptodate', self.api_isuptodate)
        self.api.get('api.add')('isbad', self.api_isbad)
Example #4
0
 def __init__(self, *args, **kwargs):
     """
 initialize the instance
 """
     AardwolfBasePlugin.__init__(self, *args, **kwargs)
     self.savelevelfile = os.path.join(self.savedir, 'level.txt')
     self.levelinfo = PersistentDict(self.savelevelfile, 'c')
Example #5
0
    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)
Example #6
0
 def __init__(self, *args, **kwargs):
     """
 initialize the instance
 """
     AardwolfBasePlugin.__init__(self, *args, **kwargs)
     self.savequestfile = os.path.join(self.savedir, 'quest.txt')
     self.queststuff = PersistentDict(self.savequestfile, 'c')
Example #7
0
 def __init__(self, *args, **kwargs):
     """
 initialize the instance
 """
     BasePlugin.__init__(self, *args, **kwargs)
     self.savesubfile = os.path.join(self.savedir, 'subs.txt')
     self._substitutes = PersistentDict(self.savesubfile, 'c')
Example #8
0
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        BasePlugin.__init__(self, *args, **kwargs)

        self.aliasfile = os.path.join(self.savedir, 'aliases.txt')
        self._aliases = PersistentDict(self.aliasfile, 'c')

        self.sessionhits = {}
Example #9
0
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.variablefile = os.path.join(self.savedir, 'variables.txt')
    self._variables = PersistentDict(self.variablefile, 'c')
    self.api.get('api.add')('getv', self.api_getv)
    self.api.get('api.add')('setv', self.api_setv)
    self.api.get('api.add')('replace', self.api_replace)
Example #10
0
    def __init__(self):
        """
    initialize the instance
    """
        # 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

        #name, sname, modpath, basepath, fullimploc
        BasePlugin.__init__(
            self,
            'Plugin Manager',  #name,
            'plugins',  #sname,
            "/__init__.py",  #modpath
            "$basepath$",  # basepath
            "plugins.__init__",  # fullimploc
        )

        self.canreload = False

        #key:   modpath
        #value: {'plugin', 'module'}
        self.loadedpluginsd = {}

        self.pluginlookupbysname = {}
        self.pluginlookupbyname = {}
        self.pluginlookupbyfullimploc = {}

        # key:   modpath
        # value: {'sname', 'name', 'purpose', 'author',
        #        'version', 'modpath', 'fullimploc'
        self.allplugininfo = {}

        index = __file__.rfind(os.sep)
        if index == -1:
            self.basepath = "." + os.sep
        else:
            self.basepath = __file__[:index]

        self.savefile = os.path.join(self.api.BASEPATH, 'data', 'plugins',
                                     'loadedplugins.txt')
        self.loadedplugins = PersistentDict(self.savefile, 'c')

        self.api('api.add')('isloaded', self._api_isloaded)
        self.api('api.add')('getp', self._api_getp)
        self.api('api.add')('module', self._api_getmodule)
        self.api('api.add')('allplugininfo', self._api_allplugininfo)
        self.api('api.add')('savestate', self.savestate)
Example #11
0
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        AardwolfBasePlugin.__init__(self, *args, **kwargs)
        self.savecpfile = os.path.join(self.savedir, 'cp.txt')
        self.cpinfo = PersistentDict(self.savecpfile, 'c')
        self.mobsleft = []
        self.cpinfotimer = {}
        self.nextdeath = False

        self.cmdqueue = None

        self.api.get('dependency.add')('cmdq')
Example #12
0
 def __init__(self, *args, **kwargs):
     """
 initialize the instance
 """
     AardwolfBasePlugin.__init__(self, *args, **kwargs)
     self.savegqfile = os.path.join(self.savedir, 'gq.txt')
     self.gqinfo = PersistentDict(self.savegqfile, 'c')
     self._gqsdeclared = {}
     self._gqsstarted = {}
     self.api.get('setting.add')('joined', -1, int, 'the gq number joined')
     self.api.get('setting.add')('maxkills', False, bool,
                                 'no qp because of maxkills')
     self.mobsleft = []
     self.linecount = 0
Example #13
0
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.canreload = True

    self.regexlookup = {}
    self.actiongroups = {}
    self.compiledregex = {}
    self.sessionhits = {}

    self.saveactionsfile = os.path.join(self.savedir, 'actions.txt')
    self.actions = PersistentDict(self.saveactionsfile, 'c')
Example #14
0
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        AardwolfBasePlugin.__init__(self, *args, **kwargs)
        self.spellupfile = os.path.join(self.savedir, 'spellups.txt')
        self.spellups = PersistentDict(self.spellupfile, 'c')

        self.api('dependency.add')('aardwolf.skills')
        self.api('dependency.add')('aardwolf.move')

        self.initspellups()

        self.lastmana = -1
        self.lastmoves = -1
Example #15
0
 def __init__(self, *args, **kwargs):
   """
   initialize the instance
   """
   BasePlugin.__init__(self, *args, **kwargs)
   self.savesubfile = os.path.join(self.savedir, 'subs.txt')
   self._substitutes = PersistentDict(self.savesubfile, 'c')
Example #16
0
 def __init__(self, *args, **kwargs):
   """
   initialize the instance
   """
   AardwolfBasePlugin.__init__(self, *args, **kwargs)
   self.savelevelfile = os.path.join(self.savedir, 'level.txt')
   self.levelinfo = PersistentDict(self.savelevelfile, 'c')
Example #17
0
 def __init__(self, *args, **kwargs):
   """
   initialize the instance
   """
   AardwolfBasePlugin.__init__(self, *args, **kwargs)
   self.savequestfile = os.path.join(self.savedir, 'quest.txt')
   self.queststuff = PersistentDict(self.savequestfile, 'c')
Example #18
0
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.aliasfile = os.path.join(self.savedir, 'aliases.txt')
    self._aliases = PersistentDict(self.aliasfile, 'c')

    self.sessionhits = {}
Example #19
0
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.variablefile = os.path.join(self.savedir, 'variables.txt')
    self._variables = PersistentDict(self.variablefile, 'c')
    self.api('api.add')('getv', self.api_getv)
    self.api('api.add')('setv', self.api_setv)
    self.api('api.add')('replace', self.api_replace)
Example #20
0
  def __init__(self):
    """
    initialize the instance
    """
    # 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


    #name, sname, modpath, basepath, fullimploc
    BasePlugin.__init__(self,
                        'Plugin Manager', #name,
                        'plugins', #sname,
                        "/__init__.py", #modpath
                        "$basepath$", # basepath
                        "plugins.__init__", # fullimploc
                       )

    self.canreload = False

    #key:   modpath
    #value: {'plugin', 'module'}
    self.loadedpluginsd = {}

    self.pluginlookupbysname = {}
    self.pluginlookupbyname = {}
    self.pluginlookupbyfullimploc = {}

    # key:   modpath
    # value: {'sname', 'name', 'purpose', 'author',
    #        'version', 'modpath', 'fullimploc'
    self.allplugininfo = {}

    index = __file__.rfind(os.sep)
    if index == -1:
      self.basepath = "." + os.sep
    else:
      self.basepath = __file__[:index]

    self.savefile = os.path.join(self.api.BASEPATH, 'data',
                                 'plugins', 'loadedplugins.txt')
    self.loadedplugins = PersistentDict(self.savefile, 'c')

    self.api('api.add')('isloaded', self._api_isloaded)
    self.api('api.add')('getp', self._api_getp)
    self.api('api.add')('module', self._api_getmodule)
    self.api('api.add')('allplugininfo', self._api_allplugininfo)
    self.api('api.add')('savestate', self.savestate)
Example #21
0
 def __init__(self, *args, **kwargs):
   """
   initialize the instance
   """
   AardwolfBasePlugin.__init__(self, *args, **kwargs)
   self.savegqfile = os.path.join(self.savedir, 'gq.txt')
   self.gqinfo = PersistentDict(self.savegqfile, 'c')
   self._gqsdeclared = {}
   self._gqsstarted = {}
   self.api('setting.add')('joined', -1, int, 'the gq number joined')
   self.api('setting.add')('maxkills', False, bool, 'no qp because of maxkills')
   self.mobsleft = []
   self.linecount = 0
Example #22
0
  def __init__(self, *args, **kwargs):
    """
    init the class
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.canreload = False

    #print('log api.api', self.api.api)
    #print('log basepath', self.api.BASEPATH)
    self.savedir = os.path.join(self.api.BASEPATH, 'data',
                                'plugins', self.sname)
    self.logdir = os.path.join(self.api.BASEPATH, 'data', 'logs')
    #print('logdir', self.logdir)
    try:
      os.makedirs(self.savedir)
    except OSError:
      pass
    self.dtypes = {}
    self.sendtoclient = PersistentDict(
        os.path.join(self.savedir, 'sendtoclient.txt'),
        'c')
    self.sendtoconsole = PersistentDict(
        os.path.join(self.savedir, 'sendtoconsole.txt'),
        'c')
    self.sendtofile = PersistentDict(
        os.path.join(self.savedir, 'sendtofile.txt'),
        'c')
    self.currentlogs = {}
    self.colors = {}

    self.filenametemplate = '%a-%b-%d-%Y.log'
    #self.sendtofile['default'] = {
                                #'logdir':os.path.join(self.logdir, 'default'),
                                #'file':'%a-%b-%d-%Y.log', 'timestamp':True
                                  #}

    self.colors['error'] = '@x136'

    self.api('api.add')('msg', self.api_msg)
    self.api('api.add')('adddtype', self.api_adddtype)
    self.api('api.add')('console', self.api_toggletoconsole)
    self.api('api.add')('file', self.api_toggletofile)
    self.api('api.add')('client', self.api_toggletoclient)
    self.api('api.add')('writefile', self.api_writefile)

    # add some default datatypes
    self.api('log.adddtype')('default')
    self.api('log.adddtype')('frommud')
    self.api('log.adddtype')('startup')
    self.api('log.adddtype')('shutdown')
    self.api('log.adddtype')('error')

    # log some datatypes by default
    self.api('log.client')('error')
    self.api('log.console')('error')
    self.api('log.console')('default')
    self.api('log.console')('startup')
    self.api('log.console')('shutdown')
Example #23
0
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    AardwolfBasePlugin.__init__(self, *args, **kwargs)
    self.savecpfile = os.path.join(self.savedir, 'cp.txt')
    self.cpinfo = PersistentDict(self.savecpfile, 'c')
    self.mobsleft = []
    self.cpinfotimer = {}
    self.nextdeath = False

    self.api('dependency.add')('cmdq')
    self.api('api.add')('oncp', self.api_oncp)
    self.api('api.add')('mobsleft', self.api_cpmobsleft)
Example #24
0
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    AardwolfBasePlugin.__init__(self, *args, **kwargs)
    self.spellupfile = os.path.join(self.savedir, 'spellups.txt')
    self.spellups = PersistentDict(self.spellupfile, 'c')

    self.api('dependency.add')('aardwolf.skills')
    self.api('dependency.add')('aardwolf.move')

    self.initspellups()

    self.lastmana = -1
    self.lastmoves = -1
Example #25
0
class PluginMgr(BasePlugin):
  """
  a class to manage plugins
  """
  def __init__(self):
    """
    initialize the instance
    """
    # 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


    #name, sname, modpath, basepath, fullimploc
    BasePlugin.__init__(self,
                        'Plugin Manager', #name,
                        'plugins', #sname,
                        "/__init__.py", #modpath
                        "$basepath$", # basepath
                        "plugins.__init__", # fullimploc
                       )

    self.canreload = False

    #key:   modpath
    #value: {'plugin', 'module'}
    self.loadedpluginsd = {}

    self.pluginlookupbysname = {}
    self.pluginlookupbyname = {}
    self.pluginlookupbyfullimploc = {}

    # key:   modpath
    # value: {'sname', 'name', 'purpose', 'author',
    #        'version', 'modpath', 'fullimploc'
    self.allplugininfo = {}

    index = __file__.rfind(os.sep)
    if index == -1:
      self.basepath = "." + os.sep
    else:
      self.basepath = __file__[:index]

    self.savefile = os.path.join(self.api.BASEPATH, 'data',
                                 'plugins', 'loadedplugins.txt')
    self.loadedplugins = PersistentDict(self.savefile, 'c')

    self.api('api.add')('isloaded', self._api_isloaded)
    self.api('api.add')('getp', self._api_getp)
    self.api('api.add')('module', self._api_getmodule)
    self.api('api.add')('allplugininfo', self._api_allplugininfo)
    self.api('api.add')('savestate', self.savestate)

  # return the dictionary of all plugins
  def _api_allplugininfo(self):
    """
    return the plugininfo dictionary
    """
    return self.allplugininfo

  def findloadedplugin(self, plugin):
    """
    find a plugin
    """
    return self.api('plugins.getp')(plugin)

  # get a plugin instance
  def _api_getmodule(self, pluginname):
    """  returns the module of a plugin
    @Ypluginname@w  = the plugin to check for"""
    plugin = self.api('plugins.getp')(pluginname)

    if plugin:
      return self.loadedpluginsd[plugin.modpath]['module']

    return None

  # get a plugin instance
  def _api_getp(self, pluginname):
    """  get a loaded plugin instance
    @Ypluginname@w  = the plugin to get"""

    if isinstance(pluginname, basestring):
      if pluginname in self.loadedpluginsd:
        return self.loadedpluginsd[pluginname]['plugin']
      if pluginname in self.pluginlookupbysname:
        return self.loadedpluginsd[self.pluginlookupbysname[pluginname]]['plugin']
      if pluginname in self.pluginlookupbyname:
        return self.loadedpluginsd[self.pluginlookupbyname[pluginname]]['plugin']
      if pluginname in self.pluginlookupbyfullimploc:
        return self.loadedpluginsd[self.pluginlookupbyfullimploc[pluginname]]['plugin']
    elif isinstance(pluginname, BasePlugin):
      return pluginname

    return None

  # check if a plugin is loaded
  def _api_isloaded(self, pluginname):
    """  check if a plugin is loaded
    @Ypluginname@w  = the plugin to check for"""
    plugin = self.api('plugins.getp')(pluginname)

    if plugin:
      return True

    return False

  # load plugin dependencies
  def _loaddependencies(self, pluginname, dependencies):
    """
    load a list of modules
    """
    for i in dependencies:
      plugin = self.api('plugins.getp')(i)
      if plugin:
        continue

      self.api('send.msg')('%s: loading dependency %s' % (pluginname, i),
                           pluginname)

      name, path = imputils.findmodule(self.basepath, i)
      if name:
        modpath = name.replace(path, '')
        self._loadplugin(modpath, path, force=True)

  # get all not loaded plugins
  def _getnotloadedplugins(self):
    """
    create a message of all not loaded plugins
    """
    msg = []
    badplugins = self._updateallplugininfo()
    pdiff = set(self.allplugininfo) - set(self.loadedpluginsd)
    for modpath in sorted(pdiff):
      msg.append("%-20s : %-25s %-10s %-5s %s@w" % \
                  (self.allplugininfo[modpath]['fullimploc'].replace('plugins.', ''),
                   self.allplugininfo[modpath]['name'],
                   self.allplugininfo[modpath]['author'],
                   self.allplugininfo[modpath]['version'],
                   self.allplugininfo[modpath]['purpose']))
    if msg:
      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

  # get plugins that are change on disk
  def _getchangedplugins(self):
    """
    create a message of plugins that are changed on disk
    """
    msg = []

    plugins = sorted([i['plugin'] for i in self.loadedpluginsd.values()],
                     key=operator.attrgetter('package'))
    packageheader = []

    msg.append("%-10s : %-25s %-10s %-5s %s@w" % \
                        ('Short Name', 'Name', 'Author', 'Vers', 'Purpose'))
    msg.append('-' * 75)

    found = False
    for tpl in plugins:
      if tpl.ischangedondisk():
        found = True
        if tpl.package not in packageheader:
          if packageheader:
            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))

    if found:
      return msg

    return ['No plugins are changed on disk.']

  # get a message of plugins in a package
  def _getpackageplugins(self, package):
    """
    create a message of plugins in a package
    """
    msg = []

    plist = []
    for plugin in [i['plugin'] for i in self.loadedpluginsd.values()]:
      if plugin.package == package:
        plist.append(plugin)

    if plist:
      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

  # create a message of all plugins
  def _getallplugins(self):
    """
    create a message of all plugins
    """
    msg = []

    plugins = sorted([i['plugin'] for i in self.loadedpluginsd.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 packageheader:
          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

  # command to list plugins
  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

  # command to load plugins
  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 = imputils.find_files(self.basepath, fname + ".py")

      if len(_module_list) > 1:
        tmsg.append('There is more than one module that matches: %s' % \
                                                              plugin)
      elif not _module_list:
        tmsg.append('There are no modules that match: %s' % plugin)
      else:
        modpath = _module_list[0].replace(self.basepath, '')
        sname, reason = self._loadplugin(modpath, self.basepath, True)
        plugin = self.api('plugins.getp')(sname)
        if sname:
          if reason == 'already':
            tmsg.append('Plugin %s is already loaded' % sname)
          else:
            tmsg.append('Load complete: %s - %s' % \
                                          (sname, plugin.name))
        else:
          tmsg.append('Could not load: %s' % plugin)
      return True, tmsg
    else:
      return False, ['@Rplease specify a plugin@w']

  # command to unload a plugin
  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:
      if plugin.canreload:
        if self._unloadplugin(plugin.fullimploc):
          tmsg.append("Unloaded: %s" % plugin.fullimploc)
        else:
          tmsg.append("Could not unload:: %s" % plugin.fullimploc)
      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']

  # command to reload a plugin
  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:
      if plugin.canreload:
        tret, _ = self._reloadplugin(plugin.modpath, True)
        if tret and tret != True:
          plugin = self.findloadedplugin(plugina)
          tmsg.append("Reload complete: %s" % plugin.fullimploc)
          return True, tmsg
      else:
        tmsg.append("That plugin cannot be reloaded")
        return True, tmsg
    else:
      tmsg.append('plugin %s does not exist' % plugina)
      return True, tmsg

    return False, tmsg

  # load all plugins
  def _loadplugins(self, tfilter):
    """
    load plugins in all directories under the plugin directory
    """
    _module_list = imputils.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._loadplugin(modpath, self.basepath,
                                        force=force, runload=load)

      if modname == 'log':
        self.api('log.adddtype')(self.sname)
        self.api('log.console')(self.sname)
        self.api('log.adddtype')('upgrade')
        self.api('log.console')('upgrade')

    if not load:
      testsort = sorted([i['plugin'] for i in self.loadedpluginsd.values()],
                        key=operator.attrgetter('priority'))
      for i in testsort:
        try:
          #check dependencies here
          self.loadplugin(i)
        except Exception: # pylint: disable=broad-except
          self.api('send.traceback')(
              "load: had problems running the load method for %s." \
                          % i.fullimploc)
          imputils.deletemodule(i.fullimploc)

  # update all plugin info
  def _updateallplugininfo(self):
    """
    find plugins that are not in self.allplugininfo
    """
    _plugin_list = imputils.find_files(self.basepath, '*.py')
    _plugin_list.sort()

    self.allplugininfo = {}
    badplugins = []

    for fullpath in _plugin_list:
      modpath = fullpath.replace(self.basepath, '')

      imploc, modname = imputils.get_module_name(modpath)

      if not modname.startswith("_"):
        fullimploc = "plugins" + '.' + imploc
        if fullimploc in sys.modules:
          plugin = self.api('plugins.getp')(modpath)
          self.allplugininfo[modpath] = {}
          self.allplugininfo[modpath]['sname'] = plugin.sname
          self.allplugininfo[modpath]['name'] = plugin.name
          self.allplugininfo[modpath]['purpose'] = plugin.purpose
          self.allplugininfo[modpath]['author'] = plugin.author
          self.allplugininfo[modpath]['version'] = plugin.version
          self.allplugininfo[modpath]['modpath'] = modpath
          self.allplugininfo[modpath]['fullimploc'] = fullimploc

        else:
          try:
            _module = __import__(fullimploc)
            _module = sys.modules[fullimploc]

            self.allplugininfo[modpath] = {}
            self.allplugininfo[modpath]['sname'] = _module.SNAME
            self.allplugininfo[modpath]['name'] = _module.NAME
            self.allplugininfo[modpath]['purpose'] = _module.PURPOSE
            self.allplugininfo[modpath]['author'] = _module.AUTHOR
            self.allplugininfo[modpath]['version'] = _module.VERSION
            self.allplugininfo[modpath]['modpath'] = modpath
            self.allplugininfo[modpath]['fullimploc'] = fullimploc

            imputils.deletemodule(fullimploc)

          except Exception: # pylint: disable=broad-except
            badplugins.append(fullimploc)

    return badplugins

  # load a plugin
  def _loadplugin(self, modpath, basepath, force=False, runload=True):
    """
    load a single plugin
    """
    success, msg, module, fullimploc = imputils.importmodule(modpath, basepath,
                                                             self, 'plugins')

    if success and msg == 'import':

      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.allplugininfo:
        self.allplugininfo[modpath] = {}
        self.allplugininfo[modpath]['sname'] = module.SNAME
        self.allplugininfo[modpath]['name'] = module.NAME
        self.allplugininfo[modpath]['purpose'] = module.PURPOSE
        self.allplugininfo[modpath]['author'] = module.AUTHOR
        self.allplugininfo[modpath]['version'] = module.VERSION
        self.allplugininfo[modpath]['modpath'] = modpath
        self.allplugininfo[modpath]['fullimploc'] = fullimploc

      if load:
        if "Plugin" in module.__dict__:
          self._addplugin(module, modpath, basepath, fullimploc, runload)

        else:
          self.api('send.msg')('Module %s has no Plugin class' % \
                                              module.NAME)

        module.__dict__["proxy_import"] = 1

        return module.SNAME, 'Loaded'
      else:
        imputils.deletemodule(fullimploc)
        self.api('send.msg')(
            'Not loading %s (%s) because autoload is False' % \
                                    (module.NAME, fullimploc), primary='plugins')
      return True, 'not autoloaded'

    return success, msg

  # unload a plugin
  def _unloadplugin(self, fullimploc):
    """
    unload a module
    """
    if fullimploc in sys.modules:

      _module = sys.modules[fullimploc]
      success = True
      try:
        if "proxy_import" in _module.__dict__:
          self.api('send.client')(
              'unload: unloading %s' % fullimploc)
          if "unload" in _module.__dict__:
            try:
              _module.unload()
            except Exception: # pylint: disable=broad-except
              success = False
              self.api('send.traceback')(
                  "unload: module %s didn't unload properly." % fullimploc)

          if not self._removeplugin(_module.SNAME):
            self.api('send.client')(
                'could not remove plugin %s' % fullimploc)
            success = False

      except Exception: # pylint: disable=broad-except
        self.api('send.traceback')(
            "unload: had problems unloading %s." % fullimploc)
        success = False

      if success:
        imputils.deletemodule(fullimploc)
        self.api('send.client')("unload: unloaded %s." % fullimploc)

    return success

  # reload a plugin
  def _reloadplugin(self, modpath, force=False):
    """
    reload a plugin
    """
    if modpath in self.loadedpluginsd:
      plugin = self.api.get('plugins.getp')(modpath)
      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._unloadplugin(fullimploc):
        return False, ''

      if modpath and basepath:
        retval = self._loadplugin(modpath, basepath, force)
        if retval and reloaddependents:
          self._reloadalldependents(sname)
        return retval

    else:
      return False, ''

  # reload all dependents
  def _reloadalldependents(self, reloadedplugin):
    """
    reload all dependents
    """
    testsort = sorted([i['plugin'] for i in self.loadedpluginsd.values()],
                      key=operator.attrgetter('priority'))
    for plugin in testsort:
      if plugin.sname != reloadedplugin:
        if reloadedplugin in plugin.dependencies:
          self.api('send.msg')('reloading dependent %s of %s' % \
                      (plugin.sname, reloadedplugin), plugin.sname)
          plugin.savestate()
          self._reloadplugin(plugin.modpath, True)

  # load a plugin
  def loadplugin(self, plugin):
    """
    check dependencies and run the load function
    """
    self.api('send.msg')('loading dependencies for %s' % \
                                  plugin.fullimploc, plugin.sname)
    self._loaddependencies(plugin.sname, plugin.dependencies)
    self.api('send.client')("load: loading %s with priority %s" % \
			    (plugin.fullimploc, plugin.priority))
    self.api('send.msg')('loading %s (%s: %s)' % \
              (plugin.fullimploc, plugin.sname, plugin.name), plugin.sname)
    plugin.load()
    self.api('send.client')("load: loaded %s" % plugin.fullimploc)
    self.api('send.msg')('loaded %s (%s: %s)' % \
              (plugin.fullimploc, plugin.sname, plugin.name), plugin.sname)

    self.api('events.eraise')('%s_plugin_loaded' % plugin.sname, {})
    self.api('events.eraise')('plugin_loaded', {'plugin':plugin.sname})

  # add a plugin
  def _addplugin(self, module, modpath, basepath, fullimploc, load=True):
    # pylint: disable=too-many-arguments
    """
    add a plugin to be managed
    """
    pluginn = self.api('plugins.getp')(module.NAME)
    plugins = self.api('plugins.getp')(module.SNAME)
    if plugins or pluginn:
      self.api('send.msg')('Plugin %s already exists' % module.NAME,
                           secondary=module.SNAME)
      return False

    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 load:
      try:
        #check dependencies here
        self.loadplugin(plugin)
      except Exception: # pylint: disable=broad-except
        self.api('send.traceback')(
            "load: had problems running the load method for %s." \
                                                % fullimploc)
        imputils.deletemodule(fullimploc)
        return False

    self.loadedpluginsd[modpath] = {}
    self.loadedpluginsd[modpath]['plugin'] = plugin
    self.loadedpluginsd[modpath]['module'] = module

    self.pluginlookupbysname[plugin.sname] = modpath
    self.pluginlookupbyname[plugin.name] = modpath
    self.pluginlookupbyfullimploc[fullimploc] = modpath

    self.loadedplugins[modpath] = True
    self.loadedplugins.sync()

    return True

  # remove a plugin
  def _removeplugin(self, pluginname):
    """
    remove a plugin
    """
    plugin = self.api('plugins.getp')(pluginname)
    if plugin:
      try:
        plugin.unload()
        self.api('events.eraise')('%s_plugin_unload' % plugin.sname, {})
        self.api('events.eraise')('plugin_unloaded', {'name':plugin.sname})
        self.api('send.msg')('Plugin %s unloaded' % plugin.sname, secondary=plugin.sname)
      except Exception: # pylint: disable=broad-except
        self.api('send.traceback')(
            "unload: had problems running the unload method for %s." \
                                  % plugin.sname)
        return False

      del self.loadedpluginsd[plugin.modpath]

      del self.pluginlookupbyfullimploc[plugin.fullimploc]
      del self.pluginlookupbyname[plugin.name]
      del self.pluginlookupbysname[plugin.sname]

      del self.loadedplugins[plugin.modpath]
      self.loadedplugins.sync()

      plugin = None

      return True

    return False

  # get stats for this plugin
  def getstats(self):
    """
    return stats for events
    """
    stats = {}
    stats['Base Sizes'] = {}

    stats['Base Sizes']['showorder'] = ['Class', 'Api', 'loadedpluginsd',
                                        'plugininfo']
    stats['Base Sizes']['loadedpluginsd'] = '%s bytes' % \
                                      sys.getsizeof(self.loadedpluginsd)
    stats['Base Sizes']['plugininfo'] = '%s bytes' % \
                                      sys.getsizeof(self.allplugininfo)

    stats['Base Sizes']['Class'] = '%s bytes' % sys.getsizeof(self)
    stats['Base Sizes']['Api'] = '%s bytes' % sys.getsizeof(self.api)

    stats['Plugins'] = {}
    stats['Plugins']['showorder'] = ['Total', 'Loaded', 'Bad']
    stats['Plugins']['Total'] = len(self.allplugininfo)
    stats['Plugins']['Loaded'] = len(self.loadedpluginsd)

    badplugins = self._updateallplugininfo()

    stats['Plugins']['Bad'] = len(badplugins)

    return stats

  def shutdown(self, args=None): # pylint: disable=unused-argument
    """
    do tasks on shutdown
    """
    self.savestate()

  # save all plugins
  def savestate(self, args=None): # pylint: disable=unused-argument
    """
    save all plugins
    """
    for i in self.loadedpluginsd.values():
      i['plugin'].savestate()

  # load this plugin
  def load(self):
    """
    load various things
    """
    self._loadplugins("*.py")

    BasePlugin._loadcommands(self)

    parser = argp.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('commands.add')('list',
                             self._cmd_list,
                             lname='Plugin Manager',
                             parser=parser)

    parser = argp.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('commands.add')('load',
                             self._cmd_load,
                             lname='Plugin Manager',
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description="unload a plugin")
    parser.add_argument('plugin',
                        help='the plugin to unload',
                        default='',
                        nargs='?')
    self.api('commands.add')('unload',
                             self._cmd_unload,
                             lname='Plugin Manager',
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description="reload a plugin")
    parser.add_argument('plugin',
                        help='the plugin to reload',
                        default='',
                        nargs='?')
    self.api('commands.add')('reload',
                             self._cmd_reload,
                             lname='Plugin Manager',
                             parser=parser)

    self.api('commands.default')('list', self.sname)

    self.api('timers.add')('save', self.savestate, 60, nodupe=True, log=False)

    self.api('events.register')('proxy_shutdown', self.shutdown)
Example #26
0
class Plugin(AardwolfBasePlugin):
    """
  a plugin to handle aardwolf cp events
  """
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        AardwolfBasePlugin.__init__(self, *args, **kwargs)
        self.savecpfile = os.path.join(self.savedir, 'cp.txt')
        self.cpinfo = PersistentDict(self.savecpfile, 'c')
        self.mobsleft = []
        self.cpinfotimer = {}
        self.nextdeath = False

        self.cmdqueue = None

        self.api.get('dependency.add')('cmdq')

    def load(self):
        """
    load the plugins
    """
        AardwolfBasePlugin.load(self)

        self.cmdqueue = self.api.get('cmdq.baseclass')()(self)

        self.cmdqueue.addcmdtype('cpcheck',
                                 'campaign check',
                                 "^campaign check$",
                                 beforef=self.cpcheckbefore,
                                 afterf=self.cpcheckafter)

        parser = argparse.ArgumentParser(add_help=False,
                                         description='show cp info')
        self.api.get('commands.add')('show', self.cmd_show, parser=parser)

        parser = argparse.ArgumentParser(add_help=False,
                                         description='refresh cp info')
        self.api.get('commands.add')('refresh',
                                     self.cmd_refresh,
                                     parser=parser)

        self.api.get('watch.add')(
            'cp_check',
            '^(cp|campa|campai|campaig|campaign) (c|ch|che|chec|check)$')

        self.api.get('triggers.add')('cpnew',
          "^Commander Barcett tells you " \
            "'Type 'campaign info' to see what you must kill.'$")
        self.api.get('triggers.add')('cpnone',
                                     "^You are not currently on a campaign.$",
                                     enabled=False,
                                     group='cpcheck',
                                     omit=True)
        self.api.get('triggers.add')(
            'cptime',
            "^You have (?P<time>.*) to finish this campaign.$",
            enabled=False,
            group='cpcheck',
            omit=True)
        self.api.get('triggers.add')('cpmob',
          "^You still have to kill \* (?P<mob>.*) " \
                "\((?P<location>.*?)(?P<dead> - Dead|)\)$",
          enabled=False, group='cpcheck', omit=True)
        self.api.get('triggers.add')('cpscramble',
          "Note: One or more target names in this " \
                "campaign might be slightly scrambled.$",
          enabled=False, group='cpcheck', omit=True)
        self.api.get('triggers.add')('cpneedtolevel',
          "^You will have to level before you" \
                    " can go on another campaign.$",
          enabled=False,
          group='cpin')
        #Note: One or more target names in this campaign might be slightly scrambled.
        self.api.get('triggers.add')(
            'cpcantake',
            "^You may take a campaign at this level.$",
            enabled=False,
            group='cpin')
        self.api.get('triggers.add')(
            'cpshnext',
            "^You cannot take another campaign for (?P<time>.*).$",
            enabled=False,
            group='cpin')
        self.api.get('triggers.add')(
            'cpmobdead',
            "^Congratulations, that was one of your CAMPAIGN mobs!$",
            enabled=False,
            group='cpin')
        self.api.get('triggers.add')(
            'cpcomplete',
            "^CONGRATULATIONS! You have completed your campaign.$",
            enabled=False,
            group='cpin')
        self.api.get('triggers.add')('cpclear',
                                     "^Campaign cleared.$",
                                     enabled=False,
                                     group='cpin')
        self.api.get('triggers.add')(
            'cpreward',
            "^\s*Reward of (?P<amount>\d+) (?P<type>.+) .+ added.$",
            enabled=False,
            group='cprew',
            argtypes={
                'amount': int
            })
        self.api.get('triggers.add')('cpcompdone',
          "^--------------------------" \
                "------------------------------------$",
          enabled=False,
          group='cpdone')

        self.api.get('events.register')('trigger_cpnew', self._cpnew)
        self.api.get('events.register')('trigger_cpnone', self._cpnone)
        self.api.get('events.register')('trigger_cptime', self._cptime)
        #self.api.get('events.register')('watch_cp_check', self._cpcheckcmd)
        self.api.get('events.register')('trigger_cpmob', self._cpmob)
        self.api.get('events.register')('trigger_cpneedtolevel',
                                        self._cpneedtolevel)
        self.api.get('events.register')('trigger_cpcantake', self._cpcantake)
        self.api.get('events.register')('trigger_cpshnext', self._cpshnext)
        self.api.get('events.register')('trigger_cpmobdead', self._cpmobdead)
        self.api.get('events.register')('trigger_cpcomplete', self._cpcomplete)
        self.api.get('events.register')('trigger_cpclear', self._cpclear)
        self.api.get('events.register')('trigger_cpreward', self._cpreward)
        self.api.get('events.register')('trigger_cpcompdone', self._cpcompdone)

    def cmd_show(self, args):
        """
    show the cp mobs
    """
        msg = []
        if self.cpinfo['oncp']:
            msg.append('Mobs left:')
            msg.append('%-40s %s' % ('Mob Name', 'Area/Room'))
            msg.append('@G' + '-' * 60)
            for i in self.mobsleft:
                color = '@w'
                if i['mobdead']:
                    color = '@R'
                msg.append('%s%-40s %s' % (color, i['name'], i['location']))
        else:
            msg.append('You are not on a cp')

        return True, msg

    def cmd_refresh(self, args):
        """
    cmd to refresh cp info
    """
        msg = []
        if self.cpinfo['oncp']:
            msg.append('Refreshing cp mobs')
            self.cmdqueue.addtoqueue('cpcheck', '')
        else:
            msg.append('You are not on a cp')

        return True, msg

    def cpcheckbefore(self):
        """
    function to run before send the command
    """
        self.mobsleft = []
        self.cpinfotimer = {}
        self.api.get('triggers.togglegroup')('cpcheck', True)

    def cpcheckafter(self):
        """
    function to run after the command is finished
    """
        self.api.get('triggers.togglegroup')("cpin", True)
        self.api.get('triggers.togglegroup')('cpcheck', False)

    def afterfirstactive(self, _=None):
        """
    do something on connect
    """
        AardwolfBasePlugin.afterfirstactive(self)
        self.cmdqueue.addtoqueue('cpcheck', '')

    def _cpreset(self):
        """
    reset the cp
    """
        self.cpinfo.clear()
        self.cpinfo['mobs'] = {}
        self.cpinfo['trains'] = 0
        self.cpinfo['pracs'] = 0
        self.cpinfo['gold'] = 0
        self.cpinfo['tp'] = 0
        self.cpinfo['qp'] = 0
        self.cpinfo['bonusqp'] = 0
        self.cpinfo['failed'] = 0
        self.cpinfo['level'] = self.api.get('aardu.getactuallevel')(
            self.api.get('GMCP.getv')('char.status.level'))
        self.cpinfo['starttime'] = time.time()
        self.cpinfo['finishtime'] = 0
        self.cpinfo['oncp'] = True
        self.cpinfo['cantake'] = False
        self.cpinfo['shtime'] = None
        self.savestate()

    def _cpnew(self, args=None):
        """
    handle a new cp
    """
        self.api.get('send.msg')('cpnew: %s' % args)
        self._cpreset()
        self.cmdqueue.addtoqueue('cpcheck', '')

    def _cpnone(self, _=None):
        """
    handle a none cp
    """
        self.api.get('send.msg')('cpnone')
        self.cpinfo['oncp'] = False
        self.savestate()
        self.api.get('triggers.togglegroup')('cpcheck', False)
        self.api.get('triggers.togglegroup')('cpin', False)
        self.api.get('triggers.togglegroup')('cprew', False)
        self.api.get('triggers.togglegroup')('cpdone', False)
        #check(EnableTimer("cp_timer", false))
        self.cpinfotimer = {}
        self.cmdqueue.cmddone('cpcheck')

    def _cptime(self, _=None):
        """
    handle cp time
    """
        self.api.get('send.msg')('handling cp time')
        self.api.get('send.msg')('%s' % self.cpinfo)
        if not self.cpinfo['mobs']:
            self.api.get('send.msg')('copying mobsleft')
            self.cpinfo['mobs'] = self.mobsleft[:]
            self.api.get('events.eraise')('aard_cp_mobsorig',
                                          copy.deepcopy(
                                              {'mobsleft': self.mobsleft}))
            self.savestate()

        self.api.get('send.msg')('raising aard_cp_mobsleft %s' % self.mobsleft)
        self.api.get('events.eraise')('aard_cp_mobsleft',
                                      copy.deepcopy(
                                          {'mobsleft': self.mobsleft}))

        self.cmdqueue.cmddone('cpcheck')

    def _cpneedtolevel(self, _=None):
        """
    handle cpneedtolevel
    """
        self.cpinfo['cantake'] = False
        self.savestate()

    def _cpcantake(self, _=None):
        """
    handle cpcantake
    """
        self.cpinfo['cantake'] = True
        self.savestate()

    def _cpshnext(self, args=None):
        """
    handle cpshnext
    """
        self.cpinfo['shtime'] = args['time']
        self.savestate()

    def _cpmob(self, args=None):
        """
    handle cpmob
    """
        name = args['mob']
        mobdead = self.api.get('utils.verify')(args['dead'], bool)
        location = args['location']

        if not name or not location:
            self.api.get('send.msg')("error parsing line: %s" % args['line'])
        else:
            self.mobsleft.append({
                'name':
                name,
                'nocolorname':
                self.api.get('colors.stripansi')(name),
                'location':
                location,
                'mobdead':
                mobdead
            })

    def _cpmobdead(self, _=None):
        """
    handle cpmobdead
    """
        self.api.get('events.register')('aard_mobkill', self._mobkillevent)
        #self.api.get('send.execute')("cp check")

    def _cpcomplete(self, _=None):
        """
    handle cpcomplete
    """
        self.api.get('triggers.togglegroup')('cprew', True)
        self.cpinfo['finishtime'] = time.time()
        self.cpinfo['oncp'] = False
        self.savestate()

    def _cpreward(self, args=None):
        """
    handle cpreward
    """
        rtype = args['type']
        ramount = int(args['amount'])
        rewardt = self.api.get('aardu.rewardtable')()
        self.cpinfo[rewardt[rtype]] = ramount
        self.savestate()
        self.api.get('triggers.togglegroup')('cpdone', True)

    def _cpcompdone(self, _=None):
        """
    handle cpcompdone
    """
        self.api.get('events.register')('trigger_all', self._triggerall)

    def _triggerall(self, args=None):
        """
    check to see if we have the bonus qp message
    """
        if 'first campaign completed today' in args['line']:
            mat = re.match('^You receive (?P<bonus>\d*) quest points bonus ' \
                        'for your first campaign completed today.$', args['line'])
            self.cpinfo['bonusqp'] = int(mat.groupdict()['bonus'])
            self.api.get('events.unregister')('trigger_all', self._triggerall)
            self.api.get('events.eraise')('aard_cp_comp',
                                          copy.deepcopy(self.cpinfo))
        elif re.match("^You have completed (\d*) campaigns today.$",
                      args['line']):
            self.api.get('events.unregister')('trigger_all', self._triggerall)
            self.api.get('events.eraise')('aard_cp_comp',
                                          copy.deepcopy(self.cpinfo))

    def _cpclear(self, _=None):
        """
    handle cpclear
    """
        self.cpinfo['failed'] = 1
        self.api.get('events.eraise')('aard_cp_failed',
                                      copy.deepcopy(self.cpinfo))
        self._cpnone()

    def _cpcheckcmd(self, args=None):
        """
    handle when we get a cp check
    """
        self.mobsleft = []
        self.cpinfotimer = {}
        self.api.get('triggers.togglegroup')('cpcheck', True)
        return args

    def _mobkillevent(self, args):
        """
    this will be registered to the mobkill hook
    """
        self.api.get('send.msg')('checking kill %s' % args['name'])
        self.api.get('events.unregister')('aard_mobkill', self._mobkillevent)

        found = False
        removeitem = None
        for i in range(len(self.mobsleft)):
            tmob = self.mobsleft[i]
            if tmob['name'] == args['name']:
                self.api.get('send.msg')('found %s' % tmob['name'])
                found = True
                removeitem = i

        if removeitem:
            del (self.mobsleft[removeitem])

        if found:
            self.api.get('events.eraise')('aard_cp_mobsleft',
                                          copy.deepcopy(
                                              {'mobsleft': self.mobsleft}))
        else:
            self.api.get('send.msg')("BP CP: could not find mob: %s" %
                                     args['name'])
            self.cmdqueue.addtoqueue('cpcheck', '')

    def savestate(self):
        """
    save states
    """
        AardwolfBasePlugin.savestate(self)
        self.cpinfo.sync()
Example #27
0
class Plugin(AardwolfBasePlugin):
    """
  a plugin manage info about spells and skills
  """
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        AardwolfBasePlugin.__init__(self, *args, **kwargs)
        self.saveskillfile = os.path.join(self.savedir, 'skills.txt')
        self.skills = PersistentDict(self.saveskillfile, 'c')
        self.skillsnamelookup = {}
        for i in self.skills:
            self.skillsnamelookup[self.skills[i]['name']] = i

        self.saverecovfile = os.path.join(self.savedir, 'recoveries.txt')
        self.recoveries = PersistentDict(self.saverecovfile, 'c')
        self.recoveriesnamelookup = {}
        for i in self.recoveries:
            self.recoveriesnamelookup[self.recoveries[i]['name']] = i

        self.current = ''
        self.isuptodatef = False

        self.cmdqueue = None

        self.api.get('dependency.add')('cmdq')

        self.api.get('api.add')('gets', self.api_getskill)
        self.api.get('api.add')('isspellup', self.api_isspellup)
        self.api.get('api.add')('getspellups', self.api_getspellups)
        self.api.get('api.add')('sendcmd', self.api_sendcmd)
        self.api.get('api.add')('isaffected', self.api_isaffected)
        self.api.get('api.add')('isblockedbyrecovery',
                                self.api_isblockedbyrecovery)
        self.api.get('api.add')('ispracticed', self.api_ispracticed)
        self.api.get('api.add')('canuse', self.api_canuse)
        self.api.get('api.add')('isuptodate', self.api_isuptodate)
        self.api.get('api.add')('isbad', self.api_isbad)

    def load(self):
        """
    load the plugins
    """
        AardwolfBasePlugin.load(self)

        self.api.get('send.msg')('running load function of skills')

        parser = argparse.ArgumentParser(
            add_help=False, description='refresh skills and spells')
        self.api.get('commands.add')('refresh',
                                     self.cmd_refresh,
                                     parser=parser)

        parser = argparse.ArgumentParser(
            add_help=False, description='lookup skill or spell by name or sn')
        parser.add_argument('skill',
                            help='the skill to lookup',
                            default='',
                            nargs='?')
        self.api.get('commands.add')('lu', self.cmd_lu, parser=parser)

        self.api.get('triggers.add')('spellh_noprompt',
                                     "^\{spellheaders noprompt\}$",
                                     group='slist',
                                     enabled=False,
                                     omit=True)
        self.api.get('triggers.add')('spellh_spellup_noprompt',
                                     "^\{spellheaders spellup noprompt\}$",
                                     group='slist',
                                     enabled=False,
                                     omit=True)
        self.api.get('triggers.add')('spellh_affected_noprompt',
                                     "^\{spellheaders affected noprompt\}$",
                                     group='slist',
                                     enabled=False,
                                     omit=True)
        self.api.get('triggers.add')('spellh_spellline',
                "^(?P<sn>\d+),(?P<name>.+),(?P<target>\d+)," \
                  "(?P<duration>\d+),(?P<pct>\d+),(?P<rcvy>-?\d+),(?P<type>\d+)$",
                group='spellhead', enabled=False, omit=True)
        self.api.get('triggers.add')('spellh_end_noprompt',
                                     "^\{/spellheaders\}$",
                                     group='spellhead',
                                     enabled=False,
                                     omit=True)
        self.api.get('triggers.add')('affoff', "^\{affoff\}(?P<sn>\d+)$")
        self.api.get('triggers.add')(
            'affon', "^\{affon\}(?P<sn>\d+),(?P<duration>\d+)$")
        self.api.get('triggers.add')('recov_noprompt',
                                     "^\{recoveries noprompt\}$",
                                     group='slist',
                                     enabled=False,
                                     omit=True)
        self.api.get('triggers.add')('recov_affected_noprompt',
                                     "^\{recoveries affected noprompt\}$",
                                     group='slist',
                                     enabled=False,
                                     omit=True)
        self.api.get('triggers.add')(
            'spellh_recovline',
            "^(?P<sn>\d+),(?P<name>.+),(?P<duration>\d+)$",
            group='recoveries',
            enabled=False,
            omit=True)
        self.api.get('triggers.add')('recov_end_noprompt',
                                     "^\{/recoveries\}$",
                                     group='recoveries',
                                     enabled=False,
                                     omit=True)
        self.api.get('triggers.add')('recoff', "^\{recoff\}(?P<sn>\d+)$")
        self.api.get('triggers.add')(
            'recon', "^\{recon\}(?P<sn>\d+),(?P<duration>\d+)$")
        self.api.get('triggers.add')(
            'skillgain', "^\{skillgain\}(?P<sn>\d+),(?P<percent>\d+)$")
        self.api.get('triggers.add')('skillfail',
                "^\{sfail\}(?P<sn>\d+),(?P<target>\d+)," \
                  "(?P<reason>\d+),(?P<recovery>-?\d+)$")

        self.api.get('events.register')('trigger_spellh_noprompt',
                                        self.skillstart)
        self.api.get('events.register')('trigger_spellh_spellup_noprompt',
                                        self.skillstart)
        self.api.get('events.register')('trigger_spellh_affected_noprompt',
                                        self.skillstart)
        self.api.get('events.register')('trigger_spellh_spellline',
                                        self.skillline)
        self.api.get('events.register')('trigger_spellh_end_noprompt',
                                        self.skillend)
        self.api.get('events.register')('trigger_affoff', self.affoff)
        self.api.get('events.register')('trigger_affon', self.affon)
        self.api.get('events.register')('trigger_recov_noprompt',
                                        self.recovstart)
        self.api.get('events.register')('trigger_recov_affected_noprompt',
                                        self.recovstart)
        self.api.get('events.register')('trigger_spellh_recovline',
                                        self.recovline)
        self.api.get('events.register')('trigger_recov_end_noprompt',
                                        self.recovend)
        self.api.get('events.register')('trigger_recoff', self.recoff)
        self.api.get('events.register')('trigger_recon', self.recon)

        self.api.get('events.register')('trigger_skillgain', self.skillgain)
        self.api.get('events.register')('trigger_skillfail', self.skillfail)

        self.api.get('events.register')('GMCP:char.status', self.checkskills)

        self.api.get('events.register')('aard_level_tier', self.cmd_refresh)
        self.api.get('events.register')('aard_level_remort', self.cmd_refresh)

        self.cmdqueue = self.api.get('cmdq.baseclass')()(self)
        self.cmdqueue.addcmdtype('slist',
                                 'slist',
                                 "^slist\s*(.*)$",
                                 beforef=self.slistbefore,
                                 afterf=self.slistafter)

        self.checkskills()

    def slistbefore(self):
        """
    stuff to do before doing slist command
    """
        self.api.get('triggers.togglegroup')('slist', True)

    def slistafter(self):
        """
    stuff to do after doing slist command
    """
        self.savestate()
        self.api.get('triggers.togglegroup')('slist', False)

    def afterfirstactive(self, _=None):
        """
    do something on connect
    """
        AardwolfBasePlugin.afterfirstactive(self)
        self.checkskills()

    # check if the spells/skills list is up to date
    def api_isuptodate(self):
        """
    return True if we have seen affected or all spells refresh
    """
        return self.isuptodatef

    def cmd_lu(self, args):
        """
    cmd to lookup a spell
    """
        msg = []
        skill = self.api.get('skills.gets')(args['skill'])
        if skill:
            msg.append('%-8s : %s' % ('SN', skill['sn']))
            msg.append('%-8s : %s' % ('Name', skill['name']))
            msg.append('%-8s : %s' % ('Percent', skill['percent']))
            if skill['duration'] > 0:
                msg.append(
                    '%-8s : %s' %
                    ('Duration', self.api.get('utils.timedeltatostring')(
                        time.time(), skill['duration'])))
            msg.append('%-8s : %s' % ('Target', skill['target']))
            msg.append('%-8s : %s' % ('Spellup', skill['spellup']))
            msg.append('%-8s : %s' % ('Type', skill['type']))
            if skill['recovery']:
                recov = skill['recovery']
                if recov['duration'] > 0:
                    duration = self.api.get('utils.timedeltatostring')(
                        time.time(), recov['duration'])
                    msg.append('%-8s : %s (%s)' %
                               ('Recovery', recov['name'], duration))
                else:
                    msg.append('%-8s : %s' % ('Recovery', recov['name']))
        else:
            msg.append('Could not find: %s' % args['skill'])

        return True, msg

    def cmd_refresh(self, args):
        """
    refresh spells and skills
    """
        self.skills.clear()
        self.recoveries.clear()
        self.cmdqueue.addtoqueue('slist', 'noprompt')
        self.cmdqueue.addtoqueue('slist', 'spellup noprompt')
        msg = ['Refreshing spells and skills']
        return True, msg

    def checkskills(self, _=None):
        """
    check to see if we have spells
    """
        state = self.api.get('GMCP.getv')('char.status.state')
        if state == 3:
            self.api.get('send.msg')('refreshing skills')
            self.api.get('events.unregister')('GMCP:char.status',
                                              self.checkskills)
            self.api.get('A102.toggle')('SPELLUPTAGS', True)
            self.api.get('A102.toggle')('SKILLGAINTAGS', True)
            self.api.get('A102.toggle')('QUIETTAGS', False)
            if len(self.skills) == 0:
                self.cmd_refresh({})
            else:
                self.resetskills()
                self.cmdqueue.addtoqueue('slist', 'affected noprompt')

    def resetskills(self):
        """
    reset the skills
    """
        for i in self.skills:
            self.skills[i]['duration'] = 0
        for i in self.recoveries:
            self.recoveries[i]['duration'] = 0

    def skillgain(self, args):
        """
    handle a skillgain tag
    """
        spellnum = int(args['sn'])
        pct = int(args['percent'])
        if spellnum in self.skills:
            self.skills[spellnum]['percent'] = pct
            self.api.get('events.eraise')('aard_skill_gain', {
                'sn': spellnum,
                'percent': pct
            })

    def skillfail(self, args):
        """
    raise an event when we fail a skill/spell
    """
        spellnum = int(args['sn'])
        reason = FAILREASON[int(args['reason'])]
        ndict = {
            'sn': spellnum,
            'reason': reason,
            'target': FAILTARG[int(args['target'])],
            'recovery': int(args['recovery'])
        }
        if reason == 'dontknow' and self.skills[spellnum]['percent'] > 0:
            self.api.get('send.msg')(
                'refreshing spells because of an unlearned spell')
            self.cmd_refresh({})
        self.api.get('send.msg')('raising skillfail: %s' % ndict)
        self.api.get('events.eraise')('skill_fail_%s' % args['sn'], ndict)
        self.api.get('events.eraise')('skill_fail', ndict)

    def affoff(self, args):
        """
    set the affect to off for spell that wears off
    """
        spellnum = int(args['sn'])
        if spellnum in self.skills:
            self.skills[spellnum]['duration'] = 0
            self.savestate()
            self.api.get('events.eraise')('aard_skill_affoff_%s' % spellnum, {
                'sn': spellnum
            })
            self.api.get('events.eraise')('aard_skill_affoff', {
                'sn': spellnum
            })

    def affon(self, args):
        """
    set the spell's duration when we see an affon
    """
        spellnum = int(args['sn'])
        duration = int(args['duration'])
        if spellnum in self.skills:
            self.skills[spellnum]['duration'] = time.mktime(time.localtime()) + \
                                                              duration
            self.savestate()
            self.api.get('events.eraise')(
                'aard_skill_affon_%s' % spellnum, {
                    'sn': spellnum,
                    'duration': self.skills[spellnum]['duration']
                })
            self.api.get('events.eraise')(
                'aard_skill_affon', {
                    'sn': spellnum,
                    'duration': self.skills[spellnum]['duration']
                })

    def recovstart(self, args):
        """
    show that the trigger fired
    """
        if 'triggername' in args \
            and args['triggername'] == 'trigger_recov_affected_noprompt':
            self.current = 'affected'
        else:
            self.current = ''
        self.api.get('triggers.togglegroup')('recoveries', True)

    def recovline(self, args):
        """
    parse a recovery line
    """
        spellnum = int(args['sn'])
        name = args['name']
        if int(args['duration']) != 0:
            duration = time.mktime(time.localtime()) + int(args['duration'])
        else:
            duration = 0

        if not (spellnum in self.recoveries):
            self.recoveries[spellnum] = {}

        self.recoveries[spellnum]['name'] = name
        self.recoveries[spellnum]['duration'] = duration
        self.recoveries[spellnum]['sn'] = spellnum

        self.recoveriesnamelookup[name] = spellnum

    def recovend(self, args):
        """
    reset current when seeing a spellheaders ending
    """
        self.api.get('triggers.togglegroup')('recoveries', False)
        if self.current == '' or self.current == 'affected':
            self.isuptodatef = True
            self.api.get('send.msg')('sending skills_affected_update')
            self.api.get('events.eraise')('skills_affected_update', {})
        self.cmdqueue.cmddone('slist')

    def recoff(self, args):
        """
    set the affect to off for spell that wears off
    """
        spellnum = int(args['sn'])
        if spellnum in self.recoveries:
            self.recoveries[spellnum]['duration'] = 0
            self.savestate()
            self.api.get('events.eraise')('aard_skill_recoff', {
                'sn': spellnum
            })

    def recon(self, args):
        """
    set the spell's duration when we see an affon
    """
        spellnum = int(args['sn'])
        duration = int(args['duration'])
        if spellnum in self.recoveries:
            self.recoveries[spellnum]['duration'] = \
                              time.mktime(time.localtime()) + duration
            self.savestate()
            self.api.get('events.eraise')(
                'aard_skill_recon', {
                    'sn': spellnum,
                    'duration': self.recoveries[spellnum]['duration']
                })

    def skillstart(self, args):
        """
    show that the trigger fired
    """
        if 'triggername' in args \
            and args['triggername'] == 'spellh_spellup_noprompt':
            self.current = 'spellup'
        elif 'triggername' in args \
            and args['triggername'] == 'spellh_affected_noprompt':
            self.current = 'affected'
        else:
            self.current = ''
        self.api.get('triggers.togglegroup')('spellhead', True)

    def skillline(self, args):
        """
    parse spell lines
    """
        spellnum = int(args['sn'])
        name = args['name']
        target = int(args['target'])
        if int(args['duration']) != 0:
            duration = time.mktime(time.localtime()) + int(args['duration'])
        else:
            duration = 0
        percent = int(args['pct'])
        recovery = int(args['rcvy'])
        stype = int(args['type'])

        if not (spellnum in self.skills):
            self.skills[spellnum] = {}

        self.skills[spellnum]['name'] = name
        self.skills[spellnum]['target'] = TARGET[target]
        self.skills[spellnum]['duration'] = duration
        self.skills[spellnum]['percent'] = percent
        self.skills[spellnum]['recovery'] = recovery
        self.skills[spellnum]['type'] = STYPE[stype]
        self.skills[spellnum]['sn'] = spellnum
        if not ('spellup' in self.skills[spellnum]):
            self.skills[spellnum]['spellup'] = False
        if self.current == 'spellup':
            self.skills[spellnum]['spellup'] = True

        self.skillsnamelookup[name] = spellnum

    def skillend(self, args):
        """
    reset current when seeing a spellheaders ending
    """
        self.api.get('triggers.togglegroup')('spellhead', False)
        self.savestate()
        if self.current:
            evname = 'aard_skill_ref_%s' % self.current
        else:
            evname = 'aard_skill_ref'
        self.api.get('events.eraise')(evname, {})
        self.current = ''

    # get a spell/skill by number
    def api_getskill(self, tsn):
        """
    get a skill
    """
        #self.api.get('send.msg')('looking for %s' % tsn)
        spellnum = -1
        name = tsn
        try:
            spellnum = int(tsn)
        except ValueError:
            pass

        tskill = None
        if spellnum >= 1:
            #self.api.get('send.msg')('%s >= 0' % spellnum)
            if spellnum in self.skills:
                #self.api.get('send.msg')('found spellnum')
                tskill = copy.deepcopy(self.skills[spellnum])
                #tskill = self.skills[spellnum]
            else:
                self.api.get('send.msg')('did not find skill for %s' %
                                         spellnum)

        if not tskill and name:
            #self.api.get('send.msg')('trying name')
            tlist = self.api.get('utils.checklistformatch')(
                name, self.skillsnamelookup.keys())
            if len(tlist) == 1:
                tskill = copy.deepcopy(
                    self.skills[self.skillsnamelookup[tlist[0]]])

        if tskill:
            if tskill['recovery'] and tskill['recovery'] != -1:
                tskill['recovery'] = copy.deepcopy(
                    self.recoveries[tskill['recovery']])
            else:
                tskill['recovery'] = None

        return tskill

    # send the command to active a skill/spell
    def api_sendcmd(self, spellnum):
        """
    send the command to activate a skill/spell
    """
        skill = self.api.get('skills.gets')(spellnum)
        if skill:
            if skill['type'] == 'spell':
                self.api.get('send.msg')('casting %s' % skill['name'])
                self.api.get('send.execute')('cast %s' % skill['sn'])
            else:
                name = skill['name'].split()[0]
                self.api.get('send.msg')('sending skill %s' % skill['name'])
                self.api.get('send.execute')(name)

    # check if a skill/spell can be used
    def api_canuse(self, spellnum):
        """
    return True if the spell can be used
    """
        if self.api.get('skills.isaffected')(spellnum) \
            or self.api.get('skills.isblockedbyrecovery')(spellnum) \
            or not self.api.get('skills.ispracticed')(spellnum):
            return False

        return True

    # check if a skill/spell is a spellup
    def api_isspellup(self, spellnum):
        """
    return True for a spellup, else return False
    """
        spellnum = int(spellnum)
        if spellnum in self.skills:
            return self.skills[spellnum]['spellup']

        return False

    # check if a skill/spell is bad
    def api_isbad(self, spellnum):
        """
    return True for a bad spell, False for a good spell
    """
        skill = self.api.get('skill.gets')(spellnum)
        if (skill['target'] == 'attack' or skill['target'] == 'special') and \
              not skill['spellup']:
            return True

        return False

    # check if a skill/spell is active
    def api_isaffected(self, spellnum):
        """
    return True for a spellup, else return False
    """
        skill = self.api.get('skills.gets')(spellnum)
        if skill:
            return skill['duration'] > 0

        return False

    # check if a skill/spell is blocked by a recovery
    def api_isblockedbyrecovery(self, spellnum):
        """
    check to see if a spell/skill is blocked by a recovery
    """
        skill = self.api.get('skills.gets')(spellnum)
        if skill:
            if 'recovery' in skill and skill['recovery'] and \
                skill['recovery']['duration'] > 0:
                return True

        return False

    # check if a skill/spell is practiced
    def api_ispracticed(self, spellnum):
        """
    is the spell learned
    """
        skill = self.api.get('skills.gets')(spellnum)
        if skill:
            if skill['percent'] > 10:
                return True

        return False

    # get the list of spellup spells/skills
    def api_getspellups(self):
        """
    return a list of spellup spells
    """
        sus = [x for x in self.skills.values() if x['spellup']]
        return sus

    def savestate(self):
        """
    save states
    """
        AardwolfBasePlugin.savestate(self)
        self.skills.sync()
        self.recoveries.sync()
Example #28
0
class Plugin(AardwolfBasePlugin):
  """
  a plugin manage info about spells and skills
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    AardwolfBasePlugin.__init__(self, *args, **kwargs)
    self.saveskillfile = os.path.join(self.savedir, 'skills.txt')
    self.skills = PersistentDict(self.saveskillfile, 'c')
    self.skillsnamelookup = {}
    for i in self.skills:
      self.skillsnamelookup[self.skills[i]['name']] = i

    self.saverecovfile = os.path.join(self.savedir, 'recoveries.txt')
    self.recoveries = PersistentDict(self.saverecovfile, 'c')
    self.recoveriesnamelookup = {}
    for i in self.recoveries:
      self.recoveriesnamelookup[self.recoveries[i]['name']] = i

    self.current = ''
    self.isuptodatef = False

    self.cmdqueue = None

    self.api.get('dependency.add')('cmdq')

    self.api.get('api.add')('gets', self.api_getskill)
    self.api.get('api.add')('isspellup', self.api_isspellup)
    self.api.get('api.add')('getspellups', self.api_getspellups)
    self.api.get('api.add')('sendcmd', self.api_sendcmd)
    self.api.get('api.add')('isaffected', self.api_isaffected)
    self.api.get('api.add')('isblockedbyrecovery',
                                        self.api_isblockedbyrecovery)
    self.api.get('api.add')('ispracticed', self.api_ispracticed)
    self.api.get('api.add')('canuse', self.api_canuse)
    self.api.get('api.add')('isuptodate', self.api_isuptodate)
    self.api.get('api.add')('isbad', self.api_isbad)

  def load(self):
    """
    load the plugins
    """
    AardwolfBasePlugin.load(self)

    self.api.get('send.msg')('running load function of skills')

    parser = argparse.ArgumentParser(add_help=False,
                 description='refresh skills and spells')
    self.api.get('commands.add')('refresh', self.cmd_refresh,
                                 parser=parser)

    parser = argparse.ArgumentParser(add_help=False,
                 description='lookup skill or spell by name or sn')
    parser.add_argument('skill', help='the skill to lookup',
                        default='', nargs='?')
    self.api.get('commands.add')('lu', self.cmd_lu,
                                 parser=parser)

    self.api.get('triggers.add')('spellh_noprompt',
            "^\{spellheaders noprompt\}$",
            group='slist', enabled=False, omit=True)
    self.api.get('triggers.add')('spellh_spellup_noprompt',
            "^\{spellheaders spellup noprompt\}$",
            group='slist', enabled=False, omit=True)
    self.api.get('triggers.add')('spellh_affected_noprompt',
            "^\{spellheaders affected noprompt\}$",
            group='slist', enabled=False, omit=True)
    self.api.get('triggers.add')('spellh_spellline',
            "^(?P<sn>\d+),(?P<name>.+),(?P<target>\d+)," \
              "(?P<duration>\d+),(?P<pct>\d+),(?P<rcvy>-?\d+),(?P<type>\d+)$",
            group='spellhead', enabled=False, omit=True)
    self.api.get('triggers.add')('spellh_end_noprompt',
            "^\{/spellheaders\}$",
            group='spellhead', enabled=False, omit=True)
    self.api.get('triggers.add')('affoff',
            "^\{affoff\}(?P<sn>\d+)$")
    self.api.get('triggers.add')('affon',
            "^\{affon\}(?P<sn>\d+),(?P<duration>\d+)$")
    self.api.get('triggers.add')('recov_noprompt',
            "^\{recoveries noprompt\}$",
            group='slist', enabled=False, omit=True)
    self.api.get('triggers.add')('recov_affected_noprompt',
            "^\{recoveries affected noprompt\}$",
            group='slist', enabled=False, omit=True)
    self.api.get('triggers.add')('spellh_recovline',
            "^(?P<sn>\d+),(?P<name>.+),(?P<duration>\d+)$",
            group='recoveries', enabled=False, omit=True)
    self.api.get('triggers.add')('recov_end_noprompt',
            "^\{/recoveries\}$",
            group='recoveries', enabled=False, omit=True)
    self.api.get('triggers.add')('recoff',
            "^\{recoff\}(?P<sn>\d+)$")
    self.api.get('triggers.add')('recon',
            "^\{recon\}(?P<sn>\d+),(?P<duration>\d+)$")
    self.api.get('triggers.add')('skillgain',
            "^\{skillgain\}(?P<sn>\d+),(?P<percent>\d+)$")
    self.api.get('triggers.add')('skillfail',
            "^\{sfail\}(?P<sn>\d+),(?P<target>\d+)," \
              "(?P<reason>\d+),(?P<recovery>-?\d+)$")

    self.api.get('events.register')('trigger_spellh_noprompt',
                                    self.skillstart)
    self.api.get('events.register')('trigger_spellh_spellup_noprompt',
                                    self.skillstart)
    self.api.get('events.register')('trigger_spellh_affected_noprompt',
                                    self.skillstart)
    self.api.get('events.register')('trigger_spellh_spellline',
                                    self.skillline)
    self.api.get('events.register')('trigger_spellh_end_noprompt',
                                    self.skillend)
    self.api.get('events.register')('trigger_affoff', self.affoff)
    self.api.get('events.register')('trigger_affon', self.affon)
    self.api.get('events.register')('trigger_recov_noprompt',
                                    self.recovstart)
    self.api.get('events.register')('trigger_recov_affected_noprompt',
                                    self.recovstart)
    self.api.get('events.register')('trigger_spellh_recovline',
                                    self.recovline)
    self.api.get('events.register')('trigger_recov_end_noprompt',
                                    self.recovend)
    self.api.get('events.register')('trigger_recoff', self.recoff)
    self.api.get('events.register')('trigger_recon', self.recon)

    self.api.get('events.register')('trigger_skillgain', self.skillgain)
    self.api.get('events.register')('trigger_skillfail', self.skillfail)

    self.api.get('events.register')('GMCP:char.status', self.checkskills)

    self.api.get('events.register')('aard_level_tier', self.cmd_refresh)
    self.api.get('events.register')('aard_level_remort', self.cmd_refresh)


    self.cmdqueue = self.api.get('cmdq.baseclass')()(self)
    self.cmdqueue.addcmdtype('slist', 'slist', "^slist\s*(.*)$",
                       beforef=self.slistbefore, afterf=self.slistafter)

    self.checkskills()

  def slistbefore(self):
    """
    stuff to do before doing slist command
    """
    self.api.get('triggers.togglegroup')('slist', True)

  def slistafter(self):
    """
    stuff to do after doing slist command
    """
    self.savestate()
    self.api.get('triggers.togglegroup')('slist', False)

  def afterfirstactive(self, _=None):
    """
    do something on connect
    """
    AardwolfBasePlugin.afterfirstactive(self)
    self.checkskills()

  # check if the spells/skills list is up to date
  def api_isuptodate(self):
    """
    return True if we have seen affected or all spells refresh
    """
    return self.isuptodatef

  def cmd_lu(self, args):
    """
    cmd to lookup a spell
    """
    msg = []
    skill = self.api.get('skills.gets')(args['skill'])
    if skill:
      msg.append('%-8s : %s' % ('SN', skill['sn']))
      msg.append('%-8s : %s' % ('Name', skill['name']))
      msg.append('%-8s : %s' % ('Percent', skill['percent']))
      if skill['duration'] > 0:
        msg.append('%-8s : %s' % ('Duration',
            self.api.get('utils.timedeltatostring')(time.time(),
              skill['duration'])))
      msg.append('%-8s : %s' % ('Target', skill['target']))
      msg.append('%-8s : %s' % ('Spellup', skill['spellup']))
      msg.append('%-8s : %s' % ('Type', skill['type']))
      if skill['recovery']:
        recov = skill['recovery']
        if recov['duration'] > 0:
          duration =  self.api.get('utils.timedeltatostring')(time.time(),
              recov['duration'])
          msg.append('%-8s : %s (%s)' % ('Recovery',
                                      recov['name'], duration))
        else:
          msg.append('%-8s : %s' % ('Recovery', recov['name']))
    else:
      msg.append('Could not find: %s' % args['skill'])

    return True, msg

  def cmd_refresh(self, args):
    """
    refresh spells and skills
    """
    self.skills.clear()
    self.recoveries.clear()
    self.cmdqueue.addtoqueue('slist', 'noprompt')
    self.cmdqueue.addtoqueue('slist', 'spellup noprompt')
    msg = ['Refreshing spells and skills']
    return True, msg

  def checkskills(self, _=None):
    """
    check to see if we have spells
    """
    state = self.api.get('GMCP.getv')('char.status.state')
    if state == 3:
      self.api.get('send.msg')('refreshing skills')
      self.api.get('events.unregister')('GMCP:char.status', self.checkskills)
      self.api.get('A102.toggle')('SPELLUPTAGS', True)
      self.api.get('A102.toggle')('SKILLGAINTAGS', True)
      self.api.get('A102.toggle')('QUIETTAGS', False)
      if len(self.skills) == 0:
        self.cmd_refresh({})
      else:
        self.resetskills()
        self.cmdqueue.addtoqueue('slist', 'affected noprompt')

  def resetskills(self):
    """
    reset the skills
    """
    for i in self.skills:
      self.skills[i]['duration'] = 0
    for i in self.recoveries:
      self.recoveries[i]['duration'] = 0

  def skillgain(self, args):
    """
    handle a skillgain tag
    """
    spellnum = int(args['sn'])
    pct = int(args['percent'])
    if spellnum in self.skills:
      self.skills[spellnum]['percent'] = pct
      self.api.get('events.eraise')('aard_skill_gain',
                                    {'sn':spellnum, 'percent':pct})

  def skillfail(self, args):
    """
    raise an event when we fail a skill/spell
    """
    spellnum = int(args['sn'])
    reason = FAILREASON[int(args['reason'])]
    ndict = {'sn':spellnum, 'reason':reason,
            'target':FAILTARG[int(args['target'])],
            'recovery':int(args['recovery'])}
    if reason == 'dontknow' and self.skills[spellnum]['percent'] > 0:
      self.api.get('send.msg')('refreshing spells because of an unlearned spell')
      self.cmd_refresh({})
    self.api.get('send.msg')('raising skillfail: %s' % ndict)
    self.api.get('events.eraise')('skill_fail_%s' % args['sn'], ndict)
    self.api.get('events.eraise')('skill_fail', ndict)

  def affoff(self, args):
    """
    set the affect to off for spell that wears off
    """
    spellnum = int(args['sn'])
    if spellnum in self.skills:
      self.skills[spellnum]['duration'] = 0
      self.savestate()
      self.api.get('events.eraise')('aard_skill_affoff_%s' % spellnum,
                                              {'sn':spellnum})
      self.api.get('events.eraise')('aard_skill_affoff', {'sn':spellnum})

  def affon(self, args):
    """
    set the spell's duration when we see an affon
    """
    spellnum = int(args['sn'])
    duration = int(args['duration'])
    if spellnum in self.skills:
      self.skills[spellnum]['duration'] = time.mktime(time.localtime()) + \
                                                        duration
      self.savestate()
      self.api.get('events.eraise')('aard_skill_affon_%s' % spellnum,
                                              {'sn':spellnum,
                              'duration':self.skills[spellnum]['duration']})
      self.api.get('events.eraise')('aard_skill_affon', {'sn':spellnum,
                              'duration':self.skills[spellnum]['duration']})

  def recovstart(self, args):
    """
    show that the trigger fired
    """
    if 'triggername' in args \
        and args['triggername'] == 'trigger_recov_affected_noprompt':
      self.current = 'affected'
    else:
      self.current = ''
    self.api.get('triggers.togglegroup')('recoveries', True)

  def recovline(self, args):
    """
    parse a recovery line
    """
    spellnum = int(args['sn'])
    name = args['name']
    if int(args['duration']) != 0:
      duration = time.mktime(time.localtime()) + int(args['duration'])
    else:
      duration = 0

    if not (spellnum in self.recoveries):
      self.recoveries[spellnum] = {}

    self.recoveries[spellnum]['name'] = name
    self.recoveries[spellnum]['duration'] = duration
    self.recoveries[spellnum]['sn'] = spellnum

    self.recoveriesnamelookup[name] = spellnum

  def recovend(self, args):
    """
    reset current when seeing a spellheaders ending
    """
    self.api.get('triggers.togglegroup')('recoveries', False)
    if self.current == '' or self.current == 'affected':
      self.isuptodatef = True
      self.api.get('send.msg')('sending skills_affected_update')
      self.api.get('events.eraise')('skills_affected_update', {})
    self.cmdqueue.cmddone('slist')

  def recoff(self, args):
    """
    set the affect to off for spell that wears off
    """
    spellnum = int(args['sn'])
    if spellnum in self.recoveries:
      self.recoveries[spellnum]['duration'] = 0
      self.savestate()
      self.api.get('events.eraise')('aard_skill_recoff', {'sn':spellnum})

  def recon(self, args):
    """
    set the spell's duration when we see an affon
    """
    spellnum = int(args['sn'])
    duration = int(args['duration'])
    if spellnum in self.recoveries:
      self.recoveries[spellnum]['duration'] = \
                        time.mktime(time.localtime()) + duration
      self.savestate()
      self.api.get('events.eraise')('aard_skill_recon', {'sn':spellnum,
                            'duration':self.recoveries[spellnum]['duration']})

  def skillstart(self, args):
    """
    show that the trigger fired
    """
    if 'triggername' in args \
        and args['triggername'] == 'spellh_spellup_noprompt':
      self.current = 'spellup'
    elif 'triggername' in args \
        and args['triggername'] == 'spellh_affected_noprompt':
      self.current = 'affected'
    else:
      self.current = ''
    self.api.get('triggers.togglegroup')('spellhead', True)

  def skillline(self, args):
    """
    parse spell lines
    """
    spellnum = int(args['sn'])
    name = args['name']
    target = int(args['target'])
    if int(args['duration']) != 0:
      duration = time.mktime(time.localtime()) + int(args['duration'])
    else:
      duration = 0
    percent = int(args['pct'])
    recovery = int(args['rcvy'])
    stype = int(args['type'])

    if not (spellnum in self.skills):
      self.skills[spellnum] = {}

    self.skills[spellnum]['name'] = name
    self.skills[spellnum]['target'] = TARGET[target]
    self.skills[spellnum]['duration'] = duration
    self.skills[spellnum]['percent'] = percent
    self.skills[spellnum]['recovery'] = recovery
    self.skills[spellnum]['type'] = STYPE[stype]
    self.skills[spellnum]['sn'] = spellnum
    if not ('spellup' in self.skills[spellnum]):
      self.skills[spellnum]['spellup'] = False
    if self.current == 'spellup':
      self.skills[spellnum]['spellup'] = True

    self.skillsnamelookup[name] = spellnum

  def skillend(self, args):
    """
    reset current when seeing a spellheaders ending
    """
    self.api.get('triggers.togglegroup')('spellhead', False)
    self.savestate()
    if self.current:
      evname = 'aard_skill_ref_%s' % self.current
    else:
      evname = 'aard_skill_ref'
    self.api.get('events.eraise')(evname, {})
    self.current = ''

  # get a spell/skill by number
  def api_getskill(self, tsn):
    """
    get a skill
    """
    #self.api.get('send.msg')('looking for %s' % tsn)
    spellnum = -1
    name = tsn
    try:
      spellnum = int(tsn)
    except ValueError:
      pass

    tskill = None
    if spellnum >= 1:
      #self.api.get('send.msg')('%s >= 0' % spellnum)
      if spellnum in self.skills:
        #self.api.get('send.msg')('found spellnum')
        tskill = copy.deepcopy(self.skills[spellnum])
        #tskill = self.skills[spellnum]
      else:
        self.api.get('send.msg')('did not find skill for %s' % spellnum)

    if not tskill and name:
      #self.api.get('send.msg')('trying name')
      tlist = self.api.get('utils.checklistformatch')(name,
                                                self.skillsnamelookup.keys())
      if len(tlist) == 1:
        tskill = copy.deepcopy(self.skills[self.skillsnamelookup[tlist[0]]])

    if tskill:
      if tskill['recovery'] and tskill['recovery'] != -1:
        tskill['recovery'] = copy.deepcopy(self.recoveries[tskill['recovery']])
      else:
        tskill['recovery'] = None

    return tskill

  # send the command to active a skill/spell
  def api_sendcmd(self, spellnum):
    """
    send the command to activate a skill/spell
    """
    skill = self.api.get('skills.gets')(spellnum)
    if skill:
      if skill['type'] == 'spell':
        self.api.get('send.msg')('casting %s' % skill['name'])
        self.api.get('send.execute')('cast %s' % skill['sn'])
      else:
        name = skill['name'].split()[0]
        self.api.get('send.msg')('sending skill %s' % skill['name'])
        self.api.get('send.execute')(name)

  # check if a skill/spell can be used
  def api_canuse(self, spellnum):
    """
    return True if the spell can be used
    """
    if self.api.get('skills.isaffected')(spellnum) \
        or self.api.get('skills.isblockedbyrecovery')(spellnum) \
        or not self.api.get('skills.ispracticed')(spellnum):
      return False

    return True

  # check if a skill/spell is a spellup
  def api_isspellup(self, spellnum):
    """
    return True for a spellup, else return False
    """
    spellnum = int(spellnum)
    if spellnum in self.skills:
      return self.skills[spellnum]['spellup']

    return False

  # check if a skill/spell is bad
  def api_isbad(self, spellnum):
    """
    return True for a bad spell, False for a good spell
    """
    skill = self.api.get('skill.gets')(spellnum)
    if (skill['target'] == 'attack' or skill['target'] == 'special') and \
          not skill['spellup']:
      return True

    return False

  # check if a skill/spell is active
  def api_isaffected(self, spellnum):
    """
    return True for a spellup, else return False
    """
    skill = self.api.get('skills.gets')(spellnum)
    if skill:
      return skill['duration'] > 0

    return False

  # check if a skill/spell is blocked by a recovery
  def api_isblockedbyrecovery(self, spellnum):
    """
    check to see if a spell/skill is blocked by a recovery
    """
    skill = self.api.get('skills.gets')(spellnum)
    if skill:
      if 'recovery' in skill and skill['recovery'] and \
          skill['recovery']['duration'] > 0:
        return True

    return False

  # check if a skill/spell is practiced
  def api_ispracticed(self, spellnum):
    """
    is the spell learned
    """
    skill = self.api.get('skills.gets')(spellnum)
    if skill:
      if skill['percent'] > 10:
        return True

    return False

  # get the list of spellup spells/skills
  def api_getspellups(self):
    """
    return a list of spellup spells
    """
    sus = [x for x in self.skills.values() if x['spellup']]
    return sus

  def savestate(self):
    """
    save states
    """
    AardwolfBasePlugin.savestate(self)
    self.skills.sync()
    self.recoveries.sync()
Example #29
0
class Plugin(BasePlugin):
    """
  a plugin for user actions
  """
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        BasePlugin.__init__(self, *args, **kwargs)

        self.canreload = True

        self.regexlookup = {}
        self.actiongroups = {}
        self.compiledregex = {}
        self.sessionhits = {}

        self.saveactionsfile = os.path.join(self.savedir, 'actions.txt')
        self.actions = PersistentDict(self.saveactionsfile, 'c')

        for i in self.actions:
            self.compiledregex[i] = re.compile(self.actions[i]['regex'])

    def load(self):
        """
    load the plugin
    """
        BasePlugin.load(self)

        self.api.get('setting.add')('nextnum',
                                    0,
                                    int,
                                    'the number of the next action added',
                                    readonly=True)

        parser = argparse.ArgumentParser(add_help=False,
                                         description='add a action')
        parser.add_argument('regex',
                            help='the regex to match',
                            default='',
                            nargs='?')
        parser.add_argument('action',
                            help='the action to take',
                            default='',
                            nargs='?')
        parser.add_argument('send',
                            help='where to send the action',
                            default='execute',
                            nargs='?',
                            choices=self.api.get('api.getchildren')('send'))
        parser.add_argument('-c',
                            "--color",
                            help="match colors (@@colors)",
                            action="store_true")
        parser.add_argument('-d',
                            "--disable",
                            help="disable the action",
                            action="store_true")
        parser.add_argument('-g',
                            "--group",
                            help="the action group",
                            default="")
        parser.add_argument('-o',
                            "--overwrite",
                            help="overwrite an action if it already exists",
                            action="store_true")
        self.api.get('commands.add')('add', self.cmd_add, parser=parser)

        parser = argparse.ArgumentParser(add_help=False,
                                         description='list actions')
        parser.add_argument(
            'match',
            help='list only actions that have this argument in them',
            default='',
            nargs='?')
        self.api.get('commands.add')('list', self.cmd_list, parser=parser)

        parser = argparse.ArgumentParser(add_help=False,
                                         description='remove an action')
        parser.add_argument('action',
                            help='the action to remove',
                            default='',
                            nargs='?')
        self.api.get('commands.add')('remove', self.cmd_remove, parser=parser)

        parser = argparse.ArgumentParser(add_help=False,
                                         description='toggle enabled flag')
        parser.add_argument('action',
                            help='the action to toggle',
                            default='',
                            nargs='?')
        self.api.get('commands.add')('toggle', self.cmd_toggle, parser=parser)

        parser = argparse.ArgumentParser(
            add_help=False, description='get detail for an action')
        parser.add_argument('action',
                            help='the action to get details for',
                            default='',
                            nargs='?')
        self.api.get('commands.add')('detail', self.cmd_detail, parser=parser)

        parser = argparse.ArgumentParser(
            add_help=False, description='toggle all actions in a group')
        parser.add_argument('group',
                            help='the group to toggle',
                            default='',
                            nargs='?')
        parser.add_argument('-d',
                            "--disable",
                            help="disable the group",
                            action="store_true")
        self.api.get('commands.add')('groupt',
                                     self.cmd_grouptoggle,
                                     parser=parser)

        #self.api.get('commands.add')('stats', self.cmd_stats,
        #                             shelp='show action stats')

        self.api.get('events.register')('from_mud_event',
                                        self.checkactions,
                                        prio=5)


#    self.api.get('events.register')('plugin_stats', self.getpluginstats)

    def lookup_action(self, action):
        """
    lookup an action by number or name
    """
        nitem = None
        try:
            num = int(action)
            nitem = None
            for titem in self.actions.keys():
                if num == self.actions[titem]['num']:
                    nitem = titem
                    break

        except ValueError:
            if action in self.actions:
                nitem = action

        return nitem

    @timeit
    def checkactions(self, args):
        """
    check a line of text from the mud
    the is called whenever the from_mud_event is raised
    """
        data = args['noansi']
        colordata = args['convertansi']

        for i in self.actions:
            if self.actions[i]['enabled']:
                trigre = self.compiledregex[i]
                datatomatch = data
                if 'matchcolor' in self.actions[i] and \
                    self.actions[i]['matchcolor']:
                    datatomatch = colordata
                mat = trigre.match(datatomatch)
                self.api.get('send.msg')('attempting to match %s' %
                                         datatomatch)
                if mat:
                    if i in self.sessionhits:
                        self.sessionhits[i] = 0
                    self.sessionhits[i] = self.sessionhits[i] + 1
                    if 'hits' in self.actions[i]:
                        self.actions[i]['hits'] = 0
                    self.actions[i]['hits'] = self.actions[i]['hits'] + 1
                    self.api.get('send.msg')('matched line: %s to action %s' %
                                             (data, i))
                    templ = Template(self.actions[i]['action'])
                    newaction = templ.safe_substitute(mat.groupdict())
                    sendtype = 'send.' + self.actions[i]['send']
                    self.api.get('send.msg')('sent %s to %s' %
                                             (newaction, sendtype))
                    self.api.get(sendtype)(newaction)

        return args

    def cmd_add(self, args):
        """
    add user defined actions
    """
        if not args['regex']:
            return False, ['Please include a regex']
        if not args['action']:
            return False, ['Please include an action']

        if not args['overwrite'] and args['regex'] in self.actions:
            return True, ['Action: %s already exists.' % args['regex']]
        else:
            num = 0

            if args['regex'] in self.actions:
                num = self.actions[args['regex']]['num']
            else:
                num = self.api.get('setting.gets')('nextnum')
                self.api.get('setting.change')('nextnum', num + 1)

            self.actions[args['regex']] = {
                'num': num,
                'regex': args['regex'],
                'action': args['action'],
                'send': args['send'],
                'matchcolor': args['color'],
                'enabled': not args['disable'],
                'group': args['group']
            }
            self.actions.sync()

            self.compiledregex[args['regex']] = re.compile(args['regex'])

            return True, ['added action %s - regex: %s' % (num, args['regex'])]

        return False, ['You should never see this']

    def cmd_remove(self, args):
        """
    @G%(name)s@w - @B%(cmdname)s@w
      Remove an action
      @CUsage@w: rem @Y<originalstring>@w
        @Yoriginalstring@w    = The original string
    """
        tmsg = []
        if args['action']:
            retval = self.removeaction(args['action'])
            if retval:
                tmsg.append("@GRemoving action@w : '%s'" % (retval))
            else:
                tmsg.append("@GCould not remove action@w : '%s'" %
                            (args['action']))

            return True, tmsg
        else:
            return False, ['@RPlease include an action to remove@w']

    def cmd_list(self, args):
        """
    @G%(name)s@w - @B%(cmdname)s@w
      List actiones
      @CUsage@w: list
    """
        tmsg = self.listactions(args['match'])
        return True, tmsg

    def cmd_toggle(self, args):
        """
    toggle the enabled flag
    """
        tmsg = []
        if args['action']:
            retval = self.toggleaction(args['action'])
            if retval:
                if self.actions[retval]['enabled']:
                    tmsg.append("@GEnabled action@w : '%s'" % (retval))
                else:
                    tmsg.append("@GDisabled action@w : '%s'" % (retval))
            else:
                tmsg.append("@GDoes not exist@w : '%s'" % (args['action']))
            return True, tmsg

        else:
            return False, ['@RPlease include an action to toggle@w']

    def cmd_grouptoggle(self, args):
        """
    toggle all actions in a group
    """
        tmsg = []
        togglea = []
        state = not args['disable']
        if args['group']:
            for i in self.actions:
                if self.actions[i]['group'] == args['group']:
                    self.actions[i]['enabled'] = state
                    togglea.append('%s' % self.actions[i]['num'])

            if togglea:
                tmsg.append('The following actions were %s: %s' % \
                      ('enabled' if state else 'disabled',
                       ','.join(togglea)))
            else:
                tmsg.append('No actions were modified')

            return True, tmsg
        else:
            return False, ['@RPlease include a group to toggle@w']

    def cmd_detail(self, args):
        """
    @G%(name)s@w - @B%(cmdname)s@w
      Add a action
      @CUsage@w: add @Y<originalstring>@w @M<replacementstring>@w
        @Yoriginalstring@w    = The original string to be replaced
        @Mreplacementstring@w = The new string
    """
        tmsg = []
        if args['action']:
            action = self.lookup_action(args['action'])
            if action:
                if 'hits' in self.actions[action]:
                    self.actions[action]['hits'] = 0
                if action in self.sessionhits:
                    self.sessionhits[action] = 0
                tmsg.append('%-12s : %d' %
                            ('Num', self.actions[action]['num']))
                tmsg.append('%-12s : %s' % \
                    ('Enabled', 'Y' if self.actions[action]['enabled'] else 'N'))
                tmsg.append('%-12s : %d' %
                            ('Total Hits', self.actions[action]['hits']))
                tmsg.append('%-12s : %d' %
                            ('Session Hits', self.sessionhits[action]))
                tmsg.append('%-12s : %s' %
                            ('Regex', self.actions[action]['regex']))
                tmsg.append('%-12s : %s' %
                            ('Action', self.actions[action]['action']))
                tmsg.append('%-12s : %s' %
                            ('Group', self.actions[action]['group']))
                tmsg.append(
                    '%-12s : %s' %
                    ('Match Color', self.actions[action]['matchcolor']))
            else:
                return True, [
                    '@RAction does not exits@w : \'%s\'' % (args['action'])
                ]

            return True, tmsg
        else:
            return False, ['@RPlease include all arguments@w']

    def listactions(self, match):
        """
    return a table of strings that list actiones
    """
        tmsg = []
        for action in sorted(self.actions.keys()):
            item = self.actions[action]
            if not match or match in item:
                regex = self.api.get('colors.stripansi')(item['regex'])
                if len(regex) > 30:
                    regex = regex[:27] + '...'
                action = self.api.get('colors.stripansi')(item['action'])
                if len(action) > 30:
                    action = action[:27] + '...'
                tmsg.append("%4s %2s  %-10s %-32s : %s@w" % \
                             (item['num'],
                              'Y' if item['enabled'] else 'N',
                              item['group'],
                              regex,
                              action))
        if len(tmsg) == 0:
            tmsg = ['None']
        else:
            tmsg.insert(
                0, "%4s %2s  %-10s %-32s : %s@w" %
                ('#', 'E', 'Group', 'Regex', 'Action'))
            tmsg.insert(1, '@B' + '-' * 60 + '@w')

        return tmsg

    def removeaction(self, item):
        """
    internally remove a action
    """
        action = self.lookup_action(item)
        print 'lookup_action', item, 'returned', action
        if action >= 0:
            del self.actions[action]
            self.actions.sync()

        return action

    def toggleaction(self, item):
        """
    toggle an action
    """
        action = self.lookup_action(item)
        if action:
            self.actions[action][
                'enabled'] = not self.actions[action]['enabled']

        return action

    def clearactions(self):
        """
    clear all actiones
    """
        self.actions.clear()
        self.actions.sync()

    def reset(self):
        """
    reset the plugin
    """
        BasePlugin.reset(self)
        self.clearactions()

    def savestate(self):
        """
    save states
    """
        BasePlugin.savestate(self)
        self.actions.sync()
Example #30
0
class PluginMgr(BasePlugin):
    """
  a class to manage plugins
  """
    def __init__(self):
        """
    initialize the instance
    """
        # 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

        #name, sname, modpath, basepath, fullimploc
        BasePlugin.__init__(
            self,
            'Plugin Manager',  #name,
            'plugins',  #sname,
            "/__init__.py",  #modpath
            "$basepath$",  # basepath
            "plugins.__init__",  # fullimploc
        )

        self.canreload = False

        #key:   modpath
        #value: {'plugin', 'module'}
        self.loadedpluginsd = {}

        self.pluginlookupbysname = {}
        self.pluginlookupbyname = {}
        self.pluginlookupbyfullimploc = {}

        # key:   modpath
        # value: {'sname', 'name', 'purpose', 'author',
        #        'version', 'modpath', 'fullimploc'
        self.allplugininfo = {}

        index = __file__.rfind(os.sep)
        if index == -1:
            self.basepath = "." + os.sep
        else:
            self.basepath = __file__[:index]

        self.savefile = os.path.join(self.api.BASEPATH, 'data', 'plugins',
                                     'loadedplugins.txt')
        self.loadedplugins = PersistentDict(self.savefile, 'c')

        self.api('api.add')('isloaded', self._api_isloaded)
        self.api('api.add')('getp', self._api_getp)
        self.api('api.add')('module', self._api_getmodule)
        self.api('api.add')('allplugininfo', self._api_allplugininfo)
        self.api('api.add')('savestate', self.savestate)

    # return the dictionary of all plugins
    def _api_allplugininfo(self):
        """
    return the plugininfo dictionary
    """
        return self.allplugininfo

    def findloadedplugin(self, plugin):
        """
    find a plugin
    """
        return self.api('plugins.getp')(plugin)

    # get a plugin instance
    def _api_getmodule(self, pluginname):
        """  returns the module of a plugin
    @Ypluginname@w  = the plugin to check for"""
        plugin = self.api('plugins.getp')(pluginname)

        if plugin:
            return self.loadedpluginsd[plugin.modpath]['module']

        return None

    # get a plugin instance
    def _api_getp(self, pluginname):
        """  get a loaded plugin instance
    @Ypluginname@w  = the plugin to get"""

        if isinstance(pluginname, basestring):
            if pluginname in self.loadedpluginsd:
                return self.loadedpluginsd[pluginname]['plugin']
            if pluginname in self.pluginlookupbysname:
                return self.loadedpluginsd[
                    self.pluginlookupbysname[pluginname]]['plugin']
            if pluginname in self.pluginlookupbyname:
                return self.loadedpluginsd[
                    self.pluginlookupbyname[pluginname]]['plugin']
            if pluginname in self.pluginlookupbyfullimploc:
                return self.loadedpluginsd[
                    self.pluginlookupbyfullimploc[pluginname]]['plugin']
        elif isinstance(pluginname, BasePlugin):
            return pluginname

        return None

    # check if a plugin is loaded
    def _api_isloaded(self, pluginname):
        """  check if a plugin is loaded
    @Ypluginname@w  = the plugin to check for"""
        plugin = self.api('plugins.getp')(pluginname)

        if plugin:
            return True

        return False

    # load plugin dependencies
    def _loaddependencies(self, pluginname, dependencies):
        """
    load a list of modules
    """
        for i in dependencies:
            plugin = self.api('plugins.getp')(i)
            if plugin:
                continue

            self.api('send.msg')('%s: loading dependency %s' % (pluginname, i),
                                 pluginname)

            name, path = imputils.findmodule(self.basepath, i)
            if name:
                modpath = name.replace(path, '')
                self._loadplugin(modpath, path, force=True)

    # get all not loaded plugins
    def _getnotloadedplugins(self):
        """
    create a message of all not loaded plugins
    """
        msg = []
        badplugins = self._updateallplugininfo()
        pdiff = set(self.allplugininfo) - set(self.loadedpluginsd)
        for modpath in sorted(pdiff):
            msg.append("%-20s : %-25s %-10s %-5s %s@w" % \
                        (self.allplugininfo[modpath]['fullimploc'].replace('plugins.', ''),
                         self.allplugininfo[modpath]['name'],
                         self.allplugininfo[modpath]['author'],
                         self.allplugininfo[modpath]['version'],
                         self.allplugininfo[modpath]['purpose']))
        if msg:
            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

    # get plugins that are change on disk
    def _getchangedplugins(self):
        """
    create a message of plugins that are changed on disk
    """
        msg = []

        plugins = sorted([i['plugin'] for i in self.loadedpluginsd.values()],
                         key=operator.attrgetter('package'))
        packageheader = []

        msg.append("%-10s : %-25s %-10s %-5s %s@w" % \
                            ('Short Name', 'Name', 'Author', 'Vers', 'Purpose'))
        msg.append('-' * 75)

        found = False
        for tpl in plugins:
            if tpl.ischangedondisk():
                found = True
                if tpl.package not in packageheader:
                    if packageheader:
                        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))

        if found:
            return msg

        return ['No plugins are changed on disk.']

    # get a message of plugins in a package
    def _getpackageplugins(self, package):
        """
    create a message of plugins in a package
    """
        msg = []

        plist = []
        for plugin in [i['plugin'] for i in self.loadedpluginsd.values()]:
            if plugin.package == package:
                plist.append(plugin)

        if plist:
            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

    # create a message of all plugins
    def _getallplugins(self):
        """
    create a message of all plugins
    """
        msg = []

        plugins = sorted([i['plugin'] for i in self.loadedpluginsd.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 packageheader:
                    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

    # command to list plugins
    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

    # command to load plugins
    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 = imputils.find_files(self.basepath, fname + ".py")

            if len(_module_list) > 1:
                tmsg.append('There is more than one module that matches: %s' % \
                                                                      plugin)
            elif not _module_list:
                tmsg.append('There are no modules that match: %s' % plugin)
            else:
                modpath = _module_list[0].replace(self.basepath, '')
                sname, reason = self._loadplugin(modpath, self.basepath, True)
                plugin = self.api('plugins.getp')(sname)
                if sname:
                    if reason == 'already':
                        tmsg.append('Plugin %s is already loaded' % sname)
                    else:
                        tmsg.append('Load complete: %s - %s' % \
                                                      (sname, plugin.name))
                else:
                    tmsg.append('Could not load: %s' % plugin)
            return True, tmsg
        else:
            return False, ['@Rplease specify a plugin@w']

    # command to unload a plugin
    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:
            if plugin.canreload:
                if self._unloadplugin(plugin.fullimploc):
                    tmsg.append("Unloaded: %s" % plugin.fullimploc)
                else:
                    tmsg.append("Could not unload:: %s" % plugin.fullimploc)
            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']

    # command to reload a plugin
    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:
            if plugin.canreload:
                tret, _ = self._reloadplugin(plugin.modpath, True)
                if tret and tret != True:
                    plugin = self.findloadedplugin(plugina)
                    tmsg.append("Reload complete: %s" % plugin.fullimploc)
                    return True, tmsg
            else:
                tmsg.append("That plugin cannot be reloaded")
                return True, tmsg
        else:
            tmsg.append('plugin %s does not exist' % plugina)
            return True, tmsg

        return False, tmsg

    # load all plugins
    def _loadplugins(self, tfilter):
        """
    load plugins in all directories under the plugin directory
    """
        _module_list = imputils.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._loadplugin(modpath,
                                              self.basepath,
                                              force=force,
                                              runload=load)

            if modname == 'log':
                self.api('log.adddtype')(self.sname)
                self.api('log.console')(self.sname)
                self.api('log.adddtype')('upgrade')
                self.api('log.console')('upgrade')

        if not load:
            testsort = sorted(
                [i['plugin'] for i in self.loadedpluginsd.values()],
                key=operator.attrgetter('priority'))
            for i in testsort:
                try:
                    #check dependencies here
                    self.loadplugin(i)
                except Exception:  # pylint: disable=broad-except
                    self.api('send.traceback')(
                        "load: had problems running the load method for %s." \
                                    % i.fullimploc)
                    imputils.deletemodule(i.fullimploc)

    # update all plugin info
    def _updateallplugininfo(self):
        """
    find plugins that are not in self.allplugininfo
    """
        _plugin_list = imputils.find_files(self.basepath, '*.py')
        _plugin_list.sort()

        self.allplugininfo = {}
        badplugins = []

        for fullpath in _plugin_list:
            modpath = fullpath.replace(self.basepath, '')

            imploc, modname = imputils.get_module_name(modpath)

            if not modname.startswith("_"):
                fullimploc = "plugins" + '.' + imploc
                if fullimploc in sys.modules:
                    plugin = self.api('plugins.getp')(modpath)
                    self.allplugininfo[modpath] = {}
                    self.allplugininfo[modpath]['sname'] = plugin.sname
                    self.allplugininfo[modpath]['name'] = plugin.name
                    self.allplugininfo[modpath]['purpose'] = plugin.purpose
                    self.allplugininfo[modpath]['author'] = plugin.author
                    self.allplugininfo[modpath]['version'] = plugin.version
                    self.allplugininfo[modpath]['modpath'] = modpath
                    self.allplugininfo[modpath]['fullimploc'] = fullimploc

                else:
                    try:
                        _module = __import__(fullimploc)
                        _module = sys.modules[fullimploc]

                        self.allplugininfo[modpath] = {}
                        self.allplugininfo[modpath]['sname'] = _module.SNAME
                        self.allplugininfo[modpath]['name'] = _module.NAME
                        self.allplugininfo[modpath][
                            'purpose'] = _module.PURPOSE
                        self.allplugininfo[modpath]['author'] = _module.AUTHOR
                        self.allplugininfo[modpath][
                            'version'] = _module.VERSION
                        self.allplugininfo[modpath]['modpath'] = modpath
                        self.allplugininfo[modpath]['fullimploc'] = fullimploc

                        imputils.deletemodule(fullimploc)

                    except Exception:  # pylint: disable=broad-except
                        badplugins.append(fullimploc)

        return badplugins

    # load a plugin
    def _loadplugin(self, modpath, basepath, force=False, runload=True):
        """
    load a single plugin
    """
        success, msg, module, fullimploc = imputils.importmodule(
            modpath, basepath, self, 'plugins')

        if success and msg == 'import':

            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.allplugininfo:
                self.allplugininfo[modpath] = {}
                self.allplugininfo[modpath]['sname'] = module.SNAME
                self.allplugininfo[modpath]['name'] = module.NAME
                self.allplugininfo[modpath]['purpose'] = module.PURPOSE
                self.allplugininfo[modpath]['author'] = module.AUTHOR
                self.allplugininfo[modpath]['version'] = module.VERSION
                self.allplugininfo[modpath]['modpath'] = modpath
                self.allplugininfo[modpath]['fullimploc'] = fullimploc

            if load:
                if "Plugin" in module.__dict__:
                    self._addplugin(module, modpath, basepath, fullimploc,
                                    runload)

                else:
                    self.api('send.msg')('Module %s has no Plugin class' % \
                                                        module.NAME)

                module.__dict__["proxy_import"] = 1

                return module.SNAME, 'Loaded'
            else:
                imputils.deletemodule(fullimploc)
                self.api('send.msg')(
                    'Not loading %s (%s) because autoload is False' % \
                                            (module.NAME, fullimploc), primary='plugins')
            return True, 'not autoloaded'

        return success, msg

    # unload a plugin
    def _unloadplugin(self, fullimploc):
        """
    unload a module
    """
        if fullimploc in sys.modules:

            _module = sys.modules[fullimploc]
            success = True
            try:
                if "proxy_import" in _module.__dict__:
                    self.api('send.client')('unload: unloading %s' %
                                            fullimploc)
                    if "unload" in _module.__dict__:
                        try:
                            _module.unload()
                        except Exception:  # pylint: disable=broad-except
                            success = False
                            self.api('send.traceback')(
                                "unload: module %s didn't unload properly." %
                                fullimploc)

                    if not self._removeplugin(_module.SNAME):
                        self.api('send.client')('could not remove plugin %s' %
                                                fullimploc)
                        success = False

            except Exception:  # pylint: disable=broad-except
                self.api('send.traceback')(
                    "unload: had problems unloading %s." % fullimploc)
                success = False

            if success:
                imputils.deletemodule(fullimploc)
                self.api('send.client')("unload: unloaded %s." % fullimploc)

        return success

    # reload a plugin
    def _reloadplugin(self, modpath, force=False):
        """
    reload a plugin
    """
        if modpath in self.loadedpluginsd:
            plugin = self.api.get('plugins.getp')(modpath)
            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._unloadplugin(fullimploc):
                return False, ''

            if modpath and basepath:
                retval = self._loadplugin(modpath, basepath, force)
                if retval and reloaddependents:
                    self._reloadalldependents(sname)
                return retval

        else:
            return False, ''

    # reload all dependents
    def _reloadalldependents(self, reloadedplugin):
        """
    reload all dependents
    """
        testsort = sorted([i['plugin'] for i in self.loadedpluginsd.values()],
                          key=operator.attrgetter('priority'))
        for plugin in testsort:
            if plugin.sname != reloadedplugin:
                if reloadedplugin in plugin.dependencies:
                    self.api('send.msg')('reloading dependent %s of %s' % \
                                (plugin.sname, reloadedplugin), plugin.sname)
                    plugin.savestate()
                    self._reloadplugin(plugin.modpath, True)

    # load a plugin
    def loadplugin(self, plugin):
        """
    check dependencies and run the load function
    """
        self.api('send.msg')('loading dependencies for %s' % \
                                      plugin.fullimploc, plugin.sname)
        self._loaddependencies(plugin.sname, plugin.dependencies)
        self.api('send.client')("load: loading %s with priority %s" % \
           (plugin.fullimploc, plugin.priority))
        self.api('send.msg')('loading %s (%s: %s)' % \
                  (plugin.fullimploc, plugin.sname, plugin.name), plugin.sname)
        plugin.load()
        self.api('send.client')("load: loaded %s" % plugin.fullimploc)
        self.api('send.msg')('loaded %s (%s: %s)' % \
                  (plugin.fullimploc, plugin.sname, plugin.name), plugin.sname)

        self.api('events.eraise')('%s_plugin_loaded' % plugin.sname, {})
        self.api('events.eraise')('plugin_loaded', {'plugin': plugin.sname})

    # add a plugin
    def _addplugin(self, module, modpath, basepath, fullimploc, load=True):
        # pylint: disable=too-many-arguments
        """
    add a plugin to be managed
    """
        pluginn = self.api('plugins.getp')(module.NAME)
        plugins = self.api('plugins.getp')(module.SNAME)
        if plugins or pluginn:
            self.api('send.msg')('Plugin %s already exists' % module.NAME,
                                 secondary=module.SNAME)
            return False

        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 load:
            try:
                #check dependencies here
                self.loadplugin(plugin)
            except Exception:  # pylint: disable=broad-except
                self.api('send.traceback')(
                    "load: had problems running the load method for %s." \
                                                        % fullimploc)
                imputils.deletemodule(fullimploc)
                return False

        self.loadedpluginsd[modpath] = {}
        self.loadedpluginsd[modpath]['plugin'] = plugin
        self.loadedpluginsd[modpath]['module'] = module

        self.pluginlookupbysname[plugin.sname] = modpath
        self.pluginlookupbyname[plugin.name] = modpath
        self.pluginlookupbyfullimploc[fullimploc] = modpath

        self.loadedplugins[modpath] = True
        self.loadedplugins.sync()

        return True

    # remove a plugin
    def _removeplugin(self, pluginname):
        """
    remove a plugin
    """
        plugin = self.api('plugins.getp')(pluginname)
        if plugin:
            try:
                plugin.unload()
                self.api('events.eraise')('%s_plugin_unload' % plugin.sname,
                                          {})
                self.api('events.eraise')('plugin_unloaded', {
                    'name': plugin.sname
                })
                self.api('send.msg')('Plugin %s unloaded' % plugin.sname,
                                     secondary=plugin.sname)
            except Exception:  # pylint: disable=broad-except
                self.api('send.traceback')(
                    "unload: had problems running the unload method for %s." \
                                          % plugin.sname)
                return False

            del self.loadedpluginsd[plugin.modpath]

            del self.pluginlookupbyfullimploc[plugin.fullimploc]
            del self.pluginlookupbyname[plugin.name]
            del self.pluginlookupbysname[plugin.sname]

            del self.loadedplugins[plugin.modpath]
            self.loadedplugins.sync()

            plugin = None

            return True

        return False

    # get stats for this plugin
    def getstats(self):
        """
    return stats for events
    """
        stats = {}
        stats['Base Sizes'] = {}

        stats['Base Sizes']['showorder'] = [
            'Class', 'Api', 'loadedpluginsd', 'plugininfo'
        ]
        stats['Base Sizes']['loadedpluginsd'] = '%s bytes' % \
                                          sys.getsizeof(self.loadedpluginsd)
        stats['Base Sizes']['plugininfo'] = '%s bytes' % \
                                          sys.getsizeof(self.allplugininfo)

        stats['Base Sizes']['Class'] = '%s bytes' % sys.getsizeof(self)
        stats['Base Sizes']['Api'] = '%s bytes' % sys.getsizeof(self.api)

        stats['Plugins'] = {}
        stats['Plugins']['showorder'] = ['Total', 'Loaded', 'Bad']
        stats['Plugins']['Total'] = len(self.allplugininfo)
        stats['Plugins']['Loaded'] = len(self.loadedpluginsd)

        badplugins = self._updateallplugininfo()

        stats['Plugins']['Bad'] = len(badplugins)

        return stats

    def shutdown(self, args=None):  # pylint: disable=unused-argument
        """
    do tasks on shutdown
    """
        self.savestate()

    # save all plugins
    def savestate(self, args=None):  # pylint: disable=unused-argument
        """
    save all plugins
    """
        for i in self.loadedpluginsd.values():
            i['plugin'].savestate()

    # load this plugin
    def load(self):
        """
    load various things
    """
        self._loadplugins("*.py")

        BasePlugin._loadcommands(self)

        parser = argp.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('commands.add')('list',
                                 self._cmd_list,
                                 lname='Plugin Manager',
                                 parser=parser)

        parser = argp.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('commands.add')('load',
                                 self._cmd_load,
                                 lname='Plugin Manager',
                                 parser=parser)

        parser = argp.ArgumentParser(add_help=False,
                                     description="unload a plugin")
        parser.add_argument('plugin',
                            help='the plugin to unload',
                            default='',
                            nargs='?')
        self.api('commands.add')('unload',
                                 self._cmd_unload,
                                 lname='Plugin Manager',
                                 parser=parser)

        parser = argp.ArgumentParser(add_help=False,
                                     description="reload a plugin")
        parser.add_argument('plugin',
                            help='the plugin to reload',
                            default='',
                            nargs='?')
        self.api('commands.add')('reload',
                                 self._cmd_reload,
                                 lname='Plugin Manager',
                                 parser=parser)

        self.api('commands.default')('list', self.sname)

        self.api('timers.add')('save',
                               self.savestate,
                               60,
                               nodupe=True,
                               log=False)

        self.api('events.register')('proxy_shutdown', self.shutdown)
Example #31
0
class Plugin(AardwolfBasePlugin):
  """
  a plugin that does spellups
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    AardwolfBasePlugin.__init__(self, *args, **kwargs)
    self.spellupfile = os.path.join(self.savedir, 'spellups.txt')
    self.spellups = PersistentDict(self.spellupfile, 'c')

    self.api('dependency.add')('aardwolf.skills')
    self.api('dependency.add')('aardwolf.move')

    self.initspellups()

    self.lastmana = -1
    self.lastmoves = -1

  def load(self):
    """
    load the plugins
    """
    AardwolfBasePlugin.load(self)

    self.api('setting.add')('enabled', True, bool,
                            'auto spellup is enabled')
    self.api('setting.add')('waiting', -1, int,
                            'the spell that was just cast',
                            readonly=True)
    self.api('setting.add')('nocast', False, bool,
                            'in a nocast room',
                            readonly=True)
    self.api('setting.add')('nomoves', False, bool,
                            'need more moves',
                            readonly=True)
    self.api('setting.add')('nomana', False, bool,
                            'need more mana',
                            readonly=True)
    self.api('setting.add')('nocastrooms', {}, dict,
                            'list of nocast rooms',
                            readonly=True)
    self.api('setting.add')('currentroom', -1, int,
                            'the current room',
                            readonly=True)

    parser = argp.ArgumentParser(add_help=False,
                                 description='add a spellup to the self list')
    parser.add_argument(
        'spell',
        help='the spells to add, use \'all\' to add all practiced spellups',
        default=[], nargs='*')
    parser.add_argument(
        '-o', "--override",
        help="add even if the spell is not flagged as a spellup by the mud",
        action="store_true")
    self.api('commands.add')('add', self.cmd_sadd,
                             parser=parser, group='Spellups on Self')

    parser = argp.ArgumentParser(add_help=False,
                                 description='list spellups for self')
    parser.add_argument(
        'match',
        help='list only spellups that have this argument in them',
        default='', nargs='?')
    self.api('commands.add')('list', self.cmd_slist,
                             parser=parser, group='Spellups on Self')

    parser = argp.ArgumentParser(add_help=False,
                                 description='remove a spellup from the self list')
    parser.add_argument(
        'spell',
        help='the spells to remove, use \'all\' to remove all spellups',
        default=[], nargs='*')
    self.api('commands.add')('rem', self.cmd_srem,
                             parser=parser, group='Spellups on Self')

    parser = argp.ArgumentParser(add_help=False,
                                 description='enable spellups on self')
    parser.add_argument(
        'spell',
        help='the spells to enable, use \'all\' to enable all spellups',
        default=[], nargs='*')
    self.api('commands.add')('en', self.cmd_en,
                             parser=parser, group='Spellups on Self')

    parser = argp.ArgumentParser(add_help=False,
                                 description='disable spells on self')
    parser.add_argument(
        'spell',
        help='the spells to disable, use \'all\' to disable all spellups',
        default=[], nargs='*')
    self.api('commands.add')('dis', self.cmd_dis,
                             shelp='disable a spellup on self',
                             parser=parser, group='Spellups on Self')

    self.api('commands.add')('check', self.cmd_check,
                             shelp='check data status for casting',
                             group='Spellups on Self')

    self.api('events.register')('GMCP:char.vitals', self._charvitals)
    self.api('events.register')('GMCP:char.status', self._charstatus)
    self.api('events.register')('moved_room', self._moved)
    self.api('events.register')('skill_fail', self._skillfail)
    self.api('events.register')('aard_skill_affon', self._affon)
    self.api('events.register')('aard_skill_affoff', self._affoff)
    self.api('events.register')('aard_skill_recoff', self._recoff)
    self.api('events.register')('aard_skill_gain', self.skillgain)
    self.api('events.register')('var_su_enabled', self.enabledchange)
    self.api('events.register')('skills_affected_update', self.nextspell)
    self.api('events.register')('plugin_%s_savestate' % self.sname, self._savestate)
    self.api('events.register')('skills_uptodate', self.nextspell)

  def skillgain(self, args=None):
    """
    check skills when we gain them
    """
    if args['sn'] in self.spellups['sorder'] and args['percent'] > 50:
      self.nextspell()

  def initspellups(self):
    """
    initialize the spellups dictionary
    """
    if 'sorder' not in self.spellups:
      self.spellups['sorder'] = []
    if 'self' not in self.spellups:
      self.spellups['self'] = {}
    if 'oorder' not in self.spellups:
      self.spellups['oorder'] = []
    if 'other' not in self.spellups:
      self.spellups['other'] = {}

  def enabledchange(self, args):
    """
    do something when enabled is changed
    """
    if args['newvalue']:
      self.nextspell()

  def _affon(self, args):
    """
    catch an affon event
    """
    if args['sn'] == self.api('setting.gets')('waiting'):
      self.api('setting.change')('waiting', -1)
    self.nextspell()

  def _affoff(self, _=None):
    """
    catch an affoff event
    """
    self.nextspell()

  def _recoff(self, _=None):
    """
    catch a recoff event
    """
    self.nextspell()

  def _skillfail(self, args): # pylint: disable=too-many-branches
    """
    catch a skill fail event
    """
    self.api('send.msg')('skillfail: %s' % args)
    spellnum = args['sn']
    skill = self.api('skills.gets')(spellnum)
    waiting = self.api('setting.gets')('waiting')
    if args['reason'] == 'nomana':
      self.api('setting.change')('waiting', -1)
      self.api('setting.change')('nomana', True)
      self.lastmana = self.api('GMCP.getv')('char.vitals.mana')
    elif args['reason'] == 'nocastroom':
      self.api('setting.change')('waiting', -1)
      self.api('setting.change')('nocast', True)
      nocastrooms = self.api('setting.gets')('nocastrooms')
      currentroom = self.api('setting.gets')('currentroom')
      nocastrooms[currentroom] = True
    elif args['reason'] == 'fighting' or args['reason'] == 'notactive':
      self.api('setting.change')('waiting', -1)
    elif args['reason'] == 'nomoves':
      self.api('setting.change')('waiting', -1)
      self.api('setting.change')('nomoves', True)
      self.lastmana = self.api('GMCP.getv')('char.vitals.moves')
    elif waiting == spellnum:
      if args['reason'] == 'lostconc':
        self.api('skills.sendcmd')(waiting)
      elif args['reason'] == 'alreadyaff':
        self.api('setting.change')('waiting', -1)
        self.api('send.client')(
            "@BSpellup - disabled %s because you are already affected" % \
                                  skill['name'])
        if spellnum in self.spellups['self']:
          self.spellups['self'][spellnum]['enabled'] = False
        #if spellnum in self.spellups['other']:
          #self.spellups['other'][spellnum]['enabled'] = False
        self.nextspell()
      elif args['reason'] == 'recblock':
        # do stuff when blocked by a recovery
        self.api('setting.change')('waiting', -1)
        self.nextspell()
      elif args['reason'] == 'dontknow':
        # do stuff when spell/skill isn't learned
        # don't disable it, hopefully the spell/skill has been updated and
        # won't be cast through nextspell
        self.api('setting.change')('waiting', -1)
        self.nextspell()
      elif args['reason'] == 'wrongtarget':
        # do stuff when a wrong target
        self.api('setting.change')('waiting', -1)
        self.nextspell()
      elif args['reason'] == 'disabled':
        self.api('setting.change')('waiting', -1)
        skill = self.api('skills.gets')(spellnum)
        self.api('send.client')(
            "@BSpellup - disabled %s because it is disabled mudside" % \
                                  skill['name'])
        if spellnum in self.spellups['self']:
          self.spellups['self'][spellnum]['enabled'] = False
        if spellnum in self.spellups['other']:
          self.spellups['other'][spellnum]['enabled'] = False
        self.nextspell()

  def _moved(self, args):
    """
    reset stuff if we move
    """
    self.api('setting.change')('currentroom', args['to']['num'])
    nocastrooms = self.api('setting.gets')('nocastrooms')
    if args['to']['num'] in nocastrooms:
      self.api('setting.change')('nocast', True)
    else:
      lastval = self.api('setting.gets')('nocast')
      self.api('setting.change')('nocast', False)
      if lastval:
        self.nextspell()

  def _charvitals(self, _=None):
    """
    check if we have more mana and moves
    """
    if self.api('setting.gets')('nomana'):
      newmana = self.api('GMCP.getv')('char.vitals.mana')
      if newmana > self.lastmana:
        self.lastmana = -1
        self.api('setting.change')('nomana', False)
        self.nextspell()
    if self.api('setting.gets')('nomoves'):
      newmoves = self.api('GMCP.getv')('char.vitals.moves')
      if newmoves > self.lastmoves:
        self.lastmoves = -1
        self.api('setting.change')('nomoves', False)
        self.nextspell()

  def _charstatus(self, _=None):
    """
    check if we have more mana and moves
    """
    status = self.api('GMCP.getv')('char.status.state')
    if status == 3 and self.api('skills.isuptodate')():
      self.nextspell()

  @timeit
  def check(self, _=None):
    """
    check to cast the next spell
    """
    mud = self.api('managers.getm')('mud')
    if not mud or not mud.connected:
      return False
    self.api('send.msg')('waiting type: %s' % \
                      type(self.api('setting.gets')('waiting')))
    self.api('send.msg')('currentstatus = %s' % \
                      self.api('GMCP.getv')('char.status.state'))

    # pylint: disable=too-many-boolean-expressions
    if self.api('setting.gets')('nomoves') \
        or self.api('setting.gets')('nomana') \
        or self.api('setting.gets')('nocast') \
        or self.api('setting.gets')('waiting') != -1 \
        or not self.api('setting.gets')('enabled') \
        or not self.api('skills.isuptodate')() or \
        self.api('GMCP.getv')('char.status.state') != 3:
      self.api('send.msg')('checked returned False')
      return False

    self.api('send.msg')('checked returned True')
    return True

  @timeit
  def nextspell(self, _=None):
    """
    try to cast the next spell
    """
    self.api('send.msg')('nextspell')
    if self.check():
      for i in self.spellups['sorder']:
        if self.spellups['self'][i]['enabled']:
          if self.api('skills.canuse')(i):
            self.api('setting.change')('waiting', int(i))
            self.api('skills.sendcmd')(i)
            return

  def _savestate(self, _=None):
    """
    save states
    """
    self.spellups.sync()

  def _addselfspell(self, spellnum, place=-1, override=False):
    """
    add a spell internally
    """
    msg = []
    spell = self.api('skills.gets')(spellnum)

    if not spell:
      msg.append('%-20s: does not exist' % spellnum)
      return msg

    if not override and not self.api('skills.isspellup')(spell['sn']):
      msg.append('%-20s: not a spellup' % spell['name'])
      return msg

    if spell['sn'] in self.spellups['sorder']:
      msg.append('%-30s: already activated' % spell['name'])
      return msg

    self.spellups['self'][spell['sn']] = {'enabled':True}
    if place > -1:
      self.spellups['sorder'].insert(place, spell['sn'])
    else:
      self.spellups['sorder'].append(spell['sn'])
    msg.append('%-20s:  place %s' % \
        (spell['name'],
         self.spellups['sorder'].index(spell['sn'])))

    return msg

  def cmd_sadd(self, args):
    """
    add a spellup
    """
    msg = []
    if len(args['spell']) < 1:
      return False, ['Please supply a spell']

    if args['spell'][0] == 'all':
      spellups = self.api('skills.getspellups')()
      for spell in spellups:
        if spell['percent'] > 1:
          tmsg = self._addselfspell(spell['sn'])
          msg.extend(tmsg)

      self.nextspell()

    else:
      for aspell in args['spell']:
        tspell = aspell
        place = -1
        if ':' in aspell:
          tlist = aspell.split(':')
          tspell = tlist[0]
          place = int(tlist[1])

        tmsg = self._addselfspell(tspell, place, args['override'])
        msg.extend(tmsg)

        self.nextspell()

    self.spellups.sync()
    return True, msg

  def cmd_slist(self, args):
    """
    list the spellups
    """
    msg = []
    match = args['match']
    if self.spellups['sorder']:
      msg.append('%-3s - %-30s : %2s %2s %2s %2s  %-2s  %-2s' % \
                    ('Num', 'Name', 'A', 'P', 'B', 'D', 'NP', 'NL'))
      msg.append('@B' + '-'* 60)
      for i in self.spellups['sorder']:
        skill = self.api('skills.gets')(i)
        if not skill:
          msg.append('%-3s: please check the skills plugin' % \
                         (self.spellups['sorder'].index(i)))
        elif not match or match in skill['name']:
          msg.append('%-3s - %-30s : %2s %2s %2s %2s  %-2s  %-2s' % \
                      (self.spellups['sorder'].index(i),
                       skill['name'],
                       'A' if self.api('skills.isaffected')(i) else '',
                       'P' if self.api('setting.gets')('waiting') == i else '',
                       'B' if self.api('skills.isblockedbyrecovery')(i) else '',
                       'D' if not self.spellups['self'][i]['enabled'] else '',
                       'NP' if skill['percent'] == 1 else '',
                       'NL' if skill['percent'] == 0 else '',))
    else:
      msg.append('There are no spellups')
    return True, msg

  def cmd_srem(self, args):
    """
    remove a spellup
    """
    if len(args['spell']) < 1:
      return True, ['Please supply a spell/skill to remove']

    msg = []
    if args['spell'][0].lower() == 'all':
      del self.spellups['sorder']
      del self.spellups['self']
      self.initspellups()
      msg.append('All spellups to be cast on self cleared')

    else:
      for spella in args['spell']:
        spell = self.api('skills.gets')(spella)

        if not spell:
          msg.append('%s does not exist' % spella)
          continue

        spellnum = spell['sn']
        if spellnum in self.spellups['sorder']:
          self.spellups['sorder'].remove(spellnum)
        if spellnum in self.spellups['self']:
          del self.spellups['self'][spellnum]

        msg.append('Removed %s from spellups to self' % spell['name'])

      self.savestate()
      return True, msg

  def cmd_en(self, args):
    """
    enable a spellup
    """
    if len(args['spell']) < 1:
      return True, ['Please supply a spell/skill to enable']

    msg = []

    if args['spell'][0].lower() == 'all':
      for i in self.spellups['self']:
        self.spellups['self'][i]['enabled'] = True

      msg.append('All spellups enabled')
      self.nextspell()
      return True, msg

    for spellnum in args['spell']:
      skill = self.api('skills.gets')(spellnum)
      if skill:
        if skill['sn'] in self.spellups['sorder']:
          self.spellups['self'][skill['sn']]['enabled'] = True
          msg.append('%s: enabled' % skill['name'])
        else:
          msg.append('%s: not in self spellup list' % skill['name'])
      else:
        msg.append('%s: could not find spell' % spellnum)
    self.nextspell()
    return True, msg

  def cmd_dis(self, args):
    """
    enable a spellup
    """
    if len(args['spell']) < 1:
      return True, ['Please supply a spell/skill to enable']

    msg = []
    if args['spell'][0].lower() == 'all':
      for i in self.spellups['self']:
        self.spellups['self'][i]['enabled'] = False

      msg.append('All spellups disabled')
      return True, msg

    for spellnum in args['spell']:
      skill = self.api('skills.gets')(spellnum)
      if skill:
        if skill['sn'] in self.spellups['sorder']:
          self.spellups['self'][skill['sn']]['enabled'] = False
          msg.append('%s: disabled' % skill['name'])
        else:
          msg.append('%s: not in self spellup list' % skill['name'])
      else:
        msg.append('%s: could not find spell' % spellnum)
    return True, msg

  def cmd_check(self, _=None):
    """
    list all items that are need for spellups and whether they are known
    """
    tmsg = []
    tformat = '%-25s : %-10s - %s'
    tmsg.append(tformat % \
                 ('enabled',
                  self.api('setting.gets')('enabled'),
                  'should be True to cast spells'))
    tmsg.append(tformat % \
                 ('waiting',
                  self.api('setting.gets')('waiting'),
                  'the spell that was last cast, should be -1 to cast spells'))
    tmsg.append(tformat % \
                 ('nocast',
                  self.api('setting.gets')('nocast'),
                  'the current room is nocast, should be False to cast spells'))
    tmsg.append(tformat % \
                 ('nomoves',
                  self.api('setting.gets')('nomoves'),
                  'ran out of moves, should be False to cast spells'))
    tmsg.append(tformat % \
                 ('nomana',
                  self.api('setting.gets')('nomana'),
                  'ran out of mana, should be False to cast spells'))
    tmsg.append(tformat % \
                 ('Skills are up to date',
                  self.api('skills.isuptodate')(),
                  'should be True to cast spells'))
    tmsg.append(tformat % \
                 ('Char state',
                  self.api('GMCP.getv')('char.status.state'),
                  'should be 3 to cast spells'))
    return True, tmsg

  def reset(self):
    """
    reset all spellups
    """
    AardwolfBasePlugin.reset(self)
    self.spellups.clear()
    self.initspellups()
    self.spellups.sync()
Example #32
0
class Plugin(BasePlugin):
  """
  a class to manage internal commands
  """
  def __init__(self, *args, **kwargs):
    """
    init the class
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.canreload = False

    self.cmds = {}
    self.nomultiplecmds = {}

    self.savehistfile = os.path.join(self.savedir, 'history.txt')
    self.cmdhistorydict = PersistentDict(self.savehistfile, 'c')
    if 'history' not in self.cmdhistorydict:
      self.cmdhistorydict['history'] = []
    self.cmdhistory = self.cmdhistorydict['history']

    self.api.get('api.add')('add', self.api_addcmd)
    self.api.get('api.add')('remove', self.api_removecmd)
    self.api.get('api.add')('change', self.api_changecmd)
    self.api.get('api.add')('default', self.api_setdefault)
    self.api.get('api.add')('removeplugin', self.api_removeplugin)
    self.api.get('api.add')('list', self.api_listcmds)
    self.api.get('api.add')('run', self.api_run)
    self.api.get('api.add')('cmdhelp', self.api_cmdhelp)


  def load(self):
    """
    load external stuff
    """
    BasePlugin.load(self)
    self.api.get('log.adddtype')(self.sname)
    #self.api.get('log.console')(self.sname)

    self.api.get('setting.add')('spamcount', 20, int,
                                'the # of times a command can ' \
                                 'be run before an antispam command')
    self.api.get('setting.add')('antispamcommand', 'look', str,
                                'the antispam command to send')
    self.api.get('setting.add')('cmdcount', 0, int,
                                'the # of times the current command has been run',
                                readonly=True)
    self.api.get('setting.add')('lastcmd', '', str,
                                'the last command that was sent to the mud',
                                readonly=True)
    self.api.get('setting.add')('historysize', 50, int,
                                'the size of the history to keep')

    parser = argparse.ArgumentParser(add_help=False,
                                     description='list commands in a category')
    parser.add_argument('category',
                        help='the category to see help for',
                        default='',
                        nargs='?')
    parser.add_argument('cmd',
                        help='the command in the category (can be left out)',
                        default='',
                        nargs='?')
    self.api.get('commands.add')('list',
                                 self.cmd_list,
                                 shelp='list commands',
                                 parser=parser,
                                 history=False)

    parser = argparse.ArgumentParser(add_help=False,
                                     description='list the command history')
    parser.add_argument('-c',
                        "--clear",
                        help="clear the history",
                        action='store_true')
    self.api.get('commands.add')('history',
                                 self.cmd_history,
                                 shelp='list or run a command in history',
                                 parser=parser,
                                 history=False)

    parser = argparse.ArgumentParser(add_help=False,
                                     description='run a command in history')
    parser.add_argument('number',
                        help='the history # to run',
                        default=-1,
                        nargs='?',
                        type=int)
    self.api.get('commands.add')('!',
                                 self.cmd_runhistory,
                                 shelp='run a command in history',
                                 parser=parser,
                                 preamble=False,
                                 format=False,
                                 history=False)

    self.api.get('events.register')('from_client_event', self.chkcmd, prio=5)
    self.api.get('events.register')('plugin_unloaded', self.pluginunloaded)
    self.api.get('events.eraise')('plugin_cmdman_loaded', {})

  def pluginunloaded(self, args):
    """
    a plugin was unloaded
    """
    self.api('send.msg')('removing commands for plugin %s' % args['name'],
                         secondary=args['name'])
    self.api('%s.removeplugin' % self.sname)(args['name'])

  def formatretmsg(self, msg, sname, cmd):
    """
    format a return message
    """

    linelen = self.api('plugins.getp')('proxy').api('setting.gets')('linelen')

    msg.insert(0, '')
    msg.insert(1, '#bp.%s.%s' % (sname, cmd))
    msg.insert(2, '@G' + '-' * linelen + '@w')
    msg.append('@G' + '-' * linelen + '@w')
    msg.append('')
    return msg

  # change an attribute for a command
  def api_changecmd(self, plugin, command, flag, value):
    """
    change an attribute for a command
    """
    if command not in self.cmds[plugin]:
      self.api('send.error')('command %s does not exist in plugin %s' % \
        (command, plugin))
      return False

    if flag not in self.cmds[plugin][command]:
      self.api('send.error')(
          'flag %s does not exist in command %s in plugin %s' % \
            (flag, command, plugin))
      return False

    self.cmds[plugin][command][flag] = value

    return True

  # return the help for a command
  def api_cmdhelp(self, plugin, cmd):
    """
    get the help for a command
    """
    if plugin in self.cmds and cmd in self.cmds[plugin]:
      return self.cmds[plugin][cmd]['parser'].format_help()
    else:
      return ''

  # return a formatted list of commands for a plugin
  def api_listcmds(self, plugin, cformat=True):
    """
    list commands for a plugin
    """
    if cformat:
      return self.listcmds(plugin)
    else:
      if plugin in self.cmds:
        return self.cmds[plugin]
      else:
        return {}

  # run a command and return the output
  def api_run(self, plugin, cmdname, argstring):
    """
    run a command and return the output
    """
    if plugin in self.cmds and cmdname in self.cmds[plugin]:
      cmd = self.cmds[plugin][cmdname]
      args, dummy = cmd['parser'].parse_known_args(argstring)

      args = vars(args)

      if args['help']:
        return cmd['parser'].format_help().split('\n')
      else:
        return cmd['func'](args)

  def runcmd(self, cmd, targs, fullargs, data):
    """
    run a command that has an ArgParser
    """
    retval = False

    args, dummy = cmd['parser'].parse_known_args(targs)

    args = vars(args)
    args['fullargs'] = fullargs
    if args['help']:
      msg = cmd['parser'].format_help().split('\n')
      self.api.get('send.client')('\n'.join(
          self.formatretmsg(msg,
                            cmd['sname'],
                            cmd['commandname'])))

    else:
      args['data'] = data
      retvalue = cmd['func'](args)
      if isinstance(retvalue, tuple):
        retval = retvalue[0]
        msg = retvalue[1]
      else:
        retval = retvalue
        msg = []

      if retval is False:
        msg.append('')
        msg.extend(cmd['parser'].format_help().split('\n'))
        self.api.get('send.client')('\n'.join(
            self.formatretmsg(msg,
                              cmd['sname'],
                              cmd['commandname'])))
      else:
        self.addtohistory(data, cmd)
        if (not cmd['format']) and msg:
          self.api.get('send.client')(msg, preamble=cmd['preamble'])
        elif msg:
          self.api.get('send.client')('\n'.join(
              self.formatretmsg(msg,
                                cmd['sname'],
                                cmd['commandname'])),
                                      preamble=cmd['preamble'])

    return retval

  def addtohistory(self, data, cmd=None):
    """
    add to the command history
    """
    if 'history' in data and not data['history']:
      return
    if cmd and not cmd['history']:
      return

    tdat = data['fromdata']
    if data['fromclient']:
      if tdat in self.cmdhistory:
        self.cmdhistory.remove(tdat)
      self.cmdhistory.append(tdat)
      if len(self.cmdhistory) >= self.api('setting.gets')('historysize'):
        self.cmdhistory.pop(0)
      self.cmdhistorydict.sync()

  def chkcmd(self, data):
    # pylint: disable=too-many-nested-blocks,too-many-return-statements,too-many-branches
    # pylint: disable=too-many-statements
    """
    check a line from a client for a command
    """
    tdat = data['fromdata']

    if tdat == '':
      return

    if tdat[0:3].lower() == '#bp':
      targs = shlex.split(tdat.strip())
      try:
        tmpind = tdat.index(' ')
        fullargs = tdat[tmpind+1:]
      except ValueError:
        fullargs = ''
      cmd = targs.pop(0)
      cmdsplit = cmd.split('.')
      sname = ''
      if len(cmdsplit) >= 2:
        sname = cmdsplit[1].strip()

      scmd = ''
      if len(cmdsplit) >= 3:
        scmd = cmdsplit[2].strip()

      if 'help' in targs:
        try:
          del targs[targs.index('help')]
        except ValueError:
          pass
        cmd = self.cmds[self.sname]['list']
        self.runcmd(cmd, [sname, scmd], fullargs, data)

      elif sname:
        if sname not in self.cmds:
          self.api.get('send.client')("@R%s.%s@W is not a command." % \
                                                  (sname, scmd))
        else:
          if scmd:
            cmd = None
            if scmd in self.cmds[sname]:
              cmd = self.cmds[sname][scmd]
            if cmd:
              try:
                self.runcmd(cmd, targs, fullargs, data)
              except Exception:  # pylint: disable=broad-except
                self.api.get('send.traceback')(
                    'Error when calling command %s.%s' % (sname, scmd))
                return {'fromdata':''}
            else:
              self.api.get('send.client')("@R%s.%s@W is not a command" % \
                                                    (sname, scmd))
          else:
            if 'default' in self.cmds[sname]:
              cmd = self.cmds[sname]['default']
              try:
                self.runcmd(cmd, targs, fullargs, data)
              except Exception:  # pylint: disable=broad-except
                self.api.get('send.traceback')(
                    'Error when calling command %s.%s' % (sname, scmd))
                return {'fromdata':''}
            else:
              cmd = self.cmds[self.sname]['list']
              try:
                self.runcmd(cmd, [sname, scmd], '', data)
              except Exception:  # pylint: disable=broad-except
                self.api.get('send.traceback')(
                    'Error when calling command %s.%s' % (sname, scmd))
                return {'fromdata':''}
      else:
        try:
          del targs[targs.index('help')]
        except ValueError:
          pass
        cmd = self.cmds[self.sname]['list']
        try:
          self.runcmd(cmd, [sname, scmd], '', data)
        except Exception:  # pylint: disable=broad-except
          self.api.get('send.traceback')(
              'Error when calling command %s.%s' % (sname, scmd))
          return {'fromdata':''}

      return {'fromdata':''}
    else:
      self.addtohistory(data)
      if tdat.strip() == self.api.get('setting.gets')('lastcmd'):
        self.api.get('setting.change')('cmdcount',
                                       self.api.get('setting.gets')('cmdcount') + 1)
        if self.api.get('setting.gets')('cmdcount') == \
                              self.api.get('setting.gets')('spamcount'):
          data['fromdata'] = self.api.get('setting.gets')('antispamcommand') \
                                      + '|' + tdat
          self.api.get('send.msg')('adding look for 20 commands')
          self.api.get('setting.change')('cmdcount', 0)
        if tdat in self.nomultiplecmds:
          data['fromdata'] = ''
      else:
        self.api.get('setting.change')('cmdcount', 0)
        self.api.get('send.msg')('resetting command to %s' % tdat.strip())
        self.api.get('setting.change')('lastcmd', tdat.strip())

      return data

  # add a command
  def api_addcmd(self, cmdname, func, **kwargs):
    # pylint: disable=too-many-branches
    """  add a command
    @Ycmdname@w  = the base that the api should be under
    @Yfunc@w   = the function that should be run when this command is executed
    @Ykeyword arguments@w
      @Yshelp@w    = the short help, a brief description of what the
                                          command does
      @Ylhelp@w    = a longer description of what the command does
      @Ypreamble@w = show the preamble for this command (default: True)
      @Yformat@w   = format this command (default: True)
      @Ygroup@w    = the group this command is in

    The command will be added as sname.cmdname

    sname is gotten from the class the function belongs to or the sname key
      in args

    this function returns no values"""

    args = kwargs.copy()

    lname = None
    if not func:
      self.api.get('send.msg')('cmd %s has no function, not adding' % \
                                                (cmdname))
      return
    try:
      sname = func.im_self.sname
    except AttributeError:
      if 'sname' in args:
        sname = args['sname']
      else:
        self.api.get('send.msg')('Function is not part of a plugin class: %s' \
                                                      % cmdname)
        return

    if 'parser' in args:
      tparser = args['parser']
      tparser.formatter_class = CustomFormatter

    else:
      self.api.get('send.msg')('adding default parser to command %s.%s' % \
                                      (sname, cmdname))
      if 'shelp' not in args:
        args['shelp'] = 'there is no help for this command'
      tparser = argparse.ArgumentParser(add_help=False,
                                        description=args['shelp'])
      args['parser'] = tparser

    tparser.add_argument("-h", "--help", help="show help",
                         action="store_true")

    tparser.prog = '@B#bp.%s.%s@w' % (sname, cmdname)

    if 'group' not in args:
      args['group'] = sname


    try:
      lname = func.im_self.name
      args['lname'] = lname
    except AttributeError:
      pass

    if 'lname' not in args:
      self.api.get('send.msg')('cmd %s.%s has no long name, not adding' % \
                                            (sname, cmdname),
                               secondary=sname)
      return

    self.api.get('send.msg')('added cmd %s.%s' % \
                                            (sname, cmdname),
                             secondary=sname)

    if sname not in self.cmds:
      self.cmds[sname] = {}
    args['func'] = func
    args['sname'] = sname
    args['lname'] = lname
    args['commandname'] = cmdname
    if 'preamble' not in args:
      args['preamble'] = True
    if 'format' not in args:
      args['format'] = True
    if 'history' not in args:
      args['history'] = True
    self.cmds[sname][cmdname] = args

  # remove a command
  def api_removecmd(self, sname, cmdname):
    """  remove a command
    @Ysname@w    = the top level of the command
    @Ycmdname@w  = the name of the command

    this function returns no values"""
    if sname in self.cmds and cmdname in self.cmds[sname]:
      del self.cmds[sname][cmdname]
    else:
      self.api.get('send.msg')('remove cmd: cmd %s.%s does not exist' % \
                                                (sname, cmdname),
                               secondary=sname)

    self.api.get('send.msg')('removed cmd %s.%s' % \
                                                (sname, cmdname),
                             secondary=sname)

  # set the default command for a plugin
  def api_setdefault(self, cmd, plugin=None):
    """  set the default command for a plugin
    @Ysname@w    = the plugin of the command
    @Ycmdname@w  = the name of the command

    this function returns True if the command exists, False if it doesn't"""

    if not plugin:
      plugin = self.api('utils.funccallerplugin')()

    if not plugin:
      print 'could not add a default cmd', cmd
      return False

    if plugin in self.cmds and cmd in self.cmds[plugin]:
      self.api('send.msg')('added default command %s for plugin %s' % (cmd, plugin),
                           secondary=plugin)
      self.cmds[plugin]['default'] = self.cmds[plugin][cmd]
      return True

    return False

  # remove all commands for a plugin
  def api_removeplugin(self, plugin):
    """  remove all commands for a plugin
    @Ysname@w    = the plugin to remove commands for

    this function returns no values"""
    if plugin in self.cmds:
      del self.cmds[plugin]
    else:
      self.api.get('send.msg')('removeplugin: plugin %s does not exist' % \
                                                        plugin)

  def format_cmdlist(self, category, cmdlist):
    """
    format a list of commands
    """
    tmsg = []
    for i in cmdlist:
      if i != 'default':
        tlist = self.cmds[category][i]['parser'].description.split('\n')
        if not tlist[0]:
          tlist.pop(0)
        tmsg.append('  @B%-10s@w : %s' % (i, tlist[0]))

    return tmsg

  def listcmds(self, category):
    """
    build a table of commands for a category
    """
    tmsg = []
    if category:
      if category in self.cmds:
        tmsg.append('Commands in %s:' % category)
        tmsg.append('@G' + '-' * 60 + '@w')
        groups = {}
        for i in sorted(self.cmds[category].keys()):
          if i != 'default':
            if self.cmds[category][i]['group'] not in groups:
              groups[self.cmds[category][i]['group']] = []

            groups[self.cmds[category][i]['group']].append(i)

        if len(groups) == 1:
          tmsg.extend(self.format_cmdlist(category,
                                          self.cmds[category].keys()))
        else:
          for group in sorted(groups.keys()):
            if group != 'Base':
              tmsg.append('@M' + '-' * 5 + ' ' +  group + ' ' + '-' * 5)
              tmsg.extend(self.format_cmdlist(category, groups[group]))
              tmsg.append('')

          tmsg.append('@M' + '-' * 5 + ' ' +  'Base' + ' ' + '-' * 5)
          tmsg.extend(self.format_cmdlist(category, groups['Base']))
        #tmsg.append('@G' + '-' * 60 + '@w')
    return tmsg

  def cmd_list(self, args):
    """
    list commands
    """
    tmsg = []
    category = args['category']
    cmd = args['cmd']
    if category:
      if category in self.cmds:
        if cmd and cmd in self.cmds[category]:
          msg = self.cmds[category][cmd]['parser'].format_help().split('\n')
          tmsg.extend(msg)
        else:
          tmsg.extend(self.listcmds(category))
      else:
        tmsg.append('There is no category %s' % category)
    else:
      tmsg.append('Categories:')
      tkeys = self.cmds.keys()
      tkeys.sort()
      for i in tkeys:
        tmsg.append('  %s' % i)
    return True, tmsg

  def cmd_runhistory(self, args):
    """
    act on the command history
    """
    if len(self.cmdhistory) < abs(args['number']):
      return True, ['# is outside of history length']

    if len(self.cmdhistory) >= self.api('setting.gets')('historysize'):
      cmd = self.cmdhistory[args['number'] - 1]
    else:
      cmd = self.cmdhistory[args['number']]

    self.api('send.client')('history: sending "%s"' % cmd)
    self.api('send.execute')(cmd)

    return True, []

  def cmd_history(self, args):
    """
    act on the command history
    """
    tmsg = []

    if args['clear']:
      del self.cmdhistorydict['history'][:]
      self.cmdhistorydict.sync()
      tmsg.append('Command history cleared')
    else:
      for i in self.cmdhistory:
        tmsg.append('%s : %s' % (self.cmdhistory.index(i), i))

    return True, tmsg

  def savestate(self):
    """
    save states
    """
    BasePlugin.savestate(self)
    self.cmdhistorydict.sync()
Example #33
0
class Plugin(BasePlugin):
    """
  a plugin to do simple substitution
  """
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        BasePlugin.__init__(self, *args, **kwargs)
        self.savesubfile = os.path.join(self.savedir, 'subs.txt')
        self._substitutes = PersistentDict(self.savesubfile, 'c')

    def load(self):
        """
    load the plugins
    """
        BasePlugin.load(self)

        parser = argp.ArgumentParser(add_help=False,
                                     description='add a simple substitute')
        parser.add_argument('original',
                            help='the output to substitute',
                            default='',
                            nargs='?')
        parser.add_argument('replacement',
                            help='the string to replace it with',
                            default='',
                            nargs='?')
        self.api('commands.add')('add', self.cmd_add, parser=parser)

        parser = argp.ArgumentParser(add_help=False,
                                     description='remove a substitute')
        parser.add_argument('substitute',
                            help='the substitute to remove',
                            default='',
                            nargs='?')
        self.api('commands.add')('remove', self.cmd_remove, parser=parser)

        parser = argp.ArgumentParser(add_help=False,
                                     description='list substitutes')
        parser.add_argument(
            'match',
            help='list only substitutes that have this argument in them',
            default='',
            nargs='?')
        self.api('commands.add')('list', self.cmd_list, parser=parser)

        parser = argp.ArgumentParser(add_help=False,
                                     description='clear all substitutes')
        self.api('commands.add')('clear', self.cmd_clear, parser=parser)

        self.api('commands.default')('list')
        self.api('events.register')('from_mud_event', self.findsub)

        self.api('events.register')('plugin_%s_savestate' % self.sname,
                                    self._savestate)

    def findsub(self, args):
        """
    this function finds subs in mud data
    """
        data = args['original']
        dtype = args['dtype']
        if dtype != 'fromproxy':
            for mem in self._substitutes.keys():
                if mem in data:
                    ndata = data.replace(
                        mem,
                        self.api('colors.convertcolors')(
                            self._substitutes[mem]['sub']))
                    if ndata != data:
                        args['trace']['changes'].append({'flag':'Modify',
                                                         'data':'changed "%s" to "%s"' % \
                                                             (data, ndata),
                                                         'plugin':self.sname,
                                                         'eventname':args['eventname']})
                        data = ndata
            args['original'] = data
            return args

    def cmd_add(self, args):
        """
    @G%(name)s@w - @B%(cmdname)s@w
      Add a substitute
      @CUsage@w: add @Y<originalstring>@w @M<replacementstring>@w
        @Yoriginalstring@w    = The original string to be replaced
        @Mreplacementstring@w = The new string
    """
        tmsg = []
        if args['original'] and args['replacement']:
            tmsg.append("@GAdding substitute@w : '%s' will be replaced by '%s'" % \
                                            (args['original'], args['replacement']))
            self.addsub(args['original'], args['replacement'])
            return True, tmsg

        tmsg.append("@RPlease specify all arguments@w")
        return False, tmsg

    def cmd_remove(self, args):
        """
    @G%(name)s@w - @B%(cmdname)s@w
      Remove a substitute
      @CUsage@w: rem @Y<originalstring>@w
        @Yoriginalstring@w    = The original string
    """
        tmsg = []
        if args['substitute']:
            tmsg.append("@GRemoving substitute@w : '%s'" %
                        (args['substitute']))
            self.removesub(args['substitute'])
            return True, tmsg

        return False, tmsg

    def cmd_list(self, args):
        """
    @G%(name)s@w - @B%(cmdname)s@w
      List substitutes
      @CUsage@w: list
    """
        tmsg = self.listsubs(args['match'])
        return True, tmsg

    def cmd_clear(self, args):
        # pylint: disable=unused-argument
        """
    @G%(name)s@w - @B%(cmdname)s@w
      List substitutes
      @CUsage@w: list"""
        self.clearsubs()
        return True, ['Substitutes cleared']

    def addsub(self, item, sub):
        """
    internally add a substitute
    """
        self._substitutes[item] = {'sub': sub}
        self._substitutes.sync()

    def removesub(self, item):
        """
    internally remove a substitute
    """
        if item in self._substitutes:
            del self._substitutes[item]
            self._substitutes.sync()

    def listsubs(self, match):
        """
    return a table of strings that list subs
    """
        tmsg = []
        for item in self._substitutes:
            if not match or match in item:
                tmsg.append("%-35s : %s@w" %
                            (item, self._substitutes[item]['sub']))
        if not tmsg:
            tmsg = ['None']
        return tmsg

    def clearsubs(self):
        """
    clear all subs
    """
        self._substitutes.clear()
        self._substitutes.sync()

    def reset(self):
        """
    reset the plugin
    """
        BasePlugin.reset(self)
        self.clearsubs()

    def _savestate(self, _=None):
        """
    save states
    """
        self._substitutes.sync()
Example #34
0
class Plugin(BasePlugin):
    """
  a plugin to handle user aliases
  """
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        BasePlugin.__init__(self, *args, **kwargs)

        self.aliasfile = os.path.join(self.savedir, 'aliases.txt')
        self._aliases = PersistentDict(self.aliasfile, 'c')

        self.sessionhits = {}

    def load(self):
        """
    load the plugin
    """
        BasePlugin.load(self)

        self.api('setting.add')('nextnum',
                                0,
                                int,
                                'the number of the next alias added',
                                readonly=True)

        parser = argp.ArgumentParser(add_help=False,
                                     description='add an alias')
        parser.add_argument('original',
                            help='the input to replace',
                            default='',
                            nargs='?')
        parser.add_argument('replacement',
                            help='the string to replace it with',
                            default='',
                            nargs='?')
        parser.add_argument('-o',
                            "--overwrite",
                            help="overwrite an alias if it already exists",
                            action="store_true")
        parser.add_argument('-d',
                            "--disable",
                            help="disable the alias",
                            action="store_true")
        parser.add_argument('-g',
                            "--group",
                            help="the alias group",
                            default="")
        self.api('commands.add')('add', self.cmd_add, parser=parser)

        parser = argp.ArgumentParser(add_help=False,
                                     description='remove an alias')
        parser.add_argument('alias',
                            help='the alias to remove',
                            default='',
                            nargs='?')
        self.api('commands.add')('remove', self.cmd_remove, parser=parser)

        parser = argp.ArgumentParser(add_help=False,
                                     description='list aliases')
        parser.add_argument(
            'match',
            help='list only aliases that have this argument in them',
            default='',
            nargs='?')
        self.api('commands.add')('list', self.cmd_list, parser=parser)

        parser = argp.ArgumentParser(add_help=False,
                                     description='toggle enabled flag')
        parser.add_argument('alias',
                            help='the alias to toggle',
                            default='',
                            nargs='?')
        self.api('commands.add')('toggle', self.cmd_toggle, parser=parser)

        parser = argp.ArgumentParser(
            add_help=False, description='toggle all aliases in a group')
        parser.add_argument('group',
                            help='the group to toggle',
                            default='',
                            nargs='?')
        parser.add_argument('-d',
                            "--disable",
                            help="disable the group",
                            action="store_true")
        self.api('commands.add')('groupt', self.cmd_grouptoggle, parser=parser)

        parser = argp.ArgumentParser(add_help=False,
                                     description='get detail for an alias')
        parser.add_argument('alias',
                            help='the alias to get details for',
                            default='',
                            nargs='?')
        self.api('commands.add')('detail', self.cmd_detail, parser=parser)

        self.api('commands.default')('list')
        self.api('events.register')('io_execute_event',
                                    self.checkalias,
                                    prio=2)
        self.api('events.register')('plugin_%s_savestate' % self.sname,
                                    self._savestate)

    def checkalias(self, args):  # pylint: disable=too-many-branches
        """
    this function finds aliases in client input
    """
        data = args['fromdata'].strip()

        if not data:
            return args

        for mem in self._aliases.keys():
            if self._aliases[mem]['enabled']:
                datan = data
                matchd = re.match(mem, data)
                if matchd:
                    self.api('send.msg')('matched input on %s' % mem)
                    tlistn = [data]
                    for i in xrange(1, len(matchd.groups()) + 1):
                        tlistn.append(matchd.group(i))
                    self.api('send.msg')('args: %s' % tlistn)
                    try:
                        datan = self._aliases[mem]['alias'].format(*tlistn)
                    except Exception:  # pylint: disable=broad-except
                        self.api('send.traceback')('alias %s had an issue' %
                                                   (mem))
                else:
                    cre = re.compile('^%s' % mem)
                    datan = cre.sub(self._aliases[mem]['alias'], data)
                if datan != data:
                    if 'trace' in args:
                        args['trace']['changes'].append({'flag':'Modify',
                                                         'data':'changed "%s" to "%s"' % \
                                                            (data, datan),
                                                         'plugin':self.sname})
                    if not 'hits' in self._aliases[mem]:
                        self._aliases[mem]['hits'] = 0
                    if not mem in self.sessionhits:
                        self.sessionhits[mem] = 0
                    self.api('send.msg')('incrementing hits for %s' % mem)
                    self._aliases[mem]['hits'] = self._aliases[mem]['hits'] + 1
                    self.sessionhits[mem] = self.sessionhits[mem] + 1
                    self.api('send.msg')('replacing "%s" with "%s"' % \
                                                    (data.strip(), datan.strip()))
                    if datan[0:3] == '#bp':
                        self.api('send.execute')(datan,
                                                 showinhistory=False,
                                                 fromclient=False)
                        args['fromdata'] = ''
                        args['history'] = False
                    else:
                        args['history'] = False
                        args['fromclient'] = False
                        args['fromdata'] = datan

        return args

    def lookup_alias(self, alias):
        """
    lookup an alias by number or name
    """
        nitem = None
        try:
            num = int(alias)
            nitem = None
            for titem in self._aliases.keys():
                if num == self._aliases[titem]['num']:
                    nitem = titem
                    break

        except ValueError:
            if alias in self._aliases:
                nitem = alias

        return nitem

    def cmd_add(self, args):
        """
    @G%(name)s@w - @B%(cmdname)s@w
      Add a alias
      @CUsage@w: add @Y<originalstring>@w @M<replacementstring>@w
        @Yoriginalstring@w    = The original string to be replaced
        @Mreplacementstring@w = The new string
    """
        tmsg = []
        if args['original'] and args['replacement']:
            if args['original'] in self._aliases and not args['overwrite']:
                return True, ['Alias: %s already exists.' % args['original']]
            else:
                tmsg.append("@GAdding alias@w : '%s' will be replaced by '%s'" % \
                                              (args['original'], args['replacement']))
                self.addalias(args['original'], args['replacement'],
                              args['disable'], args['group'])
            return True, tmsg
        else:
            return False, ['@RPlease include all arguments@w']

    def cmd_remove(self, args):
        """
    @G%(name)s@w - @B%(cmdname)s@w
      Remove a alias
      @CUsage@w: rem @Y<originalstring>@w
        @Yoriginalstring@w    = The original string
    """
        tmsg = []
        if args['alias']:
            retval = self.removealias(args['alias'])
            if retval:
                tmsg.append("@GRemoving alias@w : '%s'" % (retval))
            else:
                tmsg.append("@GCould not remove alias@w : '%s'" %
                            (args['alias']))

            return True, tmsg
        else:
            return False, ['@RPlease include an alias to remove@w']

    def cmd_toggle(self, args):
        """
    toggle the enabled flag
    """
        tmsg = []
        if args['alias']:
            retval = self.togglealias(args['alias'])
            if retval:
                if self._aliases[retval]['enabled']:
                    tmsg.append("@GEnabled alias@w : '%s'" % (retval))
                else:
                    tmsg.append("@GDisabled alias@w : '%s'" % (retval))
            else:
                tmsg.append("@GDoes not exist@w : '%s'" % (args['alias']))
            return True, tmsg

        else:
            return False, ['@RPlease include an alias to toggle@w']

    def cmd_detail(self, args):
        """
    @G%(name)s@w - @B%(cmdname)s@w
      Add a alias
      @CUsage@w: add @Y<originalstring>@w @M<replacementstring>@w
        @Yoriginalstring@w    = The original string to be replaced
        @Mreplacementstring@w = The new string
    """
        tmsg = []
        if args['alias']:
            alias = self.lookup_alias(args['alias'])
            if alias:
                if 'hits' not in self._aliases[alias]:
                    self._aliases[alias]['hits'] = 0
                if alias not in self.sessionhits:
                    self.sessionhits[alias] = 0
                tmsg.append('%-12s : %d' %
                            ('Num', self._aliases[alias]['num']))
                tmsg.append('%-12s : %s' % \
                    ('Enabled', 'Y' if self._aliases[alias]['enabled'] else 'N'))
                tmsg.append('%-12s : %d' %
                            ('Total Hits', self._aliases[alias]['hits']))
                tmsg.append('%-12s : %d' %
                            ('Session Hits', self.sessionhits[alias]))
                tmsg.append('%-12s : %s' % ('Alias', alias))
                tmsg.append('%-12s : %s' %
                            ('Replacement', self._aliases[alias]['alias']))
                tmsg.append('%-12s : %s' %
                            ('Group', self._aliases[alias]['group']))
            else:
                return True, [
                    '@RAlias does not exits@w : \'%s\'' % (args['alias'])
                ]

            return True, tmsg
        else:
            return False, ['@RPlease include all arguments@w']

    def cmd_list(self, args):
        """
    @G%(name)s@w - @B%(cmdname)s@w
      List aliases
      @CUsage@w: list
    """
        tmsg = self.listaliases(args['match'])
        return True, tmsg

    def cmd_grouptoggle(self, args):
        """
    toggle all aliases in a group
    """
        tmsg = []
        togglea = []
        state = not args['disable']
        if args['group']:
            for i in self._aliases:
                if 'group' not in self._aliases[i]:
                    self._aliases[i]['group'] = ''

                if self._aliases[i]['group'] == args['group']:
                    self._aliases[i]['enabled'] = state
                    togglea.append('%s' % self._aliases[i]['num'])

            if togglea:
                tmsg.append('The following aliases were %s: %s' % \
                      ('enabled' if state else 'disabled',
                       ','.join(togglea)))
            else:
                tmsg.append('No aliases were modified')

            return True, tmsg
        else:
            return False, ['@RPlease include a group to toggle@w']

    def addalias(self, item, alias, disabled, group):
        """
    internally add a alias
    """
        num = self.api('setting.gets')('nextnum')
        self._aliases[item] = {
            'alias': alias,
            'enabled': not disabled,
            'num': num,
            'group': group
        }
        self._aliases.sync()
        self.api('setting.change')('nextnum', num + 1)

    def removealias(self, item):
        """
    internally remove a alias
    """
        alias = self.lookup_alias(item)
        if alias:
            del self._aliases[alias]
            self._aliases.sync()

        return alias

    def togglealias(self, item):
        """
    toggle an alias
    """
        alias = self.lookup_alias(item)
        if alias:
            self._aliases[alias][
                'enabled'] = not self._aliases[alias]['enabled']

        return alias

    def listaliases(self, match):
        """
    return a table of strings that list aliases
    """
        tmsg = []
        for alias in sorted(self._aliases.iteritems(),
                            key=lambda (x, y): y['num']):
            item = alias[0]
            if not match or match in item:
                lalias = self.api('colors.stripansi')(
                    self._aliases[item]['alias'])
                if len(lalias) > 30:
                    lalias = lalias[:27] + '...'
                tmsg.append("%4s %2s  %-10s %-20s : %s@w" % \
                             (self._aliases[item]['num'],
                              'Y' if self._aliases[item]['enabled'] else 'N',
                              self._aliases[item]['group'],
                              item,
                              lalias))
        if not tmsg:
            tmsg = ['None']
        else:
            tmsg.insert(
                0, "%4s %2s  %-10s %-20s : %s@w" %
                ('#', 'E', 'Group', 'Alias', 'Replacement'))
            tmsg.insert(1, '@B' + '-' * 60 + '@w')

        return tmsg

    def clearaliases(self):
        """
    clear all aliases
    """
        self._aliases.clear()
        self._aliases.sync()

    def reset(self):
        """
    reset the plugin
    """
        BasePlugin.reset(self)
        self.clearaliases()

    def _savestate(self, _=None):
        """
    save states
    """
        self._aliases.sync()
Example #35
0
class Plugin(BasePlugin):
  """
  a plugin to handle user aliases
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.aliasfile = os.path.join(self.savedir, 'aliases.txt')
    self._aliases = PersistentDict(self.aliasfile, 'c')

    self.sessionhits = {}

  def load(self):
    """
    load the plugin
    """
    BasePlugin.load(self)

    self.api.get('setting.add')('nextnum', 0, int,
                                'the number of the next alias added',
                                readonly=True)

    parser = argparse.ArgumentParser(add_help=False,
                                     description='add an alias')
    parser.add_argument('original',
                        help='the input to replace',
                        default='',
                        nargs='?')
    parser.add_argument('replacement',
                        help='the string to replace it with',
                        default='',
                        nargs='?')
    parser.add_argument('-o',
                        "--overwrite",
                        help="overwrite an alias if it already exists",
                        action="store_true")
    parser.add_argument('-d', "--disable",
                        help="disable the alias",
                        action="store_true")
    parser.add_argument('-g',
                        "--group",
                        help="the alias group",
                        default="")
    self.api.get('commands.add')('add',
                                 self.cmd_add,
                                 parser=parser)

    parser = argparse.ArgumentParser(add_help=False,
                                     description='remove an alias')
    parser.add_argument('alias',
                        help='the alias to remove',
                        default='',
                        nargs='?')
    self.api.get('commands.add')('remove',
                                 self.cmd_remove,
                                 parser=parser)

    parser = argparse.ArgumentParser(add_help=False,
                                     description='list aliases')
    parser.add_argument('match',
                        help='list only aliases that have this argument in them',
                        default='',
                        nargs='?')
    self.api.get('commands.add')('list',
                                 self.cmd_list,
                                 parser=parser)

    parser = argparse.ArgumentParser(add_help=False,
                                     description='toggle enabled flag')
    parser.add_argument('alias',
                        help='the alias to toggle',
                        default='',
                        nargs='?')
    self.api.get('commands.add')('toggle',
                                 self.cmd_toggle,
                                 parser=parser)

    parser = argparse.ArgumentParser(add_help=False,
                                     description='toggle all aliases in a group')
    parser.add_argument('group',
                        help='the group to toggle',
                        default='',
                        nargs='?')
    parser.add_argument('-d',
                        "--disable",
                        help="disable the group",
                        action="store_true")
    self.api.get('commands.add')('groupt',
                                 self.cmd_grouptoggle,
                                 parser=parser)

    parser = argparse.ArgumentParser(add_help=False,
                                     description='get detail for an alias')
    parser.add_argument('alias',
                        help='the alias to get details for',
                        default='',
                        nargs='?')
    self.api.get('commands.add')('detail',
                                 self.cmd_detail,
                                 parser=parser)

    self.api.get('commands.default')('list')
    self.api.get('events.register')('from_client_event', self.checkalias,
                                    prio=2)

  def checkalias(self, args):
    """
    this function finds aliases in client input
    """
    data = args['fromdata'].strip()

    if not data:
      return args

    for mem in self._aliases.keys():
      if self._aliases[mem]['enabled']:
        datan = data
        matchd = re.match(mem, data)
        if matchd:
          self.api.get('send.msg')('matched input on %s' % mem)
          tlistn = [data]
          for i in xrange(1, len(matchd.groups()) + 1):
            tlistn.append(matchd.group(i))
          self.api.get('send.msg')('args: %s' % tlistn)
          try:
            datan = self._aliases[mem]['alias'].format(*tlistn)
          except Exception: # pylint: disable=broad-except
            self.api.get('send.traceback')('alias %s had an issue' % (mem))
        else:
          cre = re.compile('^%s' % mem)
          datan = cre.sub(self._aliases[mem]['alias'], data)
        if datan != data:
          if not 'hits' in self._aliases[mem]:
            self._aliases[mem]['hits'] = 0
          if not mem in self.sessionhits:
            self.sessionhits[mem] = 0
          self.api.get('send.msg')('incrementing hits for %s' % mem)
          self._aliases[mem]['hits'] = self._aliases[mem]['hits'] + 1
          self.sessionhits[mem] = self.sessionhits[mem] + 1
          self.api.get('send.msg')('replacing "%s" with "%s"' % \
                                          (data.strip(), datan.strip()))
          if datan[0:3] == '#bp':
            self.api.get('send.execute')(datan, history=False, fromclient=False)
            args['fromdata'] = ''
            args['history'] = False
          else:
            args['history'] = False
            args['fromclient'] = False
            args['fromdata'] = datan

    return args

  def lookup_alias(self, alias):
    """
    lookup an alias by number or name
    """
    nitem = None
    try:
      num = int(alias)
      nitem = None
      for titem in self._aliases.keys():
        if num == self._aliases[titem]['num']:
          nitem = titem
          break

    except ValueError:
      if alias in self._aliases:
        nitem = alias

    return nitem

  def cmd_add(self, args):
    """
    @G%(name)s@w - @B%(cmdname)s@w
      Add a alias
      @CUsage@w: add @Y<originalstring>@w @M<replacementstring>@w
        @Yoriginalstring@w    = The original string to be replaced
        @Mreplacementstring@w = The new string
    """
    tmsg = []
    if args['original'] and args['replacement']:
      if args['original'] in self._aliases and not args['overwrite']:
        return True, ['Alias: %s already exists.' % args['original']]
      else:
        tmsg.append("@GAdding alias@w : '%s' will be replaced by '%s'" % \
                                      (args['original'], args['replacement']))
        self.addalias(args['original'], args['replacement'],
                      args['disable'], args['group'])
      return True, tmsg
    else:
      return False, ['@RPlease include all arguments@w']

  def cmd_remove(self, args):
    """
    @G%(name)s@w - @B%(cmdname)s@w
      Remove a alias
      @CUsage@w: rem @Y<originalstring>@w
        @Yoriginalstring@w    = The original string
    """
    tmsg = []
    if args['alias']:
      retval = self.removealias(args['alias'])
      if retval:
        tmsg.append("@GRemoving alias@w : '%s'" % (retval))
      else:
        tmsg.append("@GCould not remove alias@w : '%s'" % (args['alias']))

      return True, tmsg
    else:
      return False, ['@RPlease include an alias to remove@w']

  def cmd_toggle(self, args):
    """
    toggle the enabled flag
    """
    tmsg = []
    if args['alias']:
      retval = self.togglealias(args['alias'])
      if retval:
        if self._aliases[retval]['enabled']:
          tmsg.append("@GEnabled alias@w : '%s'" % (retval))
        else:
          tmsg.append("@GDisabled alias@w : '%s'" % (retval))
      else:
        tmsg.append("@GDoes not exist@w : '%s'" % (args['alias']))
      return True, tmsg

    else:
      return False, ['@RPlease include an alias to toggle@w']

  def cmd_detail(self, args):
    """
    @G%(name)s@w - @B%(cmdname)s@w
      Add a alias
      @CUsage@w: add @Y<originalstring>@w @M<replacementstring>@w
        @Yoriginalstring@w    = The original string to be replaced
        @Mreplacementstring@w = The new string
    """
    tmsg = []
    if args['alias']:
      alias = self.lookup_alias(args['alias'])
      if alias:
        if 'hits' not in self._aliases[alias]:
          self._aliases[alias]['hits'] = 0
        if alias not in self.sessionhits:
          self.sessionhits[alias] = 0
        tmsg.append('%-12s : %d' % ('Num', self._aliases[alias]['num']))
        tmsg.append('%-12s : %s' % \
            ('Enabled', 'Y' if self._aliases[alias]['enabled'] else 'N'))
        tmsg.append('%-12s : %d' % ('Total Hits',
                                    self._aliases[alias]['hits']))
        tmsg.append('%-12s : %d' % ('Session Hits', self.sessionhits[alias]))
        tmsg.append('%-12s : %s' % ('Alias', alias))
        tmsg.append('%-12s : %s' % ('Replacement',
                                    self._aliases[alias]['alias']))
        tmsg.append('%-12s : %s' % ('Group', self._aliases[alias]['group']))
      else:
        return True, ['@RAlias does not exits@w : \'%s\'' % (args['alias'])]

      return True, tmsg
    else:
      return False, ['@RPlease include all arguments@w']

  def cmd_list(self, args):
    """
    @G%(name)s@w - @B%(cmdname)s@w
      List aliases
      @CUsage@w: list
    """
    tmsg = self.listaliases(args['match'])
    return True, tmsg

  def cmd_grouptoggle(self, args):
    """
    toggle all aliases in a group
    """
    tmsg = []
    togglea = []
    state = not args['disable']
    if args['group']:
      for i in self._aliases:
        if 'group' not in self._aliases[i]:
          self._aliases[i]['group'] = ''

        if self._aliases[i]['group'] == args['group']:
          self._aliases[i]['enabled'] = state
          togglea.append('%s' % self._aliases[i]['num'])

      if togglea:
        tmsg.append('The following aliases were %s: %s' % \
              ('enabled' if state else 'disabled',
               ','.join(togglea)))
      else:
        tmsg.append('No aliases were modified')

      return True, tmsg
    else:
      return False, ['@RPlease include a group to toggle@w']

  def addalias(self, item, alias, disabled, group):
    """
    internally add a alias
    """
    num = self.api.get('setting.gets')('nextnum')
    self._aliases[item] = {'alias':alias, 'enabled':not disabled,
                           'num':num, 'group':group}
    self._aliases.sync()
    self.api.get('setting.change')('nextnum', num + 1)

  def removealias(self, item):
    """
    internally remove a alias
    """
    alias = self.lookup_alias(item)
    if alias:
      del self._aliases[alias]
      self._aliases.sync()

    return alias

  def togglealias(self, item):
    """
    toggle an alias
    """
    alias = self.lookup_alias(item)
    if alias:
      self._aliases[alias]['enabled'] = not self._aliases[alias]['enabled']

    return alias

  def listaliases(self, match):
    """
    return a table of strings that list aliases
    """
    tmsg = []
    for alias in sorted(self._aliases.iteritems(),
                        key=lambda (x, y): y['num']):
      item = alias[0]
      if not match or match in item:
        lalias = self.api.get('colors.stripansi')(self._aliases[item]['alias'])
        if len(lalias) > 30:
          lalias = lalias[:27] + '...'
        tmsg.append("%4s %2s  %-10s %-20s : %s@w" % \
                     (self._aliases[item]['num'],
                      'Y' if self._aliases[item]['enabled'] else 'N',
                      self._aliases[item]['group'],
                      item,
                      lalias))
    if len(tmsg) == 0:
      tmsg = ['None']
    else:
      tmsg.insert(0, "%4s %2s  %-10s %-20s : %s@w" % ('#', 'E', 'Group',
                                                      'Alias', 'Replacement'))
      tmsg.insert(1, '@B' + '-' * 60 + '@w')

    return tmsg

  def clearaliases(self):
    """
    clear all aliases
    """
    self._aliases.clear()
    self._aliases.sync()

  def reset(self):
    """
    reset the plugin
    """
    BasePlugin.reset(self)
    self.clearaliases()

  def savestate(self):
    """
    save states
    """
    BasePlugin.savestate(self)
    self._aliases.sync()
Example #36
0
class Plugin(AardwolfBasePlugin):
    """
  a plugin to handle aardwolf quest events
  """
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        AardwolfBasePlugin.__init__(self, *args, **kwargs)
        self.savequestfile = os.path.join(self.savedir, 'quest.txt')
        self.queststuff = PersistentDict(self.savequestfile, 'c')

    def load(self):
        """
    load the plugins
    """
        AardwolfBasePlugin.load(self)

        self.api('events.register')('GMCP:comm.quest', self.quest)

        self.api('events.register')('plugin_%s_savestate' % self.sname,
                                    self._savestate)

    def resetquest(self):
        """
    reset the quest info
    """
        self.queststuff.clear()
        self.queststuff['finishtime'] = -1
        self.queststuff['starttime'] = time.time()
        self.queststuff['killedtime'] = -1
        self.queststuff['mobname'] = ''
        self.queststuff['mobarea'] = ''
        self.queststuff['mobroom'] = ''
        self.queststuff['level'] = self.api('aardu.getactuallevel')(
            self.api('GMCP.getv')('char.status.level'))
        self.queststuff['failed'] = 0

    def quest(self, args):
        """
    process the quest event
    """
        questi = args['data']
        self.api('send.msg')('quest: %s' % questi)
        if questi['action'] == 'ready':
            self.api('events.eraise')('aard_quest_ready', {})
        elif questi['action'] == 'start':
            self.resetquest()
            self.queststuff['mobname'] = questi['targ']
            self.queststuff['mobarea'] = questi['area']
            self.queststuff['mobroom'] = questi['room']
            self.queststuff['stimer'] = questi['timer']
            self.api('events.eraise')('aard_quest_start', self.queststuff)
        elif questi['action'] == 'killed':
            self.queststuff['killedtime'] = time.time()
            self.api('events.eraise')('aard_quest_killed', self.queststuff)
        elif questi['action'] == 'comp':
            self.queststuff['finishtime'] = time.time()
            self.queststuff.update(questi)
            self.api('events.eraise')('aard_quest_comp',
                                      copy.deepcopy(self.queststuff))
        elif questi['action'] == 'fail' or questi['action'] == 'timeout':
            self.queststuff['finishtime'] = time.time()
            self.queststuff['failed'] = 1
            self.api('events.eraise')('aard_quest_failed',
                                      copy.deepcopy(self.queststuff))
        elif questi['action'] == 'status':
            self.api('events.eraise')('aard_quest_status', questi)
        elif questi['action'] == 'reset':
            #reset the timer to 60 seconds
            #when_required = os.time() + (stuff.timer * 60)
            #update_timer()
            self.api('events.eraise')('aard_quest_reset', {})
        self.queststuff.sync()

    def _savestate(self, _=None):
        """
    save states
    """
        self.queststuff.sync()
Example #37
0
class Plugin(BasePlugin):
  """
  a plugin for user actions
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.canreload = True

    self.regexlookup = {}
    self.actiongroups = {}
    self.compiledregex = {}
    self.sessionhits = {}

    self.saveactionsfile = os.path.join(self.savedir, 'actions.txt')
    self.actions = PersistentDict(self.saveactionsfile, 'c')

  def load(self):
    """
    load the plugin
    """
    BasePlugin.load(self)

    self.api('setting.add')('nextnum', 0, int,
                            'the number of the next action added',
                            readonly=True)

    parser = argp.ArgumentParser(add_help=False,
                                 description='add a action')
    parser.add_argument('regex',
                        help='the regex to match',
                        default='',
                        nargs='?')
    parser.add_argument('action',
                        help='the action to take',
                        default='',
                        nargs='?')
    parser.add_argument('send',
                        help='where to send the action',
                        default='execute',
                        nargs='?',
                        choices=self.api('api.getchildren')('send'))
    parser.add_argument('-c',
                        "--color",
                        help="match colors (@@colors)",
                        action="store_true")
    parser.add_argument('-d',
                        "--disable",
                        help="disable the action",
                        action="store_true")
    parser.add_argument('-g',
                        "--group",
                        help="the action group",
                        default="")
    parser.add_argument('-o',
                        "--overwrite",
                        help="overwrite an action if it already exists",
                        action="store_true")
    self.api('commands.add')('add',
                             self.cmd_add,
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description='list actions')
    parser.add_argument('match',
                        help='list only actions that have this argument in them',
                        default='',
                        nargs='?')
    self.api('commands.add')('list',
                             self.cmd_list,
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description='remove an action')
    parser.add_argument('action',
                        help='the action to remove',
                        default='',
                        nargs='?')
    self.api('commands.add')('remove',
                             self.cmd_remove,
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description='toggle enabled flag')
    parser.add_argument('action',
                        help='the action to toggle',
                        default='',
                        nargs='?')
    action = parser.add_mutually_exclusive_group()
    action.add_argument('-t', '--toggle', action='store_const',
                        dest='togact', const='toggle',
                        default='toggle', help='toggle the action')
    action.add_argument('-d', '--disable', action='store_const',
                        dest='togact', const='disable',
                        help='disable the action')
    action.add_argument('-e', '--enable', action='store_const',
                        dest='togact', const='enable',
                        help='enable the action')
    self.api('commands.add')('toggle',
                             self.cmd_toggle,
                             parser=parser)


    parser = argp.ArgumentParser(add_help=False,
                                 description='get detail for an action')
    parser.add_argument('action',
                        help='the action to get details for',
                        default='',
                        nargs='?')
    self.api('commands.add')('detail',
                             self.cmd_detail,
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description='toggle all actions in a group')
    parser.add_argument('group',
                        help='the group to toggle',
                        default='',
                        nargs='?')
    action = parser.add_mutually_exclusive_group()
    action.add_argument('-t', '--toggle', action='store_const',
                        dest='togact', const='toggle',
                        default='toggle', help='toggle the action')
    action.add_argument('-d', '--disable', action='store_const',
                        dest='togact', const='disable',
                        help='disable the action')
    action.add_argument('-e', '--enable', action='store_const',
                        dest='togact', const='enable',
                        help='enable the action')
    self.api('commands.add')('groupt',
                             self.cmd_grouptoggle,
                             parser=parser)

    for action in self.actions.values():
      self.register_action(action)

    self.api('events.register')('plugin_%s_savestate' % self.sname, self._savestate)

  def register_action(self, action):
    """
    register an action as a trigger
    """
    if 'triggername' not in action:
      action['triggername'] = "action_%s" % action['num']
    self.api('triggers.add')(action['triggername'],
                             action['regex'])
    self.api('events.register')('trigger_%s' % action['triggername'],
                                self.action_matched)

  def unregister_action(self, action):
    """
    unregister an action
    """
    self.api('events.unregister')('trigger_%s' % action['triggername'],
                                  self.action_matched)
    self.api('triggers.remove')(action['triggername'])

  def action_matched(self, args):
    """
    do something when an action is matched
    """
    actionnum = int(args['triggername'].split('_')[-1])
    action = self.lookup_action(actionnum)
    if action:
      akey = action['regex']
      if akey not in self.sessionhits:
        self.sessionhits[akey] = 0
      self.sessionhits[akey] = self.sessionhits[akey] + 1
      action['hits'] = action['hits'] + 1
      self.api('send.msg')('matched line: %s to action %s' % (args['line'],
                                                              akey))
      templ = Template(action['action'])
      newaction = templ.safe_substitute(args)
      sendtype = 'send.' + action['send']
      self.api('send.msg')('sent %s to %s' % (newaction, sendtype))
      self.api(sendtype)(newaction)
    else:
      self.api('send.error')("Bug: could not find action for trigger %s" % \
                              args['triggername'])

  def lookup_action(self, action):
    """
    lookup an action by number or name
    """
    nitem = None
    try:
      num = int(action)
      nitem = None
      for titem in self.actions.keys():
        if num == self.actions[titem]['num']:
          nitem = self.actions[titem]
          break

    except ValueError:
      if action in self.actions:
        nitem = action

    return nitem

  def cmd_add(self, args):
    """
    add user defined actions
    """
    if not args['regex']:
      return False, ['Please include a regex']
    if not args['action']:
      return False, ['Please include an action']

    if not args['overwrite'] and args['regex'] in self.actions:
      return True, ['Action: %s already exists.' % args['regex']]
    else:
      num = 0

      if args['regex'] in self.actions:
        num = self.actions[args['regex']]['num']
      else:
        num = self.api('setting.gets')('nextnum')
        self.api('setting.change')('nextnum', num + 1)

      self.actions[args['regex']] = {
          'num':num,
          'hits':0,
          'regex': args['regex'],
          'action':args['action'],
          'send':args['send'],
          'matchcolor':args['color'],
          'enabled':not args['disable'],
          'group':args['group'],
          'triggername':"action_%s" % num
      }
      self.actions.sync()

      self.register_action(self.actions[args['regex']])

      return True, ['added action %s - regex: %s' % (num, args['regex'])]

    return False, ['You should never see this']

  def cmd_remove(self, args):
    """
    @G%(name)s@w - @B%(cmdname)s@w
      Remove an action
      @CUsage@w: rem @Y<originalstring>@w
        @Yoriginalstring@w    = The original string
    """
    tmsg = []
    if args['action']:
      retval = self.removeaction(args['action'])
      if retval:
        tmsg.append("@GRemoving action@w : '%s'" % (retval))
      else:
        tmsg.append("@GCould not remove action@w : '%s'" % (args['action']))

      return True, tmsg
    else:
      return False, ['@RPlease include an action to remove@w']

  def cmd_list(self, args):
    """
    @G%(name)s@w - @B%(cmdname)s@w
      List actiones
      @CUsage@w: list
    """
    tmsg = self.listactions(args['match'])
    return True, tmsg

  def cmd_toggle(self, args):
    """
    toggle the enabled flag
    """
    tmsg = []

    if args['togact'] == 'disable':
      state = False
    elif args['togact'] == 'enable':
      state = True
    else:
      state = "toggle"
    if args['action']:
      action = self.toggleaction(args['action'], flag=state)
      if action:
        if action['enabled']:
          tmsg.append("@GEnabled action@w : '%s'" % (action['num']))
        else:
          tmsg.append("@GDisabled action@w : '%s'" % (action['num']))
      else:
        tmsg.append("@GDoes not exist@w : '%s'" % (args['action']))
      return True, tmsg

    else:
      return False, ['@RPlease include an action to toggle@w']

  def cmd_grouptoggle(self, args):
    """
    toggle all actions in a group
    """
    tmsg = []
    togglea = []
    if args['togact'] == 'disable':
      state = False
    elif args['togact'] == 'enable':
      state = True
    else:
      state = "toggle"
    if args['group']:
      for i in self.actions:
        if self.actions[i]['group'] == args['group']:
          self.toggleaction(self.actions[i]['num'], flag=state)
          togglea.append('%s' % self.actions[i]['num'])

      if togglea:
        tmsg.append('The following actions were %s: %s' % \
              ('enabled' if state else 'disabled',
               ','.join(togglea)))
      else:
        tmsg.append('No actions were modified')

      return True, tmsg
    else:
      return False, ['@RPlease include a group to toggle@w']

  def cmd_detail(self, args):
    """
    @G%(name)s@w - @B%(cmdname)s@w
      get details of an action
      @CUsage@w: detail 1
        @Yaction@w    = the action to get details, either the number or regex
    """
    tmsg = []
    if args['action']:
      action = self.lookup_action(args['action'])
      if action:
        if 'hits' not in action:
          action['hits'] = 0
        if action['regex'] not in self.sessionhits:
          self.sessionhits[action['regex']] = 0
        tmsg.append('%-12s : %d' % ('Num', action['num']))
        tmsg.append('%-12s : %s' % \
            ('Enabled', 'Y' if action['enabled'] else 'N'))
        tmsg.append('%-12s : %d' % ('Total Hits',
                                    action['hits']))
        tmsg.append('%-12s : %d' % ('Session Hits',
                                    self.sessionhits[action['regex']]))
        tmsg.append('%-12s : %s' % ('Regex', action['regex']))
        tmsg.append('%-12s : %s' % ('Action', action['action']))
        tmsg.append('%-12s : %s' % ('Group', action['group']))
        tmsg.append('%-12s : %s' % ('Match Color',
                                    action['matchcolor']))
        tmsg.append('%-12s : %s' % ('Trigger Name',
                                    action['triggername']))
      else:
        return True, ['@RAction does not exist@w : \'%s\'' % (args['action'])]

      return True, tmsg
    else:
      return False, ['@RPlease include all arguments@w']

  def listactions(self, match):
    """
    return a table of strings that list actions
    """
    tmsg = []
    for action in sorted(self.actions.keys()):
      item = self.actions[action]
      if not match or match in item:
        regex = self.api('colors.stripansi')(item['regex'])
        if len(regex) > 30:
          regex = regex[:27] + '...'
        action = self.api('colors.stripansi')(item['action'])
        if len(action) > 30:
          action = action[:27] + '...'
        tmsg.append("%4s %2s  %-10s %-32s : %s@w" % \
                     (item['num'],
                      'Y' if item['enabled'] else 'N',
                      item['group'],
                      regex,
                      action))
    if not tmsg:
      tmsg = ['None']
    else:
      tmsg.insert(0, "%4s %2s  %-10s %-32s : %s@w" % ('#', 'E', 'Group',
                                                      'Regex', 'Action'))
      tmsg.insert(1, '@B' + '-' * 60 + '@w')

    return tmsg

  def removeaction(self, item):
    """
    internally remove a action
    """
    action = self.lookup_action(item)

    if action and action['regex'] in self.actions:
      self.unregister_action(action)
      del self.actions[action['regex']]
      self.actions.sync()

    return action

  def toggleaction(self, item, flag="toggle"):
    """
    toggle an action
    """
    action = self.lookup_action(item)
    if action:
      if flag == "toggle":
        action['enabled'] = not action['enabled']
      else:
        action['enabled'] = bool(flag)
      if action['enabled']:
        self.register_action(action)
      else:
        self.unregister_action(action)

    return action

  def clearactions(self):
    """
    clear all actiones
    """
    for action in self.actions.values():
      self.unregister_action(action)

    self.actions.clear()
    self.actions.sync()

  def reset(self):
    """
    reset the plugin
    """
    BasePlugin.reset(self)
    self.clearactions()

  def _savestate(self, _=None):
    """
    save states
    """
    self.actions.sync()
Example #38
0
class Plugin(BasePlugin):
  """
  a plugin to handle global variables, if something goes through
   send.execute (this includes from the client), a variable
   can be specified with $varname and will be substituted.
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.variablefile = os.path.join(self.savedir, 'variables.txt')
    self._variables = PersistentDict(self.variablefile, 'c')
    self.api('api.add')('getv', self.api_getv)
    self.api('api.add')('setv', self.api_setv)
    self.api('api.add')('replace', self.api_replace)

  def load(self):
    """
    load the plugin
    """
    BasePlugin.load(self)

    parser = argp.ArgumentParser(add_help=False,
                                 description='add a variable')
    parser.add_argument('name',
                        help='the name of the variable',
                        default='',
                        nargs='?')
    parser.add_argument('value',
                        help='the value of the variable',
                        default='',
                        nargs='?')
    self.api('commands.add')('add',
                             self.cmd_add,
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description='remove a variable')
    parser.add_argument('name',
                        help='the variable to remove',
                        default='',
                        nargs='?')
    self.api('commands.add')('remove',
                             self.cmd_remove,
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description='list variables')
    parser.add_argument('match',
                        help='list only variables that have this argument in their name',
                        default='',
                        nargs='?')
    self.api('commands.add')('list',
                             self.cmd_list,
                             parser=parser)

    self.api('commands.default')('list')

    self.api('events.register')('io_execute_event',
                                self.checkline,
                                prio=99)
    self.api('events.register')('io_execute_event',
                                self.checkline,
                                prio=1)
    self.api('events.register')('plugin_%s_savestate' % self.sname, self._savestate)

  # get a variable
  def api_getv(self, varname):
    """  get the variable with a specified name
    @Yvarname@w  = the variable to get

    this function returns the value of variable with the name of the argument
    """
    if varname in self._variables:
      return self._variables[varname]

    return None

  # set a variable
  def api_setv(self, varname, value):
    """  set the variable with a specified name to the specified value
    @Yvarname@w  = the variable to set
    @Yvalue@w  = the value to set

    this function returns True if the value was set, False if an error was
    encountered
    """
    try:
      self._variables[varname] = value
      return True
    except Exception: # pylint: disable=broad-except
      return False

  # replace variables in data
  def api_replace(self, data):
    """replace the variables in data
    @Ydata@w  = the variable to get

    this function returns the data after variable substition
    """
    templ = Template(data)
    return templ.safe_substitute(self._variables)

  def checkline(self, args):
    """
    this function checks for variables in input
    """
    data = args['fromdata'].strip()

    datan = self.api('vars.replace')(data)

    if datan != data:
      if 'trace' in args:
        args['trace']['changes'].append({'flag':'Modify',
                                         'data':'changed "%s" to "%s"' % (data, datan),
                                         'plugin':self.sname})

      self.api('send.msg')('replacing "%s" with "%s"' % (data.strip(),
                                                         datan.strip()))
      args['fromdata'] = datan
      args['beforevar'] = data

    return args

  def cmd_add(self, args):
    """
    command to add a variable
    """
    tmsg = []
    if args['name'] and args['value']:
      tmsg.append("@GAdding variable@w : '%s' will be replaced by '%s'" % \
                                              (args['name'], args['value']))
      self.addvariable(args['name'], args['value'])
      return True, tmsg

    tmsg.append("@RPlease include all arguments@w")
    return False, tmsg

  def cmd_remove(self, args):
    """
    command to remove a variable
    """
    tmsg = []
    if args['name']:
      tmsg.append("@GRemoving variable@w : '%s'" % (args['name']))
      self.removevariable(args['name'])
      return True, tmsg

    return False, ['@RPlease specifiy a variable to remove@w']

  def cmd_list(self, args):
    """
    command to list variables
    """
    tmsg = self.listvariables(args['match'])
    return True, tmsg

  def addvariable(self, item, value):
    """
    internally add a variable
    """
    self._variables[item] = value
    self._variables.sync()

  def removevariable(self, item):
    """
    internally remove a variable
    """
    if item in self._variables:
      del self._variables[item]
      self._variables.sync()

  def listvariables(self, match):
    """
    return a table of variables
    """
    tmsg = []
    for item in self._variables:
      if not match or match in item:
        tmsg.append("%-20s : %s@w" % (item, self._variables[item]))
    if not tmsg:
      tmsg = ['None']
    return tmsg

  def clearvariables(self):
    """
    clear all variables
    """
    self._variables.clear()
    self._variables.sync()

  def reset(self):
    """
    reset the plugin
    """
    BasePlugin.reset(self)
    self.clearvariables()

  def _savestate(self, _=None):
    """
    save states
    """
    self._variables.sync()
Example #39
0
class Plugin(AardwolfBasePlugin):
    """
  a plugin to handle aardwolf cp events
  """
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        AardwolfBasePlugin.__init__(self, *args, **kwargs)
        self.savewhoisfile = os.path.join(self.savedir, 'whois.txt')
        self.whois = PersistentDict(self.savewhoisfile, 'c')

    def load(self):
        """
    load the plugins
    """
        AardwolfBasePlugin.load(self)

        self.api('watch.add')('whois', '^(whoi|whois)$')

        self.api('triggers.add')('whoisheader',
                                 r"^\[.*\]\s+.*\s*\((?P<sex>\w+)\s+\w+\)$",
                                 enabled=False,
                                 group='whois')
        self.api('triggers.add')('whoisclasses',
                                 r"^\[Multiclass Player: (?P<classes>.*) \]$",
                                 enabled=False,
                                 group='whois')
        self.api('triggers.add')(
            'whois1',
            r"^(?P<name1>[\w\s]*)\s*:\s*\[\s*(?P<val1>[\w\d\s]*)\s*\]\s*$",
            enabled=False,
            group='whois')
        self.api('triggers.add')(
            'whois2',
            r"^(?P<name1>[\w\s]*)\s*:\s*\[\s*(?P<val1>[\w\d\s]*)\s*\]" \
              r"\s*(?P<name2>[\w\s]*)\s*:\s*\[\s*(?P<val2>[\w\d\s]*)\s*\]\s*$",
            enabled=False,
            group='whois')
        self.api('triggers.add')(
            'whois3',
            r"^(?P<name1>[\w\s]*)\s*:\s*\[\s*(?P<val1>[\w\d\s]*)\s*\]" \
              r"\s*(?P<name2>[\w\s]*)\s*:\s*\[\s*(?P<val2>[\w\d\s]*)\s*\]" \
              r"\s*(?P<name3>[\w\s]*)\s*:\s*\[\s*(?P<val3>[\w\d\s]*)\s*\]\s*$",
            enabled=False,
            group='whois')
        self.api('triggers.add')(
            'whoispowerup',
            r"^(?P<name1>[\w\s]*)\s*:\s*\[\s*(?P<val1>[\w\d\s]*)\s*\]" \
              r"\s*([\w\s]*)\s*:\s*\[\s*(?P<pval1>[\w\d\s]*)\s*\]\s*\[\s*" \
              r"(?P<pval2>[\w\d\s]*)\s*\]\s*$",
            enabled=False,
            group='whois')
        self.api('triggers.add')('whoisend', r"^-{74,74}$", enabled=False)

        self.api('events.register')('watch_whois', self._whois)
        self.api('events.register')('trigger_whoisheader', self._whoisheader)
        self.api('events.register')('trigger_whoisclasses', self._whoisclasses)
        self.api('events.register')('trigger_whois1', self._whoisstats)
        self.api('events.register')('trigger_whois2', self._whoisstats)
        self.api('events.register')('trigger_whois3', self._whoisstats)
        self.api('events.register')('trigger_whoispowerup', self._whoisstats)
        self.api('events.register')('trigger_whoisend', self._whoisend)
        self.api('events.register')('plugin_%s_savestate' % self.sname,
                                    self._savestate)

    def _whois(self, args=None):
        """
    reset the whois info when a "whois" command is sent
    """
        self.whois.clear()
        self.api('triggers.togglegroup')('whois', True)
        return args

    def _whoisstats(self, args=None):
        """
    parse a whois line
    """
        for i in range(1, 4):
            akey = 'name%s' % i
            aval = 'val%s' % i

            if akey in args:
                kname = args[akey].lower().strip()
                kname = kname.replace(' ', '')
                kval = args[aval].strip()

                self.whois[kname] = kval

        if 'pval1' in args:
            self.whois['powerupsall'] = args['pval1']
        if 'pval2' in args:
            self.whois['powerupsmort'] = args['pval2']

    def _whoisheader(self, args=None):
        """
    do stuff when we see the whois header
    """
        self.whois["name"] = self.api('GMCP.getv')('char.base.name')
        self.whois['level'] = self.api('GMCP.getv')('char.status.level')
        self.whois['tiers'] = self.api('GMCP.getv')('char.base.tier')
        self.whois['redos'] = int(self.api('GMCP.getv')('char.base.redos'))
        self.whois['race'] = self.api('GMCP.getv')('char.base.race').lower()
        self.whois['sex'] = args['sex'].lower()
        self.whois['subclass'] = self.api('GMCP.getv')(
            'char.base.subclass').lower()
        self.whois['powerupsall'] = 0
        self.whois['powerupsmort'] = 0
        self.whois['remorts'] = self.api('GMCP.getv')('char.base.remorts')
        if self.whois['remorts'] == 1:
            classabs = self.api('aardu.classabb')()
            self.whois['classes'] = []
            self.whois['classes'].append({
                'remort':
                1,
                'class':
                classabs[self.api('GMCP.getv')('char.base.class').lower()]
            })

        self.api('triggers.toggle')('whoisend', True)

    def _whoisclasses(self, args):
        """
    add classes
    """
        classabs = self.api('aardu.classabb')()
        tlist = args['classes'].split("/")
        remorts = len(tlist)
        self.whois['classes'] = []
        for i in range(remorts):
            tclass = tlist[i].strip().lower()
            self.whois['classes'].append({
                'remort': i + 1,
                'class': classabs[tclass.lower()]
            })

        self.whois['remorts'] = remorts

    def _whoisend(self, _=None):
        """
    send a whois
    """
        self.whois['totallevels'] = self.api('aardu.getactuallevel')(
            self.whois['level'], self.whois['remorts'], self.whois['tiers'],
            self.whois['redos'])
        self.whois.sync()
        self.api('triggers.togglegroup')('whois', False)
        self.api('triggers.toggle')('whoisend', False)
        self.api('events.eraise')('aard_whois', copy.deepcopy(self.whois))
        self.api('send.msg')('whois: %s' % self.whois)

    def _savestate(self, _=None):
        """
    save states
    """
        self.whois.sync()
Example #40
0
class Plugin(AardwolfBasePlugin):
  """
  a plugin to handle aardwolf cp events
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    AardwolfBasePlugin.__init__(self, *args, **kwargs)
    self.savewhoisfile = os.path.join(self.savedir, 'whois.txt')
    self.whois = PersistentDict(self.savewhoisfile, 'c')

  def load(self):
    """
    load the plugins
    """
    AardwolfBasePlugin.load(self)

    self.api.get('watch.add')('whois', '^(whoi|whois)$')

    self.api.get('triggers.add')('whoisheader',
      "^\[.*\]\s+.*\s*\((?P<sex>\w+)\s+\w+\)$",
      enabled=False,
      group='whois')
    self.api.get('triggers.add')('whoisclasses',
      "^\[Multiclass Player: (?P<classes>.*) \]$",
      enabled=False,
      group='whois')
    self.api.get('triggers.add')('whois1',
      "^(?P<name1>[\w\s]*)\s*:\s*\[\s*(?P<val1>[\w\d\s]*)\s*\]\s*$",
      enabled=False,
      group='whois')
    self.api.get('triggers.add')('whois2',
      "^(?P<name1>[\w\s]*)\s*:\s*\[\s*(?P<val1>[\w\d\s]*)\s*\]" \
        "\s*(?P<name2>[\w\s]*)\s*:\s*\[\s*(?P<val2>[\w\d\s]*)\s*\]\s*$",
      enabled=False,
      group='whois')
    self.api.get('triggers.add')('whois3',
      "^(?P<name1>[\w\s]*)\s*:\s*\[\s*(?P<val1>[\w\d\s]*)\s*\]" \
        "\s*(?P<name2>[\w\s]*)\s*:\s*\[\s*(?P<val2>[\w\d\s]*)\s*\]" \
        "\s*(?P<name3>[\w\s]*)\s*:\s*\[\s*(?P<val3>[\w\d\s]*)\s*\]\s*$",
      enabled=False,
      group='whois')
    self.api.get('triggers.add')('whoispowerup',
      "^(?P<name1>[\w\s]*)\s*:\s*\[\s*(?P<val1>[\w\d\s]*)\s*\]" \
        "\s*([\w\s]*)\s*:\s*\[\s*(?P<pval1>[\w\d\s]*)\s*\]\s*\[\s*" \
        "(?P<pval2>[\w\d\s]*)\s*\]\s*$",
      enabled=False,
      group='whois')
    self.api.get('triggers.add')('whoisend',
      "^-{74,74}$",
      enabled=False)

    self.api.get('events.register')('watch_whois', self._whois)
    self.api.get('events.register')('trigger_whoisheader', self._whoisheader)
    self.api.get('events.register')('trigger_whoisclasses', self._whoisclasses)
    self.api.get('events.register')('trigger_whois1', self._whoisstats)
    self.api.get('events.register')('trigger_whois2', self._whoisstats)
    self.api.get('events.register')('trigger_whois3', self._whoisstats)
    self.api.get('events.register')('trigger_whoispowerup', self._whoisstats)
    self.api.get('events.register')('trigger_whoisend', self._whoisend)

  def _whois(self, args=None):
    """
    reset the whois info when a "whois" command is sent
    """
    self.whois.clear()
    self.api.get('triggers.togglegroup')('whois', True)
    return args

  def _whoisstats(self, args=None):
    """
    parse a whois line
    """
    for i in range(1, 4):
      akey = 'name%s' % i
      aval = 'val%s' % i

      if akey in args:
        kname = args[akey].lower().strip()
        kname = kname.replace(' ', '')
        kval = args[aval].strip()

        self.whois[kname] = kval

    if 'pval1' in args:
      self.whois['powerupsall'] = args['pval1']
    if 'pval2' in args:
      self.whois['powerupsmort'] = args['pval2']

  def _whoisheader(self, args=None):
    """
    do stuff when we see the whois header
    """
    self.whois["name"] = self.api.get('GMCP.getv')('char.base.name')
    self.whois['level'] = self.api.get('GMCP.getv')('char.status.level')
    self.whois['tiers'] = self.api.get('GMCP.getv')('char.base.tier')
    self.whois['redos'] = int(self.api.get('GMCP.getv')('char.base.redos'))
    self.whois['race'] = self.api.get('GMCP.getv')('char.base.race').lower()
    self.whois['sex'] = args['sex'].lower()
    self.whois['subclass'] = self.api.get('GMCP.getv')(
                                            'char.base.subclass').lower()
    self.whois['powerupsall'] = 0
    self.whois['powerupsmort'] = 0
    self.whois['remorts'] = self.api.get('GMCP.getv')('char.base.remorts')
    if self.whois['remorts'] == 1:
      classabs = self.api.get('aardu.classabb')()
      self.whois['classes'] = []
      self.whois['classes'].append({'remort':1,
              'class':classabs[self.api.get('GMCP.getv')(
                                      'char.base.class').lower()]})

    self.api.get('triggers.toggle')('whoisend', True)

  def _whoisclasses(self, args):
    """
    add classes
    """
    classabs = self.api.get('aardu.classabb')()
    tlist = args['classes'].split("/")
    remorts = len(tlist)
    self.whois['classes'] = []
    for i in range(remorts):
      tclass = tlist[i].strip().lower()
      self.whois['classes'].append({'remort':i + 1,
                'class':classabs[tclass.lower()]})

    self.whois['remorts'] = remorts

  def _whoisend(self, _=None):
    """
    send a whois
    """
    self.whois['totallevels'] = self.api.get('aardu.getactuallevel')(
                      self.whois['level'], self.whois['remorts'],
                      self.whois['tiers'], self.whois['redos'])
    self.whois.sync()
    self.api.get('triggers.togglegroup')('whois', False)
    self.api.get('triggers.toggle')('whoisend', False)
    self.api.get('events.eraise')('aard_whois', copy.deepcopy(self.whois))
    self.api.get('send.msg')('whois: %s' % self.whois)

  def savestate(self):
    """
    save states
    """
    AardwolfBasePlugin.savestate(self)
    self.whois.sync()
Example #41
0
class Plugin(AardwolfBasePlugin):
    """
  a plugin to handle aardwolf cp events
  """
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        AardwolfBasePlugin.__init__(self, *args, **kwargs)
        self.savelevelfile = os.path.join(self.savedir, 'level.txt')
        self.levelinfo = PersistentDict(self.savelevelfile, 'c')

    def load(self):
        """
    load the plugins
    """
        AardwolfBasePlugin.load(self)

        self.api.get('setting.add')('preremort', False, bool,
                                    'flag for pre remort')
        self.api.get('setting.add')('remortcomp', False, bool,
                                    'flag for remort completion')
        self.api.get('setting.add')('tiering', False, bool, 'flag for tiering')
        self.api.get('setting.add')('seen2', False, bool,
                                    'we saw a state 2 after tiering')

        self.api.get('watch.add')('shloud', '^superhero loud$')
        self.api.get('watch.add')('shsilent', '^superhero silent$')
        self.api.get('watch.add')('shconfirm', '^superhero confirm$')
        self.api.get('watch.add')('shloudconfirm', '^superhero loud confirm$')

        self.api.get('triggers.add')(
            'lvlpup',
            "^Congratulations, hero. You have increased your powers!$")
        self.api.get('triggers.add')('lvlpupbless', "^You gain a powerup\.$")
        self.api.get('triggers.add')(
            'lvllevel',
            "^You raise a level! You are now level (?P<level>\d*).$",
            argtypes={
                'level': int
            })
        self.api.get('triggers.add')(
            'lvlsh',
            "^Congratulations! You are now a superhero!$",
            argtypes={
                'level': int
            })
        self.api.get('triggers.add')(
            'lvlbless',
            "^You gain a level - you are now level (?P<level>\d*).$",
            argtypes={
                'level': int
            })
        self.api.get('triggers.add')('lvlgains',
            "^You gain (?P<hp>\d*) hit points, (?P<mp>\d*) mana, "\
              "(?P<mv>\d*) moves, (?P<pr>\d*) practices and (?P<tr>\d*) trains.$",
            enabled=False, group='linfo',
            argtypes={'hp':int, 'mn':int, 'mv':int, 'pr':int, 'tr':int})
        self.api.get('triggers.add')(
            'lvlblesstrain',
            "^You gain (?P<tr>\d*) extra trains? daily blessing bonus.$",
            enabled=False,
            group='linfo',
            argtypes={
                'tr': int
            })
        self.api.get('triggers.add')('lvlpupgains',
                                     "^You gain (?P<tr>\d*) trains.$",
                                     enabled=False,
                                     group='linfo',
                                     argtypes={
                                         'tr': int
                                     })
        self.api.get('triggers.add')(
            'lvlbonustrains',
            "^Lucky! You gain an extra (?P<tr>\d*) training sessions?!$",
            enabled=False,
            group='linfo',
            argtypes={
                'tr': int
            })
        self.api.get('triggers.add')('lvlbonusstat',
                                     "^You gain a bonus (?P<stat>.*) point!$",
                                     enabled=False,
                                     group='linfo')

        self.api.get('triggers.add')('lvlshbadstar',
            "^%s$" % re.escape("*******************************" \
                  "****************************************"),
            enabled=False, group='superhero')
        self.api.get('triggers.add')('lvlshbad',
            "^Use either: 'superhero loud'   - (?P<mins>.*) mins of " \
              "double xp, (?P<qp>.*)qp and (?P<gold>.*) gold$",
            enabled=False, group='superhero')
        self.api.get('triggers.add')(
            'lvlshnogold',
            "^You must be carrying at least 500,000 gold coins.$",
            enabled=False,
            group='superhero')
        self.api.get('triggers.add')(
            'lvlshnoqp',
            "^You must have at least 1000 quest points.$",
            enabled=False,
            group='superhero')

        self.api.get('triggers.add')('lvlpreremort',
                                     "^You are now flagged as remorting.$",
                                     enabled=True,
                                     group='remort')
        self.api.get('triggers.add')('lvlremortcomp',
                                     "^\* Remort transformation complete!$",
                                     enabled=True,
                                     group='remort')
        self.api.get('triggers.add')(
            'lvltier',
            "^## You have already remorted the max number of times.$",
            enabled=True,
            group='remort')

        self.api.get('events.register')('trigger_lvlpup', self._lvl)
        self.api.get('events.register')('trigger_lvlpupbless', self._lvl)
        self.api.get('events.register')('trigger_lvllevel', self._lvl)
        self.api.get('events.register')('trigger_lvlbless', self._lvl)
        self.api.get('events.register')('trigger_lvlgains', self._lvlgains)
        self.api.get('events.register')('trigger_lvlpupgains', self._lvlgains)
        self.api.get('events.register')('trigger_lvlblesstrain',
                                        self._lvlblesstrains)
        self.api.get('events.register')('trigger_lvlbonustrains',
                                        self._lvlbonustrains)
        self.api.get('events.register')('trigger_lvlbonusstat',
                                        self._lvlbonusstat)

        self.api.get('events.register')('trigger_lvlshbadstar',
                                        self._superherobad)
        self.api.get('events.register')('trigger_lvlshbad', self._superherobad)
        self.api.get('events.register')('trigger_lvlshnogold',
                                        self._superherobad)
        self.api.get('events.register')('trigger_lvlshnoqp',
                                        self._superherobad)

        self.api.get('events.register')('watch_shloud', self.cmd_superhero)
        self.api.get('events.register')('watch_shsilent', self.cmd_superhero)
        self.api.get('events.register')('watch_shconfirm', self.cmd_superhero)
        self.api.get('events.register')('watch_shloudconfirm',
                                        self.cmd_superhero)

        self.api.get('events.register')('trigger_lvlpreremort',
                                        self._preremort)
        self.api.get('events.register')('trigger_lvlremortcomp',
                                        self._remortcomp)
        self.api.get('events.register')('trigger_lvltier', self._tier)

    def _gmcpstatus(self, _=None):
        """
    check gmcp status when tiering
    """
        state = self.api.get('GMCP.getv')('char.status.state')
        if state == 2:
            self.api.get('ouput.client')('seen2')
            self.api.get('setting.change')('seen2', True)
            self.api.get('events.unregister')('GMCP:char.status',
                                              self._gmcpstatus)
            self.api.get('events.register')('GMCP:char.base', self._gmcpbase)

    def _gmcpbase(self, _=None):
        """
    look for a new base when we remort
    """
        self.api.get('send.client')('called char.base')
        state = self.api.get('GMCP.getv')('char.status.state')
        tiering = self.api.get('setting.gets')('tiering')
        seen2 = self.api.get('setting.gets')('seen2')
        if tiering and seen2 and state == 3:
            self.api.get('send.client')('in char.base')
            self.api.get('events.unregister')('GMCP:char.base',
                                              self._gmcpstatus)
            self._lvl({'level': 1})

    def _tier(self, _=None):
        """
    about to tier
    """
        self.api.get('setting.change')('tiering', True)
        self.api.get('send.client')('tiering')
        self.api.get('events.register')('GMCP:char.status', self._gmcpstatus)

    def _remortcomp(self, _=None):
        """
    do stuff when a remort is complete
    """
        self.api.get('setting.change')('preremort', False)
        self.api.get('setting.change')('remortcomp', True)
        self._lvl({'level': 1})

    def _preremort(self, _=None):
        """
    set the preremort flag
    """
        self.api.get('setting.change')('preremort', True)
        self.api.get('events.eraise')('aard_level_preremort', {})

    def cmd_superhero(self, _=None):
        """
    figure out what is done when superhero is typed
    """
        self.api.get('send.client')('superhero was typed')
        self.api.get('triggers.togglegroup')('superhero', True)
        self._lvl({'level': 201})

    def _superherobad(self, _=None):
        """
    undo things that we typed if we didn't really superhero
    """
        self.api.get('send.client')('didn\'t sh though')
        self.api.get('triggers.togglegroup')('superhero', False)
        self.api.get('triggers.togglegroup')('linfo', False)
        self.api.get('events.unregister')('trigger_emptyline', self._finish)

    def resetlevel(self):
        """
    reset the level info, use the finishtime of the last level as
    the starttime of the next level
    """
        if 'finishtime' in self.levelinfo and self.levelinfo['finishtime'] > 0:
            starttime = self.levelinfo['finishtime']
        else:
            starttime = time.time()
        self.levelinfo.clear()
        self.levelinfo['type'] = ""
        self.levelinfo['level'] = -1
        self.levelinfo['str'] = 0
        self.levelinfo['int'] = 0
        self.levelinfo['wis'] = 0
        self.levelinfo['dex'] = 0
        self.levelinfo['con'] = 0
        self.levelinfo['luc'] = 0
        self.levelinfo['starttime'] = starttime
        self.levelinfo['hp'] = 0
        self.levelinfo['mp'] = 0
        self.levelinfo['mv'] = 0
        self.levelinfo['pracs'] = 0
        self.levelinfo['trains'] = 0
        self.levelinfo['bonustrains'] = 0
        self.levelinfo['blessingtrains'] = 0
        self.levelinfo['totallevels'] = 0

    def _lvl(self, args=None):
        """
    trigger for leveling
    """
        if not args:
            return

        self.resetlevel()
        if 'triggername' in args and (args['triggername'] == 'lvlpup' \
            or args['triggername'] == 'lvlpupbless'):
            self.levelinfo['level'] = self.api.get('GMCP.getv')(
                'char.status.level')
            self.levelinfo['totallevels'] = self.api.get(
                'aardu.getactuallevel')()
            self.levelinfo['type'] = 'pup'
        else:
            self.levelinfo['level'] = args['level']
            self.levelinfo['totallevels'] = self.api.get(
                'aardu.getactuallevel')(args['level'])
            self.levelinfo['type'] = 'level'

        self.api.get('triggers.togglegroup')('linfo', True)
        self.api.get('events.register')('trigger_emptyline', self._finish)

    def _lvlblesstrains(self, args):
        """
    trigger for blessing trains
    """
        self.levelinfo['blessingtrains'] = args['tr']

    def _lvlbonustrains(self, args):
        """
    trigger for bonus trains
    """
        self.levelinfo['bonustrains'] = args['tr']

    def _lvlbonusstat(self, args):
        """
    trigger for bonus stats
    """
        self.levelinfo[args['stat'][:3].lower()] = 1

    def _lvlgains(self, args):
        """
    trigger for level gains
    """
        self.levelinfo['trains'] = args['tr']

        if args['triggername'] == "lvlgains":
            self.levelinfo['hp'] = args['hp']
            self.levelinfo['mp'] = args['mp']
            self.levelinfo['mv'] = args['mv']
            self.levelinfo['pracs'] = args['pr']

    def _finish(self, _):
        """
    finish up and raise the level event
    """
        remortcomp = self.api.get('setting.gets')('remortcomp')
        tiering = self.api.get('setting.gets')('tiering')
        if self.levelinfo['trains'] == 0 and not remortcomp or tiering:
            return
        self.levelinfo['finishtime'] = time.time()
        self.levelinfo.sync()
        self.api.get('triggers.togglegroup')('linfo', False)
        self.api.get('events.unregister')('trigger_emptyline', self._finish)
        self.api.get('events.eraise')('aard_level_gain',
                                      copy.deepcopy(self.levelinfo))
        if self.levelinfo['level'] == 200 and self.levelinfo['type'] == 'level':
            self.api.get('send.msg')('raising hero event', 'level')
            self.api.get('events.eraise')('aard_level_hero', {})
        elif self.levelinfo['level'] == 201 and self.levelinfo[
                'type'] == 'level':
            self.api.get('send.msg')('raising superhero event', 'level')
            self.api.get('events.eraise')('aard_level_superhero', {})
        elif self.levelinfo['level'] == 1:
            if self.api.get('setting.gets')('tiering'):
                self.api.get('send.msg')('raising tier event', 'level')
                self.api.get('setting.change')('tiering', False)
                self.api.get('setting.change')('seen2', False)
                self.api.get('events.eraise')('aard_level_tier', {})
            else:
                self.api.get('send.msg')('raising remort event', 'level')
                self.api.get('setting.change')('remortcomp', False)
                self.api.get('events.eraise')('aard_level_remort', {})

    def savestate(self):
        """
    save states
    """
        AardwolfBasePlugin.savestate(self)
        self.levelinfo.sync()
Example #42
0
class Plugin(AardwolfBasePlugin):
  """
  a plugin to handle aardwolf cp events
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    AardwolfBasePlugin.__init__(self, *args, **kwargs)
    self.savelevelfile = os.path.join(self.savedir, 'level.txt')
    self.levelinfo = PersistentDict(self.savelevelfile, 'c')

  def load(self): # pylint: disable=too-many-statements
    """
    load the plugins
    """
    AardwolfBasePlugin.load(self)

    self.api('setting.add')('preremort', False, bool,
                            'flag for pre remort')
    self.api('setting.add')('remortcomp', False, bool,
                            'flag for remort completion')
    self.api('setting.add')('tiering', False, bool, 'flag for tiering')
    self.api('setting.add')('seen2', False, bool,
                            'we saw a state 2 after tiering')

    self.api('watch.add')('shloud', '^superhero loud$')
    self.api('watch.add')('shsilent', '^superhero silent$')
    self.api('watch.add')('shconfirm', '^superhero confirm$')
    self.api('watch.add')('shloudconfirm', '^superhero loud confirm$')

    self.api('triggers.add')('lvlpup',
                             r"^Congratulations, hero. You have increased your powers!$")
    self.api('triggers.add')('lvlpupbless',
                             r"^You gain a powerup\.$")
    self.api('triggers.add')('lvllevel',
                             r"^You raise a level! You are now level (?P<level>\d*).$",
                             argtypes={'level':int})
    self.api('triggers.add')('lvlshloud',
                             r"^Congratulations! You are now a superhero!" \
                             r" You receive (?P<trains>) trains for superhero loud.$",
                             argtypes={'trains':int})
    self.api('triggers.add')('lvlsh',
                             r"^Congratulations! You are now a superhero!")
    self.api('triggers.add')('lvlbless',
                             r"^You gain a level - you are now level (?P<level>\d*).$",
                             argtypes={'level':int})
    self.api('triggers.add')('lvlgains',
                             r"^You gain (?P<hp>\d*) hit points, (?P<mp>\d*) mana, "\
                               r"(?P<mv>\d*) moves, (?P<pr>\d*) practices and " \
                               r"(?P<tr>\d*) trains.$",
                             enabled=False, group='linfo',
                             argtypes={'hp':int, 'mn':int, 'mv':int, 'pr':int, 'tr':int})
    self.api('triggers.add')('lvlblesstrain',
                             r"^You gain (?P<tr>\d*) extra trains? " \
                               r"daily blessing bonus.$",
                             enabled=False, group='linfo',
                             argtypes={'tr':int})
    self.api('triggers.add')('lvlpupgains',
                             r"^You gain (?P<tr>\d*) trains.$",
                             enabled=False, group='linfo',
                             argtypes={'tr':int})
    self.api('triggers.add')('lvlbattlelearntrains',
                             r"^You gain (?P<tr>\d*) additional training sessions? " \
                               r"from your enhanced battle learning.$",
                             enabled=False, group='linfo',
                             argtypes={'tr':int})
    self.api('triggers.add')('lvlbonustrains',
                             r"^Lucky! You gain an extra (?P<tr>\d*) " \
                               r"training sessions?!$",
                             enabled=False, group='linfo',
                             argtypes={'tr':int})
    self.api('triggers.add')('lvlbonusstat',
                             r"^You gain a bonus (?P<stat>.*) point!$",
                             enabled=False, group='linfo')

    self.api('triggers.add')('lvlshbadstar',
                             r"^%s$" % re.escape("*******************************" \
                                "****************************************"),
                             enabled=False, group='superhero')
    self.api('triggers.add')('lvlshbad',
                             r"^Use either: 'superhero loud'   - (?P<mins>.*) mins of " \
                               r"double xp, (?P<qp>.*)qp and (?P<gold>.*) gold$",
                             enabled=False, group='superhero')
    self.api('triggers.add')('lvlshnogold',
                             r"^You must be carrying at least 500,000 gold coins.$",
                             enabled=False, group='superhero')
    self.api('triggers.add')('lvlshnoqp',
                             r"^You must have at least 1000 quest points.$",
                             enabled=False, group='superhero')
    self.api('triggers.add')('lvlshnodbl',
                             r"^You cannot superhero loud until double exp is over.$",
                             enabled=False, group='superhero')
    self.api('triggers.add')('lvlshnot200',
                             r"^You have to be level 200 to superhero.$",
                             enabled=False, group='superhero')

    self.api('triggers.add')('lvlpreremort',
                             r"^You are now flagged as remorting.$",
                             enabled=True, group='remort')
    self.api('triggers.add')('lvlremortcomp',
                             r"^\* Remort transformation complete!$",
                             enabled=True, group='remort')
    self.api('triggers.add')('lvltier',
                             r"^## You have already remorted the max number of times.$",
                             enabled=True, group='remort')


    self.api('events.register')('trigger_lvlpup', self._lvl)
    self.api('events.register')('trigger_lvlpupbless', self._lvl)
    self.api('events.register')('trigger_lvllevel', self._lvl)
    self.api('events.register')('trigger_lvlbless', self._lvl)
    #self.api('events.register')('trigger_lvlsh', self._lvl)
    self.api('events.register')('trigger_lvlgains', self._lvlgains)
    self.api('events.register')('trigger_lvlpupgains', self._lvlgains)
    self.api('events.register')('trigger_lvlblesstrain',
                                self._lvlblesstrains)
    self.api('events.register')('trigger_lvlbonustrains',
                                self._lvlbonustrains)
    self.api('events.register')('trigger_lvlbonusstat',
                                self._lvlbonusstat)
    self.api('events.register')('trigger_lvlbattlelearntrains',
                                self._lvlbattlelearntrains)

    self.api('events.register')('trigger_lvlshbadstar',
                                self._superherobad)
    self.api('events.register')('trigger_lvlshbad', self._superherobad)
    self.api('events.register')('trigger_lvlshnogold',
                                self._superherobad)
    self.api('events.register')('trigger_lvlshnoqp', self._superherobad)
    self.api('events.register')('trigger_lvlshnodbl', self._superherobad)
    self.api('events.register')('trigger_lvlshnot200', self._superherobad)

    self.api('events.register')('watch_shloud', self.cmd_superhero)
    self.api('events.register')('watch_shsilent', self.cmd_superhero)
    self.api('events.register')('watch_shconfirm', self.cmd_superhero)
    self.api('events.register')('watch_shloudconfirm', self.cmd_superhero)

    self.api('events.register')('trigger_lvlpreremort', self._preremort)
    self.api('events.register')('trigger_lvlremortcomp', self._remortcomp)
    self.api('events.register')('trigger_lvltier', self._tier)

    self.api('events.register')('plugin_%s_savestate' % self.sname, self._savestate)

  def _gmcpstatus(self, _=None):
    """
    check gmcp status when tiering
    """
    state = self.api('GMCP.getv')('char.status.state')
    if state == 2:
      self.api('ouput.client')('seen2')
      self.api('setting.change')('seen2', True)
      self.api('events.unregister')('GMCP:char.status', self._gmcpstatus)
      self.api('events.register')('GMCP:char.base', self._gmcpbase)

  def _gmcpbase(self, _=None):
    """
    look for a new base when we remort
    """
    self.api('send.client')('called char.base')
    state = self.api('GMCP.getv')('char.status.state')
    tiering = self.api('setting.gets')('tiering')
    seen2 = self.api('setting.gets')('seen2')
    if tiering and seen2 and state == 3:
      self.api('send.client')('in char.base')
      self.api('events.unregister')('GMCP:char.base', self._gmcpstatus)
      self._lvl({'level':1})

  def _tier(self, _=None):
    """
    about to tier
    """
    self.api('setting.change')('tiering', True)
    self.api('send.client')('tiering')
    self.api('events.register')('GMCP:char.status', self._gmcpstatus)

  def _remortcomp(self, _=None):
    """
    do stuff when a remort is complete
    """
    self.api('setting.change')('preremort', False)
    self.api('setting.change')('remortcomp', True)
    self._lvl({'level':1})

  def _preremort(self, _=None):
    """
    set the preremort flag
    """
    self.api('setting.change')('preremort', True)
    self.api('events.eraise')('aard_level_preremort', {})

  def cmd_superhero(self, _=None):
    """
    figure out what is done when superhero is typed
    """
    self.api('send.client')('superhero was typed')
    self.api('triggers.togglegroup')('superhero', True)
    self._lvl({'level':201})

  def _superherobad(self, _=None):
    """
    undo things that we typed if we didn't really superhero
    """
    self.api('send.client')('didn\'t sh though')
    self.api('triggers.togglegroup')('superhero', False)
    self.api('triggers.togglegroup')('linfo', False)
    self.api('events.unregister')('trigger_emptyline', self._finish)

  def resetlevel(self):
    """
    reset the level info, use the finishtime of the last level as
    the starttime of the next level
    """
    if 'finishtime' in self.levelinfo and self.levelinfo['finishtime'] > 0:
      starttime = self.levelinfo['finishtime']
    else:
      starttime = time.time()
    self.levelinfo.clear()
    self.levelinfo['type'] = ""
    self.levelinfo['level'] = -1
    self.levelinfo['str'] = 0
    self.levelinfo['int'] = 0
    self.levelinfo['wis'] = 0
    self.levelinfo['dex'] = 0
    self.levelinfo['con'] = 0
    self.levelinfo['luc'] = 0
    self.levelinfo['starttime'] = starttime
    self.levelinfo['hp'] = 0
    self.levelinfo['mp'] = 0
    self.levelinfo['mv'] = 0
    self.levelinfo['pracs'] = 0
    self.levelinfo['trains'] = 0
    self.levelinfo['bonustrains'] = 0
    self.levelinfo['blessingtrains'] = 0
    self.levelinfo['battlelearntrains'] = 0
    self.levelinfo['totallevels'] = 0

  def _lvl(self, args=None):
    """
    trigger for leveling
    """
    if not args:
      return

    self.resetlevel()
    if 'triggername' in args and (args['triggername'] == 'lvlpup' \
        or args['triggername'] == 'lvlpupbless'):
      self.levelinfo['level'] = self.api('GMCP.getv')('char.status.level')
      self.levelinfo['totallevels'] = self.api('aardu.getactuallevel')()
      self.levelinfo['type'] = 'pup'
    else:
      self.levelinfo['level'] = args['level']
      self.levelinfo['totallevels'] = self.api('aardu.getactuallevel')(
          args['level'])
      self.levelinfo['type'] = 'level'

    self.api('triggers.togglegroup')('linfo', True)
    self.api('events.register')('trigger_emptyline', self._finish)


  def _lvlblesstrains(self, args):
    """
    trigger for blessing trains
    """
    self.levelinfo['blessingtrains'] = args['tr']

  def _lvlbonustrains(self, args):
    """
    trigger for bonus trains
    """
    self.levelinfo['bonustrains'] = args['tr']

  def _lvlbattlelearntrains(self, args):
    """
    trigger for bonus trains
    """
    self.levelinfo['battlelearntrains'] = args['tr']

  def _lvlbonusstat(self, args):
    """
    trigger for bonus stats
    """
    self.levelinfo[args['stat'][:3].lower()] = 1

  def _lvlgains(self, args):
    """
    trigger for level gains
    """
    self.levelinfo['trains'] = args['tr']

    if args['triggername'] == "lvlgains":
      self.levelinfo['hp'] = args['hp']
      self.levelinfo['mp'] = args['mp']
      self.levelinfo['mv'] = args['mv']
      self.levelinfo['pracs'] = args['pr']

  def _finish(self, _):
    """
    finish up and raise the level event
    """
    remortcomp = self.api('setting.gets')('remortcomp')
    tiering = self.api('setting.gets')('tiering')
    if self.levelinfo['trains'] == 0 and not remortcomp or tiering:
      return
    self.levelinfo['finishtime'] = time.time()
    self.levelinfo.sync()
    self.api('triggers.togglegroup')('linfo', False)
    self.api('events.unregister')('trigger_emptyline', self._finish)
    self.api('events.eraise')('aard_level_gain',
                              copy.deepcopy(self.levelinfo))
    if self.levelinfo['level'] == 200 and self.levelinfo['type'] == 'level':
      self.api('send.msg')('raising hero event', 'level')
      self.api('events.eraise')('aard_level_hero', {})
    elif self.levelinfo['level'] == 201 and self.levelinfo['type'] == 'level':
      self.api('send.msg')('raising superhero event', 'level')
      self.api('events.eraise')('aard_level_superhero', {})
    elif self.levelinfo['level'] == 1:
      if self.api('setting.gets')('tiering'):
        self.api('send.msg')('raising tier event', 'level')
        self.api('setting.change')('tiering', False)
        self.api('setting.change')('seen2', False)
        self.api('events.eraise')('aard_level_tier', {})
      else:
        self.api('send.msg')('raising remort event', 'level')
        self.api('setting.change')('remortcomp', False)
        self.api('events.eraise')('aard_level_remort', {})

  def _savestate(self, _=None):
    """
    save states
    """
    self.levelinfo.sync()
Example #43
0
class Plugin(BasePlugin):
  """
  a plugin to do simple substitution
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    BasePlugin.__init__(self, *args, **kwargs)
    self.savesubfile = os.path.join(self.savedir, 'subs.txt')
    self._substitutes = PersistentDict(self.savesubfile, 'c')

  def load(self):
    """
    load the plugins
    """
    BasePlugin.load(self)

    parser = argp.ArgumentParser(add_help=False,
                                 description='add a simple substitute')
    parser.add_argument('original',
                        help='the output to substitute',
                        default='',
                        nargs='?')
    parser.add_argument('replacement',
                        help='the string to replace it with',
                        default='',
                        nargs='?')
    self.api('commands.add')('add',
                             self.cmd_add,
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description='remove a substitute')
    parser.add_argument('substitute',
                        help='the substitute to remove',
                        default='',
                        nargs='?')
    self.api('commands.add')('remove',
                             self.cmd_remove,
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description='list substitutes')
    parser.add_argument('match',
                        help='list only substitutes that have this argument in them',
                        default='',
                        nargs='?')
    self.api('commands.add')('list',
                             self.cmd_list,
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description='clear all substitutes')
    self.api('commands.add')('clear',
                             self.cmd_clear,
                             parser=parser)

    self.api('commands.default')('list')
    self.api('events.register')('from_mud_event', self.findsub)

    self.api('events.register')('plugin_%s_savestate' % self.sname, self._savestate)

  def findsub(self, args):
    """
    this function finds subs in mud data
    """
    data = args['original']
    dtype = args['dtype']
    if dtype != 'fromproxy':
      for mem in self._substitutes.keys():
        if mem in data:
          ndata = data.replace(mem,
                               self.api('colors.convertcolors')(
                                   self._substitutes[mem]['sub']))
          if ndata != data:
            args['trace']['changes'].append({'flag':'Modify',
                                             'data':'changed "%s" to "%s"' % \
                                                 (data, ndata),
                                             'plugin':self.sname,
                                             'eventname':args['eventname']})
            data = ndata
      args['original'] = data
      return args

  def cmd_add(self, args):
    """
    @G%(name)s@w - @B%(cmdname)s@w
      Add a substitute
      @CUsage@w: add @Y<originalstring>@w @M<replacementstring>@w
        @Yoriginalstring@w    = The original string to be replaced
        @Mreplacementstring@w = The new string
    """
    tmsg = []
    if args['original'] and args['replacement']:
      tmsg.append("@GAdding substitute@w : '%s' will be replaced by '%s'" % \
                                      (args['original'], args['replacement']))
      self.addsub(args['original'], args['replacement'])
      return True, tmsg

    tmsg.append("@RPlease specify all arguments@w")
    return False, tmsg

  def cmd_remove(self, args):
    """
    @G%(name)s@w - @B%(cmdname)s@w
      Remove a substitute
      @CUsage@w: rem @Y<originalstring>@w
        @Yoriginalstring@w    = The original string
    """
    tmsg = []
    if args['substitute']:
      tmsg.append("@GRemoving substitute@w : '%s'" % (args['substitute']))
      self.removesub(args['substitute'])
      return True, tmsg

    return False, tmsg

  def cmd_list(self, args):
    """
    @G%(name)s@w - @B%(cmdname)s@w
      List substitutes
      @CUsage@w: list
    """
    tmsg = self.listsubs(args['match'])
    return True, tmsg

  def cmd_clear(self, args):
    # pylint: disable=unused-argument
    """
    @G%(name)s@w - @B%(cmdname)s@w
      List substitutes
      @CUsage@w: list"""
    self.clearsubs()
    return True, ['Substitutes cleared']

  def addsub(self, item, sub):
    """
    internally add a substitute
    """
    self._substitutes[item] = {'sub':sub}
    self._substitutes.sync()

  def removesub(self, item):
    """
    internally remove a substitute
    """
    if item in self._substitutes:
      del self._substitutes[item]
      self._substitutes.sync()

  def listsubs(self, match):
    """
    return a table of strings that list subs
    """
    tmsg = []
    for item in self._substitutes:
      if not match or match in item:
        tmsg.append("%-35s : %s@w" % (item, self._substitutes[item]['sub']))
    if not tmsg:
      tmsg = ['None']
    return tmsg

  def clearsubs(self):
    """
    clear all subs
    """
    self._substitutes.clear()
    self._substitutes.sync()

  def reset(self):
    """
    reset the plugin
    """
    BasePlugin.reset(self)
    self.clearsubs()

  def _savestate(self, _=None):
    """
    save states
    """
    self._substitutes.sync()
Example #44
0
class Plugin(BasePlugin):
  """
  a plugin to handle global variables, if something goes through
   send.execute (this includes from the client), a variable
   can be specified with $varname and will be substituted.
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.variablefile = os.path.join(self.savedir, 'variables.txt')
    self._variables = PersistentDict(self.variablefile, 'c')
    self.api.get('api.add')('getv', self.api_getv)
    self.api.get('api.add')('setv', self.api_setv)
    self.api.get('api.add')('replace', self.api_replace)

  def load(self):
    """
    load the plugin
    """
    BasePlugin.load(self)

    parser = argparse.ArgumentParser(add_help=False,
                                     description='add a variable')
    parser.add_argument('name',
                        help='the name of the variable',
                        default='',
                        nargs='?')
    parser.add_argument('value',
                        help='the value of the variable',
                        default='',
                        nargs='?')
    self.api.get('commands.add')('add',
                                 self.cmd_add,
                                 parser=parser)

    parser = argparse.ArgumentParser(add_help=False,
                                     description='remove a variable')
    parser.add_argument('name',
                        help='the variable to remove',
                        default='',
                        nargs='?')
    self.api.get('commands.add')('remove',
                                 self.cmd_remove,
                                 parser=parser)

    parser = argparse.ArgumentParser(add_help=False,
                                     description='list variables')
    parser.add_argument('match',
                        help='list only variables that have this argument in their name',
                        default='',
                        nargs='?')
    self.api.get('commands.add')('list',
                                 self.cmd_list,
                                 parser=parser)

    self.api.get('commands.default')('list')
    #self.api.get('events.register')('from_client_event', self.checkvariable,
                                        #prio=1)
    self.api.get('events.register')('from_client_event',
                                    self.checkline,
                                    prio=99)

  # get a variable
  def api_getv(self, varname):
    """  get the variable with a specified name
    @Yvarname@w  = the variable to get

    this function returns the value of variable with the name of the argument
    """
    if varname in self._variables:
      return self._variables[varname]

    return None

  # set a variable
  def api_setv(self, varname, value):
    """  set the variable with a specified name to the specified value
    @Yvarname@w  = the variable to set
    @Yvalue@w  = the value to set

    this function returns True if the value was set, False if an error was
    encountered
    """
    try:
      self._variables[varname] = value
      return True
    except Exception: # pylint: disable=broad-except
      return False

  # replace variables in data
  def api_replace(self, data):
    """replace the variables in data
    @Ydata@w  = the variable to get

    this function returns the data after variable substition
    """
    templ = Template(data)
    return templ.safe_substitute(self._variables)

  def checkline(self, args):
    """
    this function checks for variables in input
    """
    data = args['fromdata'].strip()

    datan = self.api('vars.replace')(data)

    if datan != data:
      self.api.get('send.msg')('replacing "%s" with "%s"' % (data.strip(),
                                                             datan.strip()))
      args['fromdata'] = datan
      args['beforevar'] = data

    return args

  def cmd_add(self, args):
    """
    command to add a variable
    """
    tmsg = []
    if args['name'] and args['value']:
      tmsg.append("@GAdding variable@w : '%s' will be replaced by '%s'" % \
                                              (args['name'], args['value']))
      self.addvariable(args['name'], args['value'])
      return True, tmsg
    else:
      tmsg.append("@RPlease include all arguments@w")
      return False, tmsg

  def cmd_remove(self, args):
    """
    command to remove a variable
    """
    tmsg = []
    if args['name']:
      tmsg.append("@GRemoving variable@w : '%s'" % (args['name']))
      self.removevariable(args['name'])
      return True, tmsg
    else:
      return False, ['@RPlease specifiy a variable to remove@w']

  def cmd_list(self, args):
    """
    command to list variables
    """
    tmsg = self.listvariables(args['match'])
    return True, tmsg

  def addvariable(self, item, value):
    """
    internally add a variable
    """
    self._variables[item] = value
    self._variables.sync()

  def removevariable(self, item):
    """
    internally remove a variable
    """
    if item in self._variables:
      del self._variables[item]
      self._variables.sync()

  def listvariables(self, match):
    """
    return a table of variables
    """
    tmsg = []
    for item in self._variables:
      if not match or match in item:
        tmsg.append("%-20s : %s@w" % (item, self._variables[item]))
    if len(tmsg) == 0:
      tmsg = ['None']
    return tmsg

  def clearvariables(self):
    """
    clear all variables
    """
    self._variables.clear()
    self._variables.sync()

  def reset(self):
    """
    reset the plugin
    """
    BasePlugin.reset(self)
    self.clearvariables()

  def savestate(self):
    """
    save states
    """
    BasePlugin.savestate(self)
    self._variables.sync()
Example #45
0
class Plugin(AardwolfBasePlugin):
  """
  a plugin to handle aardwolf quest events
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    AardwolfBasePlugin.__init__(self, *args, **kwargs)
    self.savegqfile = os.path.join(self.savedir, 'gq.txt')
    self.gqinfo = PersistentDict(self.savegqfile, 'c')
    self._gqsdeclared = {}
    self._gqsstarted = {}
    self.api('setting.add')('joined', -1, int, 'the gq number joined')
    self.api('setting.add')('maxkills', False, bool, 'no qp because of maxkills')
    self.mobsleft = []
    self.linecount = 0

  def load(self):
    """
    load the plugins
    """
    AardwolfBasePlugin.load(self)
    self.api('watch.add')('gq_check',
                          r'^(gq|gqu|gque|gques|gquest) (c|ch|che|chec|check)$')

    self.api('triggers.add')(
        'gqdeclared',
        r"^Global Quest: Global quest \# *(?P<gqnum>\d*) has been " \
          r"declared for levels (?P<lowlev>\d*) to (?P<highlev>\d*)( - .*)*\.$",
        argtypes={'gqnum':int})
    self.api('triggers.add')(
        'gqjoined',
        r"^You have now joined Global Quest \# *(?P<gqnum>\d*)\. .*$",
        argtypes={'gqnum':int})
    self.api('triggers.add')(
        'gqstarted',
        r"^Global Quest: Global quest \# *(?P<gqnum>\d*) for levels .* "\
          r"to .* has now started\.$",
        argtypes={'gqnum':int})
    self.api('triggers.add')(
        'gqcancelled',
        r"^Global Quest: Global quest \# *(?P<gqnum>\d*) has been " \
          r"cancelled due to lack of (activity|participants)\.$",
        argtypes={'gqnum':int})
    self.api('triggers.add')(
        'gqquit',
        r"^You are no longer part of Global Quest \# *(?P<gqnum>\d*) " \
          r"and will be unable to rejoin.$",
        argtypes={'gqnum':int})

    # GQ Check triggers
    self.api('triggers.add')(
        'gqnone',
        r"^You are not in a global quest\.$",
        enabled=False, group='gqcheck')
    self.api('triggers.add')(
        'gqitem',
        r"^You still have to kill (?P<num>[\d]*) \* " \
          r"(?P<mob>.*?) \((?P<location>.*?)\)(|\.)$",
        enabled=False, group='gqcheck',
        argtypes={'num':int})
    self.api('triggers.add')(
        'gqnotstarted',
        r"^Global Quest \# *(?P<gqnum>\d*) has not yet started.",
        enabled=False, group='gqcheck',
        argtypes={'gqnum':int})
    self.api('triggers.add')(
        'gqwins',
        r"^You may win .* more gquests* at this level\.$",
        enabled=False, group='gqcheck')

    self.api('triggers.add')(
        'gqreward',
        r"^\s*Reward of (?P<amount>\d+) (?P<type>.+) .+ added\.$",
        enabled=False, group='gqrew',
        argtypes={'amount':int})

    self.api('triggers.add')(
        'gqmobdead',
        r"^Congratulations, that was one of the GLOBAL QUEST mobs!$",
        enabled=False, group='gqin')

    self.api('triggers.add')(
        'gqextended',
        r"^Global Quest: Global Quest \# *(?P<gqnum>\d*) will go " \
          r"into extended time for 3 more minutes.$",
        enabled=False, group='gqin',
        argtypes={'gqnum':int})

    self.api('triggers.add')(
        'gqwon',
        r"^You were the first to complete this quest!$",
        enabled=False, group='gqin')
    self.api('triggers.add')(
        'gqextfin',
        r"^You have finished this global quest.$",
        enabled=False, group='gqin')
    self.api('triggers.add')(
        'gqwonannounce',
        r"Global Quest: Global Quest \#(?P<gqnum>.*) has been won " \
          r"by (?P<winner>.*) - (.*) win.$",
        enabled=False, group='gqin',
        argtypes={'gqnum':int})

    self.api('triggers.add')(
        'gqnote',
        r"^INFO: New post \#(?P<bdnum>.*) in forum Gquest from " \
          r"Aardwolf Subj: Lvl (?P<low>.*) to (?P<high>.*) - " \
          r"Global quest \# *(?P<gqnum>\d*)$",
        argtypes={'gqnum':int})

    self.api('triggers.add')(
        'gqmaxkills',
        r"^You have reached the " \
          r"maximum (.*) kills for which you can earn quest points this level\.$")

    self.api('events.register')('trigger_gqdeclared', self._gqdeclared)
    self.api('events.register')('trigger_gqjoined', self._gqjoined)
    self.api('events.register')('trigger_gqstarted', self._gqstarted)
    self.api('events.register')('trigger_gqcancelled', self._gqcancelled)
    self.api('events.register')('trigger_gqquit', self._gqquit)

    self.api('events.register')('trigger_gqnone', self._notstarted)
    self.api('events.register')('trigger_gqitem', self._gqitem)
    self.api('events.register')('trigger_gqnotstarted', self._notstarted)
    self.api('events.register')('trigger_gqwins', self._gqwins)

    self.api('events.register')('trigger_gqreward', self._gqreward)

    self.api('events.register')('trigger_gqmobdead', self._gqmobdead)

    self.api('events.register')('trigger_gqextended', self._gqextended)

    self.api('events.register')('trigger_gqwon', self._gqwon)
    self.api('events.register')('trigger_gqextfin', self._gqextfin)
    self.api('events.register')('trigger_gqwonannounce',
                                self._gqwonannounce)

    self.api('events.register')('trigger_gqnote', self._gqnote)
    self.api('events.register')('trigger_gqmaxkills', self._gqmaxkills)

    self.api('events.register')('watch_gq_check', self._gqcheckcmd)

    self.api('events.register')('plugin_%s_savestate' % self.sname, self._savestate)

  def _gqnew(self):
    """
    reset the gq info
    """
    self.mobsleft = {}
    self.gqinfo.clear()
    self.gqinfo['mobs'] = {}
    self.gqinfo['trains'] = 0
    self.gqinfo['pracs'] = 0
    self.gqinfo['gold'] = 0
    self.gqinfo['tp'] = 0
    self.gqinfo['qp'] = 0
    self.gqinfo['qpmobs'] = 0
    self.gqinfo['level'] = self.api('aardu.getactuallevel')(
        self.api('GMCP.getv')('char.status.level'))
    self.gqinfo['starttime'] = 0
    self.gqinfo['finishtime'] = 0
    self.gqinfo['length'] = 0
    self.gqinfo['won'] = 0
    self.gqinfo['completed'] = 0
    self.gqinfo['extended'] = 0
    self.api('setting.change')('maxkills', False)
    self.savestate()

  def _gqdeclared(self, args):
    """
    do something when a gq is declared
    """
    self._gqsdeclared[args['gqnum']] = True
    self._checkgqavailable()
    self._raisegq('aard_gq_declared', args)

  def _gqjoined(self, args):
    """
    do something when a gq is joined
    """
    self._gqnew()
    self.api('setting.change')('joined', args['gqnum'])

    self.mobsleft = []

    if args['gqnum'] in self._gqsstarted:
      self._gqstarted(args)
    elif args['gqnum'] not in self._gqsdeclared:
      self._gqsdeclared[args['gqnum']] = True
      self._gqstarted(args)
    self._raisegq('aard_gq_joined', args)

  def _gqstarted(self, args):
    """
    do something when a gq starts
    """
    if args['gqnum'] not in self._gqsstarted:
      self._gqsstarted[args['gqnum']] = True
      self._raisegq('aard_gq_started', args)
      self._checkgqavailable()
    if self.api('setting.gets')('joined') == args['gqnum']:
      self.gqinfo['starttime'] = time.time()
      self.api('triggers.togglegroup')("gqin", True)
      self.api('send.execute')("gq check")

  def _gqcancelled(self, args):
    """
    the gq has been cancelled
    """
    self._raisegq('aard_gq_cancelled', {'gqnum':args['gqnum']})
    if args['gqnum'] == self.api('setting.gets')('joined'):
      if self.gqinfo['qpmobs'] > 0:
        self.gqinfo['finishtime'] = time.time()
        self._raisegq('aard_gq_done', self.gqinfo)
      self._gqreset({'gqnum':args['gqnum']})

    else:
      if args['gqnum'] in self._gqsdeclared:
        del self._gqsdeclared[args['gqnum']]
      if args['gqnum'] in self._gqsstarted:
        del self._gqsstarted[args['gqnum']]
      self._checkgqavailable()

  def _gqitem(self, args):
    """
    do something with a gq item
    """
    name = args['mob']
    num = args['num']
    location = args['location']
    if not name or not location or not num:
      self.api('send.client')("error parsing line: %s" % args['line'])
    else:
      self.mobsleft.append({'name':name,
                            'nocolorname':self.api('colors.stripansi')(name),
                            'location':location, 'num':num})

  def _notstarted(self, _=None):
    """
    this will be called when a gq check returns the not started message
    """
    self.api('triggers.togglegroup')('gqcheck', False)
    self.api('triggers.togglegroup')('gqin', False)

  def _gqwins(self, _=None):
    """
    this will be enabled when gq check is enabled
    """
    if not self.gqinfo['mobs']:
      self.gqinfo['mobs'] = self.mobsleft[:]
      self.savestate()

    self.api('triggers.togglegroup')('gqcheck', False)
    self._raisegq('aard_gq_mobsleft',
                  {'mobsleft':copy.deepcopy(self.mobsleft)})

  def _gqmobdead(self, _=None):
    """
    called when a gq mob is killed
    """
    if not self.api('setting.gets')('maxkills'):
      self.gqinfo['qpmobs'] = self.gqinfo['qpmobs'] + 3
    self.api('events.register')('aard_mobkill', self._mobkillevent)

  def _gqextended(self, args):
    """
    gquest went into extended time
    """
    if args['gqnum'] == self.api('setting.gets')('joined'):
      self.gqinfo['extended'] = 1

  def _gqmaxkills(self, _=None):
    """
    didn't get xp for that last kill
    """
    self.api('setting.change')('maxkills', True)

  def _mobkillevent(self, args):
    """
    this will be registered to the mobkill hook
    """
    self.api('send.msg')('checking kill %s' % args['name'])
    self.api('events.register')('aard_mobkill', self._mobkillevent)

    found = False
    removeitem = None
    for i in range(len(self.mobsleft)):
      tmob = self.mobsleft[i]
      if tmob['name'] == args['name']:
        self.api('send.msg')('found %s' % tmob['name'])
        found = True
        if tmob['num'] == 1:
          removeitem = i
        else:
          tmob['num'] = tmob['num'] - 1

    if removeitem:
      del self.mobsleft[removeitem]

    if found:
      self._raisegq('aard_gq_mobsleft',
                    {'mobsleft':self.mobsleft})
    else:
      self.api('send.msg')("BP GQ: could not find mob: %s" % args['name'])
      self.api('send.execute')("gq check")

  def _gqwon(self, _=None):
    """
    the gquest was won
    """
    self.gqinfo['won'] = 1
    self.gqinfo['finishtime'] = time.time()
    self.api('triggers.togglegroup')("gqrew", True)

  def _gqwonannounce(self, args):
    """
    the mud announced that someone won the gquest
    """
    if self.api('GMCP.getv')('char.base.name') == args['winner']:
      # we won
      self._raisegq('aard_gq_won', self.gqinfo)
      self._gqreset(args)

  def _gqreward(self, args=None):
    """
    handle cpreward
    """
    rtype = args['type']
    ramount = args['amount']
    rewardt = self.api('aardu.rewardtable')()
    self.gqinfo[rewardt[rtype]] = ramount
    self.savestate()

  def _gqcheckcmd(self, args=None):
    """
    do something after we see a gq check
    """
    self.mobsleft = []
    self.api('triggers.togglegroup')('gqcheck', True)
    return args

  def _gqquit(self, args):
    """
    quit the gq
    """
    if self.gqinfo['qpmobs'] > 0:
      self.gqinfo['finishtime'] = time.time()
      self._raisegq('aard_gq_done', self.gqinfo)
    self._gqreset(args)

  def _gqextfin(self, _=None):
    """
    the character finished the extended gq
    """
    if self.gqinfo['qpmobs'] > 0:
      self.gqinfo['completed'] = 1
      self.gqinfo['finishtime'] = time.time()
      self._raisegq('aard_gq_completed', self.gqinfo)
      self._gqreset({'gqnum':self.api('setting.gets')('joined')})

  def _raisegq(self, event, data=None):
    """
    raise a gq event
    """
    self.api('send.msg')('raising %s with %s' % (event, data))
    self.savestate()
    if data:
      self.api('events.eraise')(event, copy.deepcopy(data))
    else:
      self.api('events.eraise')(event)

  def _gqnote(self, args):
    """
    do something on the gquest note
    """
    if args['gqnum'] == self.api('setting.gets')('joined'):
      if self.gqinfo['qpmobs'] > 0:
        self.gqinfo['finishtime'] = time.time()
        self._raisegq('aard_gq_done', self.gqinfo)
      self._gqreset(args)
    if args['gqnum'] in self._gqsdeclared:
      del self._gqsdeclared[args['gqnum']]
    if args['gqnum'] in self._gqsstarted:
      del self._gqsstarted[args['gqnum']]
    self._checkgqavailable()

  def _gqreset(self, args=None):
    """
    reset gq settings
    """
    self._gqnew()
    if args:
      if args['gqnum'] in self._gqsdeclared:
        del self._gqsdeclared[args['gqnum']]
      if args['gqnum'] in self._gqsstarted:
        del self._gqsstarted[args['gqnum']]
      self._checkgqavailable()
    self.api('triggers.togglegroup')("gqcheck", False)
    self.api('triggers.togglegroup')("gqin", False)
    self.api('triggers.togglegroup')("gqrew", False)
    self.api('events.unregister')('aard_mobkill', self._mobkillevent)
    self.api('setting.change')('joined', 'default')
    self.api('setting.change')('maxkills', False)
    self.savestate()

  def _checkgqavailable(self):
    if self._gqsdeclared:
      self._raisegq('aard_gq_available')
    else:
      self._raisegq('aard_gq_notavailable')

  def _savestate(self, _=None):
    """
    save states
    """
    self.gqinfo.sync()
Example #46
0
class Plugin(AardwolfBasePlugin):
    """
  a plugin to handle aardwolf quest events
  """
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        AardwolfBasePlugin.__init__(self, *args, **kwargs)
        self.savegqfile = os.path.join(self.savedir, 'gq.txt')
        self.gqinfo = PersistentDict(self.savegqfile, 'c')
        self._gqsdeclared = {}
        self._gqsstarted = {}
        self.api.get('setting.add')('joined', -1, int, 'the gq number joined')
        self.api.get('setting.add')('maxkills', False, bool,
                                    'no qp because of maxkills')
        self.mobsleft = []
        self.linecount = 0

    def load(self):
        """
    load the plugins
    """
        AardwolfBasePlugin.load(self)
        self.api.get('watch.add')(
            'gq_check', '^(gq|gqu|gque|gques|gquest) (c|ch|che|chec|check)$')

        self.api.get('triggers.add')('gqdeclared',
                      "^Global Quest: Global quest \# *(?P<gqnum>\d*) has been " \
                        "declared for levels (?P<lowlev>\d*) to (?P<highlev>\d*)( - .*)*\.$",
                      argtypes={'gqnum':int})
        self.api.get('triggers.add')(
            'gqjoined',
            "^You have now joined Global Quest \# *(?P<gqnum>\d*)\. .*$",
            argtypes={
                'gqnum': int
            })
        self.api.get('triggers.add')('gqstarted',
                      "^Global Quest: Global quest \# *(?P<gqnum>\d*) for levels .* "\
                        "to .* has now started\.$",
                      argtypes={'gqnum':int})
        self.api.get('triggers.add')('gqcancelled',
                      "^Global Quest: Global quest \# *(?P<gqnum>\d*) has been " \
                        "cancelled due to lack of (activity|participants)\.$",
                      argtypes={'gqnum':int})
        self.api.get('triggers.add')('gqquit',
                      "^You are no longer part of Global Quest \# *(?P<gqnum>\d*) " \
                        "and will be unable to rejoin.$",
                      argtypes={'gqnum':int})

        # GQ Check triggers
        self.api.get('triggers.add')('gqnone',
                                     "^You are not in a global quest\.$",
                                     enabled=False,
                                     group='gqcheck')
        self.api.get('triggers.add')('gqitem',
                      "^You still have to kill (?P<num>[\d]*) \* " \
                        "(?P<mob>.*?) \((?P<location>.*?)\)(|\.)$",
                      enabled=False, group='gqcheck',
                      argtypes={'num':int})
        self.api.get('triggers.add')(
            'gqnotstarted',
            "^Global Quest \# *(?P<gqnum>\d*) has not yet started.",
            enabled=False,
            group='gqcheck',
            argtypes={
                'gqnum': int
            })
        self.api.get('triggers.add')(
            'gqwins',
            "^You may win .* more gquests* at this level\.$",
            enabled=False,
            group='gqcheck')

        self.api.get('triggers.add')(
            'gqreward',
            "^\s*Reward of (?P<amount>\d+) (?P<type>.+) .+ added\.$",
            enabled=False,
            group='gqrew',
            argtypes={
                'amount': int
            })

        self.api.get('triggers.add')(
            'gqmobdead',
            "^Congratulations, that was one of the GLOBAL QUEST mobs!$",
            enabled=False,
            group='gqin')

        self.api.get('triggers.add')('gqextended',
                      "^Global Quest: Global Quest \# *(?P<gqnum>\d*) will go " \
                        "into extended time for 3 more minutes.$",
                      enabled=False, group='gqin',
                      argtypes={'gqnum':int})

        self.api.get('triggers.add')(
            'gqwon',
            "^You were the first to complete this quest!$",
            enabled=False,
            group='gqin')
        self.api.get('triggers.add')('gqextfin',
                                     "^You have finished this global quest.$",
                                     enabled=False,
                                     group='gqin')
        self.api.get('triggers.add')('gqwonannounce',
                      "Global Quest: Global Quest \#(?P<gqnum>.*) has been won " \
                        "by (?P<winner>.*) - (.*) win.$",
                      enabled=False, group='gqin',
                      argtypes={'gqnum':int})

        self.api.get('triggers.add')('gqnote',
                      "^INFO: New post \#(?P<bdnum>.*) in forum Gquest from " \
                        "Aardwolf Subj: Lvl (?P<low>.*) to (?P<high>.*) - " \
                        "Global quest \# *(?P<gqnum>\d*)$",
                        argtypes={'gqnum':int})

        self.api.get('triggers.add')('gqmaxkills', "^You have reached the " \
            "maximum (.*) kills for which you can earn quest points this level\.$")

        self.api.get('events.register')('trigger_gqdeclared', self._gqdeclared)
        self.api.get('events.register')('trigger_gqjoined', self._gqjoined)
        self.api.get('events.register')('trigger_gqstarted', self._gqstarted)
        self.api.get('events.register')('trigger_gqcancelled',
                                        self._gqcancelled)
        self.api.get('events.register')('trigger_gqquit', self._gqquit)

        self.api.get('events.register')('trigger_gqnone', self._notstarted)
        self.api.get('events.register')('trigger_gqitem', self._gqitem)
        self.api.get('events.register')('trigger_gqnotstarted',
                                        self._notstarted)
        self.api.get('events.register')('trigger_gqwins', self._gqwins)

        self.api.get('events.register')('trigger_gqreward', self._gqreward)

        self.api.get('events.register')('trigger_gqmobdead', self._gqmobdead)

        self.api.get('events.register')('trigger_gqextended', self._gqextended)

        self.api.get('events.register')('trigger_gqwon', self._gqwon)
        self.api.get('events.register')('trigger_gqextfin', self._gqextfin)
        self.api.get('events.register')('trigger_gqwonannounce',
                                        self._gqwonannounce)

        self.api.get('events.register')('trigger_gqnote', self._gqnote)
        self.api.get('events.register')('trigger_gqmaxkills', self._gqmaxkills)

        self.api.get('events.register')('watch_gq_check', self._gqcheckcmd)

    def _gqnew(self):
        """
    reset the gq info
    """
        self.mobsleft = {}
        self.gqinfo.clear()
        self.gqinfo['mobs'] = {}
        self.gqinfo['trains'] = 0
        self.gqinfo['pracs'] = 0
        self.gqinfo['gold'] = 0
        self.gqinfo['tp'] = 0
        self.gqinfo['qp'] = 0
        self.gqinfo['qpmobs'] = 0
        self.gqinfo['level'] = self.api.get('aardu.getactuallevel')(
            self.api.get('GMCP.getv')('char.status.level'))
        self.gqinfo['starttime'] = 0
        self.gqinfo['finishtime'] = 0
        self.gqinfo['length'] = 0
        self.gqinfo['won'] = 0
        self.gqinfo['completed'] = 0
        self.gqinfo['extended'] = 0
        self.api.get('setting.change')('maxkills', False)
        self.savestate()

    def _gqdeclared(self, args):
        """
    do something when a gq is declared
    """
        self._gqsdeclared[args['gqnum']] = True
        self._checkgqavailable()
        self._raisegq('aard_gq_declared', args)

    def _gqjoined(self, args):
        """
    do something when a gq is joined
    """
        self._gqnew()
        self.api.get('setting.change')('joined', args['gqnum'])

        self.mobsleft = []

        if args['gqnum'] in self._gqsstarted:
            self._gqstarted(args)
        elif not (args['gqnum'] in self._gqsdeclared):
            self._gqsdeclared[args['gqnum']] = True
            self._gqstarted(args)
        self._raisegq('aard_gq_joined', args)

    def _gqstarted(self, args):
        """
    do something when a gq starts
    """
        if not (args['gqnum'] in self._gqsstarted):
            self._gqsstarted[args['gqnum']] = True
            self._raisegq('aard_gq_started', args)
            self._checkgqavailable()
        if self.api.get('setting.gets')('joined') == args['gqnum']:
            self.gqinfo['starttime'] = time.time()
            self.api.get('triggers.togglegroup')("gqin", True)
            self.api.get('send.execute')("gq check")

    def _gqcancelled(self, args):
        """
    the gq has been cancelled
    """
        self._raisegq('aard_gq_cancelled', {'gqnum': args['gqnum']})
        if args['gqnum'] == self.api('setting.gets')('joined'):
            if self.gqinfo['qpmobs'] > 0:
                self.gqinfo['finishtime'] = time.time()
                self._raisegq('aard_gq_done', self.gqinfo)
            self._gqreset({'gqnum': args['gqnum']})

        else:
            if args['gqnum'] in self._gqsdeclared:
                del (self._gqsdeclared[args['gqnum']])
            if args['gqnum'] in self._gqsstarted:
                del (self._gqsstarted[args['gqnum']])
            self._checkgqavailable()

    def _gqitem(self, args):
        """
    do something with a gq item
    """
        name = args['mob']
        num = args['num']
        location = args['location']
        if not name or not location or not num:
            self.api.get('send.client')("error parsing line: %s" %
                                        args['line'])
        else:
            self.mobsleft.append({
                'name':
                name,
                'nocolorname':
                self.api.get('colors.stripansi')(name),
                'location':
                location,
                'num':
                num
            })

    def _notstarted(self, _=None):
        """
    this will be called when a gq check returns the not started message
    """
        self.api.get('triggers.togglegroup')('gqcheck', False)
        self.api.get('triggers.togglegroup')('gqin', False)

    def _gqwins(self, _=None):
        """
    this will be enabled when gq check is enabled
    """
        if not self.gqinfo['mobs']:
            self.gqinfo['mobs'] = self.mobsleft[:]
            self.savestate()

        self.api.get('triggers.togglegroup')('gqcheck', False)
        self._raisegq('aard_gq_mobsleft',
                      {'mobsleft': copy.deepcopy(self.mobsleft)})

    def _gqmobdead(self, _=None):
        """
    called when a gq mob is killed
    """
        if not self.api.get('setting.gets')('maxkills'):
            self.gqinfo['qpmobs'] = self.gqinfo['qpmobs'] + 3
        self.api.get('events.register')('aard_mobkill', self._mobkillevent)

    def _gqextended(self, args):
        """
    gquest went into extended time
    """
        if args['gqnum'] == self.api('setting.gets')('joined'):
            self.gqinfo['extended'] = 1

    def _gqmaxkills(self, args):
        """
    didn't get xp for that last kill
    """
        self.api.get('setting.change')('maxkills', True)

    def _mobkillevent(self, args):
        """
    this will be registered to the mobkill hook
    """
        self.api.get('send.msg')('checking kill %s' % args['name'])
        self.api.get('events.register')('aard_mobkill', self._mobkillevent)

        found = False
        removeitem = None
        for i in range(len(self.mobsleft)):
            tmob = self.mobsleft[i]
            if tmob['name'] == args['name']:
                self.api.get('send.msg')('found %s' % tmob['name'])
                found = True
                if tmob['num'] == 1:
                    removeitem = i
                else:
                    tmob['num'] = tmob['num'] - 1

        if removeitem:
            del (self.mobsleft[removeitem])

        if found:
            self._raisegq('aard_gq_mobsleft', {'mobsleft': self.mobsleft})
        else:
            self.api.get('send.msg')("BP GQ: could not find mob: %s" %
                                     args['name'])
            self.api.get('send.execute')("gq check")

    def _gqwon(self, _=None):
        """
    the gquest was won
    """
        self.gqinfo['won'] = 1
        self.gqinfo['finishtime'] = time.time()
        self.api.get('triggers.togglegroup')("gqrew", True)

    def _gqwonannounce(self, args):
        """
    the mud announced that someone won the gquest
    """
        if self.api('GMCP.getv')('char.base.name') == args['winner']:
            # we won
            self._raisegq('aard_gq_won', self.gqinfo)
            self._gqreset(args)

    def _gqreward(self, args=None):
        """
    handle cpreward
    """
        rtype = args['type']
        ramount = args['amount']
        rewardt = self.api.get('aardu.rewardtable')()
        self.gqinfo[rewardt[rtype]] = ramount
        self.savestate()

    def _gqcheckcmd(self, args=None):
        """
    do something after we see a gq check
    """
        self.mobsleft = []
        self.api.get('triggers.togglegroup')('gqcheck', True)
        return args

    def _gqquit(self, args):
        """
    quit the gq
    """
        if self.gqinfo['qpmobs'] > 0:
            self.gqinfo['finishtime'] = time.time()
            self._raisegq('aard_gq_done', self.gqinfo)
        self._gqreset(args)

    def _gqextfin(self, _=None):
        """
    the character finished the extended gq
    """
        if self.gqinfo['qpmobs'] > 0:
            self.gqinfo['completed'] = 1
            self.gqinfo['finishtime'] = time.time()
            self._raisegq('aard_gq_completed', self.gqinfo)
            self._gqreset({'gqnum': self.api('setting.gets')('joined')})

    def _raisegq(self, event, data=None):
        """
    raise a gq event
    """
        self.api('send.msg')('raising %s with %s' % (event, data))
        self.savestate()
        if data:
            self.api.get('events.eraise')(event, copy.deepcopy(data))
        else:
            self.api.get('events.eraise')(event)

    def _gqnote(self, args):
        """
    do something on the gquest note
    """
        if args['gqnum'] == self.api('setting.gets')('joined'):
            if self.gqinfo['qpmobs'] > 0:
                self.gqinfo['finishtime'] = time.time()
                self._raisegq('aard_gq_done', self.gqinfo)
            self._gqreset(args)
        if args['gqnum'] in self._gqsdeclared:
            del (self._gqsdeclared[args['gqnum']])
        if args['gqnum'] in self._gqsstarted:
            del (self._gqsstarted[args['gqnum']])
        self._checkgqavailable()

    def _gqreset(self, args={}):
        """
    reset gq settings
    """
        self._gqnew()
        if args:
            if args['gqnum'] in self._gqsdeclared:
                del (self._gqsdeclared[args['gqnum']])
            if args['gqnum'] in self._gqsstarted:
                del (self._gqsstarted[args['gqnum']])
            self._checkgqavailable()
        self.api.get('triggers.togglegroup')("gqcheck", False)
        self.api.get('triggers.togglegroup')("gqin", False)
        self.api.get('triggers.togglegroup')("gqrew", False)
        self.api.get('events.unregister')('aard_mobkill', self._mobkillevent)
        self.api.get('setting.change')('joined', 'default')
        self.api.get('setting.change')('maxkills', False)
        self.savestate()

    def _checkgqavailable(self):
        if len(self._gqsdeclared) > 0:
            self._raisegq('aard_gq_available')
        else:
            self._raisegq('aard_gq_notavailable')

    def savestate(self):
        """
    save states
    """
        AardwolfBasePlugin.savestate(self)
        self.gqinfo.sync()
Example #47
0
class Plugin(BasePlugin):
    """
  a class to manage logging
  """
    def __init__(self, *args, **kwargs):
        """
    init the class
    """
        BasePlugin.__init__(self, *args, **kwargs)

        self.canreload = False

        #print('log api.api', self.api.api)
        #print('log basepath', self.api.BASEPATH)
        self.savedir = os.path.join(self.api.BASEPATH, 'data', 'plugins',
                                    self.sname)
        self.logdir = os.path.join(self.api.BASEPATH, 'data', 'logs')
        #print('logdir', self.logdir)
        try:
            os.makedirs(self.savedir)
        except OSError:
            pass
        self.dtypes = {}
        self.sendtoclient = PersistentDict(
            os.path.join(self.savedir, 'sendtoclient.txt'), 'c')
        self.sendtoconsole = PersistentDict(
            os.path.join(self.savedir, 'sendtoconsole.txt'), 'c')
        self.sendtofile = PersistentDict(
            os.path.join(self.savedir, 'sendtofile.txt'), 'c')
        self.openlogs = {}
        self.currentlogs = {}
        self.colors = {}

        #self.sendtofile['default'] = {
        #'logdir':os.path.join(self.logdir, 'default'),
        #'file':'%a-%b-%d-%Y.log', 'timestamp':True
        #}

        self.colors['error'] = '@x136'

        self.api.get('api.add')('msg', self.api_msg)
        self.api.get('api.add')('adddtype', self.api_adddtype)
        self.api.get('api.add')('console', self.api_toggletoconsole)
        self.api.get('api.add')('file', self.api_toggletofile)
        self.api.get('api.add')('client', self.api_toggletoclient)

        self.api.get('log.adddtype')('default')
        self.api.get('log.adddtype')('frommud')
        self.api.get('log.adddtype')('startup')
        self.api.get('log.adddtype')('error')

        self.api.get('log.client')('error')
        self.api.get('log.console')('error')
        self.api.get('log.console')('default')
        self.api.get('log.console')('startup')

        #self.api.get('log.file')('default')

    # add a datatype to the log
    def api_adddtype(self, datatype):
        """  add a datatype
    @Ydatatype@w  = the datatype to add

    this function returns no values"""
        if datatype not in self.dtypes:
            self.dtypes[datatype] = True
            self.sendtoclient[datatype] = False
            self.sendtoconsole[datatype] = False

    def process_msg(self, msg, dtype, priority='primary'):
        """
    process a message
    """
        tstring = '%s - %-10s : ' % (time.strftime('%a %b %d %Y %H:%M:%S',
                                                   time.localtime()), dtype)
        if self.api.get('api.has')('colors.convertcolors') and \
            dtype in self.colors:
            tstring = self.api.get('colors.convertcolors')(self.colors[dtype] +
                                                           tstring)
        tmsg = [tstring]
        tmsg.append(msg)

        timestampmsg = ''.join(tmsg)
        nontimestamp = msg

        if dtype in self.sendtoclient and self.sendtoclient[dtype]:
            self.api.get('send.client')(timestampmsg)

        if dtype in self.sendtoconsole and self.sendtoconsole[dtype]:
            print(timestampmsg, file=sys.stderr)

        if priority == 'primary':
            if dtype in self.sendtofile and self.sendtofile[dtype]['file']:
                if self.api.get('api.has')('colors.stripansi'):
                    self.logtofile(
                        self.api.get('colors.stripansi')(nontimestamp), dtype)
                else:
                    self.logtofile(nontimestamp, dtype)

            if 'default' in self.sendtofile:
                self.logtofile(timestampmsg, 'default')

    # process a message, use send.msg instead for the api
    def api_msg(self, args, dtypedict=None):
        """  send a message
    @Ymsg@w        = This message to send
    @Ydatatype@w   = the type to toggle

    this function returns no values"""

        if not dtypedict:
            dtypedict = {'primary': 'default'}

        dtype = dtypedict['primary']
        if 'primary' in args:
            dtype = args['primary']

        self.process_msg(args['msg'], dtype)

        if 'secondary' in dtypedict:
            for i in dtypedict['secondary']:
                if i and i != 'None' \
                    and i != 'default':
                    self.process_msg(args['msg'], i, priority='secondary')

    # archive a log fle
    def archivelog(self, dtype):
        """
    archive the previous log
    """
        tfile = os.path.split(self.currentlogs[dtype])[-1]
        self.openlogs[self.currentlogs[dtype]].close()

        backupfile = os.path.join(self.logdir, dtype, tfile)
        backupzipfile = os.path.join(self.logdir, dtype, 'archive',
                                     tfile + '.zip')
        with zipfile.ZipFile(backupzipfile,
                             'w',
                             zipfile.ZIP_DEFLATED,
                             allowZip64=True) as myzip:
            myzip.write(backupfile, arcname=self.currentlogs[dtype])
        os.remove(backupfile)
        del self.openlogs[self.currentlogs[dtype]]

    # log something to a file
    def logtofile(self, msg, dtype):
        """
    send a message to a log file
    """
        #print('logging', dtype)
        tfile = os.path.join(
            self.logdir, dtype,
            time.strftime(self.sendtofile[dtype]['file'], time.localtime()))
        if not os.path.exists(os.path.join(self.logdir, dtype)):
            os.makedirs(os.path.join(self.logdir, dtype, 'archive'))
        if (dtype not in self.currentlogs) or \
           (dtype in self.currentlogs and not self.currentlogs[dtype]):
            self.currentlogs[dtype] = tfile
        elif tfile != self.currentlogs[dtype]:
            self.archivelog(dtype)
            self.currentlogs[dtype] = tfile
        if self.currentlogs[dtype] not in self.openlogs:
            self.openlogs[self.currentlogs[dtype]] = \
                            open(self.currentlogs[dtype], 'a')
        #print('logging to %s' % tfile)
        if self.sendtofile[dtype]['timestamp']:
            tstring = '%s : ' % \
                  (time.strftime(self.api.timestring, time.localtime()))
            msg = tstring + msg

        if self.api.get('api.has')('colors.stripansi'):
            self.openlogs[self.currentlogs[dtype]].write(
                self.api.get('colors.stripansi')(msg) + '\n')
        else:
            self.openlogs[self.currentlogs[dtype]].write(msg + '\n')
        self.openlogs[self.currentlogs[dtype]].flush()

    # toggle logging a datatype to the clients
    def api_toggletoclient(self, datatype, flag=True):
        """  toggle a data type to show to clients
    @Ydatatype@w  = the type to toggle, can be multiple (list)
    @Yflag@w      = True to send to clients, false otherwise (default: True)

    this function returns no values"""
        if datatype in self.sendtoclient and datatype != 'frommud':
            self.sendtoclient[datatype] = flag

        self.api.get('send.msg')('setting %s to log to client' % \
                          datatype)

        self.sendtoclient.sync()

    # toggle logging datatypes to the clients
    def cmd_client(self, args):
        """
    toggle datatypes shown to client
    """
        tmsg = []
        if len(args['datatype']) > 0:
            for i in args['datatype']:
                if i in self.sendtoclient and i != 'frommud':
                    self.sendtoclient[i] = not self.sendtoclient[i]
                    if self.sendtoclient[i]:
                        tmsg.append('sending %s to client' % i)
                    else:
                        tmsg.append('no longer sending %s to client' % i)

                elif i != 'frommud':
                    tmsg.append('Type %s does not exist' % i)
            self.sendtoclient.sync()
            return True, tmsg
        else:
            tmsg.append('Current types going to client')
            for i in self.sendtoclient:
                if self.sendtoclient[i]:
                    tmsg.append(i)
            return True, tmsg

    # toggle logging a datatype to the console
    def api_toggletoconsole(self, datatype, flag=True):
        """  toggle a data type to show to console
    @Ydatatype@w  = the type to toggle
    @Yflag@w      = True to send to console, false otherwise (default: True)

    this function returns no values"""
        if datatype in self.sendtoconsole and datatype != 'frommud':
            self.sendtoconsole[datatype] = flag

        self.api.get('send.msg')('setting %s to log to console' % \
                          datatype, self.sname)

        self.sendtoconsole.sync()

    # toggle logging datatypes to the console
    def cmd_console(self, args):
        """
    log datatypes to the console
    """
        tmsg = []
        if len(args['datatype']) > 0:
            for i in args['datatype']:
                if i in self.sendtoconsole and i != 'frommud':
                    self.sendtoconsole[i] = not self.sendtoconsole[i]
                    if self.sendtoconsole[i]:
                        tmsg.append('sending %s to console' % i)
                    else:
                        tmsg.append('no longer sending %s to console' % i)

                elif i != 'frommud':
                    tmsg.append('Type %s does not exist' % i)
            self.sendtoconsole.sync()
            return True, tmsg
        else:
            tmsg.append('Current types going to console')
            for i in self.sendtoconsole:
                if self.sendtoconsole[i]:
                    tmsg.append(i)
            return True, tmsg

    # toggle logging a datatype to a file
    def api_toggletofile(self, datatype, timestamp=True):
        """  toggle a data type to show to file
    @Ydatatype@w  = the type to toggle
    @Yflag@w      = True to send to file, false otherwise (default: True)

    this function returns no values"""
        if datatype in self.sendtofile:
            del self.sendtofile[datatype]
        else:
            tfile = '%a-%b-%d-%Y.log'

            self.sendtofile[datatype] = {'file': tfile, 'timestamp': timestamp}
            self.api.get('send.msg')('setting %s to log to %s' % \
                            (datatype, self.sendtofile[datatype]['file']),
                                     self.sname)
            self.sendtofile.sync()

    # toggle a datatype to log to a file
    def cmd_file(self, args):
        """
    toggle a datatype to log to a file
    """
        tmsg = []
        timestamp = True
        if args['datatype'] != 'list':
            dtype = args['datatype']
            timestamp = args['notimestamp']

            if dtype in self.sendtofile:
                del self.sendtofile[dtype]
                tmsg.append('removing %s from logging' % dtype)
            else:
                tfile = '%a-%b-%d-%Y.log'

                self.sendtofile[dtype] = {
                    'file': tfile,
                    'logdir': os.path.join(self.logdir, dtype),
                    'timestamp': timestamp
                }
                tmsg.append('setting %s to log to %s' % \
                                (dtype, self.sendtofile[dtype]['file']))
                self.sendtofile.sync()
            return True, tmsg
        else:
            tmsg.append('Current types going to file')
            for i in self.sendtofile:
                if self.sendtofile[i]:
                    tmsg.append('%s - %s - %s' % \
                       (i, self.sendtofile[i]['file'], self.sendtofile[i]['timestamp']))
            return True, tmsg

    # archive a datatype
    def cmd_archive(self, args):
        """
    archive a datatype
    """
        tmsg = []
        if len(args) > 0:
            for i in args:
                if i in self.dtypes:
                    self.archivelog(i)
                else:
                    tmsg.append('%s does not exist' % i)
            return True, tmsg
        else:
            tmsg = ['Please specifiy a datatype to archive']
            return False, tmsg

    # show all types
    def cmd_types(self, args):
        """
    list data types
    """
        tmsg = []
        tmsg.append('Data Types')
        tmsg.append('-' * 30)
        match = args['match']
        tkeys = self.dtypes.keys()
        tkeys.sort()
        for i in tkeys:
            if not match or match in i:
                tmsg.append(i)
        return True, tmsg

    def logmud(self, args):
        """
    log all data from the mud
    """
        if 'frommud' in self.sendtofile and self.sendtofile['frommud']['file']:
            if args['eventname'] == 'from_mud_event':
                data = args['noansi']
            elif args['eventname'] == 'to_mud_event':
                data = 'tomud: ' + args['data'].strip()
            self.logtofile(data, 'frommud')
        return args

    def load(self):
        """
    load external stuff
    """
        BasePlugin.load(self)

        #print('log api before adding', self.api.api)

        #print('log api after adding', self.api.api)
        self.api.get('events.register')('from_mud_event', self.logmud)
        self.api.get('events.register')('to_mud_event', self.logmud)

        parser = argparse.ArgumentParser(add_help=False,
                                         description="""\
      toggle datatypes to clients

      if no arguments, data types that are currenty sent to clients will be listed"""
                                         )
        parser.add_argument('datatype',
                            help='a list of datatypes to toggle',
                            default=[],
                            nargs='*')
        self.api.get('commands.add')('client',
                                     self.cmd_client,
                                     lname='Logger',
                                     parser=parser)

        parser = argparse.ArgumentParser(add_help=False,
                                         description="""\
      toggle datatype to log to a file

      the file will be located in the data/logs/<dtype> directory

      the filename for the log will be <date>.log
          Example: Tue-Feb-26-2013.log

      if no arguments, types that are sent to file will be listed""")
        parser.add_argument('datatype',
                            help='the datatype to toggle',
                            default='list',
                            nargs='?')
        parser.add_argument("-n",
                            "--notimestamp",
                            help="do not log to file with a timestamp",
                            action="store_false")
        self.api.get('commands.add')('file',
                                     self.cmd_file,
                                     lname='Logger',
                                     parser=parser)

        parser = argparse.ArgumentParser(add_help=False,
                                         description="""\
      toggle datatypes to the console

      if no arguments, data types that are currenty sent to the console will be listed"""
                                         )
        parser.add_argument('datatype',
                            help='a list of datatypes to toggle',
                            default=[],
                            nargs='*')
        self.api.get('commands.add')('console',
                                     self.cmd_console,
                                     lname='Logger',
                                     parser=parser)

        parser = argparse.ArgumentParser(add_help=False,
                                         description="list all datatypes")
        parser.add_argument(
            'match',
            help='only list datatypes that have this argument in their name',
            default='',
            nargs='?')
        self.api.get('commands.add')('types',
                                     self.cmd_types,
                                     lname='Logger',
                                     parser=parser)
Example #48
0
class Plugin(AardwolfBasePlugin):
  """
  a plugin to handle aardwolf quest events
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    AardwolfBasePlugin.__init__(self, *args, **kwargs)
    self.savequestfile = os.path.join(self.savedir, 'quest.txt')
    self.queststuff = PersistentDict(self.savequestfile, 'c')

  def load(self):
    """
    load the plugins
    """
    AardwolfBasePlugin.load(self)

    self.api('events.register')('GMCP:comm.quest', self.quest)

    self.api('events.register')('plugin_%s_savestate' % self.sname, self._savestate)


  def resetquest(self):
    """
    reset the quest info
    """
    self.queststuff.clear()
    self.queststuff['finishtime'] = -1
    self.queststuff['starttime'] = time.time()
    self.queststuff['killedtime'] = -1
    self.queststuff['mobname'] = ''
    self.queststuff['mobarea'] = ''
    self.queststuff['mobroom'] = ''
    self.queststuff['level'] = self.api('aardu.getactuallevel')(
        self.api('GMCP.getv')('char.status.level'))
    self.queststuff['failed'] = 0

  def quest(self, args):
    """
    process the quest event
    """
    questi = args['data']
    self.api('send.msg')('quest: %s' % questi)
    if questi['action'] == 'ready':
      self.api('events.eraise')('aard_quest_ready', {})
    elif questi['action'] == 'start':
      self.resetquest()
      self.queststuff['mobname'] = questi['targ']
      self.queststuff['mobarea'] = questi['area']
      self.queststuff['mobroom'] = questi['room']
      self.queststuff['stimer'] = questi['timer']
      self.api('events.eraise')('aard_quest_start', self.queststuff)
    elif questi['action'] == 'killed':
      self.queststuff['killedtime'] = time.time()
      self.api('events.eraise')('aard_quest_killed', self.queststuff)
    elif questi['action'] == 'comp':
      self.queststuff['finishtime'] = time.time()
      self.queststuff.update(questi)
      self.api('events.eraise')('aard_quest_comp',
                                copy.deepcopy(self.queststuff))
    elif questi['action'] == 'fail' or questi['action'] == 'timeout':
      self.queststuff['finishtime'] = time.time()
      self.queststuff['failed'] = 1
      self.api('events.eraise')('aard_quest_failed',
                                copy.deepcopy(self.queststuff))
    elif questi['action'] == 'status':
      self.api('events.eraise')('aard_quest_status', questi)
    elif questi['action'] == 'reset':
      #reset the timer to 60 seconds
      #when_required = os.time() + (stuff.timer * 60)
      #update_timer()
      self.api('events.eraise')('aard_quest_reset', {})
    self.queststuff.sync()

  def _savestate(self, _=None):
    """
    save states
    """
    self.queststuff.sync()
Example #49
0
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)
Example #50
0
class Plugin(BasePlugin):
  """
  a class to manage logging
  """
  def __init__(self, *args, **kwargs):
    """
    init the class
    """
    BasePlugin.__init__(self, *args, **kwargs)

    self.canreload = False

    #print('log api.api', self.api.api)
    #print('log basepath', self.api.BASEPATH)
    self.savedir = os.path.join(self.api.BASEPATH, 'data',
                                'plugins', self.sname)
    self.logdir = os.path.join(self.api.BASEPATH, 'data', 'logs')
    #print('logdir', self.logdir)
    try:
      os.makedirs(self.savedir)
    except OSError:
      pass
    self.dtypes = {}
    self.sendtoclient = PersistentDict(
        os.path.join(self.savedir, 'sendtoclient.txt'),
        'c')
    self.sendtoconsole = PersistentDict(
        os.path.join(self.savedir, 'sendtoconsole.txt'),
        'c')
    self.sendtofile = PersistentDict(
        os.path.join(self.savedir, 'sendtofile.txt'),
        'c')
    self.currentlogs = {}
    self.colors = {}

    self.filenametemplate = '%a-%b-%d-%Y.log'
    #self.sendtofile['default'] = {
                                #'logdir':os.path.join(self.logdir, 'default'),
                                #'file':'%a-%b-%d-%Y.log', 'timestamp':True
                                  #}

    self.colors['error'] = '@x136'

    self.api('api.add')('msg', self.api_msg)
    self.api('api.add')('adddtype', self.api_adddtype)
    self.api('api.add')('console', self.api_toggletoconsole)
    self.api('api.add')('file', self.api_toggletofile)
    self.api('api.add')('client', self.api_toggletoclient)
    self.api('api.add')('writefile', self.api_writefile)

    # add some default datatypes
    self.api('log.adddtype')('default')
    self.api('log.adddtype')('frommud')
    self.api('log.adddtype')('startup')
    self.api('log.adddtype')('shutdown')
    self.api('log.adddtype')('error')

    # log some datatypes by default
    self.api('log.client')('error')
    self.api('log.console')('error')
    self.api('log.console')('default')
    self.api('log.console')('startup')
    self.api('log.console')('shutdown')

  def api_writefile(self, dtype, data, stripcolor=False):
    """
    write directly to a file
    """
    if dtype not in self.sendtofile:
      self.api('%s.file' % self.sname)(dtype)

    if stripcolor and self.api('api.has')('colors.stripansi'):
      data = self.api('colors.stripansi')(data)

    tfile = os.path.join(self.logdir, dtype,
                          time.strftime(self.sendtofile[dtype]['file'],
                                        time.localtime()))
    if not os.path.exists(os.path.join(self.logdir, dtype)):
      os.makedirs(os.path.join(self.logdir, dtype, 'archive'))
    if (dtype not in self.currentlogs) or \
      (dtype in self.currentlogs and not self.currentlogs[dtype]):
      self.currentlogs[dtype] = {}
      self.currentlogs[dtype]['filename'] = tfile
      self.currentlogs[dtype]['fhandle'] = None
    elif tfile != self.currentlogs[dtype]['filename']:
      self.archivelog(dtype)
      self.currentlogs[dtype]['filename'] = tfile

    if not self.currentlogs[dtype]['fhandle']:
      self.currentlogs[dtype]['fhandle'] = \
                      open(self.currentlogs[dtype]['filename'], 'a')

    if self.sendtofile[dtype]['timestamp']:
      tstring = '%s : ' % \
            (time.strftime(self.api.timestring, time.localtime()))
      data = tstring + data

    if self.api('api.has')('colors.stripansi'):
      self.currentlogs[dtype]['fhandle'].write(
          self.api('colors.stripansi')(data) + '\n')
    else:
      self.currentlogs[dtype]['fhandle'].write(data + '\n')
    self.currentlogs[dtype]['fhandle'].flush()
    return True

  # add a datatype to the log
  def api_adddtype(self, datatype):
    """  add a datatype
    @Ydatatype@w  = the datatype to add

    this function returns no values"""
    if datatype not in self.dtypes:
      self.dtypes[datatype] = True
      self.sendtoclient[datatype] = False
      self.sendtoconsole[datatype] = False

  # process a message, use send.msg instead for the api
  def api_msg(self, msg, tags=None):
    """  send a message
    @Ymsg@w        = This message to send
    @Ydatatype@w   = the type to toggle

    this function returns no values"""
    senttoconsole = False
    senttoclient = False

    ttime = time.strftime(self.api.timestring, time.localtime())

    self.logtofile(msg, 'default')

    for dtag in tags:
      if dtag and dtag != 'None' \
            and dtag != 'default':

        tstring = '%s - %-10s : ' % (ttime, dtag)
        timestampmsg = tstring + msg

        self.logtofile(msg, dtag)

        if self.api('api.has')('colors.convertcolors') and \
            dtag in self.colors:
          timestampmsg = self.api('colors.convertcolors')(
              self.colors[dtag] + timestampmsg)

        if dtag in self.sendtoclient and self.sendtoclient[dtag] and not senttoclient:
          self.api('send.client')(timestampmsg)
          senttoclient = True

        if dtag in self.sendtoconsole and self.sendtoconsole[dtag] and not senttoconsole:
          print(timestampmsg, file=sys.stderr)
          senttoconsole = True

  # archive a log fle
  def archivelog(self, dtype):
    """
    archive the previous log
    """
    tfile = os.path.split(self.currentlogs[dtype]['filename'])[-1]
    self.currentlogs[dtype]['fhandle'].close()
    self.currentlogs[dtype]['fhandle'] = None

    backupfile = os.path.join(self.logdir, dtype,
                              tfile)
    backupzipfile = os.path.join(self.logdir, dtype, 'archive',
                                 tfile + '.zip')
    with zipfile.ZipFile(backupzipfile, 'w', zipfile.ZIP_DEFLATED,
                         allowZip64=True) as myzip:
      myzip.write(backupfile, arcname=self.currentlogs[dtype]['filename'])
    os.remove(backupfile)

  # log something to a file
  def logtofile(self, msg, dtype, stripcolor=True):
    """
    send a message to a log file
    """
    #print('logging', dtype)
    if dtype in self.sendtofile and self.sendtofile[dtype]['file']:
      return self.api('%s.writefile'% self.sname)(dtype, msg, stripcolor)

    return False

  # toggle logging a datatype to the clients
  def api_toggletoclient(self, datatype, flag=True):
    """  toggle a data type to show to clients
    @Ydatatype@w  = the type to toggle, can be multiple (list)
    @Yflag@w      = True to send to clients, false otherwise (default: True)

    this function returns no values"""
    if datatype in self.sendtoclient and datatype != 'frommud':
      self.sendtoclient[datatype] = flag

    self.api('send.msg')('setting %s to log to client' % \
                      datatype)

    self.sendtoclient.sync()

  # toggle logging datatypes to the clients
  def cmd_client(self, args):
    """
    toggle datatypes shown to client
    """
    tmsg = []
    if args['datatype']:
      for i in args['datatype']:
        if i in self.sendtoclient and i != 'frommud':
          self.sendtoclient[i] = not self.sendtoclient[i]
          if self.sendtoclient[i]:
            tmsg.append('sending %s to client' % i)
          else:
            tmsg.append('no longer sending %s to client' % i)

        elif i != 'frommud':
          tmsg.append('Type %s does not exist' % i)
      self.sendtoclient.sync()
      return True, tmsg

    tmsg.append('Current types going to client')
    for i in self.sendtoclient:
      if self.sendtoclient[i]:
        tmsg.append(i)
    return True, tmsg

  # toggle logging a datatype to the console
  def api_toggletoconsole(self, datatype, flag=True):
    """  toggle a data type to show to console
    @Ydatatype@w  = the type to toggle
    @Yflag@w      = True to send to console, false otherwise (default: True)

    this function returns no values"""
    if datatype in self.sendtoconsole and datatype != 'frommud':
      self.sendtoconsole[datatype] = flag

    self.api('send.msg')('setting %s to log to console' % \
                      datatype, self.sname)

    self.sendtoconsole.sync()

  # toggle logging datatypes to the console
  def cmd_console(self, args):
    """
    log datatypes to the console
    """
    tmsg = []
    if args['datatype']:
      for i in args['datatype']:
        if i in self.sendtoconsole and i != 'frommud':
          self.sendtoconsole[i] = not self.sendtoconsole[i]
          if self.sendtoconsole[i]:
            tmsg.append('sending %s to console' % i)
          else:
            tmsg.append('no longer sending %s to console' % i)

        elif i != 'frommud':
          tmsg.append('Type %s does not exist' % i)
      self.sendtoconsole.sync()
      return True, tmsg

    tmsg.append('Current types going to console')
    for i in self.sendtoconsole:
      if self.sendtoconsole[i]:
        tmsg.append(i)
    return True, tmsg

  # toggle logging a datatype to a file
  def api_toggletofile(self, datatype, timestamp=True):
    """  toggle a data type to show to file
    @Ydatatype@w  = the type to toggle
    @Yflag@w      = True to send to file, false otherwise (default: True)

    this function returns no values"""
    if datatype in self.sendtofile:
      if self.currentlogs[datatype]['fhandle']:
        self.currentlogs[datatype]['fhandle'].close()
        self.currentlogs[datatype]['fhandle'] = None
      del self.sendtofile[datatype]
    else:
      self.sendtofile[datatype] = {'file':self.filenametemplate,
                                   'timestamp':timestamp}
      self.api('send.msg')('setting %s to log to %s' % \
                      (datatype, self.sendtofile[datatype]['file']),
                           self.sname)
    self.sendtofile.sync()

  # toggle a datatype to log to a file
  def cmd_file(self, args):
    """
    toggle a datatype to log to a file
    """
    tmsg = []
    timestamp = True
    if args['datatype'] != 'list':
      dtype = args['datatype']
      timestamp = args['notimestamp']

      if dtype in self.sendtofile:
        if dtype in self.currentlogs:
          self.currentlogs[dtype]['fhandle'].close()
          self.currentlogs[dtype]['fhandle'] = None
        del self.sendtofile[dtype]
        tmsg.append('removing %s from logging' % dtype)
      else:
        self.sendtofile[dtype] = {'file':self.filenametemplate,
                                  'logdir':os.path.join(self.logdir, dtype),
                                  'timestamp':timestamp}
        tmsg.append('setting %s to log to %s' % \
                        (dtype, self.sendtofile[dtype]['file']))
        self.sendtofile.sync()
      return True, tmsg
    else:
      tmsg.append('Current types going to file')
      for i in self.sendtofile:
        if self.sendtofile[i]:
          tmsg.append('%s - %s - %s' % \
             (i, self.sendtofile[i]['file'], self.sendtofile[i]['timestamp']))
      return True, tmsg

  # archive a datatype
  def cmd_archive(self, args):
    """
    archive a datatype
    """
    tmsg = []
    if args:
      for i in args:
        if i in self.dtypes:
          self.archivelog(i)
        else:
          tmsg.append('%s does not exist' % i)
      return True, tmsg

    tmsg = ['Please specifiy a datatype to archive']
    return False, tmsg

  # show all types
  def cmd_types(self, args):
    """
    list data types
    """
    tmsg = []
    tmsg.append('Data Types')
    tmsg.append('-' *  30)
    match = args['match']
    tkeys = self.dtypes.keys()
    tkeys.sort()
    for i in tkeys:
      if not match or match in i:
        tmsg.append(i)
    return True, tmsg

  def logmud(self, args):
    """
    log all data from the mud
    """
    if 'frommud' in self.sendtofile and self.sendtofile['frommud']['file']:
      if args['eventname'] == 'from_mud_event':
        data = args['noansi']
      elif args['eventname'] == 'to_mud_event':
        data = 'tomud: ' + args['data'].strip()
      self.logtofile(data, 'frommud', stripcolor=False)
    return args

  def load(self):
    """
    load external stuff
    """
    BasePlugin.load(self)

    #print('log api before adding', self.api.api)

    #print('log api after adding', self.api.api)
    self.api('events.register')('from_mud_event', self.logmud)
    self.api('events.register')('to_mud_event', self.logmud)
    self.api('events.register')('plugin_%s_savestate' % self.sname, self._savestate)

    parser = argp.ArgumentParser(add_help=False,
                                 description="""\
      toggle datatypes to clients

      if no arguments, data types that are currenty sent to clients will be listed""")
    parser.add_argument('datatype',
                        help='a list of datatypes to toggle',
                        default=[],
                        nargs='*')
    self.api('commands.add')('client',
                             self.cmd_client,
                             lname='Logger',
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description="""\
      toggle datatype to log to a file

      the file will be located in the data/logs/<dtype> directory

      the filename for the log will be <date>.log
          Example: Tue-Feb-26-2013.log

      if no arguments, types that are sent to file will be listed""")
    parser.add_argument('datatype',
                        help='the datatype to toggle',
                        default='list',
                        nargs='?')
    parser.add_argument("-n",
                        "--notimestamp",
                        help="do not log to file with a timestamp",
                        action="store_false")
    self.api('commands.add')('file',
                             self.cmd_file,
                             lname='Logger',
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description="""\
      toggle datatypes to the console

      if no arguments, data types that are currenty sent to the console will be listed""")
    parser.add_argument('datatype',
                        help='a list of datatypes to toggle',
                        default=[],
                        nargs='*')
    self.api('commands.add')('console',
                             self.cmd_console,
                             lname='Logger',
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description="list all datatypes")
    parser.add_argument('match',
                        help='only list datatypes that have this argument in their name',
                        default='',
                        nargs='?')
    self.api('commands.add')('types',
                             self.cmd_types,
                             lname='Logger',
                             parser=parser)

    #print('log loaded')

  def _savestate(self, _=None):
    """
    save items not covered by baseplugin class
    """
    self.sendtoclient.sync()
    self.sendtofile.sync()
    self.sendtoconsole.sync()
Example #51
0
class Plugin(AardwolfBasePlugin):
  """
  a plugin to handle aardwolf cp events
  """
  def __init__(self, *args, **kwargs):
    """
    initialize the instance
    """
    AardwolfBasePlugin.__init__(self, *args, **kwargs)
    self.savecpfile = os.path.join(self.savedir, 'cp.txt')
    self.cpinfo = PersistentDict(self.savecpfile, 'c')
    self.mobsleft = []
    self.cpinfotimer = {}
    self.nextdeath = False

    self.api('dependency.add')('cmdq')
    self.api('api.add')('oncp', self.api_oncp)
    self.api('api.add')('mobsleft', self.api_cpmobsleft)

  def load(self):
    """
    load the plugins
    """
    AardwolfBasePlugin.load(self)

    self.api('cmdq.addcmdtype')('cpcheck', 'campaign check', "^campaign check$",
                                beforef=self.cpcheckbefore, afterf=self.cpcheckafter)

    parser = argp.ArgumentParser(add_help=False,
                                 description='show cp info')
    self.api('commands.add')('show', self.cmd_show,
                             parser=parser)

    parser = argp.ArgumentParser(add_help=False,
                                 description='refresh cp info')
    self.api('commands.add')('refresh', self.cmd_refresh,
                             parser=parser)

    self.api('watch.add')('cp_check',
                          '^(cp|campa|campai|campaig|campaign) (c|ch|che|chec|check)$')

    self.api('triggers.add')('cpnew',
                             "^Commander Barcett tells you " \
                               "'Type 'campaign info' to see what you must kill.'$")
    self.api('triggers.add')('cpnone',
                             "^You are not currently on a campaign.$",
                             enabled=False, group='cpcheck', omit=True)
    self.api('triggers.add')('cptime',
                             "^You have (?P<time>.*) to finish this campaign.$",
                             enabled=False, group='cpcheck', omit=True)
    self.api('triggers.add')('cpmob',
                             r"^You still have to kill \* (?P<mob>.*) " \
                               r"\((?P<location>.*?)(?P<dead> - Dead|)\)$",
                             enabled=False, group='cpcheck', omit=True)
    self.api('triggers.add')('cpscramble',
                             "Note: One or more target names in this " \
                               "campaign might be slightly scrambled.$",
                             enabled=False, group='cpcheck', omit=True)
    self.api('triggers.add')('cpneedtolevel',
                             "^You will have to level before you" \
                               " can go on another campaign.$",
                             enabled=False,
                             group='cpin')
    self.api('triggers.add')('cpcantake',
                             "^You may take a campaign at this level.$",
                             enabled=False,
                             group='cpin')
    self.api('triggers.add')('cpshnext',
                             "^You cannot take another campaign for (?P<time>.*).$",
                             enabled=False,
                             group='cpin')
    self.api('triggers.add')('cpmobdead',
                             "^Congratulations, that was one of your CAMPAIGN mobs!$",
                             enabled=False,
                             group='cpin')
    self.api('triggers.add')('cpcomplete',
                             "^CONGRATULATIONS! You have completed your campaign.$",
                             enabled=False,
                             group='cpin')
    self.api('triggers.add')('cpclear',
                             "^Campaign cleared.$",
                             enabled=False,
                             group='cpin')
    self.api('triggers.add')('cpreward',
                             r"^\s*Reward of (?P<amount>\d+) (?P<type>.+) .+ added.$",
                             enabled=False,
                             group='cprew',
                             argtypes={'amount':int})
    self.api('triggers.add')('cpcompdone',
                             "^--------------------------" \
                               "------------------------------------$",
                             enabled=False,
                             group='cpdone')

    self.api('events.register')('trigger_cpnew', self._cpnew)
    self.api('events.register')('trigger_cpnone', self._cpnone)
    self.api('events.register')('trigger_cptime', self._cptime)
    #self.api('events.register')('watch_cp_check', self._cpcheckcmd)
    self.api('events.register')('trigger_cpmob', self._cpmob)
    self.api('events.register')('trigger_cpneedtolevel',
                                self._cpneedtolevel)
    self.api('events.register')('trigger_cpcantake', self._cpcantake)
    self.api('events.register')('trigger_cpshnext', self._cpshnext)
    self.api('events.register')('trigger_cpmobdead', self._cpmobdead)
    self.api('events.register')('trigger_cpcomplete', self._cpcomplete)
    self.api('events.register')('trigger_cpclear', self._cpclear)
    self.api('events.register')('trigger_cpreward', self._cpreward)
    self.api('events.register')('trigger_cpcompdone', self._cpcompdone)

    self.api('events.register')('plugin_%s_savestate' % self.sname, self._savestate)

  def api_oncp(self):
    """
    return if we are on a cp
    """
    return self.cpinfo['oncp']

  def api_cpmobsleft(self):
    """
    return the list of cp mobs left
    """
    return copy.copy(self.mobsleft)

  def cmd_show(self, _=None):
    """
    show the cp mobs
    """
    msg = []
    if self.cpinfo['oncp']:
      msg.append('Mobs left:')
      msg.append('%-40s %s' % ('Mob Name', 'Area/Room'))
      msg.append('@G' + '-' * 60)
      for i in self.mobsleft:
        color = '@w'
        if i['mobdead']:
          color = '@R'
        msg.append('%s%-40s %s' % (color, i['name'], i['location']))
    else:
      msg.append('You are not on a cp')

    return True, msg

  def cmd_refresh(self, _=None):
    """
    cmd to refresh cp info
    """
    msg = []
    if self.cpinfo['oncp']:
      msg.append('Refreshing cp mobs')
      self.api('cmdq.addtoqueue')('cpcheck', '')
    else:
      msg.append('You are not on a cp')

    return True, msg

  def cpcheckbefore(self):
    """
    function to run before send the command
    """
    self.mobsleft = []
    self.cpinfotimer = {}
    self.api('triggers.togglegroup')('cpcheck', True)
    self.api('cmdq.cmdstart')('cpcheck')

  def cpcheckafter(self):
    """
    function to run after the command is finished
    """
    self.api('triggers.togglegroup')("cpin", True)
    self.api('triggers.togglegroup')('cpcheck', False)

  def afterfirstactive(self, _=None):
    """
    do something on connect
    """
    AardwolfBasePlugin.afterfirstactive(self)
    self.api('cmdq.addtoqueue')('cpcheck', '')

  def _cpreset(self):
    """
    reset the cp
    """
    self.cpinfo.clear()
    self.cpinfo['mobs'] = {}
    self.cpinfo['trains'] = 0
    self.cpinfo['pracs'] = 0
    self.cpinfo['gold'] = 0
    self.cpinfo['tp'] = 0
    self.cpinfo['qp'] = 0
    self.cpinfo['bonusqp'] = 0
    self.cpinfo['failed'] = 0
    self.cpinfo['level'] = self.api('aardu.getactuallevel')(
        self.api('GMCP.getv')('char.status.level'))
    self.cpinfo['starttime'] = time.time()
    self.cpinfo['finishtime'] = 0
    self.cpinfo['oncp'] = True
    self.cpinfo['cantake'] = False
    self.cpinfo['shtime'] = None
    self.savestate()

  def _cpnew(self, args=None):
    """
    handle a new cp
    """
    self.api('send.msg')('cpnew: %s' % args)
    self._cpreset()
    self.api('cmdq.addtoqueue')('cpcheck', '')

  def _cpnone(self, _=None):
    """
    handle a none cp
    """
    self.api('send.msg')('cpnone')
    self.cpinfo['oncp'] = False
    self.savestate()
    self.api('triggers.togglegroup')('cpcheck', False)
    self.api('triggers.togglegroup')('cpin', False)
    self.api('triggers.togglegroup')('cprew', False)
    self.api('triggers.togglegroup')('cpdone', False)
    self.cpinfotimer = {}
    self.api('cmdq.cmdfinish')('cpcheck')

  def _cptime(self, _=None):
    """
    handle cp time
    """
    self.api('send.msg')('handling cp time')
    self.api('send.msg')('%s' % self.cpinfo)
    if not self.cpinfo['mobs']:
      self.api('send.msg')('copying mobsleft')
      self.cpinfo['mobs'] = self.mobsleft[:]
      self.api('events.eraise')('aard_cp_mobsorig',
                                copy.deepcopy({'mobsleft':self.mobsleft}))
      self.savestate()

    self.api('send.msg')('raising aard_cp_mobsleft %s' % self.mobsleft)
    self.api('events.eraise')('aard_cp_mobsleft',
                              copy.deepcopy({'mobsleft':self.mobsleft}))

    self.api('cmdq.cmdfinish')('cpcheck')

  def _cpneedtolevel(self, _=None):
    """
    handle cpneedtolevel
    """
    self.cpinfo['cantake'] = False
    self.savestate()

  def _cpcantake(self, _=None):
    """
    handle cpcantake
    """
    self.cpinfo['cantake'] = True
    self.savestate()

  def _cpshnext(self, args=None):
    """
    handle cpshnext
    """
    self.cpinfo['shtime'] = args['time']
    self.savestate()

  def _cpmob(self, args=None):
    """
    handle cpmob
    """
    name = args['mob']
    mobdead = self.api('utils.verify')(args['dead'], bool)
    location = args['location']

    if not name or not location:
      self.api('send.msg')("error parsing line: %s" % args['line'])
    else:
      self.mobsleft.append({'name':name,
                            'nocolorname':self.api('colors.stripansi')(name),
                            'location':location, 'mobdead':mobdead})

  def _cpmobdead(self, _=None):
    """
    handle cpmobdead
    """
    self.api('events.register')('aard_mobkill', self._mobkillevent)
    #self.api('send.execute')("cp check")

  def _cpcomplete(self, _=None):
    """
    handle cpcomplete
    """
    self.api('triggers.togglegroup')('cprew', True)
    self.cpinfo['finishtime'] = time.time()
    self.cpinfo['oncp'] = False
    self.savestate()

  def _cpreward(self, args=None):
    """
    handle cpreward
    """
    rtype = args['type']
    ramount = int(args['amount'])
    rewardt = self.api('aardu.rewardtable')()
    self.cpinfo[rewardt[rtype]] = ramount
    self.savestate()
    self.api('triggers.togglegroup')('cpdone', True)

  def _cpcompdone(self, _=None):
    """
    handle cpcompdone
    """
    self.api('events.register')('trigger_all', self._triggerall)

  def _triggerall(self, args=None):
    """
    check to see if we have the bonus qp message
    """
    if 'first campaign completed today' in args['line']:
      mat = re.match(r'^You receive (?P<bonus>\d*) quest points bonus ' \
                        r'for your first campaign completed today.$',
                     args['line'])
      self.cpinfo['bonusqp'] = int(mat.groupdict()['bonus'])
      self.api('events.unregister')('trigger_all', self._triggerall)
      self.api('events.eraise')('aard_cp_comp', copy.deepcopy(self.cpinfo))
    elif re.match(r"^You have completed (\d*) campaigns today.$", args['line']):
      self.api('events.unregister')('trigger_all', self._triggerall)
      self.api('events.eraise')('aard_cp_comp', copy.deepcopy(self.cpinfo))

  def _cpclear(self, _=None):
    """
    handle cpclear
    """
    self.cpinfo['failed'] = 1
    self.api('events.eraise')('aard_cp_failed', copy.deepcopy(self.cpinfo))
    self._cpnone()

  def _cpcheckcmd(self, args=None):
    """
    handle when we get a cp check
    """
    self.mobsleft = []
    self.cpinfotimer = {}
    self.api('triggers.togglegroup')('cpcheck', True)
    return args

  def _mobkillevent(self, args):
    """
    this will be registered to the mobkill hook
    """
    self.api('send.msg')('checking kill %s' % args['name'])
    self.api('events.unregister')('aard_mobkill', self._mobkillevent)

    found = False
    removeitem = None
    for i in range(len(self.mobsleft)):
      tmob = self.mobsleft[i]
      if tmob['name'] == args['name']:
        self.api('send.msg')('found %s' % tmob['name'])
        found = True
        removeitem = i

    if removeitem:
      del self.mobsleft[removeitem]

    if found:
      self.api('events.eraise')('aard_cp_mobsleft',
                                copy.deepcopy({'mobsleft':self.mobsleft}))
    else:
      self.api('send.msg')("BP CP: could not find mob: %s" % args['name'])
      self.api('cmdq.addtoqueue')('cpcheck', '')

  def _savestate(self, _=None):
    """
    save states
    """
    self.cpinfo.sync()
Example #52
0
class Plugin(AardwolfBasePlugin):
    """
  a plugin that does spellups
  """
    def __init__(self, *args, **kwargs):
        """
    initialize the instance
    """
        AardwolfBasePlugin.__init__(self, *args, **kwargs)
        self.spellupfile = os.path.join(self.savedir, 'spellups.txt')
        self.spellups = PersistentDict(self.spellupfile, 'c')

        self.api('dependency.add')('aardwolf.skills')
        self.api('dependency.add')('aardwolf.move')

        self.initspellups()

        self.lastmana = -1
        self.lastmoves = -1

    def load(self):
        """
    load the plugins
    """
        AardwolfBasePlugin.load(self)

        self.api('setting.add')('enabled', True, bool,
                                'auto spellup is enabled')
        self.api('setting.add')('waiting',
                                -1,
                                int,
                                'the spell that was just cast',
                                readonly=True)
        self.api('setting.add')('nocast',
                                False,
                                bool,
                                'in a nocast room',
                                readonly=True)
        self.api('setting.add')('nomoves',
                                False,
                                bool,
                                'need more moves',
                                readonly=True)
        self.api('setting.add')('nomana',
                                False,
                                bool,
                                'need more mana',
                                readonly=True)
        self.api('setting.add')('nocastrooms', {},
                                dict,
                                'list of nocast rooms',
                                readonly=True)
        self.api('setting.add')('currentroom',
                                -1,
                                int,
                                'the current room',
                                readonly=True)

        parser = argp.ArgumentParser(
            add_help=False, description='add a spellup to the self list')
        parser.add_argument(
            'spell',
            help='the spells to add, use \'all\' to add all practiced spellups',
            default=[],
            nargs='*')
        parser.add_argument(
            '-o',
            "--override",
            help="add even if the spell is not flagged as a spellup by the mud",
            action="store_true")
        self.api('commands.add')('add',
                                 self.cmd_sadd,
                                 parser=parser,
                                 group='Spellups on Self')

        parser = argp.ArgumentParser(add_help=False,
                                     description='list spellups for self')
        parser.add_argument(
            'match',
            help='list only spellups that have this argument in them',
            default='',
            nargs='?')
        self.api('commands.add')('list',
                                 self.cmd_slist,
                                 parser=parser,
                                 group='Spellups on Self')

        parser = argp.ArgumentParser(
            add_help=False, description='remove a spellup from the self list')
        parser.add_argument(
            'spell',
            help='the spells to remove, use \'all\' to remove all spellups',
            default=[],
            nargs='*')
        self.api('commands.add')('rem',
                                 self.cmd_srem,
                                 parser=parser,
                                 group='Spellups on Self')

        parser = argp.ArgumentParser(add_help=False,
                                     description='enable spellups on self')
        parser.add_argument(
            'spell',
            help='the spells to enable, use \'all\' to enable all spellups',
            default=[],
            nargs='*')
        self.api('commands.add')('en',
                                 self.cmd_en,
                                 parser=parser,
                                 group='Spellups on Self')

        parser = argp.ArgumentParser(add_help=False,
                                     description='disable spells on self')
        parser.add_argument(
            'spell',
            help='the spells to disable, use \'all\' to disable all spellups',
            default=[],
            nargs='*')
        self.api('commands.add')('dis',
                                 self.cmd_dis,
                                 shelp='disable a spellup on self',
                                 parser=parser,
                                 group='Spellups on Self')

        self.api('commands.add')('check',
                                 self.cmd_check,
                                 shelp='check data status for casting',
                                 group='Spellups on Self')

        self.api('events.register')('GMCP:char.vitals', self._charvitals)
        self.api('events.register')('GMCP:char.status', self._charstatus)
        self.api('events.register')('moved_room', self._moved)
        self.api('events.register')('skill_fail', self._skillfail)
        self.api('events.register')('aard_skill_affon', self._affon)
        self.api('events.register')('aard_skill_affoff', self._affoff)
        self.api('events.register')('aard_skill_recoff', self._recoff)
        self.api('events.register')('aard_skill_gain', self.skillgain)
        self.api('events.register')('var_su_enabled', self.enabledchange)
        self.api('events.register')('skills_affected_update', self.nextspell)
        self.api('events.register')('plugin_%s_savestate' % self.sname,
                                    self._savestate)
        self.api('events.register')('skills_uptodate', self.nextspell)

    def skillgain(self, args=None):
        """
    check skills when we gain them
    """
        if args['sn'] in self.spellups['sorder'] and args['percent'] > 50:
            self.nextspell()

    def initspellups(self):
        """
    initialize the spellups dictionary
    """
        if 'sorder' not in self.spellups:
            self.spellups['sorder'] = []
        if 'self' not in self.spellups:
            self.spellups['self'] = {}
        if 'oorder' not in self.spellups:
            self.spellups['oorder'] = []
        if 'other' not in self.spellups:
            self.spellups['other'] = {}

    def enabledchange(self, args):
        """
    do something when enabled is changed
    """
        if args['newvalue']:
            self.nextspell()

    def _affon(self, args):
        """
    catch an affon event
    """
        if args['sn'] == self.api('setting.gets')('waiting'):
            self.api('setting.change')('waiting', -1)
        self.nextspell()

    def _affoff(self, _=None):
        """
    catch an affoff event
    """
        self.nextspell()

    def _recoff(self, _=None):
        """
    catch a recoff event
    """
        self.nextspell()

    def _skillfail(self, args):  # pylint: disable=too-many-branches
        """
    catch a skill fail event
    """
        self.api('send.msg')('skillfail: %s' % args)
        spellnum = args['sn']
        skill = self.api('skills.gets')(spellnum)
        waiting = self.api('setting.gets')('waiting')
        if args['reason'] == 'nomana':
            self.api('setting.change')('waiting', -1)
            self.api('setting.change')('nomana', True)
            self.lastmana = self.api('GMCP.getv')('char.vitals.mana')
        elif args['reason'] == 'nocastroom':
            self.api('setting.change')('waiting', -1)
            self.api('setting.change')('nocast', True)
            nocastrooms = self.api('setting.gets')('nocastrooms')
            currentroom = self.api('setting.gets')('currentroom')
            nocastrooms[currentroom] = True
        elif args['reason'] == 'fighting' or args['reason'] == 'notactive':
            self.api('setting.change')('waiting', -1)
        elif args['reason'] == 'nomoves':
            self.api('setting.change')('waiting', -1)
            self.api('setting.change')('nomoves', True)
            self.lastmana = self.api('GMCP.getv')('char.vitals.moves')
        elif waiting == spellnum:
            if args['reason'] == 'lostconc':
                self.api('skills.sendcmd')(waiting)
            elif args['reason'] == 'alreadyaff':
                self.api('setting.change')('waiting', -1)
                self.api('send.client')(
                    "@BSpellup - disabled %s because you are already affected" % \
                                          skill['name'])
                if spellnum in self.spellups['self']:
                    self.spellups['self'][spellnum]['enabled'] = False
                #if spellnum in self.spellups['other']:
                #self.spellups['other'][spellnum]['enabled'] = False
                self.nextspell()
            elif args['reason'] == 'recblock':
                # do stuff when blocked by a recovery
                self.api('setting.change')('waiting', -1)
                self.nextspell()
            elif args['reason'] == 'dontknow':
                # do stuff when spell/skill isn't learned
                # don't disable it, hopefully the spell/skill has been updated and
                # won't be cast through nextspell
                self.api('setting.change')('waiting', -1)
                self.nextspell()
            elif args['reason'] == 'wrongtarget':
                # do stuff when a wrong target
                self.api('setting.change')('waiting', -1)
                self.nextspell()
            elif args['reason'] == 'disabled':
                self.api('setting.change')('waiting', -1)
                skill = self.api('skills.gets')(spellnum)
                self.api('send.client')(
                    "@BSpellup - disabled %s because it is disabled mudside" % \
                                          skill['name'])
                if spellnum in self.spellups['self']:
                    self.spellups['self'][spellnum]['enabled'] = False
                if spellnum in self.spellups['other']:
                    self.spellups['other'][spellnum]['enabled'] = False
                self.nextspell()

    def _moved(self, args):
        """
    reset stuff if we move
    """
        self.api('setting.change')('currentroom', args['to']['num'])
        nocastrooms = self.api('setting.gets')('nocastrooms')
        if args['to']['num'] in nocastrooms:
            self.api('setting.change')('nocast', True)
        else:
            lastval = self.api('setting.gets')('nocast')
            self.api('setting.change')('nocast', False)
            if lastval:
                self.nextspell()

    def _charvitals(self, _=None):
        """
    check if we have more mana and moves
    """
        if self.api('setting.gets')('nomana'):
            newmana = self.api('GMCP.getv')('char.vitals.mana')
            if newmana > self.lastmana:
                self.lastmana = -1
                self.api('setting.change')('nomana', False)
                self.nextspell()
        if self.api('setting.gets')('nomoves'):
            newmoves = self.api('GMCP.getv')('char.vitals.moves')
            if newmoves > self.lastmoves:
                self.lastmoves = -1
                self.api('setting.change')('nomoves', False)
                self.nextspell()

    def _charstatus(self, _=None):
        """
    check if we have more mana and moves
    """
        status = self.api('GMCP.getv')('char.status.state')
        if status == 3 and self.api('skills.isuptodate')():
            self.nextspell()

    @timeit
    def check(self, _=None):
        """
    check to cast the next spell
    """
        mud = self.api('managers.getm')('mud')
        if not mud or not mud.connected:
            return False
        self.api('send.msg')('waiting type: %s' % \
                          type(self.api('setting.gets')('waiting')))
        self.api('send.msg')('currentstatus = %s' % \
                          self.api('GMCP.getv')('char.status.state'))

        # pylint: disable=too-many-boolean-expressions
        if self.api('setting.gets')('nomoves') \
            or self.api('setting.gets')('nomana') \
            or self.api('setting.gets')('nocast') \
            or self.api('setting.gets')('waiting') != -1 \
            or not self.api('setting.gets')('enabled') \
            or not self.api('skills.isuptodate')() or \
            self.api('GMCP.getv')('char.status.state') != 3:
            self.api('send.msg')('checked returned False')
            return False

        self.api('send.msg')('checked returned True')
        return True

    @timeit
    def nextspell(self, _=None):
        """
    try to cast the next spell
    """
        self.api('send.msg')('nextspell')
        if self.check():
            for i in self.spellups['sorder']:
                if self.spellups['self'][i]['enabled']:
                    if self.api('skills.canuse')(i):
                        self.api('setting.change')('waiting', int(i))
                        self.api('skills.sendcmd')(i)
                        return

    def _savestate(self, _=None):
        """
    save states
    """
        self.spellups.sync()

    def _addselfspell(self, spellnum, place=-1, override=False):
        """
    add a spell internally
    """
        msg = []
        spell = self.api('skills.gets')(spellnum)

        if not spell:
            msg.append('%-20s: does not exist' % spellnum)
            return msg

        if not override and not self.api('skills.isspellup')(spell['sn']):
            msg.append('%-20s: not a spellup' % spell['name'])
            return msg

        if spell['sn'] in self.spellups['sorder']:
            msg.append('%-30s: already activated' % spell['name'])
            return msg

        self.spellups['self'][spell['sn']] = {'enabled': True}
        if place > -1:
            self.spellups['sorder'].insert(place, spell['sn'])
        else:
            self.spellups['sorder'].append(spell['sn'])
        msg.append('%-20s:  place %s' % \
            (spell['name'],
             self.spellups['sorder'].index(spell['sn'])))

        return msg

    def cmd_sadd(self, args):
        """
    add a spellup
    """
        msg = []
        if len(args['spell']) < 1:
            return False, ['Please supply a spell']

        if args['spell'][0] == 'all':
            spellups = self.api('skills.getspellups')()
            for spell in spellups:
                if spell['percent'] > 1:
                    tmsg = self._addselfspell(spell['sn'])
                    msg.extend(tmsg)

            self.nextspell()

        else:
            for aspell in args['spell']:
                tspell = aspell
                place = -1
                if ':' in aspell:
                    tlist = aspell.split(':')
                    tspell = tlist[0]
                    place = int(tlist[1])

                tmsg = self._addselfspell(tspell, place, args['override'])
                msg.extend(tmsg)

                self.nextspell()

        self.spellups.sync()
        return True, msg

    def cmd_slist(self, args):
        """
    list the spellups
    """
        msg = []
        match = args['match']
        if self.spellups['sorder']:
            msg.append('%-3s - %-30s : %2s %2s %2s %2s  %-2s  %-2s' % \
                          ('Num', 'Name', 'A', 'P', 'B', 'D', 'NP', 'NL'))
            msg.append('@B' + '-' * 60)
            for i in self.spellups['sorder']:
                skill = self.api('skills.gets')(i)
                if not skill:
                    msg.append('%-3s: please check the skills plugin' % \
                                   (self.spellups['sorder'].index(i)))
                elif not match or match in skill['name']:
                    msg.append('%-3s - %-30s : %2s %2s %2s %2s  %-2s  %-2s' % \
                                (self.spellups['sorder'].index(i),
                                 skill['name'],
                                 'A' if self.api('skills.isaffected')(i) else '',
                                 'P' if self.api('setting.gets')('waiting') == i else '',
                                 'B' if self.api('skills.isblockedbyrecovery')(i) else '',
                                 'D' if not self.spellups['self'][i]['enabled'] else '',
                                 'NP' if skill['percent'] == 1 else '',
                                 'NL' if skill['percent'] == 0 else '',))
        else:
            msg.append('There are no spellups')
        return True, msg

    def cmd_srem(self, args):
        """
    remove a spellup
    """
        if len(args['spell']) < 1:
            return True, ['Please supply a spell/skill to remove']

        msg = []
        if args['spell'][0].lower() == 'all':
            del self.spellups['sorder']
            del self.spellups['self']
            self.initspellups()
            msg.append('All spellups to be cast on self cleared')

        else:
            for spella in args['spell']:
                spell = self.api('skills.gets')(spella)

                if not spell:
                    msg.append('%s does not exist' % spella)
                    continue

                spellnum = spell['sn']
                if spellnum in self.spellups['sorder']:
                    self.spellups['sorder'].remove(spellnum)
                if spellnum in self.spellups['self']:
                    del self.spellups['self'][spellnum]

                msg.append('Removed %s from spellups to self' % spell['name'])

            self.savestate()
            return True, msg

    def cmd_en(self, args):
        """
    enable a spellup
    """
        if len(args['spell']) < 1:
            return True, ['Please supply a spell/skill to enable']

        msg = []

        if args['spell'][0].lower() == 'all':
            for i in self.spellups['self']:
                self.spellups['self'][i]['enabled'] = True

            msg.append('All spellups enabled')
            self.nextspell()
            return True, msg

        for spellnum in args['spell']:
            skill = self.api('skills.gets')(spellnum)
            if skill:
                if skill['sn'] in self.spellups['sorder']:
                    self.spellups['self'][skill['sn']]['enabled'] = True
                    msg.append('%s: enabled' % skill['name'])
                else:
                    msg.append('%s: not in self spellup list' % skill['name'])
            else:
                msg.append('%s: could not find spell' % spellnum)
        self.nextspell()
        return True, msg

    def cmd_dis(self, args):
        """
    enable a spellup
    """
        if len(args['spell']) < 1:
            return True, ['Please supply a spell/skill to enable']

        msg = []
        if args['spell'][0].lower() == 'all':
            for i in self.spellups['self']:
                self.spellups['self'][i]['enabled'] = False

            msg.append('All spellups disabled')
            return True, msg

        for spellnum in args['spell']:
            skill = self.api('skills.gets')(spellnum)
            if skill:
                if skill['sn'] in self.spellups['sorder']:
                    self.spellups['self'][skill['sn']]['enabled'] = False
                    msg.append('%s: disabled' % skill['name'])
                else:
                    msg.append('%s: not in self spellup list' % skill['name'])
            else:
                msg.append('%s: could not find spell' % spellnum)
        return True, msg

    def cmd_check(self, _=None):
        """
    list all items that are need for spellups and whether they are known
    """
        tmsg = []
        tformat = '%-25s : %-10s - %s'
        tmsg.append(tformat % \
                     ('enabled',
                      self.api('setting.gets')('enabled'),
                      'should be True to cast spells'))
        tmsg.append(tformat % \
                     ('waiting',
                      self.api('setting.gets')('waiting'),
                      'the spell that was last cast, should be -1 to cast spells'))
        tmsg.append(tformat % \
                     ('nocast',
                      self.api('setting.gets')('nocast'),
                      'the current room is nocast, should be False to cast spells'))
        tmsg.append(tformat % \
                     ('nomoves',
                      self.api('setting.gets')('nomoves'),
                      'ran out of moves, should be False to cast spells'))
        tmsg.append(tformat % \
                     ('nomana',
                      self.api('setting.gets')('nomana'),
                      'ran out of mana, should be False to cast spells'))
        tmsg.append(tformat % \
                     ('Skills are up to date',
                      self.api('skills.isuptodate')(),
                      'should be True to cast spells'))
        tmsg.append(tformat % \
                     ('Char state',
                      self.api('GMCP.getv')('char.status.state'),
                      'should be 3 to cast spells'))
        return True, tmsg

    def reset(self):
        """
    reset all spellups
    """
        AardwolfBasePlugin.reset(self)
        self.spellups.clear()
        self.initspellups()
        self.spellups.sync()