Update of KHOMP code.

git-svn-id: svn://192.168.202.10@3524 3d104415-ff17-0410-8863-d5cf3c621b8a
This commit is contained in:
mattf
2021-09-23 04:22:12 +00:00
parent cbddea6fbb
commit b930ae2dcd
5 changed files with 2162 additions and 354 deletions
+721 -2
View File
@@ -125,6 +125,7 @@
# 191120-2235 - Added DYN multi-prompt survey prompts functionality
# 200825-2342 - Added option for auto-only sip actions
# 200915-2218 - Fixes for surveys with hash-star
# 210907-1254 - Added KHOMP code (install JSON::PP Perl module and remove '#UC#' in the code to enable)
#
$script = 'agi-VDAD_ALL_outbound.agi';
@@ -134,9 +135,32 @@ $mysql_log_count=147;
$one_mysql_log=0;
use Time::Local;
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use Time::HiRes ('tv_interval','gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
($START_s_hires, $START_usec) = gettimeofday();
# Needed for Khomp Integration
#UC# use JSON::PP qw(encode_json decode_json);
### find curl binary for KHOMP
$curlbin = '';
$khomp_enabled = 1;
if ( -e ('/bin/curl')) {$curlbin = '/bin/curl';}
else
{
if ( -e ('/usr/bin/curl')) {$curlbin = '/usr/bin/curl';}
else
{
if ( -e ('/usr/local/bin/curl')) {$curlbin = '/usr/local/bin/curl';}
else
{
if ($AGILOG) {$agi_string = "ERROR: curl binary not found, KHOMP disabled"; &agi_output;}
$khomp_enabled = 0;
}
}
}
$DROP_TIME = 9; ### default number of seconds to wait until you drop a waiting call
$at='@';
$US='_';
@@ -843,6 +867,144 @@ if ($VDACaffected_rows > 0)
}
$sthA->finish();
### if using KHOMP Analytics get relavant system settings
if ( $amd_type eq "KHOMP" )
{
$khomp_api_url = '';
$khomp_api_proxied = 'false';
$khomp_api_login_url = '';
$khomp_api_user = '';
$khomp_api_pass = '';
$khomp_header = '';
$khomp_id_format = '';
$stmtA = "SELECT container_entry FROM vicidial_settings_containers WHERE container_id = 'KHOMPSETTINGS';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$container_entry = $aryA[0];
my @lines = split ( /\n/, $container_entry );
foreach my $line (@lines)
{
# remove comments and blank lines
$line =~ /^\s*$/ and next; # skip blank lines
$line =~ /^\s*#/ and next; # skip line that begin with #
if ( $line =~ /#/ ) # check for comments midway through the line
{
# remove them
@split_line = split( /#/ , $line );
$line = $split_line[0];
}
if ( $line =~ /=>/ )
{
@setting = split( /=>/ , $line );
$key = $setting[0];
$key =~ s/^\s+|\s+$//g;
$value = $setting[1];
$value =~ s/^\s+|\s+$//g;
if ( $key eq 'khomp_api_url' ) { $khomp_api_url = $value; }
if ( $key eq 'khomp_api_proxied' ) { $khomp_api_proxied = $value; }
if ( $key eq 'khomp_api_user' ) { $khomp_api_user = $value; }
if ( $key eq 'khomp_api_pass' ) { $khomp_api_pass = $value; }
if ( $key eq 'khomp_header' ) { $khomp_header = $value; }
if ( $key eq 'khomp_id_format' ) { $khomp_id_format = $value; }
if ( $key eq 'khomp_api_login_url' ) { $khomp_api_login_url = $value; }
if ( $key eq 'khomp_api_token' ) { $khomp_api_token = $value; }
if ( $key eq 'khomp_api_token_expire' ) { $khomp_api_token_expire = $value; }
}
}
$agi_string = "KHOMP Settings: url-$khomp_api_url|proxied-$khomp_api_proxied|login_url-$khomp_api_login_url|user-$khomp_api_user|pass-$khomp_api_pass|header-$khomp_header|format-$khomp_id_format";
&agi_output;
}
### load the Khomp status map
%conclusion_map = {};
$stmtA = "SELECT container_entry FROM vicidial_settings_containers WHERE container_id = 'KHOMPSTATUSMAP';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$container_entry = $aryA[0];
my @lines = split ( /\n/, $container_entry );
foreach my $line (@lines)
{
# remove comments and blank lines
$line =~ /^\s*$/ and next; # skip blank lines
$line =~ /^\s*#/ and next; # skip line that begin with #
if ( $line =~ /#/ ) # check for comments midway through the line
{
# remove them
@split_line = split( /#/ , $line );
$line = $split_line[0];
}
if ( $line =~ /=>/ )
{
@setting = split( /=>/ , $line );
$conclusion_pattern = $setting[0];
$conclusion_pattern =~ s/^\s+|\s+$//g;
$action_status = $setting[1];
$action_status =~ s/^\s+|\s+$//g;
# check if the conclusion_pattern looks like "blah"."blahblah" or just "blah"
if ( $conclusion_pattern =~ /\./ )
{
# if "blah"."blahblah" break it up
@rsr = split( /\./ , $conclusion_pattern );
$conclusion = $rsr[0];
$conclusion =~ s/^\s+|\s+$//g;
$conclusion =~ s/^"|"$//g;
$pattern = $rsr[1];
$pattern =~ s/^\s+|\s+$//g;
$pattern =~ s/^"|"$//g;
}
else
{
# otherwise conclusion is the string and pattern is blank
$conclusion = $conclusion_pattern;
$conclusion =~ s/^\s+|\s+$//g;
$conclusion =~ s/^"|"$//g;
$pattern = "";
}
@as = split( /\./ , $action_status );
$action = @as[0];
$action =~ s/^\s+|\s+$//g;
$action =~ s/^"|"$//g;
$status = @as[1];
$status =~ s/^\s+|\s+$//g;
$status =~ s/^"|"$//g;
$dial_status = @as[2];
$dial_status =~ s/^\s+|\s+$//g;
$dial_status =~ s/^"|"$//g;
# load the result map hash with the values
$conclusion_map{"$conclusion"}{"$pattern"}{'action'} = $action;
$conclusion_map{"$conclusion"}{"$pattern"}{'status'} = $status;
$conclusion_map{"$conclusion"}{"$pattern"}{'dial_status'} = $dial_status;
}
}
}
}
##### BEGIN SIP Action check #####
if ( ($SIP_event_recent_inserted > 0) && ($SIP_event_action_checked < 1) && (length($CAMPsip_event_logging) > 0) and ($CAMPsip_event_logging !~ /^DISABLED$/i) )
@@ -1409,6 +1571,9 @@ if ($call_handle_method =~ /REMIND/)
{
$AGI->stream_file('sip-silence');
### Using Sangoma CPD
if ( $amd_type eq 'CPD' )
{
############# BEGIN CPD AMD SECTION ############################
if ($cpd_amd_action =~ /DISPO|MESSAGE|CALLMENU|INGROUP/)
{
@@ -1454,6 +1619,27 @@ if ($call_handle_method =~ /REMIND/)
}
}
############# END CPD Unknown SECTION ############################
}
### Using KHOMP call analytics
if (( $amd_type eq 'KHOMP' ) && ( $khomp_enabled ) )
{
process_khomp_analytics(
$khomp_api_url,
$khomp_api_proxied,
$khomp_api_login_url,
$khomp_api_user,
$khomp_api_pass,
$khomp_header,
$khomp_id_format,
$external_server_ip,
$VDADcampaign,
$callerid,
$cpd_amd_action,
$cpd_unknown_action,
$CIDlead_id
);
}
$stmtA = "UPDATE vicidial_auto_calls set last_update_time='$FDtsSQLdate',stage='REMIND-0' where callerid='$callerid' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
@@ -1490,6 +1676,9 @@ if ($call_handle_method =~ /SURVEY/)
{
$AGI->stream_file('sip-silence');
### Using Sangoma CPD
if ( $amd_type eq 'CPD' )
{
############# BEGIN CPD AMD SECTION ############################
if ($cpd_amd_action =~ /DISPO|MESSAGE|CALLMENU|INGROUP/)
{
@@ -1535,6 +1724,27 @@ if ($call_handle_method =~ /SURVEY/)
}
}
############# END CPD Unknown SECTION ############################
}
### Using KHOMP call analytics
if (( $amd_type eq 'KHOMP' ) && ( $khomp_enabled ) )
{
process_khomp_analytics(
$khomp_api_url,
$khomp_api_proxied,
$khomp_api_login_url,
$khomp_api_user,
$khomp_api_pass,
$khomp_header,
$khomp_id_format,
$external_server_ip,
$VDADcampaign,
$callerid,
$cpd_amd_action,
$cpd_unknown_action,
$CIDlead_id
);
}
$stmtA = "UPDATE vicidial_auto_calls set last_update_time='$FDtsSQLdate',stage='SURVEY-0' where callerid='$callerid' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
@@ -2400,6 +2610,26 @@ $drop_seconds=0;
$hold_message_counter=25;
$hold_tone_counter=0;
#### Using KHOMP analytics
if (( $amd_type eq 'KHOMP' ) && ( $khomp_enabled ) )
{
process_khomp_analytics(
$khomp_api_url,
$khomp_api_proxied,
$khomp_api_login_url,
$khomp_api_user,
$khomp_api_pass,
$khomp_header,
$khomp_id_format,
$external_server_ip,
$VDADcampaign,
$callerid,
$cpd_amd_action,
$cpd_unknown_action,
$CIDlead_id
);
}
while ($drop_timer <= $DROP_TIME)
{
$channel_status = $AGI->channel_status("$channel");
@@ -2418,7 +2648,9 @@ while ($drop_timer <= $DROP_TIME)
$drop_timer = ($drop_timer + $DROP_TIME);
}
}
### Using Sangoma CPD
if ( $amd_type eq 'CPD' )
{
############# BEGIN CPD AMD SECTION ############################
if ($cpd_amd_action =~ /DISPO|MESSAGE|CALLMENU|INGROUP/)
{
@@ -2463,6 +2695,7 @@ while ($drop_timer <= $DROP_TIME)
&cpd_end_call;
}
}
}
############# END CPD Unknown SECTION ############################
@@ -4977,3 +5210,489 @@ sub validate_cid_name
}
}
### code for processing KHOMP analytics
sub process_khomp_analytics
{
(
$khomp_api_url,
$khomp_api_proxied,
$khomp_api_login_url,
$khomp_api_user,
$khomp_api_pass,
$khomp_header,
$khomp_id_format,
$external_server_ip,
$campaign_id,
$callerid,
$cpd_amd_action,
$cpd_unknown_action,
$CIDlead_id
) = @_;
### Extra SIP Headers begin with an X
$khomp_header = "X-" . $khomp_header;
# determin khomp id format to use
if ($khomp_id_format eq 'CALLERCODE')
{ $khomp_id = $callerid; }
elsif ($khomp_id_format eq 'CALLERCODE_EXTERNIP')
{ $khomp_id = $callerid . '_' . $external_server_ip; }
elsif ($khomp_id_format eq 'CALLERCODE_CAMP_EXTERNIP')
{ $khomp_id = $callerid . '_' . $campaign_id . '_' . $external_server_ip; }
my $api_auth_time = 0;
if ( ($khomp_api_token_expire < time() ) or ( $khomp_api_token eq 'TOKENTOKENTOKEN' ))
{
if ($AGILOG) {$agi_string = "-- KHOMP API Token $khomp_api_token has expired at $khomp_api_token_expire"; &agi_output;}
# get a new API token
my $new_khomp_api_token = '';
if ( $khomp_api_proxied eq 'false' )
{
($new_khomp_api_token, $api_auth_time) = khomp_api_login( $khomp_api_login_url, $khomp_api_user, $khomp_api_pass );
}
# update the settings container
my $old_token_string = "khomp_api_token => $khomp_api_token";
my $new_token_string = "khomp_api_token => $new_khomp_api_token";
my $new_token_expire_time = time() + 3600;
my $old_token_expire_string = "khomp_api_token_expire => $khomp_api_token_expire";
my $new_token_expire_string = "khomp_api_token_expire => $new_token_expire_time";
# LOCK vicidial_settings_containers
$stmtA = "LOCK TABLES vicidial_settings_containers WRITE";
$dbhA->do($stmtA);
# UPDATE the Token
$stmtToken = "UPDATE vicidial_settings_containers SET container_entry = REGEXP_REPLACE(container_entry, '$old_token_string', '$new_token_string') WHERE container_id = 'KHOMPSETTINGS';";
$affected_rows = $dbhA->do($stmtToken);
# UPDATE the Expire time
$stmtExpire = "UPDATE vicidial_settings_containers SET container_entry = REGEXP_REPLACE(container_entry, '$old_token_expire_string', '$new_token_expire_string') WHERE container_id = 'KHOMPSETTINGS';";
$affected_rows = $dbhA->do($stmtExpire);
# Unlock vicidial_settings_containers
$stmtA = "UNLOCK TABLES";
$dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- KHOMP SC TOKEN UPDATE|$affected_rows|$stmtToken|"; &agi_output;}
if ($AGILOG) {$agi_string = "-- KHOMP SC TOKEN EXPIRE UPDATE|$affected_rows|$stmtExpire|"; &agi_output;}
# over write the old with the new
$khomp_api_token = $new_khomp_api_token;
}
else
{
if ($AGILOG) {$agi_string = "-- KHOMP API Token $khomp_api_token still valid till $khomp_api_token_expire"; &agi_output;}
}
if ( $khomp_api_token ne 'TOKENTOKENTOKEN' )
{
# build JSON object
my $khomp_request = {
'id' => 0,
'method' => 'CallList',
'params' => {
'token' => "$khomp_api_token",
'query' => {
'type' => "eq",
'field' => "sip_header:$khomp_header",
'values' => ["$khomp_id"],
},
'selected_fields' => ["sip_header:call-id", "start_stamp", "audio_stamp", "answer_stamp", "end_stamp", "analyzer_stamp", "analyzer_conclusion", "analyzer_pattern", "analyzer_action", "hangup_origin", "hangup_cause", "hangup_cause_sent"]
},
'jsonrpc' => '2.0',
};
# encode it as JSON
#UC# $khomp_json = encode_json( $khomp_request );
# call the API
($result, $api_query_time) = khomp_json_api( $khomp_json, $khomp_api_url );
# check the result
if ( $result =~ /^ERROR/ )
{
# we got an error so log it
if ($AGILOG) { $agi_string = "--KHOMP: $result"; &agi_output; }
}
else
{
# we got a result
if ( defined $result->{'result'}->{'calls'}[0]->{'fields'} )
{
my $khomp_call_data = $result->{'result'}->{'calls'}[0]->{'fields'};
%parsed_data = khomp_parse_call_data( $khomp_header, $khomp_id, $callerid, $CIDlead_id, $khomp_id_format, $khomp_call_data );
$parsed_data{'api_auth_time'} = $api_auth_time;
$parsed_data{'api_query_time'} = $api_query_time;
$conclusion = $parsed_data{'conclusion'};
$pattern = $parsed_data{'pattern'};
#$agi_string = Dumper( \%conclusion_map );
#&agi_output;
my $action = '';
my $status = '';
if ( defined ( $conclusion_map{"$conclusion"}{"$pattern"}{'action'} ) )
{
$action = $conclusion_map{"$conclusion"}{"$pattern"}{'action'};
$status = $conclusion_map{"$conclusion"}{"$pattern"}{'status'};
}
elsif ( defined( $conclusion_map{"$conclusion"}{''}{'action'} ) )
{
$action = $conclusion_map{"$conclusion"}{''}{'action'};
$status = $conclusion_map{"$conclusion"}{''}{'status'};
}
else
{
$action = 'route';
$status = 'KPEROR';
}
if ($AGILOG) { $agi_string = "--KHOMP: conclusion = $conclusion|pattern = $pattern|action = $action|status = $status"; &agi_output; }
if ( $action ne '' ) { $parsed_data{'vici_action'} = "$action"; }
if ( $status ne '' ) { $parsed_data{'vici_status'} = "$status"; }
# log the khomp data in the vicidial_khomp_log
log_khomp_call_data( %parsed_data );
# handle the AMD action
if (
(( $action eq 'amdaction' ) && ($cpd_amd_action =~ /DISPO|MESSAGE|CALLMENU|INGROUP/)) ||
(( $action eq 'cpdunknown' ) && ($cpd_unknown_action =~ /DISPO|MESSAGE|CALLMENU|INGROUP/)) ||
( $action eq 'status' )
)
{
khomp_end_call( %parsed_data );
}
if ( $action eq 'route' )
{
if ($AGILOG) { $agi_string = "--KHOMP: Routing Call"; &agi_output; }
}
if ( $action eq '' )
{
if ($AGILOG) { $agi_string = "--KHOMP: No Action Defined. Routing Call"; &agi_output; }
}
}
else
{
if ($AGILOG) { $agi_string = "--KHOMP: No Call Record Found"; &agi_output; }
}
}
}
else
{
if ($AGILOG) { $agi_string = "--KHOMP: Login Failed"; &agi_output; }
}
}
# code to log the khomp data in vicidial_khomp_log
sub log_khomp_call_data
{
%khomp_call_data = @_;
$stmtA = "UPDATE vicidial_khomp_log SET caller_code = '$khomp_call_data{'caller_code'}', lead_id = '$khomp_call_data{'lead_id'}', server_ip = '$VARserver_ip', khomp_header = '$khomp_call_data{'khomp_header'}', khomp_id = '$khomp_call_data{'khomp_id'}', khomp_id_format = '$khomp_call_data{'khomp_id_format'}', route_auth_time = '$khomp_call_data{'api_auth_time'}', route_query_time = '$khomp_call_data{'api_query_time'}'";
if ( defined( $khomp_call_data{'sip_call_id'} ) ) { $stmtA .= ", sip_call_id = '$khomp_call_data{'sip_call_id'}'"; }
if ( defined( $khomp_call_data{'start_epoch'} ) ) { $stmtA .= ", start_date = FROM_UNIXTIME($khomp_call_data{'start_epoch'})"; }
if ( defined( $khomp_call_data{'audio_epoch'} ) ) { $stmtA .= ", audio_date = FROM_UNIXTIME($khomp_call_data{'audio_epoch'})"; }
if ( defined( $khomp_call_data{'answer_epoch'} ) ) { $stmtA .= ", answer_date = FROM_UNIXTIME($khomp_call_data{'answer_epoch'})"; }
if ( defined( $khomp_call_data{'end_epoch'} ) ) { $stmtA .= ", end_date = FROM_UNIXTIME($khomp_call_data{'end_epoch'})"; }
if ( defined( $khomp_call_data{'analyzer_epoch'} ) ) { $stmtA .= ", analyzer_date = FROM_UNIXTIME($khomp_call_data{'analyzer_epoch'})"; }
if ( defined( $khomp_call_data{'conclusion'} ) ) { $stmtA .= ", conclusion = '$khomp_call_data{'conclusion'}'"; }
if ( defined( $khomp_call_data{'pattern'} ) ) { $stmtA .= ", pattern = '$khomp_call_data{'pattern'}'"; }
if ( defined( $khomp_call_data{'action'} ) ) { $stmtA .= ", action = '$khomp_call_data{'action'}'"; }
if ( defined( $khomp_call_data{'hangup_origin'} ) ) { $stmtA .= ", hangup_origin = '$khomp_call_data{'hangup_origin'}'"; }
if ( defined( $khomp_call_data{'hangup_cause_recv'} ) ) { $stmtA .= ", hangup_cause_recv = '$khomp_call_data{'hangup_cause_recv'}'"; }
if ( defined( $khomp_call_data{'hangup_cause_sent'} ) ) { $stmtA .= ", hangup_cause_sent = '$khomp_call_data{'hangup_cause_sent'}'"; }
if ( defined( $khomp_call_data{'vici_action'} ) ) { $stmtA .= ", vici_action = '$khomp_call_data{'vici_action'}'"; }
if ( defined( $khomp_call_data{'vici_status'} ) ) { $stmtA .= ", vici_status = '$khomp_call_data{'vici_status'}'"; }
$stmtA .= " WHERE khomp_id = '$khomp_call_data{'khomp_id'}'";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- KHOMP Log Update: |$stmtA|$affected_rows|"; &agi_output;}
}
sub khomp_end_call
{
%khomp_call_data = @_;
$vdad_action = $khomp_call_data{'vici_action'};
$vdad_result = $khomp_call_data{'vici_status'};
if ($AGILOG) {$agi_string = "-- VDAD KHOMP End Call |a:$vdad_action|s:$vdad_result|"; &agi_output;}
my $conclusion = $khomp_call_data{'conclusion'};
my $pattern = $khomp_call_data{'pattern'};
($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";
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec";
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
if ($enable_queuemetrics_logging > 0)
{
$dbhB = DBI->connect("DBI:mysql:$queuemetrics_dbname:$queuemetrics_server_ip:3306", "$queuemetrics_login", "$queuemetrics_pass")
or die "Couldn't connect to database: " . DBI->errstr;
if ($DBX) {print "CONNECTED TO DATABASE: $queuemetrics_server_ip|$queuemetrics_dbname\n";}
$stmtB = "INSERT INTO queue_log SET `partition`='P01',time_id='$now_date_epoch',call_id='$callerid',queue='$VDADcampaign',agent='NONE',verb='EXITWITHTIMEOUT',data1='1',serverid='$queuemetrics_log_id';";
$Baffected_rows = $dbhB->do($stmtB);
$dbhP=$dbhB; $stmtA=$stmtB; $mysql_count='01048'; $MEL_aff_rows=$Baffected_rows; &mysql_error_logging;
$stmtB = "INSERT INTO queue_log SET `partition`='P01',time_id='$now_date_epoch',call_id='$callerid',queue='$VDADcampaign',agent='NONE',verb='CALLSTATUS',data1='$vdad_result',serverid='$queuemetrics_log_id';";
$Baffected_rows = $dbhB->do($stmtB);
$dbhP=$dbhB; $stmtA=$stmtB; $mysql_count='01049'; $MEL_aff_rows=$Baffected_rows; &mysql_error_logging;
$dbhB->disconnect();
}
if ($drop_seconds < 1)
{
$drop_seconds = $DROP_TIME;
}
if (
( ($cpd_amd_action =~ /MESSAGE|CALLMENU|INGROUP/) && ($vdad_action eq 'amdaction') ) ||
( ($cpd_unknown_action =~ /MESSAGE|CALLMENU|INGROUP/) && ($vdad_action eq 'cpdunknown' ) )
)
{
$DROPexten = "8320";
$AMDSTATUS_set = $AGI->set_variable('AMDSTATUS', "CPDMACHINE");
$AMDCAUSE_set = $AGI->set_variable('AMDCAUSE', "$conclusion-$pattern");
}
else
{
$stmtA = "DELETE FROM vicidial_auto_calls where callerid='$callerid' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01052'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- VDAD KHOMP vac record deleted: |$affected_rows|$VDADcampaign|$callerid|"; &agi_output;}
}
$Euniqueid=$uniqueid;
$Euniqueid =~ s/\.\d+//gi;
$stmtA = "UPDATE vicidial_log FORCE INDEX(lead_id) set status='$vdad_result',end_epoch='$now_date_epoch',length_in_sec='$drop_seconds',term_reason='AGENT' where lead_id = '$CIDlead_id' and uniqueid LIKE \"$Euniqueid%\";";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01050'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- VDAD KHOMP vicidial_log update: |$affected_rows|$uniqueid"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='$vdad_result' where lead_id = '$CIDlead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01051'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- VDAD KHOMP vicidial_list update: |$affected_rows|$CIDlead_id"; &agi_output;}
### use STDOUT to send call to proper DROP location
$VHqueryCID = "VH$CIDdate$VDADconf_exten";
if (length($DROPexten)>0)
{ ### if DROP extension is defined then send the dropped call there instead of hangup
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
if ($AGILOG) {$agi_string = "exiting the VDAD app, KHOMP transferring call to $DROPexten"; &agi_output;}
print "SET CONTEXT $ext_context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $DROPexten\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
}
else
{
### insert a NEW record to the vicidial_manager table to be processed
$stmtA = "INSERT INTO vicidial_manager values('','','$SQLdate','NEW','N','$VARserver_ip','','Hangup','$VHqueryCID','Channel: $channel','','','','','','','','','')";
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01053'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- VDAD call_hungup KHOMP timout: |$CIDlead_id|$VHqueryCID|$VDADconf_exten|$channel|insert to vicidial_manager"; &agi_output;}
$AGI->hangup();
exit;
}
}
### code for parsing the call data into a useful data structure
sub khomp_parse_call_data
{
( $khomp_header, $khomp_id, $callerid, $lead_id, $khomp_id_format, $khomp_call_data ) = @_;
my %new_khomp_call_data;
#KHOMP Field Names - Meaning:
# sip_header:call-id - leg A - SIP Call-ID
# start_stamp - unix timestamp of the call start (first INVITE)
# audio_stamp - unix timestamp of the audio start (183)
# answer_stamp - unix timestamp of the call answer (200 OK)
# end_stamp - unix timestamp of call end
# analyzer_stamp - unix timestamp of Analytics conclusion
# analyzer_conclusion - the Analytics conclusion
# analyzer_pattern - The specific pattern that was detected (if any)
# analyzer_action - the action taken for the analytics conclusion
# hangup_origin - which leg hangup the call: leg a or leg b
# hangup_cause - hangup cause received
# hangup_cause_sent - the cause code that was sent
#
$new_khomp_call_data{'caller_code'} = $callerid;
$new_khomp_call_data{'lead_id'} = $lead_id;
$new_khomp_call_data{'khomp_header'} = $khomp_header;
$new_khomp_call_data{'khomp_id'} = $khomp_id;
$new_khomp_call_data{'khomp_id_format'} = $khomp_id_format;
$new_khomp_call_data{'sip_call_id'} = $khomp_call_data->{'sip_header:call-id'};
$new_khomp_call_data{'start_epoch'} = $khomp_call_data->{'start_stamp'};
$new_khomp_call_data{'audio_epoch'} = $khomp_call_data->{'audio_stamp'};
$new_khomp_call_data{'answer_epoch'} = $khomp_call_data->{'answer_stamp'};
$new_khomp_call_data{'end_epoch'} = $khomp_call_data->{'end_stamp'};
$new_khomp_call_data{'analyzer_epoch'} = $khomp_call_data->{'analyzer_stamp'};
$new_khomp_call_data{'conclusion'} = $khomp_call_data->{'analyzer_conclusion'};
$new_khomp_call_data{'pattern'} = $khomp_call_data->{'analyzer_pattern'};
$new_khomp_call_data{'action'} = $khomp_call_data->{'analyzer_action'};
$new_khomp_call_data{'hangup_origin'} = $khomp_call_data->{'hangup_origin'};
$new_khomp_call_data{'hangup_cause_recv'} = $khomp_call_data->{'hangup_cause'};
$new_khomp_call_data{'hangup_cause_sent'} = $khomp_call_data->{'hangup_cause_sent'};
# handle blank times
if ($new_khomp_call_data{'start_epoch'} eq '') { $new_khomp_call_data{'start_epoch'} = 0; }
if ($new_khomp_call_data{'audio_epoch'} eq '') { $new_khomp_call_data{'audio_epoch'} = 0; }
if ($new_khomp_call_data{'answer_epoch'} eq '') { $new_khomp_call_data{'answer_epoch'} = 0; }
if ($new_khomp_call_data{'end_epoch'} eq '') { $new_khomp_call_data{'end_epoch'} = 0; }
if ($new_khomp_call_data{'analyzer_epoch'} eq '') { $new_khomp_call_data{'analyzer_epoch'} = 0; }
# time is returned in milliseconds since 1970 we need seconds
if ($new_khomp_call_data{'start_epoch'} > 0) { $new_khomp_call_data{'start_epoch'} = $new_khomp_call_data{'start_epoch'} / 1000; }
if ($new_khomp_call_data{'audio_epoch'} > 0) { $new_khomp_call_data{'audio_epoch'} = $new_khomp_call_data{'audio_epoch'} / 1000; }
if ($new_khomp_call_data{'answer_epoch'} > 0) { $new_khomp_call_data{'answer_epoch'} = $new_khomp_call_data{'answer_epoch'} / 1000; }
if ($new_khomp_call_data{'end_epoch'} > 0) { $new_khomp_call_data{'end_epoch'} = $new_khomp_call_data{'end_epoch'} / 1000; }
if ($new_khomp_call_data{'analyzer_epoch'} > 0) { $new_khomp_call_data{'analyzer_epoch'} = $new_khomp_call_data{'analyzer_epoch'} / 1000; }
return %new_khomp_call_data;
}
### code for logging into KHOMP api
sub khomp_api_login
{
(
$khomp_api_login_url,
$khomp_api_user,
$khomp_api_pass
) = @_;
my $token = 'login';
my $auth_start_sec;
my $auth_start_usec;
my $auth_end_sec;
my $auth_end_usec;
my $auth_sec;
my $auth_usec;
my $api_auth_time;
($auth_start_sec, $auth_start_usec) = gettimeofday();
# build JSON object
my $login_json = {
'id' => 0,
'method' => 'SessionLogin',
'params' => {
'username' => "$khomp_api_user",
'password' => "$khomp_api_pass",
},
'jsonrpc' => '2.0',
};
# encode it as JSON
#UC# $login_json = encode_json( $login_json );
my $curl_cmd = "$curlbin -sS --data \'$login_json\' $khomp_api_login_url";
$agi_string = "-- KHOMP CURL COMMAND: $curl_cmd"; &agi_output;
$message = `$curl_cmd`;
chomp($message);
if ($AGILOG)
{
$agi_string = "-- KHOMP LOGIN URL: |$khomp_api_login_url|"; &agi_output;
$agi_string = "-- KHOMP LOGIN JSON : |$login_json|"; &agi_output;
$agi_string = "-- KHOMP LOGIN RESPONSE JSON: |$message|"; &agi_output;
}
#UC# $json = JSON::PP->new->ascii->pretty->allow_nonref;
#UC# $result = $json->decode($message);
$token = $result->{'result'}->{'token'};
($auth_end_sec, $auth_end_usec) = gettimeofday();
$api_auth_time = tv_interval ( [$auth_start_sec, $auth_start_usec], [$auth_end_sec, $auth_end_usec]);
return ($token, $api_auth_time);
}
### code for connecting to KHOMP api and passing JSON
sub khomp_json_api
{
( $khomp_json, $khomp_api_url ) = @_;
my $query_start_sec;
my $query_start_usec;
my $query_end_sec;
my $query_end_usec;
my $query_sec;
my $query_usec;
my $api_query_time;
($query_start_sec, $query_start_usec) = gettimeofday();
my $curl_cmd = "$curlbin -sS --data \'$khomp_json\' $khomp_api_url";
$agi_string = "-- KHOMP CURL COMMAND: $curl_cmd"; &agi_output;
$message = `$curl_cmd`;
chomp($message);
if ($AGILOG)
{
$agi_string = "-- KHOMP URL: |$khomp_api_url|"; &agi_output;
$agi_string = "-- KHOMP JSON : |$khomp_json|"; &agi_output;
$agi_string = "-- KHOMP RESPONSE JSON: |$message|"; &agi_output;
}
#UC# $json = JSON::PP->new->ascii->pretty->allow_nonref;
#UC# $result = $json->decode($message);
($query_end_sec, $query_end_usec) = gettimeofday();
$api_query_time = tv_interval ( [$query_start_sec, $query_start_usec], [$query_end_sec, $query_end_usec]);
return ($result, $api_query_time);
}
+741 -3
View File
@@ -91,6 +91,7 @@
# 210718-0358 - Fixes for 24-Hour Call Count Limits with standard Auto-Alt-Dialing
# 210719-1521 - Added additional state override methods for call_limit_24hour
# 210827-0936 - Added PJSIP compatibility
# 210907-0841 - Added KHOMP code (install JSON::PP Perl module and remove '#UC#' in the code to enable)
#
# defaults for PreFork
@@ -189,10 +190,29 @@ use Net::Server;
use vars qw(@ISA);
use Net::Server::PreFork; # any personality will do
@ISA = qw(Net::Server::PreFork);
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use Time::HiRes ('tv_interval','gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use Time::Local;
# Needed for Khomp Integration
#UC# use JSON::PP qw(encode_json decode_json);
### find curl binary for KHOMP
$curlbin = '';
$khomp_enabled = 1;
if ( -e ('/bin/curl')) {$curlbin = '/bin/curl';}
else
{
if ( -e ('/usr/bin/curl')) {$curlbin = '/usr/bin/curl';}
else
{
if ( -e ('/usr/local/bin/curl')) {$curlbin = '/usr/local/bin/curl';}
else
{
if ($AGILOG) {$agi_string = "ERROR: curl binary not found, KHOMP disabled"; &agi_output;}
$khomp_enabled = 0;
}
}
}
sub process_request
@@ -265,7 +285,7 @@ sub process_request
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output,asterisk_version FROM servers where server_ip = '$VARserver_ip';";
$stmtA = "SELECT agi_output,asterisk_version,external_server_ip 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;
@@ -275,6 +295,7 @@ sub process_request
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
$asterisk_version = $aryA[1];
$external_server_ip = $aryA[2];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
@@ -286,6 +307,144 @@ sub process_request
if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} >= 12))
{$h_exten_reason=1;}
### Grab KHOMP settings from the KHOMPSETTINGS settings container
$khomp_api_url = '';
$khomp_api_proxied = 'false';
$khomp_api_login_url = '';
$khomp_api_user = '';
$khomp_api_pass = '';
$khomp_header = '';
$khomp_id_format = '';
$khomp_sub_account_header = '';
$stmtA = "SELECT container_entry FROM vicidial_settings_containers WHERE container_id = 'KHOMPSETTINGS';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$container_entry = $aryA[0];
my @lines = split ( /\n/, $container_entry );
foreach my $line (@lines)
{
# remove comments and blank lines
$line =~ /^\s*$/ and next; # skip blank lines
$line =~ /^\s*#/ and next; # skip line that begin with #
if ( $line =~ /#/ ) # check for comments midway through the line
{
# remove them
@split_line = split( /#/ , $line );
$line = $split_line[0];
}
if ( $line =~ /=>/ )
{
@setting = split( /=>/ , $line );
$key = $setting[0];
$key =~ s/^\s+|\s+$//g;
$value = $setting[1];
$value =~ s/^\s+|\s+$//g;
if ( $key eq 'khomp_api_url' ) { $khomp_api_url = $value; }
if ( $key eq 'khomp_api_proxied' ) { $khomp_api_proxied = $value; }
if ( $key eq 'khomp_api_user' ) { $khomp_api_user = $value; }
if ( $key eq 'khomp_api_pass' ) { $khomp_api_pass = $value; }
if ( $key eq 'khomp_header' ) { $khomp_header = $value; }
if ( $key eq 'khomp_id_format' ) { $khomp_id_format = $value; }
if ( $key eq 'khomp_api_login_url' ) { $khomp_api_login_url = $value; }
if ( $key eq 'khomp_sub_account_header' ) { $khomp_sub_account_header = $value; }
if ( $key eq 'khomp_api_token' ) { $khomp_api_token = $value; }
if ( $key eq 'khomp_api_token_expire' ) { $khomp_api_token_expire = $value; }
}
}
$agi_string = "KHOMP Settings: url-$khomp_api_url|user-$khomp_api_user|pass-$khomp_api_pass|header-$khomp_header|format-$khomp_id_format|sub-account-$khomp_sub_account_header";
#&agi_output;
}
### load the Khomp status map
%conclusion_map = {};
$stmtA = "SELECT container_entry FROM vicidial_settings_containers WHERE container_id = 'KHOMPSTATUSMAP';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$container_entry = $aryA[0];
my @lines = split ( /\n/, $container_entry );
foreach my $line (@lines)
{
# remove comments and blank lines
$line =~ /^\s*$/ and next; # skip blank lines
$line =~ /^\s*#/ and next; # skip line that begin with #
if ( $line =~ /#/ ) # check for comments midway through the line
{
# remove them
@split_line = split( /#/ , $line );
$line = $split_line[0];
}
if ( $line =~ /=>/ )
{
@setting = split( /=>/ , $line );
$conclusion_pattern = $setting[0];
$conclusion_pattern =~ s/^\s+|\s+$//g;
$action_status = $setting[1];
$action_status =~ s/^\s+|\s+$//g;
# check if the conclusion_pattern looks like "blah"."blahblah" or just "blah"
if ( $conclusion_pattern =~ /"\."/ )
{
# if "blah"."blahblah" break it up
@rsr = split( /"\."/ , $conclusion_pattern );
$conclusion = $rsr[0];
$conclusion =~ s/^\s+|\s+$//g;
$conclusion =~ s/^"|"$//g;
$pattern = $rsr[1];
$pattern =~ s/^\s+|\s+$//g;
$pattern =~ s/^"|"$//g;
}
else
{
# otherwise result is the string and pattern is blank
$conclusion = $conclusion_pattern;
$conclusion =~ s/^\s+|\s+$//g;
$conclusion =~ s/^"|"$//g;
$pattern = "";
}
@as = split( /\./ , $action_status );
$action = @as[0];
$action =~ s/^\s+|\s+$//g;
$action =~ s/^"|"$//g;
$status = @as[1];
$status =~ s/^\s+|\s+$//g;
$status =~ s/^"|"$//g;
$dial_status = @as[2];
$dial_status =~ s/^\s+|\s+$//g;
$dial_status =~ s/^"|"$//g;
# load the result map hash with the values
$conclusion_map{"$conclusion"}{"$pattern"}{'action'} = $action;
$conclusion_map{"$conclusion"}{"$pattern"}{'status'} = $status;
$conclusion_map{"$conclusion"}{"$pattern"}{'dial_status'} = $dial_status;
}
}
}
if ($AGILOG)
{
$agi_string = "+++++++++++++++++ FastAGI Start ++++ Asterisk version: $ast_ver_str{major} $ast_ver_str{minor} ++++++ hER: $h_exten_reason ++++++";
@@ -392,6 +551,7 @@ sub process_request
$callerid =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$calleridname =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$extension =~ s/\'|\"|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$agi_called_ext = $extension;
if ($AGILOG)
{
@@ -550,14 +710,31 @@ sub process_request
{
@aryA = $sthA->fetchrow_array;
$CAMPCUST = $aryA[0];
$campaign = $aryA[0];
}
$sthA->finish();
### get campaign settings
$stmtA = "SELECT amd_type,campaign_vdad_exten FROM vicidial_campaigns where campaign_id = '$campaign';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$amd_type = $aryA[0];
$campaign_vdad_exten = $aryA[1];
}
$sthA->finish();
### set dialplan variable CAMPCUST to the campaign_id of the outbound auto-dial or manual dial call
if (length($CAMPCUST) > 0)
{
$AGI->exec("EXEC Set(_CAMPCUST=$CAMPCUST)");
if ($AGILOG) {$agi_string = "|CAMPCUST: $CAMPCUST|$callerid|"; &agi_output;}
}
### BEGIN OpenSIPs CallerIDname code ###
### get system_settings
$stmtA = "SELECT opensips_cid_name FROM system_settings";
@@ -597,6 +774,36 @@ sub process_request
}
}
### END OpenSIPs CallerIDname code ###
if ($AGILOG) {$agi_string = "|KHOMP $amd_type|$HVcauses|$extension|$campaign_vdad_exten"; &agi_output;}
### Add the KHOMP SIP X header to the outbound call
if (( $amd_type eq 'KHOMP' ) && ($agi_called_ext!= $campaign_vdad_exten))
{
# determin header format
if ($khomp_id_format eq 'CALLERCODE')
{ $khomp_id = $callerid; }
elsif ($khomp_id_format eq 'CALLERCODE_EXTERNIP')
{ $khomp_id = $callerid . '_' . $external_server_ip; }
elsif ($khomp_id_format eq 'CALLERCODE_CAMP_EXTERNIP')
{ $khomp_id = $callerid . '_' . $campaign . '_' . $external_server_ip; }
$stmtA = "INSERT INTO vicidial_khomp_log SET caller_code = '$callerid', lead_id = '$lead_id', server_ip = '$VARserver_ip', khomp_header = '$khomp_header', khomp_id = '$khomp_id', khomp_id_format = '$khomp_id_format', start_date=NOW()";
if ($AGILOG) {$agi_string = "-- KHOMP Log Insert: |$stmtA|"; &agi_output;}
$dbhA->do($stmtA);
# add the SIP tracking header
$header = "X-" . $khomp_header . ": " . $khomp_id;
$AGI->exec("EXEC SIPAddHeader(\"$header\")");
if ($AGILOG) {$agi_string = "|KHOMP SIP Header= $header|$khomp_id_format|"; &agi_output;}
if ( $khomp_sub_account_header ne '' )
{
$sub_header = "X-KHOMP-Sub-Account:" . $khomp_sub_account_header;
$AGI->exec("EXEC SIPAddHeader(\"$sub_header\")");
if ($AGILOG) {$agi_string = "|KHOMP Sub Account Header= $sub_header|"; &agi_output;}
}
}
}
$stmtA = "INSERT INTO call_log (uniqueid,channel,channel_group,type,server_ip,extension,number_dialed,start_time,start_epoch,end_time,end_epoch,length_in_sec,length_in_min,caller_code) values('$unique_id','$channel','$channel_group','$type','$VARserver_ip','$extension','$number_dialed','$now_date','$now_date_epoch','','','','','$callerid')";
@@ -960,6 +1167,72 @@ sub process_request
if ($AGILOG) {$agi_string = "VD_hangup : $callerid $channel $priority $CIDlead_id"; &agi_output;}
if ($callerid =~ /^V\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/)
{
$campaign='';
# check vac for the call to get the campaign id
$stmtA = "SELECT campaign_id FROM vicidial_auto_calls where uniqueid = '$unique_id' or callerid = '$callerid' limit 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$campaign = $aryA[0];
}
$sthA->finish();
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
# vac does not have a record of the call check the vl
if ( $campaign eq '' )
{
$stmtA = "SELECT campaign_id FROM vicidial_log where uniqueid = '$unique_id' limit 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$campaign = $aryA[0];
}
$sthA->finish();
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
}
### get campaign settings
$stmtA = "SELECT amd_type FROM vicidial_campaigns where campaign_id = '$campaign';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$amd_type = $aryA[0];
}
$sthA->finish();
if (( $amd_type eq 'KHOMP' ) && ( $khomp_enabled ) )
{
if ($AGILOG) {$agi_string = "-- KHOMP process call for campaign $campaign callerid $callerid"; &agi_output;}
( $khomp_action, $khomp_VDL_status, $khomp_VDAC_status ) = process_khomp_analytics(
$khomp_api_url,
$khomp_api_proxied,
$khomp_api_login_url,
$khomp_api_user,
$khomp_api_pass,
$khomp_header,
$khomp_id_format,
$external_server_ip,
$campaign,
$callerid,
$cpd_amd_action,
$cpd_unknown_action,
$CIDlead_id
);
}
}
if ($channel =~ /^Local/)
{
$enhanced_disconnect_logging=0;
@@ -998,7 +1271,8 @@ sub process_request
#
# if ($AGILOG) {$agi_string = "HiRes Time: $callerid|$channel|$priority|$CIDlead_id|$uniqueid|$HRnow_date|$now_date"; &agi_output;}
if ( $amd_type eq 'CPD' )
{
##############################################################
### BEGIN - CPD Look for result for B/DC calls
##############################################################
@@ -1035,6 +1309,29 @@ sub process_request
### END - CPD Look for result for B/DC calls
##############################################################
}
##############################################################
### BEGIN - KHOMP status B/DC calls based off result
##############################################################
if (( $amd_type eq 'KHOMP' ) && ( $khomp_VDL_status ne 'ERROR' ) && ( $khomp_VDAC_status ne 'ERROR' ))
{
$VDL_status = $khomp_VDL_status;
$VDAC_status = $khomp_VDAC_status;
if ($AGILOG) {$agi_string = "-- KHOMP CPDfound=$CPDfound|khomp_action=$khomp_action|$callerid"; &agi_output;}
if (
( ( $khomp_action eq 'cpdunknown') && (( $cpd_unknown_action eq 'MESSAGE' ) || ( $cpd_unknown_action eq 'DISPO' ))) ||
( ( $khomp_action eq 'amdaction') && (( $cpd_amd_action eq 'MESSAGE' ) || ( $cpd_amd_action eq 'DISPO' ))) ||
( $khomp_action eq 'status')
)
{ $CPDfound = 1; }
if ($AGILOG) {$agi_string = "-- KHOMP setting VDL_status = $VDL_status | VDAC_status = $VDAC_status"; &agi_output;}
}
##############################################################
### END - KHOMP status B/DC calls based off result
##############################################################
}
if ( ($PRI =~ /^PRI$/) && ($callerid =~ /\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) && ( ( ($dialstatus =~ /BUSY/) || ( ($dialstatus =~ /CHANUNAVAIL/) && ($hangup_cause =~ /^1$|^28$/) ) || ( ($enhanced_disconnect_logging > 0) && ( ( ($dialstatus =~ /CONGESTION/) && ($hangup_cause =~ /^1$|^19$|^21$|^34$|^38$|^102$/) ) || ( ($dialstatus =~ /CHANUNAVAIL/) && ($hangup_cause =~ /^18$/) ) || ($dialstatus =~ /DNC|DISCONNECT/) ) ) || ($CPDfound > 0) && ($callerid !~ /^S\d\d\d\d\d\d\d\d\d\d\d\d/) ) ) )
{
if ($CPDfound < 1)
@@ -2760,3 +3057,444 @@ sub parse_asterisk_version
return ( %ast_ver_hash );
}
### code for processing KHOMP analytics
sub process_khomp_analytics
{
(
$khomp_api_url,
$khomp_api_proxied,
$khomp_api_login_url,
$khomp_api_user,
$khomp_api_pass,
$khomp_header,
$khomp_id_format,
$external_server_ip,
$campaign_id,
$callerid,
$cpd_amd_action,
$cpd_unknown_action,
$CIDlead_id
) = @_;
### Extra SIP Headers begin with an X
$khomp_header = "X-" . $khomp_header;
# determin khomp id format to use
if ($khomp_id_format eq 'CALLERCODE')
{ $khomp_id = $callerid; }
elsif ($khomp_id_format eq 'CALLERCODE_EXTERNIP')
{ $khomp_id = $callerid . '_' . $external_server_ip; }
elsif ($khomp_id_format eq 'CALLERCODE_CAMP_EXTERNIP')
{ $khomp_id = $callerid . '_' . $campaign_id . '_' . $external_server_ip; }
my $api_auth_time = 0;
if ( ($khomp_api_token_expire < time() ) or ( $khomp_api_token eq 'TOKENTOKENTOKEN' ))
{
if ($AGILOG) {$agi_string = "-- KHOMP API Token $khomp_api_token has expired at $khomp_api_token_expire"; &agi_output;}
# get a new API token
my $new_khomp_api_token = '';
if ( $khomp_api_proxied eq 'false' )
{
($new_khomp_api_token, $api_auth_time) = khomp_api_login( $khomp_api_login_url, $khomp_api_user, $khomp_api_pass );
}
# update the settings container
my $old_token_string = "khomp_api_token => $khomp_api_token";
my $new_token_string = "khomp_api_token => $new_khomp_api_token";
my $new_token_expire_time = time() + 3600;
my $old_token_expire_string = "khomp_api_token_expire => $khomp_api_token_expire";
my $new_token_expire_string = "khomp_api_token_expire => $new_token_expire_time";
# LOCK vicidial_settings_containers
$stmtA = "LOCK TABLES vicidial_settings_containers WRITE";
$dbhA->do($stmtA);
# UPDATE the Token
$stmtToken = "UPDATE vicidial_settings_containers SET container_entry = REGEXP_REPLACE(container_entry, '$old_token_string', '$new_token_string') WHERE container_id = 'KHOMPSETTINGS';";
$affected_rows = $dbhA->do($stmtToken);
# UPDATE the Expire time
$stmtExpire = "UPDATE vicidial_settings_containers SET container_entry = REGEXP_REPLACE(container_entry, '$old_token_expire_string', '$new_token_expire_string') WHERE container_id = 'KHOMPSETTINGS';";
$affected_rows = $dbhA->do($stmtExpire);
# Unlock vicidial_settings_containers
$stmtA = "UNLOCK TABLES";
$dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- KHOMP SC TOKEN UPDATE|$affected_rows|$stmtToken|"; &agi_output;}
if ($AGILOG) {$agi_string = "-- KHOMP SC TOKEN EXPIRE UPDATE|$affected_rows|$stmtExpire|"; &agi_output;}
# over write the old with the new
$khomp_api_token = $new_khomp_api_token;
}
else
{
if ($AGILOG) {$agi_string = "-- KHOMP API Token $khomp_api_token still valid till $khomp_api_token_expire"; &agi_output;}
}
if ( $khomp_api_token ne 'TOKENTOKENTOKEN' )
{
# build JSON object
my $khomp_request = {
'id' => 0,
'method' => 'CallList',
'params' => {
'token' => "$khomp_api_token",
'query' => {
'type' => "eq",
'field' => "sip_header:$khomp_header",
'values' => ["$khomp_id"],
},
'selected_fields' => ["sip_header:call-id", "start_stamp", "audio_stamp", "answer_stamp", "end_stamp", "analyzer_stamp", "analyzer_conclusion", "analyzer_pattern", "analyzer_action", "hangup_origin", "hangup_cause", "hangup_cause_sent"]
},
'jsonrpc' => '2.0',
};
# encode it as JSON
#UC# $khomp_json = encode_json( $khomp_request );
# call the API
#UC# ($result, $api_query_time) = khomp_json_api( $khomp_json, $khomp_api_url );
# check the result
if ( $result =~ /^ERROR/ )
{
# we got an error so log it
if ($AGILOG) { $agi_string = "-- KHOMP: $result"; &agi_output; }
}
else
{
# we got a result
if ( defined $result->{'result'}->{'calls'}[0]->{'fields'} )
{
my $khomp_call_data = $result->{'result'}->{'calls'}[0]->{'fields'};
%parsed_data = khomp_parse_call_data( $khomp_header, $khomp_id, $callerid, $CIDlead_id, $khomp_id_format, $khomp_call_data );
$parsed_data{'api_auth_time'} = $api_auth_time;
$parsed_data{'api_query_time'} = $api_query_time;
$conclusion = $parsed_data{'conclusion'};
$pattern = $parsed_data{'pattern'};
my $khomp_VDL_status = '';
my $khomp_VDAC_status = '';
my $khomp_action = '';
if ( $conclusion ne "" )
{
# we got a conclusion
if ( defined ( $conclusion_map{"$conclusion"}{"$pattern"}{'status'} ) )
{
# see if there is a conclusion and pattern for it
$khomp_action = $conclusion_map{"$conclusion"}{"$pattern"}{'action'};
$khomp_VDL_status = $conclusion_map{"$conclusion"}{"$pattern"}{'status'};
$khomp_VDAC_status = $conclusion_map{"$conclusion"}{"$pattern"}{'dial_status'};
}
elsif ( defined( $conclusion_map{"$conclusion"}{''}{'status'} ) )
{
# there is no known pattern for it
$khomp_action = $conclusion_map{"$conclusion"}{""}{'action'};
$khomp_VDL_status = $conclusion_map{"$conclusion"}{''}{'status'};
$khomp_VDAC_status = $conclusion_map{"$conclusion"}{""}{'dial_status'};
}
else
{
# there isnt even a known conclusion for it
$khomp_action = 'error';
$khomp_VDL_status = 'KPEROR';
$khomp_VDAC_status = 'NA';
}
}
else
{
# no conclusion was made
if ( $parsed_data{'hangup_origin'} eq 'leg a' )
{
# Vicidial Hung Up
# Not sure what to do here
}
elsif ( $parsed_data{'hangup_origin'} eq 'leg b' )
{
# Khomp or Carrier Did Not Answer
if ( $parsed_data{'hangup_cause_recv'} eq '20003' )
{
# No Channels Available on KHOMP equipment
$khomp_action = 'status';
$khomp_VDL_status = 'KPNOCH';
$khomp_VDAC_status = 'CONGESTION';
}
elsif ( $parsed_data{'hangup_cause_recv'} eq '30000' )
{
# No sip response was recieved for KHOMP's INVITE
$khomp_action = 'status';
$khomp_VDL_status = 'KPTMOT';
$khomp_VDAC_status = 'CONGESTION';
}
elsif ( $parsed_data{'hangup_cause_recv'} eq '486' )
{
# Carrier returned "Busy Here"
$khomp_action = 'status';
$khomp_VDL_status = 'KPBUSY';
$khomp_VDAC_status = 'BUSY';
}
elsif (
( $parsed_data{'hangup_cause_recv'} eq '487' ) &&
( $parsed_data{'answer_epoch'} > 0 )
)
{
# Call hung up before Khomp had a conclusion
$khomp_action = 'status';
$khomp_VDL_status = 'KPDROP';
$khomp_VDAC_status = 'ANSWER';
}
elsif ( $parsed_data{'hangup_cause_recv'} eq '488' )
{
# Carrier returned "Not Acceptable Here"
# Normally an audio codec issue, but could be other things
$khomp_action = 'status';
$khomp_VDL_status = 'KPCONG';
$khomp_VDAC_status = 'CONGESTION';
}
elsif ( $parsed_data{'hangup_cause_recv'} eq '500' )
{
# Carrier returned "Internal Server Error"
$khomp_action = 'status';
$khomp_VDL_status = 'KPCONG';
$khomp_VDAC_status = 'CONGESTION';
}
elsif ( $parsed_data{'hangup_cause_recv'} eq '503' )
{
# Carrier returned "Service Unavailable"
$khomp_action = 'status';
$khomp_VDL_status = 'KPCONG';
$khomp_VDAC_status = 'CONGESTION';
}
elsif ( $parsed_data{'hangup_cause_recv'} eq '603' )
{
# Carrier returned "Decline"
$khomp_action = 'status';
$khomp_VDL_status = 'KPCONG';
$khomp_VDAC_status = 'CONGESTION';
}
else
{
$khomp_action = 'error';
$khomp_VDL_status = 'KPEROR';
$khomp_VDAC_status = 'NA';
}
}
}
if ( $khomp_action ne '' ) { $parsed_data{'vici_action'} = "$khomp_action"; }
if ( $khomp_VDL_status ne '' ) { $parsed_data{'vici_status'} = "$khomp_VDL_status"; }
# log the khomp data in the vicidial_khomp_log
log_khomp_call_data( %parsed_data);
if ($AGILOG) { $agi_string = "--KHOMP: conclusion = $conclusion|pattern = $pattern|status = $khomp_VDL_status"; &agi_output; }
return ( $khomp_action, $khomp_VDL_status, $khomp_VDAC_status );
}
else
{
if ($AGILOG) { $agi_string = "-- KHOMP: No Call Record Found"; &agi_output; }
return ( 'error', 'ERROR', 'ERROR' );
}
}
}
else
{
if ($AGILOG) { $agi_string = "--KHOMP: Login Failed"; &agi_output; }
return ( 'error', 'ERROR', 'ERROR');
}
}
# code to log the khomp data in vicidial_khomp_log
sub log_khomp_call_data
{
(%khomp_call_data) = @_;
$stmtA = "UPDATE vicidial_khomp_log SET caller_code = '$khomp_call_data{'caller_code'}', lead_id = '$khomp_call_data{'lead_id'}', server_ip = '$VARserver_ip', khomp_header = '$khomp_call_data{'khomp_header'}', khomp_id = '$khomp_call_data{'khomp_id'}', khomp_id_format = '$khomp_call_data{'khomp_id_format'}', hangup_auth_time = '$khomp_call_data{'api_auth_time'}', hangup_query_time = '$khomp_call_data{'api_query_time'}'";
if ( defined( $khomp_call_data{'sip_call_id'} ) ) { $stmtA .= ", sip_call_id = '$khomp_call_data{'sip_call_id'}'"; }
if ( defined( $khomp_call_data{'start_epoch'} ) ) { $stmtA .= ", start_date = FROM_UNIXTIME($khomp_call_data{'start_epoch'})"; }
if ( defined( $khomp_call_data{'audio_epoch'} ) ) { $stmtA .= ", audio_date = FROM_UNIXTIME($khomp_call_data{'audio_epoch'})"; }
if ( defined( $khomp_call_data{'answer_epoch'} ) ) { $stmtA .= ", answer_date = FROM_UNIXTIME($khomp_call_data{'answer_epoch'})"; }
if ( defined( $khomp_call_data{'end_epoch'} ) ) { $stmtA .= ", end_date = FROM_UNIXTIME($khomp_call_data{'end_epoch'})"; }
if ( defined( $khomp_call_data{'analyzer_epoch'} ) ) { $stmtA .= ", analyzer_date = FROM_UNIXTIME($khomp_call_data{'analyzer_epoch'})"; }
if ( defined( $khomp_call_data{'conclusion'} ) ) { $stmtA .= ", conclusion = '$khomp_call_data{'conclusion'}'"; }
if ( defined( $khomp_call_data{'pattern'} ) ) { $stmtA .= ", pattern = '$khomp_call_data{'pattern'}'"; }
if ( defined( $khomp_call_data{'action'} ) ) { $stmtA .= ", action = '$khomp_call_data{'action'}'"; }
if ( defined( $khomp_call_data{'hangup_origin'} ) ) { $stmtA .= ", hangup_origin = '$khomp_call_data{'hangup_origin'}'"; }
if ( defined( $khomp_call_data{'hangup_cause_recv'} ) ) { $stmtA .= ", hangup_cause_recv = '$khomp_call_data{'hangup_cause_recv'}'"; }
if ( defined( $khomp_call_data{'hangup_cause_sent'} ) ) { $stmtA .= ", hangup_cause_sent = '$khomp_call_data{'hangup_cause_sent'}'"; }
if ( defined( $khomp_call_data{'vici_action'} ) ) { $stmtA .= ", vici_action = '$khomp_call_data{'vici_action'}'"; }
if ( defined( $khomp_call_data{'vici_status'} ) ) { $stmtA .= ", vici_status = '$khomp_call_data{'vici_status'}'"; }
$stmtA .= " WHERE khomp_id = '$khomp_call_data{'khomp_id'}'";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- KHOMP Log Update: |$stmtA|$affected_rows|"; &agi_output;}
}
### code for parsing the call data into a useful data structure
sub khomp_parse_call_data
{
( $khomp_header, $khomp_id, $callerid, $lead_id, $khomp_id_format, $khomp_call_data ) = @_;
my %new_khomp_call_data;
#KHOMP Field Names - Meaning:
# sip_header:call-id - leg A - SIP Call-ID
# start_stamp - unix timestamp of the call start (first INVITE)
# audio_stamp - unix timestamp of the audio start (183)
# answer_stamp - unix timestamp of the call answer (200 OK)
# end_stamp - unix timestamp of call end
# analyzer_stamp - unix timestamp of Analytics conclusion
# analyzer_conclusion - the Analytics conclusion
# analyzer_pattern - The specific pattern that was detected (if any)
# analyzer_action - the action taken for the analytics conclusion
# hangup_origin - which leg hangup the call: leg a or leg b
# hangup_cause - hangup cause received
# hangup_cause_sent - the cause code that was sent
#
$new_khomp_call_data{'caller_code'} = $callerid;
$new_khomp_call_data{'lead_id'} = $lead_id;
$new_khomp_call_data{'khomp_header'} = $khomp_header;
$new_khomp_call_data{'khomp_id'} = $khomp_id;
$new_khomp_call_data{'khomp_id_format'} = $khomp_id_format;
$new_khomp_call_data{'sip_call_id'} = $khomp_call_data->{'sip_header:call-id'};
$new_khomp_call_data{'start_epoch'} = $khomp_call_data->{'start_stamp'};
$new_khomp_call_data{'audio_epoch'} = $khomp_call_data->{'audio_stamp'};
$new_khomp_call_data{'answer_epoch'} = $khomp_call_data->{'answer_stamp'};
$new_khomp_call_data{'end_epoch'} = $khomp_call_data->{'end_stamp'};
$new_khomp_call_data{'analyzer_epoch'} = $khomp_call_data->{'analyzer_stamp'};
$new_khomp_call_data{'conclusion'} = $khomp_call_data->{'analyzer_conclusion'};
$new_khomp_call_data{'pattern'} = $khomp_call_data->{'analyzer_pattern'};
$new_khomp_call_data{'action'} = $khomp_call_data->{'analyzer_action'};
$new_khomp_call_data{'hangup_origin'} = $khomp_call_data->{'hangup_origin'};
$new_khomp_call_data{'hangup_cause_recv'} = $khomp_call_data->{'hangup_cause'};
$new_khomp_call_data{'hangup_cause_sent'} = $khomp_call_data->{'hangup_cause_sent'};
# handle blank times
if ($new_khomp_call_data{'start_epoch'} eq '') { $new_khomp_call_data{'start_epoch'} = 0; }
if ($new_khomp_call_data{'audio_epoch'} eq '') { $new_khomp_call_data{'audio_epoch'} = 0; }
if ($new_khomp_call_data{'answer_epoch'} eq '') { $new_khomp_call_data{'answer_epoch'} = 0; }
if ($new_khomp_call_data{'end_epoch'} eq '') { $new_khomp_call_data{'end_epoch'} = 0; }
if ($new_khomp_call_data{'analyzer_epoch'} eq '') { $new_khomp_call_data{'analyzer_epoch'} = 0; }
# time is returned in milliseconds since 1970 we need seconds
if ($new_khomp_call_data{'start_epoch'} > 0) { $new_khomp_call_data{'start_epoch'} = $new_khomp_call_data{'start_epoch'} / 1000; }
if ($new_khomp_call_data{'audio_epoch'} > 0) { $new_khomp_call_data{'audio_epoch'} = $new_khomp_call_data{'audio_epoch'} / 1000; }
if ($new_khomp_call_data{'answer_epoch'} > 0) { $new_khomp_call_data{'answer_epoch'} = $new_khomp_call_data{'answer_epoch'} / 1000; }
if ($new_khomp_call_data{'end_epoch'} > 0) { $new_khomp_call_data{'end_epoch'} = $new_khomp_call_data{'end_epoch'} / 1000; }
if ($new_khomp_call_data{'analyzer_epoch'} > 0) { $new_khomp_call_data{'analyzer_epoch'} = $new_khomp_call_data{'analyzer_epoch'} / 1000; }
return %new_khomp_call_data;
}
### code for logging into KHOMP api
sub khomp_api_login
{
(
$khomp_api_login_url,
$khomp_api_user,
$khomp_api_pass
) = @_;
my $token = 'login';
my $auth_start_sec;
my $auth_start_usec;
my $auth_end_sec;
my $auth_end_usec;
my $auth_sec;
my $auth_usec;
my $api_auth_time;
($auth_start_sec, $auth_start_usec) = gettimeofday();
# build JSON object
my $login_json = {
'id' => 0,
'method' => 'SessionLogin',
'params' => {
'username' => "$khomp_api_user",
'password' => "$khomp_api_pass",
},
'jsonrpc' => '2.0',
};
# encode it as JSON
#UC# $login_json = encode_json( $login_json );
my $curl_cmd = "$curlbin -sS --data \'$login_json\' $khomp_api_login_url";
$agi_string = "-- KHOMP CURL COMMAND: $curl_cmd"; &agi_output;
$message = `$curl_cmd`;
chomp($message);
if ($AGILOG)
{
$agi_string = "-- KHOMP LOGIN URL: |$khomp_api_login_url|"; &agi_output;
$agi_string = "-- KHOMP LOGIN JSON : |$login_json|"; &agi_output;
$agi_string = "-- KHOMP LOGIN RESPONSE JSON: |$message|"; &agi_output;
}
#UC# $json = JSON::PP->new->ascii->pretty->allow_nonref;
#UC# $result = $json->decode($message);
$token = $result->{'result'}->{'token'};
($auth_end_sec, $auth_end_usec) = gettimeofday();
$api_auth_time = tv_interval ( [$auth_start_sec, $auth_start_usec], [$auth_end_sec, $auth_end_usec]);
return ($token, $api_auth_time);
}
### code for connecting to KHOMP api and passing JSON
sub khomp_json_api
{
( $khomp_json, $khomp_api_url ) = @_;
my $query_start_sec;
my $query_start_usec;
my $query_end_sec;
my $query_end_usec;
my $query_sec;
my $query_usec;
my $api_query_time;
($query_start_sec, $query_start_usec) = gettimeofday();
my $curl_cmd = "$curlbin -sS --data \'$khomp_json\' $khomp_api_url";
$agi_string = "-- KHOMP CURL COMMAND: $curl_cmd"; &agi_output;
$message = `$curl_cmd`;
chomp($message);
if ($AGILOG)
{
$agi_string = "-- KHOMP URL: |$khomp_api_url|"; &agi_output;
$agi_string = "-- KHOMP JSON : |$khomp_json|"; &agi_output;
$agi_string = "-- KHOMP RESPONSE JSON: |$message|"; &agi_output;
}
#UC# $json = JSON::PP->new->ascii->pretty->allow_nonref;
#UC# $result = $json->decode($message);
($query_end_sec, $query_end_usec) = gettimeofday();
$api_query_time = tv_interval ( [$query_start_sec, $query_start_usec], [$query_end_sec, $query_end_usec]);
return ($result, $api_query_time);
}
+7 -1
View File
@@ -1,4 +1,4 @@
KHOMP Answering Machine Detection Started: 2018-09-29 Update: 2021-07-20
KHOMP Answering Machine Detection Started: 2018-09-29 Update: 2021-09-07
The KHOMP Analytics Integration code, installation and configuration information
@@ -21,6 +21,7 @@ Here are a few basic things to check with KHOMP if you are experiencing issues,
c. Make sure campaign's "AMD Type" is set to 'KHOMP'
d. Make sure the campaign's "Routing Extension" is set to '8368'.
e. If you want to leave answering machine messages make sure the "CPD AMD Action" and "CPD Unknown Actions" are setup to do so.
2. "Why did this call do this thing?"
a. Do a lead search for the phone number.
b. Bring up the lead.
@@ -29,6 +30,7 @@ Here are a few basic things to check with KHOMP if you are experiencing issues,
e. Note the 'Conclusion' and 'Pattern' KHOMP returned.
f. Go to "Reports -> Admin Utilities -> Dialer KHOMP Admin Tool".
g. Search for the Conclusion / Pattern in the list and verify that it is configured to do what you expect.
3. "Something is clearly wrong. Every call is coming back as *SOME WEIRD CONCLUSION*"
a. Recommend they reboot the KHOMP server.
b. Disable KHOMP in the campaign.
@@ -37,3 +39,7 @@ Here are a few basic things to check with KHOMP if you are experiencing issues,
III. If they want to use Asterisk AMD set the "Campaign Routing Extension" appropriately.
c. Have the manager wait until all their existing calls from before the change have ended.
d. Reboot the Khomp Server by going into Administration -> "Reboot The Gateway" in the Khomp interface.
4. "All of my answered calls are being set as PU, what's going on?"
a. The KHOMP server itself needs to either have a valid SSL certificate from a valid certificate authority, or HTTPS needs to be disabled on the KHOMP server.
If you don't do this, curl will refuse to connect to the API and all answered calls will end up as PU.
+353 -26
View File
@@ -1,6 +1,6 @@
#!/usr/bin/perl
#
# FastAGI_log.pl version 2.14 (KHOMP VERSION as of svn/trunk rev 3198)
# FastAGI_log.pl version 2.14 (KHOMP VERSION as of svn/trunk rev 3524)
#
# Experimental Deamon using perl Net::Server that runs as FastAGI to reduce load
# replaces the following AGI scripts:
@@ -25,7 +25,7 @@
# exten => h,1,DeadAGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})
#
#
# Copyright (C) 2020 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
# Copyright (C) 2021 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG:
# 61010-1007 - First test build
@@ -85,7 +85,13 @@
# 190626-1100 - Added more logging for Auto-Alt-Dial debug
# 190709-2240 - Added Call Quota logging
# 191001-1509 - Small fix for monitoring issue
# 200210-1644 - Added KHOMP code
# 200318-1054 - Added code for OpenSIPs CallerIDname
# 210314-1015 - Added enhanced_disconnect_logging=2 option
# 210606-1007 - Added TILTX features for pre-carrier call filtering
# 210718-0358 - Fixes for 24-Hour Call Count Limits with standard Auto-Alt-Dialing
# 210719-1521 - Added additional state override methods for call_limit_24hour
# 210827-0936 - Added PJSIP compatibility
# 210907-0841 - Added KHOMP code (install JSON::PP Perl module and remove '#UC#' in the code to enable)
#
# defaults for PreFork
@@ -188,7 +194,7 @@ use Time::HiRes ('tv_interval','gettimeofday','usleep','sleep'); # necessary to
use Time::Local;
# Needed for Khomp Integration
use JSON::PP qw(encode_json decode_json);
use JSON::PP qw(encode_json decode_json);
### find curl binary for KHOMP
$curlbin = '';
@@ -273,6 +279,7 @@ sub process_request
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/FASTagiout.$year-$mon-$mday";}
if (!$AADLOGfile) {$AADLOGfile = "$PATHlogs/auto-alt-dial.$year-$mon-$mday";}
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
@@ -594,7 +601,7 @@ sub process_request
if ($AGILOG) {$agi_string = "+++++ CALL LOG START : $now_date"; &agi_output;}
if ($channel =~ /^SIP/) {$channel =~ s/-.*//gi;}
if ($channel =~ /^SIP|^PJSIP/) {$channel =~ s/-.*//gi;}
if ($channel =~ /^IAX2/) {$channel =~ s/\/\d+$//gi;}
if ($channel =~ /^Zap\/|^DAHDI\//)
{
@@ -645,7 +652,7 @@ sub process_request
if ($AGILOG) {$agi_string = $channel_group . ": $aryA[0]|$channel_line|"; &agi_output;}
}
### This section breaks the outbound dialed number down(or builds it up) to a 10 digit number and gives it a description
if ( ($channel =~ /^SIP|^IAX2/) || ( ($is_client_phone > 0) && (length($channel_group) < 1) ) )
if ( ($channel =~ /^SIP|^PJSIP|^IAX2/) || ( ($is_client_phone > 0) && (length($channel_group) < 1) ) )
{
if ( ($extension =~ /^901144/) && (length($extension)==16) ) #test 207 608 6400
{$extension =~ s/^9//gi; $channel_group = 'Outbound Intl UK';}
@@ -662,7 +669,7 @@ sub process_request
if ($is_client_phone > 0)
{$channel_group = 'Client Phone';}
$SIP_ext = $channel; $SIP_ext =~ s/SIP\/|IAX2\/|Zap\/|DAHDI\/|Local\///gi;
$SIP_ext = $channel; $SIP_ext =~ s/PJSIP\/|SIP\/|IAX2\/|Zap\/|DAHDI\/|Local\///gi;
$number_dialed = $extension;
$extension = $SIP_ext;
@@ -721,12 +728,53 @@ sub process_request
$sthA->finish();
### set dialplan variable CAMPCUST to the campaign_id of the outbound auto-dial or manual dial call
if ((length($CAMPCUST) > 0) && ($DP_variables_enabled > 0) )
if (length($CAMPCUST) > 0)
{
$AGI->exec("EXEC Set(_CAMPCUST=$CAMPCUST)");
if ($AGILOG) {$agi_string = "|CAMPCUST: $CAMPCUST|$callerid|"; &agi_output;}
}
### BEGIN OpenSIPs CallerIDname code ###
### get system_settings
$stmtA = "SELECT opensips_cid_name FROM system_settings";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$opensips_cid_name = $aryA[0];
}
$sthA->finish();
if ($AGILOG) {$agi_string = "$stmtA|$opensips_cid_name"; &agi_output;}
### opensips_cid_name is active
if ( $opensips_cid_name == 1)
{
### get the Campaign CID Name
$stmtA = "SELECT opensips_cid_name FROM vicidial_campaigns where campaign_id = '$CAMPCUST';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$camp_opensips_cid_name = $aryA[0];
}
$sthA->finish();
if ($AGILOG) {$agi_string = "$stmtA|$camp_opensips_cid_name"; &agi_output;}
### check that the campaign has a CID Name set
if ( $camp_opensips_cid_name ne "" )
{
if ($AGILOG) {$agi_string = "Adding \"X-CIDNAME: $camp_opensips_cid_name\" header to INVITE"; &agi_output;}
$header = "X-CIDNAME: " . $camp_opensips_cid_name;
$AGI->exec("EXEC SIPAddHeader(\"$header\")");
}
}
### END OpenSIPs CallerIDname code ###
if ($AGILOG) {$agi_string = "|KHOMP $amd_type|$HVcauses|$extension|$campaign_vdad_exten"; &agi_output;}
### Add the KHOMP SIP X header to the outbound call
@@ -755,10 +803,7 @@ sub process_request
$AGI->exec("EXEC SIPAddHeader(\"$sub_header\")");
if ($AGILOG) {$agi_string = "|KHOMP Sub Account Header= $sub_header|"; &agi_output;}
}
}
}
$stmtA = "INSERT INTO call_log (uniqueid,channel,channel_group,type,server_ip,extension,number_dialed,start_time,start_epoch,end_time,end_epoch,length_in_sec,length_in_min,caller_code) values('$unique_id','$channel','$channel_group','$type','$VARserver_ip','$extension','$number_dialed','$now_date','$now_date_epoch','','','','','$callerid')";
@@ -941,6 +986,7 @@ sub process_request
if ( ( ($callerid =~ /^BM\d\d\d\d\d\d\d\d/) && ($channel =~ /ASTblind/) ) || ($callerid =~ /^BB\d\d\d\d\d\d\d\d/) || ($callerid =~ /^BW\d\d\d\d\d\d\d\d/) )
{
$stmtA = "SELECT monitor_start_time,UNIX_TIMESTAMP(monitor_start_time) from vicidial_rt_monitor_log where caller_code='$callerid' and ( (monitor_end_time is NULL) or (monitor_start_time=monitor_end_time) );";
# if ($AGILOG) {$agi_string = "|JCJ|$stmtA|$monitor_start_time|$EPOCHmonitor_start_time|"; &agi_output;}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -1284,11 +1330,26 @@ sub process_request
##############################################################
### END - KHOMP status B/DC calls based off result
##############################################################
}
if ( ($PRI =~ /^PRI$/) && ($callerid =~ /\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) && ( ( ($dialstatus =~ /BUSY/) || ( ($dialstatus =~ /CHANUNAVAIL/) && ($hangup_cause =~ /^1$|^28$/) ) || ( ($enhanced_disconnect_logging > 0) && ( ($dialstatus =~ /CONGESTION/) && ($hangup_cause =~ /^1$|^19$|^21$|^34$|^38$/) ) ) ) || ($CPDfound > 0) ) && ($callerid !~ /^S\d\d\d\d\d\d\d\d\d\d\d\d/) )
if ( ($PRI =~ /^PRI$/) && ($callerid =~ /\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) && ( ( ($dialstatus =~ /BUSY/) || ( ($dialstatus =~ /CHANUNAVAIL/) && ($hangup_cause =~ /^1$|^28$/) ) || ( ($enhanced_disconnect_logging > 0) && ( ( ($dialstatus =~ /CONGESTION/) && ($hangup_cause =~ /^1$|^19$|^21$|^34$|^38$|^102$/) ) || ( ($dialstatus =~ /CHANUNAVAIL/) && ($hangup_cause =~ /^18$/) ) || ($dialstatus =~ /DNC|DISCONNECT/) ) ) || ($CPDfound > 0) && ($callerid !~ /^S\d\d\d\d\d\d\d\d\d\d\d\d/) ) ) )
{
if ($CPDfound < 1)
{
if ($enhanced_disconnect_logging == '2')
{
if ($dialstatus =~ /BUSY/) {$VDL_status = 'AB'; $VDAC_status = 'BUSY';}
if ($dialstatus =~ /CHANUNAVAIL/) {$VDL_status = 'ADC'; $VDAC_status = 'DISCONNECT';}
if ($enhanced_disconnect_logging > 0)
{
if ($dialstatus =~ /CHANUNAVAIL/ && $hangup_cause =~/^18/) {$VDL_status = 'ADCT'; $VDAC_status = 'DISCONNECT';}
if ($dialstatus =~ /CONGESTION/ && $hangup_cause =~ /^1$/) {$VDL_status = 'ADC'; $VDAC_status = 'DISCONNECT';}
if (($dialstatus =~ /CONGESTION/ && $hangup_cause =~ /^21$|^34$|^38$|^102$/) || ($dialstatus =~ /BUSY/ && $hangup_cause =~ /^19$/)) {$VDL_status = 'ADCT'; $VDAC_status = 'DISCONNECT';}
if ($dialstatus =~ /DISCONNECT/) {$VDL_status = 'ADCCAR'; $VDAC_status = 'ADCCAR';} # pre-carrier disconnect filter
if ($dialstatus =~ /DNC/) {$VDL_status = 'DNCCAR'; $VDAC_status = 'DNCCAR';} # pre-carrier DNC filter
}
}
else
{
if ($dialstatus =~ /BUSY/) {$VDL_status = 'AB'; $VDAC_status = 'BUSY';}
if ($dialstatus =~ /CHANUNAVAIL/) {$VDL_status = 'ADC'; $VDAC_status = 'DISCONNECT';}
@@ -1296,6 +1357,9 @@ sub process_request
{
if ($dialstatus =~ /CONGESTION/ && $hangup_cause =~ /^1$/) {$VDL_status = 'ADC'; $VDAC_status = 'DISCONNECT';}
if ($dialstatus =~ /CONGESTION/ && $hangup_cause =~ /^19$|^21$|^34$|^38$/) {$VDL_status = 'ADCT'; $VDAC_status = 'DISCONNECT';}
if ($dialstatus =~ /DISCONNECT/) {$VDL_status = 'ADCCAR'; $VDAC_status = 'ADCCAR';} # pre-carrier disconnect filter
if ($dialstatus =~ /DNC/) {$VDL_status = 'DNCCAR'; $VDAC_status = 'DNCCAR';} # pre-carrier DNC filter
}
}
}
@@ -1724,7 +1788,7 @@ sub process_request
#############################################
##### SYSTEM SETTINGS LOOKUP #####
$stmtA = "SELECT enable_drop_lists,call_quota_lead_ranking,timeclock_end_of_day FROM system_settings;";
$stmtA = "SELECT enable_drop_lists,call_quota_lead_ranking,timeclock_end_of_day,call_limit_24hour FROM system_settings;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -1734,6 +1798,7 @@ sub process_request
$enable_drop_lists = $aryA[0];
$SScall_quota_lead_ranking = $aryA[1];
$timeclock_end_of_day = $aryA[2];
$SScall_limit_24hour = $aryA[3];
}
$sthA->finish();
##### END SYSTEM SETTINGS LOOKUP #####
@@ -1971,7 +2036,7 @@ sub process_request
$VD_auto_alt_dial = 'NONE';
$VD_auto_alt_dial_statuses='';
$VD_call_quota_lead_ranking='DISABLED';
$stmtA="SELECT auto_alt_dial,auto_alt_dial_statuses,use_internal_dnc,use_campaign_dnc,use_other_campaign_dnc,call_quota_lead_ranking FROM vicidial_campaigns where campaign_id='$VD_campaign_id';";
$stmtA="SELECT auto_alt_dial,auto_alt_dial_statuses,use_internal_dnc,use_campaign_dnc,use_other_campaign_dnc,call_quota_lead_ranking,call_limit_24hour_method,call_limit_24hour_scope,call_limit_24hour,call_limit_24hour_override FROM vicidial_campaigns where campaign_id='$VD_campaign_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
@@ -1986,6 +2051,10 @@ sub process_request
$VD_use_campaign_dnc = $aryA[3];
$VD_use_other_campaign_dnc = $aryA[4];
$VD_call_quota_lead_ranking = $aryA[5];
$VD_call_limit_24hour_method = $aryA[6];
$VD_call_limit_24hour_scope = $aryA[7];
$VD_call_limit_24hour = $aryA[8];
$VD_call_limit_24hour_override = $aryA[9];
$epc_countCAMPDATA++;
}
@@ -2005,12 +2074,13 @@ sub process_request
# if ($AGILOG) {$agi_string = "AUTO-ALT TEST: |$VD_status|$VDL_status|$VD_auto_alt_dial_statuses|$VD_auto_alt_dial|"; &agi_output;}
if ($VD_auto_alt_dial_statuses =~ / $VD_status | $VDL_status /)
{
$alt_skip_reason=''; $addr3_skip_reason='';
if ($AGILOG) {$agi_string = "AUTO-ALT MATCH: |$VD_status|$VDL_status|$VD_auto_alt_dial_statuses|$VD_auto_alt_dial|$VD_alt_dial|$VD_alt_dial_log|"; &agi_output;}
if ( ($VD_auto_alt_dial =~ /(ALT_ONLY|ALT_AND_ADDR3|ALT_AND_EXTENDED)/) && ($VD_alt_dial =~ /NONE|MAIN/) )
{
$alt_dial_skip=0;
$VD_alt_phone='';
$stmtA="SELECT alt_phone,gmt_offset_now,state,list_id FROM vicidial_list where lead_id='$VD_lead_id';";
$stmtA="SELECT alt_phone,gmt_offset_now,state,list_id,phone_code,postal_code FROM vicidial_list where lead_id='$VD_lead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
@@ -2024,6 +2094,8 @@ sub process_request
$VD_gmt_offset_now = $aryA[1];
$VD_state = $aryA[2];
$VD_list_id = $aryA[3];
$VD_phone_code = $aryA[4];
$VD_postal_code = $aryA[5];
$epc_countCAMPDATA++;
}
$sthA->finish();
@@ -2075,24 +2147,43 @@ sub process_request
$sthA->finish();
}
if ($VD_alt_dnc_count < 1)
{
$passed_24hour_call_count=1;
if ( ($SScall_limit_24hour > 0) && ($VD_call_limit_24hour_method =~ /PHONE_NUMBER|LEAD/) )
{
$temp_24hour_phone = $VD_alt_phone;
$temp_24hour_phone_code = $VD_phone_code;
$temp_24hour_state = $VD_state;
$temp_24hour_postal_code = $VD_postal_code;
if ($DB > 0) {print "24-Hour Call Count Check: $SScall_limit_24hour|$VD_call_limit_24hour_method|$VD_lead_id|\n";}
&check_24hour_call_count;
}
if ($passed_24hour_call_count > 0)
{
$stmtA = "INSERT INTO vicidial_hopper SET lead_id='$VD_lead_id',campaign_id='$VD_campaign_id',status='READY',list_id='$VD_list_id',gmt_offset_now='$VD_gmt_offset_now',state='$VD_state',alt_dial='ALT',user='',priority='25',source='A';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDH record inserted: |$affected_rows| |$stmtA|"; &agi_output;}
if ($AGILOG) {$aad_string = "$VD_lead_id|$VD_alt_phone|$VD_campaign_id|ALT|25|hopper insert|"; &aad_output;}
}
else
{$alt_dial_skip=1;}
{$alt_dial_skip=1; $alt_skip_reason='24-hour call count limit failed';}
}
else
{$alt_dial_skip=1;}
{$alt_dial_skip=1; $alt_skip_reason='DNC check failed';}
}
else
{$alt_dial_skip=1; $alt_skip_reason='ALT phone invalid';}
if ($alt_dial_skip > 0)
{$VD_alt_dial='ALT';}
{
$VD_alt_dial='ALT';
if ($AGILOG) {$aad_string = "$VD_lead_id|$VD_alt_phone|$VD_campaign_id|ALT|0|hopper skip|$alt_skip_reason|"; &aad_output;}
}
}
if ( ( ($VD_auto_alt_dial =~ /(ADDR3_ONLY)/) && ($VD_alt_dial =~ /NONE|MAIN/) ) || ( ($VD_auto_alt_dial =~ /(ALT_AND_ADDR3)/) && ($VD_alt_dial =~ /ALT/) ) )
{
$addr3_dial_skip=0;
$VD_address3='';
$stmtA="SELECT address3,gmt_offset_now,state,list_id FROM vicidial_list where lead_id='$VD_lead_id';";
$stmtA="SELECT address3,gmt_offset_now,state,list_id,phone_code,postal_code FROM vicidial_list where lead_id='$VD_lead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
@@ -2106,6 +2197,8 @@ sub process_request
$VD_gmt_offset_now = $aryA[1];
$VD_state = $aryA[2];
$VD_list_id = $aryA[3];
$VD_phone_code = $aryA[4];
$VD_postal_code = $aryA[5];
$epc_countCAMPDATA++;
}
$sthA->finish();
@@ -2157,18 +2250,37 @@ sub process_request
$sthA->finish();
}
if ($VD_alt_dnc_count < 1)
{
$passed_24hour_call_count=1;
if ( ($SScall_limit_24hour > 0) && ($VD_call_limit_24hour_method =~ /PHONE_NUMBER|LEAD/) )
{
$temp_24hour_phone = $VD_address3;
$temp_24hour_phone_code = $VD_phone_code;
$temp_24hour_state = $VD_state;
$temp_24hour_postal_code = $VD_postal_code;
if ($DB > 0) {print "24-Hour Call Count Check: $SScall_limit_24hour|$VD_call_limit_24hour_method|$VD_lead_id|\n";}
&check_24hour_call_count;
}
if ($passed_24hour_call_count > 0)
{
$stmtA = "INSERT INTO vicidial_hopper SET lead_id='$VD_lead_id',campaign_id='$VD_campaign_id',status='READY',list_id='$VD_list_id',gmt_offset_now='$VD_gmt_offset_now',state='$VD_state',alt_dial='ADDR3',user='',priority='20',source='A';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDH record inserted: |$affected_rows| |$stmtA|"; &agi_output;}
if ($AGILOG) {$aad_string = "$VD_lead_id|$VD_address3|$VD_campaign_id|ADDR3|20|hopper insert|"; &aad_output;}
}
else
{$addr3_dial_skip=1;}
{$addr3_dial_skip=1; $addr3_skip_reason='24-hour call count limit failed';}
}
else
{$addr3_dial_skip=1;}
{$addr3_dial_skip=1; $addr3_skip_reason='DNC check failed';}
}
else
{$addr3_dial_skip=1; $addr3_skip_reason='ADDR3 phone invalid';}
if ($addr3_dial_skip > 0)
{$VD_alt_dial='ADDR3';}
{
$VD_alt_dial='ADDR3';
if ($AGILOG) {$aad_string = "$VD_lead_id|$VD_address3|$VD_campaign_id|ADDR3|0|hopper skip|$addr3_skip_reason|"; &aad_output;}
}
}
if ( ( ($VD_auto_alt_dial =~ /(EXTENDED_ONLY)/) && ($VD_alt_dial =~ /NONE|MAIN/) ) || ( ($VD_auto_alt_dial =~ /(ALT_AND_EXTENDED)/) && ($VD_alt_dial =~ /ALT/) ) || ( ($VD_auto_alt_dial =~ /ADDR3_AND_EXTENDED|ALT_AND_ADDR3_AND_EXTENDED/) && ($VD_alt_dial =~ /ADDR3/) ) || ( ($VD_auto_alt_dial =~ /(EXTENDED)/) && ($VD_alt_dial =~ /X/) && ($VD_alt_dial !~ /XLAST/) ) )
{
@@ -2179,7 +2291,7 @@ sub process_request
if (length($Xlast)<1)
{$Xlast=0;}
$VD_altdialx='';
$stmtA="SELECT gmt_offset_now,state,list_id FROM vicidial_list where lead_id='$VD_lead_id';";
$stmtA="SELECT gmt_offset_now,state,list_id,postal_code FROM vicidial_list where lead_id='$VD_lead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
@@ -2191,6 +2303,7 @@ sub process_request
$VD_gmt_offset_now = $aryA[0];
$VD_state = $aryA[1];
$VD_list_id = $aryA[2];
$VD_postal_code = $aryA[3];
$epc_countCAMPDATA++;
}
$sthA->finish();
@@ -2210,7 +2323,7 @@ sub process_request
while ( ($alt_dial_phones_count > 0) && ($alt_dial_phones_count > $Xlast) )
{
$Xlast++;
$stmtA="SELECT alt_phone_id,phone_number,active FROM vicidial_list_alt_phones where lead_id='$VD_lead_id' and alt_phone_count='$Xlast';";
$stmtA="SELECT alt_phone_id,phone_number,active,phone_code FROM vicidial_list_alt_phones where lead_id='$VD_lead_id' and alt_phone_count='$Xlast';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
@@ -2221,6 +2334,7 @@ sub process_request
$VD_altdial_id = $aryA[0];
$VD_altdial_phone = $aryA[1];
$VD_altdial_active = $aryA[2];
$VD_altdial_phone_code = $aryA[3];
}
else
{$Xlast=9999999999;}
@@ -2281,14 +2395,33 @@ sub process_request
{
if ($alt_dial_phones_count eq '$Xlast')
{$Xlast = 'LAST';}
$passed_24hour_call_count=1;
if ( ($SScall_limit_24hour > 0) && ($VD_call_limit_24hour_method =~ /PHONE_NUMBER|LEAD/) )
{
$temp_24hour_phone = $VD_altdial_phone;
$temp_24hour_phone_code = $VD_altdial_phone_code;
$temp_24hour_state = $VD_state;
$temp_24hour_postal_code = $VD_postal_code;
if ($DB > 0) {print "24-Hour Call Count Check: $SScall_limit_24hour|$VD_call_limit_24hour_method|$VD_lead_id|\n";}
&check_24hour_call_count;
}
if ($passed_24hour_call_count > 0)
{
$stmtA = "INSERT INTO vicidial_hopper SET lead_id='$VD_lead_id',campaign_id='$VD_campaign_id',status='READY',list_id='$VD_list_id',gmt_offset_now='$VD_gmt_offset_now',state='$VD_state',alt_dial='X$Xlast',user='',priority='15',source='A';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDH record inserted: |$affected_rows| |$stmtA|X$Xlast|$VD_altdial_id|"; &agi_output;}
if ($AGILOG) {$aad_string = "$VD_lead_id|$VD_altdial_phone|$VD_campaign_id|X$Xlast|15|hopper insert|"; &aad_output;}
$Xlast=9999999999;
$DNC_hopper_trigger=0;
}
else
{$DNC_hopper_trigger=1;}
}
else
{$DNC_hopper_trigger=1;}
if ($DNC_hopper_trigger > 0)
{
if ( ( ($VD_auto_alt_dial_statuses =~ / DNCC /) && ($DNCC > 0) ) || ( ($VD_auto_alt_dial_statuses =~ / DNCL /) && ($DNCL > 0) ) )
if ( ( ($VD_auto_alt_dial_statuses =~ / DNCC /) && ($DNCC > 0) ) || ( ($VD_auto_alt_dial_statuses =~ / DNCL /) && ($DNCL > 0) ) || ( ($auto_alt_dial_statuses[$i] =~ / TFHCCL /) && ($TFHCCL > 0) ) )
{
if ($alt_dial_phones_count eq '$Xlast')
{$Xlast = 'LAST';}
@@ -2297,10 +2430,12 @@ sub process_request
if ($AGILOG) {$agi_string = "-- VDH record DNC inserted: |$affected_rows| |$stmtA|X$Xlast|$VD_altdial_id|"; &agi_output;}
$Xlast=9999999999;
if ($AGILOG) {$agi_string = "-- VDH alt dial inserting DNC|X$Xlast|$VD_altdial_phone|"; &agi_output;}
if ($AGILOG) {$aad_string = "$VD_lead_id|$VD_altdial_phone|$VD_campaign_id|X$Xlast|15|hopper DNC insert|"; &aad_output;}
}
else
{
if ($AGILOG) {$agi_string = "-- VDH alt dial not-inserting DNC|X$Xlast|$VD_altdial_phone|"; &agi_output;}
if ($AGILOG) {$aad_string = "$VD_lead_id|$VD_altdial_phone|$VD_campaign_id|X$Xlast|15|hopper DNC skip|"; &aad_output;}
}
}
}
@@ -2670,6 +2805,186 @@ sub call_quota_logging
}
}
sub check_24hour_call_count
{
$passed_24hour_call_count=0;
$limit_scopeSQL='';
if ($VD_call_limit_24hour_scope =~ /CAMPAIGN_LISTS/)
{
$limit_scopeCAMP='';
$stmtY = "SELECT list_id FROM vicidial_lists where campaign_id='$VD_campaign_id';";
$sthY = $dbhA->prepare($stmtY) or die "preparing: ",$dbhA->errstr;
$sthY->execute or die "executing: $stmtY", $dbhA->errstr;
$sthYrows=$sthY->rows;
$rec_campLISTS=0;
while ($sthYrows > $rec_campLISTS)
{
@aryY = $sthY->fetchrow_array;
$limit_scopeCAMP .= "'$aryY[0]',";
$rec_campLISTS++;
}
if (length($limit_scopeCAMP) < 2) {$limit_scopeCAMP="'1'";}
else {chop($limit_scopeCAMP);}
$limit_scopeSQL = "and list_id IN($limit_scopeCAMP)";
}
if ($VD_call_limit_24hour_method =~ /PHONE_NUMBER/)
{
$stmtA="SELECT count(*) FROM vicidial_lead_24hour_calls where phone_number='$temp_24hour_phone' and phone_code='$temp_24hour_phone_code' and (call_date >= NOW() - INTERVAL 1 DAY) $limit_scopeSQL;";
}
else
{
$stmtA="SELECT count(*) FROM vicidial_lead_24hour_calls where lead_id='$VD_lead_id' and (call_date >= NOW() - INTERVAL 1 DAY) $limit_scopeSQL;";
}
if ($DB) {print " Doing 24-Hour Call Count Check: $VD_lead_id|$temp_24hour_phone_code|$temp_24hour_phone|$temp_24hour_state|$temp_24hour_postal_code - $VD_call_limit_24hour_method|$VD_call_limit_24hour_scope|$VD_call_limit_24hour\n";}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$TFhourCOUNT=0;
$TFhourSTATE='';
$TFhourCOUNTRY='';
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$TFhourCOUNT = ($TFhourCOUNT + $aryA[0]);
}
$sthA->finish();
$TEMPcall_limit_24hour = $VD_call_limit_24hour;
if ($DBX) {print " 24-Hour Call Limit Count DEBUG: $TFhourCOUNT|$stmtA|\n";}
if ( ($VD_call_limit_24hour_override !~ /^DISABLED$/) && (length($VD_call_limit_24hour_override) > 0) )
{
$TFH_areacode = substr($temp_24hour_phone, 0, 3);
$stmtY = "SELECT state,country FROM vicidial_phone_codes where country_code='$temp_24hour_phone_code' and areacode='$TFH_areacode';";
$sthY = $dbhA->prepare($stmtY) or die "preparing: ",$dbhA->errstr;
$sthY->execute or die "executing: $stmtY", $dbhA->errstr;
$sthYrows=$sthY->rows;
if ($sthYrows > 0)
{
@aryY = $sthY->fetchrow_array;
$TFhourSTATE = $aryY[0];
$TFhourCOUNTRY = $aryY[1];
}
$sthA->finish();
$TEMP_TFhour_OR_entry='';
$TFH_OR_method='state_areacode';
$TFH_OR_postcode_field_match=0;
$TFH_OR_state_field_match=0;
$TFH_OR_postcode_state='';
$stmtA = "SELECT container_entry FROM vicidial_settings_containers where container_id='$VD_call_limit_24hour_override';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($DBX) {print "$sthArows|$stmtA\n";}
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$TEMP_TFhour_OR_entry = $aryA[0];
}
$sthA->finish();
if (length($TEMP_TFhour_OR_entry) > 2)
{
@container_lines = split(/\n/,$TEMP_TFhour_OR_entry);
$c=0;
foreach(@container_lines)
{
$container_lines[$c] =~ s/;.*|\r|\t//gi;
$container_lines[$c] =~ s/ => |=> | =>/=>/gi;
if (length($container_lines[$c]) > 3)
{
# define core settings
if ($container_lines[$c] =~ /^method/i)
{
#$container_lines[$c] =~ s/method=>//gi;
$TFH_OR_method = $container_lines[$c];
if ( ($TFH_OR_method =~ /state$/) && ($TFhourSTATE ne $temp_24hour_state) )
{
$TFH_OR_state_field_match=1;
}
if ( ($TFH_OR_method =~ /postcode/) && (length($temp_24hour_postal_code) > 0) )
{
if ($TFhourCOUNTRY == 'USA')
{
$temp_24hour_postal_code =~ s/\D//gi;
$temp_24hour_postal_code = substr($temp_24hour_postal_code,0,5);
}
if ($TFhourCOUNTRY == 'CAN')
{
$temp_24hour_postal_code =~ s/[^a-zA-Z0-9]//gi;
$temp_24hour_postal_code = substr($temp_24hour_postal_code,0,6);
}
$stmtA = "SELECT state FROM vicidial_postal_codes where postal_code='$temp_24hour_postal_code';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($DBX) {print "$sthArows|$stmtA\n";}
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$TFH_OR_postcode_state = $aryA[0];
$TFH_OR_postcode_field_match=1;
}
$sthA->finish();
}
}
else
{
if ($container_lines[$c] =~ /^state/i)
{
$container_lines[$c] =~ s/state=>//gi; # USA,GA,4
@TEMP_state_ARY = split(/,/,$container_lines[$c]);
if ($TFhourCOUNTRY eq $TEMP_state_ARY[0])
{
$TEMP_state_ARY[2] =~ s/\D//gi;
if ( ($TFhourSTATE eq $TEMP_state_ARY[1]) && (length($TEMP_state_ARY[2]) > 0) )
{
if ($DB) {print " 24-Hour Call Count State Override Triggered: $TEMPcall_limit_24hour|$container_lines[$c]\n";}
$TEMPcall_limit_24hour = $TEMP_state_ARY[2];
}
if ( ($TFH_OR_postcode_state eq $TEMP_state_ARY[1]) && (length($TEMP_state_ARY[2]) > 0) && ($TFH_OR_postcode_field_match > 0) )
{
if ($DBX) {print " 24-Hour Call Count State Override Match(postcode $TFH_OR_postcode_state): $TEMPcall_limit_24hour|$container_lines[$c]\n";}
if ($TEMP_state_ARY[2] < $TEMPcall_limit_24hour)
{
if ($DBX) {print " POSTCODE field override of override triggered: ($TEMP_state_ARY[2] < $TEMPcall_limit_24hour)\n";}
$TEMPcall_limit_24hour = $TEMP_state_ARY[2];
}
}
if ( ($temp_24hour_state eq $TEMP_state_ARY[1]) && (length($TEMP_state_ARY[2]) > 0) && ($TFH_OR_state_field_match > 0) )
{
if ($DBX) {print " 24-Hour Call Count State Override Match(state $temp_24hour_state): $TEMPcall_limit_24hour|$container_lines[$c]\n";}
if ($TEMP_state_ARY[2] < $TEMPcall_limit_24hour)
{
if ($DBX) {print " STATE field override of override triggered: ($TEMP_state_ARY[2] < $TEMPcall_limit_24hour)\n";}
$TEMPcall_limit_24hour = $TEMP_state_ARY[2];
}
}
}
}
}
}
if ($DBX) {print " 24-Hour Call Count State Override DEBUG: |$container_lines[$c]|\n";}
$c++;
}
}
}
if ( ($TFhourCOUNT > 0) && ($TFhourCOUNT >= $TEMPcall_limit_24hour) )
{
$TFHCCLlead=1;
$TFHCCL++;
$passed_24hour_call_count=0;
if ($DBX) {print "Flagging 24-Hour Call Limit lead: $VD_lead_id ($TFhourCOUNT >= $TEMPcall_limit_24hour) $passed_24hour_call_count\n";}
}
else
{
$passed_24hour_call_count=1;
if ($DBX) {print " 24-Hour Call Limit check passed: $VD_lead_id ($TFhourCOUNT < $TEMPcall_limit_24hour) $passed_24hour_call_count\n";}
}
}
sub agi_output
{
if ($AGILOG >=2)
@@ -2688,6 +3003,18 @@ sub agi_output
$agi_string='';
}
sub aad_output
{
if ($AGILOG > 0)
{
### open the log file for writing ###
open(Aout, ">>$AADLOGfile") || die "Can't open $AADLOGfile: $!\n";
print Aout "$now_date|$script|$aad_string\n";
close(Aout);
}
$aad_string='';
}
# subroutine to parse the asterisk version
# and return a hash with the various part
sub parse_asterisk_version
+150 -132
View File
@@ -1,6 +1,6 @@
#!/usr/bin/perl
#
# agi-VDAD_ALL_outbound.agi version 2.14 (KHOMP VERSION as of svn/trunk rev 3198)
# agi-VDAD_ALL_outbound.agi version 2.14 (KHOMP VERSION as of svn/trunk rev 3524)
#
# runs when an outbound call is answered. This script will
# send the calls out to the agents that are logged in.
@@ -18,7 +18,7 @@
# ; - SURVEYCAMPCEP - Survery question, campaign settings, cepstral name
# ; - REMINDER - Reminder campaign
# ; - REMINDX - Reminder with transfer to agent
# ; 2. the method of searching for an available agent:
# ; 2. the method of searching for an available agent: (agent_search_method)
# ; - LB - <default> Load Balance total system
# ; - LO - Load Balance Overflow only (priority to home server)
# ; - SO - Home server only
@@ -123,7 +123,9 @@
# 190925-1348 - Added campaign SIP Actions processing
# 191104-2026 - Added code for Khomp version compatibility
# 191120-2235 - Added DYN multi-prompt survey prompts functionality
# 200210-1645 - Added KHOMP code
# 200825-2342 - Added option for auto-only sip actions
# 200915-2218 - Fixes for surveys with hash-star
# 210907-1254 - Added KHOMP code (install JSON::PP Perl module and remove '#UC#' in the code to enable)
#
$script = 'agi-VDAD_ALL_outbound.agi';
@@ -137,9 +139,8 @@ use Time::HiRes ('tv_interval','gettimeofday','usleep','sleep'); # necessary to
($START_s_hires, $START_usec) = gettimeofday();
# Needed for Khomp Integration
#use Cpanel::JSON::XS qw(encode_json decode_json);
use JSON::PP qw(encode_json decode_json);
#use Data::Dumper;
use JSON::PP qw(encode_json decode_json);
### find curl binary for KHOMP
$curlbin = '';
@@ -267,7 +268,7 @@ $dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VA
#############################################
##### Gather system_settings #####
$stmtA = "SELECT sip_event_logging,call_quota_lead_ranking FROM system_settings;";
$stmtA = "SELECT sip_event_logging,call_quota_lead_ranking,agent_search_method FROM system_settings;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -276,6 +277,7 @@ if ($sthArows > 0)
@aryA = $sthA->fetchrow_array;
$SSsip_event_logging = $aryA[0];
$SScall_quota_lead_ranking = $aryA[1];
$SSagent_search_method = $aryA[2];
}
$sthA->finish();
###########################################
@@ -808,7 +810,7 @@ if ($VDACaffected_rows > 0)
##### END - Max call stats
### Grab campaign values from the database
$stmtA = "SELECT drop_call_seconds,drop_action,safe_harbor_exten,concurrent_transfers,next_agent_call,voicemail_ext,drop_inbound_group,use_internal_dnc,use_campaign_dnc,cpd_amd_action,am_message_exten,three_way_call_cid,campaign_cid,survey_first_audio_file,survey_opt_in_audio_file,survey_ni_audio_file,survey_third_audio_file,survey_fourth_audio_file,extension_appended_cidname,queue_priority,closer_campaigns,queuemetrics_phone_environment,campaign_recording,campaign_rec_filename,safe_harbor_audio,safe_harbor_menu_id,survey_recording,safe_harbor_audio_field,use_other_campaign_dnc,cpd_unknown_action,routing_initiated_recordings,campaign_rec_exten,call_quota_lead_ranking,sip_event_logging,amd_type FROM vicidial_campaigns where campaign_id = '$VDADcampaign';";
$stmtA = "SELECT drop_call_seconds,drop_action,safe_harbor_exten,concurrent_transfers,next_agent_call,voicemail_ext,drop_inbound_group,use_internal_dnc,use_campaign_dnc,cpd_amd_action,am_message_exten,three_way_call_cid,campaign_cid,survey_first_audio_file,survey_opt_in_audio_file,survey_ni_audio_file,survey_third_audio_file,survey_fourth_audio_file,extension_appended_cidname,queue_priority,closer_campaigns,queuemetrics_phone_environment,campaign_recording,campaign_rec_filename,safe_harbor_audio,safe_harbor_menu_id,survey_recording,safe_harbor_audio_field,use_other_campaign_dnc,cpd_unknown_action,routing_initiated_recordings,campaign_rec_exten,call_quota_lead_ranking,sip_event_logging,amd_type,agent_search_method FROM vicidial_campaigns where campaign_id = '$VDADcampaign';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -854,6 +856,7 @@ if ($VDACaffected_rows > 0)
$VD_call_quota_lead_ranking = $aryA[32];
$CAMPsip_event_logging = $aryA[33];
$amd_type = $aryA[34];
$agent_search_method_OVERRIDE = $aryA[35];
if (length($closer_campaigns) > 2)
{
$closer_campaigns =~ s/^ | -$//gi;
@@ -875,119 +878,6 @@ if ($VDACaffected_rows > 0)
$khomp_header = '';
$khomp_id_format = '';
##### BEGIN SIP Action check #####
if ( ($SIP_event_recent_inserted > 0) && ($SIP_event_action_checked < 1) && (length($CAMPsip_event_logging) > 0) and ($CAMPsip_event_logging !~ /^DISABLED$/i) )
{
# Gather settings container for SIP Event Actions
$CQcontainer_entry='';
$stmtA = "SELECT container_entry FROM vicidial_settings_containers where container_id='$CAMPsip_event_logging';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ( ($AGILOG > 0) && ($sthArows > 0) ) {$agi_string = "-- SIP ACTION check: |$sthArows|$invite_to_final|$CAMPsip_event_logging|"; &agi_output;}
$dbhP=$dbhA; $mysql_count='01141'; $MEL_aff_rows=$sthArows; &mysql_error_logging;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$SAcontainer_entry = $aryA[0];
$SAcontainer_entry =~ s/\r|\t|\'|\"//gi;
@sip_action_settings = split(/\n/,$SAcontainer_entry);
$sea=0;
foreach (@sip_action_settings)
{
if ($sip_action_settings[$sea] =~ /^invite_to_final => /)
{
# invite_to_final => 0.0,1.0,hangup-dispo-message,FAS,Auto Hangup and Dispo of False Answer Call
$sip_action_settings[$sea] =~ s/invite_to_final => //gi;
@invite_to_finalARY = split(/,/,$sip_action_settings[$sea]);
$T_dial_time = ($invite_to_final + 0);
$itf_begin = ($invite_to_finalARY[0] + 0);
$itf_end = ($invite_to_finalARY[1] + 0);
$itf_actions = $invite_to_finalARY[2];
$itf_dispo = $invite_to_finalARY[3];
$itf_message = $invite_to_finalARY[4];
if ( ($T_dial_time >= $itf_begin) && ($T_dial_time <= $itf_end) && (length($itf_actions) > 4) )
{
if ($itf_actions =~ /logtable/i)
{
##### insert record into vicidial_sip_action_log
$stmtA="INSERT INTO vicidial_sip_action_log set call_date='$invite_date',caller_code='$callerid',lead_id='$CIDlead_id',phone_number='$VDADphone',user='VDAD',result='$itf_dispo';";
$SAaffected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01142'; $MEL_aff_rows=$SAaffected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- SIP ACTION logtable inserted : |$SAaffected_rows|($T_dial_time <> $itf_begin -> $itf_end)|$itf_actions|$stmtA|"; &agi_output;}
}
if ($itf_actions =~ /hangup/i)
{
if (length($itf_dispo) < 1)
{$itf_dispo='SIPACT';}
$xCLlist_id=0;
$called_count=0;
$stmtA = "SELECT list_id,security_phrase,called_count from vicidial_list where lead_id='$CIDlead_id' limit 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsLI=$sthA->rows;
$dbhP=$dbhA; $mysql_count='01143'; $MEL_aff_rows=$sthArowsLI; &mysql_error_logging;
if ($sthArowsLI > 0)
{
@aryA = $sthA->fetchrow_array;
$xCLlist_id = $aryA[0];
$security_phrase = $aryA[1];
$called_count = $aryA[2];
}
$sthA->finish();
($END_s_hires, $END_usec) = gettimeofday();
$START_time = $START_s_hires . '.' . sprintf("%06s", $START_usec);
$END_time = $END_s_hires . '.' . sprintf("%06s", $END_usec);
$RUN_time = ($END_time - $START_time);
$RUN_time = sprintf("%.3f", $RUN_time);
if ($AGILOG) {$agi_string = "Preprocess time: |$RUN_time ($END_time - $START_time)|"; &agi_output;}
$stmtA = "INSERT INTO vicidial_log (uniqueid,lead_id,campaign_id,call_date,start_epoch,end_epoch,length_in_sec,status,phone_code,phone_number,user,processed,alt_dial,list_id,comments,called_count,term_reason) values('$uniqueid','$CIDlead_id','$VDADcampaign','$SQLdate','$now_date_epoch','$now_date_epoch','0','$itf_dispo','$VDADphone_code','$VDADphone','VDAD','N','$VDADalt_dial','$xCLlist_id','$RUN_time','$called_count','SYSTEM')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01144'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- SIP ACTION VDAD : |$VDADlead_id|$CIDlead_id|($T_dial_time <> $itf_begin -> $itf_end)|$itf_actions|insert to vicidial_log: $uniqueid"; &agi_output;}
$stmtA = "INSERT INTO vicidial_log_extended set uniqueid='$uniqueid',server_ip='$VARserver_ip',call_date='$SQLdate',lead_id = '$CIDlead_id',caller_code='$callerid',custom_call_id='';";
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01145'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- SIP ACTION VDAD VLE insert: |$affected_rows|\n|$stmtA|"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='$itf_dispo' where lead_id='$CIDlead_id';";
if ($AGILOG) { $agi_string = "|$stmtA|"; &agi_output; }
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01146'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG)
{$agi_string = "-- SIP ACTION VDAD vicidial_list update: $itf_dispo|$affected_rows|$CIDlead_id"; &agi_output;}
$stmtA = "DELETE FROM vicidial_auto_calls where callerid='$callerid' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01147'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|"; &agi_output;}
if ( ($SScall_quota_lead_ranking > 0) && ($VD_call_quota_lead_ranking !~ /^DISABLED$/i) )
{
$temp_status = $itf_dispo;
&call_quota_logging;
}
$AGI->hangup();
exit;
}
}
}
$sea++;
}
}
$sthA->finish();
$SIP_event_action_checked++;
}
##### END SIP Action check #####
$stmtA = "SELECT container_entry FROM vicidial_settings_containers WHERE container_id = 'KHOMPSETTINGS';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
@@ -1116,6 +1006,118 @@ if ($VDACaffected_rows > 0)
}
}
##### BEGIN SIP Action check #####
if ( ($SIP_event_recent_inserted > 0) && ($SIP_event_action_checked < 1) && (length($CAMPsip_event_logging) > 0) and ($CAMPsip_event_logging !~ /^DISABLED$/i) )
{
# Gather settings container for SIP Event Actions
$CQcontainer_entry='';
$stmtA = "SELECT container_entry FROM vicidial_settings_containers where container_id='$CAMPsip_event_logging';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ( ($AGILOG > 0) && ($sthArows > 0) ) {$agi_string = "-- SIP ACTION check: |$sthArows|$invite_to_final|$CAMPsip_event_logging|"; &agi_output;}
$dbhP=$dbhA; $mysql_count='01141'; $MEL_aff_rows=$sthArows; &mysql_error_logging;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$SAcontainer_entry = $aryA[0];
$SAcontainer_entry =~ s/\r|\t|\'|\"//gi;
@sip_action_settings = split(/\n/,$SAcontainer_entry);
$sea=0;
foreach (@sip_action_settings)
{
if ( ($sip_action_settings[$sea] =~ /^invite_to_final => /) && ($sip_action_settings[$sea] !~ /manual-only/i) )
{
# invite_to_final => 0.0,1.0,hangup-dispo-message,FAS,Auto Hangup and Dispo of False Answer Call,auto-only
$sip_action_settings[$sea] =~ s/invite_to_final => //gi;
@invite_to_finalARY = split(/,/,$sip_action_settings[$sea]);
$T_dial_time = ($invite_to_final + 0);
$itf_begin = ($invite_to_finalARY[0] + 0);
$itf_end = ($invite_to_finalARY[1] + 0);
$itf_actions = $invite_to_finalARY[2];
$itf_dispo = $invite_to_finalARY[3];
$itf_message = $invite_to_finalARY[4];
if ( ($T_dial_time >= $itf_begin) && ($T_dial_time <= $itf_end) && (length($itf_actions) > 4) )
{
if ($itf_actions =~ /logtable/i)
{
##### insert record into vicidial_sip_action_log
$stmtA="INSERT INTO vicidial_sip_action_log set call_date='$invite_date',caller_code='$callerid',lead_id='$CIDlead_id',phone_number='$VDADphone',user='VDAD',result='$itf_dispo';";
$SAaffected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01142'; $MEL_aff_rows=$SAaffected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- SIP ACTION logtable inserted : |$SAaffected_rows|($T_dial_time <> $itf_begin -> $itf_end)|$itf_actions|$stmtA|"; &agi_output;}
}
if ($itf_actions =~ /hangup/i)
{
if (length($itf_dispo) < 1)
{$itf_dispo='SIPACT';}
$xCLlist_id=0;
$called_count=0;
$stmtA = "SELECT list_id,security_phrase,called_count from vicidial_list where lead_id='$CIDlead_id' limit 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsLI=$sthA->rows;
$dbhP=$dbhA; $mysql_count='01143'; $MEL_aff_rows=$sthArowsLI; &mysql_error_logging;
if ($sthArowsLI > 0)
{
@aryA = $sthA->fetchrow_array;
$xCLlist_id = $aryA[0];
$security_phrase = $aryA[1];
$called_count = $aryA[2];
}
$sthA->finish();
($END_s_hires, $END_usec) = gettimeofday();
$START_time = $START_s_hires . '.' . sprintf("%06s", $START_usec);
$END_time = $END_s_hires . '.' . sprintf("%06s", $END_usec);
$RUN_time = ($END_time - $START_time);
$RUN_time = sprintf("%.3f", $RUN_time);
if ($AGILOG) {$agi_string = "Preprocess time: |$RUN_time ($END_time - $START_time)|"; &agi_output;}
$stmtA = "INSERT INTO vicidial_log (uniqueid,lead_id,campaign_id,call_date,start_epoch,end_epoch,length_in_sec,status,phone_code,phone_number,user,processed,alt_dial,list_id,comments,called_count,term_reason) values('$uniqueid','$CIDlead_id','$VDADcampaign','$SQLdate','$now_date_epoch','$now_date_epoch','0','$itf_dispo','$VDADphone_code','$VDADphone','VDAD','N','$VDADalt_dial','$xCLlist_id','$RUN_time','$called_count','SYSTEM')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01144'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- SIP ACTION VDAD : |$VDADlead_id|$CIDlead_id|($T_dial_time <> $itf_begin -> $itf_end)|$itf_actions|insert to vicidial_log: $uniqueid"; &agi_output;}
$stmtA = "INSERT INTO vicidial_log_extended set uniqueid='$uniqueid',server_ip='$VARserver_ip',call_date='$SQLdate',lead_id = '$CIDlead_id',caller_code='$callerid',custom_call_id='';";
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01145'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- SIP ACTION VDAD VLE insert: |$affected_rows|\n|$stmtA|"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='$itf_dispo' where lead_id='$CIDlead_id';";
if ($AGILOG) { $agi_string = "|$stmtA|"; &agi_output; }
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01146'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG)
{$agi_string = "-- SIP ACTION VDAD vicidial_list update: $itf_dispo|$affected_rows|$CIDlead_id"; &agi_output;}
$stmtA = "DELETE FROM vicidial_auto_calls where callerid='$callerid' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01147'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|"; &agi_output;}
if ( ($SScall_quota_lead_ranking > 0) && ($VD_call_quota_lead_ranking !~ /^DISABLED$/i) )
{
$temp_status = $itf_dispo;
&call_quota_logging;
}
$AGI->hangup();
exit;
}
}
}
$sea++;
}
}
$sthA->finish();
$SIP_event_action_checked++;
}
##### END SIP Action check #####
### start recording if survey recording is enabled
if ( ($call_handle_method =~ /SURVEY/) && ($survey_recording =~ /Y/) )
@@ -1812,7 +1814,7 @@ if ($call_handle_method =~ /SURVEY/)
}
# they opted out
if ($opt_code =~ /$survey_ni_digit/)
if ($opt_code eq $survey_ni_digit)
{
if ( $survey_ni_audio_file ne "")
{
@@ -1838,7 +1840,7 @@ if ($call_handle_method =~ /SURVEY/)
$dbhP=$dbhA; $mysql_count='01017'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG)
{
$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|$callerid";
$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|";
&agi_output;
}
@@ -1926,7 +1928,7 @@ if ($call_handle_method =~ /SURVEY/)
}
### third digit option
if ($opt_code =~ /$survey_third_digit/)
if ($opt_code eq $survey_third_digit)
{
if ( $survey_third_audio_file ne "")
{
@@ -1952,7 +1954,7 @@ if ($call_handle_method =~ /SURVEY/)
$dbhP=$dbhA; $mysql_count='01017'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG)
{
$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|$callerid";
$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|";
&agi_output;
}
@@ -2055,7 +2057,7 @@ if ($call_handle_method =~ /SURVEY/)
### fourth digit option
if ($opt_code =~ /$survey_fourth_digit/)
if ($opt_code eq $survey_fourth_digit)
{
if ( $survey_fourth_audio_file ne "")
{
@@ -2081,7 +2083,7 @@ if ($call_handle_method =~ /SURVEY/)
$dbhP=$dbhA; $mysql_count='01017'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG)
{
$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|$callerid";
$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|";
&agi_output;
}
@@ -2183,7 +2185,7 @@ if ($call_handle_method =~ /SURVEY/)
}
# they opted in
if ( ($opt_code =~ /\d/) || ($survey_no_response_action =~ /OPTOUT/) )
if ( ($opt_code =~ /\d|\*|\#/) || ($survey_no_response_action =~ /OPTOUT/) )
{
$now_date_epoch = time();
$FDtarget = ($now_date_epoch + 60);
@@ -2721,10 +2723,15 @@ while ($drop_timer <= $DROP_TIME)
##### Attempt to send call to an agent on this server only #####
if ($agent_search_method =~ /^SO|^LO/)
if ( ($agent_search_method =~ /^SO|^LO/) || ( ( ($SSagent_search_method == 1) || ($SSagent_search_method == 3) ) && ($agent_search_method_OVERRIDE =~ /^SO|^LO/) ) )
{
if ($agent_search_method =~ /^SO/)
{$agent_search_method = 'LO';}
if ( ( ($SSagent_search_method == 1) || ($SSagent_search_method == 3) ) && ($agent_search_method_OVERRIDE =~ /^SO/) )
{
if ($AGILOG) {$agi_string = "|Agent Search Method Campaign Override: $agent_search_method_OVERRIDE ($SSagent_search_method)$agent_search_method|"; &agi_output;}
$agent_search_method = 'SO';
}
if ($DBconcurrent_transfers =~ /AUTO/)
{
@@ -3988,7 +3995,7 @@ while ($drop_timer <= $DROP_TIME)
### END routing-initiated agent call recording for ALLCALLS/ALLFORCE ###
}
if ($extension_appended_cidname =~ /Y/)
if ($extension_appended_cidname =~ /Y|USER/)
{
$eac_extension='';
$stmtA = "SELECT extension,campaign_id FROM vicidial_live_agents where user='$VDADuser' order by last_call_time limit 1;";
@@ -4340,6 +4347,14 @@ if ($drop_timer > $DROP_TIME)
$dbhP=$dbhA; $mysql_count='01051'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- VDAD vicidial_list update: |$affected_rows|$CIDlead_id"; &agi_output;}
if ( ($DBdrop_call_seconds < 0) && ($drop_action =~ /IN_GROUP/) )
{
$stmtA = "INSERT IGNORE INTO vicidial_shared_drops (callerid,server_ip,campaign_id,status,lead_id,uniqueid,channel,phone_code,phone_number,call_time,call_type,stage,last_update_time,alt_dial,drop_time) SELECT callerid,server_ip,campaign_id,status,lead_id,uniqueid,channel,phone_code,phone_number,call_time,call_type,stage,last_update_time,alt_dial,now() from vicidial_auto_calls where callerid='$callerid' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01XXX'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
if ($AGILOG) {$agi_string = "-- SHARED drop record inserted: |$affected_rows|$VDADcampaign|"; &agi_output;}
}
$stmtA = "DELETE FROM vicidial_auto_calls where callerid='$callerid' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
$dbhP=$dbhA; $mysql_count='01052'; $MEL_aff_rows=$affected_rows; &mysql_error_logging;
@@ -4491,7 +4506,10 @@ sub enter_pin_number
$totalDTMF='';
if ($interrupt_digit > 1)
{
$interrupt_digit = $interrupt_digit - 48;
if ($interrupt_digit == 35) {$interrupt_digit='#';}
if ($interrupt_digit == 42) {$interrupt_digit='*';}
if ($interrupt_digit >= 48)
{$interrupt_digit = $interrupt_digit - 48;}
$totalDTMF=$interrupt_digit;
}
@@ -4519,7 +4537,7 @@ sub enter_pin_number
}
}
$totalDTMF =~ s/\D//gi;
#$totalDTMF =~ s/\D//gi;
$pin = $totalDTMF;
if ($totalDTMF) {if ($AGILOG) {$agi_string = "digit |$digit| TotalDTMF |$totalDTMF|"; &agi_output;}}