Пример #1
0
    def process_message(self, message, modified=False, initial_salvo=False, user_banned=False):
        """
        Called by the communicator when a new or updated message has been received.
        :type message: vbcbbot.chatbox_connector.ChatboxMessage
        """
        if modified or initial_salvo:
            return

        lower_sender_name = message.user_name.lower()

        # parse and strip
        body = remove_control_characters_and_strip(message.decompiled_body())

        if not user_banned:
            self.potential_stats(message, body)
            self.potential_spy(message, body)

        # spy on messages from banned users too

        if lower_sender_name in self.lowercase_user_names_to_triggers:
            for trigger in self.lowercase_user_names_to_triggers[lower_sender_name]:
                cursor = self.database.cursor()
                for match in trigger.pattern.finditer(body):
                    # trigger matched. log this.
                    cursor.execute(
                        "INSERT INTO incidents (trigger_id, message_id, timestamp) VALUES (?, ?, ?)",
                        (trigger.trigger_id, message.id, message.timestamp)
                    )
                self.database.commit()
Пример #2
0
    def process_message(self, message, modified=False, initial_salvo=False, user_banned=False):
        if modified or initial_salvo or user_banned:
            return

        body = remove_control_characters_and_strip(message.decompiled_body())
        if is_down_re.match(body) is None:
            return

        response = ur.urlopen(self.api_url)
        response_data = response.read().decode("us-ascii")

        pieces = response_data.split(" ")
        if len(pieces) != 3:
            logger.debug("unexpected server answer {0} for nickname {1}".format(
                repr(response_data)
            ))
            self.connector.send_message(
                random.choice(self.unknown_messages).format(sender=message.user_name)
            )
            return

        (status, since_string, last_update_string) = pieces

        try:
            since = time.strftime("%Y-%m-%d %H:%M", time.localtime(int(since_string)))
        except ValueError:
            since = -1

        try:
            last_update = time.strftime("%Y-%m-%d %H:%M", time.localtime(int(last_update_string)))
        except ValueError:
            last_update = -1

        pick_one = self.unknown_messages
        if status == "0":
            pick_one = self.up_messages
        elif status == "1":
            pick_one = self.down_messages

        outgoing = random.choice(pick_one)

        self.connector.send_message(
            outgoing.format(sender=message.user_name, since=since, last_update=last_update)
        )
Пример #3
0
    def potential_message_send(self, message, body, lower_sender_name):
        match = msg_trigger.match(body)
        if match is None:
            return

        recipient_and_message = match.group(3)
        try:
            (target_name, send_body) = split_recipient_and_message(recipient_and_message)
        except ValueError as e:
            self.connector.send_message("{0}: {1}".format(message.user_name, str(e)))
            return

        target_name = remove_control_characters_and_strip(target_name)
        lower_target_name = target_name.lower()
        send_body = remove_control_characters_and_strip(send_body)

        if len(lower_target_name) == 0:
            self.connector.send_message("{0}: You must specify a name to deliver to!".format(message.user_name))
            return
        elif len(send_body) == 0:
            self.connector.send_message("{0}: You must specify a message to deliver!".format(message.user_name))
            return
        elif lower_target_name == self.connector.username.lower():
            self.connector.send_message("{0}: Sorry, I don\u2019t deliver to myself!".format(message.user_name))
            return

        try:
            user_info = self.connector.get_user_id_and_nickname_for_uncased_name(target_name)
        except chatbox_connector.TransferError:
            self.connector.send_message(
                "[noparse]{1}[/noparse]: Sorry, I couldn\u2019t verify if \u201c{0}\u201d exists because the forum "
                "isn\u2019t being cooperative. Please try again later!".format(target_name, message.user_name)
            )
            return

        if user_info is None:
            colon_info = ""
            if ":" in send_body:
                colon_info = " (You may escape colons in usernames using a backslash.)"
            elif len(target_name) > 32:
                colon_info = " (You must place a colon between the username and the message.)"
            self.connector.send_message(
                "[noparse]{1}[/noparse]: Sorry, I don\u2019t know \u201c{0}\u201d.{2}".format(
                    target_name, message.user_name, colon_info
                )
            )
            return

        # check ignore list
        cursor = self.database.cursor()
        cursor.execute(
            "SELECT COUNT(*) FROM ignore_list WHERE sender_folded=? AND recipient_folded=?",
            (lower_sender_name, lower_target_name)
        )
        ignore_count = None
        for row in cursor:
            ignore_count = row[0]
        cursor.close()

        if ignore_count != 0:
            logger.debug("{0} wants to send a message {1} to {2}, but the recipient is ignoring the sender".format(
                repr(message.user_name), repr(send_body), repr(target_name)
            ))
            self.connector.send_message(
                (
                    "[noparse]{0}[/noparse]: Can\u2019t send a message to [i][noparse]{1}[/noparse][/i]\u2014"
                    "they\u2019re ignoring you."
                ).format(
                    message.user_name,
                    user_info[1]
                )
            )
            return

        logger.debug("{0} sending message {1} to {2}".format(
            repr(message.user_name), repr(send_body), repr(target_name)
        ))

        cursor = self.database.cursor()
        cursor.execute(
            "INSERT INTO messages "
            "(message_id, timestamp, sender_original, recipient_folded, body) "
            "VALUES (?, ?, ?, ?, ?)",
            (message.id, message.timestamp, message.user_name, lower_target_name, send_body)
        )
        self.database.commit()

        if match.group(1) == "":
            if lower_target_name == lower_sender_name:
                self.connector.send_message(
                    ("[noparse]{0}[/noparse]: Talking to ourselves? Well, no skin off my back. I\u2019ll deliver your "
                     "message to you right away. ;)").format(message.user_name)
                )
            else:
                sent_template = (
                    "[noparse]{1}[/noparse]: Aye-aye! I\u2019ll deliver your message to [i][noparse]{0}[/noparse][/i] next "
                    "time I see \u2019em!"
                )
                self.connector.send_message(sent_template.format(user_info[1], message.user_name))
Пример #4
0
    def process_message(self, message, modified=False, initial_salvo=False, user_banned=False):
        """
        Called by the communicator when a new or updated message has been received.
        :type message: vbcbbot.chatbox_connector.ChatboxMessage
        """
        if modified or initial_salvo or message.user_name == self.connector.username:
            return

        lower_sender_name = message.user_name.lower()

        # parse and strip
        body = remove_control_characters_and_strip(message.decompiled_body())

        if not user_banned:
            # process potential message send
            self.potential_message_send(message, body, lower_sender_name)

            # process potential deliver request
            self.potential_deliver_request(message, body, lower_sender_name)

            # process potential ignore/unignore request
            self.potential_ignore_list_request(message, body, lower_sender_name)

            # process potential replay request
            self.potential_replay_request(message, body, lower_sender_name)

        # even banned users get messages; they just can't respond to them

        if self.connector.should_stfu():
            # don't bother just yet
            return

        # check if the sender should get any messages
        cursor = self.database.cursor()
        cursor.execute(
            "SELECT timestamp, sender_original, body, message_id FROM messages "
            "WHERE recipient_folded=? ORDER BY message_id ASC",
            (lower_sender_name,)
        )
        messages = []
        for bin_row in cursor:
            # skip messages that the user is directly responding to
            # (0: the !msg call, 1: the confirmation, 2: the response)
            delta = message.id - bin_row[3]
            if delta < 1 or delta > 2:
                messages.append((bin_row[0], bin_row[1], bin_row[2], bin_row[3]))
            else:
                logger.debug("dropping {0}'s message #{1} for {2} ({3}) due to proximity to #{4}".format(
                    bin_row[1], bin_row[3], message.user_name, bin_row[2], message.id
                ))
        cursor.close()

        # check how many messages the user has on retainer
        cursor = self.database.cursor()
        cursor.execute(
            "SELECT COUNT(*) FROM messages_on_retainer WHERE recipient_folded=?",
            (lower_sender_name,)
        )
        on_retainer = 0
        for row in cursor:
            on_retainer = row[0]

        retainer_text = ""
        if on_retainer > 0:
            retainer_text = " (and {0} pending !delivermsg)".format(on_retainer)

        if len(messages) == 0:
            # meh
            # (pass instead of return to delete the skipped "responded directly to" messages)
            pass
        elif len(messages) == 1:
            # one message
            (the_timestamp, the_sender, the_body, the_message_id) = messages[0]
            logger.debug("delivering {0}'s message #{3} {1} to {2}".format(
                repr(the_sender), repr(the_body), repr(message.user_name), repr(the_message_id)
            ))
            self.connector.send_message(
                "Message for [noparse]{0}[/noparse]{4}! {1} <[noparse]{2}[/noparse]> {3}".format(
                    message.user_name,
                    self.format_timestamp(the_message_id, the_timestamp),
                    the_sender,
                    the_body,
                    retainer_text
                )
            )
        elif len(messages) >= self.too_many_messages:
            logger.debug("{0} got {1} messages; putting on retainer".format(message.user_name, len(messages)))
            self.connector.send_message(
                "{0} new messages for [noparse]{1}[/noparse]{2}! Use \u201c!delivermsg [i]maxnumber[/i]\u201d to get "
                "them!".format(
                    len(messages),
                    message.user_name,
                    retainer_text
                )
            )

            # put on retainer
            cursor = self.database.cursor()
            cursor.execute(
                "INSERT INTO messages_on_retainer SELECT * FROM messages WHERE recipient_folded=? "
                "ORDER BY message_id ASC",
                (lower_sender_name,)
            )
            self.database.commit()
            cursor.close()
            # non-retained messages will be deleted below
        else:
            # multiple but not too many messages
            self.connector.send_message("{0} new messages for [noparse]{1}[/noparse]{2}!".format(
                len(messages),
                message.user_name,
                retainer_text
            ))
            for (the_timestamp, the_sender, the_body, the_message_id) in messages:
                logger.debug("delivering {0}'s message #{3} {1} to {2} as part of a chunk".format(
                    repr(the_sender), repr(the_body), repr(message.user_name), repr(the_message_id)
                ))
                self.connector.send_message("{0} <[noparse]{1}[/noparse]> {2}".format(
                    self.format_timestamp(the_message_id, the_timestamp),
                    the_sender,
                    the_body
                ))
            self.connector.send_message("[noparse]{0}[/noparse]: Have a nice day!".format(message.user_name))

        # place them on the repeat heap
        cursor = self.database.cursor()
        cursor.execute(
            "INSERT INTO replayable_messages SELECT * FROM messages WHERE recipient_folded=? "
            "ORDER BY message_id ASC",
            (lower_sender_name,)
        )
        self.database.commit()

        # purge the repeat heap if necessary
        cursor.execute("SELECT COUNT(*) FROM replayable_messages WHERE recipient_folded=?", (lower_sender_name,))
        count = 0
        for row in cursor:
            count = row[0]
        if count > self.max_messages_to_replay:
            cursor.execute(
                "SELECT message_id FROM replayable_messages WHERE recipient_folded=? ORDER BY message_id ASC",
                (lower_sender_name,)
            )
            replayable_message_ids = []
            for row in cursor:
                replayable_message_ids.append(row[0])
            # lst[:-10] =^= everything but the last 10 elements
            for replayable_message_id_to_purge in replayable_message_ids[:-self.max_messages_to_replay]:
                cursor.execute("DELETE FROM replayable_messages WHERE message_id=?", (replayable_message_id_to_purge,))
            self.database.commit()

        # delete delivered/skipped messages
        cursor.execute("DELETE FROM messages WHERE recipient_folded=?", (lower_sender_name,))
        self.database.commit()
        cursor.close()