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)
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)
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()
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()
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()