Esempio n. 1
0
    def __init__(self, parent, args):
        self._skillMaxHealPoints = None
        self._seen = 0

        super(_SkillHealer, self).__init__(parent, args)
        skillId = args.setdefault('id', "UNKNOWN")
        try:
            self.id = int(skillId)
        except ValueError:
            raise FatalError("{}: Invalid skill id: {}".format(
                self.parent.id, skillId))
        if 'required_mp' not in args:
            try:
                skill = getSkillFromId(str(self.id), parent.session)
                args['required_mp'] = skill['mpCost']
            except kol.Error.Error:
                args['required_mp'] = "UNKNOWN"
        try:
            self._mpCost = int(args['required_mp'])
        except ValueError:
            raise FatalError("{}: Invalid mp cost: {}".format(
                self.parent.id, args['required_mp']))
        try:
            self.typicalCasts = int(
                args.setdefault('typical_number_casts', '1'))
        except ValueError:
            raise FatalError("{}: Invalid typical casts: {}".format(
                self.parent.id, args['typical_number_casts']))
Esempio n. 2
0
 def _configure(self, config):
     try:
         self._minPoints = int(config.setdefault('min_points_to_win', 1))
         self._killPoints = int(config.setdefault('kills', 1))
         self._bossPoints = int(config.setdefault('boss', 1))
         self._machinePoints = int(config.setdefault('machine_assist', 10))
     except ValueError:
         raise FatalError("DreadPointsModule: kills, boss, min_points "
                          "must be integers")
     try:
         self._drunkPoints = float(config.setdefault('drunk', 0.01))
     except ValueError:
         raise FatalError("DreadPointsModule: drunk must be float")
     self._keyUnlocks = config.setdefault(
         'keys', {
             'Attic': 25,
             'Fire Tower': 25,
             'Suite': 25,
             'School': 25,
             'Lab': 25,
             'Ballroom': 25
         })
     self._codePts = config.setdefault('codes', {})
     self._regexPts = config.setdefault('regex', {})
     try:
         self._keyUnlocks = {k: int(v) for k, v in self._keyUnlocks.items()}
         self._codePts = {k: int(v) for k, v in self._codePts.items()}
         self._regexPts = {k: int(v) for k, v in self._regexPts.items()}
     except ValueError:
         raise FatalError("DreadPointsModule: points " "must be integers")
Esempio n. 3
0
 def _loadConfig(self, configFile):
     """ Load ini file and parse some values from it """
     self._log.debug("Loading config file...")
     try:
         c = ConfigObj(configFile,
                       configspec=StringIO(MODULE_SPEC),
                       list_values=False,
                       raise_errors=True,
                       create_empty=True)
         passed = c.validate(Validator(), copy=True, preserve_errors=True)
     except ParseError as e:
         raise FatalError("Parse error in modules.ini:{}: \"{}\"".format(
             e.line_number, e.line))
     if passed != True:
         f = flatten_errors(c, passed)
         error1 = f[0]
         raise FatalError(
             "Invalid module configuration. First error "
             "found in section [{}], key \"{}\". Error: {}".format(
                 '/'.join(error1[0]), error1[1], error1[2]))
     self._overWriteConfig = c['overwrite_config']
     self._config = c
     with open(configFile) as f:
         txt = f.read()
     self._saveConfig(configFile, txt)
     self._chatDelay = c['system']['communication_interval']
     self._log.debug("{} loaded.".format(configFile))
     return txt
Esempio n. 4
0
    def _configure(self, config):
        for k, v in config.items():
            if isinstance(v, dict):
                modeStr = v.setdefault('mode', 'cycle').lower()
                periodStr = v.setdefault('period', 1440)

                try:
                    period = int(periodStr)
                except ValueError:
                    raise FatalError(
                        "Invalid period specified: {}".format(periodStr))

                offsetStr = v.setdefault('offset', 'random')
                try:
                    offset = int(offsetStr)
                except ValueError:
                    if offsetStr.lower() != "random":
                        raise FatalError(
                            ("Invalid offset: {}, must be "
                             "integer or 'random'").format(offsetStr))
                    else:
                        offset = random.randint(0, period)

                try:
                    mode = self._modes[modeStr]
                except IndexError:
                    raise FatalError(
                        "Invalid mode specified: {}".format(modeStr))

                channels = stringToList(v.setdefault('channel', 'clan,'))

                messages = {}
                for key_, val_ in v.items():
                    if key_.lower().startswith("message"):
                        try:
                            keyVal = "message{:06d}".format(int(key_[7:]))
                        except ValueError:
                            raise FatalError(("Invalid message name: {}; "
                                              "messages must be message1, "
                                              "message2, ...").format(key_))
                        messages[keyVal] = val_

                self._messages[k] = {
                    'mode': mode,
                    'period': period,
                    'channels': channels,
                    'messages': messages,
                    'offset': offset,
                    'order': [],
                    'index': 0,
                    'hard': True,
                    'last': 0,
                    'expires': 0,
                    'description': ""
                }
Esempio n. 5
0
 def _configure(self, config):
     try:
         self._notifyPercent = map(int, stringToList(
                                         config.setdefault('update-percent',
                                                     "25,50,75,90,100")))
     except ValueError:
         raise FatalError("update-percent must be a list of integers")
     try:
         self._perror = float(config.setdefault("p_error", "0.001"))
         if not 0 < self._perror < 1:
             raise ValueError()
     except ValueError:
         raise FatalError("p_error must be a float between 0 and 1")
Esempio n. 6
0
    def _buff(self, uid, buff):
        n = buff['casts']
        cost = buff['mp_cost']
        mpRequired = n * cost
        r2 = StatusRequest(self.session)
        d2 = self.tryRequest(r2)
        mpBefore = int(d2['mp'])
        self.log("Preparing to cast buff {} (requires {} mp)"
                 .format(buff['description'], mpRequired))
        if mpBefore < mpRequired:
            try:
                self.debugLog("Requesting healing from module {}"
                              .format(self._healer))
                replies = self._raiseEvent("heal", self._healer, 
                                           {'type': 'mp', 
                                            'points': mpRequired,
                                            'percent': self._mpMax})
                healResult = replies[-1].data
                mpBefore = healResult['mp']
            except IndexError:
                raise FatalError("Invalid healer {}".format(self._healer))

        self.log("Casting skill {} x{}".format(buff['id'], n))
        r1 = UseSkillRequest(self.session, str(buff['id']), n, uid)
        _d1 = self.tryRequest(r1, numTries=1)
        r2 = StatusRequest(self.session)
        d2 = self.tryRequest(r2)
        mpAfter = int(d2['mp'])
        self.log("Used {} mp. (Now at {}/{})"
                 .format(mpBefore - mpAfter, mpAfter, d2['maxmp']))
        return mpBefore - mpAfter 
Esempio n. 7
0
    def _processLog(self, raidlog):
        events = raidlog['events']
        self._userAdventures = {}
        self._properUserNames = {}
        for e in events:
            zone = e['db-match'].get('zone')
            user = _nameKey(e['userName'])
            if e['category'] != "Miscellaneous":
                self._userAdventures.setdefault(user, [])
                self._properUserNames[user] = e['userName']
                if zone in self._choiceLocations:
                    self._userAdventures[user].append(e['db-match'])

        try:
            replies = self._raiseEvent("dread",
                                       "dread-overview",
                                       data={
                                           'style': 'dict',
                                           'keys': ['status']
                                       })
            self._dread = replies[0].data
        except IndexError:
            raise FatalError("DreadChoicesModule requires a "
                             "DreadOverviewModule with higher priority")
        return True
Esempio n. 8
0
 def __init__(self, manager, identity, config):
     super(WarbearBlackboxModule, self).__init__(manager, identity, config)
     self.inventoryManager.refreshInventory()
     inventory = self.inventoryManager.inventory()
     blackBoxes = inventory.get(7035, 0)
     if blackBoxes == 0:
         raise FatalError("No warbear black box in inventory.")
Esempio n. 9
0
 def __init__(self, parent, args):
     minHeal = args.setdefault('only_heal_over', 0)
     try:
         self._minHealAmount = int(minHeal)
     except ValueError:
         raise FatalError("{}: Invalid only_heal_over value: {}".format(
             self.parent.id, minHeal))
     self.parent = weakref.proxy(parent)
Esempio n. 10
0
 def _initialize(self):
     if self._modules:
         raise FatalError("WalkieTalkieRepeater cannot use modules.")
     if "__numchanges__" in self._persist:
         self._numChanges = self._persist["__numchanges__"]
     lastKey = self._persist.get('__lastKey__', None)
     if lastKey != self._key:
         self._changeFrequencies(self._numChanges)
     self._playerDb = defaultdict(lambda: [None] * len(self._otherBots))
Esempio n. 11
0
    def _addModules(self, config):
        """ Dynamically import the modules specified in modules.ini. This
        should not be overridden. """
        base = config['base']

        # loop through modules
        for k, v in config.items():
            if isinstance(v, dict):
                cfg = v
                perm = toTypeOrNone(v['permission'], str)
                priority = v['priority']
                clanOnly = v['clan_only']

                # import class
                try:
                    ModuleClass = easyImportClass(base, v['type'])
                except ImportError:
                    raise FatalError("Error importing module/class {0} "
                                     "from base {1}. Either the module does "
                                     "not exist, or there was an error. To "
                                     "check for errors, use the command line "
                                     "'python -m {1}.{0}'; the actual path "
                                     "may vary.".format(v['type'], base))

                self._modules.append(
                    ModuleEntry(ModuleClass, priority, perm, clanOnly, self, k,
                                cfg))

        # sort by decreasing priority
        self._modules.sort(key=lambda x: -x.priority)
        self._log.info("---- {} creating module instances... ----".format(
            self.identity))
        for m in self._modules:
            self._log.info(
                "Creating {0.className} with priority "
                "{0.priority}, permission {0.permission}.".format(m))
            try:
                m.createInstance()
            except TypeError as e:
                self._log.exception("Error!")
                raise FatalError("Error instantiating class {}: {}".format(
                    m.className, e.args[0]))

        self._log.info("---- All modules created. ----")
Esempio n. 12
0
    def initialize(self, state, initData):
        self._db = initData['event-db']

        lockedSubzones = set(record['subzone'] for record in self._db
                             if record['zone'] == "(unlock)")
        keySubzones = set(self._keyUnlocks.keys())
        if lockedSubzones != keySubzones:
            missing = lockedSubzones.difference(keySubzones)
            if missing:
                raise FatalError(
                    "DreadPointsModule: no 'keys' entry for '{}'".format(
                        missing.pop()))
            extra = keySubzones.difference(lockedSubzones)
            if extra:
                raise FatalError(
                    "DreadPointsModule: no such locked area '{}'".format(
                        extra.pop()))
        self._grantedPoints = state['granted']
        self._processLog(initData)
Esempio n. 13
0
    def _configure(self, config):
        self._buffs = {}
        self._used = {}
        healer = toTypeOrNone(config.setdefault('healer', "none"), str)
        if healer is not None:
            healer = "__" + healer + "__"
        self._healer = healer
        try:
            self._mpMax = int(config.setdefault('restore_mp_to_percent', 80))
        except ValueError:
            raise FatalError("Invalid restore_mp_to_percent: {}".format(
                config['restore_mp_to_percent']))

        buffs = config.setdefault(
            'buffs', {
                'The Ode To Booze': {
                    'id': 6014,
                    'cost': 1,
                    'casts': 1,
                    'daily_limit': 2,
                    'outfit': 'none'
                }
            })
        for k, v in buffs.items():
            _integerize(v, 'id', "UNKNOWN", k)
            _integerize(v, 'cost', "UNKNOWN", k)
            _integerize(v, 'casts', "UNKNOWN", k)
            _integerize(v, 'daily_limit', "0", k)
            v.setdefault('outfit', "none")
            v.setdefault('description', "none")
            try:
                if "mp_cost" not in v:
                    skill = getSkillFromId(str(v['id']), self.session)
                    v['mp_cost'] = skill['mpCost']
                else:
                    _integerize(v, 'mp_cost', "UNKNOWN", k)
            except kol.Error.Error:
                _integerize(v, 'mp_cost', "UNKNOWN", k)
            self._buffs[k] = v
        priceList = [v['cost'] for v in self._buffs.values() if v['cost'] > 0]
        if len(priceList) != len(set(priceList)):
            raise FatalError("Duplicate buff prices for module {}".format(
                self.id))
Esempio n. 14
0
 def __init__(self, parent, name, iData, config):
     """ Initialize the manager """
     self._playerDb = None
     self._numChanges = 0
     self._ready = False
     self._otherBots = None
     self._myFreq = None
     self._numPlayersForFreqChange = None
     self._freqChangeTimeout = None
     self._format, self._emoteFormat = None, None
     super(WalkieTalkieRepeater, self).__init__(parent, name, iData, config)
     self._invMan.refreshInventory()
     self._lastOutsiderCheck = 0
     self._changeFreqRequests = {}
     inventory = self._invMan.inventory()
     numTalkies = inventory.get(6846, 0)
     if numTalkies == 0:
         numUnusedTalkies = inventory.get(6845, 0)
         if numUnusedTalkies > 0:
             try:
                 r = UseItemRequest(self._s, 6845)
                 d = tryRequest(r)
                 numTalkies = 1
             except Error:
                 raise FatalError("Could not use unused walkie talkie.")
         else:
             raise FatalError("Cannot use WalkieTalkieRepeater with "
                              "no walkie talkie!")
     replies = self.sendChatMessage("/kenneth",
                                    None,
                                    waitForReply=True,
                                    raw=True)
     for reply in replies:
         txt = reply['text']
         freq = re.search(r"The frequency is (\d+.\d), Mr. Rather", txt)
         if freq:
             self._myFreq = freq.group(1)
             self._log.info("My walkie talkie frequency is {}".format(
                 freq.group(1)))
     if self._myFreq is None:
         raise RuntimeError("Could not determine walkie talkie frequency.")
     self._ready = True
Esempio n. 15
0
 def __init__(self, parent, args):
     super(_LuciferHealer, self).__init__(parent, args)
     self.extHealer = toTypeOrNone(
         args.setdefault('external_healer', 'none'), str)
     try:
         self.maxFull = toTypeOrNone(args.setdefault('max_full', 'none'),
                                     int)
     except ValueError:
         raise FatalError("Invalid max_full value for Lucifer: {}".format(
             args['max_full']))
     self.buyFromMall = stringToBool(args.setdefault('use_mall', 'true'))
Esempio n. 16
0
    def __init__(self, parent, args):
        self._itemMaxHealPoints = None
        self._seen = 0

        super(_ItemHealer, self).__init__(parent, args)
        itemId = args.setdefault('id', "UNKNOWN")
        try:
            self.id = int(itemId)
        except ValueError:
            raise FatalError("{}: Invalid item id: {}".format(
                self.parent.id, itemId))
        self.buyFrom = toTypeOrNone(args.setdefault('buy_from', "none"), str)
Esempio n. 17
0
 def _processLog(self, raidlog):
     try:
         replies = self._raiseEvent("dread",
                                    "dread-overview",
                                    data={
                                        'style': "dict",
                                        'keys': ['status', 'locked']
                                    })
         self._dread = replies[0].data
     except IndexError:
         raise FatalError("DreadKeyModule requires a DreadOverviewModule "
                          "with higher priority")
     return True
Esempio n. 18
0
    def _processLog(self, raidlog):
        events = raidlog['events']
        
        # get dread status
        try:
            replies = self._raiseEvent("dread", "dread-overview", 
                                       data={'style': 'dict',
                                             'keys': ['status',
                                                      'index',
                                                      'locked']})
            self._dread = replies[0].data
        except IndexError:
            raise FatalError("DreadUniquesModule requires a "
                             "DreadOverviewModule with higher priority")

        newClaimed = defaultdict(list)
        userNames = {}
        for record in self._uniques:
            itemTxt = record['unique_text']
            quantity = toTypeOrNone(record['quantity'], int)
            if quantity is None:
                quantity = 1
            
            # see how many items were taken and who did it
            itemsAcquired = 0
            logMessage = ""
            for e in eventDbMatch(events, record):
                logMessage = e['event']
                newClaimed[itemTxt].extend([e['userId']] * e['turns'])
                userNames[e['userId']] = e['userName']
                itemsAcquired += e['turns']
            
            # compare to old list and announce if specified in the options
            if self._claimed is not None:
                # count up which users got this log message
                c1 = Counter(self._claimed.get(itemTxt, []))
                c2 = Counter(newClaimed.get(itemTxt, []))
                for k,v in c2.items():
                    # iterate through each user
                    numCollected = v - c1[k]
                    # print a pickup message for each time user X got item
                    # should be only once for dreadsylvania
                    for _ in range(numCollected):
                        self.chat("{} {} ({} remaining)."
                                  .format(userNames[k], 
                                          logMessage,
                                          quantity - itemsAcquired))
        self._claimed = newClaimed
        return True
Esempio n. 19
0
 def _configure(self, config):
     BaseChatManager._configure(self, config)
     try:
         otherBots = stringToList(config.setdefault('other_bots', "none"))
         self._otherBots = map(int, otherBots)
     except ValueError:
         raise FatalError("Error configuring WalkieTalkieRepeater: "
                          "other_bots must be list of integers (userIds)")
     try:
         self._numPlayersForFreqChange = int(
             config.setdefault('num_players_to_change', 3))
         self._freqChangeTimeout = int(
             config.setdefault('change_timeout', 10))
     except ValueError:
         raise FatalError("Error configuring WalkieTalkieRepeater: "
                          "num_players_to_change and change_timeout must "
                          "be integral")
     self._format = config.setdefault('format', "[[%username%]] %text%")
     self._emoteFormat = config.setdefault('emote_format',
                                           "[[%username% %text%]]")
     self._key = str(config.setdefault('key', random.randint(0, 999999)))
     if self._key.strip() == "":
         config['key'] = random.randint(0, 999999)
         self._key = str(config['key'])
Esempio n. 20
0
    def _configure(self, config):
        self._daysUntilBoot = int(config.setdefault('boot_after_days', 180))
        safeRanks = stringToList(
            config.setdefault('safe_ranks', "rank1, rank2"))
        safeTitles = stringToList(
            config.setdefault('safe_titles', "DO NOT DELETE, "
                              "DO NOT ERASE"))
        self._safeRanks = map(_rankTransform, safeRanks)
        self._safeTitles = map(_rankTransform, safeTitles)
        self._bootMessage = toTypeOrNone(
            config.setdefault('boot_message', "none"))
        self._simulate = stringToBool(config.setdefault('simulate', "false"))
        self._immediate = stringToBool(
            config.setdefault('run_immediately', "false"))
        try:
            self._bootFrequencyDays = int(
                config.setdefault('boot_every_n_days', 1))
        except ValueError:
            raise FatalError("ClanRankModule: boot_every_n_days must "
                             "be integral")

        rules = config.setdefault(
            'rules', {
                'Normal Member': {
                    'demotion_allowed': "false",
                    'min_karma': 0,
                    'min_days_until_next_promotion': 7,
                    'min_days_in_clan': 0,
                    'next_rank': 'Rank2'
                },
                'Rank2': {
                    'demotion_allowed': "true",
                    'min_karma': 0,
                    'min_days_until_next_promotion': 0,
                    'min_days_in_clan': 0,
                    'next_rank': "none"
                }
            })

        for rule in rules.values():
            rule.setdefault('demotion_allowed', True)
            rule.setdefault('min_karma', 0)
            rule.setdefault('min_days_until_next_promotion', 0)
            rule.setdefault('min_days_in_clan', 0)
            rule.setdefault('next_rank', "none")

        self._ruleConfig = rules
Esempio n. 21
0
    def _finishInitialization(self):
        # get list of clan members (both in whitelist and roster)
        self.log("Initializing ranks...")
        r1 = ClanWhitelistRequest(self.session)
        d1 = self.tryRequest(r1)
        self._ranks = {
            _rankTransform(rank['rankName']): rank
            for rank in d1['ranks']
        }
        r2 = StatusRequest(self.session)
        d2 = self.tryRequest(r2)
        self._rolloverTime = int(d2['rollover'])

        # load promotion rules
        self._promotionRules = {}
        for rankname, rule in self._ruleConfig.items():
            key = _rankTransform(rankname)
            nextRankName = toTypeOrNone(rule['next_rank'])
            nextkey = _rankTransform(nextRankName) if nextRankName else None
            nextRankId = self._ranks.get(nextkey, {}).get('rankId')

            if key not in self._ranks:
                raise FatalError(
                    "Invalid clan rank: {} (available ranks: {})".format(
                        key, ", ".join(self._ranks.keys())))
            if nextkey is not None and nextkey not in self._ranks:
                raise FatalError(
                    "Invalid clan rank: {} (available ranks: {})".format(
                        nextkey, ", ".join(self._ranks.keys())))

            try:
                self._promotionRules[self._ranks[key]['rankId']] = ({
                    'demotionAllowed':
                    stringToBool(rule['demotion_allowed']),
                    'minKarma':
                    int(rule['min_karma']),
                    'minDaysBeforePromotion':
                    int(rule['min_days_until_next_promotion']),
                    'minDaysInClan':
                    int(rule['min_days_in_clan']),
                    'nextRankId':
                    nextRankId,
                    'rankName':
                    rankname
                })
            except ValueError:
                raise "ClanRankModule: error parsing rank {}".format(rankname)

        # pick a random time to run today
        assumedExecTime = 7200
        latestPossibleExecTime = self._rolloverTime - assumedExecTime
        if time.time() < self._lastRun:
            self.log("Already performed ranking today.")
        elif time.time() > latestPossibleExecTime:
            self.log("Too late to run rankings today.")
        else:
            if self._immediate:
                self._execTime = int(time.time()) + 15
            else:
                self._execTime = random.randint(int(time.time()),
                                                latestPossibleExecTime)
            self.log("Running rankings in {} minutes.".format(
                int((self._execTime - time.time()) / 60)))
Esempio n. 22
0
def _integerize(map_, keyname, defaultval, desc):
    try:
        map_[keyname] = int(map_.setdefault(keyname, defaultval))
    except ValueError:
        raise FatalError("Invalid value for key '{}' in {}: {}"
                         .format(keyname, desc, map_[keyname]))