bzrh.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 "bzrh.h"
00030 
00034 BZRH::BZRH(BotKernel*b)
00035 {
00036         this->author = "eponyme";
00037         this->description = "Plugin that allows queries to bugzilla.redhat.com";
00038         this->version = VERSION;
00039         this->name = "bzrh";
00040    this->bindFunction("bzsearch",IN_COMMAND_HANDLER,"bzsearch",0,120);
00041    this->bindFunction("bug",IN_COMMAND_HANDLER,"bug",0,60);
00042    this->bindFunction("",IN_ALL_MSGS,"checkBug",0,60);
00043 }
00044 
00051 vector<string> BZRH::searchBugs(string pattern,string max) 
00052 {
00053    vector<string>results ;
00054    string bug_search = Tools::urlencode(pattern);
00055    const string URL_BZRH = "https://bugzilla.redhat.com/";
00056    const string BEGIN_BUGS = "<tr class=\"bz_bugitem";
00057    const string END_BUGS = "</table>";
00058    const string BEGIN_URL = "href=\"";
00059    const string BEGIN_DESC = "<td ";
00060    string URL = URL_BZRH+"buglist.cgi?quicksearch="+bug_search;
00061    CURL *curl;  
00062    CURLcode result;
00063    string::size_type pos;
00064    string tmp;
00065    char errorBuffer[CURL_ERROR_SIZE];  
00066    string buffer;  
00067    curl = curl_easy_init();  
00068    if (curl) {  
00069       curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);  
00070       curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());  
00071       curl_easy_setopt(curl, CURLOPT_HEADER, 0);  
00072       curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);  
00073       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, BZRH::writer);  
00074       curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);  
00075       result = curl_easy_perform(curl);  
00076       curl_easy_cleanup(curl);  
00077       if (result == CURLE_OK) { 
00078          pos = buffer.find(BEGIN_BUGS);
00079          if ( pos == string::npos ) {
00080             results.clear();
00081             results.push_back("Zarro Boogs found."); 
00082             return results;
00083          }
00084          buffer = buffer.substr(pos);
00085          pos = buffer.find(END_BUGS);
00086          if ( pos == string::npos ) {
00087             results.clear();
00088             results.push_back("* Parse error (1) *"); 
00089             return results;
00090          }
00091          buffer = buffer.substr(0,pos);
00092          while(pos != string::npos ) {
00093             pos = buffer.find(BEGIN_URL);
00094             if ( pos == string::npos ) {
00095                results.clear();
00096                results.push_back("* Parse error (2) *"); 
00097                return results;
00098             }
00099             buffer = buffer.substr(pos+BEGIN_URL.length());
00100             tmp=URL_BZRH+buffer.substr(0,buffer.find("\">"));   
00101             for(unsigned int i = 0 ; i < 7 ; i ++ ) {
00102                pos = buffer.find(BEGIN_DESC);
00103                if ( pos == string::npos ) {
00104                   results.clear();
00105                   results.push_back("* Parse error (3) *"); 
00106                   return results;
00107                }
00108                buffer=buffer.substr(pos+BEGIN_DESC.length());
00109             }
00110             results.push_back(tmp+" : "+Tools::cleanHTML(buffer.substr(1,buffer.find("\n")-1)));
00111             pos= buffer.find(BEGIN_URL);
00112          }
00113          if ( (max=="") || (max=="0") || (Tools::strToUnsignedInt(max)>=results.size()) ) {
00114             return results;
00115          }
00116          else {
00117             tmp = "Too many bugs ("+Tools::intToStr(results.size())+") ! Max is "+max+". Use bz's webiste : "+URL ;
00118             results.clear();
00119             results.push_back(tmp); 
00120             return results;
00121          }
00122       }  
00123       else {   
00124          results.clear();
00125          results.push_back("* ERROR, try again later please *");
00126          return results;
00127       }  
00128    }
00129    results.clear();
00130    results.push_back("curl init error");
00131    return results;
00132 }
00133 
00140 string BZRH::getBugInfos(string bug,bool displayNotFound) 
00141 {
00142    string bug_number;
00143    if (bug[0] == '#' ) {
00144       bug_number = bug.substr(1);
00145    }
00146    else {
00147       bug_number =bug;
00148    }
00149    const string URL = "https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id="+Tools::urlencode(bug_number);
00150    const string SHOW_BUG_URL = "http://bugzilla.redhat.com/show_bug.cgi?id=";
00151    const string SUMMARY = "<th>Summary:</th>";
00152    const string BEGIN_SUMMARY = "<td colspan=3>";
00153    const string ASSIGNEE = "Assignee:</th>";
00154    const string BEGIN_ASSIGNEE = "<td>";
00155    const string STATUS = "<th>Status:</th>";
00156    const string BEGIN_STATUS = "<td>";
00157    const string SEVERITY = "<th>Severity:</th>";
00158    const string BEGIN_SEVERITY = ">";
00159    const string PRIORITY = "<th>Priority:</th>";
00160    const string BEGIN_PRIORITY = ">";
00161    string summary,assignee,status,severity,priority;
00162    string::size_type pos;
00163    CURL *curl;  
00164    CURLcode result;  
00165    char errorBuffer[CURL_ERROR_SIZE];  
00166    string buffer;  
00167    curl = curl_easy_init(); 
00168    if (curl) {  
00169       curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);  
00170       curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());  
00171       curl_easy_setopt(curl, CURLOPT_HEADER, 0);  
00172       curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);  
00173       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,BZRH::writer);  
00174       curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);  
00175       result = curl_easy_perform(curl);  
00176       curl_easy_cleanup(curl);  
00177       if (result == CURLE_OK) {  
00178          pos = buffer.find(SUMMARY);
00179          if ( pos == string::npos ) {
00180             if (displayNotFound)
00181                return "Bug not found";
00182             else 
00183                return "";
00184          }
00185          buffer = buffer.substr(pos);
00186          pos = buffer.find(BEGIN_SUMMARY) +BEGIN_SUMMARY.length();
00187          summary = buffer.substr(pos, buffer.find("</td>") - pos );
00188          pos = buffer.find(ASSIGNEE);
00189          if ( pos == string::npos ) {
00190             return "parse error";
00191          }
00192          buffer = buffer.substr(pos);
00193          pos = buffer.find(BEGIN_ASSIGNEE) +BEGIN_ASSIGNEE.length(); 
00194          assignee = buffer.substr(pos, buffer.find("</td>") - pos );
00195          pos = buffer.find(STATUS);
00196          if ( pos == string::npos ) {
00197             return "parse error";
00198          }
00199          buffer = buffer.substr(pos);
00200          pos = buffer.find(BEGIN_STATUS) + BEGIN_STATUS.length();
00201          buffer = buffer.substr(pos);
00202          status = buffer.substr(0, buffer.find("\n"));
00203          pos = buffer.find(SEVERITY);
00204          if ( pos == string::npos ) {
00205             return "parse error";
00206          }
00207          buffer = buffer.substr(pos+SEVERITY.length());
00208          pos = buffer.find(BEGIN_SEVERITY) + BEGIN_SEVERITY.length();
00209          buffer = buffer.substr(pos);
00210          severity = buffer.substr(0, buffer.find("\n"));
00211          pos = buffer.find(PRIORITY);
00212          if ( pos == string::npos ) {
00213             return "parse error";
00214          }
00215          buffer = buffer.substr(pos+PRIORITY.length());
00216          pos = buffer.find(BEGIN_PRIORITY) + BEGIN_PRIORITY.length();
00217          buffer = buffer.substr(pos);
00218          priority = buffer.substr(0, buffer.find("\n"));
00219          return "bug "+SHOW_BUG_URL+bug_number+" : "+severity+", "+priority+", "+status+", "+Tools::cleanHTML(assignee)+", "+Tools::cleanHTML(summary);
00220       }  
00221       else {   
00222          return "* ERROR, try again later please *"; 
00223       }  
00224    }
00225    return "curl init error"; 
00226 }
00227 
00228 int BZRH::writer(char *data, size_t size, size_t nmemb,string *buffer)  
00229 {  
00230    int result = 0;  
00231    if (buffer != NULL) {  
00232       buffer->append(data, size * nmemb);  
00233       result = size * nmemb;  
00234    }   
00235    return result;  
00236 }
00237 
00238 extern "C"
00239 {
00240         Plugin *contruct_bzrh(BotKernel*b)
00241         {
00242                 return new BZRH(b);
00243         }
00244         void destroy_bzrh(Plugin*p)
00245         {
00246                 delete p;
00247         }
00248         bool bzsearch (Message*m,Plugin*p,BotKernel*b)
00249         {
00250       BZRH*bz= (BZRH*)p;
00251       if ( m->isPublic() && (m->nbParts() >= 5) ) {
00252          b->send(IRCProtocol::sendMsg(m->getSource(),bz->searchBugs(Tools::vectorToString(m->getSplit()," ",4), b->getCONFF()->getValue(p->getName()+".maxbugs"))));
00253       }
00254                 return true;
00255         }
00256         bool bug (Message*m,Plugin*p,BotKernel*b)
00257         {
00258       BZRH*bz= (BZRH*)p;
00259       if ( m->isPublic() && (m->nbParts() == 5) && (m->getPart(4)!="") ) {
00260          b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(4),true)));
00261       }
00262                 return true;
00263         }
00264    bool checkBug(Message*m,Plugin*p,BotKernel*b)
00265    {
00266       const string BUG = "bug";
00267       const string URL1 = "https://bugzilla.redhat.com/show_bug.cgi?id=";
00268       const string URL2 = "http://bugzilla.redhat.com/show_bug.cgi?id=";
00269       BZRH*bz= (BZRH*)p;
00270       if (m->isPublic() && (b->getCONFF()->getValue(p->getName()+".autoreact")=="1")) {
00271          if ( m->getPart(3).find(":"+BUG) == 0 ) {
00272             b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(4),false)));
00273          }
00274          else if (m->getPart(3).find(":"+URL1) == 0 ) {
00275             b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(3).substr(URL1.length()+1),false)));
00276          }
00277          else if (m->getPart(3).find(":"+URL2) == 0 ) {
00278             b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(3).substr(URL2.length()+1),false)));
00279          }
00280          for (unsigned int i = 4 ; i < m->nbParts() ; i ++ ) {
00281             if ( m->getPart(i).find(BUG) == 0 ) {
00282                b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(i+1),false)));
00283             }
00284             else if (m->getPart(i).find(URL1) == 0 ) {
00285                b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(i).substr(URL1.length()),false)));
00286             }
00287             else if (m->getPart(i).find(URL2) == 0 ) {
00288                b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(i).substr(URL2.length()),false)));
00289             }
00290          }  
00291       }
00292       return true;   
00293    }
00294 }

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