def handle(self, descr, func, bot, ievent, *args, **kwargs): """ schedule a job. """ self.working = True try: name = getname(str(func)) stats.up("runners", name) stats.up("runners", bot.name) rlog( 4, "runner", "%s (%s) running %s: %s at speed %s" % (ievent.nick, ievent.userhost, descr, str(func), ievent.speed), ) self.starttime = time.time() func(bot, ievent, *args, **kwargs) for queue in ievent.queues: queue.put_nowait(None) self.finished = time.time() self.elapsed = self.finished - self.starttime if self.elapsed > 3: rlog( 10, "runner", "ALERT %s %s job taking too long: %s \ seconds" % (descr, str(func), self.elapsed), ) except Exception, ex: handle_exception(ievent)
def callback(self, cb, bot, ievent): """ callback cb with bot and ievent as arguments """ try: # see if the callback pre requirement succeeds if cb.prereq: rlog(-10, "callback", "excecuting in loop %s" % str(cb.prereq)) if not cb.prereq(bot, ievent): return # check if callback function is there if not cb.func: return # log and stats rlog(0, "callback", "excecuting callback %s" % str(cb.func)) stats.up("callbacks", getname(cb.func)) stats.up("callbacks", cb.plugname) # launcn the callback .. either threaded or dispatched at runners if cb.threaded: start_new_thread(cb.func, (bot, ievent), cb.kwargs) else: cbrunners[10 - cb.speed].put("cb-%s" % cb.plugname, cb.func, bot, ievent, **cb.kwargs) except Exception, ex: handle_exception()
def handle(self, *args, **kwargs): """ fire monitor callbacks. """ for i in self.outs: # check if precondition is met try: if i[2]: stats.up('monitors', thr.getname(str(i[2]))) rlog(-10, 'jabbermonitor', 'checking inloop %s' % str(i[2])) doit = i[2](*args, **kwargs) else: doit = 1 except Exception, ex: handle_exception() doit = 0 if doit: # run monitor callback in its own thread rlog(0, 'jabbermonitor', 'excecuting jabbermonitor callback \ %s' % i[0]) stats.up('monitors', thr.getname(str(i[1]))) if not i[3]: cbrunners[5].put("monitor-%s" % i[0], i[1], *args) else: thr.start_new_thread(i[1], args, kwargs)
def overload(self): """ overload functions in self.overloads. """ for funcname, perms in self.overloads.iteritems(): if self.permoverload(funcname, perms): rlog(10, 'plugins', '%s permission set to %s' % (funcname, \ perms))
def _doresume(self, data, reto=None): """ resume a party line connection after reboot. """ for i in data['partyline']: bot = fleet.byname(i['botname']) sock = socket.fromfd(i['fileno'], socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(1) nick = i['nick'] userhost = i['userhost'] channel = i['channel'] if not bot: rlog(10, 'partyline', "can't find %s bot in fleet" % i['botname']) continue self.socks.append({ 'bot': bot, 'sock': sock, 'nick': nick, 'userhost': userhost, 'channel': channel, 'silent': i['silent'] }) bot._dccresume(sock, nick, userhost, channel) if reto: self.say_nick(nick, 'rebooting done')
def reload(self, mod, name, enable=True): """ reload plugin. """ # create the plugin data dir if not os.path.isdir(datadir + os.sep + 'plugs'): os.mkdir(datadir + os.sep + 'plugs') if not os.path.isdir(datadir + os.sep + 'plugs' + os.sep + name): os.mkdir(datadir + os.sep + 'plugs' + os.sep + name) reloaded = [] modname = mod + '.' + name self.unload(name) if enable: self.enable(name) # force an import of the plugin plug = self.plugs[name] = force_import(modname) # recurse the reload function if plugin is a dir try: for p in plug.__plugs__: reloaded.extend(self.reload(modname, p)) except (KeyError, AttributeError): pass # call plugins init() function try: rlog(0, 'plugins', 'calling %s init()' % modname) plug.init() self.initcalled.append(modname) except (AttributeError, KeyError): pass except Exception, ex: rlog(10, 'plugins', '%s module init failed' % name) raise
def add(self, what, func, prereq=None, kwargs=None, threaded=False, nr=False, speed=5): """ add a callback. """ what = what.upper() # get the plugin this callback was registered from plugname = calledfrom(sys._getframe(1)) # check if plugname is in loadlist .. if not don't add callback if config['loadlist'] and not plugname in config['loadlist']: return # see if kwargs is set if not init to {} if not kwargs: kwargs = {} # add callback to the dict of lists if nr != False: self.cbs.insert( nr, what, Callback(func, prereq, plugname, kwargs, threaded, speed)) else: self.cbs.add( what, Callback(func, prereq, plugname, kwargs, threaded, speed)) rlog(-3, 'callbacks', 'added %s (%s)' % (what, plugname))
def callback(self, cb, bot, ievent): """ callback cb with bot and ievent as arguments """ try: # see if the callback pre requirement succeeds if cb.prereq: rlog(-10, 'callback', 'excecuting in loop %s' % str(cb.prereq)) if not cb.prereq(bot, ievent): return # check if callback function is there if not cb.func: return # log and stats rlog(0, 'callback', 'excecuting callback %s' % str(cb.func)) stats.up('callbacks', getname(cb.func)) stats.up('callbacks', cb.plugname) # launcn the callback .. either threaded or dispatched at runners if cb.threaded: start_new_thread(cb.func, (bot, ievent), cb.kwargs) else: cbrunners[10 - cb.speed].put("cb-%s" % cb.plugname, cb.func, bot, ievent, **cb.kwargs) except Exception, ex: handle_exception()
def dotimeout(self, timeout, ticket): """ start timeout thread for wait with ticket nr. """ rlog(1, 'wait', 'starting timeouthread for %s' % str(ticket)) time.sleep(float(timeout)) self.delete(ticket)
def showregistered(self): """ show registered plugins. """ self.avail.sort() rlog(10, 'plugins', 'registered %s' % ' .. '.join(self.avail)) self.overload()
def delete(self, ticket): """ delete wait item with ticket nr. """ for itemnr in range(len(self.waitlist) - 1, -1, -1): if self.waitlist[itemnr][3] == ticket: self.waitlist[itemnr][2].put_nowait(None) del self.waitlist[itemnr] rlog(1, 'wait', 'deleted ' + str(ticket)) return 1
def register(self, catch, queue, timeout=15): """ register wait for privmsg. """ rlog(1, 'jabberwait', 'registering for %s' % catch) self.ticket += 1 self.waitlist.append((catch, queue, self.ticket)) if timeout: thr.start_new_thread(self.dotimeout, (timeout, self.ticket)) return self.ticket
def handleloop(self): """ thread that polls the queues for items to dispatch. """ rlog(0, 'eventhandler', 'starting handle thread') while not self.stopped: self.go.get() self.handle_one() rlog(0, 'eventhandler', 'stopping %s' % str(self))
def register(self, cmnd, catch, queue, timeout=15): """ register wait for cmnd. """ rlog(1, 'wait', 'registering for cmnd ' + cmnd) self.ticket += 1 self.waitlist.insert(0, (cmnd, catch, queue, self.ticket)) if timeout: # start timeout thread thr.start_new_thread(self.dotimeout, (timeout, self.ticket)) return self.ticket
def add_party(self, bot, sock, nick, userhost, channel): ''' add a socket with nick to the list. ''' for i in self.socks: if i['sock'] == sock: return self.socks.append({'bot': bot, 'sock': sock, 'nick': nick, \ 'userhost': userhost, 'channel': channel, 'silent': False}) rlog(1, 'partyline', 'added user %s on the partyline' % nick)
def add(self, name, callback, pre, threaded=False): """ add a monitoring callback. """ name = calledfrom(sys._getframe(0)) if config['loadlist'] and name not in config['loadlist']: return self.outs.append((name, callback, pre, threaded)) rlog(0, self.name, 'added %s (%s)' % (name, str(callback)))
def shoot(): """ knock down all jobs belonging to group. """ deljobs = [job for job in self.jobs if job.member(group)] for job in deljobs: self.jobs.remove(job) rlog(5, 'periodical', 'killed %d jobs for %s' % (len(deljobs), \ group)) del deljobs
def delete(self, ticket): """ delete wait item with ticket nr. """ for itemnr in range(len(self.waitlist)-1, -1, -1): if self.waitlist[itemnr][3] == ticket: self.waitlist[itemnr][2].put_nowait(None) del self.waitlist[itemnr] rlog(1, 'wait', 'deleted ' + str(ticket)) return 1
def unloadnosave(self, plugname): """ unload plugin without saving. """ # call shutdown function try: self.plugs[plugname].shutdown() rlog(10, 'plugins', '%s shutdown called' % plugname) except (AttributeError, KeyError): pass except Exception, ex: handle_exception()
def check(self, ievent): """ check if there are wait items for ievent. """ for item in self.waitlist: if item[0] == 'PRIVMSG': if ievent.userhost == item[1]: ievent.ticket = item[3] item[2].put_nowait(ievent) self.delete(ievent.ticket) rlog(1, 'privwait', 'got response for %s' % item[0]) ievent.isresponse = True
def check(self, msg): """ check if <msg> is waited for. """ for teller in range(len(self.waitlist) - 1, -1, -1): i = self.waitlist[teller] if i[0] == msg.userhost: msg.ticket = i[2] i[1].put_nowait(msg) self.delete(msg.ticket) rlog(10, 'jabberwait', 'got response for %s' % i[0]) msg.isresponse = 1
def check(self): """ run check to see if job needs to be scheduled. """ if self.next <= time.time(): rlog(-15, 'periodical', 'running %s' % str(self.func)) self.func(*self.args, **self.kw) self.next += self.delta self.counts += 1 if self.repeat > 0 and self.counts >= self.repeat: return False # remove this job return True
def check(self, msg): """ check if <msg> is waited for. """ for teller in range(len(self.waitlist)-1, -1, -1): i = self.waitlist[teller] if i[0] == msg.userhost: msg.ticket = i[2] i[1].put_nowait(msg) self.delete(msg.ticket) rlog(10, 'jabberwait', 'got response for %s' % i[0]) msg.isresponse = 1
def delete(self, ticket): """ delete wait item with ticket nr. """ for itemnr in range(len(self.waitlist) - 1, -1, -1): item = self.waitlist[itemnr] if item[2] == ticket: item[1].put_nowait(None) try: del self.waitlist[itemnr] rlog(1, 'jabberwait', 'deleted ' + str(ticket)) except IndexError: pass return 1
def del_party(self, nick): ''' remove a socket with nick from the list. ''' nick = nick.lower() self.lock.acquire() try: for socknr in range(len(self.socks) - 1, -1, -1): if self.socks[socknr]['nick'].lower() == nick: del self.socks[socknr] rlog(1, 'partyline', 'removed user %s from the partyline' % nick) finally: self.lock.release()
def __init__(self, interval, repeat, func, *args, **kw): Job.__init__(self) self.func = func self.args = args self.kw = kw self.repeat = int(repeat) self.counts = 0 self.interval = float(interval) self.description = "" self.next = time.time() + self.interval self.group = None rlog(-10, 'periodical', 'scheduled next run of %s in %d seconds' % \ (str(self.func), self.interval))
def del_party(self, nick): ''' remove a socket with nick from the list. ''' nick = nick.lower() self.lock.acquire() try: for socknr in range(len(self.socks)-1, -1, -1): if self.socks[socknr]['nick'].lower() == nick: del self.socks[socknr] rlog(1, 'partyline', 'removed user %s from the partyline' % nick) finally: self.lock.release()
def delete(self, ticket): """ delete wait item with ticket nr. """ for itemnr in range(len(self.waitlist)-1, -1, -1): item = self.waitlist[itemnr] if item[2] == ticket: item[1].put_nowait(None) try: del self.waitlist[itemnr] rlog(1, 'jabberwait', 'deleted ' + str(ticket)) except IndexError: pass return 1
def daily(function): """ day decorator. """ rlog(-15, 'periodical', '@daily(%s)' % str(function)) daily.func_dict = function.func_dict group = calledfrom(sys._getframe()) def wrapper(*args, **kw): job = JobInterval(86400, 0, function, *args, **kw) job.group = group periodical.jobs.append(job) rlog(-15, 'periodical', 'new interval job %d running daily' % job.id()) return wrapper
def check(self, msg): """ check if <msg> is waited for. """ if not msg.getType() == 'error': return errorcode = msg.getErrorCode() for teller in range(len(self.waitlist) - 1, -1, -1): i = self.waitlist[teller] if i[0] == 'ALL' or i[0] == errorcode: msg.error = msg.getError() msg.ticket = i[2] i[1].put_nowait(msg) self.delete(msg.ticket) rlog(10, 'jabbererrorwait', 'got error response for %s' % i[0])
def unload(self, plugname): """ unload regexs commands. """ got = 0 try: for i in range(len(self.relist)-1, -1 , -1): if self.relist[i].plugname == plugname: rlog(1, 'redispatcher', 'unloading %s (%s)' % \ (self.relist[i].regex, plugname)) del self.relist[i] got = 1 finally: pass if got: return 1
def add(self, cmnd, func, perm, speed=5, threaded=False, allowqueue=True, options={}): """ add a command. """ # plugin where the command is added plugname = calledfrom(sys._getframe(1)) # check if plugin is in loadlist .. if not dont register command. if config['loadlist'] and plugname not in config['loadlist']: return rlog(-3, 'commands', 'added %s (%s) ' % (cmnd, plugname)) # add command self[cmnd.lower()] = Command(func, perm, plugname, speed, threaded, allowqueue, options) self[cmnd.lower()].name = cmnd.lower()
def check(self, ievent): """ check if there are wait items for ievent .. check if 'catch' matches on ievent.postfix if so put ievent on queue. """ cmnd = ievent.cmnd for item in self.waitlist: if item[0] == cmnd: if cmnd == "JOIN": catch = ievent.txt + ievent.postfix else: catch = ievent.nick + ievent.postfix if item[1] in catch: ievent.ticket = item[3] item[2].put_nowait(ievent) self.delete(ievent.ticket) rlog(1, 'wait', 'got response for %s' % item[0]) ievent.isresponse = True
def check(self, msg): """ check if <msg> is waited for. """ if not msg.getType() == 'error': return errorcode = msg.getErrorCode() for teller in range(len(self.waitlist)-1, -1, -1): i = self.waitlist[teller] if i[0] == 'ALL' or i[0] == errorcode: msg.error = msg.getError() msg.ticket = i[2] i[1].put_nowait(msg) self.delete(msg.ticket) rlog(10,'jabbererrorwait','got error response for %s' % i[0])
def handle(self, bot, txt): """ fire outmonitor callbacks. """ ievent = Ircevent().parse(bot, txt) if not ievent: rlog(10, 'monitor', "can't make ircevent: %s" % txt) return ievent.nick = bot.nick try: ievent.userhost = bot.userhosts[bot.nick] except KeyError: ievent.userhost = "bot@bot" Monitor.handle(self, bot, ievent)
def unload(self, plugname): """ unload all callbacks registered in a plugin. """ unload = [] # look for all callbacks in a plugin for name, cblist in self.cbs.iteritems(): index = 0 for item in cblist: if item.plugname == plugname: unload.append((name, index)) index += 1 # delete callbacks for callback in unload[::-1]: self.cbs.delete(callback[0], callback[1]) rlog(1, 'callbacks', 'unloaded %s' % callback[0])
def add(self, index, regex, func, perm, speed=5, threaded=True, allowqueue=True, options={}): """ add a command. """ try: # get plugin name from where callback is added plugname = calledfrom(sys._getframe()) if config['loadlist'] and plugname not in config['loadlist']: return # add Recallback self.relist.append(Recallback(index, regex, func, perm, plugname, \ speed, threaded, allowqueue, options)) # sort of index number self.relist.sort(lambda a, b: cmp(a.index, b.index)) rlog(0, 'redispatcher', 'added %s (%s) ' % (regex, plugname)) finally: pass
def check(self): """ run check to see if job needs to be scheduled. """ if self.next <= time.time(): rlog(-15, 'periodical', 'running %s' % (str(self.func))) self.next = time.time() + self.interval # try the callback try: self.func(*self.args, **self.kw) except Exception, ex: handle_exception() self.counts += 1 if self.repeat > 0 and self.counts >= self.repeat: return False # remove this job
def unload(self, plugname): """ unload all callbacks registered in a plugin. """ unload = [] # look for all callbacks in a plugin for name, cblist in self.cbs.iteritems(): index = 0 for item in cblist: if item.plugname == plugname: unload.append((name, index)) index += 1 # delete callbacks for callback in unload[::-1]: self.cbs.delete(callback[0], callback[1]) rlog(1, "callbacks", "unloaded %s" % callback[0])
def permoverload(self, funcname, perms): """ overload permission of function with funcname. """ perms = [perm.upper() for perm in perms] got = 0 for nr in range(len(self.relist)): try: if self.relist[nr].func.func_name == funcname: self.relist[nr].perms = list(perms) rlog(0, 'redispatcher', '%s function overloaded with %s' \ % (funcname, perms)) got = 1 except AttributeError: rlog(10, 'redispatcher', 'permoverload: no %s function' % \ funcname) if got: return 1
def handle(self, descr, func, *args, **kwargs): """ schedule a job. """ self.working = True try: name = getname(str(func)) stats.up('runners', name) rlog(4, 'runner', 'running %s: %s' % (descr, name)) self.starttime = time.time() func(*args, **kwargs) self.finished = time.time() self.elapsed = self.finished - self.starttime if self.elapsed > 3: rlog( 10, 'runner', 'ALERT %s %s job taking too long: %s \ seconds' % (descr, str(func), self.elapsed)) except Exception, ex: handle_exception()
def dispatch(self, what, com, bot, ievent): """ do the actual dispatch of event. """ if bot.stopped: return 0 # make command options if com.options: makeoptions(ievent, com.options) else: makeoptions(ievent) # make arguments and rest makeargrest(ievent) ievent.usercmnd = 1 rlog(10, 'plugins', 'dispatching %s for %s' % (ievent.command, ievent.userhost)) # call dispatch what.dispatch(com, bot, ievent) return 1
def unload(self, plugname): """ unload plugin commands. """ results = [] # look for the commands registerd in plugin for name, cmnd in self.iteritems(): if cmnd.plugname == plugname: results.append(name) got = 0 # remove commands for name in results: del self[name] rlog(-3, 'commands', 'unloaded %s (%s)' % (name, plugname)) got = 1 if got: return 1
def globalshutdown(): """ shutdown the bot. """ rlog(10, 'GOZERBOT', 'SHUTTING DOWN') try: os.remove('gozerbot.pid') except: pass try: runners_stop() rlog(10, 'gozerbot', 'shutting down fleet') fleet.exit() rlog(10, 'gozerbot', 'shutting down plugins') plugins.exit() rlog(10, 'GOZERBOT', 'done') os._exit(0) except Exception, ex: rlog(10, 'gozerbot.exit', 'exit error %s:' % str(ex))
def exit(self): """ call registered plugins save. """ self.save() threadlist = [] # call shutdown on all plugins for name, plug in self.plugs.iteritems(): try: shutdown = getattr(plug, 'shutdown') thread = start_new_thread(shutdown, ()) threadlist.append((name, thread)) try: self.initcalled.remove(name) except ValueError: pass except AttributeError: continue except Exception, ex: rlog(10, 'plugins', 'error shutting down %s: %s' % (name, str(ex)))
def regplugins(self): """ register plugins. """ self.regcore() avail = [] # check for myplugs directory if os.path.isdir('myplugs'): avail.extend(self.regdir('myplugs')) for i in os.listdir('myplugs'): if i.startswith('.'): continue if os.path.isdir('myplugs' + os.sep + i): avail.extend(self.regdir('myplugs' + os.sep + i)) else: rlog(10, 'plugins', 'no myplugs directory found') # check for gozerplugs package try: plugs = gozer_import('gozerplugs') except ImportError: rlog(20, 'plugins', "no gozerplugs package found") plugs = None if plugs: for i in plugs.__plugs__: if i not in avail: try: self.regplugin('gozerplugs', i) avail.append(i) except Exception, ex: handle_exception() else: rlog(10, 'plugins', '%s already loaded' % i)
def readoverload(self): """ see if there is a permoverload file and if so use it to overload permissions based on function name. """ try: overloadfile = open(datadir + os.sep + 'permoverload', 'r') except IOError: return try: for i in overloadfile: i = i.strip() splitted = i.split(',') try: funcname = splitted[0].strip() perms = [] for j in splitted[1:]: perms.append(j.strip()) except IndexError: rlog(10, 'plugins', "permoverload: can't set perms of %s" \ % i) continue if not funcname: rlog(10, 'plugins', "permoverload: no function provided") continue if not perms: rlog( 10, 'plugins', "permoverload: no permissions \ provided for %s" % funcname) continue self.overloads[funcname] = perms except Exception, ex: handle_exception()