Esempio n. 1
0
    def prepare_threaded(self):
        super().prepare_threaded()

        if "parsed_line" in self.hook.required_args:
            try:
                self.parsed_line = Message.parse(self.line)
            except Exception:
                logger.exception("Unable to parse line requested by hook %s",
                                 self.hook)
                self.parsed_line = None
Esempio n. 2
0
    def data_received(self, data):
        self._input_buffer += data

        while b"\r\n" in self._input_buffer:
            line_data, self._input_buffer = self._input_buffer.split(
                b"\r\n", 1)
            line = decode(line_data)

            try:
                message = Message.parse(line)
            except Exception:
                logger.exception(
                    "[%s] Error occurred while parsing IRC line '%s' from %s",
                    self.conn.name, line, self.conn.describe_server())
                continue

            command = message.command
            command_params = message.parameters

            # Reply to pings immediately

            if command == "PING":
                self.conn.send("PONG " + command_params[-1], log=False)

            # Parse the command and params

            # Content
            if command_params.has_trail:
                content_raw = command_params[-1]
                content = irc_clean(content_raw)
            else:
                content_raw = None
                content = None

            # Event type
            if command in irc_command_to_event_type:
                event_type = irc_command_to_event_type[command]
            else:
                event_type = EventType.other

            # Target (for KICK, INVITE)
            if event_type is EventType.kick:
                target = command_params[1]
            elif command == "INVITE":
                target = command_params[0]
            else:
                # TODO: Find more commands which give a target
                target = None

            # Parse for CTCP
            if event_type is EventType.message and content_raw.count(
                    "\x01") >= 2 and content_raw.startswith("\x01"):
                # Remove the first \x01, then rsplit to remove the last one, and ignore text after the last \x01
                ctcp_text = content_raw[1:].rsplit("\x01", 1)[0]
                ctcp_text_split = ctcp_text.split(None, 1)
                if ctcp_text_split[0] == "ACTION":
                    # this is a CTCP ACTION, set event_type and content accordingly
                    event_type = EventType.action
                    content = ctcp_text_split[1]
                else:
                    # this shouldn't be considered a regular message
                    event_type = EventType.other
            else:
                ctcp_text = None

            # Channel
            channel = None
            if command_params:
                if command in [
                        "NOTICE", "PRIVMSG", "KICK", "JOIN", "PART", "MODE"
                ]:
                    channel = command_params[0]
                elif command == "INVITE":
                    channel = command_params[1]
                elif len(command_params) > 2 or not (
                        command_params.has_trail and len(command_params) == 1):
                    channel = command_params[0]

            prefix = message.prefix

            nick = prefix.nick
            user = prefix.user
            host = prefix.host
            mask = prefix.mask

            if channel:
                # TODO Migrate plugins to accept the original case of the channel
                channel = channel.lower()

                channel = channel.split()[0]  # Just in case there is more data

                if channel == self.conn.nick.lower():
                    channel = nick.lower()

            # Set up parsed message
            # TODO: Do we really want to send the raw `prefix` and `command_params` here?
            event = Event(bot=self.bot,
                          conn=self.conn,
                          event_type=event_type,
                          content_raw=content_raw,
                          content=content,
                          target=target,
                          channel=channel,
                          nick=nick,
                          user=user,
                          host=host,
                          mask=mask,
                          irc_raw=line,
                          irc_prefix=mask,
                          irc_command=command,
                          irc_paramlist=command_params,
                          irc_ctcp_text=ctcp_text)

            # handle the message, async
            async_util.wrap_future(self.bot.process(event), loop=self.loop)