Пример #1
0
    def c(self, irc, msg, args, a, c, b, iftrue, iffalse):
        """<a> (==|!=|<|>|<=|>=|==#|!=#|<#|>#|<=#|>=#) <b> [<dotrue>]
        [<dofalse>]

        Compares <a> with <b>.  If true, then returns <iftrue> or else,
        <iffalse>.  Operators ending in '#' compare <a>'s
        string length with <b>, which must be an integer in this case.
        In '==' comparisons, <b> can be a regular expression by encasing
        it within a delimiter.  If either <a> or <b> are @last or
        @last[<nick>], uses the result of the last match/replace operation
        from yourself or <nick>, respectively.
        See $delims for valid delimiter characters.
        """
        # TODO: <type> <a> <oper> <type> <b> ... [<a>, <b>]
        # <condition>: <command> <parms> ...
        a = wvm.fixexpr(ircutils.stripFormatting(a), False)
        a = self._getmatch(msg.nick, a)[1]
        b = wvm.fixexpr(ircutils.stripFormatting(b))
        b = self._getmatch(msg.nick, b)[1]
        if c.endswith('#'):
            if b.isdigit():
                a = len(a)
                b = int(b)
            else:
                irc.error('<b> must be an integer.')
                return
        elif c in ('<', '>', '<=', '>='):
            try:
                a = float(a)
                b = float(b)
            except ValueError:
                pass
        if c in ('==', "!="):
            nick, expr = wvm.parseexpr(b)
            try:
                if expr['isre']:
                    r = re.search(expr['match'], a)
                else:
                    r = a == expr['match']
                if c.startswith('!'):
                    r = not r
            except re.error:
                r = False
        elif c in ('<', '<#'):
            r = a < b
        elif c in ('>', '>#'):
            r = a > b
        elif c in ('<=', '<=#'):
            r = a <= b
        elif c in ('>=', '>=#'):
            r = a >= b
        elif c == '==#':
            r = a == b
        elif c == '!=#':
            r = a != b
        else:
            irc.error('Invalid operator.')
            return
        if r:
            if iftrue:
                if iftrue == '%a':
                    r = a
                elif iftrue == '%b':
                    r = expr['match']
                else:
                    r = iftrue
            else:
                r = a
        else:
            if iffalse:
                if iffalse == '%a':
                    r = a
                elif iffalse == '%b':
                    r = expr['match']
                else:
                    r = iffalse
            else:
                r = expr['match']
        self._setmatch(msg.nick, r)
        irc.reply(r)
Пример #2
0
    def array(self, irc, msg, args, opts, index, elements):
        """<index> [--i] [<key>:]<string> [[<key>:]<string> ...] [?:<string>]

        Returns the <string> whose <key> matches <index>.
        An <index> of "?" returns a random item.  Keys that are not
        defined will be assigned the number of their position, starting
        at zero.  If a key is not found and a "!" key exists, it will be
        returned instead, otherwise, an key error will be thrown.  If
        --i is set, keys will be case-insensitive.  Multiple keys can be
        assigned to a string by separating them with semicolons.
        This function is meant to be used in an alias:
            array $1 key1:item1 key2:item2 ...
        """
        array = {}
        casei = False
        for o, a in opts:
            if o == "i":
                casei = True
        for position, element in enumerate(elements):
            element = element.split(":", 1)
            if len(element) == 1:
                array[str(position)] = element[0]
            else:
                if casei:
                    element[0] = element[0].lower()
                for key in element[0].split(";"):
                    array[wvm.fixexpr(key, False)] = wvm.fixexpr(element[1]).lstrip()
        if not index:
            index = "0"
        elif index == "#":
            try:
                irc.reply(len(array))
            except KeyError:
                irc.reply(0)
            return
        elif index == "@":
            try:
                irc.reply(" / ".join(sorted(array.values(), reverse=True)))
            except KeyError:
                irc.reply("")
            return
        elif index == "@@":
            try:
                irc.reply(" / ".join(sorted(array.keys(), reverse=True)))
            except KeyError:
                irc.reply("")
            return
        elif index == "?":
            element = self.rng.choice(array.values())
        else:
            index = wvm.fixexpr(index, False)
            if casei:
                index = index.lower()
            try:
                element = array[index]
            except KeyError:
                try:
                    element = array["!"]
                except KeyError:
                    irc.error("No such array key: %s" % index)
                    return
        irc.reply(element)
Пример #3
0
    def var(self, irc, msg, args, opts, name, elements):
        """[--i] [--d=<default>] [--u=<ifundef>] [--t=<timeout>] [--o=<owner>] <var>[:<index>] [[<key>:]<string> ...]

        If no <key>:<string> pair or <string> arguments are included,
        returns the <string> whose <key> matches <index> in variable
        <var>.  If the <index> is left out, it will be assumed to be
        "0".  An <index> of "?" returns a random item.  Adding
        <key>:<string> pair or <string> arguments will set <var> to
        them.  If an <index> is included with this, the existing
        <string> at that index will be set to the arguments as one
        merged <string>.  If a <key> is left out, it will be assingned
        the number of that item's position, starting at zero.
        If a <key> is not found for an <index> and a "!" key exists,
        its will be returned instead; otherwise, a key error will be
        thrown.  Multiple keys can be assigned to a string by separating
        them with semicolons.  If --i is set, keys will be case-insensitve.
        Variables will live up to ~10 seconds unless the timeout is set with
        --t (0 == permanent).  Variables can be made private (only the same
        user can modify) by prefixing it with an underscore.  If --d is set,
        <default> will be returned as the value.  If --u is set, <ifundef>
        will be returned as the error if the variable isn't defined.  If --o
        is set, will give read-only access to variables belonging to that
        owner.
        """
        name = name.split(":", 1)
        default = None
        ifundef = None
        index = None
        private = False
        casei = False
        count = False
        owner = msg.nick.lower()
        timeout = 10
        for o, a in opts:
            if o == "i":
                casei = True
            elif o == "t":
                timeout = max(0, int(a))
            elif o == "d":
                default = a
            elif o == "u":
                ifundef = a
            elif o == "o":
                owner = a
        if name[0].startswith("_"):
            private = True
            name[0] = "%s-%s" % (name[0], owner)
        if len(name) == 2:
            index = wvm.fixexpr(name[1]).lstrip()
        else:
            index = None
        name = name[0].lower()
        try:
            if not elements:
                if not index:
                    index = "0"
                elif index == "#":
                    try:
                        irc.reply(len(self.variables[name][0]))
                    except KeyError:
                        irc.reply(0)
                    return
                elif index == "@":
                    try:
                        irc.reply(" / ".join(sorted(self.variables[name][0].values())))
                    except KeyError:
                        irc.reply("")
                    return
                elif index == "@@":
                    try:
                        irc.reply(" / ".join(sorted(self.variables[name][0].keys())))
                    except KeyError:
                        irc.reply("")
                    return
                elif index == "?":
                    element = self.variables[name][0].values()
                    irc.reply(self.rng.choice(element))
                    return
                try:
                    if self.variables[name][3]:
                        index = index.lower()
                except KeyError:
                    if default:
                        irc.reply(default)
                    elif ifundef:
                        irc.error(ifundef)
                    else:
                        irc.error('Variable "%s" is undefined.' % name)
                    return
                irc.reply(self.variables[name][0][index])
            else:
                if private and not ircdb.checkCapability(msg.prefix, "owner"):
                    if not ircutils.nickEqual(owner, msg.nick):
                        irc.error("Only read-only allowed outside your scope.")
                        return
                    try:
                        current_owner = self.variables[name][2]
                        if not ircutils.nickEqual(current_owner, msg.nick):
                            irc.error('Variable "%s" is locked by %s.' % (name, current_owner))
                            return
                    except KeyError:
                        pass
                if not index:
                    array = {}
                    for position, element in enumerate(elements):
                        element = element.split(":", 1)
                        if len(element) == 1:
                            array[str(position)] = element[0]
                        else:
                            if casei:
                                element[0] = element[0].lower()
                            for key in element[0].split(";"):
                                array[wvm.fixexpr(key, False)] = wvm.fixexpr(element[1]).lstrip()
                    self.variables[name] = [array, (time.time(), timeout), owner, casei]
                else:
                    if casei:
                        index = index.lower()
                    try:
                        self.variables[name][0][index] = " ".join(elements)
                        self.variables[name][1] = (time.time(), timeout)
                        self.variables[name][2] = owner
                    except KeyError:
                        self.variables[name] = [{index: " ".join(elements)}, (time.time(), timeout), owner, casei]
                self._writevarsfile()
                irc.reply("")
        except KeyError:
            try:
                irc.reply(self.variables[name][0]["!"])
            except KeyError:
                irc.error("No such variable key: %s[%s]" % (name, index))
Пример #4
0
def striphtml(html, tags=[True], limit=0, offset=0, joiner=''):
    """
    Extracts the text from a list of HTML <tags> in <html>, returning
    up to <limit> elements per tag, starting at match <offset>.
    """
    soup = BeautifulSoup(html)
    comments = soup.find_all(text=lambda text:isinstance(text, Comment))
    [comment.extract() for comment in comments]
    text = []

    for tag in tags:
        tag = str(tag).split(':')
        skip = offset
        matches = 0
        attrs = {}
        getprop = None

        try:
            skip += int(float(tag[0]))
            tag = tag[1:]
        except ValueError:
            pass

        if tag[0] in ('', 'True'):
            tag[0] == 'body'

        for attr in tag[1:]:
            attr = attr.split('=', 2)
            l = len(attr)
            if l == 1:
                getprop = attr[0]
            elif l > 1:
                try:
                    attrs[attr[0]] = re.compile(wvm.fixexpr(attr[1]))
                except re.error:
                    attrs[attr[0]] = attr[1]

                if l == 3:
                    getprop = attr[2]

        for tag in soup.find_all(tag[0], attrs=attrs):
            if not getprop:
                if skip > 0:
                    skip -= 1
                    continue
                text.append(tagtotext(tag, joiner))
            else:
                try:
                    t = tag[getprop]
                    if skip > 0:
                        skip -= 1
                        continue
                    text.append(t)
                except KeyError:
                    continue
            matches += 1
            if matches == limit:
                break

        text.append('~~')
    return "\n".join(text[:-1])