/* * GnuDialer - Complete, free predictive dialer * * Complete, free predictive dialer for contact centers. * * Copyright (C) 2003-2008, GnuDialer Project * * Heath Schultz * Richard Lyman * Jamerson Medley * * This program is free software, distributed under the terms of * the GNU General Public License. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "queue.h" #include "Socket.h" #include "tzfilter.h" #include "tzpopulate.h" #include "statepopulate.h" #include "exceptions.h" #include "asterisk.h" #include "call.h" #include "evaluate.h" #include "etcinfo.h" #include "itos.h" #include "stoi.h" #include "dtos.h" #include "ltos.h" #include "ftos.h" #include "log.h" #include "dispo.h" #include "settings.h" #include "adminwork.h" #include "abnhelper.h" #include "color.h" #define CRASH do { fprintf(stderr, "!! Forcing immediate crash a-la abort !!\n"); *((int *)0) = 0; } while(0) const bool debugPos = false; const bool startstopProtection = true; #define HERE(x) if (debugPos) { std::cout << "Here:" << #x << std::endl; } const bool debugCampaignSettings = false; bool doTailLogs = false; bool doEvalLogs = false; const int & selectLessorOf(const int & lhs, const int & rhs) { if (lhs < rhs) { return lhs; } else { return rhs; } } bool safeMode; void sig_handler(int sig) { if (sig == SIGABRT) { // CRASH; std::cout << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_red : "") << "FATAL ERROR! Segmentation Fault!" << ((doColorize) ? normal : "") << std::endl; std::cout << "Please report this to the GnuDialer project." << std::endl; std::cout << "Please also be advised that you can start gnudialer in \"safe\" mode which will" << std::endl; std::cout << "automatically restart GnuDialer if you receive a fatal error." << std::endl; std::cout << "Type: \"gnudialer --help\" for more information." << std::endl << std::endl; } if (sig == SIGSEGV) { if (safeMode == true) { std::cout << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_red : "") << "FATAL ERROR! Segmentation Fault!" << ((doColorize) ? normal : "") << std::endl; std::cout << "You are running in safe mode, so GnuDialer will attempt to restart itself!" << std::endl << std::endl; std::system("sleep 1 && gnudialer &"); } else { // CRASH; std::cout << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_red : "") << "FATAL ERROR! Segmentation Fault!" << ((doColorize) ? normal : "") << std::endl; std::cout << "Please report this to the GnuDialer project." << std::endl; std::cout << "Please also be advised that you can start gnudialer in \"safe\" mode which will" << std::endl; std::cout << "automatically restart GnuDialer if you receive a fatal error." << std::endl; std::cout << "Type: \"gnudialer --help\" for more information." << std::endl << std::endl; } exit(0); } if (sig == SIGQUIT) { // CRASH; } if (sig == SIGCHLD) { int stat; while (waitpid (-1, &stat, WNOHANG) > 0); } return; } //remove void doOldRedirect(const std::string & channel, \ const std::string & agent, \ const std::string & campaign, \ const std::string & leadid, \ const std::string & managerUser, \ const std::string & managerPass, \ const bool & doChangeCallerId) \ { \ std::string response; if (atoi(agent.c_str()) || agent == "699" || agent == "700" && doChangeCallerId) { std::cout << campaign << ": " << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_magenta : "") << "Transferring - " << channel << " to Agent: " << agent << ((doColorize) ? normal : "") << std::endl; writeGnudialerLog(campaign + ": Transferring - " + channel + " to Agent: " + agent + ""); ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents:off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Redirect\r\n"; AsteriskRedir << "Channel: " + channel + "\r\n"; AsteriskRedir << "Exten: " + agent + "\r\n"; if (!doChangeCallerId) { AsteriskRedir << "Context: agent\r\n"; } else { AsteriskRedir << "Context: closerloop\r\n"; } AsteriskRedir << "Priority: 1\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; usleep(10000000); } } void doRedirect(const std::string & channel, \ const std::string & agent, \ const std::string & campaign, \ const std::string & leadid, \ const std::string & managerUser, \ const std::string & managerPass, \ const std::string & transferContext) \ { \ std::string response; if (atoi(agent.c_str())) { std::cout << campaign << ": " << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_magenta : "") << "Transferring - " << channel << " to Exten: " << agent << " Context: " << transferContext << ((doColorize) ? normal : "") << std::endl; writeGnudialerLog(campaign + ": Transferring - " + channel + " to Exten: " + agent + " Context: " + transferContext + ""); ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents:off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Redirect\r\n"; AsteriskRedir << "Channel: " + channel + "\r\n"; AsteriskRedir << "Exten: " + agent + "\r\n"; AsteriskRedir << "Context: " + transferContext + "\r\n"; AsteriskRedir << "Priority: 1\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; usleep(10000000); } } void writeTailLogs(const std::string & theBlock) { std::cout << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_magenta : "") << "writeTailLogs - (PARSE ERROR) - " << theBlock << ((doColorize) ? normal : "") << std::endl; std::system("/usr/bin/tail -30 /var/log/asterisk/debug /var/log/asterisk/messages /var/log/asterisk/gnudialer.log >>/tmp/parse.log"); } void doPrintSale(const std::string & theText, \ const std::string & theCampaign, \ const std::string & theLeadid) \ { \ usleep(3000000); std::cout << theCampaign << ": " << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_magenta : "") << "writeCampaignSale - " << theLeadid << ((doColorize) ? normal : "") << std::endl; writeCampaignSale(theText,theCampaign,theLeadid); } void doSetVarTransfer(const std::string & channel, \ const std::string & agent, \ const std::string & managerUser, \ const std::string & managerPass) \ { \ std::string response; std::cout << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_magenta : "") << "doSetVarTransfer - " << channel << ((doColorize) ? normal : "") << std::endl; //writeGnudialerLog(campaign + ": doSetVarTransfer - " + channel + " from Agent: " + agent + ""); ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents:off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: SetVar\r\n"; AsteriskRedir << "Channel: " + channel + "\r\n"; AsteriskRedir << "Variable: ISTRANSFER=TRANSFER\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; if (response == "Success") { std::cout << "doSetVarTransfer - SUCCESSFUL " << channel << std::endl; } AsteriskRedir >> response; usleep(1); } void doHangupCall(const std::string & channel, \ const std::string & agent, \ const std::string & managerUser, \ const std::string & managerPass) \ { \ std::string response; std::cout << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_magenta : "") << "doHangupCall - " << channel << ((doColorize) ? normal : "") << std::endl; writeGnudialerLog("doHangupCall - " + channel + " from Agent: " + agent + ""); ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents:off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Hangup\r\n"; AsteriskRedir << "Channel: " + channel + "\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; usleep(1); } void doSend2Conf(const std::string & channel, \ const std::string & agent, \ const std::string & clid, \ const std::string & campaign, \ const std::string & leadid, \ const bool & usecloser, \ const std::string & managerUser, \ const std::string & managerPass) \ { \ std::string response; std::cout << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_magenta : "") << "doSend2Conf - " << channel << ((doColorize) ? normal : "") << std::endl; writeGnudialerLog("doSend2Conf - " + channel + " from Agent: " + agent + ""); ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents:off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Redirect\r\n"; AsteriskRedir << "Channel: " + channel + "\r\n"; AsteriskRedir << "Exten: " + agent + "" + clid + "\r\n"; AsteriskRedir << "Context: conf\r\n"; AsteriskRedir << "Priority: 1\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; usleep(1); } void do3rdParty(const std::string & channel, \ const std::string & agent, \ const std::string & clid, \ const std::string & campaign, \ const std::string & leadid, \ const bool & usecloser, \ const std::string & managerUser, \ const std::string & managerPass) \ { \ std::string response; std::string useCloser = "false"; if (usecloser) { useCloser = "true"; } std::cout << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_magenta : "") << "do3rdParty - " << channel << ((doColorize) ? normal : "") << std::endl; writeGnudialerLog("do3rdParty - " + channel + " from Agent: " + agent + ""); ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents:off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Originate\r\n"; AsteriskRedir << "Channel: " + channel + "\r\n"; AsteriskRedir << "Exten: " + agent + "" + clid + "\r\n"; AsteriskRedir << "Context: conf\r\n"; AsteriskRedir << "Priority: 1\r\n"; AsteriskRedir << "Variable: __CAMPAIGN=" + campaign +"\r\n"; AsteriskRedir << "Variable: __LEADID=" + leadid + "\r\n"; AsteriskRedir << "Variable: __PHONENUM=" + clid + "\r\n"; AsteriskRedir << "CallerID: ~" + campaign + "-" + leadid + "-" + useCloser + "~ <" + clid + ">\r\n"; //AsteriskRedir << "Async: true\r\n"; AsteriskRedir << "\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; usleep(1); } void doJoinConf(const std::string & channel, \ const std::string & agent, \ const std::string & clid, \ const std::string & campaign, \ const std::string & leadid, \ const bool & usecloser, \ const std::string & managerUser, \ const std::string & managerPass) \ { \ std::string response; std::string useCloser = "false"; if (usecloser) { useCloser = "true"; } unsigned int sliceend = channel.find("-",0); std::string tempSlice = channel.substr(0,sliceend); //std::string tempSlice = channel; std::cout << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_magenta : "") << "doJoinConf - " << tempSlice << ((doColorize) ? normal : "") << std::endl; writeGnudialerLog("doJoinConf - " + tempSlice + " from Agent: " + agent + ""); ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents:off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Originate\r\n"; AsteriskRedir << "Channel: " + tempSlice + "\r\n"; AsteriskRedir << "Exten: " + agent + "" + clid + "\r\n"; AsteriskRedir << "Context: conf\r\n"; AsteriskRedir << "Priority: 1\r\n"; AsteriskRedir << "Variable: __CAMPAIGN=" + campaign +"\r\n"; AsteriskRedir << "Variable: __LEADID=" + leadid + "\r\n"; AsteriskRedir << "Variable: __PHONENUM=" + clid + "\r\n"; AsteriskRedir << "CallerID: ~" + campaign + "-" + leadid + "-" + useCloser + "~ <" + clid + ">\r\n"; //AsteriskRedir << "Async: true\r\n"; AsteriskRedir << "\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; usleep(1); } void doSendLoggedIn(const std::string & agent, \ const std::string & paused, \ const std::string & managerUser, \ const std::string & managerPass) \ { \ std::string response; std::cout << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_magenta : "") << "doSendLoggedIn - " << agent << ((doColorize) ? normal : "") << std::endl; writeGnudialerLog("doSendLoggedIn - Agent: " + agent + ""); ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents:off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: SendEvent\r\n"; AsteriskRedir << "Event: AlreadyLoggedIn\r\n"; AsteriskRedir << "Body: Agent/" + agent + " Paused: " + paused + "\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; usleep(1); } void doMonitorStart(const std::string & channel, \ const std::string & agent, \ const std::string & campaign, \ const std::string & leadid, \ const std::string & managerUser, \ const std::string & managerPass) \ { \ std::string response; std::cout << "doMonitorStart - " << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << channel << std::endl; writeGnudialerLog("doMonitorStart - " + channel + " from Agent: " + agent + ""); ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents:off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Monitor\r\n"; AsteriskRedir << "Channel: " + channel + "\r\n"; AsteriskRedir << "File: " + agent + "-" + campaign + "-" + leadid + "\r\n"; AsteriskRedir << "Mix: 1\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; usleep(1); } void doMonitorStop(const std::string & channel, \ const std::string & agent, \ const std::string & campaign, \ const std::string & leadid, \ const std::string & managerUser, \ const std::string & managerPass) \ { \ std::string response; std::cout << "doMonitorStop - " << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << channel << std::endl; writeGnudialerLog("doMonitorStop - " + channel + " from Agent: " + agent + ""); ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents:off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: StopMonitor\r\n"; AsteriskRedir << "Channel: " + channel + "\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; usleep(1); } void doAgentPause(const std::string & agent, \ const std::string & campaign, \ const std::string & paused, \ const std::string & managerUser, \ const std::string & managerPass) \ { \ std::string response; std::cout << "doAgentPause - " << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << " Agent: " << agent << " Paused: " << paused << std::endl; writeGnudialerLog("doAgentPause - Agent: " + agent + " Paused: " + paused + ""); ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents:off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: QueuePause\r\n"; AsteriskRedir << "Interface: Agent/" + agent + "\r\n"; AsteriskRedir << "Queue: " + campaign + "\r\n"; AsteriskRedir << "Paused: " + paused + "\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; usleep(1); } void sendMgrEvent(const std::string & eventname, const std::string & eventbody, const std::string & managerUser, const std::string & managerPass) { std::string response; //std::cout << "sendMgrEvent - " << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << " Event: " << eventname << " Body: " << eventbody << std::endl; ClientSocket AsteriskRedir(getMainHost(),getMainPort()); AsteriskRedir >> response; AsteriskRedir << "Action: Login\r\nUserName: " + managerUser + "\r\nSecret: " + managerPass + "\r\nEvents: off\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: SendEvent\r\n"; AsteriskRedir << "Event: " + eventname + "\r\n"; AsteriskRedir << "Body: " + eventbody + "\r\n\r\n"; AsteriskRedir >> response; AsteriskRedir << "Action: Logoff\r\n\r\n"; AsteriskRedir >> response; usleep(1); //usleep(10000000); } int main(int argc, char** argv) { usleep(100000); safeMode = false; bool daemonMode = false; bool gDebug = false; bool gLog = false; int gTZOffset = 0; unsigned int gMaxlines = 0; signal(SIGCHLD,sig_handler); signal(SIGSEGV,sig_handler); signal(SIGABRT,sig_handler); signal(SIGQUIT,sig_handler); //set default console color to white on black std::cout << ((doColorize) ? fg_light_white : "") << std::endl; for (int i = 1; i < argc; ++i) { const std::string arg(argv[i]); if (arg == "stop" || \ arg == "-stop" || \ arg == "--stop") \ { \ writeGnudialerLog("GnuDialer: Stopped"); std::cout << ((doColorize) ? fg_light_green : "") << "GnuDialer: Stopped" << ((doColorize) ? normal : "") << std::endl; std::system(("killall " + std::string(argv[0])).c_str()); exit(0); } if (arg == "--tzpopulate" || \ arg == "tzpopulate" || \ arg == "-tzpopulate") \ { \ if (i+1 < argc) { tzpopulate(argv[i+1]); statepopulate(argv[i+1]); return 0; } else { std::cout << "GnuDialer: tzpopulate - Error! Missing campaign name!" << std::endl; return 1; } } if (arg == "-h" || \ arg == "--help" || \ arg == "-help") \ { \ std::cout << std::endl << std::endl; std::cout << "Usage: gnudialer " << std::endl << std::endl; std::cout << "\t--safe (or -s) Starts gnudialer in \"safe\" mode which makes in auto-restart on fatal error." << std::endl; std::cout << "\t--tzpopulate Will create and populate the fields necessary for a campaign." << std::endl; std::cout << "\t--help (or -h) This help screen." << std::endl; std::cout << "\t--stop (or -stop) Unconditionally stop the dialer." << std::endl; std::cout << "\t--no-daemon (or -nd) Do not run as a daemon." << std::endl; std::cout << "\t--daemon (or -d) Do run as a daemon. (no longer the fault)" << std::endl; std::cout << std::endl << std::endl; return 0; } if (arg == "-s" || \ arg == "--safe" || \ arg == "-safe") \ { \ std::cout << "GnuDialer: SAFE MODE enabled!" << std::endl; safeMode = true; } if (arg == "-nd" || arg == "--no-daemon" || arg == "-no-daemon") { daemonMode = false; } if (arg == "-d" || arg == "--daemon" || arg == "-daemon") { daemonMode = true; } } if (daemonMode) { int daemonizer = 0; daemonizer = fork(); if (daemonizer<0) { std::cout << "GnuDialer: Error setting up daemon process... Aborting." << std::endl; exit(1); } if (daemonizer > 0) { exit(0); } } umask(017); chdir("/tmp"); int lfp = open("gnudialer.lock",O_RDWR|O_CREAT,0660); if (lfp<0) { std::cout << "GnuDialer: Error opening lock file!" << std::endl; exit(1); } if (lockf(lfp,F_TLOCK,0)<0) { std::cout << "GnuDialer: process already running!" << std::endl; exit(0); } char str[80]; sprintf(str,"%d\n",getpid()); int parentPID = getpid(); write(lfp,str,strlen(str)); bool isAHoliday; try { isAHoliday = isHoliday(); } catch(const xFileOpenError & e) { std::cout << "GnuDialer: Exception! Unable to open " << e.GetFilename() << "!" << std::endl; return 1; } // this creates a few placeholder campaigns if they // do not exist. // (recreates them if deleted and gnudialer restarted) if (!existsQueue("CLOSER")) { createQueue("CLOSER"); addBasicSettings("CLOSER"); reloadQueues(); } if (!existsQueue("INBOUND")) { createQueue("INBOUND"); addBasicSettings("INBOUND"); reloadQueues(); } if (!existsQueue("DNC")) { createQueue("DNC"); addBasicSettings("DNC"); reloadQueues(); } addGlobalSettings("general"); Queue TheQueueGlobals; TheQueueGlobals.ParseQueue("general"); try { gDebug = TheQueueGlobals.GetSetting("debug").GetBool(); std::cout << "Global Debug: " << gDebug << std::endl; gLog = TheQueueGlobals.GetSetting("log").GetBool(); std::cout << "Global Log: " << gLog << std::endl; gTZOffset = TheQueueGlobals.GetSetting("tzoffset").GetInt(); std::cout << "Global TZOffset: " << gTZOffset << std::endl; gMaxlines = TheQueueGlobals.GetSetting("gmaxlines").GetInt(); std::cout << "Global Maxlines: " << gMaxlines << std::endl; } catch (xLoopEnd e) { std::cout << "Caught xLoopEnd while getting TheQueueGlobals..." << std::endl; std::cout << e.what(); std::cout << std::endl << std::endl; } std::string mainHost = getMainHost(); MYSQL *mysql = NULL; MYSQL_RES *result; MYSQL_ROW row; mysql = mysql_init(NULL); if(mysql == NULL) { std::cout << "GnuDialer: MySql init failed!" << std::endl; return 1; } if(!mysql_real_connect(mysql, getMySqlHost().c_str(), \ getMySqlUser().c_str(), \ getMySqlPass().c_str(), \ getDbName().c_str(), \ 3306, NULL, 0)) \ { \ std::cout << "GnuDialer: MySql connection failed!" << std::endl; return 1; } //replace this section with tzoffset (global) option //std::string tzquery = "SELECT (CONCAT(YEAR(NOW()),LPAD(MONTH(NOW()),2,0),LPAD(DAY(NOW()),2,0),LPAD(HOUR(NOW()),2,0)) - CONCAT(YEAR(UTC_DATE()),LPAD(MONTH(UTC_DATE()),2,0),LPAD(DAY(UTC_DATE()),2,0),LPAD(HOUR(UTC_TIME())+1,2,0)) - IF(HOUR(NOW())>12,84,0))"; //std::string tzquery = "SELECT (CONCAT(YEAR(NOW()),LPAD(MONTH(NOW()),2,0),LPAD(DAY(NOW()),2,0),LPAD(HOUR(NOW()),2,0)) - CONCAT(YEAR(UTC_DATE()),LPAD(MONTH(UTC_DATE()),2,0),LPAD(DAY(UTC_DATE()),2,0),LPAD(HOUR(UTC_TIME())+1,2,0)) )"; //std::string tzquery = "SELECT FLOOR(TIME_TO_SEC(NOW())/3600) - FLOOR(TIME_TO_SEC(UTC_TIMESTAMP())/3600)-1"; //if(mysql_query(mysql, tzquery.c_str()) != 0) //{ // std::cout << "Error selecting records !" << std::endl; //} //else //{ // result = mysql_use_result(mysql); // row = mysql_fetch_row(result); //tzoffset = stoi(std::string(row[0])); // tzoffset = -8; //if (debug) //{ // std::cout << "Timezone offset: " << tzoffset << std::endl; //} // mysql_free_result(result); //} // to here try { // Not nested for convenience. if (gLog) { writeGnudialerLog("GnuDialer: Started"); } if (gDebug) { std::cout << ((doColorize) ? fg_light_green : "") << "GnuDialer: Started" << ((doColorize) ? normal : "") << std::endl; std::cout << "GnuDialer: loading gdhosts.conf" << std::endl; } CallCache * TheCallCache; try { TheCallCache = new CallCache(); } catch(xTooFewFields) { std::cout << "Exception: Too few fields in gdhosts.conf!" << std::endl; return 1; } catch(xTooManyFields) { std::cout << "Exception: Too many fields in gdhosts.conf!" << std::endl; return 1; } catch(xInvalidWeightValue) { std::cout << "Exception: Invalid weight value in gdhosts.conf!" << std::endl; return 1; } catch(const xFileOpenError & e) { std::cout << "Exception: Error opening " << e.GetFilename() << "!" << std::endl; return 1; } catch(xNoHostsDefined) { std::cout << "Exception: No hosts defined in gdhosts.conf!" << std::endl; return 1; } if (gDebug) { std::cout << "GnuDialer: loading gdhosts.conf (done)" << std::endl; } std::string response, block, queue, mode, calltoday, usednc, query, tzearliest, tzlatest, allowedhours; std::string callerid, channel; std::string tempagent, usecloser,closercam; std::string dspmode, trunk, dialprefix, vmmessage, sfmessage, extravars, transfer, filter, usecallback, usetzfilter; bool debug; int skip; std::string f_areacode, f_areacode_prefix, f_zipcode, orderby; std::string managerUser = getManagerUsername(); std::string managerPass = getManagerPassword(); std::stringstream BlockStream; unsigned int maxlines = 0, timeout = 0, linesdialing = 0, totallinesdialing = 0; //unsigned int gMaxlines = 0; unsigned int availagents = 0, onlineagents = 0, dialableagents = 0; unsigned int linestodial = 0, counter = 0; unsigned int pos = 0, end = 0, pos2 = 0, end2 = 0; unsigned long int calls = 0, agentcalls = 0, abandons = 0; int pid = 0; double maxratio = 0.0, maxabandons = 0.0, tmpAbnPerc = 0.0; double fudge = 20.0; std::string infoString; ClientSocket AsteriskManager(getMainHost(),getMainPort()); AsteriskManager.setRecvTimeout(500); AsteriskManager >> response; AsteriskManager << "Action: login\r\nUsername: " + managerUser + "\r\nSecret: " + managerPass + "\r\n\r\n"; AsteriskManager >> response; QueueList TheQueues; AgentList TheAgents; TheQueues.ParseQueues(); TheAgents.ParseAgentList(); if (gDebug) { std::cout << "GnuDialer: Querying Asterisk Agents" << std::endl; } TheAgents.Initialize(managerUser,managerPass); if (gDebug) { std::cout << "GnuDialer: Querying Asterisk Agents (done)" << std::endl; } std::string tempCheckCampaign; for (int i = 0; i < TheQueues.size(); i++) { tempCheckCampaign = TheQueues.at(i).GetName(); if (gDebug) { std::cout << tempCheckCampaign << ": Settings Pre-Check " << std::endl; } addBasicSettings(tempCheckCampaign); if (gDebug) { std::cout << tempCheckCampaign << ": Resetting Filters " << std::endl; } resetFilterSettings(tempCheckCampaign); } TheQueues.ParseQueues(); timeval tv; unsigned long int timeSinceLastQueueUpdate = 0, currentTime = 0; unsigned long int myepoch = 0; //unsigned long int lastEvalSend = 0; char mytimestamp[14]; char cur24HourTime[4]; std::string theTimeStamp; std::string the24HourTime; try { gDebug = TheQueueGlobals.GetSetting("debug").GetBool(); gLog = TheQueueGlobals.GetSetting("log").GetBool(); gMaxlines = TheQueueGlobals.GetSetting("gmaxlines").GetInt(); } catch (xLoopEnd e) { std::cout << "Caught exception while trying to get debug & log settings!" << std::endl; std::cout << e.what(); std::cout << std::endl << std::endl; } //testing area for setselected returning agent to ready //TheAgents.where(300).SetSelected(); for(unsigned long int t = 0; true; t++) { gettimeofday(&tv,NULL); currentTime = tv.tv_sec % 1000000; time_t thetime = tv.tv_sec; myepoch = tv.tv_sec; tm * ptm = localtime(&thetime); sprintf(mytimestamp, "%4.4i%2.2i%2.2i%2.2i%2.2i%2.2i", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); theTimeStamp = std::string(mytimestamp); sprintf(cur24HourTime, "%2.2i%2.2i", ptm->tm_hour, ptm->tm_min); the24HourTime = std::string(cur24HourTime); // set to 1 if you want a visual loop indicator if (0) { std::cout << myepoch<< ":" << ((doColorize) ? fg_light_white : "")<< " [" << parentPID << ":" << getpid() << "] " << ((doColorize) ? fg_light_yellow : "") << " Still Running! " << ((doColorize) ? fg_light_cyan : "") << "(" << currentTime << ") HHMM: " << the24HourTime << " Timestamp: " << theTimeStamp << ((doColorize) ? normal : "") << std::endl; } // set even to run this section which was part of the old stuff that would constantly // flush and load new agent/queue conf info (which was a super resource hog, and // because of the flushing would cause segfaults). This code will be gone in the future. if (1 == 2) { \ if (gDebug) { std::cout << myepoch << ":" << ((doColorize) ? fg_light_white : "")<< " [" << parentPID << ":" << getpid() << "] " << ((doColorize) ? fg_light_yellow : "") << "Updating Campaign Settings " << ((doColorize) ? fg_light_cyan : "") << "(" << currentTime << ") HHMM: " << the24HourTime << " Timestamp: " << theTimeStamp << ((doColorize) ? normal : "") << std::endl; } TheAgents.ParseAgentList(); TheQueues.ParseQueues(); //Queue TheQueueGlobals; TheQueueGlobals.ParseQueue("general"); try { gDebug = TheQueueGlobals.GetSetting("debug").GetBool(); gLog = TheQueueGlobals.GetSetting("log").GetBool(); gMaxlines = TheQueueGlobals.GetSetting("gmaxlines").GetInt(); } catch (xLoopEnd e) { std::cout << "Caught exception while trying to get debug & log settings!" << std::endl; std::cout << e.what(); std::cout << std::endl << std::endl; } timeSinceLastQueueUpdate = currentTime; } // setting up the asterisk manager event/responses response = ""; AsteriskManager >> response; if (response.empty()) { response = "Event: NoEvent\r\n\r\n"; } BlockStream.clear(); BlockStream.str(response); // TRIGGER LOOP for (std::string tempLine; std::getline(BlockStream,tempLine,'\n'); ) { tempLine = tempLine.substr(0,tempLine.length()-1); // strip '\r' if (tempLine.empty()) { pos = 0; end = 0; pos2 = 0; end2 = 0; // obviously this section is not being used, but someday i will get around to // using it, as it would help to modularize things. // // Begin block analysis //const std::string param(const std::string & block, const std::string & type) { // int pos = 0, len = 0; // if (block.find(type + ": ",0) == std::string::npos) { // return static_cast(""); // } else { // pos = block.find(type + ": ",0) + 2; // len = type.length(); // return block.substr(pos + len,block.find("\n",pos) - (pos + len)); // } // } //*********************************************************************************** // THIS CAUSES GNUDIALER TO BE KILLED WHEN ASTERISK WAS SHUTDOWN // THIS DOES NOT HANDLE OTHER ASTERISK EXITS, LIKE CORES if (block.find("Event: Shutdown",0) != std::string::npos) { if (gDebug) { std::cout << "GnuDialer: Asterisk Shutdown - GnuDialer Killed" <ListLinesDialing(); if (gDebug) { std::cout << "Event: ListLinesDialing - " << theTimeStamp << std::endl; } if (gLog) { writeGnudialerLog("Event: ListLinesDialing "); } } if (block.find("Event: FreeLinesDialing",0) != std::string::npos) { TheCallCache->FreeLinesDialing(); if (gDebug) { std::cout << "Event: FreeLinesDialing - " << theTimeStamp << std::endl; } if (gLog) { writeGnudialerLog("Event: FreeLinesDialing "); } } //*********************************************************************************** if ((block.find("Event: OriginateFailure",0) != std::string::npos || (block.find("Event: OriginateResponse",0) != std::string::npos && block.find("Response: Failure",0) != std::string::npos)) && block.find("Context: gdincoming",0) != std::string::npos) { int iTheReason = 0; std::string theReason, theCallerIDName, theCampaign, theLeadid; std::string theDispo = "0"; std::string theReasonDesc = "Unknown"; if (block.find("Reason: ",0) != std::string::npos) { pos = block.find("Reason: ",0) + 8; end = block.find("\n",pos); theReason = block.substr(pos,end-pos); iTheReason = atoi(theReason.c_str()); } if (block.find("CallerIDName: ",0) != std::string::npos && block.find("~",0) != std::string::npos && !theReason.empty()) { pos = block.find("CallerIDName: ",0) + 15; end = block.find("\n",pos); theCallerIDName = block.substr(pos,end-pos); if (block.find("~",0) != std::string::npos) { pos = theCallerIDName.find("~",end) + 1; end = theCallerIDName.find("-",pos+1); pos2 = end + 1; end2 = theCallerIDName.find("-",pos2); theCampaign = theCallerIDName.substr(pos,end-pos); theLeadid = theCallerIDName.substr(pos2,end2-pos2); } if (!theCampaign.empty() && !theLeadid.empty() && TheQueues.exists(theCampaign)) { //TheCallCache->SetHungup(theCampaign,theLeadid); //unknown failure, disconnect if (theReason == "0") { theDispo = "-7"; writeDBString(theCampaign,theLeadid,"disposition='" + theDispo + "'"); TheQueues.rWhere(theCampaign).IncrementDisconnects(); } // AST_CONTROL_RINGING //timed out while ringing, no answer if (theReason == "3") { theDispo = "-2"; writeDBString(theCampaign,theLeadid,"disposition='" + theDispo + "'"); TheQueues.rWhere(theCampaign).IncrementNoanswers(); } // AST_CONTROL_BUSY //busy if (theReason == "5") { theDispo = "-4"; writeDBString(theCampaign,theLeadid,"disposition='" + theDispo + "'"); TheQueues.rWhere(theCampaign).IncrementBusies(); } // AST_CONTROL_HANGUP //hangup, no answer if (theReason == "1") { theDispo = "-2"; writeDBString(theCampaign,theLeadid,"disposition='" + theDispo + "'"); TheQueues.rWhere(theCampaign).IncrementNoanswers(); } // AST_CONTROL_CONGESTION //congestion if (theReason == "8") { theDispo = "-5"; writeDBString(theCampaign,theLeadid,"disposition=(((disposition=-5)*-2)-5)"); TheQueues.rWhere(theCampaign).IncrementCongestions(); } if (theDispo == "0") { std::cout << theCampaign << ": " << ((doColorize) ? fg_light_red : "") << "OriginateFailure - " << ((doColorize) ? fg_yellow : "") << theReason << " (" << dispo2long(stoi(theDispo)) << ") " << ((doColorize) ? normal : "") << std::endl; } //stats testing TheQueues.rWhere(theCampaign).WriteAbn(); if (gDebug) { std::cout << theCampaign << ": " << ((doColorize) ? fg_light_red : "") << "OriginateFailure - " << ((doColorize) ? fg_yellow : "") << "theLeadid: " << theLeadid << " theReason: " << theReason << " theDispo: " << theDispo << " (" << dispo2long(stoi(theDispo)) << ") " << ((doColorize) ? normal : "") << std::endl; } if (gLog) { writeGnudialerLog(theCampaign + ": OriginateFailure - theLeadid: " + theLeadid + " theReason: " + theReason + " theDispo: " + theDispo); } } else { std::cout << ((doColorize) ? fg_light_red : "") << "OriginateFailure: PARSE ERROR " << ((doColorize) ? normal : "") << std::endl; if (gLog) { writeGnudialerLog("OriginateFailure - PARSE ERROR - Something Empty (block: " + block + ")"); } if (doTailLogs) { pid = fork(); if (pid == 0) { writeTailLogs(block); exit(0); } if (pid == -1) { throw xForkError(); } } } } else { if (gLog) { writeGnudialerLog("OriginateFailure - PARSE ERROR - No CallerIDName or Empty Reason (block: " + block + ")"); } if (doTailLogs) { pid = fork(); if (pid == 0) { writeTailLogs(block); exit(0); } if (pid == -1) { throw xForkError(); } } } } //*********************************************************************************** if ((block.find("Event: OriginateSuccess",0) != std::string::npos || (block.find("Event: OriginateResponse",0) != std::string::npos && block.find("Response: Success",0) != std::string::npos)) && block.find("Context: gdincoming",0) != std::string::npos) { int iTheReason = 0; std::string theReason, theCallerIDName, theCampaign, theLeadid; std::string theDispo = "-3"; if (block.find("Reason: ",0) != std::string::npos) { pos = block.find("Reason: ",0) + 8; end = block.find("\n",pos); theReason = block.substr(pos,end-pos); iTheReason = atoi(theReason.c_str()); } if (block.find("CallerIDName: ",0) != std::string::npos && block.find("~",0) != std::string::npos && !theReason.empty()) { pos = block.find("CallerIDName: ",0) + 15; end = block.find("\n",pos); theCallerIDName = block.substr(pos,end-pos); if (block.find("~",0) != std::string::npos) { pos = theCallerIDName.find("~",end) + 1; end = theCallerIDName.find("-",pos+1); pos2 = end + 1; end2 = theCallerIDName.find("-",pos2); theCampaign = theCallerIDName.substr(pos,end-pos); theLeadid = theCallerIDName.substr(pos2,end2-pos2); } if (!theCampaign.empty() && !theLeadid.empty() && TheQueues.exists(theCampaign)) { // answer, we'll assume voicemail/answering machine // if it passes talkdetect it will be sent to agent // or abandons++ if (theReason == "4") { theDispo = "-3"; writeDBString(theCampaign,theLeadid,"disposition='" + theDispo + "'"); TheQueues.rWhere(theCampaign).IncrementAnsmachs(); } //timed out while ringing, no answer if (theReason == "3") { theDispo = "-2"; writeDBString(theCampaign,theLeadid,"disposition='" + theDispo + "'"); } //busy if (theReason == "5") { theDispo = "-4"; writeDBString(theCampaign,theLeadid,"disposition='" + theDispo + "'"); } //hangup, no answer if (theReason == "1") { theDispo = "-2"; writeDBString(theCampaign,theLeadid,"disposition='" + theDispo + "'"); } //congestion if (theReason == "8") { theDispo = "-5"; writeDBString(theCampaign,theLeadid,"disposition='" + theDispo + "'"); } if (theDispo == "0") { std::cout << theCampaign << ": " << ((doColorize) ? fg_light_red : "") << "OriginateSuccess - " << ((doColorize) ? fg_yellow : "") << "UNKNOWN REASON - " << theReason << ((doColorize) ? normal : "") << std::endl; if (gLog) { writeGnudialerLog(theCampaign + ": OriginateSuccess - UNKNOWN REASON - theLeadid: " + theLeadid + " theReason: " + theReason + " theDispo: " + theDispo); } } //stats testing TheQueues.rWhere(theCampaign).WriteAbn(); if (gDebug) { std::cout << theCampaign << ": " << ((doColorize) ? fg_light_green : "") << "OriginateSuccess - " << ((doColorize) ? fg_yellow : "") << "theLeadid: " << theLeadid << " theReason: " << theReason << " theDispo: " << theDispo << " (" << dispo2long(stoi(theDispo)) << ") " << ((doColorize) ? normal : "") << std::endl; } if (gLog) { writeGnudialerLog(theCampaign + ": OriginateSuccess - theLeadid: " + theLeadid + " theReason: " + theReason + " theDispo: " + theDispo); } } else { std::cout << ((doColorize) ? fg_light_red : "") << "OriginateSuccess: PARSE ERROR " << ((doColorize) ? normal : "") << std::endl; if (gLog) { writeGnudialerLog("OriginateSuccess - PARSE ERROR - Something Empty (block: " + block + ")"); } if (doTailLogs) { pid = fork(); if (pid == 0) { writeTailLogs(block); exit(0); } if (pid == -1) { throw xForkError(); } } } } else { if (gLog) { writeGnudialerLog("OriginateSuccess - PARSE ERROR - No CallerIDName or Empty Reason (block: " + block + ")"); } if (doTailLogs) { pid = fork(); if (pid == 0) { writeTailLogs(block); exit(0); } if (pid == -1) { throw xForkError(); } } } } //*********************************************************************************** if (block.find("Event: Agentlogin",0) != std::string::npos || block.find("Event: Agentcallbacklogin",0) != std::string::npos) { if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; end = block.find("\n",pos); std::string theAgent, theAgentLoginChannel; theAgent = block.substr(pos,end-pos); if (gDebug) { std::cout << "theAgent: " << theAgent << " - login attempt" << std::endl; } if (block.find("Channel: ",0) != std::string::npos) { pos = block.find("Channel: ",0) + 9; end = block.find("\n",pos); //end = block.find("-",pos); //end = block.find("is",pos-1); theAgentLoginChannel = block.substr(pos,end-pos); TheAgents.where(atoi(theAgent.c_str())).SetLoginChannel(theAgentLoginChannel); if (gDebug) { std::cout << "Event AgentLogin: theAgentLoginChannel - " << theAgentLoginChannel << std::endl; } } if (TheAgents.exists(atoi(theAgent.c_str()))) { if (gDebug) { std::cout << "theAgent: " << ((doColorize) ? fg_light_green : "") << theAgent << " - logged in" << ((doColorize) ? normal : "") << std::endl; } TheAgents.where(atoi(theAgent.c_str())).SetLoggedIn(); if (gLog) { writeGnudialerLog("SetLoggedIn: " + theAgent); } } else { std::cout << "AgentLogin: Error parsing agent number!" << std::endl; } } } //*********************************************************************************** if (block.find("Event: Agentlogoff",0) != std::string::npos || block.find("Event: Agentcallbacklogoff",0) != std::string::npos) { if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; end = block.find("\n",pos); std::string theAgent, theAgentLoginChannel; theAgent = block.substr(pos,end-pos); if (gDebug) { std::cout << "theAgent: " << theAgent << " - logoff attempt" << std::endl; } if (block.find("Channel: ",0) != std::string::npos) { pos = block.find("Channel: ",0) + 9; end = block.find("\n",pos); theAgentLoginChannel = block.substr(pos,end-pos); TheAgents.where(atoi(theAgent.c_str())).SetLoginChannel("hungup"); if (gDebug) { std::cout << "Event AgentLogoff: theAgentLoginChannel - " << theAgentLoginChannel << std::endl; } } if (TheAgents.exists(atoi(theAgent.c_str()))) { TheAgents.where(atoi(theAgent.c_str())).SetOffline(); if (gDebug) { std::cout << "theAgent: " << ((doColorize) ? fg_light_green : "") << theAgent << " - logged off" << ((doColorize) ? normal : "") << std::endl; } if (gLog) { writeGnudialerLog("SetOffline: " + theAgent); } } else { std::cout << "AgentLogoff: Error parsing agent number!" << std::endl; } } } //*********************************************************************************** if (block.find("Event: REMOVEFOROLDUSAGEUnlink",0) != std::string::npos && \ block.find("Agent/",0) != std::string::npos) \ { \ pos = block.find("Agent/",0) + 6; end = block.find("\n",pos); std::string theAgent, theCampaign; theAgent = block.substr(pos,end-pos); if (gDebug) { std::cout << "theAgent: " << theAgent << " - unlink attempt" << std::endl; } if (TheAgents.exists(atoi(theAgent.c_str()))) { theCampaign = TheAgents.where(atoi(theAgent.c_str())).GetCampaign(); if (gDebug) { std::cout << theCampaign << ": " << ((doColorize) ? fg_light_green : "") << "theAgent - " << theAgent << " - unlinked" << ((doColorize) ? normal : "") << std::endl; } if (theCampaign == "initialized") { TheAgents.where(atoi(theAgent.c_str())).SetOnWait(false,false,TheAgents); if (gLog) { writeGnudialerLog("SetOnWait: " + theAgent); } } else { //TheQueues.where(TheAgents.where(atoi(theAgent.c_str())).GetCampaign()).AddTalkTime(TheAgents.where(atoi(theAgent.c_str())).SetOnWait(false,false,TheAgents)); TheAgents.where(atoi(theAgent.c_str())).writeAgentLog(TheAgents); if (gLog) { writeGnudialerLog("SetOnWait: " + theAgent); } } } else { std::cout << "Unlink: Error parsing agent number!" << std::endl; } } //*********************************************************************************** if (block.find("Event: Link",0) != std::string::npos && \ block.find("Agent/",0) != std::string::npos) \ { \ pos = block.find("Agent/",0) + 6; end = block.find("\n",pos); std::string theAgent; theAgent = block.substr(pos,end-pos); if (gDebug) { std::cout << "theAgent: " << theAgent << " - link attempt" << std::endl; } if (TheAgents.exists(atoi(theAgent.c_str()))) { TheAgents.where(atoi(theAgent.c_str())).SetOnCall(); if (gDebug) { std::cout << "theAgent: " << ((doColorize) ? fg_light_green : "") << theAgent << " - linked" << ((doColorize) ? normal : "") << std::endl; } if (gLog) { writeGnudialerLog("SetOnCall: " + theAgent); } } else { std::cout << "Link: Error parsing agent number!" << std::endl; } } //*********************************************************************************** if ((block.find("Event: UserEventQueue",0) != std::string::npos && block.find("~",0) != std::string::npos) || \ (block.find("Event: UserEventQueueTRANSFER",0) != std::string::npos && block.find("~",0) != std::string::npos) || \ (block.find("UserEvent: Queue",0) != std::string::npos && block.find("~",0) != std::string::npos) || \ (block.find("UserEvent: QueueTRANSFER",0) != std::string::npos && block.find("~",0) != std::string::npos)) \ { \ bool isNone = false; std::string theChannel, theAgent, theLeadid, theCampaign; bool isTransfer = false; std::string tempQueueAgent, tempQueueCampaign; if (block.find("Channel: ",0) != std::string::npos) { pos = block.find("Channel: ",0) + 9; end = block.find("\n",pos); theChannel = block.substr(pos,end-pos); if (gDebug) { std::cout << "UserEventQueue: theChannel - " << theChannel << std::endl; } } if (block.find("~",0) != std::string::npos) { pos = block.find("~",end) + 1; end = block.find("-",pos+1); theCampaign = block.substr(pos,end-pos); //hunt down why the campaign would be 'none' if (theCampaign.find("none",0) != std::string::npos) { isNone = true; } if (gDebug) { std::cout << "UserEventQueue: theCampaign - " << theCampaign << std::endl; } pos2 = end + 1; end2 = block.find("-",pos2); theLeadid = block.substr(pos2,end2-pos2); if (gDebug) { std::cout << "UserEventQueue: theLeadid - " << theLeadid << std::endl; } } if (TheQueues.exists(theCampaign)) { //testing here TheCallCache->SetAnswered(theCampaign,theLeadid); if (block.find("TRANSFER",0) != std::string::npos && !isNone) { isTransfer = true; if (gDebug) { std::cout << "UserEventQueue: isTransfer - " << isTransfer << std::endl; } } if (isTransfer) { //****************************************************************************** //this section is where calls are handled for CLOSERS try { tempQueueAgent = TheQueues.LeastRecent(theCampaign,theChannel,theLeadid,true,TheQueues.rWhere(theCampaign).GetSetting("closercam").Get(),TheAgents); if (atoi(tempQueueAgent.c_str())) { if (gDebug) { std::cout << theCampaign << ": " << ((doColorize) ? fg_light_green : "") << "Transfer - tempQueueAgent: " << tempQueueAgent << ((doColorize) ? normal : "") << std::endl; } //tempQueueCampaign = TheQueues.rWhere(theCampaign).GetSetting("closercam").Get(); //testing here //TheCallCache->SetAnswered(theCampaign,theLeadid); pid = fork(); if (pid == 0) { if (isNone == false) { doRedirect(theChannel,tempQueueAgent,theCampaign,theLeadid,managerUser,managerPass,"closerloop"); exit(0); } } if (pid == -1) { throw xForkError(); } } else { std::cout << theCampaign << ": " << ((doColorize) ? fg_light_white : "") << " [" << getppid() << ":" << getpid() << "] " << ((doColorize) ? fg_light_red : "") << " No available Closers! (QUEUE)" << ((doColorize) ? normal : "") << std::endl; } } catch (xLoopEnd e) { std::cout << "Caught xLoopEnd when getting closer leastrecent." << std::endl; std::cout << e.what(); std::cout << std::endl << std::endl; } } else { //****************************************************************************** //this section is where calls are handled for AGENTS try { tempQueueAgent = TheQueues.LeastRecent(theCampaign,theChannel,theLeadid,false,TheQueues.rWhere(theCampaign).GetSetting("closercam").Get(),TheAgents); if (atoi(tempQueueAgent.c_str())) { if (gDebug) { std::cout << theCampaign << ": " << ((doColorize) ? fg_light_green : "") << "Transfer - tempQueueAgent: " << tempQueueAgent << ((doColorize) ? normal : "") << std::endl; } TheQueues.rWhere(theCampaign).DecrementAnsmachs(); TheQueues.rWhere(theCampaign).WriteAbn(); //testing here //TheCallCache->SetAnswered(theCampaign,theLeadid); pid = fork(); if (pid == 0) { if (isNone == false) { doRedirect(theChannel,tempQueueAgent,theCampaign,theLeadid,managerUser,managerPass,"agent"); exit(0); } } if (pid == -1) { throw xForkError(); } } else { std::cout << theCampaign << ": " << ((doColorize) ? fg_light_red : "") << " No available Agents! (QUEUE)" << ((doColorize) ? normal : "") << std::endl; } } catch (xLoopEnd e) { std::cout << "Caught xLoopEnd when getting agent leastrecent." << std::endl; std::cout << e.what(); std::cout << std::endl << std::endl; } } } else { std::cout << theCampaign << ": " << ((doColorize) ? fg_light_red : "") << "Parse ERROR! (QUEUE)" << ((doColorize) ? normal : "") << std::endl; } } //*********************************************************************************** if (block.find("Event: ManagerUserEvent",0) != std::string::npos && \ block.find("Event: AgentPause",0) != std::string::npos) \ { \ std::string theEvent, theAgent; theEvent = "Pause"; if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; end = block.find("\n",pos); theAgent = block.substr(pos,end-pos); } if (gDebug) { std::cout << "Asterisk: ManagerUserEvent - " << theEvent << " - " << theAgent<< std::endl; } if (gLog) { writeGnudialerLog("Asterisk: ManagerUserEvent - " + theEvent + " - " + theAgent); } if (TheAgents.exists(atoi(theAgent.c_str()))) { TheAgents.where(atoi(theAgent.c_str())).SetOnPause(); if (gDebug) { std::cout << "GnuDialer: SetOnPause - " << theAgent<< std::endl; } if (gLog) { writeGnudialerLog("GnuDialer: SetOnPause - " + theAgent); } } else { std::cout << "AgentPause: Error parsing agent number!" << std::endl; } } //*********************************************************************************** if (block.find("Event: ManagerUserEvent",0) != std::string::npos && \ block.find("Event: AgentUnPause",0) != std::string::npos) \ { \ std::string theEvent, theAgent; theEvent = "UnPause"; if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; end = block.find("\n",pos); theAgent = block.substr(pos,end-pos); } if (gDebug) { std::cout << "Asterisk: ManagerUserEvent - " << theEvent << " - " << theAgent<< std::endl; } if (gLog) { writeGnudialerLog("Asterisk: ManagerUserEvent - " + theEvent + " - " + theAgent); } if (TheAgents.exists(atoi(theAgent.c_str()))) { //TheAgents.where(atoi(theAgent.c_str())).SetOnWait(false,false,TheAgents); TheAgents.where(atoi(theAgent.c_str())).SetInReady(); if (gDebug) { std::cout << "GnuDialer: SetInReady - " << theAgent<< std::endl; } if (gLog) { writeGnudialerLog("GnuDialer: SetInReady - " + theAgent); } } else { std::cout << "AgentUnPause: Error parsing agent number!" << std::endl; } } //*********************************************************************************** if (block.find("Event: QueueMemberPaused",0) != std::string::npos && \ block.find("Location:",0) != std::string::npos) \ { \ std::string theEvent, theAgent, theCampaign; theEvent = ""; bool pauseAgent = false; if (gDebug) { std::cout << "Asterisk: QueueMemberPaused -"; } // this is missing A for a reason // manager output has A and a // so we trigger off rest if (block.find("gent/",0) != std::string::npos) { pos = block.find("gent/",0) + 5; end = block.find("\n",pos); theAgent = block.substr(pos,end-pos); if (gDebug) { std::cout << " theAgent: " << theAgent; } } if (block.find("Queue: ",0) != std::string::npos) { pos = block.find("Queue: ",0) + 7; end = block.find("\n",pos); theCampaign = block.substr(pos,end-pos); if (gDebug) { std::cout << " theCampaign: " << theCampaign; } } if (block.find("Paused: ",0) != std::string::npos) { pos = block.find("Paused: ",0) + 8; end = block.find("\n",pos); theEvent = block.substr(pos,end-pos); if (theEvent.find("1",0) != std::string::npos) { theEvent = "Pause"; pauseAgent = true; } else { theEvent = "UnPause"; pauseAgent = false; } if (gDebug) { std::cout << " theEvent: " << theEvent; } } if (gDebug) { std::cout << " " << std::endl; } //if (gDebug) { // std::cout << "Asterisk: QueueMemberPaused - " << theEvent << " - " << theAgent << " for Queue - " << theCampaign << std::endl; //} if (gLog) { writeGnudialerLog("Asterisk: QueueMemberPaused - " + theEvent + " - " + theAgent + " for Queue - " + theCampaign + ""); } if (TheAgents.exists(atoi(theAgent.c_str()))) { if (pauseAgent) { TheAgents.where(atoi(theAgent.c_str())).SetOnPause(); if (gDebug) { std::cout << "GnuDialer: SetOnPause - " << theAgent << std::endl; } if (gLog) { writeGnudialerLog("GnuDialer: SetOnPause - " + theAgent); } } else { //TheAgents.where(atoi(theAgent.c_str())).SetOnWait(false,false,TheAgents); TheAgents.where(atoi(theAgent.c_str())).SetInReady(); if (gDebug) { std::cout << "GnuDialer: SetInReady - " << theAgent << std::endl; } if (gLog) { writeGnudialerLog("GnuDialer: SetOnReady - " + theAgent); } } } else { std::cout << "AgentPause: Error parsing agent number!" << std::endl; } } //*********************************************************************************** if (block.find("Event: ManagerUserEvent",0) != std::string::npos && \ block.find("Event: AgentMonitor",0) != std::string::npos) \ { \ std::string theEvent, theAgent, theCampaign, theLeadid, theChannel, theTempCampaign; theEvent = "Monitor"; if (gDebug) { std::cout << "ManagerUserEvent - " + theEvent + " - "; } if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; end = block.find("|",pos); theAgent = block.substr(pos,end-pos); if (gLog) { writeGnudialerLog("ManagerUserEvent - " + theEvent + " - " + theAgent); } if (gDebug) { std::cout << " Agent: " << theAgent; } } if (block.find("Campaign: ",0) != std::string::npos) { pos = block.find("Campaign: ",0) + 10; end = block.find("|",pos); theCampaign = block.substr(pos,end-pos); //this is due to crm adding -isclosercam to campaign name if (theCampaign.find("-isclosercam",0) != std::string::npos) { end2 = theCampaign.find("-",0); theTempCampaign = theCampaign.substr(0,end2); theCampaign = theTempCampaign; } if (gDebug) { std::cout << " Campaign: " << theCampaign; } } if (block.find("Leadid: ",0) != std::string::npos) { pos = block.find("Leadid: ",0) + 8; end = block.find("|",pos); theLeadid = block.substr(pos,end-pos); if (gDebug) { std::cout << " Leadid: " << theLeadid; } } if (block.find("Channel: ",0) != std::string::npos) { pos = block.find("Channel: ",0) + 9; end = block.find("\n",pos); theChannel = block.substr(pos,end-pos); //if (gDebug) { // std::cout << " Channel: " << theChannel; //} } if (gDebug) { std::cout << std::endl; } if (gLog) { writeGnudialerLog("Asterisk: ManagerUserEvent - " + theEvent + " - " + theAgent); } pid = fork(); if (pid == 0) { doMonitorStart(theChannel,theAgent,theCampaign,theLeadid,managerUser,managerPass); exit(0); } if (pid == -1) { throw xForkError(); } } //*********************************************************************************** if (block.find("Event: ManagerUserEvent",0) != std::string::npos && \ block.find("Event: AgentUnMonitor",0) != std::string::npos) \ { \ std::string theEvent, theAgent, theCampaign, theLeadid, theChannel, theTempCampaign; theEvent = "UnMonitor"; if (gDebug) { std::cout << "ManagerUserEvent - " + theEvent + " - "; } if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; end = block.find("|",pos); theAgent = block.substr(pos,end-pos); if (gLog) { writeGnudialerLog("ManagerUserEvent - " + theEvent + " - " + theAgent); } if (gDebug) { std::cout << " Agent: " << theAgent; } } if (block.find("Campaign: ",0) != std::string::npos) { pos = block.find("Campaign: ",0) + 10; end = block.find("|",pos); theCampaign = block.substr(pos,end-pos); //this is due to crm adding -isclosercam to campaign name if (theCampaign.find("-isclosercam",0) != std::string::npos) { end2 = theCampaign.find("-",0); theTempCampaign = theCampaign.substr(0,end2); theCampaign = theTempCampaign; } if (gDebug) { std::cout << " Campaign: " << theCampaign; } } if (block.find("Leadid: ",0) != std::string::npos) { pos = block.find("Leadid: ",0) + 8; end = block.find("|",pos); theLeadid = block.substr(pos,end-pos); if (gDebug) { std::cout << " Leadid: " << theLeadid; } } if (block.find("Channel: ",0) != std::string::npos) { pos = block.find("Channel: ",0) + 9; end = block.find("\n",pos); theChannel = block.substr(pos,end-pos); //if (gDebug) { // std::cout << " Channel: " << theChannel; //} } if (gDebug) { std::cout << std::endl; } if (gLog) { writeGnudialerLog("Asterisk: ManagerUserEvent - " + theEvent + " - " + theAgent); } pid = fork(); if (pid == 0) { doMonitorStop(theChannel,theAgent,theCampaign,theLeadid,managerUser,managerPass); exit(0); } if (pid == -1) { throw xForkError(); } } //*********************************************************************************** //testing here // This block is to make sure that in case the call hangs up we adjust the // linesdialing tracking if (block.find("Event: Hangup",0) != std::string::npos && block.find("Channel: ",0) != std::string::npos) { pos = block.find("Channel: ",0) + 9; end = block.find("\n",pos); std::string theChannel, theAgent, theCampaign, theLeadid, theCallerIDName; theChannel = block.substr(pos,end-pos); if (gDebug) { std::cout << "theChannel: " << theChannel << " - hungup" << std::endl; } if (block.find("CallerIDName: ",0) != std::string::npos && block.find("~",0) != std::string::npos) { pos = block.find("CallerIDName: ",0) + 15; end = block.find("\n",pos); theCallerIDName = block.substr(pos,end-pos); if (block.find("~",0) != std::string::npos) { pos = theCallerIDName.find("~",end) + 1; end = theCallerIDName.find("-",pos+1); pos2 = end + 1; end2 = theCallerIDName.find("-",pos2); theCampaign = theCallerIDName.substr(pos,end-pos); theLeadid = theCallerIDName.substr(pos2,end2-pos2); } if (!theCampaign.empty() && !theLeadid.empty() && TheQueues.exists(theCampaign)) { TheCallCache->SetHungup(theCampaign,theLeadid); if (gDebug) { std::cout << theCampaign << ": " << "theChannel: " << theChannel << " - SetHungup - record " << theLeadid << std::endl; //std::cout << theCampaign << ": " << "theChannel: " << theChannel << " - Hungup record: " << theLeadid << " (informational only)" << std::endl; } } } } //if (TheAgents.existsConnected(theChannel) && block.find("Agent/",0) != std::string::npos) { // TheAgents.whereConnected(theChannel).SetOnWait(false,false,TheAgents); // theAgent = TheAgents.whereConnected(theChannel).GetNumber(); // if (gDebug) { // std::cout << "theAgent: " << theAgent << " - on wait" << std::endl; // } // if (gLog) { // writeGnudialerLog("SetOnWait: " + theChannel); // } //} //} //*********************************************************************************** //this isn't used anymore, just left as a template incase we find something we want to //trigger off the Unlink event // // This block is to make sure that just in case an Unlink event fails // we still set the agent on wait so that they still get calls! //if (block.find("Event: Hangup",0) != std::string::npos && block.find("Channel: ",0) != std::string::npos) { // pos = block.find("Channel: ",0) + 9; // end = block.find("\n",pos); // std::string theChannel, theAgent; // theChannel = block.substr(pos,end-pos); //if (gDebug) { // std::cout << "theChannel: " << theChannel << " - hungup" << std::endl; //} //if (TheAgents.existsConnected(theChannel) && block.find("Agent/",0) != std::string::npos) { // TheAgents.whereConnected(theChannel).SetOnWait(false,false,TheAgents); // theAgent = TheAgents.whereConnected(theChannel).GetNumber(); // if (gDebug) { // std::cout << "theAgent: " << theAgent << " - on wait" << std::endl; // } // if (gLog) { // writeGnudialerLog("SetOnWait: " + theChannel); // } //} //} //*********************************************************************************** if (block.find("Event: ManagerUserEvent",0) != std::string::npos && \ block.find("Event: CRM_CallHangup",0) != std::string::npos) \ { \ std::string theEvent, theAgent, theChannel, theCampaign, theLeadid; std::string theTempCampaign, theAgentChannel; theEvent = "CallHangup"; if (gDebug) { std::cout << "UserEvent - CallHangup "; } if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; end = block.find("|",pos); theAgent = block.substr(pos,end-pos); if (gLog) { writeGnudialerLog("ManagerUserEvent - " + theEvent + " - " + theAgent); } if (gDebug) { std::cout << " Agent: " << theAgent; } } if (block.find("Campaign: ",0) != std::string::npos) { pos = block.find("Campaign: ",0) + 10; end = block.find("|",pos); theCampaign = block.substr(pos,end-pos); //this is due to crm adding -isclosercam to campaign name if (theCampaign.find("-isclosercam",0) != std::string::npos) { end2 = theCampaign.find("-",0); theTempCampaign = theCampaign.substr(0,end2); theCampaign = theTempCampaign; } if (gDebug) { std::cout << " Campaign: " << theCampaign; } } if (block.find("Leadid: ",0) != std::string::npos) { pos = block.find("Leadid: ",0) + 8; end = block.find("|",pos); theLeadid = block.substr(pos,end-pos); if (gDebug) { std::cout << " Leadid: " << theLeadid; } } //if (!theCampaign.empty() && !theLeadid.empty()) { // TheCallCache->SetHungup(theCampaign,theLeadid); //} if (block.find("Channel: ",0) != std::string::npos) { pos = block.find("Channel: ",0) + 9; end = block.find("\n",pos); theChannel = block.substr(pos,end-pos); if (gDebug) { std::cout << " Channel: " << theChannel; } } try { if (TheAgents.exists(atoi(theAgent.c_str()))) { std::cout << " (agent exists) "; if (TheAgents.where(atoi(theAgent.c_str())).GetStatus() != -4) { std::cout << " (GetStatus ne -4) "; if (!theCampaign.empty() && theCampaign != "initialized") { std::cout << " (campaign not empty, nor equal initialized) "; TheAgents.where(atoi(theAgent.c_str())).writeAgentLog(TheAgents); std::cout << " (writeAgentLog) "; TheAgents.where(atoi(theAgent.c_str())).SetInCloseout(); std::cout << std::endl; if (gDebug) { std::cout << theCampaign << ": SetInCloseout - " << theAgent << std::endl; } if (gLog) { writeGnudialerLog(theCampaign + ": SetInCloseout - " + theAgent); } } else { std::cout << theAgent << ": UserEvent - CallHangup - ERROR: Empty Campaign or 'initialized'" << std::endl; } } } else { std::cout << "CallHangup: Error parsing agent number! (CLOSEOUT)" << std::endl; } } catch (xLoopEnd e) { std::cout << "Caught xLoopEnd callhangup 00" << std::endl; std::cout << e.what(); std::cout << std::endl << std::endl; } try { theAgentChannel = TheAgents.where(atoi(theAgent.c_str())).GetConnectedChannel(); TheAgents.where(atoi(theAgent.c_str())).SetConnectedChannel("hungup"); } catch (xLoopEnd e) { std::cout << "Caught xLoopEnd callhangup 01" << std::endl; std::cout << e.what(); std::cout << std::endl << std::endl; } if (theChannel != theAgentChannel && theChannel != "hungup") { if (theCampaign == "initialized") { //set theChannel to empty so no hangup happens theChannel = ""; } else { theChannel = theAgentChannel; } } if (!theChannel.empty() && theChannel != "hungup") { pid = fork(); if (pid == 0) { doHangupCall(theChannel,theAgent,managerUser,managerPass); exit(0); } if (pid == -1) { throw xForkError(); } } else { std::cout << theAgent << ": UserEvent - CallHangup - ERROR: Empty Channel " << std::endl; } } //*********************************************************************************** //Event: ManagerUserEvent //Privilege: user,all //Event: CRM_Send2Conf //Body: Agent: 399|Campaign: |Leadid: |Channel: if (block.find("Event: ManagerUserEvent",0) != std::string::npos && \ block.find("Event: CRM_Send2Conf",0) != std::string::npos) \ { \ std::string theEvent, theAgent, theChannel, theCampaign, theLeadid, theClid; std::string theTempCampaign, theAgentChannel; theEvent = "Send2Conf"; if (gDebug) { std::cout << "UserEvent - Send2Conf "; } if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; end = block.find("|",pos); theAgent = block.substr(pos,end-pos); if (gLog) { writeGnudialerLog("ManagerUserEvent - " + theEvent + " - " + theAgent); } if (gDebug) { std::cout << " Agent: " << theAgent; } } if (block.find("Campaign: ",0) != std::string::npos) { pos = block.find("Campaign: ",0) + 10; end = block.find("|",pos); theCampaign = block.substr(pos,end-pos); //this is due to crm adding -isclosercam to campaign name if (theCampaign.find("-isclosercam",0) != std::string::npos) { end2 = theCampaign.find("-",0); theTempCampaign = theCampaign.substr(0,end2); theCampaign = theTempCampaign; } if (gDebug) { std::cout << " Campaign: " << theCampaign; } } if (block.find("Leadid: ",0) != std::string::npos) { pos = block.find("Leadid: ",0) + 8; end = block.find("|",pos); theLeadid = block.substr(pos,end-pos); if (gDebug) { std::cout << " Leadid: " << theLeadid; } } if (block.find("Channel: ",0) != std::string::npos) { pos = block.find("Channel: ",0) + 9; end = block.find("|",pos); theChannel = block.substr(pos,end-pos); if (gDebug) { std::cout << " Channel: " << theChannel; } } if (block.find("Clid: ",0) != std::string::npos) { pos = block.find("Clid: ",0) + 6; end = block.find("\n",pos); theClid = block.substr(pos,end-pos); if (gDebug) { std::cout << " Clid: " << theClid; } } bool tempUseCloser = TheQueues.rWhere(theCampaign).GetSetting("usecloser").GetBool(); if (!theChannel.empty() && theChannel != "hungup") { pid = fork(); if (pid == 0) { doSend2Conf(theChannel,theAgent,theClid,theCampaign,theLeadid,tempUseCloser,managerUser,managerPass); exit(0); } if (pid == -1) { throw xForkError(); } } else { std::cout << theAgent << ": UserEvent - Send2Conf - ERROR: Empty Channel " << std::endl; } } //*********************************************************************************** //Event: ManagerUserEvent //Privilege: user,all //Event: CRM_3rdParty //Body: Agent: 399|Campaign: |Leadid: |Channel: if (block.find("Event: ManagerUserEvent",0) != std::string::npos && \ block.find("Event: CRM_3rdParty",0) != std::string::npos) \ { \ std::string theEvent, theAgent, theChannel, theCampaign, theLeadid, theClid; std::string theTempCampaign, theAgentChannel; theEvent = "3rdParty"; if (gDebug) { std::cout << "UserEvent - 3rdParty "; } if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; end = block.find("|",pos); theAgent = block.substr(pos,end-pos); if (gLog) { writeGnudialerLog("ManagerUserEvent - " + theEvent + " - " + theAgent); } if (gDebug) { std::cout << " Agent: " << theAgent; } } if (block.find("Campaign: ",0) != std::string::npos) { pos = block.find("Campaign: ",0) + 10; end = block.find("|",pos); theCampaign = block.substr(pos,end-pos); //this is due to crm adding -isclosercam to campaign name if (theCampaign.find("-isclosercam",0) != std::string::npos) { end2 = theCampaign.find("-",0); theTempCampaign = theCampaign.substr(0,end2); theCampaign = theTempCampaign; } if (gDebug) { std::cout << " Campaign: " << theCampaign; } } if (block.find("Leadid: ",0) != std::string::npos) { pos = block.find("Leadid: ",0) + 8; end = block.find("|",pos); theLeadid = block.substr(pos,end-pos); if (gDebug) { std::cout << " Leadid: " << theLeadid; } } if (block.find("Channel: ",0) != std::string::npos) { pos = block.find("Channel: ",0) + 9; end = block.find("|",pos); theChannel = block.substr(pos,end-pos); if (gDebug) { std::cout << " Channel: " << theChannel; } } if (block.find("Clid: ",0) != std::string::npos) { pos = block.find("Clid: ",0) + 6; end = block.find("\n",pos); theClid = block.substr(pos,end-pos); if (gDebug) { std::cout << " Clid: " << theClid; } } bool tempUseCloser = TheQueues.rWhere(theCampaign).GetSetting("usecloser").GetBool(); std::string temp3rdParty = TheQueues.rWhere(theCampaign).GetSetting("thirdparty").Get(); if (!temp3rdParty.empty() && temp3rdParty != "none") { pid = fork(); if (pid == 0) { do3rdParty(temp3rdParty,theAgent,theClid,theCampaign,theLeadid,tempUseCloser,managerUser,managerPass); exit(0); } if (pid == -1) { throw xForkError(); } } else { std::cout << theAgent << ": UserEvent - 3rdParty - Campaign Setting is 'none' " << std::endl; } } //*********************************************************************************** if (block.find("Event: ManagerUserEvent",0) != std::string::npos && \ block.find("Event: CRM_LoginAgent",0) != std::string::npos) \ { \ std::string theEvent, theAgent, isPaused = "0"; int theStatus; theEvent = "CRM_LoginAgent"; if (gDebug) { std::cout << "UserEvent - CRM_LoginAgent "; } if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; end = block.find("|",pos); theAgent = block.substr(pos,end-pos); if (gLog) { writeGnudialerLog("ManagerUserEvent - " + theEvent + " - " + theAgent); } if (gDebug) { std::cout << " Agent: " << theAgent; } } std::cout << std::endl; if (TheAgents.exists(atoi(theAgent.c_str()))) { //std::cout << " (agent exists) "; theStatus = TheAgents.where(atoi(theAgent.c_str())).GetStatus(); if (theStatus != -2) { //std::cout << " (agent logged in) "; if (theStatus == -3) { //std::cout << " (agent paused) "; isPaused = "1"; } pid = fork(); if (pid == 0) { doSendLoggedIn(theAgent,isPaused,managerUser,managerPass); exit(0); } if (pid == -1) { throw xForkError(); } } } else { std::cout << "CRM_LoginAgent: Error parsing agent number! " << std::endl; } } //*********************************************************************************** if (block.find("Event: ManagerUserEvent",0) != std::string::npos && \ block.find("Event: CRM_JoinConf",0) != std::string::npos) \ { \ std::string theEvent, theAgent, theChannel, theCampaign, theLeadid, theClid; std::string theTempCampaign, theAgentChannel, theAgentLoginChannel; theEvent = "JoinConf"; if (gDebug) { std::cout << "UserEvent - JoinConf "; } if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; end = block.find("|",pos); theAgent = block.substr(pos,end-pos); theAgentLoginChannel = TheAgents.where(atoi(theAgent.c_str())).GetLoginChannel(); if (gLog) { writeGnudialerLog("ManagerUserEvent - " + theEvent + " - " + theAgent); } if (gDebug) { std::cout << " Agent: " << theAgent << " theAgentLoginChannel: [" << theAgentLoginChannel << "] "; } } if (block.find("Campaign: ",0) != std::string::npos) { pos = block.find("Campaign: ",0) + 10; end = block.find("|",pos); theCampaign = block.substr(pos,end-pos); //this is due to crm adding -isclosercam to campaign name if (theCampaign.find("-isclosercam",0) != std::string::npos) { end2 = theCampaign.find("-",0); theTempCampaign = theCampaign.substr(0,end2); theCampaign = theTempCampaign; } if (gDebug) { std::cout << " Campaign: " << theCampaign; } } if (block.find("Leadid: ",0) != std::string::npos) { pos = block.find("Leadid: ",0) + 8; end = block.find("|",pos); theLeadid = block.substr(pos,end-pos); if (gDebug) { std::cout << " Leadid: " << theLeadid; } } if (block.find("Channel: ",0) != std::string::npos) { pos = block.find("Channel: ",0) + 9; end = block.find("|",pos); theChannel = block.substr(pos,end-pos); if (gDebug) { std::cout << " Channel: " << theChannel; } } if (block.find("Clid: ",0) != std::string::npos) { pos = block.find("Clid: ",0) + 6; end = block.find("\n",pos); theClid = block.substr(pos,end-pos); if (gDebug) { std::cout << " Clid: " << theClid; } } bool tempUseCloser = TheQueues.rWhere(theCampaign).GetSetting("usecloser").GetBool(); std::string temp3rdParty = TheQueues.rWhere(theCampaign).GetSetting("thirdparty").Get(); if (!temp3rdParty.empty() && temp3rdParty != "none") { pid = fork(); if (pid == 0) { doJoinConf(theAgentLoginChannel,theAgent,theClid,theCampaign,theLeadid,tempUseCloser,managerUser,managerPass); exit(0); } if (pid == -1) { throw xForkError(); } } else { std::cout << theAgent << ": UserEvent - JoinConf - Campaign Setting is 'none' " << std::endl; } } //*********************************************************************************** if (block.find("Event: CRM_DispoRecord",0) != std::string::npos || \ block.find("Event: UserEventDispo",0) != std::string::npos || \ block.find("UserEvent: Dispo",0) != std::string::npos) \ { \ std::string theEvent, theAgent, theDispo, theChannel, theCampaign, theLeadid; std::string theTransfer, theAgentCloser, theDispoColumn, theCloserCam; bool tempUseCloser = false, tempPrintAgentSales, tempPrintCloserSales, tempPrintCloserNoSales; std::string tempCloserCam, theTempCampaign, theAgentChannel; std::string tempVMMessage; std::string theUid; theEvent = "DispoRecord"; std::string tempStringAgent; int tempIntAgent; if (gDebug) { std::cout << "Manager/UserEvent - DispoRecord "; } if (block.find("Agent: ",0) != std::string::npos) { pos = block.find("Agent: ",0) + 7; //end = block.find("|",pos); if (block.find("|Dispo: ",0) != std::string::npos) { end = block.find("|",pos); } else { end = block.find("\n",pos); } theAgent = block.substr(pos,end-pos); if (gLog) { writeGnudialerLog("Asterisk: ManagerUserEvent - " + theEvent + " - " + theAgent); } if (gDebug) { std::cout << " Agent: " << theAgent; } } if (block.find("Dispo: ",0) != std::string::npos) { pos = block.find("Dispo: ",0) + 7; //end = block.find("|",pos); if (block.find("|Dispo: ",0) != std::string::npos) { end = block.find("|",pos); } else { end = block.find("\n",pos); } theDispo = block.substr(pos,end-pos); if (gDebug) { std::cout << " Dispo: " << theDispo; } } if (block.find("Transfer: ",0) != std::string::npos) { pos = block.find("Transfer: ",0) + 10; //end = block.find("|",pos); if (block.find("|Dispo: ",0) != std::string::npos) { end = block.find("|",pos); } else { end = block.find("\n",pos); } theTransfer = block.substr(pos,end-pos); if (gDebug) { std::cout << " Transfer: " << theTransfer; } } if (block.find("Campaign: ",0) != std::string::npos) { pos = block.find("Campaign: ",0) + 10; //end = block.find("|",pos); if (block.find("|Dispo: ",0) != std::string::npos) { end = block.find("|",pos); } else { end = block.find("\n",pos); } theCampaign = block.substr(pos,end-pos); //this is due to crm adding -isclosercam to campaign name if (theCampaign.find("-isclosercam",0) != std::string::npos) { end2 = theCampaign.find("-",0); theTempCampaign = theCampaign.substr(0,end2); theCampaign = theTempCampaign; } if (gDebug) { std::cout << " Campaign: " << theCampaign; } } if (block.find("Leadid: ",0) != std::string::npos) { pos = block.find("Leadid: ",0) + 8; //end = block.find("|",pos); if (block.find("|Dispo: ",0) != std::string::npos) { end = block.find("|",pos); } else { end = block.find("\n",pos); } theLeadid = block.substr(pos,end-pos); if (gDebug) { std::cout << " Leadid: " << theLeadid; } } //if (!theCampaign.empty() && !theLeadid.empty()) { // TheCallCache->SetHungup(theCampaign,theLeadid); //} if (block.find("Channel: ",0) != std::string::npos) { pos = block.find("Channel: ",0) + 9; end = block.find("|",pos); theChannel = block.substr(pos,end-pos); if (gDebug) { std::cout << " Channel: " << theChannel; } } if (block.find("Uid: ",0) != std::string::npos) { pos = block.find("Uid: ",0) + 5; end = block.find("\n",pos); theUid = block.substr(pos,end-pos); if (gDebug) { std::cout << " Uid: " << theUid; } } // still need UID (not sure how to get this from phone dispo menthod) if (!theCampaign.empty() && !theAgent.empty()) { std::string thequeuestring = ltos(myepoch) + "|" + ((!theUid.empty()) ? theUid : "NONE") + "|" + theCampaign + "|" + theAgent + "|COMPLETECALLER"; writeQueueLog(thequeuestring); // 1220055577|1234567890.1234|06087T|300|COMPLETECALLER } if (TheQueues.exists(theCampaign)) { tempVMMessage = TheQueues.rWhere(theCampaign).GetSetting("vm_message").Get(); if (theTransfer == "TRANSFER") { try { tempUseCloser = TheQueues.rWhere(theCampaign).GetSetting("usecloser").GetBool(); } catch (xLoopEnd e) { std::cout << "Caught xLoopEnd while trying to get usecloser variable" << std::endl; std::cout << e.what(); std::cout << std::endl << std::endl; } try { tempCloserCam = TheQueues.rWhere(theCampaign).GetSetting("closercam").Get(); } catch (xLoopEnd e) { std::cout << "Caught xLoopEnd while trying to get closercam variable" << std::endl; std::cout << e.what(); std::cout << std::endl << std::endl; } if (gDebug) { std::cout << " tempCloserCam: " << tempCloserCam; } } if (gDebug) { std::cout << std::endl; } if (TheAgents.exists(atoi(theAgent.c_str()))) { tempIntAgent = atoi(theAgent.c_str()); int tempAgentStatus = TheAgents.where(atoi(theAgent.c_str())).GetStatus(); if (tempAgentStatus != -4 && tempAgentStatus != -3) { TheAgents.where(tempIntAgent).writeAgentLog(TheAgents); } TheAgents.where(tempIntAgent).SetInReady(); if (gDebug) { std::cout << "GnuDialer: SetInReady - " << theAgent << std::endl; } if (gLog) { writeGnudialerLog("GnuDialer: SetInReady - " + theAgent); } } else { std::cout << "DispoRecord: Error parsing agent number!" << std::endl; } if (theTransfer == "TRANSFER") { theDispoColumn = "disposition"; theAgentCloser = "agent"; } else { theDispoColumn = "closerdispo"; theAgentCloser = "closer"; } writeDBString(theCampaign,theLeadid,"" + theDispoColumn + "='" + theDispo + "'," + theAgentCloser + "='" + theAgent + "'"); if (theDispo == "8") { writeDBDNC(theCampaign,theLeadid); } if (gDebug) { std::cout << theCampaign << ": writeDBString - DispoRecord - " << theAgentCloser + ": " << theAgent << " theDispo: " << theDispo << std::endl; } writeDispo(theAgent,theCampaign,theDispo); // added by wasim to get dispo into a file for upload into sql if (gLog) { std::string thedispostring = ltos(myepoch) + "|" + theCampaign + "|" + theAgent + "|" + theLeadid + "|" + theDispo; writeDispoLog(thedispostring); } if (gDebug) { std::cout << theCampaign << ": writeDispo - DispoRecord - theAgent: " << theAgent << " theDispo: " << theDispo << std::endl; } // if there is a vm message set, and agent only, and dispo of 3 if (tempVMMessage != "none" && theTransfer == "TRANSFER" && (theDispo == "3" || theDispo == "6" || theDispo == "10")) //if (tempVMMessage != "none" && theTransfer == "TRANSFER" && theDispo == "3") { if (gDebug) { std::cout << theCampaign << ": Transfering " << theChannel << " to VM Message: " << tempVMMessage << std::endl; } pid = fork(); if (pid == 0) { doRedirect(theChannel,theDispo,theCampaign,theLeadid,managerUser,managerPass,"agentdispo"); exit(0); } if (pid == -1) { throw xForkError(); } } tempPrintAgentSales = TheQueues.rWhere(theCampaign).GetSetting("prn_agent_sales").GetBool(); tempPrintCloserSales = TheQueues.rWhere(theCampaign).GetSetting("prn_closer_sales").GetBool(); tempPrintCloserNoSales = TheQueues.rWhere(theCampaign).GetSetting("prn_closer_nosales").GetBool(); if (theTransfer == "TRANSFER" && theDispo == "12" && tempPrintAgentSales) { pid = fork(); if (pid == 0) { doPrintSale("Agent SALE NON-Verified",theCampaign,theLeadid); exit(0); } if (pid == -1) { throw xForkError(); } } if (theTransfer == "TRANSFER" && theDispo == "12" && tempUseCloser) { tempStringAgent = TheQueues.LeastRecent(theCampaign,theChannel,theLeadid,true,tempCloserCam,TheAgents); if (atoi(tempStringAgent.c_str())) { if (gDebug) { std::cout << theCampaign << ": Transfer - tempStringAgent: " << tempStringAgent << std::endl; } if (TheAgents.exists(atoi(tempStringAgent.c_str()))) { TheAgents.where(atoi(tempStringAgent.c_str())).SetConnectedChannel(theChannel); TheAgents.where(atoi(tempStringAgent.c_str())).SetCampaign(theCampaign); TheAgents.where(atoi(tempStringAgent.c_str())).SetLeadId(theLeadid); if (gDebug) { std::cout << theCampaign << ": theLeadid - " << theLeadid << std::endl; } pid = fork(); if (pid == 0) { doRedirect(theChannel,tempStringAgent,tempCloserCam,theLeadid,managerUser,managerPass,"closerloop"); exit(0); } if (pid == -1) { throw xForkError(); } } else { std::cout << "DispoRecord: Closer no longer Exists (DISPO)!" << std::endl; } } else { std::cout << theCampaign << ": No available Closers! (DISPO)" << std::endl; pid = fork(); if (pid == 0) { doRedirect(theChannel,"699",tempCloserCam,theLeadid,managerUser,managerPass,"closerloop"); exit(0); } if (pid == -1) { throw xForkError(); } } } else { if (theTransfer == "" && theDispo == "11" && tempPrintCloserNoSales) { pid = fork(); if (pid == 0) { doPrintSale("SALE Verification FAILED (for some reason)",theCampaign,theLeadid); exit(0); } if (pid == -1) { throw xForkError(); } } if (theDispo == "12" && tempPrintCloserSales) { pid = fork(); if (pid == 0) { doPrintSale("Agent SALE (Verified/or not Required)",theCampaign,theLeadid); exit(0); } if (pid == -1) { throw xForkError(); } } theAgentChannel = TheAgents.where(atoi(theAgent.c_str())).GetConnectedChannel(); if (tempVMMessage == "none" || tempVMMessage != "none" && (theDispo != "3" && theDispo != "6" && theDispo != "10")) { TheAgents.where(atoi(theAgent.c_str())).SetConnectedChannel("hungup"); } if (theChannel != theAgentChannel && theChannel != "hungup") { if (theCampaign == "initialized") { //set theChannel to empty so no hangup happens theChannel = ""; } else { theChannel = theAgentChannel; } } //working here std::string temp3rdParty = TheQueues.rWhere(theCampaign).GetSetting("thirdparty").Get(); if (theDispo == "12" && (!temp3rdParty.empty() && temp3rdParty != "none")) { theChannel = ""; } if (!theChannel.empty() && theChannel != "hungup") { if (tempVMMessage == "none" || tempVMMessage != "none" && (theDispo != "3" && theDispo != "6" && theDispo != "10")) //if (tempVMMessage == "none" || tempVMMessage != "none" && theDispo != "3") { pid = fork(); if (pid == 0) { doHangupCall(theChannel,theAgent,managerUser,managerPass); exit(0); } if (pid == -1) { throw xForkError(); } } } else { if (theChannel == "hungup") { std::cout << "DispoRecord: Channel Empty (Already Hungup - Agent was InCloseout)!" << std::endl; } else { std::cout << "DispoRecord: Channel Empty (HANGUP)!" << std::endl; } } } } else { std::cout << theCampaign << ": Parse ERROR! (DISPO)" << std::endl; } } //*********************************************************************************** if ((block.find("Event: UserEventAbandon",0) != std::string::npos) || \ (block.find("UserEvent: Abandon",0) != std::string::npos)) \ { \ std::string theCallerIDName, theCampaign, theAgent, theLeadid; if (gDebug) { std::cout << "UserEvent - Abandon "; } if (block.find("CallerIDName: ",0) != std::string::npos && block.find("~",0) != std::string::npos) { pos = block.find("CallerIDName: ",0) + 15; end = block.find("\n",pos); theCallerIDName = block.substr(pos,end-pos); pos = theCallerIDName.find("~",end) + 1; end = theCallerIDName.find("-",pos+1); pos2 = end + 1; end2 = theCallerIDName.find("-",pos2); theCampaign = theCallerIDName.substr(pos,end-pos); if (gDebug) { std::cout << " theCampaign: " << theCampaign; } theLeadid = theCallerIDName.substr(pos2,end2-pos2); if (gDebug) { std::cout << " theLeadid: " << theLeadid; } if (gDebug) { std::cout << std::endl; } if (!theCampaign.empty() && !theLeadid.empty() && TheQueues.exists(theCampaign)) { //TheCallCache->SetHungup(theCampaign,theLeadid); TheQueues.rWhere(theCampaign).IncrementAbandons(); TheQueues.rWhere(theCampaign).WriteAbn(); TheQueues.rWhere(theCampaign).WriteCalls(); writeDBString(theCampaign,theLeadid,"abandons=abandons+1"); if (gDebug) { std::cout << theCampaign << ": writeDBString - Abandon " << std::endl; } if (gLog) { writeGnudialerLog(theCampaign + ": theLeadid - " + theLeadid + " was abanadoned"); } } else { if (gDebug) { std::cout << "UserEventAbandon: Parse ERROR " << std::endl; } } } } //*********************************************************************************** if ((block.find("Event: UserEventPickup",0) != std::string::npos) || \ (block.find("UserEvent: Pickup",0) != std::string::npos)) \ { \ std::string theCallerIDName, theCampaign, theAgent, theLeadid; if (gDebug) { std::cout << "UserEvent - Pickup "; } if (block.find("CallerIDName: ",0) != std::string::npos && block.find("~",0) != std::string::npos) { pos = block.find("CallerIDName: ",0) + 15; end = block.find("\n",pos); theCallerIDName = block.substr(pos,end-pos); pos = theCallerIDName.find("~",end) + 1; end = theCallerIDName.find("-",pos+1); pos2 = end + 1; end2 = theCallerIDName.find("-",pos2); theCampaign = theCallerIDName.substr(pos,end-pos); if (gDebug) { std::cout << " theCampaign: " << theCampaign; } theLeadid = theCallerIDName.substr(pos2,end2-pos2); if (gDebug) { std::cout << " theLeadid: " << theLeadid; } if (gDebug) { std::cout << std::endl; } if (!theCampaign.empty() && !theLeadid.empty() && TheQueues.exists(theCampaign)) { //testing here TheCallCache->SetAnswered(theCampaign,theLeadid); writeDBString(theCampaign,theLeadid,"pickups=pickups+1"); if (gDebug) { std::cout << theCampaign << ": writeDBString - Pickup " << std::endl; } if (gLog) { writeGnudialerLog(theCampaign + ": theLeadid - " + theLeadid + " was picked-up"); } } else { if (gDebug) { std::cout << "UserEventPickup: Parse ERROR " << std::endl; } } } } //*********************************************************************************** if ((block.find("Event: UserEventFax",0) != std::string::npos) || \ (block.find("UserEvent: Fax",0) != std::string::npos)) \ { \ std::string theCallerIDName, theCampaign, theAgent, theLeadid; if (gDebug) { std::cout << "UserEvent - Fax "; } if (block.find("CallerIDName: ",0) != std::string::npos && block.find("~",0) != std::string::npos) { pos = block.find("CallerIDName: ",0) + 15; end = block.find("\n",pos); theCallerIDName = block.substr(pos,end-pos); pos = theCallerIDName.find("~",end) + 1; end = theCallerIDName.find("-",pos+1); pos2 = end + 1; end2 = theCallerIDName.find("-",pos2); theCampaign = theCallerIDName.substr(pos,end-pos); if (gDebug) { std::cout << " theCampaign: " << theCampaign; } theLeadid = theCallerIDName.substr(pos2,end2-pos2); if (gDebug) { std::cout << " theLeadid: " << theLeadid; } if (gDebug) { std::cout << std::endl; } if (!theCampaign.empty() && !theLeadid.empty() && TheQueues.exists(theCampaign)) { writeDBString(theCampaign,theLeadid,"disposition='-6',pickups=pickups+1"); if (gDebug) { std::cout << theCampaign << ": writeDBString - Fax " << std::endl; } if (gLog) { writeGnudialerLog(theCampaign + ": theLeadid - " + theLeadid + " was a fax"); } } else { if (gDebug) { std::cout << "UserEventPickup: Parse ERROR " << std::endl; } } } } //*********************************************************************************** // End block analysis block = ""; } else { block += tempLine + "\n"; } } //added to help cleanup regardless of the campaign being active TheCallCache->CleanupLinesDialing(); // DIALING LOOP for (int i = 0; i < TheQueues.size(); i++) { int isActive = 0; if (TheQueues.at(i).GetSetting("active").Get() == "true") { isActive++; queue = TheQueues.at(i).GetName(); if (startstopProtection) { std::string starttime = TheQueues.at(i).GetSetting("tzearliest").Get()+"00"; std::string stoptime = TheQueues.at(i).GetSetting("tzlatest").Get()+"00"; if (stoi(the24HourTime) < stoi(starttime) || stoi(the24HourTime) > stoi(stoptime)) { std::cout << TheQueues.at(i).GetName() << ": Earliest/Latest Time Violation - (" << starttime << ":" << the24HourTime << ":" << stoptime << ")" << " Setting Campaign **INACTIVE**" << std::endl; stopQueue(queue); break; } } maxratio = TheQueues.at(i).GetSetting("maxratio").GetFloat(); maxlines = TheQueues.at(i).GetSetting("maxlines").GetInt(); maxabandons = TheQueues.at(i).GetSetting("maxabandons").GetFloat(); mode = TheQueues.at(i).GetSetting("function").Get(); calltoday = TheQueues.at(i).GetSetting("calltoday").Get(); usednc = TheQueues.at(i).GetSetting("usednc").Get(); callerid = TheQueues.at(i).GetSetting("callerid").Get(); filter = TheQueues.at(i).GetSetting("filter").Get(); timeout = TheQueues.at(i).GetSetting("timeout").GetInt(); usecloser = TheQueues.at(i).GetSetting("usecloser").Get(); closercam = TheQueues.at(i).GetSetting("closercam").Get(); dspmode = TheQueues.at(i).GetSetting("dspmode").Get(); trunk = TheQueues.at(i).GetSetting("trunk").Get(); dialprefix = TheQueues.at(i).GetSetting("dialprefix").Get(); vmmessage = TheQueues.at(i).GetSetting("vm_message").Get(); sfmessage = TheQueues.at(i).GetSetting("sf_message").Get(); usecallback = TheQueues.at(i).GetSetting("usecallback").Get(); usetzfilter = TheQueues.at(i).GetSetting("usetzfilter").Get(); debug = TheQueues.at(i).GetSetting("debug").GetBool(); skip = TheQueues.at(i).GetSetting("skip").GetInt(); f_areacode = TheQueues.at(i).GetSetting("f_areacode").Get(); f_areacode_prefix = TheQueues.at(i).GetSetting("f_areacode_prefix").Get(); f_zipcode = TheQueues.at(i).GetSetting("f_zipcode").Get(); orderby = TheQueues.at(i).GetSetting("orderby").Get(); fudge = TheQueues.at(i).GetSetting("fudge").GetFloat(); allowedhours = TheQueues.at(i).GetSetting("allowedhours").Get(); extravars = ""; for (int c = 0; c < TheQueues.at(i).OccurencesOf("chanvars"); c++) { std::string cnum = TheQueues.at(i).GetSetting(c,"chanvars").GetAttribute("number"); std::string cvar = TheQueues.at(i).GetSetting(c,"chanvars").GetAttribute("var"); std::string cstring = TheQueues.at(i).GetSetting(c,"chanvars").GetAttribute("string"); std::string cenabled = TheQueues.at(i).GetSetting(c,"chanvars").GetAttribute("enable"); if (cenabled == "true") { extravars += "Variable: __" + cvar + "=" + cstring + "\r\n"; } } unsigned int remaininglines = 0; //put these down here so that most important ones get processed last calls = atoi(TheQueues.at(i).GetCalls().c_str()); TheQueues.rWhere(queue).CalcAgentCalls(); agentcalls = atoi(TheQueues.at(i).GetAgentCalls().c_str()); if (agentcalls == 0) { agentcalls = calls; } abandons = atoi(TheQueues.at(i).GetAbandons().c_str()); linesdialing = TheCallCache->LinesDialing(queue); availagents = TheQueues.at(i).GetAvailAgents(TheAgents); onlineagents = TheQueues.at(i).GetOnlineAgents(TheAgents); dialableagents = TheQueues.at(i).GetDialableAgents(TheAgents); //add gMaxlines in here totallinesdialing = TheCallCache->TotalLinesDialing(); linestodial = evaluate(mode,linesdialing,totallinesdialing,onlineagents,availagents,dialableagents,fudge,maxratio,maxlines,gMaxlines,maxabandons,agentcalls,abandons); //linestodial = (linestodial/isActive); //if (linestodial > 4) //{ if (linestodial > gMaxlines) { if (gDebug) { std::cout << queue << ": linestodial " << linestodial << " is greater than global maxlines of " << gMaxlines << ", resetting to half gMaxlines " << (gMaxlines/2) << std::endl; std::cout << queue << ": ldg: " << linesdialing << " aa: " << availagents << " mr: " << maxratio << " ml: " << maxlines << " ma: " << maxabandons << " mode: " << mode << " calls: " << calls << " abs: " << abandons << " l2d: " << linestodial << " rls: " << remaininglines << std::endl; } linestodial = (gMaxlines/2); } // else // { // if (gDebug) { // std::cout << queue << ": linestodial is greater than 4, trimming to 4 this loop" << std::endl; // std::cout << queue << ": ldg: " << linesdialing << " aa: " << availagents << " mr: " << maxratio << " ml: " << maxlines << " ma: " << maxabandons << " mode: " << mode << " calls: " << calls << " abs: " << abandons << " l2d: " << linestodial << " rls: " << remaininglines << std::endl; // } // linestodial = 4; // } //} remaininglines = maxlines - linestodial; if (totallinesdialing > gMaxlines && totallinesdialing != 0) { if (gDebug) { std::cout << queue << ": totallinesdialing is greater than global maxlines of " << gMaxlines << ", resetting to 0" << std::endl; std::cout << queue << ": ldg: " << linesdialing << " aa: " << availagents << " mr: " << maxratio << " ml: " << maxlines << " ma: " << maxabandons << " mode: " << mode << " calls: " << calls << " abs: " << abandons << " l2d: " << linestodial << " rls: " << remaininglines << std::endl; } linestodial = 0; remaininglines = 0; } // just extra fallthru stuff if (linestodial >= 5000) { std::cout << queue << ": linestodial is greater than 5000, something is WRONG!" << std::endl; std::cout << queue << ": ldg: " << linesdialing << " aa: " << availagents << " mr: " << maxratio << " ml: " << maxlines << " ma: " << maxabandons << " mode: " << mode << " calls: " << calls << " abs: " << abandons << " l2d: " << linestodial << " rls: " << remaininglines << std::endl; linestodial = 0; } if (remaininglines >= 5000) { std::cout << queue << ": remaininglines is greater than 5000, something is WRONG!" << std::endl; std::cout << queue << ": ldg: " << linesdialing << " aa: " << availagents << " mr: " << maxratio << " ml: " << maxlines << " ma: " << maxabandons << " mode: " << mode << " calls: " << calls << " abs: " << abandons << " l2d: " << linestodial << " rls: " << remaininglines << std::endl; remaininglines = 0; } if (agentcalls && abandons) { tmpAbnPerc = static_cast(abandons) / static_cast(agentcalls) * 100.0; } else { tmpAbnPerc = 0.0; } //***************************************************************************************** //testing area (this stuff happens every second) //put closer callbacks in front so they are taken care of right away if ((remaininglines && usecloser == "true" && closercam != "none" && TheQueues.exists(closercam) && true) && (currentTime - timeSinceLastQueueUpdate == 5)) { transfer = "TRANSFER"; int availclosers = TheQueues.rWhere(closercam).GetAvailAgents(TheAgents); if (debugCampaignSettings) { std::cout << currentTime << ":" << queue << ": " << "availclosers: " << availclosers << " - remaininglines: " << remaininglines << std::endl; query = "SELECT count(*) FROM `" + queue + "` WHERE "; query += " disposition = 12 AND closerdispo = 0 "; if(mysql_query(mysql, query.c_str()) != 0) { std::cout << "Error selecting records !" << std::endl; } else { result = mysql_use_result(mysql); row = mysql_fetch_row(result); int ccb_counter = stoi(std::string(row[0])); if (debug) { if (ccb_counter) { std::cout << queue << ": " << "Total Closer Callbacks Remaining: " << ccb_counter << std::endl; } } mysql_free_result(result); } } //std::cout << queue << ": Testing - got here " << std::endl; if (availclosers) { query = "SELECT `id`, `phone` FROM `" + queue + "` WHERE "; query += " disposition = 12 AND closerdispo = 0 AND ((lastupdated) < DATE_SUB(NOW(),INTERVAL 5 MINUTE)) "; query += " ORDER BY attempts + pickups ASC LIMIT 1"; //query += " ORDER BY attempts + pickups ASC LIMIT " + itos(selectLessorOf(remaininglines,availclosers)); if(mysql_query(mysql, query.c_str()) != 0) { std::cout << "Error selecting leads from mysql! (check table structures)" << std::endl; return 1; } else { result = mysql_use_result(mysql); query = "UPDATE `" + queue + "` SET attempts=attempts+1 WHERE "; for(counter = 0; (row = mysql_fetch_row(result)); counter++) { if (counter) { query += " OR "; } query += " id=" + std::string(row[0]); remaininglines--; TheCallCache->AddCall(row[1],queue,row[0],callerid,usecloser,dspmode,trunk,dialprefix,vmmessage,sfmessage,extravars,transfer,timeout); if (debug) { std::cout << queue << ": " << "Dialing Closer Callback Number: " << row[1] << std::endl; } } if(mysql_errno(mysql)) { std::cout << "Error fetching rows from mysql!" << std::endl; return 1; } mysql_free_result(result); if (counter) { TheQueues.rWhere(queue).AddCallsDialed(counter); TheQueues.rWhere(queue).WriteCalls(); if(mysql_query(mysql, query.c_str()) != 0) { std::cout << "Error updating leads in mysql!" << std::endl; return 1; } } } } } //callback section if ((remaininglines && usecallback == "true" && true) && (currentTime - timeSinceLastQueueUpdate == 5)) { transfer = ""; //int availclosers = TheQueues.rWhere(closercam).GetAvailAgents(TheAgents); //int availagents = TheQueues.rWhere(campaign).GetAvailAgents(TheAgents); if (debugCampaignSettings) { std::cout << currentTime << ":" << queue << ": availagents: " << availagents << " - remaininglines: " << remaininglines << std::endl; query = "SELECT count(*) FROM `" + queue + "` WHERE "; query += " disposition = 0 AND cb_datetime > '0000-00-00 00:00:00' AND cb_datetime < NOW()"; if(mysql_query(mysql, query.c_str()) != 0) { std::cout << "Error selecting records !" << std::endl; } else { result = mysql_use_result(mysql); row = mysql_fetch_row(result); int ccb_counter = stoi(std::string(row[0])); if (debug) { if (ccb_counter) { std::cout << queue << ": " << "Total Agent Callbacks Remaining: " << ccb_counter << std::endl; } } mysql_free_result(result); } } // create function to see if a particular agent/type is available if (availagents) { query = "SELECT `id`, `phone` FROM `" + queue + "` WHERE "; query += " disposition = 0 AND cb_datetime > '0000-00-00 00:00:00' AND cb_datetime < NOW()"; query += " AND ((lastupdated) < DATE_SUB(NOW(),INTERVAL 3 MINUTE)) "; query += " ORDER BY attempts + pickups ASC LIMIT 1"; if(mysql_query(mysql, query.c_str()) != 0) { std::cout << "Error selecting leads from mysql! (check table structures)" << std::endl; return 1; } else { result = mysql_use_result(mysql); query = "UPDATE `" + queue + "` SET cb_datetime='',attempts=attempts+1 WHERE "; for(counter = 0; (row = mysql_fetch_row(result)); counter++) { if (counter) { query += " OR "; } query += " id=" + std::string(row[0]); remaininglines--; TheCallCache->AddCall(row[1],queue,row[0],callerid,usecloser,dspmode,trunk,dialprefix,vmmessage,sfmessage,extravars,transfer,timeout); if (debug) { std::cout << queue << ": " << "Dialing Agent Callback Number: " << row[1] << std::endl; } } if(mysql_errno(mysql)) { std::cout << "Error fetching rows from mysql!" << std::endl; return 1; } mysql_free_result(result); if (counter) { TheQueues.rWhere(queue).AddCallsDialed(counter); TheQueues.rWhere(queue).WriteCalls(); if(mysql_query(mysql, query.c_str()) != 0) { std::cout << "Error updating leads in mysql!" << std::endl; return 1; } } } } } //end testing area //********************************************************************************************8 //MAIN DIALING AREA (reloading key data to maximize call potential) calls = atoi(TheQueues.at(i).GetCalls().c_str()); TheQueues.rWhere(queue).CalcAgentCalls(); agentcalls = atoi(TheQueues.at(i).GetAgentCalls().c_str()); if (agentcalls == 0) { agentcalls = calls; } abandons = atoi(TheQueues.at(i).GetAbandons().c_str()); linesdialing = TheCallCache->LinesDialing(queue); availagents = TheQueues.at(i).GetAvailAgents(TheAgents); onlineagents = TheQueues.at(i).GetOnlineAgents(TheAgents); dialableagents = TheQueues.at(i).GetDialableAgents(TheAgents); //old way was using campaign calls for abandon calcs (oopsie, amazingly noone but me noticed) //linestodial = evaluate(mode,linesdialing,availagents,maxratio,maxlines,maxabandons,calls,abandons); totallinesdialing = TheCallCache->TotalLinesDialing(); linestodial = evaluate(mode,linesdialing,totallinesdialing,onlineagents,availagents,dialableagents,fudge,maxratio,maxlines,gMaxlines,maxabandons,agentcalls,abandons); // testing here //std::string thequeuestring = ltos(myepoch) + "|1234567890.1234|" + queue + "|" + "300" + "|COMPLETECALLER"; //writeQueueLog(thequeuestring); // 1220055577|1234567890.1234|06087T|300|COMPLETECALLER if (gDebug && (1 == 2)) { std::cout << "CampaignInfo - (" +ltos(currentTime)+") Camp: " << queue << \ " CLs: " << itos(calls) << \ " ACs: " << itos(agentcalls) << \ " ABs: " << itos(abandons) << \ " ABp: " << ftos(tmpAbnPerc) << \ " LDg: " << itos(linesdialing) << \ " MxR: " << ftos(maxratio) << \ " MxB: " << ftos(maxabandons) << \ " OAs: " << itos(onlineagents) << \ " AAs: " << itos(availagents) << \ " DAs: " << itos(dialableagents) << \ " L2D: " << itos(linestodial) << "" << std::endl; } //if (linestodial > 4) //{ if (linestodial > gMaxlines) { if (gDebug) { std::cout << queue << ": linestodial " << linestodial << " is greater than global maxlines of " << gMaxlines << ", resetting to half gMaxlines " << (gMaxlines/2) << std::endl; std::cout << queue << ": ldg: " << linesdialing << " aa: " << availagents << " mr: " << maxratio << " ml: " << maxlines << " ma: " << maxabandons << " mode: " << mode << " calls: " << calls << " abs: " << abandons << " l2d: " << linestodial << " rls: " << remaininglines << std::endl; } linestodial = (gMaxlines/2); } // else // { // if (gDebug) { // std::cout << queue << ": linestodial is greater than 4, trimming to 4 this loop" << std::endl; // std::cout << queue << ": ldg: " << linesdialing << " aa: " << availagents << " mr: " << maxratio << " ml: " << maxlines << " ma: " << maxabandons << " mode: " << mode << " calls: " << calls << " abs: " << abandons << " l2d: " << linestodial << " rls: " << remaininglines << std::endl; // } // linestodial = 4; // } //} remaininglines = maxlines - linestodial; if (totallinesdialing > gMaxlines && totallinesdialing != 0) { if (gDebug) { std::cout << queue << ": totallinesdialing is greater than global maxlines of " << gMaxlines << ", resetting to 0" << std::endl; std::cout << queue << ": ldg: " << linesdialing << " aa: " << availagents << " mr: " << maxratio << " ml: " << maxlines << " ma: " << maxabandons << " mode: " << mode << " calls: " << calls << " abs: " << abandons << " l2d: " << linestodial << " rls: " << remaininglines << std::endl; } linestodial = 0; remaininglines = 0; } // just extra fallthru stuff if (linestodial >= 5000) { std::cout << queue << ": linestodial is greater than 5000, something is WRONG! (reset to 0)" << std::endl; std::cout << queue << ": ldg: " << linesdialing << " aa: " << availagents << " mr: " << maxratio << " ml: " << maxlines << " ma: " << maxabandons << " mode: " << mode << " calls: " << calls << " abs: " << abandons << " l2d: " << linestodial << " rls: " << remaininglines << std::endl; linestodial = 0; } if (remaininglines >= 5000) { std::cout << queue << ": remaininglines is greater than 5000, something is WRONG! (reset to 0)" << std::endl; std::cout << queue << ": ldg: " << linesdialing << " aa: " << availagents << " mr: " << maxratio << " ml: " << maxlines << " ma: " << maxabandons << " mode: " << mode << " calls: " << calls << " abs: " << abandons << " l2d: " << linestodial << " rls: " << remaininglines << std::endl; remaininglines = 0; } if (calls && abandons) { tmpAbnPerc = static_cast(abandons) / static_cast(calls) * 100.0; } else { tmpAbnPerc = 0.0; } transfer = ""; if (debugCampaignSettings) { std::cout << queue << ": ldg: " << linesdialing << " aa: " << availagents << " mr: " << maxratio << " ml: " << maxlines << " ma: " << maxabandons << " mode: " << mode << " calls: " << calls << " abs: " << abandons << " l2d: " << linestodial << " rls: " << remaininglines << std::endl; } //MAIN SECTION for dialing calls for a particular campaign if (linestodial && mode != "closer" && mode != "inbound" && true) { if (debug) { if (calls != 0) { std::cout << std::setprecision(4) << queue << ": " << ((doColorize) ? fg_light_cyan : "") << "ABANDON \% (this now reflects division by agentcalls): " << static_cast(abandons) / static_cast(agentcalls) * 100.0 << ((doColorize) ? normal : "") << std::endl; } // No div by 0 allowed! else { std::cout << queue << ": " << ((doColorize) ? fg_light_cyan : "") << "ABANDON \%: 0 (or less than zero)" << ((doColorize) ? normal : "") << std::endl; } } //this is just a base to get the building of the query string going query = "SELECT DISTINCT `id`, `phone` FROM `" + queue + "` IGNORE INDEX (disposition) WHERE 1 "; //this allows a record to be called back multiple times the same day //without needing to be a specific callback (like closer callback) //be careful, if your viable data is running low this will loop thru //and burn all your data (very fast), and piss off alot of people! if (calltoday != "true") { //timezone based filter (currently US only) if (usetzfilter == "true") { tzearliest = TheQueues.at(i).GetSetting("tzearliest").Get(); tzlatest = TheQueues.at(i).GetSetting("tzlatest").Get(); query += " AND " + getFilter(tzearliest,tzlatest,isAHoliday,allowedhours,gTZOffset); if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_green : "") << "tzFilter Enabled " << ((doColorize) ? normal : "") << std::endl; } } else { if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_yellow : "") << "tzFilter Disabled " << ((doColorize) ? normal : "") << std::endl; } } //query += " AND ((LEFT(lastupdated,10) = LEFT(NOW(),10) AND disposition = 1) OR LEFT(lastupdated,10) <> LEFT(NOW(),10))"; query += " AND (LEFT(lastupdated,10) = LEFT(NOW(),10) AND disposition = 1 OR (LEFT(lastupdated,10) <> LEFT(NOW(),10)))"; } // SELECT DISTINCT id, phone FROM camp WHERE 1 // AND LEFT(lastupdated,10) = LEFT(NOW(),10) AND disposition = 1 OR (LEFT(lastupdated,10) <> LEFT(NOW(),10)) // AND ((disposition > -6 AND disposition < 6) AND disposition <> -3 AND disposition <> 3 AND disposition <> 0) AND attempts < 4 // ORDER BY phone ASC LIMIT 0,10; //areacode based filter if (f_areacode.empty() == false && f_areacode != "0") { if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_yellow : "") << "f_areacode - " << f_areacode << ((doColorize) ? normal : "") << std::endl; } query += " AND LEFT(phone,3)='" + f_areacode + "'"; } //areacode + prefix based filter if (f_areacode_prefix.empty() == false && f_areacode_prefix != "0") { if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_yellow : "") << "f_areacode_prefix - " << f_areacode_prefix << ((doColorize) ? normal : "") << std::endl; } query += " AND LEFT(phone,6)='" + f_areacode_prefix + "'"; } //zipcode based filter if (f_zipcode.empty() == false && f_zipcode != "0") { if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_yellow : "") << "f_zipcode - " << f_zipcode << ((doColorize) ? normal : "") << std::endl; } //query += " AND LEFT(zip,5)='" + f_zipcode + "'"; query += " AND zip='" + f_zipcode + "'"; } //this is an extra filter if you want to attempt to call a specific data subset //(this also lets you test a filter before adding it to the primary filters) if (filter.empty() == false && filter != "0" && filter != "None" && filter != "none") { if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_yellow : "") << "filter - " << filter << ((doColorize) ? normal : "") << std::endl; } query += " AND " + filter; } query += " AND ("; //these are the primary filters, it will default to filter 0 on startup //so make sure that is your 'fresh + main' calling data int y = 0; for (int x = 0; x < TheQueues.at(i).OccurencesOf("filters"); x++) { std::string fnum,fstring,enabled; fnum = TheQueues.at(i).GetSetting(x,"filters").GetAttribute("number"); fstring = TheQueues.at(i).GetSetting(x,"filters").GetAttribute("string"); enabled = TheQueues.at(i).GetSetting(x,"filters").GetAttribute("enable"); if (enabled == "true") { y++; if (y > 1) { query += " OR "; } if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_yellow : "") << "filter - " << fstring << ((doColorize) ? normal : "") << std::endl; } query += fstring; } } query += ") "; //timezone based filter (currently US only) if (usetzfilter == "true") { tzearliest = TheQueues.at(i).GetSetting("tzearliest").Get(); tzlatest = TheQueues.at(i).GetSetting("tzlatest").Get(); query += " AND " + getFilter(tzearliest,tzlatest,isAHoliday,allowedhours,gTZOffset); if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_green : "") << "tzFilter Enabled " << ((doColorize) ? normal : "") << std::endl; } } else { if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_yellow : "") << "tzFilter Disabled " << ((doColorize) ? normal : "") << std::endl; } } //this is a realtime 'do not call' filter that does a lookup against dialer.DNC table when calling //this is resource intensive so DO NOT load dialer.DNC with alot of numbers //i suggest you 'pre-process' your calling data against DNC numbers, as you dial, dispo 8's //will be added to dialer.DNC, so you can make sure this campaign you don't call them back //then at the end of a campaign, add them to your main set of DNC's to once again //'pre-process' against your main calling data for the next campaign. if (usednc == "true") { query += " AND phone NOT IN (SELECT `phone` FROM `DNC`) "; } //original order by line, keeping till i work all the bugs out of the multiple //order by methods below //query += " ORDER BY attempts + pickups ASC LIMIT " + itos(skip) + "," + itos(linestodial); //SELECT DISTINCT id,phone,lastupdated FROM 308CLD05 WHERE (id > 0) //AND (LEFT(lastupdated,10) = LEFT(NOW(),10) AND disposition = 1) //OR (LEFT(lastupdated,10) <> LEFT(NOW(),10)) AND //((disposition > -6 AND disposition < 6) AND attempts < 3) //ORDER BY id,id,lastupdated ASC LIMIT 0,3; //SELECT DISTINCT id, phone FROM arcor WHERE 1 AND ((LEFT(lastupdated,10) = LEFT(NOW(),10) //AND disposition = 1) OR LEFT(lastupdated,10) <> LEFT(NOW(),10)) //AND ((((disposition > -6 AND disposition < 6) //AND disposition <> -3 AND disposition <> 3 AND disposition <> 0) //AND attempts < 4)) ORDER BY phone,id,lastupdated ASC LIMIT 0,1 //added to skip 'id' and 'phone' ordering for now //orderby = "foobared"; /* if (orderby == "id" || orderby == "phone") { if (orderby == "id") { query += " ORDER BY id,id,lastupdated ASC "; } if (orderby == "phone") { query += " ORDER BY phone,id,lastupdated ASC "; } } else { query += " ORDER BY attempts+pickups,id,lastupdated ASC "; } */ if (usetzfilter == "true") { query += " ORDER BY tzl DESC "; } else { if (orderby == "id" || orderby == "phone") { if (orderby == "id") { query += " ORDER BY id ASC "; } if (orderby == "phone") { query += " ORDER BY phone ASC "; } } else { query += " ORDER BY attempts ASC "; } } //if (orderby == "id" || orderby == "phone") { // if (orderby == "id") { //query += " ORDER BY id ASC "; //} // if (orderby == "phone") { // query += " ORDER BY phone ASC "; // } //} else { // query += " ORDER BY attempts + pickups ASC "; // } //self explanitory query += " LIMIT " + itos(skip) + "," + itos(linestodial); if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_white : "") << "query - " << query << ((doColorize) ? normal : "") << std::endl; } if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_light_yellow : "") << "Dialing " << linestodial << " calls (" << skip << ") skipped" << ((doColorize) ? normal : "") << std::endl; } //if(mysql_query(mysql, query.c_str()) != 0) int my_res = mysql_query(mysql, query.c_str()); if(my_res != 0) { if (debug) { std::cout << queue << ": " << ((doColorize) ? fg_yellow : "") << "mysql error (" << my_res << ")" << ((doColorize) ? normal : "") << std::endl; } if (gLog) { writeGnudialerLog(queue + ":mysql error - query failed:" + query + ""); } //std::cout << "Error selecting leads from mysql! (check table structures)" << std::endl; //return 1; } else { result = mysql_use_result(mysql); query = "UPDATE `" + queue + "` SET attempts=attempts+1 WHERE "; for(counter = 0; (row = mysql_fetch_row(result)); counter++) { if (counter) { query += " OR "; } query += " id=" + std::string(row[0]); remaininglines--; TheCallCache->AddCall(row[1],queue,row[0],callerid,usecloser,dspmode,trunk,dialprefix,vmmessage,sfmessage,extravars,transfer,timeout); } if(mysql_errno(mysql)) { std::cout << "Error fetching rows from mysql!" << std::endl; return 1; } if (!counter) { std::cout << queue << ((doColorize) ? fg_light_red : "") << ": has ran out of leads! (CHECK YOUR FILTERS!!!)" << ((doColorize) ? normal : "") << std::endl; } else if (counter < linestodial) { std::cout << queue << ((doColorize) ? fg_light_red : "") << ": is running very low on leads!" << ((doColorize) ? normal : "") << std::endl; } mysql_free_result(result); if (counter) { TheQueues.rWhere(queue).AddCallsDialed(counter); TheQueues.rWhere(queue).WriteCalls(); if(mysql_query(mysql, query.c_str()) != 0) { std::cout << "Error updating leads in mysql!" << std::endl; return 1; } } } } } } try { TheCallCache->CallAll(mainHost); } catch(xOutOfHosts) { std::cout << "Exception: Ran out of hosts!" << std::endl; return 1; } catch(xForkError) { std::cout << "Exception: Unable to fork the parent process!" << std::endl; return 1; } } mysql_close(mysql); } // Not nested for convenience. catch(const std::exception & e) { std::cout << "Caught Exception: " << e.what() << std::endl; signal(SIGKILL, SIG_DFL); return 1; } catch(...) { std::cout << "Unhandled Exception: This is most likely a STL issue." << std::endl; signal(SIGKILL, SIG_DFL); return 1; } return 0; }