Example #1
0
    def __init__(self, parent=None, event=None):
        if event:
            self.event = event
        else:
            self.event = Event('', '', '', [''])
        self.source = event.source()
        self.source_nick = event.source_nick 

        self.handler = parent
        self.bot = parent.bot
        self.conn = parent.conn
        self.storage = parent.storage
        self.storage.setdefault('extra_commands', {})
Example #2
0
 def group_to_event(group):
     e = Event('pubmsg', group['nick'], target, (group['message'],))
     e.timestamp = datetime.datetime(int(stats['year']), months.index(stats['month']), int(stats['date']), \
                                     int(group['H']), int(group['M']), int(group['S']))
     e.keywords = Lexer(group['message']).keywords
     return e
Example #3
0
class Commands(object):
    def __init__(self, parent=None, event=None):
        if event:
            self.event = event
        else:
            self.event = Event('', '', '', [''])
        self.source = event.source()
        self.source_nick = event.source_nick 

        self.handler = parent
        self.bot = parent.bot
        self.conn = parent.conn
        self.storage = parent.storage
        self.storage.setdefault('extra_commands', {})

    def reply(self, message):
        self.handler.reply(self.event, message)

    def match(self, nick):
        if not len(self.event.arguments()):
            return
        
        text = self.event.arguments()[0]
        cmdline = ''
        match = COMMAND_REGEX.match(text)
        if match:
            cmdline = match.groups()[1]
        elif self.event.eventtype() == 'privmsg':
            cmdline = text
        
        if self.parse_cmdline(cmdline):
            return self
    
    def parse_cmdline(self, cmdline, doreturn=False):
        if not cmdline:
            return
       
        results = []
        
        def find_cmd(cmdline, n):
            name = ('_'.join(cmdline.split(' ', n)[:n])).lower()
            if name in self.storage['extra_commands']:
                mod = util.get_module(self.storage['extra_commands'][name])
                method = lambda: getattr(mod, "cmd_" + name, None)(self)
            else:
                method = getattr(self, "cmd_" + name, None)
            
            
            if method:
                params = (cmdline + ' ').split(' ', n)[1].strip()
                results.append((method, params))

        [find_cmd(cmdline, n) for n in range(1, 5)]
        
        if results:
            if doreturn:
                return results[-1]
            else:
                self.command, self.params = results[-1]
                return True

    def do(self):
        self.handler.send(self.command(), self.event)
    
    def command(self):
        '''dummy function to be replaced by other commands'''
        pass

    @cmd.admin
    def cmd_die(self):
        self.storage.save()
        self.bot.die('*dies*')
    
    @cmd.admin
    def cmd_eval(self):
        '''this is a docstring i just added'''
        import code
        codestring = self.params.replace("[NL]", "\n")
        try:
            return str(eval(compile(codestring, '<irc>', 'eval')))
        except Exception:
            self.enable_stdout()
            try:
                eval(code.compile_command(codestring))
            except Exception:
                return util.exc_lines()[-1]
            self.disable_stdout()
    
    def enable_stdout(self):
        if hasattr(self.storage, "stdout") and self.storage.stdout:
            return
        self.storage.stdout = sys.stdout

        def message(buffer):
            self.reply("stdout: " + buffer.strip())

        handler = self.handler
        class NewStdout(object):
            def __init__(self):
                self.buffer = StringIO()
            
            def write(self, text):
                self.buffer.write(text)
                if text.find("\n") != -1:
                    message(self.buffer.getvalue())
                    self.buffer = StringIO()

        sys.stdout = NewStdout()

    def disable_stdout(self):
        if hasattr(self.storage, "stdout") and self.storage.stdout:
            sys.stdout = self.storage.stdout
            self.storage.stdout = None

    @cmd.user
    @params.new('#channel')
    def cmd_join(self, channel):
        self.conn.join(channel)

    @cmd.admin
    @params.new('#channel [...]')
    def cmd_leave(self, channel, msg):
        self.conn.part(channel, msg or '')
    
    @cmd.admin
    @params.auto
    def cmd_nick(self, nick):
        self.conn.nick(nick)
    
    @cmd.admin
    @params.new('/(markov|outputqueue)/')
    def cmd_reload(self, what):
        if what == 'markov':
            start = time.time()
            reload(markov).rebuild()
            return "took %s seconds" % (time.time() - start)
        elif what == 'outputqueue':
            self.storage.output = util.get_module('outputqueue').Manager()
            return "now what?"

    @cmd.user
    @params.auto
    def cmd_set(self, option, value=None):
        option = option.strip().lower()
        key = "option_%s" % option
        if value is None:
            self.storage[key] = not self.storage.get(key, False)
        else:
            self.storage[key] = bool(value)
        return "%s set to %s" % (option, self.storage[key])

    @cmd.user
    def cmd_list_options(self):
        keys = [(x, y) for (x, y) in self.storage.items() if x.startswith("option_")]
        return (', '.join(['%s (%s)' % x for x in keys]))

    @cmd.admin
    @params.new('/(load|unload|list)/ [...]')
    def cmd_module(self, action, modules):
        modules = modules and modules.split() or []
    
        for module in modules:
            try:
                if action == 'load' and module not in self.storage['modules']:
                    mod = util.get_module(module)
                    mod.load(self.handler)
                    
                    if getattr(mod, 'PROVIDES_COMMANDS', None):
                        for cmd in mod.PROVIDES_COMMANDS:
                            self.storage['extra_commands'][cmd] = module
                    
                    self.storage['modules'].append(module)
                    self.storage.touch()
                elif action == 'unload' and module in self.storage['modules']:
                    self.storage['modules'].remove(module)
                    self.storage.touch()
                    mod = util.get_module(module)
                    mod.unload(self.handler)
                    
                    if getattr(mod, 'PROVIDES_COMMANDS', None):
                        for cmd in mod.PROVIDES_COMMANDS:
                            if cmd in self.storage['extra_commands']:
                                del self.storage['extra_commands'][cmd]
                        self.storage.touch()
            except:
                yield "%s: %s" % (module, util.exc_lines()[-1])
            else:
                yield '%s: done' % module
 
        if action == 'list':
            modules = self.storage['modules']
            all = [x.replace(".py", "").replace("mods/", "") for x in glob.glob("mods/*.py")]
            all = [x + (x in modules and "*" or "") for x in all if not x.startswith("_")]
            yield ', '.join(sorted(all))

    @cmd.user
    @params.auto
    def cmd_help(self, what=None):
        if what is None or what == 'all':
            cmdlist = cmd.list + self.storage['extra_commands'].keys()
            if self.source_nick in config.ADMINS and what == 'all':
                yield ', '.join(cmd.list)
            else:
                yield ', '.join([x for x in cmd.list if not x.endswith("*")])
            return
        elif hasattr(self, 'cmd_%s' % what):
            # command
            f = self.parse_cmdline(what, True)[0]
            usage = getattr(f, 'usage', DUNNO)
            yield "%s: Usage: %s" % (what, usage)
            if hasattr(f, '__doc__') and f.__doc__ is not None:
                yield "%s: %s" % (what, f.__doc__)
        else: 
            # module
            try:
                mod = util.get_module(what)
                if hasattr(mod, '__doc__') and mod.__doc__ is not None:
                    yield '%s (module): %s' % (what, mod.__doc__.split("\n")[0])
                else:
                    yield '%s (module)' % what
            except ImportError:
                pass
    
    @cmd.user
    @params.new('[#channel] ...')
    def cmd_say(self, to, msg):
        return Message(msg, to=to, event=self.event)

    @cmd.user
    @params.new('[#channel] ...')
    def cmd_action(self, to, msg):
        return Message(msg, to=to, event=self.event, action=True)

    @cmd.admin
    @params.new('[#channel] ...')
    def cmd_mode(self, channel, mode):
        channel = channel or self.event.target()
        self.conn.mode(channel, mode)

    @cmd.admin
    @params.new('...')
    def cmd_umode(self, mode):
        self.conn.mode(self.conn.get_nickname(), mode)
    
    @cmd.admin
    @params.new('[#channel] t:str [...]')
    def cmd_kick(self, channel, who, reason):
        channel = channel or self.event.target()
        reason = reason or ''
        self.conn.kick(channel, who, reason)

    @cmd.user
    @params.auto
    def cmd_markov(self, nick):
        return markov.markov(nick)[:400]

    @cmd.user
    def cmd_kriegs(self):
        return markov.markov("KriegsaffeNo9")
    
    @cmd.user
    def cmd_tumbleweed(self):
        r = random.randint(10,20)
        r2 = 7 + 15 - r
        r3 = random.randint(4, 7)
        r2 = r2 - r3 + 6
        t = tuple(["." * x for x in (r, r2, r3)])
        return "%s~*%s*%s*" % t
    
    @cmd.user
    @params.new('[#channel] [/wide/]')
    def cmd_nicks(self, channel, wide):
        channel = channel or self.event.target()
        if channel not in self.bot.channels:
            return
        users = self.bot.channels[channel].users()
        
        if wide == 'wide':
            filter = lambda s: ''.join([unichr(0xfee0 + ord(c)) for c in s]).replace(unichr(0xff00), unichr(0x3000))
        else:
            ZWSP = u'\u200b'
            filter = lambda s: ''.join([''.join(x) for x in map(None, s, ZWSP * len(s))])

        list = []
        current = ''
        for x in users:
            text = filter(x.lstrip("!@+%")).encode("utf8")
            if len(current) + len(text) > 450:
                list.append(current.strip())
                current = ''
            current += text + ' '
        list.append(current.strip())
        return list
        
    @cmd.user
    def cmd_kickban_stats(self):
        tops = self.storage.get('kickban_tops', {})
        ranking = sorted(tops.items(), key=lambda x: x[1], reverse=True)
        ranking = [(n + 1, nick, times) for (n, (nick, times)) in enumerate(ranking)]
        return ', '.join(["%s. %s (%s)" % t for t in ranking])

    @cmd.user
    @params.auto
    def cmd_attack(self, nick):
        return "&attack %s" % nick

    @cmd.user
    @params.auto
    def cmd_heal(self, nick):
        return "&heal %s" % nick

    @cmd.user
    def cmd_shut_up(self):
        self.storage.output.shut_up()

    @cmd.user
    def cmd_off(self):
        self.storage.output.shut_up()

    @cmd.user
    def cmd_come_back(self):
        self.storage.output.come_back()
        return 'ohai'
    
    @cmd.user
    def cmd_go_away(self):
        self.conn.part(self.event.target(), "bye")

    @cmd.user
    def cmd_gtfo(self):
        self.conn.part(self.event.target(), "bye")


# kept for historical purposes

#    def make_cocks(locals, name, list):
#        f = lambda self: self.reply('%s (%s): %s' % (name, len(list), ', '.join(sorted(list))))
#        f.__name__ = 'cmd_list_%s' % name
#        locals[f.__name__] = usercmd(f)
#        for x in list:
#            f = lambda self: self.reply(random.choice(list))
#            f.__name__ = 'cmd_%s' % x.replace(" ", "_")
#            locals[f.__name__] = cmd.hidden(f)
#    
#    make_cocks(locals(), 'derp', ['hurr', 'durr', 'derp', 'hurrdurr'])

    @cmd.user
    @params.new('/(add|remove|set|off)/ [#channel] [t:float]')
    def cmd_idle(self, action, channel, idletime):
        self.storage.setdefault('idle_enabled', set())
        self.storage.setdefault('idle_times', {})

        if action == 'set' and idletime:
            idletime = int(60 * idletime)
            self.storage['idle_time'] = idletime
            return "Idle time set to %s seconds" % idletime
        elif action == 'off':
            self.storage['idle_enabled'] = set()
            return "Ok, ok..."

        if action == 'add':
            self.storage['idle_enabled'].update([channel])
            self.storage['idle_times'][channel] = time.time()
            self.storage.touch()
            return 'Idle detectors enabled for %s' % channel

        elif action == 'remove':
            if channel in self.storage['idle_enabled']:
                self.storage['idle_enabled'].remove(channel)
                self.storage.touch()
                return 'Idle detectors disabled for %s' % channel 
            else:
                return '%s not enabled' % channel
    
    @cmd.user
    @params.new('/(radio|dxdx|.+)/')
    def cmd_np(self, nick):
        if nick == 'dxdx':
            s = socket.socket()
            IPS = ["192.168.0.16", "192.168.1.5", "192.168.0.30"]
            connected = False
            for ip in IPS:
                try:
                    s.connect((ip, 6600))
                except socket.error:
                    pass
                else:
                    connected = True 
                    break

            if connected:
                s.send("currentsong\n")
                time.sleep(0.4)
                result = dict([x.split(": ", 1) for x in s.recv(2048).split("\n")[1:-2]])
                if result:
                    return (nick + " np: %(Artist)s - %(Title)s [%(Album)s]" % result)
        elif nick == 'radio':
            return ("desuradio np: " + [x for x in urllib.urlopen("http://desuchan.net:8000/").readlines() if x.count("streamdata")][-1].split(">")[1].split("<")[0])
        else:
            key = "8977c4d8c9031da3608cd318bc56b70e"
            url = "http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=%s&api_key=%s&limit=1"
            track = ET.fromstring(urllib.urlopen(url % (nick, key)).read())[0][0]
            trackdict = dict([(x.tag, x.text) for x in track])
            
            if 'date' in trackdict:
                datetime.strptime(trackdict['date'], "%d %b %Y, %H:%M")
                trackdate = datetime.strptime(trackdict['date'], "%d %b %Y, %H:%M")

                # up to 30 minutes
                recent = (datetime.now() - trackdate) < timedelta(0, 1800, 0)
            else:
                recent = True
            
            if recent:
                return (nick + (u" np: %(artist)s - %(name)s" % trackdict).encode("utf8"))
        return (nick + " np: nothing %s" % DESPAIR)
        
    
    @cmd.user
    @params.new('[#channel] [t:int] [/(line|reply|context|before)/] ...')
    def cmd_grepback(self, channel, results, what, words):
        channel = channel or '#desuchan'
            
        if not results or results > 10:
            results = 1

        grep_params = []
        if what == 'before':
            grep_params = ['-A1']
        elif what == 'reply':
            grep_params = ['-B1']
        elif what == 'context':
            grep_params = ['-C1']
        
        grep_params.append('-m%s' % results)
            
        tac = Popen(["tac", LOGS_PATH + channel + ".log"], stdout=PIPE)
        grepv = Popen(["grep", "-v", "\(<.dekisu>\|> \(dekisu: \|:\)grepback\)"], stdin=tac.stdout, stdout=PIPE)
        grep = Popen(["grep", "-iF"] + grep_params + [words], stdin=grepv.stdout, stdout=PIPE)

        ret = grep.communicate()[0].strip()
        if ret.count("\n") == 0:
            return ret
        elif ret:
            r = [Message(x, to=self.source_nick) for x in ret.split("\n")[::-1]]
            return r
        else:
            return Message("Nothing found", to=self.source_nick)

    @cmd.user
    @params.new('[t:str]')
    def cmd_rena_stats(self, who):
        channel = '#desuchan'

        which = who and r'\2' or r'\1'
        who = who or '[^>]*'

        egrep = Popen(['egrep', '-i', '^[0-9:]{5} <.%s> &[0-9a-z]+' % who, LOGS_PATH + channel + ".log"], stdout=PIPE)
        sed = Popen(['sed', '-r', 's/^[0-9:]{5} <.(%s)> &([0-9a-z]+).*$/%s/g' % (who, which)], stdin=egrep.stdout, stdout=PIPE)
        sort = Popen(['sort'], stdin=sed.stdout, stdout=PIPE)
        uniq = Popen(['uniq', '-c'], stdin=sort.stdout, stdout=PIPE)
        sortn = Popen(['sort', '-n'], stdin=uniq.stdout, stdout=PIPE)
        tail = Popen(['tail', '-n20'], stdin=sortn.stdout, stdout=PIPE)
        
        list = []
        for line in tail.communicate()[0].strip().split("\n"):
            yield repr(line.strip().split())
            #number, item = line.strip().split()
            #list.append((number, item))
        #list.sort(key=lambda x: x[0])
        #return ','.join(['%s. %s (%s)' % (x, y[1], y[0]) for x, y in enumerate(list)])

    @cmd.user
    @params.new('[t:str] [t:str]')
    def cmd_asd(self, who, word):
        channel = '#desuchan'

        egrep = Popen(['egrep', '-i', '^[0-9:]{5} <.%s> ' % who, LOGS_PATH + channel + ".log"], stdout=PIPE)
        all = 0
        matched = 0
        for line in egrep.communicate()[0].strip().split("\n"):
            if line.lower().find(word) != -1:
                matched += 1
            all += 1

        return '%s said %s %s out of %s messages (%s%%)' % (who, word, matched, all, matched / float(all) * 100)

    @cmd.user
    def cmd_pipe(self):
        redirect = re.compile("^(.*)> ?([#|a-zA-Z0-9_-]*) *$")
        m = redirect.match(self.params)
        if m:
            self.parse_cmdline(m.groups()[0])
            target = m.groups()[1]

            self.event._target = target
            self.event._eventtype = 'pubmsg'

            retval = self.command()
            for m in messages.normalize(retval):
                m.to = target
            return retval
        else:
            return 'Usage: pipe somecommandhere > #channelname'

    @cmd.admin
    def cmd_storage_tree(self):
        def tree(dict):
            for key, value in dict.iteritems():
                yield '%s = %s' % (key, value)
        
        return tree(self.storage)

    @cmd.admin
    @params.new('/(del|set|get)/ t:str [t:str]')
    def cmd_storage(self, action, key, value):
        if action == 'del':
            if key in self.storage:
                del self.storage[key]
                return '%s removed from storage' % key
            else:
                return 'No such key'
        elif action == 'set':
            self.storage[key] = eval(value)
        elif action == 'set':
            return repr(self.storage[key])

    @cmd.user
    @params.new('t:str [...]')
    def cmd_test(self, filename, content):
        PATH = "/home/dx/cocks/%s"
        URL = "http://dequis.no-ip.org/%s"
        if content:
            open(PATH % filename, "w").write(eval(content))
            return URL % filename
        else:
            return URL % filename + " - contents: " + repr(open(PATH % filename).read())

    @cmd.user
    def cmd_raise_an_exception_motherfucker(self):
        raise Exception('ok')

    @cmd.user
    def cmd_fakemon(self):
        randomsort = lambda x: sorted(x, key=lambda y: random.random())

        vowels = "aeiou"
        consonants = "bcdfghjklmnpqrstvwxyz"

        length = random.randint(2,3)
        return ''.join(map(lambda x, y: x + y,
            randomsort(consonants)[:length],
            randomsort(vowels)[:length])).title() + "mon"

    @cmd.user
    @params.new('[...]')
    def cmd_noop(self, arg):
        pass

    @cmd.user
    def cmd_colortable(self):
        table = ' '.join(['\3%s text %s' % (x, x) for x in range(16)])
        return '\x031,1%s\n\x031,1\2%s' % (table, table)
Example #4
0
    def handler(self, **args):
        """Simply increments a counter in the database that keeps track of how
		many times a person has spoken.  Also stores a random quote from the
		person (basically 10% chance a given quote is going to be chosen for the
		"random quote" in the database."""
        import database, time, random
        from irclib import Event, nm_to_n

        # Get nick and quote text
        nick = nm_to_n(args["source"]).lower()
        quote = self.sqlEscape(" ".join(args["text"].split()[1:]))
        channel = args["channel"].lower()
        if args["type"] == "privmsg": target = nm_to_n(args["source"])
        else: target = args["channel"]
        # Increment counter for that nick if it exists, otherwise insert into DB
        query = "select count, quote_time from webstats where nick='" + \
         nick + "' and" + " channel='" + channel + "'"
        result = database.doSQL(query)
        response = []
        if result == []:
            # Insert their first quote as their random quote and set count to 1
            query = "insert into webstats(nick, channel, count, quote," \
             + " quote_time) values('" + nick + "', '" + channel + "', 1, '" \
             + quote + "', " + str(int(time.time())) + ")"
            database.doSQL(query)


#			response.append(Event("action", "", target, \
#				["jots down a new quote for " + nick]))
        else:
            import time
            # Get the current count and increment it
            new_count = int(result[0][0]) + 1
            # Get the current quote's date
            quote_time = int(result[0][1])
            curr_time = int(time.time())
            secs_elapsed = curr_time - quote_time
            days_elapsed = secs_elapsed / 24 / 60 / 60
            # We don't want quotes that are under 8 letters, they are boring.
            #
            # We also don't want quotes of less than 4 words, also usually
            # boring as well.
            #
            # We also don't want stale quotes, so use the number of days since
            # the current quote times some constant to pick the quote
            if (random.randrange(new_count) < (days_elapsed * 10)) and \
             len(quote) > 8 and \
             len(quote.split()) >= 4:
                query = "update webstats set count=" + str(new_count) \
                 + ", quote='" + quote + "', quote_time=" \
                 + str(int(time.time())) + " where nick='" + nick + "'" \
                 + " and channel='" + channel + "'"
                database.doSQL(query)
                if new_count > 10:
                    response.append(Event("continue", "", target, [""]))
            else:
                query = "update webstats set count=" + str(new_count) + " where " \
                + "nick='" + nick + "' and channel='" + channel + "'"
                database.doSQL(query)

        response.append(Event("continue", "", target, [""]))
        return response
Example #5
0
    def handler(self, **args):
        """Allows someone to alter material in a factoid by using a regular
		expression.  Invoked like: "moobot: foo =~ s/moo/bar/"."""
        import priv, re, time
        from irclib import Event
        target = self.return_to_sender(args)

        # Grab the factoid to change:
        # first, drop the bot name
        factoid_key = " ".join(args["text"].split()[1:])
        # Now split on " =~ " and take the left half
        factoid_key = factoid_key.split(" =~ ", 1)[0]

        locked_by = FactoIds.getLockedBy(factoid_key)
        if locked_by == None:
            message = "Factoid '%s' does not exist." % factoid_key
            return Event("privmsg", "", target, [message])

        # Check for the appropriate privilege (delete_priv, even
        # though we aren't deleting - we are modifying, and there
        # is no modify priv)
        if priv.checkPriv(args["source"], "delete_priv") == 0 and (
                locked_by != "" and locked_by != args["source"]):
            message = "You do not have permission to modify factoid '%s." % factoid_key
            return Event("privmsg", "", target, [message])

        # get the original factoid value
        factoid = FactoIds.getValueByKey(factoid_key)

        # Grab the regex(es) to apply
        # First split on =~, then split on spaces for the RHS
        regexes_str = args["text"].split(" =~ ", 1)[1]
        # Now we can't split just on spaces, because the regex itself
        # can have spaces in it.  We gotta grab each one individually
        # because a regex to get them all (potentially each having
        # unique separators, like "s/foo/bar blatz/g s:moo:mooooo!:i
        # s%this%makes it hard to parse%".
        #
        # The basic algorithm is:
        # 1 - find out the separator character (2nd)
        # 2 - find the index of the third occurrence of this character
        # 3 - find the next space, chop off everything before it and
        #     append it to the regex_list
        regex_list = []
        # regex for removing leading spaces, compiling it first
        lead_spaces = re.compile("^\s+")
        while len(regexes_str) > 2:
            # Strip leading spaces first (so regexes with many spaces
            # between them don't mess things up when we assume the separator
            # is the second character)
            regexes_str = lead_spaces.sub("", regexes_str)
            # Separator = 2nd char
            separator = regexes_str[1]
            # Find it once, then use that as a low range
            # NOTE - if there is garbage at any point, ignore everything
            # after it
            second_sep = regexes_str.find(separator, 2)
            if second_sep == 0: break
            third_sep = regexes_str.find(separator, second_sep + 1)
            if third_sep == 0: break
            # now the space
            space_index = regexes_str.find(" ", third_sep)

            if space_index == -1:  # no space found
                regex_list.append(regexes_str)
                break
            else:
                regex_list.append(regexes_str[:space_index])
                regexes_str = regexes_str[space_index:]

        # apply each of the regexes in order
        # For now we are assuming all of the regexes are search and replace
        # s/foo/bar/[gi]
        ACCEPTABLE_PREFIXES = "sy"
        ACCEPTABLE_SUFFIXES = "gi"
        for regex_string in regex_list:
            # Split the regex into parts - strictly, we split on the second
            # character, as s:foo:bar: is valid as well
            try:
                parts = regex_string.split(regex_string[1])
            except IndexError:
                break

            # If we don't get four parts (even if the last is empty)
            # then it's not a valid regex - chastise them ... also,
            # if it's not one of the valid prefixes/suffixes, chastise them :)
            if len(parts) != 4 or \
            parts[0] not in ACCEPTABLE_PREFIXES:
                message = "Invalid regular expression: " + regex_string
                return Event("privmsg", "", target, [message])
            for letter in parts[3]:
                if letter not in ACCEPTABLE_SUFFIXES:
                    message = "Invalid regular expression: " + regex_string
                    return Event("privmsg", "", target, [message])

            # Get some flags before we compile a regex
            if "g" in parts[3]: count = 0
            else: count = 1
            if "i" in parts[3]: case_sensitive = 0
            else: case_sensitive = 1

            # Make a regex object for the first pattern
            try:
                re_str = parts[1]
                if case_sensitive:
                    regex = re.compile(re_str)
                else:
                    regex = re.compile(re_str, re.I)
            except re.error:
                message = "Invalid regular expression: " + regex_string
                return Event("privmsg", "", target, [message])

            # Actually perform the transformation
            if parts[0] == "s":
                factoid = regex.sub(parts[2], factoid)
            elif parts[0] == "y":
                message = "This regex not yet supported.  Sorry :("
                return Event("privmsg", "", target, [message])

        # When all the regexes are applied, store the factoid again
        # with the new date as the modification date.
        FactoIds.update(factoid_key, factoid, args["source"])
        return Event("privmsg", "", target, ["ok"])
Example #6
0
    def handler(self, **args):
        """ gets the factoid_value field """
        import time
        from irclib import Event, nm_to_n

        # Store the ref
        # 		ref = args["ref"]()

        # If we were /msg'ed this, /msg it back, otherwise send it to the
        # channel
        # (set up here because there are some rather early returns for the
        # continue handler types and whatnot)
        target = self.return_to_sender(args)

        factoid_key = args["text"]
        factoid_key = self.strip_words(factoid_key, 1)  # removes "moobot: "

        # By default we want to parse the factoid value after grabbing it from
        # the db, but certain flags along the way may set this flag so that we
        # don't do so (e.g., "literal").
        dont_parse = 0

        # If we are called with something like "moobot: literal foo", we want
        # to strip the "literal" from it as that is not part of the
        # factoid, unless of course nothing follows "literal", in which
        # case we would be looking for the factoid for "literal"
        if len(args["text"].split(" ")) > 1 and \
         args["text"].split(" ")[1] == "literal":
            dont_parse = 1  # set for later, when we spit the value back
            factoid_key = self.strip_words(factoid_key, 1)

        # Strip trailing ?'s and !'s (so asking for "moobot: foo?!?!?!???" is
        # the same as just asking for "moobot: foo"
        factoid_key = self.strip_punctuation(factoid_key)

        text = FactoIds.getValueByKey(factoid_key, args["source"])

        # If the factoid doesn't exist, simply continue trying
        # to match with other handlers using the continue event type
        if not text:
            return Event("continue", "", target, [""])

        ### The new length stuff
        # Here we check to see if the total message length would be greater
        # than irclib.MESSAGE_SIZE_LIMIT, and if so, split it up accordingly
        # and return the requested one, or print out a warning.

        # Message format:
        # nickname!username@localhost privmsg #channel_name :factoid_text


# 		self.debug("%s!%s@%s" % (ref.connection.ircname,
# 			ref.connection.username, ref.connection.localhost))
# #		msg_length = len(text) + len(" privmsg # :") + len(target) + \
# #			len(ref.connection.nickname) + len(ref.connection.username) + \
# #			len(ref.connection.localhost)
# #		self.debug(msg_length)

# by default we will just say something to the target, but if the
# factoid contains an <action> tag, we will make it an action
# eventtype
        eventtype = "privmsg"

        # If the person says something like "moobot: literal foo", we don't
        # want to parse the factoid, we just want to spit it back in its raw
        # form.  Otherwise, we want to replace parentheses and pipes as well
        # as see if we need to change the eventtype
        if not dont_parse:  # awkward, but supports the more general case,
            # instead of having to set a flag for every case
            # where we DO want to parse, only set a flag where
            # we do NOT parse

            # Strip spaces from the left-hand side
            text = text.lstrip()

            # Parse parentheses and pipes to come up with one random string
            # from many choices specified in the factoid
            text = FactoIds.parseSar(text)

            # Replace $who and $nick with the person requesting the factoid
            text = text.replace("$who", nm_to_n(args["source"]))
            if args.has_key("channel"):
                text = text.replace("$chan", args["channel"])
            text = text.replace("$nick", nm_to_n(args["source"]))

            # If the new string (after previous replacements) begins with
            # "<action>" or "<reply>" (case insensitive), then we strip them
            # and possibly change the eventtype if necessary.  Otherwise, we
            # simply say "foo is bar" back to the target.
            if text[:8].lower() == "<action>":
                eventtype = "action"
                text = text[8:]
            elif text[:7].lower() == "<reply>":
                text = text[7:]
            else:
                text = factoid_key + " is " + text

        return Event(eventtype, "", target, [text.strip()])
Example #7
0
	def handler(self, **args):
		from irclib import Event, nm_to_n
		params = args['text'].strip().split(' ')[1:]
		cmd = params[0]
		params = params[1:]

		paramc = len(params)
		if paramc == 1 and params[0].lower() == 'help':
			msg = self.msg_help
		elif cmd == 'imspk' or cmd == 'imsnb' or cmd == 'imsbt':
			if paramc != 1 and paramc != 2:
				msg = self.msg_imspkhelp
			else:
				if paramc == 2:
					nick, rival = params
				else:
					nick = nm_to_n(args['source'])
					rival = params[0]
				if nick == rival:
					msg = "%s cannot pk her/himself" % (nick)
				else:
					birthday = Birthday(nick).get()

					if not birthday:
						msg = self.msgfmt_setbirtyday % (nick)
					else:
						rival_birthday = Birthday(rival).get()
						if not rival_birthday:
							msg = self.msgfmt_setbirtyday % (rival)
						else:
							today = ND()
							def sumIms(ims, absolute):
								if absolute:
									return abs(ims[0]) + abs(ims[1]) + abs(ims[2])
								else:
									return ims[0] + ims[1] + ims[2]
							n_score = sumIms(self.calcIms(birthday, today), cmd == "imsbt")
							r_score = sumIms(self.calcIms(rival_birthday, today), cmd == "imsbt")
							if n_score == r_score:
								msg = "are %s and %s the same guy?" % (nick, rival)
							elif cmd == "imspk":
								if n_score > r_score:
									msg = "%s ROCKS and %s sucks today" % (nick, rival)
								elif n_score < r_score:
									msg = "%s sucks and %s ROCKS today" % (nick, rival)
							elif cmd == "imsnb":
								n_score = abs(n_score)
								r_score = abs(r_score)
								if n_score > r_score:
									msg = "%s is NBer than %s" % (nick, rival)
								elif n_score < r_score:
									msg = "%s is NBer than %s" % (rival, nick)
							elif cmd == "imsbt":
								if n_score > r_score:
									msg = "%s is BTer than %s" % (nick, rival)
								elif n_score < r_score:
									msg = "%s is BTer than %s" % (rival, nick)
		# 'ims here'
		elif paramc == 1 and self.pdate.search(params[0]):
			date = params[0]
			try:
				birthday = ND(date.split('-'))
			except:
				birthday = False
			if birthday:
				msg = self.calc(date, birthday)
			else:
				msg = "date error"
		elif paramc == 0 or paramc == 1:
			if paramc == 0:
				nick = nm_to_n(args['source'])
			elif paramc == 1:
				nick = params[0]
				
			b = Birthday(nick)
			birthday = b.get()

			if birthday:
				msg = self.calc(nick, birthday)
			else:
				msg = self.msgfmt_setbirtyday % (nick)
		else:
			msg = self.msg_help

		return Event("privmsg", "", self.return_to_sender(args), [ msg ])
Example #8
0
	def handler(self, **args):
		"""when you say, for instance, hehstats, this function is 
		called and reports your hehstats."""
		import database
		from irclib import nm_to_n, Event

		target = self.return_to_sender(args)

		# Grab which type of stat we are trying to get
		# 
		# Split into separate words, take the first word (which should be
		# "<type>stats"), and chop off the last five letters ("stats")
		type = args["text"].split(" ")[1][:-5]
		
		#type = args["text"]
		#type = type[type.find(" ")+1:]
		#type = type[:len(type)-5]
		
		# Grab the top 3
		records=database.doSQL("select nick, counter from stats where type = '" + type  + "' order by counter desc limit 3")
		stat=0
		text = "Top 3 \"" + type +"\"ers"
		addUser = 1
		while stat < 3 and stat < len(records) :
			text = text + "   " + str(stat+1) + ")  " + records[stat][0] + ": " + str(int(records[stat][1]))
			# If the user is in the top 3, no need to add their stats to the
			# end
			if records[stat][0] == nm_to_n(args["source"]):
				addUser = 0
			stat=stat+1

		# Grab the total stats and prepend them to the top 3
		records=database.doSQL("select sum(counter) from stats where type='" + type + "'")
		total = records[0][0]
		text = '"' + type + '" said a total of ' + str(total)[:-2] + ' times. ' + text

		# If we need to add the user's stats on, grab them and add them
		if addUser == 1:
			# Find the user's place in the grand scheme
			# 
			# First grab their totals
			usercount = database.doSQL("select counter from stats where type = '" + type + "' and nick = '" + nm_to_n(args["source"]) + "'")
			if len(usercount):
				usercount = usercount[0][0]
			else:
				usercount = 0
			# Then see how many have stats
			query = "select count(nick) from stats where type='" + type + "'"
			total_users = database.doSQL(query)[0][0]
			# And lastly, see how many have better stats
			query = "select count(nick) from stats where type='" + type + \
				"' and counter > " + str(usercount)
			beaten_by = database.doSQL(query)[0][0] + 1


			text += " -- You have said \"" + type +"\" " + \
				`int(usercount)` + " times, " + nm_to_n(args["source"]) + "."
				
			if usercount != 0:
				text += "  You rank " + str(beaten_by) + " out of " + \
				str(total_users) + "."

		return Event("privmsg", "", target, [ text ])