<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def process_action(self, raw_user, channel, raw_message):
 """Called when a message is received from a channel or user."""

        log.info("%s %s %s", channel, raw_user, raw_message)

        if not raw_user:
            # ignore server messages
            return

        # This monster of a regex extracts msg and target from a message, where
        # the target may not be there, and the target is a valid irc name.
        # Valid ways to target someone are "<nick>: ..." and "<nick>, ..."
        target, message = re.match(
            r'^(?:([a-z_\-\[\]\\^{}|`]'  # First letter can't be a number
            '[a-z0-9_\-\[\]\\^{}|`]*)'   # The rest can be many things
            '[:,] )? *(.*)$',            # The actual message
            raw_message, re.I).groups()

        pm = channel == self.nickname
        if pm:
            directed = True
        if target:
            if target.lower() == self.nickname.lower():
                directed = True
            else:
                directed = False
                message = '{0}: {1}'.format(target, message)
        else:
            directed = False
        if message.startswith('!'):
            message = message[1:]
            directed = True

        if directed:
            message = message.rstrip()

        try:
            user, mask = raw_user.split('!', 1)
        except ValueError:
            user = raw_user
            mask = ''

        comm = {
            'raw_message': raw_message,
            'message': message,
            'raw_user': raw_user,
            'user': user,
            'mask': mask,
            'target': target,
            'channel': channel,
            'directed': directed,
            'pm': pm,
        }

        self.dispatch('chat', 'message', comm)

        self.factory.history.setdefault(
            channel, deque(maxlen=100)).append(comm)