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 dbstart(ddir=None, mainconfig=None): """ start the database connection setting Session and engine. """ dburi = geturi(ddir, mainconfig) # only show dburi if it doesn't contain a password if '///' in dburi: rlog(10, 'alchemy', 'starting database %s' % dburi) else: rlog(10, 'alchemy', 'starting database') # create engine if 'mysql' in config['dbtype']: engine = create_engine(dburi, strategy='threadlocal', pool_recycle=3600, max_overflow=-1) else: engine = create_engine(dburi, strategy='threadlocal') # setup metadata and session Base.metadata.bind = engine rlog(10, 'alchemy', 'checking for tables') Base.metadata.create_all() Session = scoped_session(sessionmaker(autocommit=True)) Session.configure(bind=engine) stats.up('alchemy', 'engines') return (Session, engine)
def missing(self, txt): """ show what arguments are missing. """ stats.up('events', 'missing') if self.origtxt: splitted = self.origtxt.split() if self.bot.nick in splitted[0]: try: cmnd = splitted[1] except IndexError: cmnd = splitted[0] elif 'cmnd' in splitted[0]: try: cmnd = splitted[2] except IndexError: cmnd = splitted[0] else: if self.msg: cmnd = splitted[0] else: if self.aliased: cmnd = self.aliased else: cmnd = splitted[0][1:] self.reply(cmnd + ' ' + txt) else: self.reply('missing origtxt: %s' % txt)
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 save(self): """ persist data attribute. """ if stopsave: rlog(100, "persist", "stopping mode .. not saving %s" % self.fn) return # save data try: saving.append(str(self.fn)) self.lock.acquire() tmp = self.fn + ".tmp" # tmp file to save to # first save to temp file and when done rename try: datafile = open(tmp, "w") except IOError, ex: rlog(100, "persist", "can't save %s: %s" % (self.fn, str(ex))) return # dump JSON to file dump(self.data, datafile) datafile.close() os.rename(tmp, self.fn) stats.up("persist", "saved") rlog(10, "persist", "%s saved" % self.fn)
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 save(self): """ persist data attribute. """ if stopsave: rlog(100, 'persist', 'stopping mode .. not saving %s' % self.fn) return # save data try: saving.append(str(self.fn)) self.lock.acquire() tmp = self.fn + '.tmp' # tmp file to save to # first save to temp file and when done rename try: datafile = open(tmp, 'w') except IOError, ex: rlog(100, 'persist', "can't save %s: %s" % (self.fn, str(ex))) return # dump JSON to file dump(self.data, datafile) datafile.close() os.rename(tmp, self.fn) stats.up('persist', 'saved') rlog(10, 'persist', '%s saved' % self.fn)
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 create_session(): """ create a session ready for use. """ stats.up('alchemy', 'sessions') session = Session() return session
def query(q, session=None): """ do a query on the database. """ stats.up('alchemy', 'query') if not session: session = create_session() res = session.query(q) return res
def __init__(self, func, prereq, plugname, kwargs, threaded=False, speed=5): self.func = func # the callback function self.prereq = prereq # pre condition function self.plugname = plugname # plugin name self.kwargs = kwargs # kwargs to pass on to function self.threaded = copy.deepcopy(threaded) # run callback in thread self.speed = copy.deepcopy(speed) # speed to execute callback with stats.up("callbacks", "created")
def __init__(self, func, prereq, plugname, kwargs, threaded=False, \ speed=5): self.func = func # the callback function self.prereq = prereq # pre condition function self.plugname = plugname # plugin name self.kwargs = kwargs # kwargs to pass on to function self.threaded = copy.deepcopy(threaded) # run callback in thread self.speed = copy.deepcopy(speed) # speed to execute callback with stats.up('callbacks', 'created')
def __init__(self, event=None): self.orig = None # the original command if self.type = 'chat' # type of event self.jabber = False # set if event is jabber event self.groupchat = False # set if event is groupchat self.botoutput = False # set if event is bot output self.cmnd = None # the event command self.prefix = u"" # txt before the command self.postfix = u"" # txt after the command self.target = u"" # target to give reposnse to self.arguments = [] # arguments of event self.nick = u"" # nick of user originating the event self.user = u"" # user originating the event self.ruserhost = u"" # real userhost self.userhost = u"" # userhost that might change self.stripped = u"" # stripped JID self.resource = u"" # resource part of JID self.origchannel = u"" # original channel self.channel = u"" # channel .. might change self.origtxt = u"" # original txt self.txt = u"" # text .. might change self.command = u"" # the bot command if any self.alias = u"" # set to alias if one is used self.aliased = u"" # set if commadn is aliased self.time = time.time() # event creation time self.msg = False # set if event is a private message self.args = [] # arguments of command self.rest = u"" # txt following the command self.usercmnd = 0 # set if event is a command self.bot = None # the bot where the event originated on self.sock = None # socket (set in DCC chat) self.allowqueue = True # allow event to be used in pipeline self.closequeue = True # cloase event queues when execution has ended self.inqueue = None # queue used as input in pipeline self.queues = [] # output queues (only used when set) self.printto = None # target to printti self.speed = 0 # speed with which this event needs to be processed self.groups = None # set if event triggers a RE callback self.cc = u"" # control character self.jid = None # JID of used originating the event self.jidchange = None # set is event changes jid self.conn = None # connection of bot originating the event self.to = None # target self.denied = False # set if command is denied self.isresponse = False # set if event is a reponse self.isdcc = False # set if event is DCC related self.options = {} # options dict on the event self.optionset = [] # list of options set self.filter = [] # filter list to use on output # if event is provided inititalise this object with it if event: self.copyin(event) # stats stats.up('events', 'created')
def run(self): """ run the thread """ try: if self.name not in dontshowthreads: rlog(-4, 'thr', 'running thread %s' % self.name) stats.up('threads', self.name) threading.Thread.run(self) except Exception, ex: handle_exception() time.sleep(0.1)
def run(self): """ run the bot command """ try: rlog(10, 'thr', 'running bot command thread %s' % self.name) stats.up('threads', self.name) result = threading.Thread.run(self) if self.ievent.closequeue: rlog(4, 'thr', 'closing queue for %s' % self.ievent.userhost) for i in self.ievent.queues: i.put_nowait(None) except Exception, ex: handle_exception(self.ievent) time.sleep(0.1)
def check(self, bot, ievent): """ check for callbacks to be fired. """ # check for "ALL" callbacks if self.cbs.has_key('ALL'): for cb in self.cbs['ALL']: stats.up('callbacks', 'ALL') self.callback(cb, bot, ievent) cmnd = ievent.cmnd.upper() # check for CMND callbacks if self.cbs.has_key(cmnd): for cb in self.cbs[cmnd]: stats.up('callbacks', cmnd) self.callback(cb, bot, ievent)
def check(self, bot, ievent): """ check for callbacks to be fired. """ # check for "ALL" callbacks if self.cbs.has_key("ALL"): for cb in self.cbs["ALL"]: stats.up("callbacks", "ALL") self.callback(cb, bot, ievent) cmnd = ievent.cmnd.upper() # check for CMND callbacks if self.cbs.has_key(cmnd): for cb in self.cbs[cmnd]: stats.up("callbacks", cmnd) self.callback(cb, bot, ievent)
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 transaction(*args, **kwargs): """ the tranasction wrapper .. works on methods. """ try: stats.up('alchemy', 'transactions') session = create_session() session.begin(subtransactions=True) arglist = list(args) if not ismethod: arglist.insert(0, session) else: arglist.insert(1, session) res = func(*arglist, **kwargs) session.flush() engine.commit() except sqlalchemy.exc.TimeoutError: rlog(10, 'alchemy', 'timeout occured') session.rollback() except Exception, ex: session.rollback() raise
def getuser(userhost, session=None): """ get a user based on userhost. """ stats.up('alchemy', 'getuser') if not session: session = create_session() try: user = query(UserHost, session).filter_by(userhost=userhost).first() if user: res = query(User, session).filter_by(name=user.name.lower()).first() if res: return res except sqlalchemy.exc.TimeoutError: rlog(10, 'alchemy', 'timeout occured') session.rollback() except Exception, ex: session.rollback() raise
def transaction(*args, **kwargs): """ the tranasction wrapper .. works on methods. """ try: stats.up('alchemy', 'transactions') session = create_session() session.begin(subtransactions=True) arglist = list(args) if not ismethod: arglist.insert(0, session) else: arglist.insert(1, session) res = func(*arglist, **kwargs) session.flush() engine.commit() except sqlalchemy.exc.TimeoutError: rlog(10, 'alchemy', 'timeout occured') session.rollback() except Exception ,ex: session.rollback() raise
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 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()
class Persist(object): """ persist data attribute to JSON file. """ def __init__(self, filename, default=None, init=True): """ Persist constructor """ self.fn = filename # filename to save to self.lock = thread.allocate_lock() # lock used when saving) self.data = None # attribute to hold the data if init: self.init(default) def init(self, default=None): """ initialize the data. """ rlog(0, 'persist', 'reading %s' % self.fn) # see if file exists .. if not initialize data to default try: datafile = open(self.fn, 'r') except IOError, ex: if not 'No such file' in str(ex): rlog(10, 'persist', 'failed to read %s: %s' % (self.fn, str(ex))) if default != None: self.data = copy.deepcopy(default) return # load the JSON data into attribute try: self.data = load(datafile) datafile.close() stats.up('persist', 'load') except Exception, ex: rlog(100, 'persist', 'ERROR: %s' % self.fn) raise
def dispatch(self, com, bot, ievent): """ dispatch on ircevent passing bot an ievent as arguments """ if bot.stopped: return 0 # stats stats.up('cmnds', com.name) stats.up('cmnds', com.plugname) stats.up('cmnds', 'speed%s' % com.speed) # execute command if com.threaded: start_bot_command(com.func, (bot, ievent)) else: speed = ievent.speed or com.speed ievent.speed = speed cmndrunners[10 - speed].put(com.name, com.func, bot, ievent) return 1
def dispatch(self, com, bot, ievent): """ dispatch on ircevent passing bot an ievent as arguments """ if bot.stopped: return 0 # stats stats.up('cmnds', com.name) stats.up('cmnds', com.plugname) stats.up('cmnds', 'speed%s' % com.speed) # execute command if com.threaded: start_bot_command(com.func, (bot, ievent)) else: speed = ievent.speed or com.speed ievent.speed = speed cmndrunners[10-speed].put(com.name, com.func, bot, ievent) return 1
def parse(self, bot, rawstr): """ parse raw string into ircevent. """ self.bot = bot stats.up('events', bot.name) bot.nrevents += 1 rawstr = rawstr.rstrip() splitted = re.split('\s+', rawstr) # check if there is a prefix (: in front) if not rawstr[0] == ':': # no prefix .. 1st word is command splitted.insert(0, ":none!none@none") rawstr = ":none!none@none " + rawstr self.prefix = splitted[0][1:] # get nick/userhost nickuser = self.prefix.split('!') if len(nickuser) == 2: self.nick = nickuser[0] stats.up('events', self.nick) if self.bot.cfg['stripident'] or config['stripident']: self.userhost = stripident(nickuser[1]) else: self.userhost = nickuser[1] # set command self.cmnd = splitted[1] stats.up('events', self.cmnd) # split string based of postfix count .. nr of items ater the command if pfc.has_key(self.cmnd): self.arguments = splitted[2:pfc[self.cmnd] + 2] txtsplit = re.split('\s+', rawstr, pfc[self.cmnd] + 2) self.txt = txtsplit[-1] else: self.arguments = splitted[2:] # 1st argument is target if self.arguments: self.target = self.arguments[0] self.postfix = ' '.join(self.arguments) # check if target is text if self.target and self.target.startswith(':'): self.txt = ' '.join(self.arguments) # strip strarting ':' from txt if self.txt: if self.txt[0] == ":": self.txt = self.txt[1:] rlog(0, 'ircevent', "%s %s %s" % (self.cmnd, self.arguments, self.txt)) # set ircevent attributes if self.cmnd == 'PING': self.speed = 10 if self.cmnd == 'PRIVMSG': self.channel = self.arguments[0] elif self.cmnd == 'JOIN' or self.cmnd == 'PART': if self.arguments: self.channel = self.arguments[0] else: self.channel = self.txt elif self.cmnd == 'MODE': self.channel = self.arguments[0] elif self.cmnd == 'TOPIC': self.channel = self.arguments[0] elif self.cmnd == 'KICK': self.channel = self.arguments[0] elif self.cmnd == '353': self.channel = self.arguments[2] elif self.cmnd == '324': self.channel = self.arguments[1] if self.userhost: # userhost before possible stripident self.ruserhost = self.userhost # jabber compat .. this is userhost on irc self.stripped = self.userhost # determine user self.user = stripident(self.userhost).split('@')[0] self.origtxt = self.txt self.channel = self.channel.strip() stats.up('events', self.channel) self.origchannel = self.channel rlog(-1, 'ircevent', self) # show error try: nr = int(self.cmnd) if nr > 399: rlog(10, bot.name + '.error', '%s: %s %s' % (self.cmnd, \ self.arguments, self.txt)) except ValueError: pass return self
def reply(self, txt, result=None, nick=None, dot=False, nritems=False, nr=False, fromm=None, private=False, how=''): # don't replu is result is empty list if result == []: return # stats stats.up('events', 'replies') if not how: try: how = self.options['--how'] except KeyError: how = 'msg' # init restxt = "" splitted = [] # make reply if result is a dict if type(result) == types.DictType: for i, j in result.iteritems(): if type(j) == types.ListType: try: z = ' .. '.join(j) except TypeError: z = unicode(j) else: z = j res = "%s: %s" % (i, z) splitted.append(res) if dot == True: restxt += "%s%s" % (res, ' .. ') else: restxt += "%s %s" % (dot or ' ', res) if restxt: if dot == True: restxt = restxt[:-6] elif dot: restxt = restxt[:-len(dot)] lt = False # set if result is list # set vars if result is a list if type(txt) == types.ListType and not result: result = txt origtxt = u"" lt = True else: origtxt = txt if result: lt = True # if queues are set write output to them if self.queues: for i in self.queues: if splitted: for item in splitted: i.put_nowait(item) elif restxt: i.put_nowait(restxt) elif lt: for j in result: i.put_nowait(j) else: i.put_nowait(txt) return # check if bot is set in event if not self.bot: rlog(10, 'event', 'no bot defined in event') return # make response pretxt = origtxt if lt and not restxt: res = [] # check if there are list in list for i in result: if type(i) == types.ListType or type(i) == types.TupleType: try: res.append(u' .. '.join(i)) except TypeError: res.extend(i) else: res.append(i) # if nritems is set .. result = res if nritems: if len(result) > 1: pretxt += "(%s items) .. " % len(result) txtlist = result # prepend item number for results if not nr is False: try: start = int(nr) except ValueError: start = 0 txtlist2 = [] teller = start for i in txtlist: txtlist2.append(u"%s) %s" % (teller, i)) teller += 1 txtlist = txtlist2 # convert results to encoding txtl = [] for item in txtlist: txtl.append(toenc(item)) txtlist = txtl # join result with dot if dot == True: restxt = ' .. '.join(txtlist) elif dot: restxt = dot.join(txtlist) else: restxt = ' '.join(txtlist) # see if txt needs to be prepended if pretxt: try: restxt = pretxt + restxt except TypeError: rlog(10, 'eventbase', "can't add %s and %s" % (str(pretxt), str(restxt))) # if txt in result is filtered ignore the reuslt if self.filtered(restxt): return # if event is DCC based write result directly to socket if self.cmnd == 'DCC' and self.sock: self.bot.say(self.sock, restxt, speed=self.speed, how=how) return # if nick is set write result to nick in question if nick: self.bot.say(nick, restxt, fromm=nick, speed=self.speed, how=how) return # if originatiog event is a private message or private flaf is set if self.msg or private: self.bot.say(self.nick, restxt, fromm=self.nick, speed=self.speed, how=how) return # check if bot is in silent mode .. if so use /msg silent = False channel = self.printto or self.channel try: silent = self.bot.channels[channel]['silent'] except (KeyError, TypeError): pass fromm = fromm or self.nick # check if notice needs to be used if silent: notice = False try: notice = self.bot.channels[channel]['notice'] except (KeyError, TypeError): pass if notice: self.bot.say(self.nick, restxt, how='notice', fromm=fromm, speed=self.speed) else: self.bot.say(self.nick, restxt, fromm=fromm, speed=self.speed, how=how) return # if printto is set used that as the target if self.printto: self.bot.say(self.printto, restxt, fromm=fromm, speed=self.speed, how=how) return else: self.bot.say(self.channel, restxt, fromm=fromm, speed=self.speed, how=how)
def parse(self, bot, rawstr): """ parse raw string into ircevent. """ self.bot = bot stats.up('events', bot.name) bot.nrevents += 1 rawstr = rawstr.rstrip() splitted = re.split('\s+', rawstr) # check if there is a prefix (: in front) if not rawstr[0] == ':': # no prefix .. 1st word is command splitted.insert(0, ":none!none@none") rawstr = ":none!none@none " + rawstr self.prefix = splitted[0][1:] # get nick/userhost nickuser = self.prefix.split('!') if len(nickuser) == 2: self.nick = nickuser[0] stats.up('events', self.nick) if self.bot.cfg['stripident'] or config['stripident']: self.userhost = stripident(nickuser[1]) else: self.userhost = nickuser[1] # set command self.cmnd = splitted[1] stats.up('events', self.cmnd) # split string based of postfix count .. nr of items ater the command if pfc.has_key(self.cmnd): self.arguments = splitted[2:pfc[self.cmnd]+2] txtsplit = re.split('\s+', rawstr, pfc[self.cmnd]+2) self.txt = txtsplit[-1] else: self.arguments = splitted[2:] # 1st argument is target if self.arguments: self.target = self.arguments[0] self.postfix = ' '.join(self.arguments) # check if target is text if self.target and self.target.startswith(':'): self.txt = ' '.join(self.arguments) # strip strarting ':' from txt if self.txt: if self.txt[0] == ":": self.txt = self.txt[1:] rlog(0, 'ircevent',"%s %s %s" % (self.cmnd, self.arguments, self.txt)) # set ircevent attributes if self.cmnd == 'PING': self.speed = 10 if self.cmnd == 'PRIVMSG': self.channel = self.arguments[0] elif self.cmnd == 'JOIN' or self.cmnd == 'PART': if self.arguments: self.channel = self.arguments[0] else: self.channel = self.txt elif self.cmnd == 'MODE': self.channel = self.arguments[0] elif self.cmnd == 'TOPIC': self.channel = self.arguments[0] elif self.cmnd == 'KICK': self.channel = self.arguments[0] elif self.cmnd == '353': self.channel = self.arguments[2] elif self.cmnd == '324': self.channel = self.arguments[1] if self.userhost: # userhost before possible stripident self.ruserhost = self.userhost # jabber compat .. this is userhost on irc self.stripped = self.userhost # determine user self.user = stripident(self.userhost).split('@')[0] self.origtxt = self.txt self.channel = self.channel.strip() stats.up('events', self.channel) self.origchannel = self.channel rlog(-1, 'ircevent', self) # show error try: nr = int(self.cmnd) if nr > 399: rlog(10, bot.name + '.error', '%s: %s %s' % (self.cmnd, \ self.arguments, self.txt)) except ValueError: pass return self