示例#1
0
def cleanChatText(dirtyText):
    "This functions parses player links and external links in the body of the chat text, and cleans any html tags"

    linkPattern = PatternManager.getOrCompilePattern("chatLink")
    linkedPlayerPattern = PatternManager.getOrCompilePattern(
        "chatLinkedPlayer")
    htmlTagPattern = PatternManager.getOrCompilePattern("htmlTag")

    text = dirtyText

    # Parse user links.
    text = linkedPlayerPattern.sub(r'\2', text)

    # Parse misc links.
    match = linkPattern.search(text)
    while match != None:
        url = match.group(1)
        urlIndex = 0
        textStart = match.end()
        textEnd = textStart
        found = False
        foundTag = False
        while found == False:
            if foundTag == True:
                if text[textEnd] == '>':
                    foundTag = False
            elif text[textEnd] == '<':
                foundTag = True
            elif text[textEnd] == url[urlIndex]:
                urlIndex += 1

            # Always advance the textEnd
            textEnd += 1

            if urlIndex == len(url):
                found = True

        newText = text[:match.start()] + url + text[textEnd:]
        text = newText
        match = linkPattern.search(text)

    # Decode HTML entities.
    text = StringUtils.htmlEntityDecode(text)

    # Clean up the text.
    text = htmlTagPattern.sub('', text)

    return text
示例#2
0
文件: ChatUtils.py 项目: Alecat/pykol
def cleanChatText(dirtyText):
    "This functions parses player links and external links in the body of the chat text, and cleans any html tags"

    linkPattern = PatternManager.getOrCompilePattern("chatLink")
    linkedPlayerPattern = PatternManager.getOrCompilePattern("chatLinkedPlayer")
    htmlTagPattern = PatternManager.getOrCompilePattern("htmlTag")

    text = dirtyText

    # Parse user links.
    text = linkedPlayerPattern.sub(r'\2', text)

    # Parse misc links.
    match = linkPattern.search(text)
    while match != None:
        url = match.group(1)
        urlIndex = 0
        textStart = match.end()
        textEnd = textStart
        found = False
        while found == False:
            if text[textEnd] == url[urlIndex]:
                textEnd += 1
                urlIndex += 1
            elif text[textEnd] == ' ':
                textEnd += 1

            if urlIndex == len(url):
                found = True

        newText = text[:match.start()] + url + text[textEnd:]
        text = newText
        match = linkPattern.search(text)

    # Decode HTML entities.
    text = StringUtils.htmlEntityDecode(text)

    # Clean up the text.
    text = htmlTagPattern.sub('', text)

    return text
示例#3
0
    def parseResponse(self):
        """
        Parses through the response and constructs an array of messages.
        Each message is represented as a dictionary with the following
        keys:

              id -- The integer identifier for the message.
          userId -- The ID of the user who sent or received this message.
        userName -- The name of the user who sent or received this message.
            date -- The date the message was sent as a datetime object.
            text -- The contents of the message.
           items -- An array of items attached to the message.
            meat -- The amount of meat sent with the message.
        """

        fullMessagePattern = PatternManager.getOrCompilePattern('fullMessage')
        whitespacePattern = PatternManager.getOrCompilePattern('whitespace')
        singleItemPattern = PatternManager.getOrCompilePattern('acquireSingleItem')
        multiItemPattern = PatternManager.getOrCompilePattern('acquireMultipleItems')
        meatPattern = PatternManager.getOrCompilePattern('gainMeat')
        brickPattern = PatternManager.getOrCompilePattern('brickMessage')
        coffeePattern = PatternManager.getOrCompilePattern('coffeeMessage')
        candyHeartPattern = PatternManager.getOrCompilePattern('candyHeartMessage')

        messages = []

        for message in fullMessagePattern.finditer(self.responseText):
            messageId = int(message.group(1))
            userId = int(message.group(2))
            userName = message.group(3).strip()

            dateStr = message.group(4).strip()
            try:
                date = datetime.strptime(dateStr, "%A, %B %d, %Y, %I:%M%p")
            except ValueError:
                date = dateStr

            rawText = message.group(5).strip()
            index = rawText.find('<center')
            if index >= 0:
                text = rawText[:index].strip()
            else:
                text = rawText.strip()

            # Get rid of extraneous spaces, tabs, or new lines.
            text = text.replace("\r\n", "\n")
            text = whitespacePattern.sub(' ', text)
            text = text.replace("<br />\n", "\n")
            text = text.replace("<br/>\n", "\n")
            text = text.replace("<br>\n", "\n")
            text = text.replace("\n<br />", "\n")
            text = text.replace("\n<br/>", "\n")
            text = text.replace("\n<br>", "\n")
            text = text.replace("<br />", "\n")
            text = text.replace("<br/>", "\n")
            text = text.replace("<br>", "\n")
            text = text.strip()

            # KoL encodes all of the HTML entities in the message. Let's decode them to get the real text.
            text = StringUtils.htmlEntityDecode(text)

            m = {"id":messageId, "userId":userId, "userName":userName, "date":date, "text":text}

            # Find the items attached to the message.
            items = []
            for match in singleItemPattern.finditer(rawText):
                descId = int(match.group(1))
                try:
                    item = ItemDatabase.getOrDiscoverItemFromDescId(descId, self.session)
                    item["quantity"] = 1
                    items.append(item)
                except Error.Error as e:
                    if e.code == Error.ITEM_NOT_FOUND and self._allowUnknown:
                        items.append({'id': None, 
                                      'quantity': 1, 
                                      'descId': descId})
                    else:
                        raise
            for match in multiItemPattern.finditer(rawText):
                descId = int(match.group(1))
                quantity = int(match.group(2).replace(',', ''))
                try:
                    item = ItemDatabase.getOrDiscoverItemFromDescId(descId, self.session)
                    item["quantity"] = quantity
                    items.append(item)
                except Error.Error as e:
                    if e.code == Error.ITEM_NOT_FOUND and self._allowUnknown:
                        items.append({'id': None, 
                                      'quantity': quantity, 
                                      'descId': descId})
                    else:
                        raise
            m["items"] = items

            # Find how much meat was attached to the message.
            meat = 0
            meatMatch = meatPattern.search(rawText)
            if meatMatch:
                meat = int(meatMatch.group(1).replace(',', ''))
            m["meat"] = meat

            # Handle special messages.
            if brickPattern.search(rawText):
                m["messageType"] = "brick"
            elif coffeePattern.search(rawText):
                m["messageType"] = "coffeeCup"
            elif candyHeartPattern.search(rawText):
                m["messageType"] = "candyHeart"
            else:
                m["messageType"] = "normal"

            messages.append(m)

        self.responseData["kmails"] = messages
示例#4
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
示例#5
0
文件: ChatUtils.py 项目: Alecat/pykol
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
示例#6
0
    def parseResponse(self):
        """
        Parses through the response and constructs an array of messages.
        Each message is represented as a dictionary with the following
        keys:

              id -- The integer identifier for the message.
          userId -- The ID of the user who sent or received this message.
        userName -- The name of the user who sent or received this message.
            date -- The date the message was sent as a datetime object.
            text -- The contents of the message.
           items -- An array of items attached to the message.
            meat -- The amount of meat sent with the message.
        """

        fullMessagePattern = PatternManager.getOrCompilePattern('fullMessage')
        whitespacePattern = PatternManager.getOrCompilePattern('whitespace')
        singleItemPattern = PatternManager.getOrCompilePattern(
            'acquireSingleItem')
        multiItemPattern = PatternManager.getOrCompilePattern(
            'acquireMultipleItems')
        meatPattern = PatternManager.getOrCompilePattern('gainMeat')
        brickPattern = PatternManager.getOrCompilePattern('brickMessage')
        coffeePattern = PatternManager.getOrCompilePattern('coffeeMessage')
        candyHeartPattern = PatternManager.getOrCompilePattern(
            'candyHeartMessage')

        messages = []

        for message in fullMessagePattern.finditer(self.responseText):
            messageId = int(message.group(1))
            userId = int(message.group(2))
            userName = message.group(3).strip()

            dateStr = message.group(4).strip()
            try:
                date = datetime.strptime(dateStr, "%A, %B %d, %Y, %I:%M%p")
            except ValueError:
                date = dateStr

            rawText = message.group(5).strip()
            index = rawText.find('<center')
            if index >= 0:
                text = rawText[:index].strip()
            else:
                text = rawText.strip()

            # Get rid of extraneous spaces, tabs, or new lines.
            text = text.replace("\r\n", "\n")
            text = whitespacePattern.sub(' ', text)
            text = text.replace("<br />\n", "\n")
            text = text.replace("<br/>\n", "\n")
            text = text.replace("<br>\n", "\n")
            text = text.replace("\n<br />", "\n")
            text = text.replace("\n<br/>", "\n")
            text = text.replace("\n<br>", "\n")
            text = text.replace("<br />", "\n")
            text = text.replace("<br/>", "\n")
            text = text.replace("<br>", "\n")
            text = text.strip()

            # KoL encodes all of the HTML entities in the message. Let's decode them to get the real text.
            text = StringUtils.htmlEntityDecode(text)

            m = {
                "id": messageId,
                "userId": userId,
                "userName": userName,
                "date": date,
                "text": text
            }

            # Find the items attached to the message.
            items = []
            for match in singleItemPattern.finditer(rawText):
                descId = int(match.group(1))
                try:
                    item = ItemDatabase.getOrDiscoverItemFromDescId(
                        descId, self.session)
                    item["quantity"] = 1
                    items.append(item)
                except Error.Error as e:
                    if e.code == Error.ITEM_NOT_FOUND and self._allowUnknown:
                        items.append({
                            'id': None,
                            'quantity': 1,
                            'descId': descId
                        })
                    else:
                        raise
            for match in multiItemPattern.finditer(rawText):
                descId = int(match.group(1))
                quantity = int(match.group(2).replace(',', ''))
                try:
                    item = ItemDatabase.getOrDiscoverItemFromDescId(
                        descId, self.session)
                    item["quantity"] = quantity
                    items.append(item)
                except Error.Error as e:
                    if e.code == Error.ITEM_NOT_FOUND and self._allowUnknown:
                        items.append({
                            'id': None,
                            'quantity': quantity,
                            'descId': descId
                        })
                    else:
                        raise
            m["items"] = items

            # Find how much meat was attached to the message.
            meat = 0
            meatMatch = meatPattern.search(rawText)
            if meatMatch:
                meat = int(meatMatch.group(1).replace(',', ''))
            m["meat"] = meat

            # Handle special messages.
            if brickPattern.search(rawText):
                m["messageType"] = "brick"
            elif coffeePattern.search(rawText):
                m["messageType"] = "coffeeCup"
            elif candyHeartPattern.search(rawText):
                m["messageType"] = "candyHeart"
            else:
                m["messageType"] = "normal"

            messages.append(m)

        self.responseData["kmails"] = messages
示例#7
0
文件: ChatUtils.py 项目: ZJ/pykol
def parseMessages(text, isGet):
	# 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")
	
	# Get the chat messages.
	chats = []
	lines = text.split("<br>")
		
	for line in lines:
		line = htmlCommentPattern.sub('', line)
		line = line.strip()
		if len(line) == 0:
			continue
		
		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)
				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 isGet:
			# 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
			
		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):
						userId = match.group(1)
						userName = match.group(2)
						chat["users"].append({"userId":userId, "userName":userName})
					parsedChat = True
		
		if parsedChat and "text" in chat:
			# Parse user links.
			chat["text"] = linkedPlayerPattern.sub(r'\2', chat["text"])
		
			# Parse misc links.
			match = linkPattern.search(chat["text"])
			while match != None:
				url = match.group(1)
				urlIndex = 0
				textStart = match.end()
				textEnd = textStart
				found = False
				while found == False:
					if chat["text"][textEnd] == url[urlIndex]:
						textEnd += 1
						urlIndex += 1
					elif chat["text"][textEnd] == ' ':
						textEnd += 1
						
					if urlIndex == len(url) - 1:
						found = True
				
				newText = chat["text"][:match.start()] + url + chat["text"][textEnd+1:]
				chat["text"] = newText
				match = linkPattern.search(chat["text"])
			
			# Decode HTML entities.
			chat["text"] = StringUtils.htmlEntityDecode(chat["text"])
		
			# Clean up the text.
			chat["text"] = htmlTagPattern.sub('', chat["text"])
		
		# Handle unrecognized chat messages.
		if parsedChat == False:
			chat["type"] = "unknown"
			chat["text"] = StringUtils.htmlEntityDecode(line)
			
		chats.append(chat)
	
	return chats
示例#8
0
    def parseResponse(self):
        """
        Parses through the response and constructs an array of messages.
        Each message is represented as a dictionary with the following
        keys:

              id -- The integer identifier for the message.
          userId -- The ID of the user who sent or received this message.
        userName -- The name of the user who sent or received this message.
            date -- The date the message was sent as a datetime object.
            text -- The contents of the message.
           items -- An array of items attached to the message.
            meat -- The amount of meat sent with the message.
        """

        fullMessagePattern = PatternManager.getOrCompilePattern('fullMessage')
        whitespacePattern = PatternManager.getOrCompilePattern('whitespace')
        singleItemPattern = PatternManager.getOrCompilePattern(
            'acquireSingleItem')
        multiItemPattern = PatternManager.getOrCompilePattern(
            'acquireMultipleItems')
        meatPattern = PatternManager.getOrCompilePattern('gainMeat')
        brickPattern = PatternManager.getOrCompilePattern('brickMessage')
        coffeePattern = PatternManager.getOrCompilePattern('coffeeMessage')
        candyHeartPattern = PatternManager.getOrCompilePattern(
            'candyHeartMessage')

        _linkParser = re.compile(
            r'<a target=_blank href="([^"]*)"><font color=blue>\[link\]</font></a>'
        )

        messages = []

        for message in fullMessagePattern.finditer(self.responseText):
            messageId = int(message.group(1))
            userId = int(message.group(2))
            userName = message.group(3).strip()

            dateStr = message.group(4).strip()
            try:
                date = datetime.strptime(dateStr, "%A, %B %d, %Y, %I:%M%p")
            except ValueError:
                date = dateStr

            rawText = message.group(5).strip()
            index = rawText.find('<center')
            if index >= 0:
                text = rawText[:index].strip()
            else:
                text = rawText.strip()

            # Get rid of extraneous spaces, tabs, or new lines.
            text = text.replace("\r\n", "\n")
            text = whitespacePattern.sub(' ', text)
            text = text.replace("<br />\n", "\n")
            text = text.replace("<br/>\n", "\n")
            text = text.replace("<br>\n", "\n")
            text = text.replace("\n<br />", "\n")
            text = text.replace("\n<br/>", "\n")
            text = text.replace("\n<br>", "\n")
            text = text.replace("<br />", "\n")
            text = text.replace("<br/>", "\n")
            text = text.replace("<br>", "\n")
            text = text.strip()

            # parse links
            oldText, text = text, ""
            curPos = 0
            curMatch = _linkParser.search(oldText)
            while curMatch is not None and curPos <= len(oldText):
                toAdd = ""
                oldPos = curPos
                matchStart = curMatch.start()
                link = curMatch.group(1)
                if curPos < matchStart:
                    toAdd += oldText[curPos:matchStart]
                toAdd += link

                # remove the link text, which may have spaces
                curPos = curMatch.end()
                while link:
                    curChar = oldText[curPos]
                    if curChar in whitespace:
                        curPos += 1
                    elif curChar == link[0]:
                        link = link[1:]
                        curPos += 1
                    else:
                        # ran into a match error -- roll back everything
                        toAdd = oldText[oldPos:matchStart + 1]
                        curPos = matchStart + 1
                        break
                text += toAdd
                toAdd = ""
                curMatch = _linkParser.search(oldText, pos=curPos)
            text += oldText[curPos:]

            # KoL encodes all of the HTML entities in the message. Let's decode them to get the real text.
            text = StringUtils.htmlEntityDecode(text)

            m = {
                "id": messageId,
                "userId": userId,
                "userName": userName,
                "date": date,
                "text": text
            }

            # Find the items attached to the message.
            items = []
            for match in singleItemPattern.finditer(rawText):
                descId = int(match.group(1))
                try:
                    item = ItemDatabase.getOrDiscoverItemFromDescId(
                        descId, self.session)
                    item["quantity"] = 1
                    items.append(item)
                except Error.Error as e:
                    if e.code == Error.ITEM_NOT_FOUND and self._allowUnknown:
                        items.append({
                            'id': None,
                            'quantity': 1,
                            'descId': descId
                        })
                    else:
                        raise
            for match in multiItemPattern.finditer(rawText):
                descId = int(match.group(1))
                quantity = int(match.group(2).replace(',', ''))
                try:
                    item = ItemDatabase.getOrDiscoverItemFromDescId(
                        descId, self.session)
                    item["quantity"] = quantity
                    items.append(item)
                except Error.Error as e:
                    if e.code == Error.ITEM_NOT_FOUND and self._allowUnknown:
                        items.append({
                            'id': None,
                            'quantity': quantity,
                            'descId': descId
                        })
                    else:
                        raise
            m["items"] = items

            # Find how much meat was attached to the message.
            meat = 0
            meatMatch = meatPattern.search(rawText)
            if meatMatch:
                meat = int(meatMatch.group(1).replace(',', ''))
            m["meat"] = meat

            # Handle special messages.
            if brickPattern.search(rawText):
                m["messageType"] = "brick"
            elif coffeePattern.search(rawText):
                m["messageType"] = "coffeeCup"
            elif candyHeartPattern.search(rawText):
                m["messageType"] = "candyHeart"
            else:
                m["messageType"] = "normal"

            messages.append(m)

        self.responseData["kmails"] = messages