Exemple #1
0
    def _regex_command(self, session: InboundMessageSession):
        channel = session.message['channel']
        if self._avoid_pikalaxbot and 'pikalaxbot' in self._user_list[channel]:
            session.skip_rate_limit = True
            return

        # Special split http://stackoverflow.com/a/21107911/1524507
        parts = re.split(r'(?<!\\)/', session.match.group(1))

        if not (2 <= len(parts) <= 3):
            return

        search_pattern = parts[0]
        replacement = parts[1].replace('\\/', '/')
        options = parts[2] if len(parts) == 3 else ''
        flags = 0
        count = 1

        if 'i' in options:
            flags |= re.IGNORECASE

        if 'g' in options:
            count = 0

        try:
            pattern = re.compile(search_pattern, flags)
        except re.error as error:
            session.reply('{} {}!'.format(gen_roar(), error.args[0].title()))
            return

        for history_message in reversed(
                self._recent_messages_for_regex[session.message['channel']]):
            text = history_message['text']
            channel = session.message['channel']

            if text.startswith('s/') or text.startswith('!s/'):
                continue

            try:
                matched = self._regex_server.search(pattern, text)
            except RegexTimeout:
                _logger.warning('Regex DoS by %s on %s',
                                session.message['username'],
                                session.message['channel'])
                session.reply(gen_roar().upper())
                return

            if matched:
                try:
                    new_text = pattern.sub(replacement, text, count=count)
                except re.error as error:
                    session.reply('{} {}!'.format(gen_roar(),
                                                  error.args[0].title()))
                    return

                if _random.random() < 0.05:
                    new_text = gen_roar()
                    fake_out = True
                else:
                    fake_out = False

                formatted_text = '{user} wishes to {stacked}correct ' \
                    '{target_user}: {text}'.format(
                        user=session.message['nick'],
                        target_user=history_message['nick'],
                        text=new_text,
                        stacked='re' if history_message.get('stacked') else '',
                )

                ok = self._try_say_or_reply_too_long(formatted_text, session)
                if not ok:
                    return

                if not fake_out:
                    stacked_message = copy.copy(history_message)
                    stacked_message['text'] = new_text
                    stacked_message['stacked'] = True
                    self._recent_messages_for_regex[channel].append(
                        stacked_message)

                return

        session.reply(
            '{} Your request does not apply to any recent messages!'.format(
                gen_roar()))
Exemple #2
0
    def _regex_command(self, session: InboundMessageSession):
        channel = session.message["channel"]
        if self._avoid_pikalaxbot and "pikalaxbot" in self._user_list[channel]:
            session.skip_rate_limit = True
            return

        # Special split http://stackoverflow.com/a/21107911/1524507
        parts = re.split(r"(?<!\\)/", session.match.group(1))

        if not (2 <= len(parts) <= 3):
            return

        search_pattern = parts[0]
        replacement = parts[1]
        options = parts[2] if len(parts) == 3 else ""
        flags = 0
        count = 1

        if "i" in options:
            flags |= re.IGNORECASE

        if "g" in options:
            count = 0

        try:
            pattern = re.compile(search_pattern, flags)
        except re.error as error:
            session.reply("{} {}!".format(gen_roar(), error.args[0].title()))
            return

        for history_message in reversed(self._recent_messages_for_regex[session.message["channel"]]):
            text = history_message["text"]
            channel = session.message["channel"]

            if text.startswith("s/"):
                continue

            try:
                matched = self._regex_server.search(pattern, text)
            except RegexTimeout:
                _logger.warning("Regex DoS by %s on %s", session.message["username"], session.message["channel"])
                session.reply(gen_roar().upper())
                return

            if matched:
                try:
                    new_text = pattern.sub(replacement, text, count=count)
                except re.error as error:
                    session.reply("{} {}!".format(gen_roar(), error.args[0].title()))
                    return

                if _random.random() < 0.05:
                    new_text = gen_roar()
                    fake_out = True
                else:
                    fake_out = False

                formatted_text = "{user} wishes to {stacked}correct " "{target_user}: {text}".format(
                    user=session.message["nick"],
                    target_user=history_message["nick"],
                    text=new_text,
                    stacked="re" if history_message.get("stacked") else "",
                )

                ok = self._try_say_or_reply_too_long(formatted_text, session)
                if not ok:
                    return

                if not fake_out:
                    stacked_message = copy.copy(history_message)
                    stacked_message["text"] = new_text
                    stacked_message["stacked"] = True
                    self._recent_messages_for_regex[channel].append(stacked_message)

                return

        session.reply("{} Your request does not apply to any recent messages!".format(gen_roar()))