Beispiel #1
0
 def doPrivmsg(self, irc, msg):
     assert self is irc.callbacks[0], \
            'Owner isn\'t first callback: %r' % irc.callbacks
     if ircmsgs.isCtcp(msg):
         return
     s = callbacks.addressed(irc.nick, msg)
     if s:
         ignored = ircdb.checkIgnored(msg.prefix)
         if ignored:
             self.log.info('Ignoring command from %s.', msg.prefix)
             return
         maximum = conf.supybot.abuse.flood.command.maximum()
         self.commands.enqueue(msg)
         if conf.supybot.abuse.flood.command() \
            and self.commands.len(msg) > maximum \
            and not ircdb.checkCapability(msg.prefix, 'trusted'):
             punishment = conf.supybot.abuse.flood.command.punishment()
             banmask = conf.supybot.protocols.irc.banmask \
                     .makeBanmask(msg.prefix)
             self.log.info('Ignoring %s for %s seconds due to an apparent '
                           'command flood.', banmask, punishment)
             ircdb.ignores.add(banmask, time.time() + punishment)
             if conf.supybot.abuse.flood.command.notify():
                 irc.reply('You\'ve given me %s commands within the last '
                           '%i seconds; I\'m now ignoring you for %s.' %
                           (maximum,
                            conf.supybot.abuse.flood.interval(),
                            utils.timeElapsed(punishment, seconds=False)))
             return
         try:
             tokens = callbacks.tokenize(s, channel=msg.args[0])
             self.Proxy(irc, msg, tokens)
         except SyntaxError as e:
             irc.queueMsg(callbacks.error(msg, str(e)))
Beispiel #2
0
 def doPrivmsg(self, irc, msg):
     assert self is irc.callbacks[0], \
            'Owner isn\'t first callback: %r' % irc.callbacks
     if ircmsgs.isCtcp(msg):
         return
     s = callbacks.addressed(irc.nick, msg)
     if s:
         ignored = ircdb.checkIgnored(msg.prefix)
         if ignored:
             self.log.info('Ignoring command from %s.', msg.prefix)
             return
         maximum = conf.supybot.abuse.flood.command.maximum()
         self.commands.enqueue(msg)
         if conf.supybot.abuse.flood.command() \
            and self.commands.len(msg) > maximum \
            and not ircdb.checkCapability(msg.prefix, 'trusted'):
             punishment = conf.supybot.abuse.flood.command.punishment()
             banmask = ircutils.banmask(msg.prefix)
             self.log.info('Ignoring %s for %s seconds due to an apparent '
                           'command flood.', banmask, punishment)
             ircdb.ignores.add(banmask, time.time() + punishment)
             irc.reply('You\'ve given me %s commands within the last '
                       'minute; I\'m now ignoring you for %s.' %
                       (maximum,
                        utils.timeElapsed(punishment, seconds=False)))
             return
         try:
             tokens = callbacks.tokenize(s, channel=msg.args[0])
             self.Proxy(irc, msg, tokens)
         except SyntaxError, e:
             irc.queueMsg(callbacks.error(msg, str(e)))
Beispiel #3
0
    def _replacer_process(self, irc, msg, target, pattern, replacement, count,
                          messages):
        for m in messages:
            if m.command in ('PRIVMSG', 'NOTICE') and \
                    ircutils.strEqual(m.args[0], msg.args[0]) and m.tagged('receivedBy') == irc:
                if target and m.nick != target:
                    continue
                # Don't snarf ignored users' messages unless specifically
                # told to.
                if ircdb.checkIgnored(m.prefix) and not target:
                    continue

                # When running substitutions, ignore the "* nick" part of any actions.
                action = ircmsgs.isAction(m)
                if action:
                    text = ircmsgs.unAction(m)
                else:
                    text = m.args[1]

                # Test messages sent before SedRegex was activated. Mark them all as seen
                # so we only need to do this check once per message.
                if not m.tagged(TAG_SEEN):
                    m.tag(TAG_SEEN)
                    if SED_REGEX.match(m.args[1]):
                        m.tag(TAG_IS_REGEX)
                # Ignore messages containing a regexp if ignoreRegex is on.
                if self.registryValue('ignoreRegex', msg.channel,
                                      irc.network) and m.tagged(TAG_IS_REGEX):
                    self.log.debug(
                        "Skipping message %s because it is tagged as isRegex",
                        m.args[1])
                    continue
                if m.nick == msg.nick:
                    messageprefix = msg.nick
                else:
                    messageprefix = '%s thinks %s' % (msg.nick, m.nick)

                try:
                    replace_result = pattern.search(text)
                    if replace_result:
                        if self.registryValue('boldReplacementText',
                                              msg.channel, irc.network):
                            replacement = ircutils.bold(replacement)
                        subst = pattern.sub(replacement, text, count)
                        if action:  # If the message was an ACTION, prepend the nick back.
                            subst = '* %s %s' % (m.nick, subst)

                        subst = axe_spaces(subst)

                        return _("%s meant to say: %s") % \
                            (messageprefix, subst)
                except Exception as e:
                    self.log.warning(_("SedRegex error: %s"), e, exc_info=True)
                    raise

        self.log.debug(
            _("SedRegex: Search %r not found in the last %i messages of %s."),
            msg.args[1], len(irc.state.history), msg.args[0])
        raise SearchNotFoundError()
Beispiel #4
0
    def replacer(self, irc, msg, regex):
        if not self.registryValue('enable', msg.args[0]):
            return
        iterable = reversed(irc.state.history)
        msg.tag('Replacer')

        try:
            (pattern, replacement, count) = self._unpack_sed(msg.args[1])
        except (ValueError, re.error) as e:
            self.log.warning(_("Replacer error: %s"), e)
            if self.registryValue('displayErrors', msg.args[0]):
                irc.error(_("Replacer error: %s" % e), Raise=True)
            return

        next(iterable)
        for m in iterable:
            if m.command in ('PRIVMSG', 'NOTICE') and \
                    m.args[0] == msg.args[0]:
                target = regex.group('nick')
                if not ircutils.isNick(str(target), strictRfc=True):
                    return
                if target and m.nick != target:
                    continue
                # Don't snarf ignored users' messages unless specifically
                # told to.
                if ircdb.checkIgnored(m.prefix) and not target:
                    continue
                # When running substitutions, ignore the "* nick" part of any actions.
                action = ircmsgs.isAction(m)
                if action:
                    text = ircmsgs.unAction(m)
                else:
                    text = m.args[1]

                if self.registryValue('ignoreRegex', msg.args[0]) and \
                        m.tagged('Replacer'):
                    continue
                if m.nick == msg.nick:
                    messageprefix = msg.nick
                else:
                    messageprefix = '%s thinks %s' % (msg.nick, m.nick)
                if regexp_wrapper(text, pattern, timeout=0.05, plugin_name=self.name(),
                                  fcn_name='replacer'):
                    if self.registryValue('boldReplacementText', msg.args[0]):
                        replacement = ircutils.bold(replacement)
                    subst = process(pattern.sub, replacement,
                                text, count, timeout=0.05)
                    if action:  # If the message was an ACTION, prepend the nick back.
                        subst = '* %s %s' % (m.nick, subst)
                    irc.reply(_("%s meant to say: %s") %
                              (messageprefix, subst), prefixNick=False)
                    return

        self.log.debug(_("Replacer: Search %r not found in the last %i messages of %s."),
                         msg.args[1], len(irc.state.history), msg.args[0])
        if self.registryValue("displayErrors", msg.args[0]):
            irc.error(_("Search not found in the last %i messages.") %
                      len(irc.state.history), Raise=True)
Beispiel #5
0
 def doPrivmsg(self, irc, msg):
     (targets, t) = msg.args
     text = escape(t)
     if msg.prefix == irc.prefix:
         return
     for channel in targets.split(','):
         if irc.isChannel(channel) and channel in irc.state.channels:
             learn = self.registryValue('learn', channel=channel)
             replyRandom = self.registryValue('replyPercent',
                                              channel=channel) > 0.00
             replyAddressed = self.registryValue('replyWhenAddressed',
                                                 channel=channel)
             called = False
             if ircdb.checkIgnored(msg.prefix, channel):
                 continue
             if not learn and not replyRandom and not replyAddressed:
                 continue
             if replyAddressed and msg.addressed:
                 text = escape(callbacks.addressed(irc.nick, msg))
                 m = None
                 if learn:
                     m = self.callHailo(channel, '-L', text)
                 else:
                     m = self.callHailo(channel, '-r', text)
                 if m != None and len(m):
                     if self.registryValue('checkSimilarity',
                                           channel=channel):
                         if similar(m, text) < self.registryValue(
                                 'similarity', channel=channel):
                             irc.queueMsg(ircmsgs.privmsg(channel, m))
                         else:
                             m = self.callHailo(channel, '-R', '')
                             if m != None and len(m):
                                 irc.queueMsg(ircmsgs.privmsg(channel, m))
                     else:
                         irc.queueMsg(ircmsgs.privmsg(channel, m))
                 called = True
             if not msg.addressed and replyRandom and randint(
                     1, 99) < self.registryValue('replyPercent',
                                                 channel=channel) * 100:
                 m = None
                 if learn:
                     m = self.callHailo(channel, '-L', text)
                 else:
                     m = self.callHailo(channel, '-r', text)
                 called = True
                 if m != None and len(m):
                     if self.registryValue('checkSimilarity',
                                           channel=channel):
                         if similar(m, text) < self.registryValue(
                                 'similarity', channel=channel):
                             irc.queueMsg(ircmsgs.privmsg(channel, m))
                     else:
                         irc.queueMsg(ircmsgs.privmsg(channel, m))
             if not called and learn:
                 self.callHailo(channel, '-l', text)
Beispiel #6
0
    def _doPrivmsgs(self, irc, msg):
        """If the given message is a command, triggers Limnoria's
        command-dispatching for that command.

        Takes the same arguments as ``doPrivmsg`` would, but ``msg`` can
        potentially be an artificial message synthesized in doBatch
        from a multiline batch.

        Usually, a command is a single message, so ``payload=msg.params[0]``
        However, when ``msg`` is part of a multiline message, the payload
        is the concatenation of multiple messages.
        See <https://ircv3.net/specs/extensions/multiline>.
        """
        assert self is irc.callbacks[0], \
               'Owner isn\'t first callback: %r' % irc.callbacks
        if ircmsgs.isCtcp(msg):
            return

        s = callbacks.addressed(irc, msg)
        if s:
            ignored = ircdb.checkIgnored(msg.prefix)
            if ignored:
                self.log.info('Ignoring command from %s.', msg.prefix)
                return
            maximum = conf.supybot.abuse.flood.command.maximum()
            self.commands.enqueue(msg)
            if conf.supybot.abuse.flood.command() \
               and self.commands.len(msg) > maximum \
               and not ircdb.checkCapability(msg.prefix, 'trusted'):
                punishment = conf.supybot.abuse.flood.command.punishment()
                banmask = conf.supybot.protocols.irc.banmask \
                        .makeBanmask(msg.prefix)
                self.log.info(
                    'Ignoring %s for %s seconds due to an apparent '
                    'command flood.', banmask, punishment)
                ircdb.ignores.add(banmask, time.time() + punishment)
                if conf.supybot.abuse.flood.command.notify():
                    irc.reply('You\'ve given me %s commands within the last '
                              '%i seconds; I\'m now ignoring you for %s.' %
                              (maximum, conf.supybot.abuse.flood.interval(),
                               utils.timeElapsed(punishment, seconds=False)))
                return
            try:
                tokens = callbacks.tokenize(s,
                                            channel=msg.channel,
                                            network=irc.network)
                self.Proxy(irc, msg, tokens)
            except SyntaxError as e:
                if conf.supybot.reply.error.detailed():
                    irc.error(str(e))
                else:
                    irc.replyError(msg=msg)
                    self.log.info('Syntax error: %s', e)
Beispiel #7
0
    def _replacer_process(self, irc, msg, target, pattern, replacement, count,
                          messages):
        for m in messages:
            if m.command in ('PRIVMSG', 'NOTICE') and \
                    ircutils.strEqual(m.args[0], msg.args[0]) and m.tagged('receivedBy') == irc:
                if target and m.nick != target:
                    continue
                # Don't snarf ignored users' messages unless specifically
                # told to.
                if ircdb.checkIgnored(m.prefix) and not target:
                    continue

                # When running substitutions, ignore the "* nick" part of any actions.
                action = ircmsgs.isAction(m)
                if action:
                    text = ircmsgs.unAction(m)
                else:
                    text = m.args[1]

                if self.registryValue('ignoreRegex', msg.channel, irc.network) and \
                        m.tagged('Replacer'):
                    continue
                if m.nick == msg.nick:
                    messageprefix = msg.nick
                else:
                    messageprefix = '%s thinks %s' % (msg.nick, m.nick)

                try:
                    replace_result = pattern.search(text)
                    if replace_result:
                        if self.registryValue('boldReplacementText',
                                              msg.channel, irc.network):
                            replacement = ircutils.bold(replacement)
                        subst = pattern.sub(replacement, text, count)
                        if action:  # If the message was an ACTION, prepend the nick back.
                            subst = '* %s %s' % (m.nick, subst)

                        subst = axe_spaces(subst)

                        return _("%s meant to say: %s") % \
                            (messageprefix, subst)
                except Exception as e:
                    self.log.warning(_("SedRegex error: %s"), e, exc_info=True)
                    raise

        self.log.debug(
            _("SedRegex: Search %r not found in the last %i messages of %s."),
            msg.args[1], len(irc.state.history), msg.args[0])
        raise SearchNotFound()
Beispiel #8
0
	def doPrivmsg (self,irc,msg):
		(targets, t) = msg.args
		text = escape(t)
		if msg.prefix == irc.prefix:
			return
		for channel in targets.split(','):
			if irc.isChannel(channel) and channel in irc.state.channels:
				learn = self.registryValue('learn',channel=channel)
				replyRandom = self.registryValue('replyPercent',channel=channel) > 0.00
				replyAddressed = self.registryValue('replyWhenAddressed',channel=channel)
				called = False
				if ircdb.checkIgnored(msg.prefix,channel):
					continue
				if not learn and not replyRandom and not replyAddressed:
					continue
				if replyAddressed and msg.addressed:
					text = escape(callbacks.addressed(irc.nick,msg))
					m = None
					if learn:
						m = self.callHailo(channel,'-L',text)
					else:
						m = self.callHailo(channel,'-r',text)
					if m != None and len(m):
						if self.registryValue('checkSimilarity',channel=channel):
							if similar(m,text) < self.registryValue('similarity',channel=channel):
								irc.queueMsg(ircmsgs.privmsg(channel,m))
							else:
								m = self.callHailo(channel,'-R','')
								if m != None and len(m):
									irc.queueMsg(ircmsgs.privmsg(channel,m))
						else:
							irc.queueMsg(ircmsgs.privmsg(channel,m))
					called = True
				if not msg.addressed and replyRandom and randint(1,99) < self.registryValue('replyPercent',channel=channel)*100:
					m = None
					if learn:
						m = self.callHailo(channel,'-L',text)
					else:
						m = self.callHailo(channel,'-r',text)
					called = True
					if m != None and len(m):
						if self.registryValue('checkSimilarity',channel=channel):
							if similar(m,text) < self.registryValue('similarity',channel=channel):
								irc.queueMsg(ircmsgs.privmsg(channel,m))
						else:
							irc.queueMsg(ircmsgs.privmsg(channel,m))
				if not called and learn:
					self.callHailo(channel,'-l',text)
Beispiel #9
0
    def relay(self, irc, msg, channel=None):
        channel = (channel or msg.args[0]).lower()
        self.log.debug("RelayNext (%s): got channel %s", irc.network, channel)
        if not channel in irc.state.channels:
            return

        # Check for ignored events first. Checking for "'.' not in msg.nick" is for skipping
        # ignore checks from servers.
        ignoredevents = map(str.upper,
                            self.registryValue('events.userIgnored', channel))
        if msg.command in ignoredevents and msg.nick != irc.nick and '.' not in msg.nick and\
                ircdb.checkIgnored(msg.prefix, channel):
            self.log.debug("RelayNext (%s): ignoring message from %s",
                           irc.network, msg.prefix)
            return

        # Get the source channel
        source = "%s@%s" % (channel, irc.network)
        source = source.lower()

        out_s = self._format(irc, msg, channel)
        if out_s:
            for relay in self.db.values():
                self.log.debug("RelayNext (%s): check if %s in %s",
                               irc.network, source, relay)
                if source in relay:  # If our channel is in a relay
                    self.log.debug("RelayNext: found %s to be in relay %s",
                                   source, relay)

                    # Remove ourselves from the target channels so we don't get duplicated messages
                    targets = list(relay)
                    targets.remove(source)

                    self.log.debug("RelayNext: found targets %s for relay %s",
                                   targets, relay)

                    if self.registryValue("antiflood.enable", channel):
                        # Flood prevention timeout - how long commands of a certain type
                        # should cease being relayed after flood prevention triggers
                        timeout = self.registryValue("antiflood.timeout",
                                                     channel)

                        # If <maximum> messages of the same kind on one channel is
                        # received in <seconds> seconds, flood prevention timeout is
                        # triggered.
                        maximum = self.registryValue("antiflood.maximum",
                                                     channel)
                        seconds = self.registryValue("antiflood.seconds",
                                                     channel)

                        # Store the message in a counter, with the keys taking the
                        # form of (source channel@network, command name). If the counter
                        # doesn't already exist, create one here.
                        try:
                            self.msgcounters[(source,
                                              msg.command)].enqueue(msg.prefix)
                        except KeyError:
                            self.msgcounters[(
                                source, msg.command)] = TimeoutQueue(seconds)

                        # Two different limits: one for messages and one for all others
                        if msg.command == "PRIVMSG":
                            maximum = self.registryValue(
                                "antiflood.maximum", channel)
                        else:
                            maximum = self.registryValue(
                                "antiflood.maximum.nonPrivmsgs", channel)

                        if len(self.msgcounters[(source,
                                                 msg.command)]) > maximum:
                            # Amount of messages in the counter surpassed our limit,
                            # announce the flood and block relaying messages of the
                            # same type for X seconds
                            self.log.debug(
                                "RelayNext (%s): message from %s blocked by "
                                "flood protection.", irc.network, channel)

                            if self.floodTriggered.get((source, msg.command)):
                                # However, only send the announcement once.
                                return

                            c = msg.command
                            e = format(
                                "Flood detected on %s (%s %ss/%s seconds), "
                                "not relaying %ss for %s seconds!", channel,
                                maximum, c, seconds, c, timeout)
                            out_s = self._format(irc,
                                                 msg,
                                                 channel,
                                                 announcement=e)

                            self.floodTriggered[(source, msg.command)] = True
                            self.log.info("RelayNext (%s): %s", irc.network, e)
                        else:
                            self.floodTriggered[(source, msg.command)] = False

                    for cn in targets:
                        # Iterate over all the relay targets for this message:
                        # each target is stored internally as a #channel@netname
                        # string.
                        target, net = cn.split("@")
                        otherIrc = world.getIrc(net)
                        if otherIrc is None:
                            self.log.debug(
                                "RelayNext: message to network %r"
                                " dropped, we are not connected "
                                "there!", net)
                            return

                        target_chanobj = otherIrc.state.channels.get(target)
                        if (not target_chanobj
                            ) or otherIrc.nick not in target_chanobj.users:
                            # We're not in the target relay channel!
                            self.log.debug(
                                "RelayNext: message to %s@%s "
                                "dropped, we are not in that "
                                "channel!", target, net)
                        else:
                            out_msg = ircmsgs.privmsg(target, out_s)

                            # Tag the message as relayed so we (and other relayers) don't
                            # try to relay it again.
                            out_msg.tag('relayedMsg')
                            otherIrc.queueMsg(out_msg)
Beispiel #10
0
    def relay(self, irc, msg, channel=None):
        channel = (channel or msg.args[0]).lower()
        self.log.debug("RelayNext (%s): got channel %s", irc.network, channel)
        if not channel in irc.state.channels:
            return

        # Check for ignored events first. Checking for "'.' not in msg.nick" is for skipping
        # ignore checks from servers.
        ignoredevents = map(str.upper, self.registryValue('events.userIgnored', channel))
        if msg.command in ignoredevents and msg.nick != irc.nick and '.' not in msg.nick and\
                ircdb.checkIgnored(msg.prefix, channel):
            self.log.debug("RelayNext (%s): ignoring message from %s",
                           irc.network, msg.prefix)
            return

        # Get the source channel
        source = "%s@%s" % (channel, irc.network)
        source = source.lower()

        out_s = self._format(irc, msg, channel)
        if out_s:
            for relay in self.db.values():
                self.log.debug("RelayNext (%s): check if %s in %s", irc.network, source, relay)
                if source in relay:  # If our channel is in a relay
                    self.log.debug("RelayNext: found %s to be in relay %s", source, relay)

                    # Remove ourselves from the target channels so we don't get duplicated messages
                    targets = list(relay)
                    targets.remove(source)

                    self.log.debug("RelayNext: found targets %s for relay %s", targets, relay)

                    if self.registryValue("antiflood.enable", channel):
                        # Flood prevention timeout - how long commands of a certain type
                        # should cease being relayed after flood prevention triggers
                        timeout = self.registryValue("antiflood.timeout", channel)

                        # If <maximum> messages of the same kind on one channel is
                        # received in <seconds> seconds, flood prevention timeout is
                        # triggered.
                        maximum = self.registryValue("antiflood.maximum", channel)
                        seconds = self.registryValue("antiflood.seconds", channel)

                        # Store the message in a counter, with the keys taking the
                        # form of (source channel@network, command name). If the counter
                        # doesn't already exist, create one here.
                        try:
                            self.msgcounters[(source, msg.command)].enqueue(msg.prefix)
                        except KeyError:
                            self.msgcounters[(source, msg.command)] = TimeoutQueue(seconds)

                        # Two different limits: one for messages and one for all others
                        if msg.command == "PRIVMSG":
                            maximum = self.registryValue("antiflood.maximum", channel)
                        else:
                            maximum = self.registryValue("antiflood.maximum.nonPrivmsgs",
                                                         channel)

                        if len(self.msgcounters[(source, msg.command)]) > maximum:
                            # Amount of messages in the counter surpassed our limit,
                            # announce the flood and block relaying messages of the
                            # same type for X seconds
                            self.log.debug("RelayNext (%s): message from %s blocked by "
                                           "flood protection.", irc.network, channel)

                            if self.floodTriggered.get((source, msg.command)):
                                # However, only send the announcement once.
                                return

                            c = msg.command
                            e = format("Flood detected on %s (%s %ss/%s seconds), "
                                       "not relaying %ss for %s seconds!", channel,
                                       maximum, c, seconds, c, timeout)
                            out_s = self._format(irc, msg, channel, announcement=e)

                            self.floodTriggered[(source, msg.command)] = True
                            self.log.info("RelayNext (%s): %s", irc.network, e)
                        else:
                            self.floodTriggered[(source, msg.command)] = False

                    for cn in targets:
                        # Iterate over all the relay targets for this message:
                        # each target is stored internally as a #channel@netname
                        # string.
                        target, net = cn.split("@")
                        otherIrc = world.getIrc(net)
                        if otherIrc is None:
                            self.log.debug("RelayNext: message to network %r"
                                           " dropped, we are not connected "
                                           "there!", net)
                            return

                        target_chanobj = otherIrc.state.channels.get(target)
                        if (not target_chanobj) or otherIrc.nick not in target_chanobj.users:
                            # We're not in the target relay channel!
                            self.log.debug("RelayNext: message to %s@%s "
                                           "dropped, we are not in that "
                                           "channel!", target, net)
                        else:
                            out_msg = ircmsgs.privmsg(target, out_s)

                            # Tag the message as relayed so we (and other relayers) don't
                            # try to relay it again.
                            out_msg.tag('relayedMsg')
                            otherIrc.queueMsg(out_msg)
Beispiel #11
0
    def replacer(self, irc, msg, regex):
        if not self.registryValue('enable', msg.args[0]):
            return
        iterable = reversed(irc.state.history)
        msg.tag('Replacer')

        try:
            (pattern, replacement, count, flags) = self._unpack_sed(msg.args[1])
        except (ValueError, re.error) as e:
            self.log.warning(_("SedRegex error: %s"), e)
            if self.registryValue('displayErrors', msg.args[0]):
                irc.error('%s.%s: %s' % (e.__class__.__module__, e.__class__.__name__, e))
            return

        next(iterable)
        if 's' in flags:  # Special 's' flag lets the bot only look at self messages
            target = msg.nick
        else:
            target = regex.group('nick')
        if not ircutils.isNick(str(target), strictRfc=True):
            return

        for m in iterable:
            if m.command in ('PRIVMSG', 'NOTICE') and \
                    m.args[0] == msg.args[0] and m.tagged('receivedBy') == irc:
                if target and m.nick != target:
                    continue
                # Don't snarf ignored users' messages unless specifically
                # told to.
                if ircdb.checkIgnored(m.prefix) and not target:
                    continue

                # When running substitutions, ignore the "* nick" part of any actions.
                action = ircmsgs.isAction(m)
                if action:
                    text = ircmsgs.unAction(m)
                else:
                    text = m.args[1]

                if self.registryValue('ignoreRegex', msg.args[0]) and \
                        m.tagged('Replacer'):
                    continue
                if m.nick == msg.nick:
                    messageprefix = msg.nick
                else:
                    messageprefix = '%s thinks %s' % (msg.nick, m.nick)
                try:
                    regex_timeout = self.registryValue('processTimeout')
                    if regexp_wrapper(text, pattern, timeout=regex_timeout, plugin_name=self.name(),
                                      fcn_name='replacer'):
                        if self.registryValue('boldReplacementText', msg.args[0]):
                            replacement = ircutils.bold(replacement)
                        subst = process(pattern.sub, replacement,
                                        text, count, timeout=0.05)
                        if action:  # If the message was an ACTION, prepend the nick back.
                            subst = '* %s %s' % (m.nick, subst)

                        subst = axe_spaces(subst)

                        irc.reply(_("%s meant to say: %s") %
                                    (messageprefix, subst), prefixNick=False)
                        return
                except (ValueError, re.error) as e:
                    if self.registryValue('displayErrors', msg.args[0]):
                        irc.error('%s.%s: %s' % (e.__class__.__module__, e.__class__.__name__, e))
                    return

        self.log.debug(_("SedRegex: Search %r not found in the last %i messages of %s."),
                         msg.args[1], len(irc.state.history), msg.args[0])
        if self.registryValue("displayErrors", msg.args[0]):
            irc.error(_("Search not found in the last %i messages.") %
                      len(irc.state.history), Raise=True)