usingGee;classModuleMucLog:Module{protectedweakModuleMucmuc;protectedHashMap<string,RoomLog>rooms;classRoomLog:Object{publicstringjid;publicstringlogpath;publicstringfilename;protectedweakModuleMucLogmuclog;protectedFileStreamfile;publicstringgetid(Timetime){returntime.format("%s");}protectedintlastday;protectedintlastyear;protectedintlastmonth;publicRoomLog(ModuleMucLogmuclog,stringjid){this.jid=jid;this.muclog=muclog;logpath=muclog.getconf(jid,"log-path",null);filename=null;write(Time.local(time_t()),"logstart","","Log started");}~RoomLog(){write(Time.local(time_t()),"logstop","","Log stopped");}publicstaticuintnick_hash(strings){uintsum=0;constuintk=102,m=54,l=140;for(varj=0,iTop=s.length;j<iTop;j++){sum+=k^s[j];}return((sum^m)+l)%10;}protectedvoidreal_write(Timetime,string_class,stringnick,stringstr){varid=getid(time);vartimes=time.format("%H:%M:%S");varnicklass=(_class=="message")?(" nick%u".printf(nick_hash(nick))):"";file.printf("<tr id='l_%s' class='%s'><td class='time'><a id='i_%s' href='#i_%s'>%s</a></td>",id,_class,id,id,times);file.printf("<td class='nick%s'>%s</td><td class='text'>%s</td></tr>\n",nicklass,nick,str);file.flush();}publicvoidwrite(Timetime,string_class,stringnick,stringstr){if((lastday!=time.day)||(lastmonth!=time.month)||(lastyear!=time.year)){varfname=time.format(logpath).replace("<muc>",jid);log("muc_log",LogLevelFlags.LEVEL_INFO,"Switching log file '%s' to '%s'",filename,fname);boolwasntnull=false;if(file!=null){wasntnull=true;real_write(time,"logstop","","Log stopped. See you in the next episode.");}//try {file=FileStream.open(fname,"a");if(file==null){intstart=0;intlength=fname.length;while(true){varpos=fname.index_of("/",start);if(pos==-1)break;stderr.printf("--------------------- %s\n",fname[0:pos]);Posix.mkdir(fname[0:pos],0777);start=pos+1;}file=FileStream.open(fname,"a");if(file==null){log("muc_log",LogLevelFlags.LEVEL_WARNING,"Failed to create log file '%s'",fname);return;}}if(file.tell()==0){varloghead=muclog.getconf(jid,"log-head",null);if(loghead!="null"){try{varheadfile=newIOChannel.file(loghead,"r");stringhead;size_tlength;headfile.read_to_end(outhead,outlength);headfile.shutdown(false);file.printf("%s\n",head.replace("<muc>",jid).replace("<date>",time.format("%d.%m.%Y")));}catch(FileErrorfe){log("muc_log",LogLevelFlags.LEVEL_WARNING,"Failed to read head");}}}filename=fname;lastyear=time.year;lastmonth=time.month;lastday=time.day;if(wasntnull)real_write(time,"logstart","","Log started. This soap opera will never end.");}real_write(time,_class,nick,str);}}publicstringgetconf(stringjid,stringkey,string?def){varres=cfg["muc "+jid,key];if(res==null)res=cfg["muc",key];if(res==null)res=def;returnres;}publicModuleMucLog(Configcfg,Connectionconn){base(cfg,conn);rooms=newHashMap<string,RoomLog>();muc=null;foreach(varmoduleinconn.modules){if(module.name()=="muc")muc=(ModuleMuc)module;}if(muc==null)log("muc_log",LogLevelFlags.LEVEL_ERROR,"Module 'muc' is not loaded");muc.state_changed.connect((conf,olds,news,desc)=>{switch(news){caseModuleMuc.State.CONNECTED:if(getconf(conf.jid,"log","no")=="yes"){varroom=newRoomLog(this,conf.jid);rooms[conf.jid]=room;varsb=newStringBuilder();varnotfirst=false;sb.append("Participants: ");foreach(varoccupantinconf.occupants.values){if(notfirst)sb.append(", ");elsenotfirst=true;sb.append(Markup.escape_text(occupant.nick).replace(" "," "));}room.write(Time.local(time_t()),"userlist","",sb.str);}break;caseModuleMuc.State.DISCONNECTED:rooms.unset(conf.jid);break;}});muc.on_message.connect((conf,user,message,body)=>{if((user!=null)&&(body!=null)&&(message.get_child("delay")==null)){varroom=rooms[conf.jid];if(room!=null){varnick=Markup.escape_text(user.nick).replace(" "," ");if(body.has_prefix("/me ")){room.write(Time.local(time_t()),"action","*",nick+Markup.escape_text(body[3:body.length]).replace("\n","<br/>"));}elseroom.write(Time.local(time_t()),"message",nick,Markup.escape_text(body).replace("\n","<br/>"));}}});muc.on_join.connect((conf,user)=>{varroom=rooms[conf.jid];if(room!=null){varnick=Markup.escape_text(user.nick).replace(" "," ");room.write(Time.local(time_t()),"join","*",nick+" has joined the room");}});muc.on_part.connect((conf,user,status)=>{varroom=rooms[conf.jid];if(room!=null){varnick=Markup.escape_text(user.nick).replace(" "," ");room.write(Time.local(time_t()),"part","*",nick+" has left the room"+((status!=null)?(": "+Markup.escape_text(status)):""));}});muc.on_nick.connect((conf,user,prev)=>{varroom=rooms[conf.jid];if(room!=null){varnick=Markup.escape_text(user.nick).replace(" "," ");varnickp=Markup.escape_text(prev).replace(" "," ");room.write(Time.local(time_t()),"nickchange","*",nickp+" is now known as "+nick);}});}publicoverridestringname(){return"muc_log";}}