From 2554f770eea0f3c78a1495b25a99a862a747b38e Mon Sep 17 00:00:00 2001 From: Stefan Krulj Date: Wed, 17 Oct 2012 15:19:48 +0200 Subject: [PATCH] Added a persistent container, changed logger and last_active modules to use it --- modules/active/last_active.py | 28 ++++++--- modules/active/logger.py | 111 ++++++++++++++++++---------------- sys/brathuhn.py | 19 +++++- sys/config.py | 7 ++- sys/persistent.py | 75 +++++++++++++++++++++++ 5 files changed, 179 insertions(+), 61 deletions(-) create mode 100644 sys/persistent.py diff --git a/modules/active/last_active.py b/modules/active/last_active.py index a74e891..b0f22cb 100644 --- a/modules/active/last_active.py +++ b/modules/active/last_active.py @@ -1,27 +1,40 @@ -import brathuhn, datetime, time +import brathuhn, datetime, time, config +from persistent import PersistentContainer -last_active = dict() +pc_msg = PersistentContainer(__name__+'_msg',config.PCACHE) +pc_stat = PersistentContainer(__name__+'_stat',config.PCACHE) def active(mfrom,msg): - global last_active + global pc_msg body = unicode(msg.getBody()) res = mfrom.getResource() date=datetime.datetime.fromtimestamp(time.time()) - last_active[res]=(body,date.strftime("%a, %d-%b-%Y %H:%M:%S")) + pc_msg[res]=(body,date.strftime("%a, %d-%b-%Y %H:%M:%S")) brathuhn.addGroupListener(active) +def sactive(mfrom,msg,status): + global pc_stat + res = mfrom.getResource() + date=datetime.datetime.fromtimestamp(time.time()) + stat = brathuhn.statusString(status) + pc_stat[res]=(stat,date.strftime("%a, %d-%b-%Y %H:%M:%S")) +brathuhn.addStatusListener(sactive) def last_active_cmd(msg,args): + global pc_msg + global pc_stat if( len(args)==2 ): res = args[1] - if res in last_active: + if res in pc_msg: if res[-1]!='s': mymsg=res+"'s" else: mymsg=res+"'" - la = last_active[res] + la = pc_msg[res] mymsg+= " last message on "+la[1]+' : "'+la[0]+'"' - + if res in pc_stat: + ls = pc_stat[res] + mymsg+= "\nlast status change on "+ls[1]+' to "'+ls[0]+'"' brathuhn.sendMsg(brathuhn.ROOM,mymsg,'groupchat') else: brathuhn.sendMsg(brathuhn.ROOM,"no message in record",'groupchat') @@ -30,4 +43,3 @@ def last_active_cmd(msg,args): brathuhn.addCommand("last_active","Usage: !last_active nick",last_active_cmd) - diff --git a/modules/active/logger.py b/modules/active/logger.py index 8bacf12..64b22c0 100644 --- a/modules/active/logger.py +++ b/modules/active/logger.py @@ -1,77 +1,86 @@ -import brathuhn, tempfile, datetime, time +import brathuhn, datetime, time from StringIO import StringIO -user_logs = dict() +from persistent import PersistentContainer +import config +user_logs = PersistentContainer(__name__,config.PCACHE) + +log=open("channel_log_"+brathuhn.NAME,"a+") def get_log(msg,args): - if msg.getFrom() in user_logs: - user_logs[msg.getFrom()].seek(0) - log = user_logs[msg.getFrom()].read() - fd = StringIO(log) - brathuhn.sendFileStream(msg.getFrom(),len(log),"log.txt",fd) + global log + if unicode(msg.getFrom()) in user_logs: + log.seek(user_logs[unicode(msg.getFrom())]) + txtlog = log.read() + fd = StringIO(txtlog ) + brathuhn.sendFileStream(unicode(msg.getFrom()),len(txtlog),"log.txt",fd) else: - brathuhn.sendMsg(msg.getFrom(),"I'm currently not logging for you") + brathuhn.sendMsg(unicode(msg.getFrom()),"I'm currently not logging for you") def show_log(msg,args): - if msg.getFrom() in user_logs: - user_logs[msg.getFrom()].seek(0) - log = user_logs[msg.getFrom()].read() - brathuhn.sendMsg(msg.getFrom(),'\n'+log) + global log + if unicode(msg.getFrom()) in user_logs: + log.seek(user_logs[unicode(msg.getFrom())]) + txtlog = log.read() + brathuhn.sendMsg(unicode(msg.getFrom()),'\n'+txtlog) else: - brathuhn.sendMsg(msg.getFrom(),"I'm currently not logging for you") + brathuhn.sendMsg(unicode(msg.getFrom()),"I'm currently not logging for you") def delete_log(msg,args): - if msg.getFrom() in user_logs: - user_logs[msg.getFrom()].seek(0) - user_logs[msg.getFrom()].truncate(0) - brathuhn.sendMsg(msg.getFrom(),"Done!") + global log + if unicode(msg.getFrom()) in user_logs: + user_logs[unicode(msg.getFrom())]=log.tell() + brathuhn.sendMsg(unicode(msg.getFrom()),"Done!") else: - brathuhn.sendMsg(msg.getFrom(),"I'm currently not logging for you") + brathuhn.sendMsg(unicode(msg.getFrom()),"I'm currently not logging for you") def stop_log(msg,args): - if msg.getFrom() in user_logs: - brathuhn.sendMsg(brathuhn.ROOM,"/me stopped logging for "+unicode(msg.getFrom()),'groupchat') - del user_logs[msg.getFrom()] + if unicode(msg.getFrom()) in user_logs: + brathuhn.sendMsg(brathuhn.ROOM,"/me stopped logging for "+unicode(unicode(msg.getFrom())),'groupchat') + del user_logs[unicode(msg.getFrom())] else: - brathuhn.sendMsg(msg.getFrom(),"I'm currently not logging for you") + brathuhn.sendMsg(unicode(msg.getFrom()),"I'm currently not logging for you") def start_log(msg,args): - if not msg.getFrom() in user_logs: - brathuhn.sendMsg(brathuhn.ROOM,"/me started logging for "+unicode(msg.getFrom()),'groupchat') - user_logs[msg.getFrom()]=open(tempfile.mkstemp(brathuhn.NAME)[1],"w+") + global log + if not unicode(msg.getFrom()) in user_logs: + brathuhn.sendMsg(brathuhn.ROOM,"/me started logging for "+unicode(unicode(msg.getFrom())),'groupchat') + user_logs[unicode(msg.getFrom())]=log.tell() else: - brathuhn.sendMsg(msg.getFrom(),"I'm already logging for you") + brathuhn.sendMsg(unicode(msg.getFrom()),"I'm already logging for you") def message_logger(mfrom,msg): + global log body = unicode(msg.getBody()) - for key in user_logs: - date=datetime.datetime.fromtimestamp(time.time()) - user_logs[key].write(date.strftime("(%H:%M:%S) ")) - user_logs[key].write(unicode(mfrom)+": "+body+"\n") + + date=datetime.datetime.fromtimestamp(time.time()) + log.write(date.strftime("(%H:%M:%S) ")) + log.write(mfrom.getResource()+": "+body+"\n") + log.flush() def status_logger(mfrom,msg,status): - for key in user_logs: - date=datetime.datetime.fromtimestamp(time.time()) - user_logs[key].write(date.strftime("(%H:%M:%S) ")) - if status==brathuhn.STATUS_JOIN: - user_logs[key].write(unicode(mfrom)+" joined\n") - if status==brathuhn.STATUS_ONLINE: - user_logs[key].write(unicode(mfrom)+" is now online\n") - if status==brathuhn.STATUS_OFFLINE: - user_logs[key].write(unicode(mfrom)+" left\n") - if status==brathuhn.STATUS_RENAME: - user_logs[key].write(unicode(mfrom)+" is now known as "+msg.getName()+"\n") - if status==brathuhn.STATUS_XAWAY: - user_logs[key].write(unicode(mfrom)+" is now extended away\n") - if status==brathuhn.STATUS_AWAY: - user_logs[key].write(unicode(mfrom)+" is now away\n") - if status==brathuhn.STATUS_UNKNOWN: - user_logs[key].write(unicode(mfrom)+" is now ???\n") + global log + date=datetime.datetime.fromtimestamp(time.time()) + log.write(date.strftime("(%H:%M:%S) ")) + if status==brathuhn.STATUS_JOIN: + log.write(mfrom.getResource()+" joined\n") + if status==brathuhn.STATUS_ONLINE: + log.write(mfrom.getResource()+" is now online\n") + if status==brathuhn.STATUS_OFFLINE: + log.write(mfrom.getResource()+" left\n") + if status==brathuhn.STATUS_RENAME: + log.write(mfrom.getResource()+" is now known as "+msg.getName()+"\n") + if status==brathuhn.STATUS_XAWAY: + log.write(mfrom.getResource()+" is now extended away\n") + if status==brathuhn.STATUS_AWAY: + log.write(mfrom.getResource()+" is now away\n") + if status==brathuhn.STATUS_UNKNOWN: + log.write(mfrom.getResource()+" is now ???\n") -def log(msg,args): +def logger(msg,args): if len(args)!=2: - brathuhn.sendMsg(msg.getFrom(),"Usage: !log (start|stop|delete|show|get)") + brathuhn.sendMsg(unicode(msg.getFrom()),"Usage: !log (start|stop|delete|show|get)") return if args[1]=='start': start_log(msg,args) @@ -84,8 +93,8 @@ def log(msg,args): elif args[1]=='get': get_log(msg,args) else: - brathuhn.sendMsg(msg.getFrom(),"Usage: !log (start|stop|delete|show|get)") + brathuhn.sendMsg(unicode(msg.getFrom()),"Usage: !log (start|stop|delete|show|get)") -brathuhn.addPrivateCommand("log","Usage: !log (start|stop|delete|show|get)",log) +brathuhn.addPrivateCommand("log","Usage: !log (start|stop|delete|show|get)",logger) brathuhn.addGroupListener(message_logger) brathuhn.addStatusListener(status_logger) diff --git a/sys/brathuhn.py b/sys/brathuhn.py index 24868b5..be1f06b 100644 --- a/sys/brathuhn.py +++ b/sys/brathuhn.py @@ -304,7 +304,7 @@ def callAt(func,_time,*args): number of arguments you need. Returns the call id, needed to cancel a call E.g this will call foo(arg1,arg2) in ~5 seconds - brathuhn.callAt(foo,time.time()+5,arg1,arg2) + callAt(foo,time.time()+5,arg1,arg2) @param func -- Function to be called @param time -- The time when the message will be called""" @@ -354,3 +354,20 @@ def sendFileStream(to,size,name,fd,method=SI): cl.send(cim) else: fd.close() + +def statusString(status): + if status==STATUS_JOIN: + return "join" + if status==STATUS_ONLINE: + return "online" + if status==STATUS_OFFLINE: + return "leave" + if status==STATUS_RENAME: + return "rename" + if status==STATUS_XAWAY: + return "extended away" + if status==STATUS_AWAY: + return "away" + if status==STATUS_UNKNOWN: + return "???" + diff --git a/sys/config.py b/sys/config.py index f730a05..59ad9cc 100644 --- a/sys/config.py +++ b/sys/config.py @@ -7,14 +7,19 @@ cp.read(["/etc/brathuhn/config.cfg","brathuhn.cfg",os.path.expanduser('~/.brathu NAME = cp.get("Account","NAME") SRV = cp.get("Account","SRV") PWD = cp.get("Account","PWD") + try: RESOURCE = cp.get("Account","RESOURCE") except: RESOURCE = 'bot' try: - S5B_PROXY = cp.get("General","RESOURCE") + S5B_PROXY = cp.get("General","PROXY") except: S5B_PROXY = 'proxy.jabbim.cz' +try: + PCACHE = cp.get("General","PROXY") +except: + PCACHE = 'pcache.ini' ROOM = cp.get("Conference","ROOM") PWD_ROOM = cp.get("Conference","PWD_ROOM") diff --git a/sys/persistent.py b/sys/persistent.py new file mode 100644 index 0000000..139b32f --- /dev/null +++ b/sys/persistent.py @@ -0,0 +1,75 @@ +from ConfigParser import ConfigParser +import cPickle as pickle +from threading import Lock +#TODO replace ConfigParser for better performance + +class PersistentContainer(object): + cfgparsers = dict() + locks = dict() + def __init__(self,namespace,path): + self.namespace = namespace + self.path = path + self.trans_cache = dict() + self.trans_del = [] + + if not path in PersistentContainer.locks: + PersistentContainer.locks[path] = Lock() + self.transaction = PersistentContainer.locks[path] + + if not path in PersistentContainer.cfgparsers: + PersistentContainer.cfgparsers[path] = ConfigParser() + PersistentContainer.cfgparsers[path].read([path]) + self.cp = PersistentContainer.cfgparsers[path] + + if not self.cp.has_section(namespace): + self.cp.add_section(namespace) + + def start_transaction(self,blocking=True): + return self.transaction.acquire(blocking) + + def commit_transaction(self): + self._write() + self.transaction.release() + + def rollback(self): + for k in self.trans_cache: + del self.trans_cache[k] + self.transaction.release() + + def is_owned(self): + return self.transaction.locked() + + def __getitem__(self, name): + if self.cp.has_option(self.namespace,name): + return pickle.loads(self.cp.get(self.namespace,name)) + return None + + def __setitem__(self, name,val): + self.trans_cache[name]=val + if not self.is_owned(): + self._write() + + def __delitem__(self, name): + if name not in self.trans_del: + self.trans_del.append(name) + if name in self.trans_cache: + del self.trans_cache[name] + if not self.is_owned(): + self._write() + + + def __contains__(self,name): + return self.cp.has_option(self.namespace,name) + + def _write(self): + for k in self.trans_cache: + val = self.trans_cache[k] + self.cp.set(self.namespace,k,pickle.dumps(val)) + while len(self.trans_del): + n = self.trans_del.pop() + self.cp.remove_option(self.namespace,n) + + f = open(self.path,'w') + self.cp.write(f) + f.close() +