logfactory.cpp

Go to the documentation of this file.
00001 /*
00002 #########################################################################
00003 #
00004 #  This file is part of trustyRC.
00005 #
00006 #  trustyRC, fully modular IRC robot 
00007 #  Copyright (C) 2006-2008 Nicoleau Fabien 
00008 #
00009 #  trustyRC is free software: you can redistribute it and/or modify
00010 #  it under the terms of the GNU General Public License as published by
00011 #  the Free Software Foundation, either version 3 of the License, or
00012 #  (at your option) any later version.
00013 #
00014 #  trustyRC is distributed in the hope that it will be useful,
00015 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 #  GNU General Public License for more details.
00018 #
00019 #  You should have received a copy of the GNU General Public License
00020 #  along with trustyRC.  If not, see <http://www.gnu.org/licenses/>.
00021 #
00022 #########################################################################
00023 */
00024 
00029 #include "logfactory.h"
00030 
00034 LogFactory::LogFactory(BotKernel*b)
00035 {
00036         this->author = "eponyme";
00037         this->description = "Channels logging manager";
00038         this->version = VERSION;
00039         this->name = "logfactory";
00040    this->bindFunction("greplog",IN_COMMAND_HANDLER,"greplog",0,25); 
00041    this->bindFunction("lastseen",IN_COMMAND_HANDLER,"lastseen",0,25); 
00042         this->bindFunction("JOIN",IN_TYPE_HANDLER,"joinHandler",0,10);
00043         this->bindFunction("PART",IN_TYPE_HANDLER,"partHandler",0,10);
00044         this->bindFunction("QUIT",IN_TYPE_HANDLER,"quitHandler",0,10);
00045         this->bindFunction("NICK",IN_TYPE_HANDLER,"nickHandler",0,10);
00046         this->bindFunction("TOPIC",IN_TYPE_HANDLER,"topicHandler",0,10);
00047         this->bindFunction("KICK",IN_TYPE_HANDLER,"kickHandler",0,10);
00048         this->bindFunction("MODE",IN_TYPE_HANDLER,"modeHandler",0,10);
00049         this->bindFunction("PRIVMSG",IN_TYPE_HANDLER,"privmsgHandler",0,10);
00050         this->bindFunction("332",IN_TYPE_HANDLER,"topicJoin",0,10);
00051         this->bindFunction("333",IN_TYPE_HANDLER,"topicInfos",0,10);
00052         this->bindFunction("240",IN_LOOP,"cleanLogs",0,30);
00053    this->bindFunction("",OUT_ALL_MSGS,"sendHandler",0,10);
00054    this->addRequirement("usersinfos");
00055    this->logs = new map<string,LogFile*>;
00056    this->kernel = b;
00057    DIR*directory = opendir((this->kernel->getDatasDir()+"logs").c_str());
00058    if (directory == NULL ) {
00059       if (mkdir((this->kernel->getDatasDir()+"logs").c_str(),0755) == -1 ) {
00060          this->kernel->getSysLog()->log("Unable to create logs dir (check write access?). Nothing will be logged ...",WARNING);
00061       }
00062    } 
00063 }
00064 
00068 LogFactory::~LogFactory() 
00069 {
00070    this->destroyLogs();
00071    delete this->logs;
00072 }
00073 
00077 void LogFactory::destroyLogs() {
00078    for(map<string,LogFile*>::const_iterator iter = this->logs->begin();iter!=this->logs->end();iter++) {
00079       delete iter->second;
00080    }   
00081 }
00082 
00088 bool LogFactory::hasToBeLogged(string channel) 
00089 {
00090    return Tools::isInVector(Tools::stringToVector(this->kernel->getCONFF()->getValue(this->name+".log"),","),channel) ; 
00091 }
00092 
00097 vector<Channel*> LogFactory::getLoggedChannels() {
00098    vector<Channel*> results;
00099    map<string,Channel*>::iterator fter ;
00100    pPlugin * ppUser = this->kernel->getPlugin("usersinfos");
00101    UsersInfos*ui = (UsersInfos*)ppUser->object ;
00102    map<string,Channel*>* users = ui->getUsers();
00103    vector<string> channels = Tools::stringToVector(this->kernel->getCONFF()->getValue(this->name+".log"),",") ;
00104    for (unsigned int i = 0; i < channels.size(); i ++ ) {
00105       fter = users->find(channels[i]);
00106       if(fter != users->end() ) {
00107          results.push_back(fter->second);
00108       }
00109    }
00110    return results;
00111 }
00112 
00123 void LogFactory::cleanLogs() { 
00124    vector<string> logged,joined;
00125    pPlugin * ppUser = this->kernel->getPlugin("usersinfos");
00126    UsersInfos*ui = (UsersInfos*)ppUser->object ;
00127    map<string,Channel*>* users = ui->getUsers();
00128    for(map<string,Channel*>::const_iterator iter = users->begin();iter!=users->end();iter++) {
00129       joined.push_back(iter->first);
00130    } 
00131    for(map<string,LogFile*>::const_iterator iter = this->logs->begin();iter!=this->logs->end();iter++) {
00132       logged.push_back(iter->first);
00133    } 
00134    for (unsigned int i = 0 ; i < logged.size() ; i ++ ) {
00135       if ( logged[i] == "private" ) {
00136          if ( !hasToBeLogged(logged[i]) ) {
00137             this->closeLog(logged[i]) ;
00138          }
00139       }
00140       else {
00141          if ( (!Tools::isInVector(joined,logged[i])) || (!hasToBeLogged(logged[i])) ) {
00142             this->closeLog(logged[i]) ;
00143          }
00144       }
00145    }
00146 }
00147 
00155 bool LogFactory::log(string channel,string event) {
00156    LogFile* lf = (*this->logs)[channel] ;
00157    if ( lf == NULL ) {
00158       if(this->newLog(channel)) {
00159          lf = (*this->logs)[channel] ;
00160       }
00161    }
00162    if ( lf != NULL ) {
00163       return lf->log(event);
00164    }
00165    return false;
00166 }
00167 
00173 bool LogFactory::newLog(string channel) {
00174    LogFile* newFile = new LogFile(this->kernel->getDatasDir()+"logs/"+channel+"-",false,true,"","%Y");
00175    (*this->logs)[channel] = newFile;
00176    return newFile->open();
00177 }
00178 
00183 void LogFactory::closeLog(string channel) {
00184    LogFile* lf = (*this->logs)[channel];
00185    if ( lf != NULL ) {
00186       lf->close();
00187       delete(lf);
00188       this->logs->erase(channel); 
00189    }
00190 }
00191 
00192 extern "C"
00193 {
00194         Plugin* contruct_logfactory(BotKernel*b)
00195         {
00196                 return new LogFactory(b);
00197         }
00198         void destroy_logfactory(Plugin*p)
00199         {
00200                 delete p;
00201         }
00202         bool greplog (Message*m,Plugin*p,BotKernel*b)
00203         {
00204       string command;
00205       if(m->isPublic()&&(m->nbParts()>=5) ) {
00206          if ( ((LogFactory*)p)->hasToBeLogged(m->getSource()) ) {
00207             command = "grep \""+Tools::vectorToString(m->getSplit()," ",4)+"\" $(ls -tr "+b->getDatasDir()+"logs/"+ m->getSource() +"-*.log)|sed -e '$!{h;d;}' -e x > "+b->getDatasDir()+"greplog.log" ;
00208          }
00209          else {
00210             command = "grep \""+Tools::vectorToString(m->getSplit()," ",4)+"\" $(ls -tr "+b->getDatasDir()+"logs/"+ m->getSource() +"-*.log)|tail -1 > "+b->getDatasDir()+"greplog.log" ;
00211          }
00212          if (system (command.c_str()) != -1 ) {
00213             std::ifstream greplog((b->getDatasDir()+"greplog.log").c_str() );
00214             if ( greplog ) {
00215                string line; 
00216                while ( getline( greplog, line ) ) {
00217                   b->send(IRCProtocol::sendMsg(m->getSource(),line));
00218                }
00219                greplog.close();
00220             }
00221          }
00222          else {
00223             b->send(IRCProtocol::sendMsg(m->getSource(),"Execution error"));
00224          }
00225       }
00226                 return true;
00227         }
00228         bool lastseen (Message*m,Plugin*p,BotKernel*b)
00229         {
00230       string command;
00231       if(m->isPublic()&&(m->nbParts()==5) ) {
00232          if ( ((LogFactory*)p)->hasToBeLogged(m->getSource()) ) {
00233             command = "grep \""+m->getPart(4)+"\" $(ls -tr "+b->getDatasDir()+"logs/"+ m->getSource() +"-*.log)|sed -e '$!{h;d;}' -e x > "+b->getDatasDir()+"greplog.log" ;
00234          }
00235          else {
00236             command = "grep \""+m->getPart(4)+"\" $(ls -tr "+b->getDatasDir()+"logs/"+ m->getSource() +"-*.log)|tail -1 > "+b->getDatasDir()+"greplog.log" ;
00237          }
00238          if (system (command.c_str()) != -1 ) {
00239             std::ifstream greplog((b->getDatasDir()+"greplog.log").c_str() );
00240             if ( greplog ) {
00241                string line; 
00242                while ( getline( greplog, line ) ) {
00243                   b->send(IRCProtocol::sendMsg(m->getSource(),line));
00244                }
00245                greplog.close();
00246             }
00247          }
00248          else {
00249             b->send(IRCProtocol::sendMsg(m->getSource(),"Execution error"));
00250          }
00251       }
00252                 return true;
00253         }
00254         bool joinHandler (Message*m,Plugin*p,BotKernel*b) 
00255         {
00256       string channel;
00257       if (m->getSource()[0] == ':' ) {
00258          channel = m->getSource().substr(1);
00259       }
00260       else {
00261          channel = m->getSource() ;
00262       }
00263       if ( ((LogFactory*)p)->hasToBeLogged(channel)) {
00264          if ( m->getNickSender() == b->getNick() ) {
00265             ((LogFactory*)p)->log(channel,"* Now talking on "+ channel );
00266          }
00267          else {
00268             ((LogFactory*)p)->log(channel,"* " + m->getNickSender() + " (" + m->getSender() + ") has joined " + channel);
00269          }
00270       }
00271                 return true;
00272         }
00273         bool topicJoin (Message*m,Plugin*p,BotKernel*b)
00274         {
00275       if ( ((LogFactory*)p)->hasToBeLogged(m->getPart(3))) {
00276          ((LogFactory*)p)->log(m->getPart(3),"* Topic for " + m->getPart(3) + " is: " + Tools::vectorToString(m->getSplit()," ",4).substr(1));
00277       }
00278                 return true;
00279         }
00280         bool topicInfos (Message*m,Plugin*p,BotKernel*b)
00281         {
00282       time_t time;
00283       if ( ((LogFactory*)p)->hasToBeLogged(m->getPart(3))) {
00284          time =  Tools::strToUnsignedInt(m->getPart(5)) ;
00285          ((LogFactory*)p)->log(m->getPart(3),"* Topic for " + m->getPart(3) + " set by " + m->getPart(4) + " at " + ((string)ctime(&time)).substr(0,24)) ;
00286       }
00287                 return true;
00288         }
00289         bool partHandler (Message*m,Plugin*p,BotKernel*b) 
00290         {
00291       if ( ((LogFactory*)p)->hasToBeLogged(m->getSource())) {
00292          if ( m->getNickSender() == b->getNick() ) {
00293             ((LogFactory*)p)->log(m->getSource(),"* You have left channel " + m->getSource());
00294          }
00295          else {
00296             ((LogFactory*)p)->log(m->getSource(),"* "+m->getNickSender()+" ("+m->getSender()+") has left "+m->getSource()+((m->nbParts()>3)?" ("+Tools::vectorToString(m->getSplit()," ",3).substr(1)+")":""));
00297          }
00298       }
00299                 return true;
00300         }
00301         bool quitHandler (Message*m,Plugin*p,BotKernel*b)
00302         {
00303       vector<string>* channels;
00304       pPlugin * ppUser = b->getPlugin("usersinfos");
00305       UsersInfos*ui = (UsersInfos*)ppUser->object ;
00306       channels = ui->getLastQuitChannels() ;
00307       for(unsigned int i = 0 ; i < channels->size() ; i ++ ) {
00308          if (((LogFactory*)p)->hasToBeLogged(channels->at(i))) {
00309             ((LogFactory*)p)->log(channels->at(i),"* "+m->getNickSender()+" has quit"+" ("+Tools::vectorToString(m->getSplit()," ",2).substr(1)+")");
00310          } 
00311       }
00312                 return true;
00313         }
00314         bool nickHandler (Message*m,Plugin*p,BotKernel*b) 
00315         {
00316       bool isBot;
00317       vector<Channel*> channels ;
00318       string event;
00319       if( m->getPart(2).substr(1) == b->getNick() ) { // as setNick command would have changed nick before this function is called, we use new nick to check
00320          isBot = true;
00321          event = "* You are now known as "+m->getPart(2).substr(1);
00322       }
00323       else {
00324          isBot = false;
00325          event = "* "+m->getNickSender()+" is now known as "+m->getPart(2).substr(1); 
00326       }
00327       channels = ((LogFactory*)p)->getLoggedChannels() ;
00328       for (unsigned int i = 0 ; i < channels.size() ; i ++ ) {
00329          if (isBot) {
00330             ((LogFactory*)p)->log(channels[i]->getName(),event);
00331          }
00332          else {
00333             if (channels[i]->isOnChannel(m->getPart(2).substr(1)) ) {
00334                ((LogFactory*)p)->log(channels[i]->getName(),event);
00335             }  
00336          }
00337       }
00338                 return true;
00339         }
00340         bool topicHandler (Message*m,Plugin*p,BotKernel*b)
00341         {
00342       if ( ((LogFactory*)p)->hasToBeLogged(m->getSource())) {
00343          ((LogFactory*)p)->log(m->getSource(),"* "+m->getNickSender()+" has changed the topic to: "+Tools::vectorToString(m->getSplit()," ",3).substr(1));
00344       }
00345                 return true;
00346         }
00347         bool kickHandler (Message*m,Plugin*p,BotKernel*b)
00348         {
00349       if ( ((LogFactory*)p)->hasToBeLogged(m->getSource())) {
00350          if ( m->getPart(3) == b->getNick() ) {
00351             ((LogFactory*)p)->log(m->getSource(),"* You have been kicked from "+m->getSource()+" by "+m->getNickSender()+" ("+Tools::vectorToString(m->getSplit()," ",4).substr(1)+")");
00352          }
00353          else {
00354             ((LogFactory*)p)->log(m->getSource(),"* "+m->getNickSender()+" has kicked "+m->getPart(3)+" from "+m->getSource()+" ("+Tools::vectorToString(m->getSplit()," ",4).substr(1)+")");
00355          }
00356       }
00357                 return true;
00358         }
00359         bool modeHandler (Message*m,Plugin*p,BotKernel*b)
00360         {
00361       string modeAction = "";
00362         string modes = m->getPart(3) ;
00363                 char sign = '\0';
00364                 unsigned int nicksIndex = 4 ;
00365       if ( ((LogFactory*)p)->hasToBeLogged(m->getSource())) {
00366                 for (unsigned int i = 0 ; i < modes.length() ; i ++ ) {
00367                         if ((modes[i]=='+')||(modes[i]=='-')) {
00368                                 sign = modes[i];
00369                         }
00370                         else {
00371                switch(modes[i]) {
00372                   case 'o': modeAction = (string)((sign=='+')?"gives":"removes")+" channel operator status "+(string)((sign=='+')?"to ":"from ")+m->getPart(nicksIndex);
00373                   break;
00374                   case 'v': modeAction = (string)((sign=='+')?"gives":"removes")+" voice "+(string)((sign=='+')?"to ":"from ")+m->getPart(nicksIndex);
00375                   break;
00376                   case 'b': modeAction = (string)((sign=='+')?"sets":"removes")+" ban on "+m->getPart(nicksIndex);
00377                   break;
00378                   default : modeAction = (string)"sets mode "+sign+modes[i]+" "+m->getSource() ;
00379                }
00380                ((LogFactory*)p)->log(m->getSource(),"* "+m->getNickSender()+" "+modeAction);
00381                                 nicksIndex++;
00382                         }
00383                 }
00384       }
00385                 return true;
00386         }
00387         bool privmsgHandler (Message*m,Plugin*p,BotKernel*b)
00388         {
00389       string actionMsg;
00390       if (m->isPublic() ) {
00391          if ( ((LogFactory*)p)->hasToBeLogged(m->getSource())) { 
00392             if ( m->getPart(3)==(":"+(string)"\x01"+"ACTION") ) {
00393                actionMsg = Tools::vectorToString(m->getSplit()," ",4) ;
00394                ((LogFactory*)p)->log(m->getSource(),"* "+m->getNickSender()+" "+actionMsg.substr(0,actionMsg.length()-1));
00395             }
00396             else {
00397                ((LogFactory*)p)->log(m->getSource(),"<"+m->getNickSender()+"> "+Tools::vectorToString(m->getSplit()," ",3).substr(1));
00398             }
00399          } 
00400       }
00401       else {
00402          if ( ((LogFactory*)p)->hasToBeLogged("private")) { 
00403             ((LogFactory*)p)->log("private","<"+m->getNickSender()+"> "+Tools::vectorToString(m->getSplit()," ",3).substr(1));
00404          }
00405       }
00406                 return true;
00407         }
00408    bool cleanLogs (Message*m,Plugin*p,BotKernel*b) 
00409    {
00410       ((LogFactory*)p)->cleanLogs();
00411       return true;
00412    }
00413         bool sendHandler (Message*m,Plugin*p,BotKernel*b) 
00414         {
00415       string actionMsg;
00416       if (m->getPart(0) == "PRIVMSG") {
00417          if ( m->getPart(1)[0] == '#' ) { // public msg
00418             if ( ((LogFactory*)p)->hasToBeLogged(m->getPart(1))) { 
00419                if ( m->getPart(2) == (":"+(string)"\x01"+"ACTION") ) {
00420                   actionMsg = Tools::vectorToString(m->getSplit()," ",3) ;
00421                   ((LogFactory*)p)->log(m->getPart(1),"* "+b->getNick()+" "+actionMsg.substr(0,actionMsg.length()-1));
00422                }
00423                else {
00424                   ((LogFactory*)p)->log(m->getPart(1),"<"+b->getNick()+"> "+Tools::vectorToString(m->getSplit()," ",2).substr(1));
00425                }
00426             } 
00427          }
00428       }
00429       // Following lines are useless cause if the bot disconnects, then object will be deleted, and logs will be closed
00430       /*else if (m->getPart(0) == "QUIT") {
00431          ((LogFactory*)p)->destroyLogs();
00432       }*/
00433                 return true;
00434         }
00435 }

Generated on Sun Aug 16 15:28:28 2009 for trustyRC by  doxygen 1.5.8