00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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() ) {
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] == '#' ) {
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
00430
00431
00432
00433 return true;
00434 }
00435 }