コード例 #1
0
ファイル: botbase.py プロジェクト: buzzworkers/Jsonbot
class BotBase(LazyDict):

    """ base class for all bots. """

    def __init__(self, cfg=None, usersin=None, plugs=None, botname=None, nick=None, bottype=None, nocbs=None, *args, **kwargs):
        logging.debug("type is %s" % str(type(self)))
        if cfg: self.cfg = cfg ; botname = botname or self.cfg.name
        if not botname: botname = u"default-%s" % str(type(self)).split('.')[-1][:-2]
        if not botname: raise Exception("can't determine  botname")
        self.fleetdir = u'fleet' + os.sep + stripname(botname)
        if not self.cfg: self.cfg = Config(self.fleetdir + os.sep + u'config')
        self.cfg.name = botname or self.cfg.name
        if not self.cfg.name: raise Exception("name is not set in %s config file" % self.fleetdir)
        logging.debug("name is %s" % self.cfg.name)
        LazyDict.__init__(self)
        logging.debug("created bot with config %s" % self.cfg.tojson(full=True))
        self.ecounter = 0
        self.ids = []
        self.aliases = getaliases()
        self.reconnectcount = 0
        self.plugs = coreplugs
        self.gatekeeper = GateKeeper(self.cfg.name)
        self.gatekeeper.allow(self.user or self.jid or self.cfg.server or self.cfg.name)
        self.starttime = time.time()
        self.type = bottype or "base"
        self.status = "init"
        self.networkname = self.cfg.networkname or self.cfg.name or ""
        from jsb.lib.datadir import getdatadir
        datadir = getdatadir()
        self.datadir = datadir + os.sep + self.fleetdir
        self.maincfg = getmainconfig()
        self.owner = self.cfg.owner
        if not self.owner:
            logging.debug(u"owner is not set in %s - using mainconfig" % self.cfg.cfile)
            self.owner = self.maincfg.owner
        self.users = usersin or getusers()
        logging.debug(u"owner is %s" % self.owner)
        self.users.make_owner(self.owner)
        self.outcache = outcache
        self.userhosts = LazyDict()
        self.nicks = LazyDict()
        self.connectok = threading.Event()
        self.reconnectcount = 0
        self.cfg.nick = nick or self.cfg.nick or u'jsb'
        try:
            if not os.isdir(self.datadir): os.mkdir(self.datadir)
        except: pass
        self.setstate()
        self.outputlock = thread.allocate_lock()
        try:
            self.outqueue = Queue.PriorityQueue()
            self.eventqueue = Queue.PriorityQueue()
        except AttributeError:
            self.outqueue = Queue.Queue()
            self.eventqueue = Queue.Queue()
        self.laterqueue = Queue.Queue()
        self.encoding = self.cfg.encoding or "utf-8"
        self.cmndperms = getcmndperms()
        self.outputmorphs = outputmorphs
        self.inputmorphs = inputmorphs
        try:
            if nocbs: self.nocbs = nocbs.split(",")
        except ValueError: logging.error("cannot determine %s nocbs argument" % self.nocbs)
        self.lastiter = 0

    def copyin(self, data):
        self.update(data)

    def _resume(self, data, botname, *args, **kwargs):
        pass

    def _resumedata(self):
        """ return data needed for resuming. """
        try: self.cfg.fd = self.oldsock.fileno()
        except AttributeError: logging.warn("no oldsock found for %s" % self.cfg.name)
        return {self.cfg.name: dict(self.cfg)}

    def benice(self, event=None, sleep=0.005):
        logging.debug("i'm being nice")
        if self.server and self.server.io_loop:
            if event and self.server and event.handler: self.server.io_loop.add_callback(event.handler.async_callback(lambda: time.sleep(sleep)))
            elif self.server: self.server.io_loop.add_callback(lambda: time.sleep(sleep))
        else: time.sleep(sleep)

    def do_enable(self, modname):
        """ enable plugin given its modulename. """
        try: self.cfg.blacklist and self.cfg.blacklist.remove(modname)
        except ValueError: pass           
        if self.cfg.loadlist and modname not in self.cfg.loadlist: self.cfg.loadlist.append(modname)
        self.cfg.save()

    def do_disable(self, modname):
        """ disable plugin given its modulename. """
        if self.cfg.blacklist and modname not in self.cfg.blacklist: self.cfg.blacklist.append(modname)
        if self.cfg.loadlist and modname in self.cfg.loadlist: self.cfg.loadlist.remove(modname)
        self.cfg.save()

    #@locked
    def put(self, event, direct=False):
        """ put an event on the worker queue. """
        if direct: self.doevent(event)
        else:
            if event:
                 logging.debug("putted event on %s" % self.cfg.name)
                 self.ecounter += 1
                 self.input(event.speed, event)
            else: self.input(0, None)
        return event

    def broadcast(self, txt):
        """ broadcast txt to all joined channels. """
        for chan in self.state['joinedchannels']:
            self.say(chan, txt)

    def _eventloop(self):
        """ output loop. """
        logging.debug('%s - starting eventloop' % self.cfg.name)
        self.stopeventloop = 0
        while not self.stopped and not self.stopeventloop:
            try:
                res = self.eventqueue.get()
                if not res: break
                (prio, event) = res
                if not event: break
                logging.debug("%s - eventloop - %s - %s" % (self.cfg.name, event.cbtype, event.userhost)) 
                event.speed = prio
                self.doevent(event)
                self.benice()
            except Queue.Empty: time.sleep(0.01) ; continue
            except Exception, ex: handle_exception() ; logging.warn("error in eventloop: %s" % str(ex))
        logging.debug('%s - stopping eventloop' % self.cfg.name)

    def input(self, prio, event):
        """ put output onto one of the output queues. """
        self.eventqueue.put(("%s-%s" % (prio, self.ecounter), event))

    def _outloop(self):
        """ output loop. """
        logging.debug('%s - starting output loop' % self.cfg.name)
        self.stopoutloop = 0
        while not self.stopped and not self.stopoutloop:
            try:
                self.benice()
                try: r = self.outqueue.get(True, 1.0) 
                except Queue.Empty:
                    try: r = self.laterqueue.get_nowait()
                    except Queue.Empty: continue
                if not r: continue
                (prio, res, kwargs) = r
                logging.debug("%s - OUT - %s - %s" % (self.cfg.name, self.type, str(res))) 
                if not res: continue
                self.out(*res, **kwargs)
            except Exception, ex: handle_exception()
        logging.debug('%s - stopping output loop' % self.cfg.name)

    def _pingloop(self):
        """ output loop. """
        logging.debug('%s - starting ping loop' % self.cfg.name)
        time.sleep(5)
        while not self.stopped:
            try:
                if self.status != "start" and not self.pingcheck(): self.reconnect() ; break
            except Exception, ex: logging.error(str(ex)) ; self.reconnect() ; break
            time.sleep(self.cfg.pingsleep or 60)
        logging.debug('%s - stopping ping loop' % self.cfg.name)

    def putonqueue(self, nr, *args, **kwargs):
        """ put output onto one of the output queues. """
        if nr == -1: self.laterqueue.put((nr, args, kwargs))
        else: self.outqueue.put((nr, args, kwargs))

    def outputsizes(self):
        """ return sizes of output queues. """
        return (self.outqueue.qsize(), self.eventqueue.qsize())

    def setstate(self, state=None):
        """ set state on the bot. """
        self.state = state or Pdod(self.datadir + os.sep + 'state')
        if self.state:
            if not 'joinedchannels' in self.state.data: self.state.data.joinedchannels = []
            if not 'ignore' in self.state.data: self.state.data.ignore = []

    def setusers(self, users=None):
        """ set users on the bot. """
        if users:
            self.users = users
            return
        import jsb.lib.users as u
        if not u.users: u.users_boot()
        self.users = u.users

    def loadplugs(self, packagelist=[]):
        """ load plugins from packagelist. """
        self.plugs.loadall(packagelist)
        return self.plugs

    def joinchannels(self):
        """ join channels. """
        time.sleep(getmainconfig().waitforjoin or 1)
        target = self.cfg.channels
        try:
            for i in self.state['joinedchannels']:
                if i not in target: target.append(i)
        except: pass
        if not target: target = self.state['joinedchannels']
        for i in target:
            try:
                logging.debug("%s - joining %s" % (self.cfg.name, i))
                channel = ChannelBase(i, self.cfg.name)
                if channel: key = channel.data.key
                else: key = None
                if channel.data.nick: self.ids.append("%s/%s" % (i, channel.data.nick))
                start_new_thread(self.join, (i, key))
            except Exception, ex:
                logging.warn('%s - failed to join %s: %s' % (self.cfg.name, i, str(ex)))
                handle_exception()
            time.sleep(3)
コード例 #2
0
class BotBase(LazyDict):
    """ base class for all bots. """
    def __init__(self,
                 cfg=None,
                 usersin=None,
                 plugs=None,
                 botname=None,
                 nick=None,
                 bottype=None,
                 nocbs=None,
                 *args,
                 **kwargs):
        logging.debug("type is %s" % str(type(self)))
        if cfg:
            self.cfg = cfg
            botname = botname or self.cfg.name
        if not botname:
            botname = u"default-%s" % str(type(self)).split('.')[-1][:-2]
        if not botname: raise Exception("can't determine  botname")
        self.fleetdir = u'fleet' + os.sep + stripname(botname)
        if not self.cfg: self.cfg = Config(self.fleetdir + os.sep + u'config')
        self.cfg.name = botname or self.cfg.name
        if not self.cfg.name:
            raise Exception("name is not set in %s config file" %
                            self.fleetdir)
        logging.debug("name is %s" % self.cfg.name)
        LazyDict.__init__(self)
        logging.debug("created bot with config %s" %
                      self.cfg.tojson(full=True))
        self.ecounter = 0
        self.ids = []
        self.aliases = getaliases()
        self.reconnectcount = 0
        self.plugs = coreplugs
        self.gatekeeper = GateKeeper(self.cfg.name)
        self.gatekeeper.allow(self.user or self.jid or self.cfg.server
                              or self.cfg.name)
        self.starttime = time.time()
        self.type = bottype or "base"
        self.status = "init"
        self.networkname = self.cfg.networkname or self.cfg.name or ""
        from jsb.lib.datadir import getdatadir
        datadir = getdatadir()
        self.datadir = datadir + os.sep + self.fleetdir
        self.maincfg = getmainconfig()
        self.owner = self.cfg.owner
        if not self.owner:
            logging.debug(u"owner is not set in %s - using mainconfig" %
                          self.cfg.cfile)
            self.owner = self.maincfg.owner
        self.users = usersin or getusers()
        logging.debug(u"owner is %s" % self.owner)
        self.users.make_owner(self.owner)
        self.outcache = outcache
        self.userhosts = LazyDict()
        self.nicks = LazyDict()
        self.connectok = threading.Event()
        self.reconnectcount = 0
        self.cfg.nick = nick or self.cfg.nick or u'jsb'
        try:
            if not os.isdir(self.datadir): os.mkdir(self.datadir)
        except:
            pass
        self.setstate()
        self.outputlock = thread.allocate_lock()
        try:
            self.outqueue = Queue.PriorityQueue()
            self.eventqueue = Queue.PriorityQueue()
        except AttributeError:
            self.outqueue = Queue.Queue()
            self.eventqueue = Queue.Queue()
        self.laterqueue = Queue.Queue()
        self.encoding = self.cfg.encoding or "utf-8"
        self.cmndperms = getcmndperms()
        self.outputmorphs = outputmorphs
        self.inputmorphs = inputmorphs
        try:
            if nocbs: self.nocbs = nocbs.split(",")
        except ValueError:
            logging.error("cannot determine %s nocbs argument" % self.nocbs)
        self.lastiter = 0

    def copyin(self, data):
        self.update(data)

    def _resume(self, data, botname, *args, **kwargs):
        pass

    def _resumedata(self):
        """ return data needed for resuming. """
        try:
            self.cfg.fd = self.oldsock.fileno()
        except AttributeError:
            logging.warn("no oldsock found for %s" % self.cfg.name)
        return {self.cfg.name: dict(self.cfg)}

    def benice(self, event=None, sleep=0.005):
        logging.debug("i'm being nice")
        if self.server and self.server.io_loop:
            if event and self.server and event.handler:
                self.server.io_loop.add_callback(
                    event.handler.async_callback(lambda: time.sleep(sleep)))
            elif self.server:
                self.server.io_loop.add_callback(lambda: time.sleep(sleep))
        else:
            time.sleep(sleep)

    def do_enable(self, modname):
        """ enable plugin given its modulename. """
        try:
            self.cfg.blacklist and self.cfg.blacklist.remove(modname)
        except ValueError:
            pass
        if self.cfg.loadlist and modname not in self.cfg.loadlist:
            self.cfg.loadlist.append(modname)
        self.cfg.save()

    def do_disable(self, modname):
        """ disable plugin given its modulename. """
        if self.cfg.blacklist and modname not in self.cfg.blacklist:
            self.cfg.blacklist.append(modname)
        if self.cfg.loadlist and modname in self.cfg.loadlist:
            self.cfg.loadlist.remove(modname)
        self.cfg.save()

    #@locked
    def put(self, event, direct=False):
        """ put an event on the worker queue. """
        if direct: self.doevent(event)
        else:
            if event:
                logging.debug("putted event on %s" % self.cfg.name)
                self.ecounter += 1
                self.input(event.speed, event)
            else:
                self.input(0, None)
        return event

    def broadcast(self, txt):
        """ broadcast txt to all joined channels. """
        for chan in self.state['joinedchannels']:
            self.say(chan, txt)

    def _eventloop(self):
        """ output loop. """
        logging.debug('%s - starting eventloop' % self.cfg.name)
        self.stopeventloop = 0
        while not self.stopped and not self.stopeventloop:
            try:
                res = self.eventqueue.get()
                if not res: break
                (prio, event) = res
                if not event: break
                logging.debug("%s - eventloop - %s - %s" %
                              (self.cfg.name, event.cbtype, event.userhost))
                event.speed = prio
                self.doevent(event)
                self.benice()
            except Queue.Empty:
                time.sleep(0.01)
                continue
            except Exception, ex:
                handle_exception()
                logging.warn("error in eventloop: %s" % str(ex))
        logging.debug('%s - stopping eventloop' % self.cfg.name)
コード例 #3
0
ファイル: botbase.py プロジェクト: melmothx/jsonbot
class BotBase(LazyDict):

    """ base class for all bots. """

    def __init__(self, cfg=None, usersin=None, plugs=None, botname=None, nick=None, *args, **kwargs):
        if not botname and cfg and cfg.botname: botname = cfg.botname
        if botname: self.botname = botname
        else: self.botname = u"default-%s" % str(type(self)).split('.')[-1][:-2]
        logging.info("botbase - name is %s" % self.botname)
        self.fleetdir = u'fleet' + os.sep + stripname(self.botname)
        if cfg: self.cfg = Config(self.fleetdir + os.sep + u'config', input=cfg)
        else: self.cfg = Config(self.fleetdir + os.sep + u'config')
        LazyDict.__init__(self)
        self.update(self.cfg)
        self.ignore = []
        self.aliases = getaliases()
        self.curevent = None
        self.inqueue = Queue.Queue()
        self.outqueue = Queue.Queue()
        self.reconnectcount = 0
        self.stopped = False
        self.plugs = coreplugs
        self.gatekeeper = GateKeeper(self.botname)
        self.gatekeeper.allow(self.user or self.jid or self.server or self.botname)
        self.closed = False
        try:
            import waveapi
            self.isgae = True
            logging.debug("botbase - bot is a GAE bot (%s)" % self.botname)
        except ImportError:
            self.isgae = False
            logging.debug("botbase - bot is a shell bot (%s)" % self.botname)
        self.starttime = time.time()
        self.type = "base"
        self.status = "init"
        self.networkname = self.cfg.networkname or self.botname or ""
        if not self.uuid:
            if self.cfg and self.cfg.uuid: self.uuid = self.cfg.uuid
            else:
                self.uuid = self.cfg.uuid = uuid.uuid4()
                self.cfg.save()
        if self.cfg and not self.cfg.followlist: self.cfg.followlist = [] ; self.cfg.save()
        from jsb.lib.datadir import getdatadir
        datadir = getdatadir()
        self.datadir = datadir + os.sep + self.fleetdir
        self.name = self.botname
        self.owner = self.cfg.owner
        if not self.owner:
            logging.debug(u"owner is not set in %s - using mainconfig" % self.cfg.cfile)
            self.owner = Config().owner
        self.setusers(usersin)
        logging.info(u"botbase - owner is %s" % self.owner)
        self.users.make_owner(self.owner)
        self.outcache = outcache
        self.userhosts = {}
        self.connectok = threading.Event()
        if not self.nick: self.nick = (nick or self.cfg.nick or u'jsb')
        try:
            if not os.isdir(self.datadir): os.mkdir(self.datadir)
        except: pass
        self.setstate()
        self.stopreadloop = False
        self.stopoutloop = False
        self.outputlock = thread.allocate_lock()
        self.outqueues = [Queue.Queue() for i in range(10)]
        self.tickqueue = Queue.Queue()
        self.encoding = self.cfg.encoding or "utf-8"
        self.cmndperms = getcmndperms()
        self.outputmorphs = outputmorphs
        self.inputmorphs = inputmorphs
        fleet = getfleet(datadir)
        if not fleet.byname(self.name): fleet.bots.append(self) ; 
        if not self.isgae:
            defaultrunner.start()
            tickloop.start(self)

    def __deepcopy__(self, a):
        """ deepcopy an event. """  
        logging.debug("botbase - cpy - %s" % type(self))
        bot = BotBase() 
        bot.copyin(self)
        return bot

    def copyin(self, data):
        self.update(data)

    def _resumedata(self):
       """ overload this. """ 
       pass

    def enable(self, modname):
        """ enable plugin given its modulename. """
        try: self.cfg.blacklist and self.cfg.blacklist.remove(modname)
        except ValueError: pass           
        if self.cfg.loadlist and modname not in self.cfg.loadlist: self.cfg.loadlist.append(modname)
        self.cfg.save()

    def disable(self, modname):
        """ disable plugin given its modulename. """
        if self.cfg.blacklist and modname not in self.cfg.blacklist: self.cfg.blacklist.append(modname)
        if self.cfg.loadlist and modname in self.cfg.loadlist: self.cfg.loadlist.remove(modname)
        self.cfg.save()

    def put(self, event):
        """ put an event on the worker queue. """
        if self.isgae:
            from jsb.lib.gae.tasks import start_botevent
            start_botevent(self, event, event.speed)
        else: self.inqueue.put_nowait(event)

    def broadcast(self, txt):
        """ broadcast txt to all joined channels. """
        for chan in self.state['joinedchannels']:
            self.say(chan, txt)

    def _eventloop(self):
        """ fetch events from the inqueue and handle them. """
        logging.debug("%s - eventloop started" % self.name)
        while not self.stopped:
            event = self.inqueue.get()
            if not event: break
            self.doevent(event)
        logging.debug("%s - eventloop stopped" % self.name)

    def _getqueue(self):
        """ get one of the outqueues. """
        go = self.tickqueue.get()
        for index in range(len(self.outqueues)):
            if not self.outqueues[index].empty(): return self.outqueues[index]

    def _outloop(self):
        """ output loop. """
        logging.debug('%s - starting output loop' % self.name)
        self.stopoutloop = 0
        while not self.stopped and not self.stopoutloop:
            queue = self._getqueue()
            if queue:
                try:
                    res = queue.get() 
                except Queue.Empty: continue
                if not res: continue
                if not self.stopped and not self.stopoutloop:
                    logging.debug("%s - OUT - %s - %s" % (self.name, self.type, str(res))) 
                    self.out(*res)
            time.sleep(0.1)
        logging.debug('%s - stopping output loop' % self.name)

    def putonqueue(self, nr, *args):
        """ put output onto one of the output queues. """
        self.outqueues[10-nr].put_nowait(args)
        self.tickqueue.put_nowait('go')

    def outputsizes(self):
        """ return sizes of output queues. """
        result = []  
        for q in self.outqueues:
            result.append(q.qsize())
        return result

    def setstate(self, state=None):
        """ set state on the bot. """
        self.state = state or Pdod(self.datadir + os.sep + 'state')
        if self.state and not 'joinedchannels' in self.state.data: self.state.data.joinedchannels = []

    def setusers(self, users=None):
        """ set users on the bot. """
        if users:
            self.users = users
            return
        import jsb.lib.users as u
        if not u.users: u.users_boot()
        self.users = u.users

    def loadplugs(self, packagelist=[]):
        """ load plugins from packagelist. """
        self.plugs.loadall(packagelist)
        return self.plugs

    def joinchannels(self):
        """ join channels. """
        time.sleep(Config().waitforjoin or 5)
        for i in self.state['joinedchannels']:
            try:
                logging.debug("%s - joining %s" % (self.name, i))
                channel = ChannelBase(i)
                if channel: key = channel.getpass()
                else: key=None
                start_new_thread(self.join, (i, key))
                time.sleep(1)
            except Exception, ex:
                logging.warn('%s - failed to join %s: %s' % (self.name, i, str(ex)))
                handle_exception()
コード例 #4
0
ファイル: botbase.py プロジェクト: code2u/jsb
class BotBase(LazyDict):

    """ base class for all bots. """

    def __init__(self, cfg=None, usersin=None, plugs=None, botname=None, nick=None, *args, **kwargs):
        logging.debug("type is %s" % str(type(self)))
        if cfg: cfg = LazyDict(cfg)
        if cfg and not botname: botname = cfg.name
        if not botname: botname = u"default-%s" % str(type(self)).split('.')[-1][:-2]
        if not botname: raise Exception("can't determine type")
        self.fleetdir = u'fleet' + os.sep + stripname(botname)
        self.cfg = Config(self.fleetdir + os.sep + u'config')
        if cfg: self.cfg.merge(cfg)
        self.cfg.name = botname
        if not self.cfg.name: raise Exception(" name is not set in %s config file" % self.fleetdir)
        logging.debug("name is %s" % self.cfg.name)
        LazyDict.__init__(self)
        self.ignore = []
        self.ids = []
        self.started = False
        self.aliases = getaliases()
        self.curevent = None
        self.inqueue = Queue.Queue()
        self.outqueue = Queue.Queue()
        self.reconnectcount = 0
        self.stopped = False
        self.plugs = coreplugs
        self.gatekeeper = GateKeeper(self.cfg.name)
        self.gatekeeper.allow(self.user or self.jid or self.cfg.server or self.cfg.name)
        self.closed = False
        try:
            import waveapi
            self.isgae = True
            logging.debug("bot is a GAE bot (%s)" % self.cfg.name)
        except ImportError:
            self.isgae = False
            logging.debug("bot is a shell bot (%s)" % self.cfg.name)
        self.starttime = time.time()
        self.type = "base"
        self.status = "init"
        self.networkname = self.cfg.networkname or self.cfg.name or ""
        if not self.uuid:
            if self.cfg and self.cfg.uuid: self.uuid = self.cfg.uuid
            else:
                self.uuid = self.cfg.uuid = uuid.uuid4()
                self.cfg.save()
        if self.cfg and not self.cfg.followlist: self.cfg.followlist = [] ; self.cfg.save()
        from jsb.lib.datadir import getdatadir
        datadir = getdatadir()
        self.datadir = datadir + os.sep + self.fleetdir
        self.owner = self.cfg.owner
        if not self.owner:
            logging.debug(u"owner is not set in %s - using mainconfig" % self.cfg.cfile)
            self.owner = getmainconfig().owner
        self.setusers(usersin)
        logging.debug(u"owner is %s" % self.owner)
        self.users.make_owner(self.owner)
        self.outcache = outcache
        self.userhosts = LazyDict()
        self.connectok = threading.Event()
        self.reconnectcount = 0
        self.cfg.nick = nick or self.cfg.nick or u'jsb'
        try:
            if not os.isdir(self.datadir): os.mkdir(self.datadir)
        except: pass
        self.setstate()
        self.stopreadloop = False
        self.stopoutloop = False
        self.outputlock = thread.allocate_lock()
        self.outqueues = [Queue.Queue() for i in range(10)]
        self.tickqueue = Queue.Queue()
        self.encoding = self.cfg.encoding or "utf-8"
        self.cmndperms = getcmndperms()
        self.outputmorphs = outputmorphs
        self.inputmorphs = inputmorphs
        if not self.isgae:
            defaultrunner.start()
            callbackrunner.start()
            waitrunner.start()
            tickloop.start(self)

    def __setattr__(self, a ,b):
        if self.cfg and a == "cfg": raise Exception("attempt to overwrite config")
        else: self[a] = b

    def __deepcopy__(self, a):
        """ deepcopy an event. """  
        logging.debug("cpy - %s" % type(self))
        bot = bot_factory.create(self.type, self.cfg)
        return bot

    def copyin(self, data):
        self.update(data)

    def _resume(self, data, botname, *args, **kwargs):
        pass

    def _resumedata(self):
        """ return data needed for resuming. """
        data = self.cfg
        try: data.fd = self.sock.fileno()
        except: pass
        return {self.cfg.name: data}

    def benice(self, event=None):
        if self.server and self.server.io_loop:
            logging.debug("i'm being nice")
            if event and self.server and event.handler: self.server.io_loop.add_callback(event.handler.async_callback(lambda: time.sleep(0.001)))
            elif self.server: self.server.io_loop.add_callback(lambda: time.sleep(0.001))
        time.sleep(0.001)

    def enable(self, modname):
        """ enable plugin given its modulename. """
        try: self.cfg.blacklist and self.cfg.blacklist.remove(modname)
        except ValueError: pass           
        if self.cfg.loadlist and modname not in self.cfg.loadlist: self.cfg.loadlist.append(modname)
        self.cfg.save()

    def disable(self, modname):
        """ disable plugin given its modulename. """
        if self.cfg.blacklist and modname not in self.cfg.blacklist: self.cfg.blacklist.append(modname)
        if self.cfg.loadlist and modname in self.cfg.loadlist: self.cfg.loadlist.remove(modname)
        self.cfg.save()

    def put(self, event):
        """ put an event on the worker queue. """
        if self.isgae:
            from jsb.drivers.gae.tasks import start_botevent
            start_botevent(self, event, event.speed)
        else: logging.info("%s - putted event %s" % (self.cfg.name, str(event))) ; self.inqueue.put_nowait(event)

    def broadcast(self, txt):
        """ broadcast txt to all joined channels. """
        for chan in self.state['joinedchannels']:
            self.say(chan, txt)

    def _eventloop(self):
        """ fetch events from the inqueue and handle them. """
        logging.warn("%s - eventloop started" % self.cfg.name)
        while not self.stopped:
            event = self.inqueue.get()
            if not event:
                if self.stopped: break
                else: continue
            self.doevent(event)
            self.benice(event)
        logging.warn("%s - eventloop stopped" % self.cfg.name)
        self.started = False

    def _getqueue(self):
        """ get one of the outqueues. """
        go = self.tickqueue.get()
        for index in range(len(self.outqueues)):
            if not self.outqueues[index].empty(): return self.outqueues[index]

    def _outloop(self):
        """ output loop. """
        logging.warn('%s - starting output loop' % self.cfg.name)
        self.stopoutloop = 0
        while not self.stopped and not self.stopoutloop:
            queue = self._getqueue()
            if queue:
                try:
                    res = queue.get_nowait() 
                except Queue.Empty: continue
                if not res: break
                if not self.stopped and not self.stopoutloop:
                    logging.debug("%s - OUT - %s - %s" % (self.cfg.name, self.type, str(res))) 
                    try: self.out(*res)
                    except Exception, ex: logging.warn("error in outloop: %s" % str(ex))
                else: break
        logging.warn('%s - stopping output loop' % self.cfg.name)

    def putonqueue(self, nr, *args):
        """ put output onto one of the output queues. """
        self.outqueues[10-nr].put_nowait(args)
        self.tickqueue.put_nowait('go')

    def outputsizes(self):
        """ return sizes of output queues. """
        result = []  
        for q in self.outqueues:
            result.append(q.qsize())
        return result

    def setstate(self, state=None):
        """ set state on the bot. """
        self.state = state or Pdod(self.datadir + os.sep + 'state')
        if self.state and not 'joinedchannels' in self.state.data: self.state.data.joinedchannels = []

    def setusers(self, users=None):
        """ set users on the bot. """
        if users:
            self.users = users
            return
        import jsb.lib.users as u
        if not u.users: u.users_boot()
        self.users = u.users

    def loadplugs(self, packagelist=[]):
        """ load plugins from packagelist. """
        self.plugs.loadall(packagelist)
        return self.plugs

    def joinchannels(self):
        """ join channels. """
        time.sleep(getmainconfig().waitforjoin or 1)
        target = self.cfg.channels
        try:
            for i in self.state['joinedchannels']:
                if i not in target: target.append(i)
        except: pass
        if not target: target = self.state['joinedchannels']
        for i in target:
            time.sleep(5)
            try:
                logging.debug("%s - joining %s" % (self.cfg.name, i))
                channel = ChannelBase(i, self.cfg.name)
                if channel: key = channel.data.key
                else: key = None
                if channel.data.nick: self.ids.append("%s/%s" % (i, channel.data.nick))
                start_new_thread(self.join, (i, key))
            except Exception, ex:
                logging.warn('%s - failed to join %s: %s' % (self.cfg.name, i, str(ex)))
                handle_exception()
コード例 #5
0
class BotBase(LazyDict):
    """ base class for all bots. """
    def __init__(self,
                 cfg=None,
                 usersin=None,
                 plugs=None,
                 botname=None,
                 nick=None,
                 *args,
                 **kwargs):
        if not botname and cfg and cfg.botname: botname = cfg.botname
        if botname: self.botname = botname
        else:
            self.botname = u"default-%s" % str(type(self)).split('.')[-1][:-2]
        logging.info("botbase - name is %s" % self.botname)
        self.fleetdir = u'fleet' + os.sep + stripname(self.botname)
        if cfg:
            self.cfg = Config(self.fleetdir + os.sep + u'config', input=cfg)
        else:
            self.cfg = Config(self.fleetdir + os.sep + u'config')
        LazyDict.__init__(self)
        self.update(self.cfg)
        self.ignore = []
        self.aliases = getaliases()
        self.curevent = None
        self.inqueue = Queue.Queue()
        self.outqueue = Queue.Queue()
        self.reconnectcount = 0
        self.stopped = False
        self.plugs = coreplugs
        self.gatekeeper = GateKeeper(self.botname)
        self.gatekeeper.allow(self.user or self.jid or self.server
                              or self.botname)
        self.closed = False
        try:
            import waveapi
            self.isgae = True
            logging.debug("botbase - bot is a GAE bot (%s)" % self.botname)
        except ImportError:
            self.isgae = False
            logging.debug("botbase - bot is a shell bot (%s)" % self.botname)
        self.starttime = time.time()
        self.type = "base"
        self.status = "init"
        self.networkname = self.cfg.networkname or self.botname or ""
        if not self.uuid:
            if self.cfg and self.cfg.uuid: self.uuid = self.cfg.uuid
            else:
                self.uuid = self.cfg.uuid = uuid.uuid4()
                self.cfg.save()
        if self.cfg and not self.cfg.followlist:
            self.cfg.followlist = []
            self.cfg.save()
        from jsb.lib.datadir import getdatadir
        datadir = getdatadir()
        self.datadir = datadir + os.sep + self.fleetdir
        self.name = self.botname
        self.owner = self.cfg.owner
        if not self.owner:
            logging.debug(u"owner is not set in %s - using mainconfig" %
                          self.cfg.cfile)
            self.owner = Config().owner
        self.setusers(usersin)
        logging.info(u"botbase - owner is %s" % self.owner)
        self.users.make_owner(self.owner)
        self.outcache = outcache
        self.userhosts = {}
        self.connectok = threading.Event()
        if not self.nick: self.nick = (nick or self.cfg.nick or u'jsb')
        try:
            if not os.isdir(self.datadir): os.mkdir(self.datadir)
        except:
            pass
        self.setstate()
        self.stopreadloop = False
        self.stopoutloop = False
        self.outputlock = thread.allocate_lock()
        self.outqueues = [Queue.Queue() for i in range(10)]
        self.tickqueue = Queue.Queue()
        self.encoding = self.cfg.encoding or "utf-8"
        self.cmndperms = getcmndperms()
        self.outputmorphs = outputmorphs
        self.inputmorphs = inputmorphs
        fleet = getfleet(datadir)
        if not fleet.byname(self.name): fleet.bots.append(self)
        if not self.isgae:
            defaultrunner.start()
            tickloop.start(self)

    def __deepcopy__(self, a):
        """ deepcopy an event. """
        logging.debug("botbase - cpy - %s" % type(self))
        bot = BotBase()
        bot.copyin(self)
        return bot

    def copyin(self, data):
        self.update(data)

    def _resumedata(self):
        """ overload this. """
        pass

    def enable(self, modname):
        """ enable plugin given its modulename. """
        try:
            self.cfg.blacklist and self.cfg.blacklist.remove(modname)
        except ValueError:
            pass
        if self.cfg.loadlist and modname not in self.cfg.loadlist:
            self.cfg.loadlist.append(modname)
        self.cfg.save()

    def disable(self, modname):
        """ disable plugin given its modulename. """
        if self.cfg.blacklist and modname not in self.cfg.blacklist:
            self.cfg.blacklist.append(modname)
        if self.cfg.loadlist and modname in self.cfg.loadlist:
            self.cfg.loadlist.remove(modname)
        self.cfg.save()

    def put(self, event):
        """ put an event on the worker queue. """
        if self.isgae:
            from jsb.lib.gae.tasks import start_botevent
            start_botevent(self, event, event.speed)
        else:
            self.inqueue.put_nowait(event)

    def broadcast(self, txt):
        """ broadcast txt to all joined channels. """
        for chan in self.state['joinedchannels']:
            self.say(chan, txt)

    def _eventloop(self):
        """ fetch events from the inqueue and handle them. """
        logging.debug("%s - eventloop started" % self.name)
        while not self.stopped:
            event = self.inqueue.get()
            if not event: break
            self.doevent(event)
        logging.debug("%s - eventloop stopped" % self.name)

    def _getqueue(self):
        """ get one of the outqueues. """
        go = self.tickqueue.get()
        for index in range(len(self.outqueues)):
            if not self.outqueues[index].empty(): return self.outqueues[index]

    def _outloop(self):
        """ output loop. """
        logging.debug('%s - starting output loop' % self.name)
        self.stopoutloop = 0
        while not self.stopped and not self.stopoutloop:
            queue = self._getqueue()
            if queue:
                try:
                    res = queue.get()
                except Queue.Empty:
                    continue
                if not res: continue
                if not self.stopped and not self.stopoutloop:
                    logging.debug("%s - OUT - %s - %s" %
                                  (self.name, self.type, str(res)))
                    self.out(*res)
            time.sleep(0.1)
        logging.debug('%s - stopping output loop' % self.name)

    def putonqueue(self, nr, *args):
        """ put output onto one of the output queues. """
        self.outqueues[10 - nr].put_nowait(args)
        self.tickqueue.put_nowait('go')

    def outputsizes(self):
        """ return sizes of output queues. """
        result = []
        for q in self.outqueues:
            result.append(q.qsize())
        return result

    def setstate(self, state=None):
        """ set state on the bot. """
        self.state = state or Pdod(self.datadir + os.sep + 'state')
        if self.state and not 'joinedchannels' in self.state.data:
            self.state.data.joinedchannels = []

    def setusers(self, users=None):
        """ set users on the bot. """
        if users:
            self.users = users
            return
        import jsb.lib.users as u
        if not u.users: u.users_boot()
        self.users = u.users

    def loadplugs(self, packagelist=[]):
        """ load plugins from packagelist. """
        self.plugs.loadall(packagelist)
        return self.plugs

    def joinchannels(self):
        """ join channels. """
        time.sleep(Config().waitforjoin or 5)
        for i in self.state['joinedchannels']:
            try:
                logging.debug("%s - joining %s" % (self.name, i))
                channel = ChannelBase(i)
                if channel: key = channel.getpass()
                else: key = None
                start_new_thread(self.join, (i, key))
                time.sleep(1)
            except Exception, ex:
                logging.warn('%s - failed to join %s: %s' %
                             (self.name, i, str(ex)))
                handle_exception()