#!/usr/bin/perl # # agi-ingroup_survey.agi version 2.14 # # runs after a call gets transferred from an agent to ask a question, then # optionally transfer to a call menu. Takes settings from an In-Group # # Copyright (C) 2017 Matt Florell LICENSE: AGPLv2 # # changes: # 170816-2357 - first build # $script = 'agi-ingroup_survey.agi'; $wav='.wav'; ($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"; # default path to astguiclient configuration file: $PATHconf = '/etc/astguiclient.conf'; open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n"; @conf = ; close(conf); $i=0; foreach(@conf) { $line = $conf[$i]; $line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi; if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) ) {$PATHhome = $line; $PATHhome =~ s/.*=//gi;} if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) ) {$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;} if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) ) {$PATHagi = $line; $PATHagi =~ s/.*=//gi;} if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) ) {$PATHweb = $line; $PATHweb =~ s/.*=//gi;} if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) ) {$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;} if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) ) {$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;} if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) ) {$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;} if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) ) {$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;} if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) ) {$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;} if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) ) {$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;} if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) ) {$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;} if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) ) {$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;} $i++; } if (!$VARDB_port) {$VARDB_port='3306';} if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";} use DBI; use Asterisk::AGI; $AGI = new Asterisk::AGI; $dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass") or die "Couldn't connect to database: " . DBI->errstr; ### Grab Server values from the database $stmtA = "SELECT agi_output,asterisk_version,ext_context 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; if ($sthArows > 0) { $AGILOG = '0'; @aryA = $sthA->fetchrow_array; $DBagi_output = $aryA[0]; $asterisk_version = $aryA[1]; $DBext_context = $aryA[2]; if ($DBext_context) {$ext_context = $DBext_context;} if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';} if ($DBagi_output =~ /FILE/) {$AGILOG = '2';} if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';} } $sthA->finish(); ### begin parsing run-time options ### if (length($ARGV[0])>1) { if ($AGILOG) {$agi_string = "Perl Environment Dump:"; &agi_output;} $i=0; while ($#ARGV >= $i) { $args = "$args $ARGV[$i]"; if ($AGILOG) {$agi_string = "$i|$ARGV[$i]"; &agi_output;} $i++; } ### list of command-line array arguments: @ARGV_vars = split(/-----/, $ARGV[0]); $CLI_exten = $ARGV_vars[0]; $force_playback = $ARGV_vars[1]; } $|=1; while() { chomp; last unless length($_); if ($AGILOG) { if (/^agi_(\w+)\:\s+(.*)$/) { $AGI{$1} = $2; } } if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;} if (/^agi_priority\:\s+(.*)$/) {$priority = $1;} if (/^agi_channel\:\s+(.*)$/) {$channel = $1;} if (/^agi_extension\:\s+(.*)$/) {$extension = $1;} if (/^agi_type\:\s+(.*)$/) {$type = $1;} if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1; $calleridnum = $callerid;} if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;} } if ( (length($callerid)>20) && ($callerid =~ /\"\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S/) ) { $callerid =~ s/^\"//gi; $callerid =~ s/\".*$//gi; # ### set the callerid to the ACQS value(calleridname) # print "SET CALLERID $callerid\n"; # checkresult($result); # print STDERR "callerID changed: $callerid\n"; } if ( ( (length($calleridname)>5) && ( (!$callerid) or ($callerid =~ /unknown|private|00000000/i) or ($callerid =~ /5551212/) ) ) or ( (length($calleridname)>17) && ($calleridname =~ /\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) ) ) { $callerid = $calleridname; # ### set the callerid to the ACQS value(calleridname) # print "SET CALLERID $callerid\n"; # checkresult($result); # print STDERR "callerID changed: $callerid\n"; } if ($AGILOG) {$agi_string = "AGI Environment Dump:"; &agi_output;} foreach $i (sort keys %AGI) { if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;} } $VDADcampaign=''; $VDADphone=''; $VDADphone_code=''; $callerid =~ s/\"//gi; $callerid =~ s/ .*//gi; $CIDlead_id = $callerid; $CIDlead_id = substr($CIDlead_id, 10, 10); $CIDlead_id = ($CIDlead_id + 0); if ( ($CLIlead_id > 0) && ($CIDlead_id < 1) ) {$CIDlead_id = $CLIlead_id;} $VD_lead_id = $CIDlead_id; if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$CIDlead_id|$callerid|$AST_ver|"; &agi_output;} if ( ($channel =~ /Local/i) && ($AST_ver !~ /^1\.0\.8|^1\.0\.9/) ) { if ($AGILOG) {$agi_string = "+++++ VDAD START LOCAL CHANNEL: EXITING- $priority"; &agi_output;} if ($priority > 2) {sleep(1);} exit; } $AGI->stream_file('sip-silence'); $AGI->stream_file('sip-silence'); ########## FIND vicidial_inbound_survey_log record ########## $stmtA = "SELECT campaign_id,participate,call_date FROM vicidial_inbound_survey_log where lead_id='$CIDlead_id' and uniqueid='$unique_id' order by call_date desc limit 1;"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; $sthArows=$sthA->rows; if ($AGILOG) {$agi_string = "$sthArows|$stmtA|"; &agi_output;} if ($sthArows > 0) { @aryA = $sthA->fetchrow_array; $VD_campaign_id = $aryA[0]; $VD_participate = $aryA[1]; $VD_call_date = $aryA[2]; $sthA->finish(); } else { ### log record not found, hangup and exit if ($AGILOG) {$agi_string = "-- vicidial_inbound_survey_log record not found, exiting: |$CIDlead_id|$unique_id"; &agi_output;} $AGI->hangup($channel); exit; } ### find in-group settings for this call $stmtA = "SELECT inbound_survey,inbound_survey_question_filename,inbound_survey_callmenu from vicidial_inbound_groups where group_id = '$VD_campaign_id';"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; $sthArowsL=$sthA->rows; if ($sthArowsL > 0) { @aryA = $sthA->fetchrow_array; $inbound_survey = $aryA[0]; $inbound_survey_question_filename = $aryA[1]; $inbound_survey_callmenu = $aryA[2]; } $sthA->finish(); ##### BEGIN ASK QUESTION, COLLECT RESPONSE ##### if ( ($inbound_survey =~ /ENABLED/) && (length($inbound_survey_question_filename) > 0) && ($VD_participate =~ /Y/) ) { $digits_to_collect=1; $AGI->stream_file('sip-silence'); $AGI->stream_file('sip-silence'); $AGI->stream_file('silence'); $stmtA = "UPDATE vicidial_inbound_survey_log SET played='R' where lead_id='$CIDlead_id' and uniqueid='$unique_id' and campaign_id='$VD_campaign_id' order by call_date desc limit 1;"; if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} $VISLaffected_rowsX = $dbhA->do($stmtA); $stmtA = "INSERT INTO live_inbound_log (uniqueid,channel,server_ip,caller_id,extension,phone_ext,start_time,comment_a,comment_b,comment_d,comment_e) values('$uniqueid','$channel','$VARserver_ip','$callerid','$extension','$CIDlead_id','$now_date','$VD_campaign_id','$VD_campaign_id','$VD_campaign_id','1');"; if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} $LILaffected_rowsX = $dbhA->do($stmtA); if ($AGILOG) {$agi_string = "-- Ask-Post-Call-Survey RUNNING: $VISLaffected_rowsX|$LILaffected_rowsX|$unique_id|$CIDlead_id|"; &agi_output;} $digit=''; undef $digit; $interrupt_digit=''; undef $interrupt_digit; $digit_loop_counter=0; $interrupt_digit = $AGI->stream_file('sip-silence',"123456789"); $interrupt_digit=''; undef $interrupt_digit; $interrupt_digit = $AGI->stream_file("$inbound_survey_question_filename","123456789"); if ($AGILOG) {$agi_string = "interrupt_digit |$interrupt_digit| |$inbound_survey_question_filename|"; &agi_output;} $digits_being_entered=1; $totalDTMF=''; if ($interrupt_digit > 1) { if ($interrupt_digit == 48) {$interrupt_digit=0;} if ($interrupt_digit == 49) {$interrupt_digit=1;} if ($interrupt_digit == 50) {$interrupt_digit=2;} if ($interrupt_digit == 51) {$interrupt_digit=3;} if ($interrupt_digit == 52) {$interrupt_digit=4;} if ($interrupt_digit == 53) {$interrupt_digit=5;} if ($interrupt_digit == 54) {$interrupt_digit=6;} if ($interrupt_digit == 55) {$interrupt_digit=7;} if ($interrupt_digit == 56) {$interrupt_digit=8;} if ($interrupt_digit == 57) {$interrupt_digit=9;} $totalDTMF=$interrupt_digit; $digit_loop_counter++; } while ( ($digit_loop_counter < $digits_to_collect) ) { $digit = chr($AGI->wait_for_digit('10000')); # wait 5 seconds for input or until the key is pressed if ($digit =~ /\d/) { $totalDTMF = "$totalDTMF$digit"; if ($AGILOG) {$agi_string = "digit |$digit| TotalDTMF |$totalDTMF|"; &agi_output;} # $AGI->say_digits("$digit"); undef $digit; } else { $digit_loop_counter=$digits_to_collect; } $digit_loop_counter++; } $totalDTMF =~ s/\D//gi; $VISLaffected_rows=0; if (length($totalDTMF) > 0) { if ($AGILOG) {$agi_string = "digit |$digit| TotalDTMF |$totalDTMF|"; &agi_output;} } $stmtA = "UPDATE vicidial_inbound_survey_log SET played='Y',dtmf_response='$totalDTMF',next_call_menu='$inbound_survey_callmenu' where lead_id='$CIDlead_id' and uniqueid='$unique_id' and campaign_id='$VD_campaign_id' order by call_date desc limit 1;"; if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} $VISLaffected_rows = $dbhA->do($stmtA); $stmtA = "INSERT INTO live_inbound_log (uniqueid,channel,server_ip,caller_id,extension,phone_ext,start_time,comment_a,comment_b,comment_d,comment_e) values('$uniqueid','$channel','$VARserver_ip','$callerid','$extension','$CIDlead_id','$now_date','$VD_campaign_id','$totalDTMF','$VD_campaign_id>$totalDTMF','1');"; if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} $LILaffected_rows = $dbhA->do($stmtA); if ($AGILOG) {$agi_string = "-- Ask-Post-Call-Survey DONE: $VISLaffected_rows|$LILaffected_rows|$totalDTMF|$unique_id|$CIDlead_id|"; &agi_output;} ### send call to a call menu, if defined if (length($inbound_survey_callmenu) > 0) { $AGI->stream_file('sip-silence'); $AGI->stream_file('sip-silence'); $AGI->stream_file('sip-silence'); $AGI->stream_file('sip-silence'); if ($AGILOG) {$agi_string = "exiting the ingroup survey app, transferring call to s:$inbound_survey_callmenu"; &agi_output;} print "SET CONTEXT $inbound_survey_callmenu\n"; $result = ; checkresult($result); print "SET EXTENSION s\n"; $result = ; checkresult($result); print "SET PRIORITY 1\n"; $result = ; checkresult($result); } else { ### no call menu defined, hangup and exit if ($AGILOG) {$agi_string = "-- exiting the ingroup survey app, no call menu defined: |$CIDlead_id|$unique_id"; &agi_output;} $AGI->hangup($channel); exit; } } ##### END ASK QUESTION, COLLECT RESPONSE ##### $dbhA->disconnect(); exit; sub checkresult { my ($res) = @_; my $retval; $tests++; chomp $res; if ($res =~ /^200/) { $res =~ /result=(-?\d+)/; if (!length($1)) { # print STDERR "FAIL ($res)\n"; $fail++; } else { # print STDERR "PASS ($1)\n"; $pass++; } } else { # print STDERR "FAIL (unexpected result '$res')\n"; $fail++; } } sub agi_output { if ($AGILOG >=2) { ### open the log file for writing ### open(Lout, ">>$AGILOGfile") || die "Can't open $AGILOGfile: $!\n"; print Lout "$now_date|$script|$agi_string\n"; close(Lout); } ### send to STDERR writing ### if ( ($AGILOG == '1') || ($AGILOG == '3') ) {print STDERR "$now_date|$script|$agi_string\n";} $agi_string=''; } # subroutine to parse the asterisk version # and return a hash with the various part sub parse_asterisk_version { # grab the arguments my $ast_ver_str = $_[0]; # get everything after the - and put it in $ast_ver_postfix my @hyphen_parts = split( /-/ , $ast_ver_str ); my $ast_ver_postfix = $hyphen_parts[1]; # now split everything before the - up by the . my @dot_parts = split( /\./ , $hyphen_parts[0] ); my %ast_ver_hash; if ( $dot_parts[0] <= 1 ) { %ast_ver_hash = ( "major" => $dot_parts[0], "minor" => $dot_parts[1], "build" => $dot_parts[2], "revision" => $dot_parts[3], "postfix" => $ast_ver_postfix ); } # digium dropped the 1 from asterisk 10 but we still need it if ( $dot_parts[0] > 1 ) { %ast_ver_hash = ( "major" => 1, "minor" => $dot_parts[0], "build" => $dot_parts[1], "revision" => $dot_parts[2], "postfix" => $ast_ver_postfix ); } return ( %ast_ver_hash ); }