Example #1
0
    def rpn(self, irc, msg, args):
        """<rpn math expression>

        Returns the value of an RPN expression.
        """
        stack = []
        for arg in args:
            try:
                x = complex(arg)
                if x == abs(x):
                    x = abs(x)
                stack.append(x)
            except ValueError:  # Not a float.
                if arg in SAFE_ENV:
                    f = SAFE_ENV[arg]
                    if callable(f):
                        called = False
                        arguments = []
                        while not called and stack:
                            arguments.append(stack.pop())
                            try:
                                stack.append(f(*arguments))
                                called = True
                            except TypeError:
                                pass
                        if not called:
                            irc.error(_('Not enough arguments for %s') % arg)
                            return
                    else:
                        stack.append(f)
                elif arg in self._rpnEnv:
                    self._rpnEnv[arg](stack)
                else:
                    arg2 = stack.pop()
                    arg1 = stack.pop()
                    s = '%s%s%s' % (arg1, arg, arg2)
                    try:
                        stack.append(safe_eval(s, allow_ints=False))
                    except SyntaxError:
                        irc.error(
                            format(_('%q is not a defined function.'), arg))
                        return
        if len(stack) == 1:
            irc.reply(str(self._complexToString(complex(stack[0]))))
        else:
            s = ', '.join(map(self._complexToString, list(map(complex,
                                                              stack))))
            irc.reply(_('Stack: [%s]') % s)
Example #2
0
    def rank(self, irc, msg, args, channel, expr):
        """[<channel>] <stat expression>

        Returns the ranking of users according to the given stat expression.
        Valid variables in the stat expression include 'msgs', 'chars',
        'words', 'smileys', 'frowns', 'actions', 'joins', 'parts', 'quits',
        'kicks', 'kicked', 'topics', and 'modes'.  Any simple mathematical
        expression involving those variables is permitted.
        """
        if channel != '#':
            # Skip this check if databases.plugins.channelspecific is False.
            if msg.nick not in irc.state.channels[channel].users:
                irc.error(
                    format('You must be in %s to use this command.', channel))
                return
        expr = expr.lower()
        users = []
        for ((c, id), stats) in self.db.items():
            if ircutils.strEqual(c, channel) and \
               (id == 0 or ircdb.users.hasUser(id)):
                e = {}
                for attr in stats._values:
                    e[attr] = float(getattr(stats, attr))
                try:
                    v = safe_eval(expr, allow_ints=True, variables=e)
                except ZeroDivisionError:
                    v = float('inf')
                except NameError as e:
                    irc.errorInvalid(_('stat variable'), str(e))
                except InvalidNode as e:
                    irc.error(_('Invalid syntax: %s') % e.args[0], Raise=True)
                except Exception as e:
                    irc.error(utils.exnToString(e), Raise=True)
                else:
                    v = float(v)
                if id == 0:
                    users.append((v, irc.nick))
                else:
                    users.append((v, ircdb.users.getUser(id).name))
        users.sort()
        users.reverse()
        s = utils.str.commaAndify([
            '#%s %s (%.3g)' % (i + 1, u, v) for (i, (v, u)) in enumerate(users)
        ])
        irc.reply(s)
Example #3
0
    def icalc(self, irc, msg, args, text):
        """<math expression>

        This is the same as the calc command except that it allows integer
        math, and can thus cause the bot to suck up CPU.  Hence it requires
        the 'trusted' capability to use.
        """
        try:
            self.log.info('evaluating %q from %s', text, msg.prefix)
            x = safe_eval(text, allow_ints=True)
            irc.reply(str(x))
        except OverflowError:
            maxFloat = math.ldexp(0.9999999999999999, 1024)
            irc.error(_('The answer exceeded %s or so.') % maxFloat)
        except InvalidNode as e:
            irc.error(_('Invalid syntax: %s') % e.args[0])
        except NameError as e:
            irc.error(_('%s is not a defined function.') % str(e).split()[1])
        except Exception as e:
            irc.error(utils.exnToString(e))
Example #4
0
    def calc(self, irc, msg, args, text):
        """<math expression>

        Returns the value of the evaluated <math expression>.  The syntax is
        Python syntax; the type of arithmetic is floating point.  Floating
        point arithmetic is used in order to prevent a user from being able to
        crash to the bot with something like '10**10**10**10'.  One consequence
        is that large values such as '10**24' might not be exact.
        """
        try:
            self.log.info('evaluating %q from %s', text, msg.prefix)
            x = complex(safe_eval(text, allow_ints=False))
            irc.reply(self._complexToString(x))
        except OverflowError:
            maxFloat = math.ldexp(0.9999999999999999, 1024)
            irc.error(_('The answer exceeded %s or so.') % maxFloat)
        except InvalidNode as e:
            irc.error(_('Invalid syntax: %s') % e.args[0])
        except NameError as e:
            irc.error(_('%s is not a defined function.') % e.args[0])
        except MemoryError:
            irc.error(_('Memory error (too much recursion?)'))
        except Exception as e:
            irc.error(str(e))