From 27f71e9ef2f7cc1e99e28e59ee0de0c593db146a Mon Sep 17 00:00:00 2001 From: mattf Date: Wed, 31 Aug 2016 14:06:50 +0000 Subject: [PATCH] Fixed DB collation issue Added cm_dnc_new.agi script git-svn-id: svn://192.168.202.10@2584 3d104415-ff17-0410-8863-d5cf3c621b8a --- agc_2-X/trunk/agi/cm_dnc_new.agi | 387 ++++++++++++++++++ .../trunk/extras/MySQL_AST_CREATE_tables.sql | 4 +- agc_2-X/trunk/extras/upgrade_2.12.sql | 4 + 3 files changed, 393 insertions(+), 2 deletions(-) create mode 100644 agc_2-X/trunk/agi/cm_dnc_new.agi diff --git a/agc_2-X/trunk/agi/cm_dnc_new.agi b/agc_2-X/trunk/agi/cm_dnc_new.agi new file mode 100644 index 00000000..d4d18abd --- /dev/null +++ b/agc_2-X/trunk/agi/cm_dnc_new.agi @@ -0,0 +1,387 @@ +#!/usr/bin/perl +# +# cm_dnc_new.agi version 2.12 +# +# Designed to work with Cell Menus to allow setting of a number as DNC or NI +# This script is meant as a replacecment for the agi-VDADinbound_NI_DNC_CIDlookup.agi +# script. It is designed to work easily in the Call Menu framework, it plays no +# audio itself, and it has more options. +# +# Flag Options: +# 1- run as DNC status or ANY OTHER status (Default=NI) +# 2- default to insert into the vicidial_dnc table for DNC selections (Default=YES) +# 3- campaigns to take dnc settings from(overrides option 2) multiple campaigns separated by single dash +# 4- call menu option to send the call to after executing (Default=B) +# 5- if option 3 is used, search for lead in campaign lists or whole system(CAMP or SYS) (Default=SYS) +# 6- optional audio store file to play +# +# example of what to put in the AGI entry for a Call Menu AGI route: +# cm_dnc_new.agi,DNC---YES---TESTCAMP---B---CAMP---auth-thankyou +# +# Copyright (C) 2016 Matt Florell LICENSE: AGPLv2 +# +# changes: +# 121109-1623 - First draft +# 130108-1817 - Changes for Asterisk 1.8 compatibility +# 130925-1825 - Added variable filter to prevent DID SQL injection attack +# 150928-1822 - Added dnc logging +# 160825-1117 - modifications allowing for a lead to be updated to any +# disposition, not just NI/DNC. Also, modified to use multiple +# campaigns for lead lookups and an option to play an audio file +# without redirecting +# + +$script = 'cm_dnc_new.agi'; + +($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); +$year = ($year + 1900); +$mon++; +if ($mon < 10) {$mon = "0$mon";} +if ($mday < 10) {$mday = "0$mday";} +if ($hour < 10) {$hour = "0$hour";} +if ($min < 10) {$min = "0$min";} +if ($sec < 10) {$sec = "0$sec";} + +$now_date_epoch = time(); +$now_date = "$year-$mon-$mday $hour:$min:$sec"; +$start_time=$now_date; +$CIDdate = "$mon$mday$hour$min$sec"; +$tsSQLdate = "$year$mon$mday$hour$min$sec"; +$SQLdate = "$year-$mon-$mday $hour:$min:$sec"; +$SQLdateBEGIN = $SQLdate; + +# default path to astguiclient configuration file: +$PATHconf = '/etc/astguiclient.conf'; + +open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n"; +@conf = ; +close(conf); +$i=0; +foreach(@conf) + { + $line = $conf[$i]; + $line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi; + if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) ) + {$PATHhome = $line; $PATHhome =~ s/.*=//gi;} + if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) ) + {$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;} + if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) ) + {$PATHagi = $line; $PATHagi =~ s/.*=//gi;} + if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) ) + {$PATHweb = $line; $PATHweb =~ s/.*=//gi;} + if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) ) + {$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;} + if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) ) + {$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;} + if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) ) + {$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;} + if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) ) + {$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;} + if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) ) + {$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;} + if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) ) + {$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;} + if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) ) + {$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;} + if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) ) + {$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;} + $i++; + } + +if (!$VARDB_port) {$VARDB_port='3306';} +if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";} + +use DBI; +use Asterisk::AGI; +$AGI = new Asterisk::AGI; + +$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass") + or die "Couldn't connect to database: " . DBI->errstr; + +### Grab Server values from the database +$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';"; +$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; +$sthA->execute or die "executing: $stmtA ", $dbhA->errstr; +$sthArows=$sthA->rows; +$rec_count=0; +while ($sthArows > $rec_count) + { + $AGILOG = '0'; + @aryA = $sthA->fetchrow_array; + $DBagi_output = $aryA[0]; + if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';} + if ($DBagi_output =~ /FILE/) {$AGILOG = '2';} + if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';} + $rec_count++; + } +$sthA->finish(); + +$AGILOG='3'; + +### begin parsing run-time options ### +if (length($ARGV[0])>1) + { + if ($AGILOG) {$agi_string = "Perl Environment Dump:"; &agi_output;} + $i=0; + while ($#ARGV >= $i) + { + $args = "$args $ARGV[$i]"; + if ($AGILOG) {$agi_string = "$i|$ARGV[$i]"; &agi_output;} + $i++; + } + + ### list of command-line array arguments: + @ARGV_vars = split(/---/, $ARGV[0]); + + $new_status = $ARGV_vars[0]; + $dnc_default = $ARGV_vars[1]; + $campaign_id = $ARGV_vars[2]; + $next_step = $ARGV_vars[3]; + $camp_sys = $ARGV_vars[4]; + $audio_file = $ARGV_vars[5]; + } + +if (length($new_status) < 1) + {$new_status = 'NI';} +if (length($dnc_default) < 2) + {$dnc_default = 'YES';} +if (length($next_step) < 1) + {$next_step = 'B';} +if (length($camp_sys) < 2) + {$camp_sys = 'SYS';} + +$|=1; +while() + { + chomp; + last unless length($_); + if ($AGILOG) + { + if (/^agi_(\w+)\:\s+(.*)$/) + { + $AGI{$1} = $2; + } + } + + if (/^agi_context\:\s+(.*)$/) {$context = $1;} + if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;} + if (/^agi_channel\:\s+(.*)$/) {$channel = $1;} + if (/^agi_extension\:\s+(.*)$/) {$extension = $1;} + if (/^agi_type\:\s+(.*)$/) {$type = $1;} + if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;} + if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;} + $callerid =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi; + $calleridname =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi; + $extension =~ s/\'|\"|\\\\|\\\|\\|\\;|\\\;|\;|;//gi; + + if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) ) + { + $calleridname = $callerid; + $calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi; + $calleridname =~ s/\"|\" //gi; + } + + $callerid =~ s/\D//gi; + $calleridname =~ s/unknown//gi; + if ( (!$callerid) or ($callerid =~ /unknown/) ) + {$callerid = $calleridname;} + + if (length($callerid)>0) {$phone_number = $callerid;} + else {$phone_number = '';} + if (length($calleridname)>0) {$VLcomments = $calleridname;} + else {$VLcomments = '';} + if (length($callerid)<10) {$callerid = $parked_by;} + if (length($pin)>0) {$callerid = $pin;} + } + +foreach $i (sort keys %AGI) + { + if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;} + } + +if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;} + + +# if campaign is used and selected for search, find the lists in the campaign +$listSQL=''; +if ( (length($campaign_id) > 0) && ($camp_sys =~ /CAMP/) ) + { + # Multiple campaigns should be separated by a SINGLE DASH if more than one should be used for looking up leads + $campaign_id=~s/\-/\',\'/gi; + $cbc=0; + $SlistsSQL=''; + $stmtA = "SELECT list_id FROM vicidial_lists where campaign_id in ('$campaign_id') limit 1000;"; + print "\n\n$stmtA\n\n"; + $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; + $sthArows=$sthA->rows; + if ($AGILOG) {$agi_string = "$sthArows|$stmtA|"; &agi_output;} + while ($sthArows > $cbc) + { + @aryA = $sthA->fetchrow_array; + $SlistsSQL .= "'$aryA[0]',"; + $cbc++; + } + $sthA->finish(); + chop($SlistsSQL); + + if (length($SlistsSQL)<3) + {$SlistsSQL = "''";} + if (length($SlistsSQL)>1) + {$listSQL = "and list_id IN($SlistsSQL)";} + } + + +### Gather the lead IDs of the leads with this phone number ### +$stmtA= "SELECT lead_id from vicidial_list where phone_number='$phone_number' $listSQL;"; +$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; +$sthA->execute or die "executing: $stmtA ", $dbhA->errstr; +$sthArows=$sthA->rows; + if ($AGILOG) {$agi_string = "$sthArows|$stmtA|"; &agi_output;} +$g=0; +$SleadsSQL=''; +while ($sthArows > $g) + { + @aryA = $sthA->fetchrow_array; + $SleadsSQL .= "'$aryA[0]',"; + $g++; + } +$sthA->finish(); +chop($SleadsSQL); + +### process for NI path +# JCJ changd 8/23 to update all leads regardless of status if status>0 +# JCJ REMOVED if ($new_status =~ /NI|IVDQ/) # set the phone_number to NI +if (length($new_status)>0) + { + if ($g > 0) + { + ### update all records for the phone_number in vicidial_list to NI (Not Interested), or whatever the new disposition is set to + $stmtA = "UPDATE vicidial_list SET status='$new_status' where lead_id IN($SleadsSQL);"; + $affected_rows = $dbhA->do($stmtA); + if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;} + } + } + +### process for DNC path +if ($new_status =~ /DNC/) # set the phone_number to DNC + { +# JCJ - Removed because we're doing this on all calls for the above section +# if ($g > 0) +# { + ### update all records for the phone_number in vicidial_list to NI (Not Interested) +# $stmtA = "UPDATE vicidial_list SET status='DNC' where lead_id IN($SleadsSQL);"; +# $affected_rows = $dbhA->do($stmtA); +# if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;} +# } + + if (length($campaign_id)>1) + { + ### Grab DNC settings from campaign + $stmtA = "SELECT use_internal_dnc,use_campaign_dnc FROM vicidial_campaigns where campaign_id = '$campaign_id';"; + $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; + $sthArows=$sthA->rows; + @aryA = $sthA->fetchrow_array; + $use_internal_dnc = $aryA[0]; + $use_campaign_dnc = $aryA[1]; + $sthA->finish(); + + if ( ($use_internal_dnc =~ /Y|AREACODE/) && ($dnc_default =~ /YES/) ) + { + ### add the number to the vicidial_dnc table + $stmtA = "INSERT IGNORE INTO vicidial_dnc SET phone_number='$phone_number';"; + $affected_rows = $dbhA->do($stmtA); + if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;} + + $stmtA="INSERT INTO vicidial_dnc_log SET phone_number='$phone_number', campaign_id='-SYSINT-', action='add', action_date=NOW(), user='CMAGI';"; + $affected_rows = $dbhA->do($stmtA); + if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;} + } + if ($use_campaign_dnc =~ /Y|AREACODE/) + { + ### add the number to the vicidial_campaign_dnc table + $stmtA = "INSERT IGNORE INTO vicidial_campaign_dnc SET phone_number='$phone_number',campaign_id='$campaign_id';"; + $affected_rows = $dbhA->do($stmtA); + if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;} + + $stmtA="INSERT INTO vicidial_dnc_log SET phone_number='$phone_number', campaign_id='$campaign_id', action='add', action_date=NOW(), user='CMAGI';"; + $affected_rows = $dbhA->do($stmtA); + if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;} + } + } + else + { + if ($dnc_default =~ /YES/) + { + ### add the number to the vicidial_dnc table + $stmtA = "INSERT INTO vicidial_dnc SET phone_number='$phone_number';"; + $affected_rows = $dbhA->do($stmtA); + if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;} + } + } + } +$dbhA->disconnect(); + +if (length($audio_file)>0) { + $AGI->exec("playback","$audio_file"); +} + +if ($AGILOG) {$agi_string = "exiting the cm_dnc app, transferring call to $next_step:$context |$phone_number|"; &agi_output;} +print "SET CONTEXT $context\n"; + $result = ; + checkresult($result); +print "SET EXTENSION $next_step\n"; + $result = ; + checkresult($result); +print "SET PRIORITY 1\n"; + $result = ; + checkresult($result); + +exit; + + + +sub agi_output +{ +if ($AGILOG >=2) + { + ### open the log file for writing ### + open(Lout, ">>$AGILOGfile") + || die "Can't open $AGILOGfile: $!\n"; + print Lout "$now_date|$script|$agi_string\n"; + close(Lout); + } + ### send to STDERR writing ### +if ( ($AGILOG == '1') || ($AGILOG == '3') ) + {print STDERR "$now_date|$script|$agi_string\n";} +$agi_string=''; +} + + +sub checkresult + { + my ($res) = @_; + my $retval; + $tests++; + chomp $res; + if ($res =~ /^200/) + { + $res =~ /result=(-?\d+)/; + if (!length($1)) + { + # print STDERR "FAIL ($res)\n"; + $fail++; + } + else + { + # print STDERR "PASS ($1)\n"; + $pass++; + } + } + else + { + # print STDERR "FAIL (unexpected result '$res')\n"; + $fail++; + } + } diff --git a/agc_2-X/trunk/extras/MySQL_AST_CREATE_tables.sql b/agc_2-X/trunk/extras/MySQL_AST_CREATE_tables.sql index 33e3f4ec..ff35a85a 100644 --- a/agc_2-X/trunk/extras/MySQL_AST_CREATE_tables.sql +++ b/agc_2-X/trunk/extras/MySQL_AST_CREATE_tables.sql @@ -3501,7 +3501,7 @@ ip VARCHAR(15) default '', PRIMARY KEY (recording_access_log_id), index(recording_id), index(lead_id) -) ENGINE=MyISAM AUTO_INCREMENT=1599 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=1599 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; CREATE TABLE vicidial_ivr_response ( id INT(11) unsigned NOT NULL AUTO_INCREMENT, @@ -3791,4 +3791,4 @@ UPDATE vicidial_configuration set value='1766' where name='qc_database_version'; UPDATE system_settings set vdc_agent_api_active='1'; -UPDATE system_settings SET db_schema_version='1466',db_schema_update_date=NOW(),reload_timestamp=NOW(); +UPDATE system_settings SET db_schema_version='1467',db_schema_update_date=NOW(),reload_timestamp=NOW(); diff --git a/agc_2-X/trunk/extras/upgrade_2.12.sql b/agc_2-X/trunk/extras/upgrade_2.12.sql index bed9c8ba..7b654bf3 100644 --- a/agc_2-X/trunk/extras/upgrade_2.12.sql +++ b/agc_2-X/trunk/extras/upgrade_2.12.sql @@ -650,3 +650,7 @@ ALTER TABLE recording_log_archive MODIFY recording_id INT(10) UNSIGNED UNIQUE NO ALTER TABLE recording_log_archive DROP PRIMARY KEY; UPDATE system_settings SET db_schema_version='1466',db_schema_update_date=NOW() where db_schema_version < 1466; + +ALTER TABLE vicidial_recording_access_log convert to character set utf8 collate utf8_unicode_ci; + +UPDATE system_settings SET db_schema_version='1467',db_schema_update_date=NOW() where db_schema_version < 1467;