Example #1
0
class Pdod(Persist):

    """ pickled dicts of dicts """

    def __init__(self, filename):
        Persist.__init__(self, filename)
        if not self.data: self.data = LazyDict()

    def __getitem__(self, name):
        """ return item with name """
        if self.data.has_key(name): return self.data[name]

    def save(self):
        Persist.save(self)

    def __delitem__(self, name):
        """ delete name item """
        if self.data.has_key(name): return self.data.__delitem__(name)

    def __setitem__(self, name, item):
        """ set name item """
        self.data[name] = item

    def __contains__(self, name):
        return self.data.__contains__(name)

    def setdefault(self, name, default):
        """ set default of name """
        return self.data.setdefault(name, default)

    def has_key(self, name):
        """ has name key """
        return self.data.has_key(name)

    def has_key2(self, name1, najsb):
        """ has [name1][najsb] key """
        if self.data.has_key(name1): return self.data[name1].has_key(najsb)

    def get(self, name1, najsb):
        """ get data[name1][najsb] """
        try:
            result = self.data[name1][najsb]
            return result
        except KeyError: pass

    def set(self, name1, najsb, item):
        """ set name, najsb item """
        if not self.data.has_key(name1): self.data[name1] = {}
        self.data[name1][najsb] = item
Example #2
0
class Pdod(Persist):
    """ pickled dicts of dicts """
    def __init__(self, filename):
        Persist.__init__(self, filename)
        if not self.data: self.data = LazyDict()

    def __getitem__(self, name):
        """ return item with name """
        if self.data.has_key(name): return self.data[name]

    def save(self):
        Persist.save(self)

    def __delitem__(self, name):
        """ delete name item """
        if self.data.has_key(name): return self.data.__delitem__(name)

    def __setitem__(self, name, item):
        """ set name item """
        self.data[name] = item

    def __contains__(self, name):
        return self.data.__contains__(name)

    def setdefault(self, name, default):
        """ set default of name """
        return self.data.setdefault(name, default)

    def has_key(self, name):
        """ has name key """
        return self.data.has_key(name)

    def has_key2(self, name1, najsb):
        """ has [name1][najsb] key """
        if self.data.has_key(name1): return self.data[name1].has_key(najsb)

    def get(self, name1, najsb):
        """ get data[name1][najsb] """
        try:
            result = self.data[name1][najsb]
            return result
        except KeyError:
            pass

    def set(self, name1, najsb, item):
        """ set name, najsb item """
        if not self.data.has_key(name1): self.data[name1] = {}
        self.data[name1][najsb] = item
Example #3
0
def savecallbacktable(modname=None):
    """ save command -> plugin list to db backend. """
    if modname:
        logging.warn("boot - module name is %s" % modname)
    global callbacktable
    assert callbacktable
    if not callbacktable.data:
        callbacktable.data = {}
    if modname:
        target = LazyDict(callbacktable.data)
    else:
        target = LazyDict()
    from jsb.lib.callbacks import first_callbacks, callbacks, last_callbacks, remote_callbacks

    for cb in [first_callbacks, callbacks, last_callbacks, remote_callbacks]:
        for type, cbs in cb.cbs.iteritems():
            for c in cbs:
                if modname and c.modname != modname:
                    continue
                if not target.has_key(type):
                    target[type] = []
                if not c.modname in target[type]:
                    target[type].append(c.modname)
    logging.warn("saving callback table")
    assert callbacktable
    assert target
    callbacktable.data = target
    callbacktable.save()
Example #4
0
def savecmndtable(modname=None, saveperms=True):
    """ save command -> plugin list to db backend. """
    global cmndtable
    if not cmndtable.data: cmndtable.data = {}
    if modname: target = LazyDict(cmndtable.data)
    else: target = LazyDict()
    global shorttable
    if not shorttable.data: shorttable.data = {}
    if modname: short = LazyDict(shorttable.data)
    else: short = LazyDict()
    global cmndperms
    from jsb.lib.commands import cmnds
    assert cmnds
    for cmndname, c in cmnds.iteritems():
        if modname and c.modname != modname or cmndname == "subs": continue
        if cmndname and c:
            target[cmndname] = c.modname
            cmndperms[cmndname] = c.perms
            try:
                s = cmndname.split("-")[1]
                if not target.has_key(s):
                    if not short.has_key(s): short[s] = [
                            cmndname,
                    ]
                    if cmndname not in short[s]: short[s].append(cmndname)
            except (ValueError, IndexError):
                pass
    logging.warn("saving command table")
    assert cmndtable
    assert target
    cmndtable.data = target
    cmndtable.save()
    logging.warn("saving short table")
    assert shorttable
    assert short
    shorttable.data = short
    shorttable.save()
    logging.warn("saving RE table")
    for command in cmnds.regex:
        retable.data[command.regex] = command.modname
    assert retable
    retable.save()
    if saveperms:
        logging.warn("saving command perms")
        cmndperms.save()
Example #5
0
def savecmndtable(modname=None, saveperms=True):
    """ save command -> plugin list to db backend. """
    global cmndtable
    if not cmndtable.data: cmndtable.data = {}
    if modname: target = LazyDict(cmndtable.data)
    else: target = LazyDict()
    global shorttable
    if not shorttable.data: shorttable.data = {}
    if modname: short = LazyDict(shorttable.data)
    else: short = LazyDict()
    global cmndperms
    from jsb.lib.commands import cmnds
    assert cmnds
    for cmndname, c in cmnds.iteritems():
        if modname and c.modname != modname or cmndname == "subs": continue
        if cmndname and c:
            target[cmndname] = c.modname  
            cmndperms[cmndname] = c.perms
            try:
                 s = cmndname.split("-")[1]
                 if not target.has_key(s):
                     if not short.has_key(s): short[s] = [cmndname, ]
                     if cmndname not in short[s]: short[s].append(cmndname)
            except (ValueError, IndexError): pass
    logging.warn("saving command table")
    assert cmndtable
    assert target
    cmndtable.data = target
    cmndtable.save()
    logging.warn("saving short table")
    assert shorttable
    assert short
    shorttable.data = short
    shorttable.save()
    logging.warn("saving RE table")
    for command in cmnds.regex:
        retable.data[command.regex] = command.modname
    assert retable
    retable.save()
    if saveperms:
        logging.warn("saving command perms")
        cmndperms.save()
Example #6
0
class FloodControl(object):

    def __init__(self):
        self.stats = StatDict()
        self.times = LazyDict()
        self.wait = LazyDict()
        self.warned = LazyDict()

    def reset(self, userhost):
        try: del self.times[userhost]
        except KeyError: pass
        try: del self.stats[userhost]
        except KeyError: pass
        try: del self.wait[userhost]
        except KeyError: pass
        try: del self.warned[userhost]
        except KeyError: pass

    def check(self, userhost, timetomonitor=60, threshold=10, wait=120, floodrate=1):
        u = userhost
        t = time.time()
        w = wait
        if self.times.has_key(u):
            if t - self.times[u] > w: self.reset(u) ; return False
            if (t - self.times[u] < timetomonitor): self.stats.upitem(u)
            if (self.stats.get(u) >  threshold) or (t - self.times[u] < floodrate): self.wait[userhost] = wait ; return True
        else: self.times[u] = t ; return False
        if self.stats.get(u) <= threshold: return False
        return True

    def checkevent(self, event, dobind=True):
        if not event.iscommand: return False
        if getmainconfig().floodallow: return False
        if dobind: event.bind()
        if not event.user: got = False
        else: got = True
        t = got and event.user.data.floodtime or 60
        if t < 60: t = 60
        threshold = got and event.user.data.floodthreshold or 20
        if threshold < 20: threshold = 20
        wait = got and event.user.data.floodwait or 120
        if wait < 120: wait = 120
        floodrate = got and event.user.data.floodrate or 0.1
        if floodrate < 0.1: floodrate = 0.1
        if not self.check(event.userhost, t, threshold, wait, floodrate): return False 
        if event.user and "OPER" in event.user.data.perms: return False
        logging.warn("floodcontrol block on %s" % event.userhost)
        if event.userhost not in self.warned:
            logging.warn("floodcontrol block on %s" % event.userhost)
            event.reply("floodcontrol enabled (%s seconds)" % wait)
        self.warned[event.userhost] = time.time()
        return True
Example #7
0
def makeoptions(ievent, options={}):
    options = LazyDict(options)
    try:
        optargs = ""
        optlist = []
        if not options.has_key('--filter'):
            options['--filter'] = ""
        if not options.has_key('--to'):
            options['--to'] = None
        if not options.has_key('--chan'):
            options['--chan'] = ievent.channel
        if not options.has_key('--how'):
            options['--how'] = "msg"
        if not options.has_key('--speed'):
            options['--speed'] = str(ievent.speed)
        else:
            options['--speed'] = str(options['--speed'])
        for i, j in options.iteritems():
            if '--' in i:
                optlist.append("%s=" % i[2:])
                if j:
                    optlist.append(j)
                continue
            if '-' in i:
                if j:
                    optargs += ":%s" % i[1:]
                else:
                    optargs += i[1:]
        args = ievent.txt.split()
        try:
            (opts, rest) = getopt.getopt(args[1:], optargs, optlist)
        except AttributeError, ex:
            print "option not allowed: %s" % str(ex), ievent.txt, options
            return 0
        except getopt.GetoptError, ex:
            return 0
Example #8
0
def savecallbacktable(modname=None):
    """ save command -> plugin list to db backend. """
    if modname: logging.warn("boot - module name is %s" % modname)
    global callbacktable
    assert callbacktable
    if not callbacktable.data: callbacktable.data = {}
    if modname: target = LazyDict(callbacktable.data)
    else: target = LazyDict()
    from jsb.lib.callbacks import first_callbacks, callbacks, last_callbacks, remote_callbacks
    for cb in [first_callbacks, callbacks, last_callbacks, remote_callbacks]:
        for type, cbs in cb.cbs.iteritems():
            for c in cbs:
                if modname and c.modname != modname: continue
                if not target.has_key(type): target[type] = []
                if not c.modname in target[type]:
                    target[type].append(c.modname)
    logging.warn("saving callback table")
    assert callbacktable
    assert target
    callbacktable.data = target
    callbacktable.save()
Example #9
0
class FloodControl(object):
    def __init__(self):
        self.stats = StatDict()
        self.times = LazyDict()
        self.wait = LazyDict()
        self.warned = LazyDict()

    def reset(self, userhost):
        try:
            del self.times[userhost]
        except KeyError:
            pass
        try:
            del self.stats[userhost]
        except KeyError:
            pass
        try:
            del self.wait[userhost]
        except KeyError:
            pass
        try:
            del self.warned[userhost]
        except KeyError:
            pass

    def check(self,
              userhost,
              timetomonitor=60,
              threshold=10,
              wait=120,
              floodrate=1):
        u = userhost
        t = time.time()
        w = wait
        if self.times.has_key(u):
            if t - self.times[u] > w:
                self.reset(u)
                return False
            if (t - self.times[u] < timetomonitor): self.stats.upitem(u)
            if (self.stats.get(u) > threshold) or (t - self.times[u] <
                                                   floodrate):
                self.wait[userhost] = wait
                return True
        else:
            self.times[u] = t
            return False
        if self.stats.get(u) <= threshold: return False
        return True

    def checkevent(self, event, dobind=True):
        if not event.iscommand: return False
        if getmainconfig().floodallow: return False
        if dobind: event.bind()
        if not event.user: got = False
        else: got = True
        t = got and event.user.data.floodtime or 60
        if t < 60: t = 60
        threshold = got and event.user.data.floodthreshold or 20
        if threshold < 20: threshold = 20
        wait = got and event.user.data.floodwait or 120
        if wait < 120: wait = 120
        floodrate = got and event.user.data.floodrate or 0.1
        if floodrate < 0.1: floodrate = 0.1
        if not self.check(event.userhost, t, threshold, wait, floodrate):
            return False
        if event.user and "OPER" in event.user.data.perms: return False
        logging.warn("floodcontrol block on %s" % event.userhost)
        if event.userhost not in self.warned:
            logging.warn("floodcontrol block on %s" % event.userhost)
            event.reply("floodcontrol enabled (%s seconds)" % wait)
        self.warned[event.userhost] = time.time()
        return True
Example #10
0
class Commands(LazyDict):

    """
        the commands object holds all commands of the bot.
 
    """

    def add(self, cmnd, func, perms, threaded=False, wait=False, orig=None, how=None, *args, **kwargs):
        """ add a command. """
        modname = calledfrom(sys._getframe())
        target = Command(modname, cmnd, func, perms, threaded, wait, orig, how)
        self[cmnd] = target
        try:
            c = cmnd.split('-')[1]
            if not self.subs: self.subs = LazyDict()
            if self.subs.has_key(c):
                if not self.subs[c]: self.subs[c] = []
                if target not in self.subs[c]: self.subs[c].append(target)
            else: self.subs[c] = [target, ]
        except IndexError: pass
        try:
            p = cmnd.split('-')[0]
            if not self.pre: self.pre = LazyDict()
            if self.pre.has_key(p):
                if not self.pre[p]: self.pre[p] = []
                if target not in self.pre[p]: self.pre[p].append(target)
            else: self.pre[p] = [target, ]
        except IndexError: pass
        return self

    def woulddispatch(self, bot, event, cmnd=""):
        """ 
            dispatch an event if cmnd exists and user is allowed to exec this 
            command.

        """
        event.bind(bot)
        cmnd = cmnd or event.usercmnd.lower()
        if not cmnd: return
        try:
            cmnd = event.chan.data.aliases[cmnd]
        except (KeyError, TypeError):
            try: cmnd = bot.aliases.data[cmnd]
            except (KeyError, TypeError): pass
        try:
            if cmnd:
                event.txt = cmnd +  ' ' + ' '.join(event.txt.split()[1:])
                event.usercmnd = cmnd.split()[0]
                event.prepare()
        except (TypeError, KeyError, AttributeError): pass
        logging.debug("commands - %s" % cmnd)
        bot.plugs.reloadcheck(bot, event)
        result = None
        cmnd = event.usercmnd
        try:
            result = self[cmnd]
        except KeyError:
            if self.subs and self.subs.has_key(cmnd):
                cmndlist = self.subs[cmnd]
                if len(cmndlist) == 1: result = cmndlist[0]
                else: event.reply("try one of: %s" % ", ".join([x.cmnd for x in cmndlist])) ; return
            else:
                if self.pre and self.pre.has_key(cmnd):
                    cmndlist = self.pre[cmnd]
                    if len(cmndlist) == 1: result = cmndlist[0]
                    else: event.reply("try one of: %s" % ", ".join([x.cmnd for x in cmndlist])) ; return
        logging.debug("commands - woulddispatch result: %s" % result)
        return result

    def dispatch(self, bot, event, wait=0):
        """ 
            dispatch an event if cmnd exists and user is allowed to exec this 
            command.

        """
        event.bind(bot)
        if event.groupchat: id = event.auth = event.userhost
        else: id = event.auth
        if not event.user: raise NoSuchUser(event.auth)
        c = self.woulddispatch(bot, event)
        if not c: raise NoSuchCommand()
        if bot.cmndperms and bot.cmndperms[c.cmnd]: perms = bot.cmndperms[c.cmnd]
        else: perms = c.perms
        if bot.allowall: return self.doit(bot, event, c, wait=wait)
        elif event.chan and event.chan.data.allowcommands and event.usercmnd in event.chan.data.allowcommands: 
            if not 'OPER' in perms:  return self.doit(bot, event, c, wait=wait)
            else: logging.warn("commands - %s is not in allowlist" % c)
        elif not bot.users or bot.users.allowed(id, perms, bot=bot): return self.doit(bot, event, c, wait=wait)
        elif bot.users.allowed(id, perms, bot=bot): return self.doit(bot, event, c, wait=wait)
        return event

    def doit(self, bot, event, target, wait=0):
        """ do the dispatching. """
        if not target.enable: return
        if target.modname in event.chan.data.denyplug:
             logging.warn("commands - %s is denied in channel %s - %s" % (target.plugname, event.channel, event.userhost))
             return
        id = event.auth or event.userhost
        event.iscommand = True
        event.how = target.how
        logging.warning('commands - dispatching %s for %s' % (event.usercmnd, id))
        try:
            if bot.isgae:
                if not event.notask and (target.threaded or event.threaded) and not event.nothreads:
                    logging.warn("commands - LAUNCHING AS TASK")
                    from jsb.lib.gae.tasks import start_botevent
                    event.txt = event.origtxt
                    start_botevent(bot, event, event.speed)
                    event.reply("task started for %s" % event.auth)
                else: target.func(bot, event) ; event.ready() ; return event
            else:
                if target.threaded and not event.nothreads:
                    logging.warning("commands - launching thread for %s" % event.usercmnd)
                    t = start_bot_command(target.func, (bot, event))
                    event.threads.append(t)
                else: event.dontclose = False; cmndrunner.put(target.modname, target.func, bot, event)
        except Exception, ex:
            logging.error('commands - %s - error executing %s' % (whichmodule(), str(target.func)))
            raise
        return event
Example #11
0
class Commands(LazyDict):

    """
        the commands object holds all commands of the bot.
 
    """

    regex = []

    def add(self, cmnd, func, perms, threaded=False, wait=False, orig=None, how=None, speed=None, regex=False, needcc=False, *args, **kwargs):
        """ add a command. """
        modname = calledfrom(sys._getframe())
        try: prev = self[cmnd]
        except KeyError: prev = None
        target = Command(modname, cmnd, func, perms, threaded, wait, orig, how, speed=speed, needcc=needcc)
        if regex:
            logging.info("regex command detected - %s" % cmnd)
            self.regex.append(target)
            target.regex = cmnd 
            return self
        self[cmnd] = target
        try:
            p = cmnd.split('-')[0]
            if not self.pre: self.pre = LazyDict()
            if self.pre.has_key(p):
                if not self.pre[p]: self.pre[p] = []
                if prev in self.pre[p]: self.pre[p].remove(prev) 
                if target not in self.pre[p]: self.pre[p].append(target)
            else: self.pre[p] = [target, ]
        except IndexError: pass
        return self

    def checkre(self, bot, event):
        gotcc = event.gotcc()
        for r in self.regex:
            if not r.enable: continue
            if r.needcc and not event.gotcc(): logging.debug("RE needs cc but not found") ; continue
            s = re.search(r.cmnd, event.txt)
            if s:
                logging.info("regex matches %s" % r.cmnd)
                event.groups = list(s.groups())
                return r

    def wouldmatchre(self, bot, event, cmnd=""):
        groups = self.checkre(bot, event)
        if groups: return groups
        
    def woulddispatch(self, bot, event):
        """ 
            dispatch an event if cmnd exists and user is allowed to exec this 
            command.

        """
        event.bind(bot)
        aliased = False
        try:
            cmnd = event.stripcc().split()[0]
            if not cmnd: cmnd = event.execstr.split()[0]
            if not cmnd: cmnd = event.txt.split()[0]
        except Exception, ex: logging.warn("can't determine command from %s" % event.txt) ; return None
        try:
            a = event.chan.data.aliases[cmnd]
            if a: cmnd = a.split()[0] ; aliased = True
        except (KeyError, TypeError):
            try:
                a = getaliases()[cmnd]
                if a: cmnd = a.split()[0] ; aliased = True
            except (KeyError, TypeError): 
                if not self.has_key(cmnd):
                    try:
                        short = getshorttable()
                        if short.has_key(cmnd):
                            cmndlist = short[cmnd]
                            if len(cmndlist) == 1: cmnd = cmndlist[0]
                            else: event.reply("choose one of: ", cmndlist) ; return
                    except Exception, ex: handle_exception()
        logging.info("trying for %s" % cmnd)
        result = None
        try:
            result = self[cmnd]
        except KeyError: pass
        logging.debug("woulddispatch result: %s" % result)
        if result: event.bloh() ; event.makeargs()
        if aliased: event.usercmnd = cmnd
        return result

    def dispatch(self, bot, event, direct=False):
        """ 
            dispatch an event if cmnd exists and user is allowed to exec this 
            command.

        """
        if event.nodispatch: logging.info("nodispatch is set on event") ; return
        if event.groupchat and bot.cfg.fulljids: id = event.auth
        elif event.groupchat: id = event.auth = event.userhost
        else: id = event.auth
        if not event.user: event.bind(bot)
        if not event.user: raise NoSuchUser(event.userhost)
        self.reloadcheck(bot, event)
        c = self.woulddispatch(bot, event)
        if not c: c = self.checkre(bot, event)
        if not c: raise NoSuchCommand(event.usercmnd)
        event.plugorigin = c.modname
        if c.modname in bot.plugs.loading and bot.plugs.loading[c.modname]: event.reply("%s is loading" % c.modname) ; return
        if bot.cmndperms and bot.cmndperms[c.cmnd]: perms = bot.cmndperms[c.cmnd]
        else: perms = c.perms
        if bot.allowall: return self.doit(bot, event, c, direct)
        elif not bot.users or bot.users.allowed(id, perms, bot=bot): return self.doit(bot, event, c, direct)
        elif bot.users.allowed(id, perms, bot=bot): return self.doit(bot, event, c, direct)
        return event

    def doit(self, bot, event, target, direct=False):
        """ do the dispatching. """
        if not target.enable: return
        if target.modname in event.chan.data.denyplug:
             logging.warn("%s is denied in channel %s - %s" % (target.plugname, event.channel, event.userhost))
             return
        id = event.auth or event.userhost
        event.iscommand = True
        event.how = event.how or target.how or "overwrite"
        aliascheck(event)
        display = "%s/%s/%s" % (target.plugname, bot.cfg.name, event.nick or event.channel)
        logging.warning('dispatching %s (%s)' % (event.usercmnd, display))
        try:
            if direct or event.direct: target.func(bot, event)
            elif (target.threaded or event.threaded) and not event.nothreads:
                logging.warning("DIRECT COMMAND THREAD %s (%s)" % (event.usercmnd, display))
                t = start_bot_command(target.func, (bot, event))
                event.threaded = True
                event.thread = t
            else:
                event.dontclose = False
                cmndrunner.put(target.speed or event.speed, display, target.func, bot, event)
        except Exception, ex:
            logging.error('%s - error executing %s' % (whichmodule(), str(target.func)))
            raise
        return event
Example #12
0
class Commands(LazyDict):
    """
        the commands object holds all commands of the bot.
 
    """

    regex = []

    def add(self,
            cmnd,
            func,
            perms,
            threaded=False,
            wait=False,
            orig=None,
            how=None,
            speed=None,
            regex=False,
            needcc=False,
            *args,
            **kwargs):
        """ add a command. """
        modname = calledfrom(sys._getframe())
        try:
            prev = self[cmnd]
        except KeyError:
            prev = None
        target = Command(modname,
                         cmnd,
                         func,
                         perms,
                         threaded,
                         wait,
                         orig,
                         how,
                         speed=speed,
                         needcc=needcc)
        if regex:
            logging.info("regex command detected - %s" % cmnd)
            self.regex.append(target)
            target.regex = cmnd
            return self
        self[cmnd] = target
        try:
            p = cmnd.split('-')[0]
            if not self.pre: self.pre = LazyDict()
            if self.pre.has_key(p):
                if not self.pre[p]: self.pre[p] = []
                if prev in self.pre[p]: self.pre[p].remove(prev)
                if target not in self.pre[p]: self.pre[p].append(target)
            else: self.pre[p] = [
                target,
            ]
        except IndexError:
            pass
        return self

    def checkre(self, bot, event):
        gotcc = event.gotcc()
        for r in self.regex:
            if not r.enable: continue
            if r.needcc and not event.gotcc():
                logging.debug("RE needs cc but not found")
                continue
            s = re.search(r.cmnd, event.txt)
            if s:
                logging.info("regex matches %s" % r.cmnd)
                event.groups = list(s.groups())
                return r

    def wouldmatchre(self, bot, event, cmnd=""):
        groups = self.checkre(bot, event)
        if groups: return groups

    def woulddispatch(self, bot, event):
        """ 
            dispatch an event if cmnd exists and user is allowed to exec this 
            command.

        """
        event.bind(bot)
        aliased = False
        try:
            cmnd = event.stripcc().split()[0]
            if not cmnd: cmnd = event.execstr.split()[0]
            if not cmnd: cmnd = event.txt.split()[0]
        except Exception, ex:
            logging.warn("can't determine command from %s" % event.txt)
            return None
        try:
            a = event.chan.data.aliases[cmnd]
            if a:
                cmnd = a.split()[0]
                aliased = True
        except (KeyError, TypeError):
            try:
                a = getaliases()[cmnd]
                if a:
                    cmnd = a.split()[0]
                    aliased = True
            except (KeyError, TypeError):
                if not self.has_key(cmnd):
                    try:
                        short = getshorttable()
                        if short.has_key(cmnd):
                            cmndlist = short[cmnd]
                            if len(cmndlist) == 1: cmnd = cmndlist[0]
                            else:
                                event.reply("choose one of: ", cmndlist)
                                return
                    except Exception, ex:
                        handle_exception()
Example #13
0
class HubbubWatcher(PlugPersist):

    """ 
        this watcher helps with the handling of incoming POST. also maitains 
        index of feed names.
    """

    def __init__(self, filename, host):
        PlugPersist.__init__(self, filename)
        if not self.data: self.data = LazyDict()
        if not self.data.has_key('names'): self.data['names'] = []
        if not self.data.has_key('urls'): self.data['urls'] = {}
        if not self.data.has_key('feeds'): self.data['feeds'] = {}
        if not self.data.has_key('host'): self.data['host'] = host
        self.feeds = {}

    def add(self, name, url, owner):
        """ add a feed to the database. """
        if not name in self.data['names']:
            self.data['names'].append(name)
            self.data['urls'][url] = name
            self.save()

        item = HubbubItem(name, url, owner)
        if item.data.url != url:
            return False

        item.save()
        self.feeds[name] = item
        return True

    def byname(self, name):
        """ retrieve a feed by it's name. """
        if name in self.feeds: return self.feeds[name]
        item = HubbubItem(name)
        if item.data.url: self.feeds[name] = item ; return item

    def byurl(self, url):
        """ retrieve a feed by it's url. """
        try:
            name = self.data['urls'][url]
            return self.byname(name)
        except KeyError: pass

    def cloneurl(self, url, auth):
        """ add feeds from remote url. """
        data = geturl2(url)
        got = []
        for line in data.split('\n'):
            try: (name, url) = line.split()
            except ValueError:
                logging.debug("hubbub - cloneurl - can't split %s line" % line)
                continue
            if url.endswith('<br>'): url = url[:-4]
            self.add(name, url, auth)
            got.append(name)
        return got

    def watch(self, name):
        """ make feed ready for watching and mark it running. """
        logging.debug('trying %s hubbub feed' % name)
        item = self.byname(name)
        if item == None: raise NoSuchFeed(name)
        if not item.data.running:
            item.data.running = 1
            item.data.stoprunning = 0
            item.save()
            subscribe(item.data['url'], self.data.host)
        logging.info('hubbub - started %s watch' % name)

    def work(self, botname, type, channel, entries, url, *args, **kwargs):
        logging.debug("in work .. %s" % str(entries))
        try:
            item = self.byurl(url)
            name = item.data.name
            try:
                fleet = getfleet()
                bot = fleet.byname(botname)
                if not bot: logging.warn("can't find %s bot in fleet" % botname) ; return
            except NoSuchBotType, ex: logging.warn("hubbub - %s" % str(ex)) ; return
            if not bot: logging.error("hubbub - can't find %s bot in fleet" % type) ; return
            res2 = entries
            if not res2: logging.info("no updates for %s (%s) feed available" % (item.data.name, channel)) ; return
            if item.markup.get(jsonstring([name, channel]), 'reverse-order'): res2 = res2[::-1]
            if item.markup.get(jsonstring([name, channel]), 'all-lines'):
                for i in res2:
                    response = self.makeresponse(name, [i, ], channel)
                    try: bot.say(channel, response)
                    except Exception, ex: handle_exception()
            else:
                sep =  item.markup.get(jsonstring([name, channel]), 'separator')
                if sep: response = self.makeresponse(name, res2, channel, sep=sep)
                else: response = self.makeresponse(name, res2, channel)
                bot.say(channel, response)
        except Exception, ex: handle_exception()

    def incoming(self, data):
        """ process incoming hubbub data. """
        result = feedparser.parse(data)
        url = find_self_url(result.feed.links)
        logging.debug("hubbub - in - %s - %s" % (url, data))
        try:
            item = self.byurl(url)
            if not item: logging.warn("hubbub - can't find feed for %s" % url) ; return
            if not item.data.running: logging.warn("hubbub - %s is not in running mode" % item.data.url) ; return
            if not item.data.url or item.data.url == 'urlnotset':
                item.data.url = url
                item.save()
            if item:
                loopover = item.data.watchchannels
                name = item.data.name
            else: logging.warn("hubbub - can't find %s item" % url) ; return
            logging.warn("loopover in %s peek is: %s" % (name, loopover))
            counter = 1
            for i in loopover:
                if len(i) == 3:
                    try: (botname, type, channel) = i
                    except:
                        try: (botname, type, channel) = loads(i)
                        except:
                            logging.warn('hubbub - %s is not in the format (botname, bottype, channel)' % str(item))
                            continue
                else:
                    logging.warn('hubbub - %s is not in the format (botname, bottype, channel)' % item.data.url)
                    continue
                counter += 1
                start_new_thread(self.work, (botname, type, channel, result.entries, url), {"_countdown": counter})
        except Exception, ex: handle_exception(txt=url)
        return True

    def getall(self):
        """ reconstruct all feeditems into self.feeds. """
        for name in self.data['names']: self.feeds[name] = HubbubItem(name)
        return self.feeds
       
    def ownercheck(self, name, userhost):
        """ check if userhost is the owner of feed. """
        try: return self.byname(name).ownercheck(userhost)
        except (KeyError, AttributeError): pass
        return False

    def makeresult(self, name, target, data):
        """ 
            make a result (txt) of a feed depending on its itemlist (tokens)
            and markup.

        """
        item = self.byname(name)
        res = []
        for j in data:
            tmp = {}
            if not item.itemslists.data[jsonstring([name, target])]: return []
            for i in item.itemslists.data[jsonstring([name, target])]:
                try: tmp[i] = unicode(j[i])
                except KeyError: continue
            res.append(tmp)
        return res


    def makeresponse(self, name, res, channel, sep=" .. "):
        """ loop over result to make a response. """
        item = self.byname(name)
        result = u"[%s] - " % name 
        try: itemslist = item.itemslists.data[jsonstring([name, channel])]
        except KeyError: 
            item = self.byname(name)
            if item == None: return "no %s rss item" % name
            else:
                item.itemslists.data[jsonstring([name, channel])] = ['title', 'link']
                item.itemslists.save()
        for j in res:
            if item.markup.get(jsonstring([name, channel]), 'skipmerge') and 'Merge branch' in j['title']: continue
            resultstr = u""
            for i in item.itemslists.data[jsonstring([name, channel])]:
                try:
                    ii = getattr(j, i)
                    if not ii: continue
                    ii = unicode(ii)
                    if ii.startswith('http://'):
                        if item.markup.get(jsonstring([name, channel]), 'tinyurl'):
                            try:
                                tinyurl = get_tinyurl(ii)
                                logging.debug('rss - tinyurl is: %s' % str(tinyurl))
                                if not tinyurl: resultstr += u"%s - " % ii
                                else: resultstr += u"%s - " % tinyurl[0]
                            except Exception, ex:
                                handle_exception()
                                resultstr += u"%s - " % item
                        else: resultstr += u"%s - " % ii
                    else: resultstr += u"%s - " % ii.strip()
                except (KeyError, AttributeError), ex:
                    logging.info('hubbub - %s - %s' % (name, str(ex)))
                    continue