Example #1
0
def botProcessChat(context, **kwargs):
    returnCode = FilterManager.CONTINUE
    chat = kwargs["chat"]
    
    if chat["type"] == "private":
        if BotUtils.canUserPerformAction(chat["userId"], "execute", kwargs["bot"]):
            doAction = False
            executeAll = False
            wordList = chat["text"].split()
            if len(wordList) > 0:
                if wordList[0].lower() == "execute":
                    doAction = True
                elif wordList[0].lower() == "executeall":
                    doAction = True
                    executeAll = True

            if doAction:
                returnCode = FilterManager.FINISHED
                del wordList[0]
                command = " ".join(wordList)

                if executeAll:
                    for bot in BotManager._bots:
                        if bot.session != None and bot.session.isConnected and hasattr(bot.session, "chatManager"):
                            try:
                                bot.sendChatMessage(command)
                            except AttributeError, inst:
                                Report.error("chat", "Could not execute command: %s" % command, inst)
                else:
                    kwargs["bot"].sendChatMessage(command)
Example #2
0
    def parseResponse(self):
        # Check for errors.
        effectRemovedPattern = PatternManager.getOrCompilePattern(
            'effectRemoved')
        if effectRemovedPattern.search(self.responseText):
            return

        youDontHaveThatEffectPattern = PatternManager.getOrCompilePattern(
            'youDontHaveThatEffect')
        if youDontHaveThatEffectPattern.search(self.responseText):
            raise DontHaveEffectError(
                "Unable to remove effect. The user does not have that effect.")

        youDontHaveSGEEAPattern = PatternManager.getOrCompilePattern(
            'youDontHaveSGEEA')
        if youDontHaveSGEEAPattern.search(self.responseText):
            raise NotEnoughItemsError(
                "Unable to remove effect. You do not have a soft green echo eyedrop antidote."
            )

        Report.error("request",
                     "Unknown error occurred when trying to remove an effect")
        Report.error("request", self.responseText)
        raise RequestError(
            "Unknown error occurred when trying to remove an effect.")
Example #3
0
def botEndCycle(context, **kwargs):
    returnCode = FilterManager.CONTINUE
    bot = kwargs['bot']

    # Check for new kmails?
    aleabot.kmail_check_timer += aleabot.config.get('time_to_sleep')
    if aleabot.kmail_check_timer >= aleabot.config.get('time_to_sleep_kmail'):
        Report.trace('bot', 'Enabling doWork:kmail')
        bot.params['doWork:kmail'] = True
        aleabot.kmail_check_timer = 0
    else:
        Report.trace('bot', 'Disabling doWork:kmail')
        bot.params.pop('doWork:kmail', None)

    # Update clan state in regular intervals (as configured)
    try:
        aleabot.clanstate.set_session(bot.session)
        if aleabot.clanstate.update(aleabot.config.get('clan_state_refresh_time')):
            Report.info('bot', 'Clan state update successful.')
            Report.trace('bot', 'I am in clan: ' + repr(aleabot.clanstate.my_clan()))
            Report.trace('bot', 'I have ' + str(len(aleabot.clanstate.my_whitelists())) + ' whitelists')
            # Set timer to switch back to home clan
            if aleabot.home_clan_timer < 0:
                aleabot.home_clan_timer = 0
    except alea.clan.ClanRequestError as err:
        Report.error('bot', 'Unable to update clan state! Error: ' + str(err))

    # Switch to home clan after some delay
    if aleabot.home_clan_timer >= 0:
        aleabot.home_clan_timer += aleabot.config.get('time_to_sleep')
        if aleabot.home_clan_timer >= aleabot.config.get('home_clan_delay'):
            aleabot.home_clan_timer = -1

            # Breakfast now if not yet breakfasted today
            if 'breakfast' not in bot.states['rollover']:
                alea.breakfast.breakfast(bot.session)
                bot.states['rollover']['breakfast'] = True
                bot.writeState('rollover')

            # Switch to home clan now
            home_clan_id = aleabot.config.get('home_clan_id')
            if home_clan_id > 0 and aleabot.clanstate.my_clan().id() != home_clan_id:
                Report.info('bot', 'Switching back to home clan.')
                try:
                    aleabot.clanstate.switch(alea.clan.Clan(home_clan_id, ''))
                except alea.clan.ClanRequestError as err:
                    Report.error('bot', 'Unable to switch clan! Error: ' + str(err))

    return returnCode
Example #4
0
    def parseResponse(self):
        # Check for errors.
        effectRemovedPattern = PatternManager.getOrCompilePattern("effectRemoved")
        if effectRemovedPattern.search(self.responseText):
            return

        youDontHaveThatEffectPattern = PatternManager.getOrCompilePattern("youDontHaveThatEffect")
        if youDontHaveThatEffectPattern.search(self.responseText):
            raise DontHaveEffectError("Unable to remove effect. The user does not have that effect.")

        youDontHaveSGEEAPattern = PatternManager.getOrCompilePattern("youDontHaveSGEEA")
        if youDontHaveSGEEAPattern.search(self.responseText):
            raise NotEnoughItemsError("Unable to remove effect. You do not have a soft green echo eyedrop antidote.")

        Report.error("request", "Unknown error occurred when trying to remove an effect")
        Report.error("request", self.responseText)
        raise RequestError("Unknown error occurred when trying to remove an effect.")
Example #5
0
def handleClanChat(context, **kwargs):
    chat = kwargs["chat"]
    bot = kwargs["bot"]
    globalState = bot.states["global"]

    # Do nothing if the bot is squelched.
    if DataUtils.getBoolean(globalState, "isSquelched", False):
        return FilterManager.CONTINUE

    # Do nothing if the text is prefixed by PRIVATE:
    lowerText = chat["text"].lower()
    if lowerText.find("private:") == 0:
        return FilterManager.CONTINUE

    # Do nothing for broadcasted messages.
    if chat["userName"] == "System Message":
        return FilterManager.CONTINUE

    # Construct the message to send to the other bots.
    msg = None
    if "chatBroadcastDelimiters" in bot.params:
        chars = bot.params["chatBroadcastDelimiters"]
        if chat["type"] == "normal":
            msg = "%s%s%s %s" % (chars[0], chat["userName"], chars[1],
                                 chat["text"])
        elif chat["type"] == "emote":
            msg = "/me %s%s%s %s" % (chars[0], chat["userName"], chars[1],
                                     chat["text"])
    else:
        if chat["type"] == "normal":
            msg = "[%s] %s" % (chat["userName"], chat["text"])
        elif chat["type"] == "emote":
            msg = "/me [%s] %s" % (chat["userName"], chat["text"])

    # Send the message to the other bots.
    if msg != None:
        thisBot = kwargs["bot"]
        for bot in BotManager._bots:
            if bot.id != thisBot.id:
                if bot.session != None and bot.session.isConnected and hasattr(
                        bot.session, "chatManager"):
                    try:
                        bot.sendChatMessage(msg)
                    except AttributeError, inst:
                        Report.error("chat", "Could not broadcast message.",
                                     inst)
Example #6
0
    def parseResponse(self):
        # Check for errors.
        effectRemovedPattern = PatternManager.getOrCompilePattern('effectRemoved')
        if effectRemovedPattern.search(self.responseText):
            return

        youDontHaveThatEffectPattern = PatternManager.getOrCompilePattern('youDontHaveThatEffect')
        if youDontHaveThatEffectPattern.search(self.responseText):
            raise Error.Error("Unable to remove effect. The user does not have that effect.", Error.EFFECT_NOT_FOUND)

        youDontHaveSGEEAPattern = PatternManager.getOrCompilePattern('youDontHaveSGEEA')
        if youDontHaveSGEEAPattern.search(self.responseText):
            raise Error.Error("Unable to remove effect. You do not have a soft green echo eyedrop antidote.", Error.ITEM_NOT_FOUND)

        Report.error("request", "Unknown error occurred when trying to remove an effect")
        Report.error("request", self.responseText)
        raise Error.Error("Unknown error occurred when trying to remove an effect.", Error.REQUEST_FATAL)
Example #7
0
def handleClanChat(context, **kwargs):
    chat = kwargs["chat"]
    bot = kwargs["bot"]
    globalState = bot.states["global"]

    # Do nothing if the text is prefixed by PRIVATE:
    lowerText = chat["text"].lower()
    if lowerText.find("private:") == 0 or lowerText[0:2] == "p:":
        return FilterManager.CONTINUE

    if DataUtils.getBoolean(kwargs["bot"].params, "doWork:doLogChat", False):
        HogDatabase.logChat(chat["userId"], chat["userName"], bot.params["userClan"], chat["text"])

    # Do nothing if the bot is squelched.
    if DataUtils.getBoolean(globalState, "isSquelched", False):
        return FilterManager.CONTINUE

    # Do nothing for broadcasted messages.
    if chat["userName"] == "System Message":
        return FilterManager.CONTINUE

    # Construct the message to send to the other bots.
    msg = None
    if "chatBroadcastDelimiters" in bot.params:
        chars = bot.params["chatBroadcastDelimiters"]
        if chat["type"] == "normal":
            msg = "%s%s%s %s" % (chars[0], chat["userName"], chars[1], chat["text"])
        elif chat["type"] == "emote":
            msg = "/me %s%s%s %s" % (chars[0], chat["userName"], chars[1], chat["text"])
    else:
        if chat["type"] == "normal":
            msg = "[%s] %s" % (chat["userName"], chat["text"])
        elif chat["type"] == "emote":
            msg = "/me [%s] %s" % (chat["userName"], chat["text"])

    # Send the message to the other bots.
    if msg != None:
        thisBot = kwargs["bot"]
        for bot in BotManager._bots:
            if bot.id != thisBot.id:
                if bot.session != None and bot.session.isConnected and hasattr(bot.session, "chatManager"):
                    try:
                        bot.sendChatMessage(msg)
                    except AttributeError, inst:
                        Report.error("chat", "Could not broadcast message.", inst)
Example #8
0
    def parseResponse(self):
        weakSkillPattern = PatternManager.getOrCompilePattern('skillTooWeak')
        badSkillPattern = PatternManager.getOrCompilePattern('skillNotTrainable')
        poorSkillPattern = PatternManager.getOrCompilePattern('skillTooPoor')
        haveSkillPattern = PatternManager.getOrCompilePattern('skillHaveAlready')

        if weakSkillPattern.search(self.responseText):
            raise InvalidActionError("You aren't a high enough level to train that skill")
        if badSkillPattern.search(self.responseText):
            raise SkillMissingError("You cannot train that skill at the Guild Hall")
        if poorSkillPattern.search(self.responseText):
            raise NotEnoughMeatError("You cannot afford to train that skill")
        if haveSkillPattern.search(self.responseText):
            raise RequestError("You already know that skill")

        skillLearnedPattern = PatternManager.getOrCompilePattern('skillLearned')
        match = skillLearnedPattern.search(self.responseText)
        if match:
            try:
                skill = SkillDatabase.getSkillFromName(match.group(1))
                self.responseData["skill"] = skill
            except SkillNotFoundError, inst:
                Report.error("bot", inst.message, inst)
Example #9
0
def breakfast(session):
    Report.info('bot', 'Start of breakfast.')

    meatGained = 0

    Report.info('bot', 'Visiting hippy produce stand.')
    try:
        req = HippyProduceStandRequest(session)
        response = req.doRequest()
        meatGained += response['meat']
    except Error.Error as err:
        Report.error('bot', 'Error while visiting hippy produce stand: ' + str(err))

    Report.info('bot', 'Visiting potted meat bush.')
    try:
        req = MeatBushRequest(session)
        response = req.doRequest()
        meatGained += response['meat']
    except Error.Error as err:
        Report.error('bot', 'Error while visiting potted meat bush: ' + str(err))

    Report.info('bot', 'Visiting exotic hanging meat orchid.')
    try:
        req = MeatOrchidRequest(session)
        response = req.doRequest()
        meatGained += response['meat']
    except Error.Error as err:
        Report.error('bot', 'Error while visiting exotic hanging meat orchid: ' + str(err))

    Report.info('bot', 'Visiting potted meat tree.')
    try:
        req = MeatTreeRequest(session)
        response = req.doRequest()
        meatGained += response['meat']
    except Error.Error as err:
        Report.error('bot', 'Error while visiting potted meat tree: ' + str(err))

    Report.info('bot', 'End of breakfast. Meat gained: ' + str(meatGained))
Example #10
0
    def parseResponse(self):
        entries = []
        entryPattern = PatternManager.getOrCompilePattern('clanLogEntry')
        for entryMatch in entryPattern.finditer(self.responseText):
            entry = {}
            date = entryMatch.group('date')
            entry['date'] = datetime.strptime(date, "%m/%d/%y, %I:%M%p")
            entry['userId'] = int(entryMatch.group('userId'))
            entry['userName'] = entryMatch.group('userName')
            action = entryMatch.group('action')
            foundAction = False

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogFax')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_FAX
                    entry['monster'] = match.group('monsterName')

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogAttack')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_ATTACK
                    entry['clanName'] = match.group('clanName')

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern(
                    'clanLogWhitelistAdd')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_WHITELISTED_PLAYER
                    entry['targetUserName'] = match.group('userName')
                    entry['targetUserId'] = int(match.group('userId'))

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern(
                    'clanLogPlayerJoinedAnotherClan')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_JOINED_ANOTHER_CLAN

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern(
                    'clanLogPlayerJoinedClanWhitelist')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_WHITELISTED_IN

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern(
                    'clanLogStashItemAdd')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_STASH_ADD
                    entry['itemName'] = match.group('itemName')
                    entry['quantity'] = int(
                        match.group('quantity').replace(',', ''))

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern(
                    'clanLogStashItemRemove')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_STASH_REMOVE
                    entry['itemName'] = match.group('itemName')
                    entry['quantity'] = int(
                        match.group('quantity').replace(',', ''))

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern(
                    'clanLogMeatSpentArmy')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_MEAT_SPENT_ARMY
                    entry['meat'] = int(match.group('meat').replace(',', ''))

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern(
                    'clanLogChangedRank')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_CHANGED_RANK
                    entry['targetUserName'] = match.group('userName')
                    entry['targetUserId'] = int(match.group('userId'))

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern(
                    'clanLogChangedTitle')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_CHANGED_RANK
                    entry['targetUserName'] = match.group('userName')
                    entry['targetUserId'] = int(match.group('userId'))
                    entry['clanTitle'] = match.group('clanTitle')

            if foundAction == False:
                Report.error("request", "Unknown clan log action: %s" % action)
                entry['type'] = CLAN_LOG_UNKNOWN
                entry['action'] = action

            entries.append(entry)

        self.responseData["entries"] = entries
Example #11
0
def parseChatMessages(text, isIncoming):
    """
    This function parses chats passed to it. The chats are assumed to come from a GetChatMessagesRequest.
    Returns a list of chats, each of which is a dictionary possibly containing the following keys:
        "type" : What kind of chat this is.  Current possible values are
            "channel"
            "listen"
            "listen:start"
            "listen:stop"
            "normal"
            "emote"
            "private"
            "system message"
            "mod warning"
            "mod announcement"
            "notification:kmail"
            "notification:carnival"
            "unknown"
        "currentChannel" : The current channel as indicated when sending a /c, /s, or /l request
        "otherChannels" : The other channels being listened to as indicated by a /l request
        "description" : The description of the current channel as indicated when sending a /c or /s request
        "channel" : The channel this chat message was posted from
        "userId" : The user id number of the user sending this chat message
        "userName" : The user name of the user sending this chat message
        "text" : The text of the current chat message
        "isMultiline" : A flag indicating whether this is a multiline message such as a haiku or a message from the Gothy Effect
    """

    # Prepare the patterns.
    htmlCommentPattern = PatternManager.getOrCompilePattern("htmlComment")
    htmlTagPattern = PatternManager.getOrCompilePattern("htmlTag")
    channelPattern = PatternManager.getOrCompilePattern("chatChannel")
    chatPattern = PatternManager.getOrCompilePattern("chatMessage")
    emotePattern = PatternManager.getOrCompilePattern("chatEmote")
    privateChatPattern = PatternManager.getOrCompilePattern("privateChat")
    newKmailPattern = PatternManager.getOrCompilePattern(
        "chatNewKmailNotification")
    linkPattern = PatternManager.getOrCompilePattern("chatLink")
    chatWhoPattern = PatternManager.getOrCompilePattern("chatWhoResponse")
    linkedPlayerPattern = PatternManager.getOrCompilePattern(
        "chatLinkedPlayer")
    multiLinePattern = PatternManager.getOrCompilePattern("chatMultiLineStart")
    multiEmotePattern = PatternManager.getOrCompilePattern(
        "chatMultiLineEmote")
    playerLoggedOnPattern = PatternManager.getOrCompilePattern(
        "chatPlayerLoggedOn")
    playerLoggedOffPattern = PatternManager.getOrCompilePattern(
        "chatPlayerLoggedOff")
    newCarnivalPattern = PatternManager.getOrCompilePattern("chatCarnival")

    # Get the chat messages.
    chats = []

    # Check for responses to outgoing chat commands.
    if isIncoming == False:
        outPrivatePattern = PatternManager.getOrCompilePattern(
            "outgoingPrivate")
        chatNewChannelPattern = PatternManager.getOrCompilePattern(
            "newChatChannel")
        chatListenPattern = PatternManager.getOrCompilePattern(
            "chatListenResponse")
        chatListenStartPattern = PatternManager.getOrCompilePattern(
            "chatStartListen")
        chatListenStopPattern = PatternManager.getOrCompilePattern(
            "chatStopListen")

        # See if it is an outgoing private message
        match = outPrivatePattern.search(text)
        if match:
            chat = {}
            chat["type"] = "private"
            chat["userName"] = match.group(2)
            chat["userId"] = int(match.group(1))
            chat["text"] = match.group(3).strip()
            text = text[:match.start()] + text[match.end():]
            chats.append(chat)

        # See if the user changed chat channels through /c or /s
        match = chatNewChannelPattern.search(text)
        if match:
            chat = {}
            chat["type"] = "channel"
            chat["currentChannel"] = match.group(1)
            chat["description"] = match.group(2).replace('<br>', '')
            text = text[:match.start()] + text[match.end():]
            chats.append(chat)

        # See if it is a /l response
        match = chatListenPattern.search(text)
        if match:
            chat = {}
            listen = match.group()
            currentPattern = PatternManager.getOrCompilePattern(
                "chatListenCurrent")
            otherPattern = PatternManager.getOrCompilePattern(
                "chatListenOthers")
            chat["type"] = "listen"
            chat["currentChannel"] = currentPattern.search(listen).group(1)
            other = []
            for channel in otherPattern.finditer(listen):
                other.append(channel.group(1))
            chat["otherChannels"] = other
            text = text[:match.start()] + text[match.end():]
            chats.append(chat)

        # See if it is a /l <channel> response to start listening to a channel
        match = chatListenStartPattern.search(text)
        if match:
            chat = {}
            chat["type"] = "listen:start"
            chat["channel"] = match.group(1)
            text = text[:match.start()] + text[match.end():]
            chats.append(chat)

        # See if it is a /l <channel> response to stop listening to a channel
        match = chatListenStopPattern.search(text)
        if match:
            chat = {}
            chat["type"] = "listen:stop"
            chat["channel"] = match.group(1)
            text = text[:match.start()] + text[match.end():]
            chats.append(chat)

    lines = text.split("<br>")

    for line in lines:
        line = htmlCommentPattern.sub('', line)
        line = line.strip()
        if len(line) == 0:
            continue

        # Mod Announcements and Mod Warnings leave leading </font> tags at the beginning of the next message
        # This method will remove them and also skip the line if that is all there is
        if line[:7] == "</font>":
            if len(line) == 7:
                continue
            else:
                line = line[7:].strip()

        # System Announcements leave leading </b></font> tags at the beginning of the next message
        # This method will remove them and also skip the line if that is all there is
        if line[:11] == "</b></font>":
            if len(line) == 11:
                continue
            else:
                line = line[11:].strip()

        chat = {}
        parsedChat = False

        # See if this message was posted to a different channel.
        match = channelPattern.search(line)
        if match:
            chat["channel"] = match.group(1)
            line = line[len(match.group(0)):]

        # See if this was a normal chat message.
        if parsedChat == False:
            match = chatPattern.search(line)
            if match:
                chat["type"] = "normal"
                chat["userId"] = int(match.group(1))
                chat["userName"] = match.group(2)

                # Check for special announcements
                if chat["userId"] == -1 or chat["userName"] == "System Message":
                    chat["type"] = "system message"
                elif chat["userName"] == "Mod Warning":
                    chat["type"] = "mod warning"
                elif chat["userName"] == "Mod Announcement":
                    chat["type"] = "mod announcement"

                chat["text"] = match.group(3).strip()
                parsedChat = True

        # See if this was an emote.
        if parsedChat == False:
            match = emotePattern.search(line)
            if match:
                chat["type"] = "emote"
                chat["userId"] = int(match.group(1))
                chat["userName"] = match.group(2)
                chat["text"] = match.group(3).strip()
                parsedChat = True

        if isIncoming == True:
            # See if a user logged in.
            if parsedChat == False:
                match = playerLoggedOnPattern.search(line)
                if match:
                    chat["type"] = "logonNotification"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    parsedChat = True

            # See if a user logged out.
            if parsedChat == False:
                match = playerLoggedOffPattern.search(line)
                if match:
                    chat["type"] = "logoffNotification"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    parsedChat = True

            # See if this was a private message.
            if parsedChat == False:
                match = privateChatPattern.search(line)
                if match:
                    chat["type"] = "private"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    chat["text"] = match.group(3).strip()
                    parsedChat = True

            # See if this is a new kmail notification.
            if parsedChat == False:
                match = newKmailPattern.search(line)
                if match:
                    chat["type"] = "notification:kmail"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    parsedChat = True

            # See if this is the start of a multi-line message (Gothy or Haiku)
            if parsedChat == False:
                match = multiLinePattern.search(line)
                if match:
                    chat["type"] = "normal"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    chat["isMultiline"] = True
                    chat["text"] = ""
                    parsedChat = True

            if parsedChat == False:
                match = newCarnivalPattern.search(line)
                if match:
                    chat["type"] = "notification:carnival"
                    chat["userName"] = match.group(2)
                    chat["userId"] = int(match.group(1))
                    parsedChat = True

            # See if this is the start of a multi-line emote (Gothy or Haiku)
            # I've seen a Haiku emote, don't know if Gothy will trigger for it
            if parsedChat == False:
                match = multiEmotePattern.search(line)
                if match:
                    chat["type"] = "emote"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    chat["isMultiline"] = True
                    chat["text"] = ""
                    parsedChat = True

        else:
            # See if this is a /who response.
            if parsedChat == False:
                if chatWhoPattern.search(line):
                    chat["type"] = "who"
                    chat["users"] = []
                    chatWhoPersonPattern = PatternManager.getOrCompilePattern(
                        "chatWhoPerson")
                    for match in chatWhoPersonPattern.finditer(line):
                        userClass = match.group(1)
                        userId = match.group(2)
                        userName = match.group(3)
                        userInfo = {"userId": userId, "userName": userName}
                        if userClass == "afk":
                            userInfo["isAway"] = True
                        chat["users"].append(userInfo)
                    parsedChat = True

        if parsedChat and "text" in chat:
            chat["text"] = cleanChatText(chat["text"])

        # Handle unrecognized chat messages.
        if parsedChat == False:
            # If the last chat was flagged as starting a multiline
            if len(chats) > 0 and "isMultiline" in chats[-1]:
                if chats[-1]["isMultiline"] == True:
                    if len(chats[-1]["text"]) > 0:
                        chats[-1]["text"] += "\n"
                    line = line.replace('<Br>', '\n')
                    cleanLine = cleanChatText(line)
                    cleanLine = cleanLine.replace('&nbsp;', '').strip()

                    chats[-1]["text"] += cleanLine

                    continue

            # If the last chat was flagged as a System or Mod Announcement, skip past the trailing tags
            elif len(chats) > 0:
                if "type" in chats[-1] and chats[-1]["type"] in [
                        "system message", "mod warning", "mod announcement"
                ]:
                    if line == "</b></font>":
                        continue

            # Any other case we aren't prepared to handle
            Report.error("bot", "Unknown message.  ResponseText = %s" % text)
            chat["type"] = "unknown"
            chat["text"] = StringUtils.htmlEntityDecode(line)

        chats.append(chat)

    return chats
Example #12
0
def parseChatMessages(text, isIncoming):
    """
    This function parses chats passed to it. The chats are assumed to come from a GetChatMessagesRequest.
    Returns a list of chats, each of which is a dictionary possibly containing the following keys:
        "type" : What kind of chat this is.  Current possible values are
            "channel"
            "listen"
            "listen:start"
            "listen:stop"
            "normal"
            "emote"
            "private"
            "system message"
            "mod warning"
            "mod announcement"
            "notification:kmail"
            "unknown"
        "currentChannel" : The current channel as indicated when sending a /c, /s, or /l request
        "otherChannels" : The other channels being listened to as indicated by a /l request
        "description" : The description of the current channel as indicated when sending a /c or /s request
        "channel" : The channel this chat message was posted from
        "userId" : The user id number of the user sending this chat message
        "userName" : The user name of the user sending this chat message
        "text" : The text of the current chat message
        "isMultiline" : A flag indicating whether this is a multiline message such as a haiku or a message from the Gothy Effect
    """
    
    # Prepare the patterns.
    htmlCommentPattern = PatternManager.getOrCompilePattern("htmlComment")
    htmlTagPattern = PatternManager.getOrCompilePattern("htmlTag")
    channelPattern = PatternManager.getOrCompilePattern("chatChannel")
    chatPattern = PatternManager.getOrCompilePattern("chatMessage")
    emotePattern = PatternManager.getOrCompilePattern("chatEmote")
    privateChatPattern = PatternManager.getOrCompilePattern("privateChat")
    newKmailPattern = PatternManager.getOrCompilePattern("chatNewKmailNotification")
    linkPattern = PatternManager.getOrCompilePattern("chatLink")
    chatWhoPattern = PatternManager.getOrCompilePattern("chatWhoResponse")
    linkedPlayerPattern = PatternManager.getOrCompilePattern("chatLinkedPlayer")
    multiLinePattern = PatternManager.getOrCompilePattern("chatMultiLineStart")
    multiEmotePattern = PatternManager.getOrCompilePattern("chatMultiLineEmote")
    playerLoggedOnPattern = PatternManager.getOrCompilePattern("chatPlayerLoggedOn")
    playerLoggedOffPattern = PatternManager.getOrCompilePattern("chatPlayerLoggedOff")

    # Get the chat messages.
    chats = []

    # Check for responses to outgoing chat commands.
    if isIncoming == False:
        outPrivatePattern = PatternManager.getOrCompilePattern("outgoingPrivate")
        chatNewChannelPattern = PatternManager.getOrCompilePattern("newChatChannel")
        chatListenPattern = PatternManager.getOrCompilePattern("chatListenResponse")
        chatListenStartPattern = PatternManager.getOrCompilePattern("chatStartListen")
        chatListenStopPattern = PatternManager.getOrCompilePattern("chatStopListen")

        # See if it is an outgoing private message
        match = outPrivatePattern.search(text)
        if match:
            chat = {}
            chat["type"] = "private"
            chat["userName"] = match.group(2)
            chat["userId"] = int(match.group(1))
            chat["text"] = match.group(3).strip()
            text = text[:match.start()] + text[match.end():]
            chats.append(chat)

        # See if the user changed chat channels through /c or /s
        match = chatNewChannelPattern.search(text)
        if match:
            chat = {}
            chat["type"] = "channel"
            chat["currentChannel"] = match.group(1)
            chat["description"] = match.group(2).replace('<br>','')
            text = text[:match.start()] + text[match.end():]
            chats.append(chat)

        # See if it is a /l response
        match = chatListenPattern.search(text)
        if match:
            chat = {}
            listen = match.group()
            currentPattern = PatternManager.getOrCompilePattern("chatListenCurrent")
            otherPattern = PatternManager.getOrCompilePattern("chatListenOthers")
            chat["type"] = "listen"
            chat["currentChannel"] = currentPattern.search(listen).group(1)
            other = []
            for channel in otherPattern.finditer(listen):
                other.append(channel.group(1))
            chat["otherChannels"] = other
            text = text[:match.start()] + text[match.end():]
            chats.append(chat)

        # See if it is a /l <channel> response to start listening to a channel
        match = chatListenStartPattern.search(text)
        if match:
            chat = {}
            chat["type"] = "listen:start"
            chat["channel"] = match.group(1)
            text = text[:match.start()] + text[match.end():]
            chats.append(chat)
        
        # See if it is a /l <channel> response to stop listening to a channel
        match = chatListenStopPattern.search(text)
        if match:
            chat = {}
            chat["type"] = "listen:stop"
            chat["channel"] = match.group(1)
            text = text[:match.start()] + text[match.end():]
            chats.append(chat)

    lines = text.split("<br>")

    for line in lines:
        line = htmlCommentPattern.sub('', line)
        line = line.strip()
        if len(line) == 0:
            continue

        # Mod Announcements and Mod Warnings leave leading </font> tags at the beginning of the next message
        # This method will remove them and also skip the line if that is all there is
        if line[:7] == "</font>":
            if len(line) == 7:
                continue
            else:
                line = line[7:].strip()

        # System Announcements leave leading </b></font> tags at the beginning of the next message
        # This method will remove them and also skip the line if that is all there is
        if line[:11] == "</b></font>":
            if len(line) == 11:
                continue
            else:
                line = line[11:].strip()

        chat = {}
        parsedChat = False

        # See if this message was posted to a different channel.
        match = channelPattern.search(line)
        if match:
            chat["channel"] = match.group(1)
            line = line[len(match.group(0)):]

        # See if this was a normal chat message.
        if parsedChat == False:
            match = chatPattern.search(line)
            if match:
                chat["type"] = "normal"
                chat["userId"] = int(match.group(1))
                chat["userName"] = match.group(2)

                # Check for special announcements
                if chat["userId"] == -1 or chat["userName"] == "System Message":
                    chat["type"] = "system message"
                elif chat["userName"] == "Mod Warning":
                    chat["type"] = "mod warning"
                elif chat["userName"] == "Mod Announcement":
                    chat["type"] = "mod announcement"

                chat["text"] = match.group(3).strip()
                parsedChat = True

        # See if this was an emote.
        if parsedChat == False:
            match = emotePattern.search(line)
            if match:
                chat["type"] = "emote"
                chat["userId"] = int(match.group(1))
                chat["userName"] = match.group(2)
                chat["text"] = match.group(3).strip()
                parsedChat = True

        if isIncoming == True:
            # See if a user logged in.
            if parsedChat == False:
                match = playerLoggedOnPattern.search(line)
                if match:
                    chat["type"] = "logonNotification"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    parsedChat = True

            # See if a user logged out.
            if parsedChat == False:
                match = playerLoggedOffPattern.search(line)
                if match:
                    chat["type"] = "logoffNotification"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    parsedChat = True

            # See if this was a private message.
            if parsedChat == False:
                match = privateChatPattern.search(line)
                if match:
                    chat["type"] = "private"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    chat["text"] = match.group(3).strip()
                    parsedChat = True

            # See if this is a new kmail notification.
            if parsedChat == False:
                match = newKmailPattern.search(line)
                if match:
                    chat["type"] = "notification:kmail"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    parsedChat = True

            # See if this is the start of a multi-line message (Gothy or Haiku)
            if parsedChat == False:
                match = multiLinePattern.search(line)
                if match:
                    chat["type"] = "normal"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    chat["isMultiline"] = True
                    chat["text"] = ""
                    parsedChat = True

            # See if this is the start of a multi-line emote (Gothy or Haiku)
            # I've seen a Haiku emote, don't know if Gothy will trigger for it
            if parsedChat == False:
                match = multiEmotePattern.search(line)
                if match:
                    chat["type"] = "emote"
                    chat["userId"] = int(match.group(1))
                    chat["userName"] = match.group(2)
                    chat["isMultiline"] = True
                    chat["text"] = ""
                    parsedChat = True

        else:
            # See if this is a /who response.
            if parsedChat == False:
                if chatWhoPattern.search(line):
                    chat["type"] = "who"
                    chat["users"] = []
                    chatWhoPersonPattern = PatternManager.getOrCompilePattern("chatWhoPerson")
                    for match in chatWhoPersonPattern.finditer(line):
                        userClass = match.group(1)
                        userId = match.group(2)
                        userName = match.group(3)
                        userInfo = {"userId" : userId, "userName" : userName}
                        if userClass == "afk":
                            userInfo["isAway"] = True
                        chat["users"].append(userInfo)
                    parsedChat = True

        if parsedChat and "text" in chat:
            chat["text"] = cleanChatText(chat["text"])

        # Handle unrecognized chat messages.
        if parsedChat == False:
            # If the last chat was flagged as starting a multiline
            if len(chats) > 0 and "isMultiline" in chats[-1]:
                if chats[-1]["isMultiline"] == True:
                    if len(chats[-1]["text"]) > 0:
                        chats[-1]["text"] += "\n"
                    line = line.replace('<Br>','\n')
                    cleanLine = cleanChatText(line)
                    cleanLine = cleanLine.replace('&nbsp;','').strip()

                    chats[-1]["text"] += cleanLine

                    continue

            # If the last chat was flagged as a System or Mod Announcement, skip past the trailing tags
            elif len(chats) > 0:
                if "type" in chats[-1] and chats[-1]["type"] in ["system message", "mod warning", "mod announcement"]:
                    if line == "</b></font>":
                        continue

            # Any other case we aren't prepared to handle
            Report.error("bot", "Unknown message.  ResponseText = %s" % text)
            chat["type"] = "unknown"
            chat["text"] = StringUtils.htmlEntityDecode(line)

        chats.append(chat)

    return chats
Example #13
0
def botProcessKmail(context, **kwargs):
    returnCode = FilterManager.CONTINUE
    message = kwargs['kmail']
    bot = kwargs['bot']

    user_name = str(message['userName'])
    user_id = str(message['userId'])
    current_time = time.time()
    cmd = BotUtils.getKmailCommand(message)
    meat = message['meat']
    items = message['items']

    # Our response
    response = ''
    # Should items and meat be sent back?
    return_goodies = True
    # Should a candy heart be sent?
    send_heart = False

    # if 1 arrow was sent and the kmail is empty, interpret it as "arrow"
    if cmd == "" and len(items) == 1 and items[0]['id'] == ITEM_ID_ARROW and items[0]['quantity'] == 1 and meat == 0:
        cmd = 'arrow'

    if cmd == 'arrow':
        # Handle arrow request
        if len(items) == 1 and items[0]['id'] == ITEM_ID_ARROW and items[0]['quantity'] == 1 and meat == 0:
            # Everything is okay
            try:
                Report.info('bot', 'Firing arrow at player: ' + user_name)
                arrowreq = CursePlayerRequest(bot.session, user_id, ITEM_ID_ARROW)
                arrowreq.doRequest()
                return_goodies = False
            except Error.Error as err:
                if err.code == Error.ITEM_NOT_FOUND:
                    response = aleabot.config.get('error_arrow_no_arrows')
                elif err.code == Error.USER_NOT_FOUND:
                    response = aleabot.config.get('error_arrow_player_not_found')
                elif err.code == Error.USER_IN_HARDCORE_RONIN:
                    response = aleabot.config.get('error_arrow_ronin')
                elif err.code == Error.ALREADY_COMPLETED:
                    response = aleabot.config.get('error_arrow_already_hit')
                else:
                    response = aleabot.config.get('error_arrow_generic')

        elif len(items) == 0 and meat == 0:
            Report.warning('bot', 'Arrow request without arrow from ' + user_name)
            response = aleabot.config.get('kmailtext_arrow_notattached')

        else:
            Report.warning('bot', 'Arrow request with extra items or meat from ' + user_name)
            response = aleabot.config.get('kmailtext_arrow_extraattached')

    elif cmd == 'donate' or cmd == 'donation':
        # Handle donation
        if len(items) == 0 and meat == 0:
            # Empty donation kmail?
            Report.warning('bot', 'Empty donation received from ' + user_name)
            response = aleabot.config.get('kmailtext_donate_empty')
        else:
            Report.info('bot', 'Donation received from ' + user_name)
            response = aleabot.config.get('kmailtext_donate_thanks')
            return_goodies = False
            send_heart = True

    else:
        # Handle unknown command
        Report.warning('bot', 'Unknown kmail command: ' + cmd)
        response = aleabot.config.get('kmailtext_unknown')

    # Send our response
    if response != '' or (return_goodies and (len(items) != 0 or meat != 0)):
        Report.info('bot', 'Responding to kmail')
        response_kmail = {}
        response_kmail['userId'] = message['userId']
        response_kmail['text'] = format_reply(response + '\n\n' + aleabot.config.get('kmailtext_quote'), user_name=user_name, user_id=user_id, current_time=current_time) + '\n' + quote_kmail(message)
        if return_goodies:
            response_kmail['items'] = items
            response_kmail['meat'] = meat
        try:
            bot.sendKmail(response_kmail)
        except Error.Error as err:
            if err.code == Error.USER_IN_HARDCORE_RONIN:
                Report.error('bot', 'Tried to send items and meat back, but user is in Hardcore or Ronin!')
                response_kmail2 = {}
                response_kmail2['userId'] = message['userId']
                response_kmail2['text'] = format_reply(response + '\n\n' + aleabot.config.get('kmailtext_quote_ronin'), user_name=user_name, user_id=user_id, curent_time=current_time) + '\n' + quote_kmail(message)
                try:
                    bot.sendKmail(response_kmail2)
                except Error.Error as err2:
                    Report.error('bot', 'Unexpected error while sending response_kmail2: ' + str(err2))
            else:
                Report.error('bot', 'Unexpected error while sending response_kmail: ' + str(err))

    # Send a candy heart
    if send_heart:
        try:
            Report.info('bot', 'Sending candy heart to player: ' + user_name)
            heartreq = CursePlayerRequest(bot.session, user_id, ITEM_ID_CANDYHEART)
            heartreq.requestData['texta'] = 'THANK'
            heartreq.requestData['textb'] = 'YOU'
            heartreq.doRequest()
        except Error.Error as err:
            Report.error('bot', 'Couldn\'t send candy heart: ' + str(err))

    returnCode = FilterManager.FINISHED
    return returnCode
Example #14
0
    def parseResponse(self):
        entries = []
        entryPattern = PatternManager.getOrCompilePattern('clanLogEntry')
        for entryMatch in entryPattern.finditer(self.responseText):
            entry = {}
            date = entryMatch.group('date')
            entry['date'] = datetime.strptime(date, "%m/%d/%y, %I:%M%p")
            entry['userId'] = int(entryMatch.group('userId'))
            entry['userName'] = entryMatch.group('userName')
            action = entryMatch.group('action')
            foundAction = False
            
            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogFax')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_FAX
                    entry['monster'] = match.group('monsterName')

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogAttack')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_ATTACK
                    entry['clanName'] = match.group('clanName')

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogWhitelistAdd')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_WHITELISTED_PLAYER
                    entry['targetUserName'] = match.group('userName')
                    entry['targetUserId'] = int(match.group('userId'))

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogPlayerJoinedAnotherClan')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_JOINED_ANOTHER_CLAN

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogPlayerJoinedClanWhitelist')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_WHITELISTED_IN

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogStashItemAdd')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_STASH_ADD
                    entry['itemName'] = match.group('itemName')
                    entry['quantity'] = int(match.group('quantity').replace(',', ''))

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogStashItemRemove')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_STASH_REMOVE
                    entry['itemName'] = match.group('itemName')
                    entry['quantity'] = int(match.group('quantity').replace(',', ''))

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogMeatSpentArmy')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_MEAT_SPENT_ARMY
                    entry['meat'] = int(match.group('meat').replace(',', ''))

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogChangedRank')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_CHANGED_RANK
                    entry['targetUserName'] = match.group('userName')
                    entry['targetUserId'] = int(match.group('userId'))

            if foundAction == False:
                pattern = PatternManager.getOrCompilePattern('clanLogChangedTitle')
                match = pattern.match(action)
                if match:
                    foundAction = True
                    entry['type'] = CLAN_LOG_CHANGED_RANK
                    entry['targetUserName'] = match.group('userName')
                    entry['targetUserId'] = int(match.group('userId'))
                    entry['clanTitle'] = match.group('clanTitle')

            if foundAction == False:
                Report.error("request", "Unknown clan log action: %s" % action)
                entry['type'] = CLAN_LOG_UNKNOWN
                entry['action'] = action

            entries.append(entry)

        self.responseData["entries"] = entries