Exemple #1
0
    def last(self, irc, msg, args, optlist):
        """[--{from,in,on,with,without,regexp} <value>] [--nolimit]

        Returns the last message matching the given criteria.  --from requires
        a nick from whom the message came; --in requires a channel the message
        was sent to; --on requires a network the message was sent on; --with
        requires some string that had to be in the message; --regexp requires
        a regular expression the message must match; --nolimit returns all
        the messages that can be found.  By default, the channel this command is
        given in is searched.
        """
        predicates = {}
        nolimit = False
        skipfirst = True
        if ircutils.isChannel(msg.args[0]):
            predicates['in'] = lambda m: ircutils.strEqual(m.args[0],
                                                           msg.args[0])
        else:
            skipfirst = False
        for (option, arg) in optlist:
            if option == 'from':
                def f(m, arg=arg):
                    return ircutils.hostmaskPatternEqual(arg, m.nick)
                predicates['from'] = f
            elif option == 'in':
                def f(m, arg=arg):
                    return ircutils.strEqual(m.args[0], arg)
                predicates['in'] = f
                if arg != msg.args[0]:
                    skipfirst = False
            elif option == 'on':
                def f(m, arg=arg):
                    return m.receivedOn == arg
                predicates['on'] = f
            elif option == 'with':
                def f(m, arg=arg):
                    return arg.lower() in m.args[1].lower()
                predicates.setdefault('with', []).append(f)
            elif option == 'without':
                def f(m, arg=arg):
                    return arg.lower() not in m.args[1].lower()
                predicates.setdefault('without', []).append(f)
            elif option == 'regexp':
                def f(m, arg=arg):
                    def f1(s, arg):
                        """Since we can't enqueue match objects into the multiprocessing queue,
                        we'll just wrap the function to return bools."""
                        if arg.search(s) is not None:
                            return True
                        else:
                            return False
                    if ircmsgs.isAction(m):
                        m1 = ircmsgs.unAction(m)
                        #return arg.search(ircmsgs.unAction(m))
                    else:
                        m1 = m.args[1]
                        #return arg.search(m.args[1])
                    try:
                        # use a subprocess here, since specially crafted regexps can
                        # take exponential time and hang up the bot.
                        # timeout of 0.1 should be more than enough for any normal regexp.
                        v = commands.process(f1, m1, arg, timeout=0.1, pn=self.name(), cn='last')
                        return v
                    except commands.ProcessTimeoutError:
                        return False
                predicates.setdefault('regexp', []).append(f)
            elif option == 'nolimit':
                nolimit = True
        iterable = ifilter(self._validLastMsg, reversed(irc.state.history))
        if skipfirst:
            # Drop the first message only if our current channel is the same as
            # the channel we've been instructed to look at.
            iterable.next()
        predicates = list(utils.iter.flatten(predicates.itervalues()))
        # Make sure the user can't get messages from channels they aren't in
        def userInChannel(m):
            return m.args[0] in irc.state.channels \
                    and msg.nick in irc.state.channels[m.args[0]].users
        predicates.append(userInChannel)
        # Make sure the user can't get messages from a +s channel unless
        # they're calling the command from that channel or from a query
        def notSecretMsg(m):
            return not irc.isChannel(msg.args[0]) \
                    or msg.args[0] == m.args[0] \
                    or (m.args[0] in irc.state.channels \
                        and 's' not in irc.state.channels[m.args[0]].modes)
        predicates.append(notSecretMsg)
        resp = []
        if irc.nested and not \
          self.registryValue('last.nested.includeTimestamp'):
            tsf = None
        else:
            tsf = self.registryValue('timestampFormat')
        if irc.nested and not self.registryValue('last.nested.includeNick'):
            showNick = False
        else:
            showNick = True
        for m in iterable:
            for predicate in predicates:
                if not predicate(m):
                    break
            else:
                if nolimit:
                    resp.append(ircmsgs.prettyPrint(m,
                                                    timestampFormat=tsf,
                                                    showNick=showNick))
                else:
                    irc.reply(ircmsgs.prettyPrint(m,
                                                  timestampFormat=tsf,
                                                  showNick=showNick))
                    return
        if not resp:
            irc.error('I couldn\'t find a message matching that criteria in '
                      'my history of %s messages.' % len(irc.state.history))
        else:
            irc.reply(format('%L', resp))
Exemple #2
0
    def last(self, irc, msg, args, optlist):
        """[--{from,in,on,with,without,regexp} <value>] [--nolimit]

        Returns the last message matching the given criteria.  --from requires
        a nick from whom the message came; --in requires a channel the message
        was sent to; --on requires a network the message was sent on; --with
        requires some string that had to be in the message; --regexp requires
        a regular expression the message must match; --nolimit returns all
        the messages that can be found.  By default, the channel this command is
        given in is searched.
        """
        predicates = {}
        nolimit = False
        skipfirst = True
        if ircutils.isChannel(msg.args[0]):
            predicates["in"] = lambda m: ircutils.strEqual(m.args[0], msg.args[0])
        else:
            skipfirst = False
        for (option, arg) in optlist:
            if option == "from":

                def f(m, arg=arg):
                    return ircutils.hostmaskPatternEqual(arg, m.nick)

                predicates["from"] = f
            elif option == "in":

                def f(m, arg=arg):
                    return ircutils.strEqual(m.args[0], arg)

                predicates["in"] = f
                if arg != msg.args[0]:
                    skipfirst = False
            elif option == "on":

                def f(m, arg=arg):
                    return m.receivedOn == arg

                predicates["on"] = f
            elif option == "with":

                def f(m, arg=arg):
                    return arg.lower() in m.args[1].lower()

                predicates.setdefault("with", []).append(f)
            elif option == "without":

                def f(m, arg=arg):
                    return arg.lower() not in m.args[1].lower()

                predicates.setdefault("without", []).append(f)
            elif option == "regexp":

                def f(m, arg=arg):
                    if ircmsgs.isAction(m):
                        m1 = ircmsgs.unAction(m)
                    else:
                        m1 = m.args[1]
                    return regexp_wrapper(m1, reobj=arg, timeout=0.1, plugin_name=self.name(), fcn_name="last")

                predicates.setdefault("regexp", []).append(f)
            elif option == "nolimit":
                nolimit = True
        iterable = ifilter(self._validLastMsg, reversed(irc.state.history))
        if skipfirst:
            # Drop the first message only if our current channel is the same as
            # the channel we've been instructed to look at.
            iterable.next()
        predicates = list(utils.iter.flatten(predicates.itervalues()))
        # Make sure the user can't get messages from channels they aren't in
        def userInChannel(m):
            return m.args[0] in irc.state.channels and msg.nick in irc.state.channels[m.args[0]].users

        predicates.append(userInChannel)
        # Make sure the user can't get messages from a +s channel unless
        # they're calling the command from that channel or from a query
        def notSecretMsg(m):
            return (
                not irc.isChannel(msg.args[0])
                or msg.args[0] == m.args[0]
                or (m.args[0] in irc.state.channels and "s" not in irc.state.channels[m.args[0]].modes)
            )

        predicates.append(notSecretMsg)
        resp = []
        if irc.nested and not self.registryValue("last.nested.includeTimestamp"):
            tsf = None
        else:
            tsf = self.registryValue("timestampFormat")
        if irc.nested and not self.registryValue("last.nested.includeNick"):
            showNick = False
        else:
            showNick = True
        for m in iterable:
            for predicate in predicates:
                if not predicate(m):
                    break
            else:
                if nolimit:
                    resp.append(ircmsgs.prettyPrint(m, timestampFormat=tsf, showNick=showNick))
                else:
                    irc.reply(ircmsgs.prettyPrint(m, timestampFormat=tsf, showNick=showNick))
                    return
        if not resp:
            irc.error(
                "I couldn't find a message matching that criteria in "
                "my history of %s messages." % len(irc.state.history)
            )
        else:
            irc.reply(format("%L", resp))
Exemple #3
0
    def last(self, irc, msg, args, optlist):
        """[--{from,in,on,with,without,regexp} <value>] [--nolimit]

        Returns the last message matching the given criteria.  --from requires
        a nick from whom the message came; --in requires a channel the message
        was sent to; --on requires a network the message was sent on; --with
        requires some string that had to be in the message; --regexp requires
        a regular expression the message must match; --nolimit returns all
        the messages that can be found.  By default, the channel this command is
        given in is searched.
        """
        predicates = {}
        nolimit = False
        skipfirst = True
        if ircutils.isChannel(msg.args[0]):
            predicates['in'] = lambda m: ircutils.strEqual(m.args[0],
                                                           msg.args[0])
        else:
            skipfirst = False
        for (option, arg) in optlist:
            if option == 'from':
                def f(m, arg=arg):
                    return ircutils.hostmaskPatternEqual(arg, m.nick)
                predicates['from'] = f
            elif option == 'in':
                def f(m, arg=arg):
                    return ircutils.strEqual(m.args[0], arg)
                predicates['in'] = f
                if arg != msg.args[0]:
                    skipfirst = False
            elif option == 'on':
                def f(m, arg=arg):
                    return m.receivedOn == arg
                predicates['on'] = f
            elif option == 'with':
                def f(m, arg=arg):
                    return arg.lower() in m.args[1].lower()
                predicates.setdefault('with', []).append(f)
            elif option == 'without':
                def f(m, arg=arg):
                    return arg.lower() not in m.args[1].lower()
                predicates.setdefault('without', []).append(f)
            elif option == 'regexp':
                def f(m, arg=arg):
                    if ircmsgs.isAction(m):
                        m1 = ircmsgs.unAction(m)
                    else:
                        m1 = m.args[1]
                    return regexp_wrapper(m1, reobj=arg, timeout=0.1,
                                          plugin_name=self.name(),
                                          fcn_name='last')
                predicates.setdefault('regexp', []).append(f)
            elif option == 'nolimit':
                nolimit = True
        iterable = ifilter(self._validLastMsg, reversed(irc.state.history))
        if skipfirst:
            # Drop the first message only if our current channel is the same as
            # the channel we've been instructed to look at.
            iterable.next()
        predicates = list(utils.iter.flatten(predicates.itervalues()))
        # Make sure the user can't get messages from channels they aren't in
        def userInChannel(m):
            return m.args[0] in irc.state.channels \
                    and msg.nick in irc.state.channels[m.args[0]].users
        predicates.append(userInChannel)
        # Make sure the user can't get messages from a +s channel unless
        # they're calling the command from that channel or from a query
        def notSecretMsg(m):
            return not irc.isChannel(msg.args[0]) \
                    or msg.args[0] == m.args[0] \
                    or (m.args[0] in irc.state.channels \
                        and 's' not in irc.state.channels[m.args[0]].modes)
        predicates.append(notSecretMsg)
        resp = []
        if irc.nested and not \
          self.registryValue('last.nested.includeTimestamp'):
            tsf = None
        else:
            tsf = self.registryValue('timestampFormat')
        if irc.nested and not self.registryValue('last.nested.includeNick'):
            showNick = False
        else:
            showNick = True
        for m in iterable:
            for predicate in predicates:
                if not predicate(m):
                    break
            else:
                if nolimit:
                    resp.append(ircmsgs.prettyPrint(m,
                                                    timestampFormat=tsf,
                                                    showNick=showNick))
                else:
                    irc.reply(ircmsgs.prettyPrint(m,
                                                  timestampFormat=tsf,
                                                  showNick=showNick))
                    return
        if not resp:
            irc.error('I couldn\'t find a message matching that criteria in '
                      'my history of %s messages.' % len(irc.state.history))
        else:
            irc.reply(format('%L', resp))
Exemple #4
0
class Debian(callbacks.Plugin, PeriodicFileDownloader):
    threaded = True
    periodicFiles = {
        # This file is only updated once a week, so there's no sense in
        # downloading a new one every day.
        'Contents-i386.gz':
        ('ftp://ftp.us.debian.org/'
         'debian/dists/unstable/Contents-i386.gz', 604800, None)
    }
    contents = conf.supybot.directories.data.dirize('Contents-i386.gz')

    def file(self, irc, msg, args, optlist, glob):
        """[--{regexp,exact} <value>] [<glob>]

        Returns packages in Debian that includes files matching <glob>. If
        --regexp is given, returns packages that include files matching the
        given regexp.  If --exact is given, returns packages that include files
        matching exactly the string given.
        """
        self.getFile('Contents-i386.gz')
        # Make sure it's anchored, make sure it doesn't have a leading slash
        # (the filenames don't have leading slashes, and people may not know
        # that).
        if not optlist and not glob:
            raise callbacks.ArgumentError
        if optlist and glob:
            irc.error(
                'You must specify either a glob or a regexp/exact '
                'search, but not both.',
                Raise=True)
        for (option, arg) in optlist:
            if option == 'exact':
                regexp = arg.lstrip('/')
            elif option == 'regexp':
                regexp = arg
        if glob:
            regexp = fnmatch.translate(glob.lstrip('/'))
            regexp = regexp.rstrip('$')
            regexp = ".*%s.* " % regexp
        try:
            re_obj = re.compile(regexp, re.I)
        except re.error, e:
            irc.error(format('Error in regexp: %s', e), Raise=True)
        if self.registryValue('pythonZgrep'):
            fd = gzip.open(self.contents)
            r = imap(
                lambda tup: tup[0],
                ifilter(lambda tup: tup[0],
                        imap(lambda line: (re_obj.search(line), line), fd)))
        else:
            try:
                (r, w) = popen2.popen4(['zgrep', '-ie', regexp, self.contents])
                w.close()
            except TypeError:
                # We're on Windows.
                irc.error(
                    'This command won\'t work on this platform.  '
                    'If you think it should (i.e., you know that you '
                    'have a zgrep binary somewhere) then file a bug '
                    'about it at http://supybot.sf.net/ .',
                    Raise=True)
        packages = set()  # Make packages unique
        try:
            for line in r:
                if len(packages) > 100:
                    irc.error(
                        'More than 100 packages matched, '
                        'please narrow your search.',
                        Raise=True)
                try:
                    if hasattr(line, 'group'):  # we're actually using
                        line = line.group(0)  # pythonZgrep  :(
                    (filename, pkg_list) = line.split()
                    if filename == 'FILE':
                        # This is the last line before the actual files.
                        continue
                except ValueError:  # Unpack list of wrong size.
                    continue  # We've not gotten to the files yet.
                packages.update(pkg_list.split(','))
        finally:
            if hasattr(r, 'close'):
                r.close()
        if len(packages) == 0:
            irc.reply('I found no packages with that file.')
        else:
            irc.reply(format('%L', sorted(packages)))