Created stable release branch of 2.13

git-svn-id: svn://192.168.202.10@2631 3d104415-ff17-0410-8863-d5cf3c621b8a
This commit is contained in:
mattf
2016-11-27 02:22:52 +00:00
parent 8a8b6e65d4
commit 5bcff3bfa4
1977 changed files with 755298 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
################ INSTALL
For in-depth installation instructions read the docs/SCRATCH_INSTALL.txt file
For more brief install instructions read the docs/BASE_INSTALL.txt file
For Requirements of astGUIclient/VICIDIAL read the docs/REQUIREMENTS.txt file
For installtion on Ubuntu Linux read the docs/Ubuntu_install.txt
To place the astGUIclient/VICIDIAL files where they belong on the server:
run the install.pl script from this directory:
perl install.pl
If you are upgrading from a previous version, see the UPGRADE file
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,3 @@
<html><body bgcolor=white>
Static language builds are no longer supported. For more information on our new non-English language dynamic features, please <a href="http://www.vicidial.org/docs/LANGUAGES_QXZ_notes.txt">click here</a>.
</body></html>
@@ -0,0 +1,29 @@
#!/bin/bash
cd /usr/src
wget http://www.daveltd.com/src/util/ttyload/ttyload-0.4.4.tar.gz
wget http://superb-west.dl.sourceforge.net/sourceforge/ploticus/pl240src.tar.gz
wget http://bart.eaccelerator.net/source/0.9.5.2/eaccelerator-0.9.5.2.tar.bz2
wget http://superb-east.dl.sourceforge.net/sourceforge/mtop/mtop-0.6.6.tar.gz
wget http://download.berlios.de/sipsak/sipsak-0.9.6-1.tar.gz
wget http://ftp.digium.com/pub/asterisk/releases/asterisk-1.2.29.tar.gz
wget http://ftp.digium.com/pub/zaptel/releases/zaptel-1.2.24.tar.gz
#wget http://ftp.digium.com/pub/zaptel/releases/zaptel-1.2.26.tar.gz
wget http://ftp.digium.com/pub/libpri/releases/libpri-1.2.7.tar.gz
#wget http://downloads.digium.com/pub/asterisk/releases/asterisk-1.4.19.1.tar.gz
#wget http://downloads.digium.com/pub/libpri/libpri-1.4.3.tar.gz
#wget http://downloads.digium.com/pub/zaptel/zaptel-1.4.10.tar.gz
mkdir patches
cd patches
wget http://www.eflo.net/files/app_amd2.c
wget http://www.eflo.net/files/amd2.conf
wget http://www.eflo.net/files/meetme_DTMF_passthru-1.2.23.patch
wget http://www.eflo.net/files/meetme_volume_control_1.2.16.patch
wget http://www.eflo.net/files/cli_chan_concise_delimiter.patch
wget http://www.eflo.net/files/app_waitforsilence.c
wget http://www.eflo.net/files/enter.h
wget http://www.eflo.net/files/leave.h
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,411 @@
#!/usr/bin/perl
#
# VDL_CID_lookup.agi version 2.6
#
# runs after a call goes through AMD in extensions.conf to send the call on to
# it's proper destination
#
# You need to put lines similar to those below in your extensions.conf file:
#
# ; VICIDIAL_auto_dialer transfer script AMD with Load Balanced:
# exten => 8369,1,Ringing
# exten => 8369,2,Wait(1)
# exten => 8369,3,Answer
# exten => 8369,4,AGI(VDL_CID_lookup.agi)
# exten => 8369,5,AGI(agi-VDAD_ALL_inbound.agi,CID-----LB-----IN_TEST-----7275551212-----Closer-----park----------999-----1)
# exten => 8369,6,Hangup
# exten => 8369,7,AGI(call_logCID.agi,${EXTEN}-----${CALLERID}-----${CALLERIDNUM}-----${CALLERIDNAME})
# exten => 8369,8,AGI(agi-VDADinbound_NI_DNC_CIDlookup.agi)
# exten => 8369,9,Hangup
#
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: GPLv2
#
# changes:
# 80930-0226 - first build
# 81015-1702 - added filter stats
# 130108-1836 - Changes for Asterisk 1.8 compatibility
#
$filter_stats = 1;
$script = 'VDL_CID_lookup.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$SQLdate = "$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 = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n [-q] = quiet\n [-t] = test\n [-debug] = verbose debug messages\n\n";
}
else
{
if ($args =~ /-V/i)
{
$V=1;
}
if ($args =~ /-debug/i)
{
$DG=1;
}
if ($args =~ /-dbAVS/i)
{
$DGA=1;
}
if ($args =~ /-q/i)
{
$q=1;
$Q=1;
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
}
}
$|=1;
while(<STDIN>)
{
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;
}
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;
}
if ($AGILOG) {$agi_string = "AGI Environment Dump:"; &agi_output;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|BUS: $business_hours|"; &agi_output;}
$callerid =~ s/\"//gi;
if ($filter_stats > 0)
{
### find out if phone number exists in the vicidial_list table
$stmtA = "SELECT count(*) FROM vicidial_list where phone_number = '$callerid';";
$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;
$VDL_count = "$aryA[0]";
}
$sthA->finish();
if ($VDL_count < 1)
{
$priority = ($priority + 3);
$stmtA = "INSERT INTO live_inbound_log (uniqueid,channel,server_ip,caller_id,extension,start_time,comment_a,comment_b) values('$uniqueid','$channel','$VARserver_ip','$callerid','$extension','$SQLdate','INBOUND_IVR_FILTER','NOT_FOUND')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- cid_lookup finish: : |$affected_rows|$callerid|$priority|NOT_FOUND|"; &agi_output;}
print "SET PRIORITY $priority\n";
$result = <STDIN>;
checkresult($result);
$dbhA->disconnect();
exit;
}
else ################# LEAD IN SYSTEM, FILTER FURTHER #########################
{
$stmtA = "SELECT count(*) FROM vicidial_list where phone_number = '$callerid' and status IN('A1','A2','A3','A4','SALE');";
$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;
$sales_count = "$aryA[0]";
}
$sthA->finish();
if ($sales_count > 0)
{
$priority = ($priority + 3);
$stmtA = "INSERT INTO live_inbound_log (uniqueid,channel,server_ip,caller_id,extension,start_time,comment_a,comment_b,comment_c) values('$uniqueid','$channel','$VARserver_ip','$callerid','$extension','$SQLdate','INBOUND_IVR_FILTER','EXISTING','SALE')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- cid_lookup finish: : |$affected_rows|$callerid|$priority|EXISTING|SALE|"; &agi_output;}
print "SET PRIORITY $priority\n";
$result = <STDIN>;
checkresult($result);
$dbhA->disconnect();
exit;
}
$stmtA = "SELECT count(*) FROM vicidial_list where phone_number = '$callerid' and status IN('DNC');";
$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;
$dnc_count = "$aryA[0]";
}
$sthA->finish();
if ($dnc_count > 0)
{
$priority = ($priority + 3);
$stmtA = "INSERT INTO live_inbound_log (uniqueid,channel,server_ip,caller_id,extension,start_time,comment_a,comment_b,comment_c) values('$uniqueid','$channel','$VARserver_ip','$callerid','$extension','$SQLdate','INBOUND_IVR_FILTER','EXISTING','DNC')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- cid_lookup finish: : |$affected_rows|$callerid|$priority|EXISTING|DNC|"; &agi_output;}
print "SET PRIORITY $priority\n";
$result = <STDIN>;
checkresult($result);
$dbhA->disconnect();
exit;
}
$stmtA = "SELECT count(*) FROM vicidial_list where phone_number = '$callerid' and list_id NOT IN('999999');";
$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;
$archive_count = "$aryA[0]";
}
$sthA->finish();
if ($archive_count < 1)
{
$priority = ($priority + 3);
$stmtA = "INSERT INTO live_inbound_log (uniqueid,channel,server_ip,caller_id,extension,start_time,comment_a,comment_b,comment_c) values('$uniqueid','$channel','$VARserver_ip','$callerid','$extension','$SQLdate','INBOUND_IVR_FILTER','EXISTING','ARCHIVE')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- cid_lookup finish: : |$affected_rows|$callerid|$priority|EXISTING|ARCHIVE|"; &agi_output;}
print "SET PRIORITY $priority\n";
$result = <STDIN>;
checkresult($result);
$dbhA->disconnect();
exit;
}
$stmtA = "INSERT INTO live_inbound_log (uniqueid,channel,server_ip,caller_id,extension,start_time,comment_a,comment_b,comment_c) values('$uniqueid','$channel','$VARserver_ip','$callerid','$extension','$SQLdate','INBOUND_IVR_FILTER','CLEAN','TO_AGENT')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- cid_lookup finish: : |$affected_rows|$callerid|$priority|EXISTING|CLEAN|"; &agi_output;}
exit;
}
}
else
{
### find out if phone number exists in the vicidial_list table
$stmtA = "SELECT count(*) FROM vicidial_list where phone_number = '$callerid' and list_id NOT IN('999999');";
$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;
$VDL_count = "$aryA[0]";
}
$sthA->finish();
if ($VDL_count < 1)
{
$priority = ($priority + 3);
if ($AGILOG) {$agi_string = "-- cid_lookup finish: |$priority|$callerid"; &agi_output;}
print "SET PRIORITY $priority\n";
$result = <STDIN>;
checkresult($result);
}
}
$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='';
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,394 @@
#!/usr/bin/perl
#
# VD_auto_post_VERIFY.agi version 2.0.5 *DBI-version*
#
# NOTE: This script is only used with auto-message campaigns with dynamic data
#
# runs after a call is answered
#
# You need to put lines similar to those below in your extensions.conf file:
#
# ; VICIDIAL_auto_dialer transfer script AMD with Load Balanced:
#exten => 8320,1,WaitForSilence(2000,2) ; wait for 2 seconds of silence
#exten => 8320,2,AGI(VD_auto_post_VERIFY.agi,${EXTEN})
#exten => 8320,3,Hangup
#
#
# Copyright (C) 2008 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 60915-1616 - first build
# 100903-0041 - Changed lead_id max length to 10 digits
#
$script = 'VD_auto_post_VERIFY.agi';
### files to play for message of not interested or DNC and your request has been processed
$goodbye_audio_file = 'US_reminder_goodbye';
$mc_one_file = '85100019';
$mc_two_file = '85100021';
$visa_one_file = '85100018';
$visa_two_file = '85100020';
#$A = 1; # set to 1 for AMD output messages mode
$AMD_LOG = 0; # set to 1 for logfile
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$start_time=$now_date;
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec";
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$SQLdateBEGIN = $SQLdate;
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n [-q] = quiet\n [-t] = test\n [-debug] = verbose debug messages\n\n";
}
else
{
if ($args =~ /-V/i)
{
$V=1;
}
if ($args =~ /-debug/i)
{
$DG=1;
}
if ($args =~ /-dbAVS/i)
{
$DGA=1;
}
if ($args =~ /-q/i)
{
$q=1;
$Q=1;
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
}
}
$|=1;
while(<STDIN>)
{
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;}
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;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|$calleridname|$priority|"; &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);
$VD_lead_id = $CIDlead_id;
if ($AGILOG) {$agi_string = "+++++ VD amd START: |$CIDlead_id|$now_date|$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;
}
# Thank you for your recent purchase of ACME Sprockets, we have
# confirmed your enrollment in the
# [Verified by Visa| MasterCard SecureCode]
# program. Please go to www.iconfirm.net and enter your name and
# verification code
# [verification code]
# within the next (x amount of hours) to
# complete
# [Verified by Visa|MasterCard SecureCode]
# authentication. Your
# participation is optional and does not effect the processing of your
# purchase. Thank you."
$AGI->stream_file('beep');
$stmtA = "UPDATE vicidial_log set status='PU' where lead_id='$VD_lead_id' order by call_date desc limit 1;";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_log PU update: |$affected_rows|$uniqueid|"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='PU' where lead_id='$VD_lead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_list PU update: |$affected_rows|$uniqueid|"; &agi_output;}
### Check to see if the number is in the system ###
$stmtA= "SELECT security_phrase,comments from vicidial_list where lead_id='$VD_lead_id';";
$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;
$security_phrase = "$aryA[0]";
$comments = "$aryA[1]";
$sthA->finish();
}
else
{
$AGI->stream_file("$goodbye_audio_file");
}
### first read of the message
if ($comments =~ /Master/i)
{
$message_one = $mc_one_file;
$message_two = $mc_two_file;
}
else
{
$message_one = $visa_one_file;
$message_two = $visa_two_file;
}
if ($AGILOG) {$agi_string = "Verify message playing: |$VD_lead_id|$security_phrase|$comments|$message_one|$message_two|"; &agi_output;}
$AGI->stream_file("$message_one");
sleep(1);
$AGI->stream_file("letters/v");
$AGI->say_digits("$security_phrase");
sleep(1);
$AGI->stream_file("$message_two");
$stmtA = "UPDATE vicidial_log set status='AL' where lead_id='$VD_lead_id' order by call_date desc limit 1;";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_log AM update: |$affected_rows|$uniqueid|"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='AL' where lead_id='$VD_lead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_list AM update: |$affected_rows|$uniqueid|"; &agi_output;}
$dbhA->disconnect();
### second read of the message
$AGI->stream_file("$message_one");
sleep(1);
$AGI->stream_file("letters/v");
$AGI->say_digits("$security_phrase");
sleep(1);
$AGI->stream_file("$message_two");
$AGI->stream_file("$goodbye_audio_file");
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='';
}
@@ -0,0 +1,710 @@
#!/usr/bin/perl
#
# agent_monitor.agi version 2.8
#
# This script is designed to allow managers to listen to agent sessions by
# dialing a phone exten number or user ID number. For this to work, the user ID
# or phone extension must be only digits. If you are using the phone extension,
# then all phone extensions on the system must be unique.
#
# user is prompted for a user ID or phone login then press #
# then the user is forwarded to monitor the active vicidial agent session
#
# ; settings for this script:
# ; 1. USER, PHONE, PLOGIN or REDIRECT, lookup by user id, phone extension or phone login (default is USER)
# ; 2. Y or N, log in api log (default is N)
# ; 3. BARGE or LISTEN, (default is LISTEN)
# ; 4. Prepopulated ID, for use in context by itself
# ; 5. Campaign limits, double-dash-delimited, i.e. "TEST--TEST2", (default is disabled)
# ; 6. Y or N, play user IDs to listen to (default is N)
#
# can be added as an AGI to a Call Menu, or just a direct extension transfer:
#
# ; call menu AGI with options:
# agent_monitor.agi,USER---N---LISTEN------TEST--TEST2---N
#
# ; or as extension transfer to "up_monitor" context and "s" extension
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 130716-1315 - First build based upon agi-phone_monitor.agi
# 130925-1823 - Added variable filter to prevent DID SQL injection attack
#
&get_time_now;
$start_epoch = $now_date_epoch;
$script = 'agent_monitor.agi';
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
($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";}
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$CIDdate = "$mon$mday$hour$min$sec";
while (length($CIDdate) > 9) {$CIDdate =~ s/^.//gi;} # 0902235959 changed to 902235959
$US='_';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ 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/agent_monitor.$year-$mon-$mday";}
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
($START_s_hires, $START_usec) = gettimeofday();
$START_usec = sprintf("%06s", $START_usec);
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;
### 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]);
$user_phone = $ARGV_vars[0];
$api_log = $ARGV_vars[1];
$barge_listen = $ARGV_vars[2];
$prepop_id = $ARGV_vars[3];
$campaigns_limit = $ARGV_vars[4];
$users_list = $ARGV_vars[5];
}
if ( (length($user_phone) < 1) || ($user_phone !~ /USER|PHONE|PLOGIN|REDIRECT/) )
{$user_phone = 'USER';}
if ( (length($api_log) < 1) || ($api_log !~ /Y|N/) )
{$api_log = 'N';}
if ( (length($barge_listen) < 1) || ($barge_listen !~ /BARGE|LISTEN/) )
{$barge_listen = 'LISTEN';}
if ( (length($users_list) < 1) || ($users_list !~ /Y|N/) )
{$users_list = 'N';}
$campaigns_limitSQL='';
if (length($campaigns_limit) > 1)
{
$campaigns_limitSQL = $campaigns_limit;
$campaigns_limitSQL =~ s/--/','/gi;
$campaigns_limitSQL = "and campaign_id IN('$campaigns_limitSQL')";
$campaigns_limitSQL =~ s/,''//gi;
}
### END parsing run-time options ###
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($V)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
$callerid =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$calleridname =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$extension =~ s/\'|\"|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$orig_callerid = $callerid;
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
$phone_number=$callerid;
### Grab Server values from the database
$stmtA = "SELECT ext_context,agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$DBext_context = $aryA[0];
$DBagi_output = $aryA[1];
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';}
$rec_count++;
}
$sthA->finish();
if ($calleridname =~ /^AGMON/)
{
$user_REDIRECT=0;
if ($user_phone =~ /REDIRECT/)
{$user_REDIRECT++;}
$stmtA = "SELECT channel,server_ip,user_phone,api_log,barge_listen,prepop_id,campaigns_limit,users_list,context FROM vicidial_monitor_calls where callerid='$calleridname';";
$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;
$channel = $aryA[0];
$server_ip = $aryA[1];
$user_phone = $aryA[2];
$api_log = $aryA[3];
$barge_listen = $aryA[4];
$prepop_id = $aryA[5];
$campaigns_limit = $aryA[6];
$users_list = $aryA[7];
$context = $aryA[8];
}
$sthA->finish();
if ($AGILOG) {$agi_string = "EXISTING MONITOR SESSION: |$calleridname|$channel|$server_ip|$user_phone|$api_log|$barge_listen|$prepop_id|$campaigns_limit|$users_list|$context|"; &agi_output;}
$campaigns_limitSQL='';
if (length($campaigns_limit) > 1)
{
$campaigns_limitSQL = $campaigns_limit;
$campaigns_limitSQL =~ s/--/','/gi;
$campaigns_limitSQL = "and campaign_id IN('$campaigns_limitSQL')";
$campaigns_limitSQL =~ s/,''//gi;
}
if ($user_REDIRECT > 0)
{
$MHGqueryCID = "AGMHG$CIDdate$START_usec";
### insert a NEW record to the vicidial_manager table to be processed
$stmtA = "INSERT INTO vicidial_manager values('','','$SQLdate','NEW','N','$server_ip','','Redirect','$MHGqueryCID','Channel: $channel','Context: $context','Exten: s','Priority: 1','CallerID: $MHGqueryCID','','','','','')";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- AGENT MONITOR CALL RESET: |$affected_rows|$calleridname|$channel|$server_ip|$context|$MHGqueryCID|"; &agi_output;}
sleep(5);
exit;
}
}
else
{
### Insert agent monitor record entry to keep track of the call
$MONqueryCID = "AGMON$CIDdate$START_usec";
$calleridname = $MONqueryCID;
$AGI->set_callerid($MONqueryCID);
print STDERR "Setting CID \"$MONqueryCID\"\n";
$stmtA="INSERT INTO vicidial_monitor_calls set server_ip='$VARserver_ip',callerid='$MONqueryCID',channel='$channel',context='$context',uniqueid='$uniqueid',monitor_time=NOW(),user_phone='$user_phone',api_log='$api_log',barge_listen='$barge_listen',prepop_id='$prepop_id',campaigns_limit='$campaigns_limit',users_list='$users_list';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "MONITOR CALLS INSERT $affected_rows|$stmtA|"; &agi_output;}
}
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
if ($users_list =~ /Y/i)
{
### find sox binary to do the combination of audio files for agent listing
$soxbin = '';
if ( -e ('/usr/bin/sox')) {$soxbin = '/usr/bin/sox';}
else
{
if ( -e ('/usr/local/bin/sox')) {$soxbin = '/usr/local/bin/sox';}
else
{
print "Can't find sox binary! Exiting...\n";
$AGI->stream_file('an-error-has-occured');
exit;
}
}
}
$entry_chances=0;
$VALID_login=0;
$ACTIVE_login=0;
$VDADremDIALstr='';
while ( ($entry_chances < 3) && ($VALID_login < 1) )
{
$entry_chances++;
if (length($prepop_id)<2)
{
&user_phone_gather;
}
else
{$PIN_number = $prepop_id;}
###### Check userID and password against vicidial_users table
$stmtA = "SELECT count(*) FROM vicidial_users where user='$PIN_number' and active='Y';";
if ($user_phone =~ /PHONE/)
{$stmtA = "SELECT count(*) FROM phones where extension='$PIN_number' and active='Y';";}
if ($user_phone =~ /PLOGIN/)
{$stmtA = "SELECT count(*) FROM phones where login='$PIN_number' and active='Y';";}
$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;
$VALID_login = $aryA[0];
}
$sthA->finish();
if ($VALID_login > 0)
{
$AGI->stream_file('pin-number-accepted');
}
else
{
if ($api_log =~ /Y/)
{
$stmtA="INSERT INTO vicidial_api_log set user='$calleridname',agent_user='$PIN_number',function='phone_monitor',value='',result='ERROR',result_reason='No user found',source='monitor',data='$calleridname|$callerid',api_date='$now_date',api_script='$script',run_time='0';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "API LOG INSERT $affected_rows|$stmtA|"; &agi_output;}
}
$AGI->stream_file('pin-invalid');
}
}
if ($VALID_login < 1)
{
if ($AGILOG) {$agi_string = "PHONE MONITOR END: Invalid Login |$VALID_login|$PIN_number|"; &agi_output;}
if ($use_call_menu =~ /Y/)
{
if ($AGILOG) {$agi_string = "exiting the agent dial-in app, transferring call to B @ $context"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION B\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
}
else
{
$AGI->stream_file('vm-goodbye');
$AGI->hangup();
$dbhA->disconnect();
}
exit;
}
else
{
$secX = time();
$PDtarget = ($secX - 30);
($Psec,$Pmin,$Phour,$Pmday,$Pmon,$Pyear,$Pwday,$Pyday,$Pisdst) = localtime($PDtarget);
$Pyear = ($Pyear + 1900);
$Pmon++;
if ($Pmon < 10) {$Pmon = "0$Pmon";}
if ($Pmday < 10) {$Pmday = "0$Pmday";}
if ($Phour < 10) {$Phour = "0$Phour";}
if ($Pmin < 10) {$Pmin = "0$Pmin";}
if ($Psec < 10) {$Psec = "0$Psec";}
$PDtsSQLdate = "$Pyear$Pmon$Pmday$Phour$Pmin$Psec";
###### Check if user is logged in, vicidial_live_agents table
$stmtA = "SELECT count(*) FROM vicidial_live_agents where user='$PIN_number' and extension NOT LIKE \"R/%\" and last_update_time > \"$PDtsSQLdate\" $campaigns_limitSQL;";
if ($user_phone =~ /PHONE/)
{$stmtA = "SELECT count(*) FROM vicidial_live_agents where extension LIKE \"%/$PIN_number\" and extension NOT LIKE \"R/%\" and last_update_time > \"$PDtsSQLdate\" $campaigns_limitSQL;";}
if ($user_phone =~ /PLOGIN/)
{
$PLOGIN_extension='XXXXXXXXXXXXXXXXXX';
$PLOGIN_server_ip='1.1.1.1';
$stmtA = "SELECT extension,server_ip FROM phones where login='$PIN_number' and active='Y';";
$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;
$PLOGIN_extension = $aryA[0];
$PLOGIN_server_ip = $aryA[1];
}
$sthA->finish();
if ($AGILOG) {$agi_string = "PLOGIN DEBUG: |$PLOGIN_extension|$PLOGIN_server_ip|$stmtA|"; &agi_output;}
$stmtA = "SELECT count(*) FROM vicidial_live_agents where extension LIKE \"%/$PLOGIN_extension\" and server_ip='$PLOGIN_server_ip' and extension NOT LIKE \"R/%\" and last_update_time > \"$PDtsSQLdate\" $campaigns_limitSQL;";
}
$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;
$ACTIVE_login = "$aryA[0]";
}
$sthA->finish();
if ($ACTIVE_login < 1)
{
if ($AGILOG) {$agi_string = "PHONE MONIOR END: Inactive Login |$VALID_login|$PIN_number|$PASS_word| |$ACTIVE_login|$PDtsSQLdate|$stmtA|"; &agi_output;}
if ($api_log =~ /Y/)
{
$stmtA="INSERT INTO vicidial_api_log set user='$calleridname',agent_user='$PIN_number',function='phone_monitor',value='',result='ERROR',result_reason='Inactive Login',source='monitor',data='$calleridname|$callerid',api_date='$now_date',api_script='$script',run_time='0';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "API LOG INSERT $affected_rows|$stmtA|"; &agi_output;}
}
$AGI->stream_file('login-fail');
$AGI->stream_file('vm-goodbye');
$AGI->hangup();
$dbhA->disconnect();
exit;
}
else
{
$stmtA = "SELECT conf_exten,extension,server_ip,campaign_id from vicidial_live_agents WHERE user='$PIN_number' and extension NOT LIKE \"R/%\" and last_update_time > \"$PDtsSQLdate\" $campaigns_limitSQL limit 1;";
if ($user_phone =~ /PHONE/)
{$stmtA = "SELECT conf_exten,extension,server_ip,campaign_id FROM vicidial_live_agents where extension LIKE \"%/$PIN_number\" and extension NOT LIKE \"R/%\" and last_update_time > \"$PDtsSQLdate\" $campaigns_limitSQL limit 1;";}
if ($user_phone =~ /PLOGIN/)
{
$PLOGIN_extension='XXXXXXXXXXXXXXXXXX';
$PLOGIN_server_ip='1.1.1.1';
$stmtA = "SELECT extension,server_ip FROM phones where login='$PIN_number' and active='Y';";
$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;
$PLOGIN_extension = $aryA[0];
$PLOGIN_server_ip = $aryA[1];
}
$sthA->finish();
$stmtA = "SELECT conf_exten,extension,server_ip,campaign_id FROM vicidial_live_agents where extension LIKE \"%/$PLOGIN_extension\" and server_ip='$PLOGIN_server_ip' and extension NOT LIKE \"R/%\" and last_update_time > \"$PDtsSQLdate\" $campaigns_limitSQL limit 1;";
}
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_countCUSTDATA=0;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$VDADconf_exten = $aryA[0];
$VDADextension = $aryA[1];
$VDADserver_ip = $aryA[2];
$VDADcampaign_id = $aryA[3];
}
$sthA->finish();
### format the remote server dialstring to get the call to the overflow agent meetme room
$S='*';
if( $VDADserver_ip =~ m/(\S+)\.(\S+)\.(\S+)\.(\S+)/ )
{
$a = leading_zero($1);
$b = leading_zero($2);
$c = leading_zero($3);
$d = leading_zero($4);
# use double-star prefix to go through native bridge IAX path
$VDADremDIALstr = "$S$S$a$S$b$S$c$S$d$S";
}
$barge_listen_prefix = '58';
if($barge_listen =~ /BARGE/)
{$barge_listen_prefix = '59';}
$VDADremDIALstr .= "$barge_listen_prefix$VDADconf_exten";
if ($api_log =~ /Y/)
{
$stmtA="INSERT INTO vicidial_api_log set user='$orig_callerid',agent_user='$PIN_number',function='phone_monitor',value='',result='SUCCESS',result_reason='',source='monitor',data='$VDADconf_exten|$VDADextension|$VDADserver_ip|$calleridname|$callerid',api_date='$now_date',api_script='$script',run_time='0';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "API LOG INSERT $affected_rows|$stmtA|"; &agi_output;}
}
$stmtA="INSERT INTO vicidial_monitor_log set server_ip='$VARserver_ip',callerid='$calleridname',channel='$channel',context='$context',uniqueid='$uniqueid',monitor_time=NOW(),user='$PIN_number',campaign_id='$VDADcampaign_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "MONITOR LOG INSERT $affected_rows|$stmtA|"; &agi_output;}
if ($AGILOG) {$agi_string = "Agent $PIN_number sent to $VDADremDIALstr"; &agi_output;}
print "SET CONTEXT $ext_context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $VDADremDIALstr\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
}
}
$dbhA->disconnect();
exit;
################################################################################
##### SUBROUTINES ##############################################################
################################################################################
##### BEGIN collect the user and password ######################################
sub user_phone_gather
{
################################################################################
# please enter the pin number followed by the pound key
$gsm = '.gsm';
$gather_prompt = 'ld_welcome_pin_number';
if ($users_list =~ /Y/i)
{
### generate user list for live agents available for monitoring
$sox_cmd = "$soxbin --combine concatenate /var/lib/asterisk/sounds/ld_welcome_pin_number.gsm /var/lib/asterisk/sounds/silence.wav";
$secX = time();
$PDtarget = ($secX - 30);
($Psec,$Pmin,$Phour,$Pmday,$Pmon,$Pyear,$Pwday,$Pyday,$Pisdst) = localtime($PDtarget);
$Pyear = ($Pyear + 1900);
$Pmon++;
if ($Pmon < 10) {$Pmon = "0$Pmon";}
if ($Pmday < 10) {$Pmday = "0$Pmday";}
if ($Phour < 10) {$Phour = "0$Phour";}
if ($Pmin < 10) {$Pmin = "0$Pmin";}
if ($Psec < 10) {$Psec = "0$Psec";}
$PDtsSQLdate = "$Pyear$Pmon$Pmday$Phour$Pmin$Psec";
$stmtA = "SELECT user FROM vicidial_live_agents where last_update_time > \"$PDtsSQLdate\" and extension NOT LIKE \"R/%\" $campaigns_limitSQL order by last_update_time desc limit 100;";
if ($user_phone =~ /PHONE/)
{$stmtA = "SELECT extension FROM vicidial_live_agents where extension NOT LIKE \"R/%\" and last_update_time > \"$PDtsSQLdate\" $campaigns_limitSQL limit 100;";}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($AGILOG) {$agi_string = "Available Agents Found: |$sthArows|$stmtA|"; &agi_output;}
$i=0;
while ($sthArows > $i)
{
@aryA = $sthA->fetchrow_array;
$sox_cmd .= " /var/lib/asterisk/sounds/silence.wav /var/lib/asterisk/sounds/user.gsm";
$sox_user = $aryA[0];
$sox_user =~ s/IAX2\/|IAX\/|SIP\///gi;
$sox_user =~ s/\D//gi;
foreach $user_char (split //, $sox_user)
{
$sox_cmd .= " /var/lib/asterisk/sounds/digits/$user_char$gsm";
}
$i++;
}
$sthA->finish();
if ($sthArows < 1)
{
$sox_cmd .= " /var/lib/asterisk/sounds/silence.wav /var/lib/asterisk/sounds/user.gsm /var/lib/asterisk/sounds/unavailable.gsm";
}
$sox_cmd .= " /var/lib/asterisk/sounds/mtemp/$calleridname$gsm";
if ($AGILOG) {$agi_string = "SoX CLI: |$i|$sox_cmd|"; &agi_output;}
@sox_cmd_output = `$sox_cmd`;
sleep(2);
if ( -e ("/var/lib/asterisk/sounds/mtemp/$calleridname$gsm"))
{$gather_prompt = "./mtemp/$calleridname";}
else
{
print "ERROR! Dynamic user list not created! Exiting...\n";
$AGI->stream_file('an-error-has-occured');
exit;
}
}
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file("$gather_prompt",'0123456789');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$PIN_number='';
if ($interrupt_digit > 0)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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;}
$PIN_number=$interrupt_digit;
}
$digit_loop_counter=0;
while ( ($digits_being_entered > 0) && ($digit_loop_counter < 20) )
{
$digit = chr($AGI->wait_for_digit('10000')); # wait 10 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
$PIN_number = "$PIN_number$digit";
print STDERR "digit |$digit| PIN_number |$PIN_number|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digits_being_entered=0;
}
$digit_loop_counter++;
}
$PIN_number =~ s/\D//gi;
if ($PIN_number) {print STDERR "digit |$digit| PIN_number |$PIN_number|\n";}
}
##### END collect the user and password ###############################################
sub get_time_now #get the current date and time and epoch for logging call lengths and datetimes
{
($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";
$filedate = "$year$mon$mday$hour$min$sec";
}
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='';
}
sub leading_zero($)
{
$_ = $_[0];
s/^(\d)$/0$1/;
s/^(\d\d)$/0$1/;
return $_;
} # End of the leading_zero() routine.
@@ -0,0 +1,597 @@
#!/usr/bin/perl
#
# agi-AGENT_dial_in.agi version 2.6
#
# This script is designed to allow agents the ability to dial in to an extension
# to establish the phone connection to their VICIDIAL session. The user login
# and password must be only digits and nothing but digits to use this utility.
#
# user is prompted for their user ID then press #
# user is prompted for their passcode then press #
# then the user is forwarded to the active vicidial agent session
#
# ; settings for this script:
# ; 1. allow user_id only login (disabled by default)
# ; Y - allow user ID only with no password
# ; CONTACTS - lookup the user ID as the 'office_num' field in the contact_information table
# ; N or (blank) - require password (default)
# ; 2. forward to A or B within Call Menu instead of logging into an agent session
# ; Y - forward to A option on valid user ID or B option on invalid user ID
# ; N or (blank) - go to agent session (default)
#
# can be added as an AGI to a Call Menu, or as below:
# ;agent dial-in:
#exten => 2345,1,Answer ; Answer the line
#exten => 2345,2,AGI(agi-AGENT_dial_in.agi)
#exten => 2345,3,Hangup
#
# ; call menu with options:
# agi-AGENT_dial_in.agi,Y---Y
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 81022-2115 - First build
# 120511-1423 - Added new options
# 130108-1809 - Changes for Asterisk 1.8 compatibility
#
&get_time_now;
$start_epoch = $now_date_epoch;
$script = 'agi-AGENT_dial_in.agi';
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
($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";}
$US='_';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ 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/ivrout.$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;
### 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]);
$user_id_only = $ARGV_vars[0];
$use_call_menu = $ARGV_vars[1];
}
if ( (length($user_id_only) < 1) || ($user_id_only !~ /Y|N/) )
{$user_id_only = 'N';}
if ( (length($use_call_menu) < 1) || ($use_call_menu !~ /Y|N/) )
{$use_call_menu = 'N';}
### END parsing run-time options ###
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($V)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
$phone_number=$callerid;
### Grab Server values from the database
$stmtA = "SELECT ext_context,agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$DBext_context = "$aryA[0]";
$DBagi_output = "$aryA[1]";
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';}
$rec_count++;
}
$sthA->finish();
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$entry_chances=0;
$VALID_login=0;
$ACTIVE_login=0;
$VDADremDIALstr='';
while ( ($entry_chances < 3) && ($VALID_login < 1) )
{
$entry_chances++;
&user_password_gather;
###### Check userID and password against vicidial_users table
if ($user_id_only =~ /CONTACT/)
{
#############################################
##### START SYSTEM SETTINGS LOOKUP #####
$stmtA = "SELECT alt_log_server_ip,alt_log_dbname,alt_log_login,alt_log_pass,tables_use_alt_log_db 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;
$alt_log_server_ip = $aryA[0];
$alt_log_dbname = $aryA[1];
$alt_log_login = $aryA[2];
$alt_log_pass = $aryA[3];
$tables_use_alt_log_db = $aryA[4];
}
$sthA->finish();
##### END SYSTEM SETTINGS LOOKUP #####
###########################################
if ( ($tables_use_alt_log_db =~ /contact_information/) && (length($alt_log_server_ip)>4) && (length($alt_log_dbname)>0) )
{
$linkALT = DBI->connect("DBI:mysql:$alt_log_dbname:$alt_log_server_ip:$VARDB_port", "$alt_log_login", "$alt_log_pass")
or die "Couldn't connect to database: " . DBI->errstr;
}
else
{$linkALT = $dbhA;}
$stmtA = "SELECT count(*) FROM contact_information where office_num='$PIN_number';";
$sthA = $linkALT->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $linkALT->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$VALID_login = "$aryA[0]";
}
$sthA->finish();
}
else
{
$stmtA = "SELECT count(*) FROM vicidial_users where user='$PIN_number' and pass='$PASS_word' and active='Y';";
if ($user_id_only =~ /Y/)
{$stmtA = "SELECT count(*) FROM vicidial_users where user='$PIN_number' and active='Y';";}
$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;
$VALID_login = "$aryA[0]";
}
$sthA->finish();
}
if ($VALID_login > 0)
{
$AGI->exec("EXEC Set(_agent_user_id=$PIN_number)");
$AGI->stream_file('pin-number-accepted');
}
else
{
$AGI->stream_file('pin-invalid');
}
}
if ($VALID_login < 1)
{
if ($AGILOG) {$agi_string = "DIAL-IN END: Invalid Login |$VALID_login|$PIN_number|$PASS_word|"; &agi_output;}
if ($use_call_menu =~ /Y/)
{
if ($AGILOG) {$agi_string = "exiting the agent dial-in app, transferring call to B @ $context"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION B\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
}
else
{
$AGI->stream_file('vm-goodbye');
$AGI->hangup();
$dbhA->disconnect();
}
exit;
}
else
{
$secX = time();
$PDtarget = ($secX - 30);
($Psec,$Pmin,$Phour,$Pmday,$Pmon,$Pyear,$Pwday,$Pyday,$Pisdst) = localtime($PDtarget);
$Pyear = ($Pyear + 1900);
$Pmon++;
if ($Pmon < 10) {$Pmon = "0$Pmon";}
if ($Pmday < 10) {$Pmday = "0$Pmday";}
if ($Phour < 10) {$Phour = "0$Phour";}
if ($Pmin < 10) {$Pmin = "0$Pmin";}
if ($Psec < 10) {$Psec = "0$Psec";}
$PDtsSQLdate = "$Pyear$Pmon$Pmday$Phour$Pmin$Psec";
if ($use_call_menu =~ /Y/)
{
if ($AGILOG) {$agi_string = "exiting the agent dial-in app, transferring call to A @ $context"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION A\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
}
else
{
###### Check if user is logged in, vicidial_live_agents table
$stmtA = "SELECT count(*) FROM vicidial_live_agents where user='$PIN_number' and last_update_time > \"$PDtsSQLdate\";";
$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;
$ACTIVE_login = "$aryA[0]";
}
$sthA->finish();
if ($ACTIVE_login < 1)
{
if ($AGILOG) {$agi_string = "DIAL-IN END: Inactive Login |$VALID_login|$PIN_number|$PASS_word| |$ACTIVE_login|$PDtsSQLdate|"; &agi_output;}
$AGI->stream_file('login-fail');
$AGI->stream_file('you-must-be-logged-in');
$AGI->stream_file('vm-goodbye');
$AGI->hangup();
$dbhA->disconnect();
exit;
}
else
{
$stmtA = "SELECT conf_exten,extension,server_ip from vicidial_live_agents WHERE user='$PIN_number' limit 1;";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_countCUSTDATA=0;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$VDADconf_exten = "$aryA[0]";
$VDADextension = "$aryA[1]";
$VDADserver_ip = "$aryA[2]";
}
$sthA->finish();
### format the remote server dialstring to get the call to the overflow agent meetme room
$S='*';
if( $VDADserver_ip =~ m/(\S+)\.(\S+)\.(\S+)\.(\S+)/ )
{
$a = leading_zero($1);
$b = leading_zero($2);
$c = leading_zero($3);
$d = leading_zero($4);
$VDADremDIALstr = "$a$S$b$S$c$S$d$S";
}
$VDADremDIALstr .= "$VDADconf_exten";
if ($AGILOG) {$agi_string = "Agent $PIN_number sent to $VDADremDIALstr"; &agi_output;}
print "SET CONTEXT $ext_context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $VDADremDIALstr\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
}
}
}
$dbhA->disconnect();
exit;
################################################################################
##### SUBROUTINES ##############################################################
################################################################################
##### BEGIN collect the user and password ######################################
sub user_password_gather
{
################################################################################
# please enter the pin number followed by the pound key
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file('ld_welcome_pin_number','0123456789');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$PIN_number='';
if ($interrupt_digit > 0)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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;}
$PIN_number=$interrupt_digit;
}
$digit_loop_counter=0;
while ( ($digits_being_entered > 0) && ($digit_loop_counter < 20) )
{
$digit = chr($AGI->wait_for_digit('10000')); # wait 10 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
$PIN_number = "$PIN_number$digit";
print STDERR "digit |$digit| PIN_number |$PIN_number|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digits_being_entered=0;
}
$digit_loop_counter++;
}
$PIN_number =~ s/\D//gi;
if ($PIN_number) {print STDERR "digit |$digit| PIN_number |$PIN_number|\n";}
if ($user_id_only !~ /Y|CONTACT/)
{
################################################################################
# please enter your password followed by the pound key
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file('enter-password','0123456789');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$PASS_word='';
if ($interrupt_digit > 0)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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;}
$PASS_word=$interrupt_digit;
}
$digit_loop_counter=0;
while ( ($digits_being_entered > 0) && ($digit_loop_counter < 20) )
{
$digit = chr($AGI->wait_for_digit('10000')); # wait 10 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
$PASS_word = "$PASS_word$digit";
print STDERR "digit |$digit| PASS_word |$PASS_word|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digits_being_entered=0;
}
$digit_loop_counter++;
}
$PASS_word =~ s/\D//gi;
if ($PASS_word) {print STDERR "digit |$digit| PASS_word |$PASS_word| PIN_number |$PIN_number|\n";}
}
}
##### END collect the user and password ###############################################
##### SUBROUTINES #####
sub get_time_now #get the current date and time and epoch for logging call lengths and datetimes
{
($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";
$filedate = "$year$mon$mday$hour$min$sec";
}
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='';
}
sub leading_zero($)
{
$_ = $_[0];
s/^(\d)$/0$1/;
s/^(\d\d)$/0$1/;
return $_;
} # End of the leading_zero() routine.
@@ -0,0 +1,478 @@
#!/usr/bin/perl
#
# agi-AGENT_route.agi version 2.6
#
# for use with a Call Menu in the custom dialplan section or as an AGI route.
#
# ; settings for this script:
# ; 1. DID pattern to use for In-group initiation settings ('default' is default)
# ; 2. the agentdirect in-group to send the calls to ('AGENTDIRECT' is default)
# ; 3. transfer only to ACTIVE in the system agent or vicidial LOGGED_IN agent
# ; ('ACTIVE' is default)
# ; 4. prompt for user ID, if this is filled in with a filename it will ask,
# ; otherwise it will assume $extension is the user ID
# ; 5. number of digits required for user ID validation, X will allow anything,
# ; this will only be enforced if "prompt for user ID" prompt is populated
# ; 6. audio filename for invalid selection, agent not available ('invalid' is default)
# ; 7. audio filename for invalid user id re-enter prompt, agent not available
# ; 8. number of retry attempts to enter a valid user ID
# ; this will only be enforced if "prompt for user ID" prompt is populated
# ; 9. in-group to send the call to if there is no valid agent, if none is
# ; defined, then the call will be directed to 's' exten
# ; 10. audio filename before sending call to no-agent route
# ; 11. audio filename before sending call to no-agent route if agent active but
# ; not logged-in to vicidial
#
#; example in CallMenu AGI route with all options
# "agi-AGENT_route.agi,default---AGENTDIRECT---LOGGED_IN---if-u-know-ext-dial---X---invalid---please-try-again---3---TEST_IN3---pbxtransfer---outside-transfer"
#; example with 4-digit agent IDs
# exten => _XXXX,1,AGI(agi-AGENT_route.agi,default---AGENTDIRECT---ACTIVE)
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 100321-0108 - First Build
# 100704-2128 - Added several options
# 130108-1811 - Changes for Asterisk 1.8 compatibility
#
$script = 'agi-AGENT_route.agi';
$S='*';
$US='_';
($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";}
$hm = "$hour$min";
$hm = ($hm + 0);
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$CLInow_date = "$year-$mon-$mday\\ $hour:$min:$sec";
$start_time=$now_date;
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec";
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$SQLdateBEGIN = $SQLdate;
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
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,local_gmt 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];
$local_gmt = $aryA[1];
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]);
$did_settings = $ARGV_vars[0];
$in_group = $ARGV_vars[1];
$agent_active_filter = $ARGV_vars[2];
$user_id_prompt = $ARGV_vars[3];
$minimum_user_digits = $ARGV_vars[4];
$invalid_prompt = $ARGV_vars[5];
$invalid_reenter_prompt = $ARGV_vars[6];
$retry_attempts = $ARGV_vars[7];
$invalid_ingroup = $ARGV_vars[8];
$transfer_prompt = $ARGV_vars[9];
$transfer_logout_prompt = $ARGV_vars[10];
}
if (length($did_settings) < 1)
{$did_settings = 'default';}
if (length($in_group) < 1)
{$in_group = 'AGENTDIRECT';}
if (length($agent_active_filter) < 1)
{$agent_active_filter = 'ACTIVE';}
if (length($invalid_prompt) < 1)
{$invalid_prompt = 'invalid';}
if (length($retry_attempts) < 1)
{$retry_attempts = '3';}
if (length($minimum_user_digits) < 1)
{$minimum_user_digits = 'X';}
$pound_finish = 0;
if ($minimum_user_digits =~ /X/)
{
$minimum_user_digits = '20';
$pound_finish = 1;
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_priority\:\s+(.*)$/) {$priority = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D|\'//gi;
$calleridname =~ s/unknown|\'//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
### Grab DID values from the database
$DIDs_in_system=0;
$stmtA = "SELECT did_id FROM vicidial_inbound_dids where did_pattern = '$did_settings' and did_active='Y';";
$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;
$did_id = $aryA[0];
$DIDs_in_system++;
}
$sthA->finish();
if ($sthArows < 1)
{
### Grab DID values from the database for a default DID pattern if there is one
$stmtA = "SELECT did_id FROM vicidial_inbound_dids where did_pattern = 'default' and did_active='Y';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$DIDs_in_system=$sthA->rows;
if ($DIDs_in_system > 0)
{
@aryA = $sthA->fetchrow_array;
$did_id = $aryA[0];
}
$sthA->finish();
}
### Grab Server values from the database
$cbc=0;
$stmtA = "SELECT 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;
while ($sthArows > $cbc)
{
@aryA = $sthA->fetchrow_array;
$DBext_context = $aryA[0];
if ($DBext_context) {$ext_context = $DBext_context;}
$cbc++;
}
$sthA->finish();
$active_user=0;
$logged_in_user=0;
if (length($user_id_prompt) > 0)
{
$attempts=0;
while ( ($retry_attempts > $attempts) && ($active_user < 1) )
{
$attempts++;
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
&user_id_gather;
&find_if_active_user;
if (length($invalid_reenter_prompt) > 0)
{
$user_id_prompt = $invalid_reenter_prompt;
}
}
}
else
{
&find_if_active_user;
}
if ( ($agent_active_filter =~ /LOGGED_IN/) && ($logged_in_user < 1) && ($active_user > 0) )
{
$transfer_prompt = $transfer_logout_prompt;
$active_user=0;
}
### Route call to a logged-in VICIDIAL agent
if ($active_user > 0)
{
$did_extension = "99909$S$did_id$S$in_group$S$extension$S";
}
else
{
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file("$invalid_prompt");
if (length($invalid_ingroup) > 1)
{
$did_extension = "99909$S$did_id$S$invalid_ingroup$S$S";
}
else
{
$did_extension = "s";
$ext_context = $context;
}
}
if (length($transfer_prompt) > 1)
{
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file("$transfer_prompt");
}
if ($AGILOG) {$agi_string = "exiting the AGENT app, transferring call to $did_extension @ $ext_context"; &agi_output;}
print "SET CONTEXT $ext_context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $did_extension\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
######### SUBROUTINES #################
sub find_if_active_user
{
### find out if user exists and is active in system
$stmtA = "SELECT count(*) FROM vicidial_users where user='$extension' and active='Y';";
$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;
$active_user = $aryA[0];
}
$sthA->finish();
if ($agent_active_filter =~ /LOGGED_IN/)
{
$stmtA = "SELECT count(*) FROM vicidial_live_agents where user='$extension';";
$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;
$logged_in_user = $aryA[0];
}
$sthA->finish();
}
}
##### BEGIN collect the user id number ######################################
sub user_id_gather
{
################################################################################
# please enter the agent id followed by the pound key
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file("$user_id_prompt",'0123456789');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$extension='';
if ($interrupt_digit > 0)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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;}
$extension=$interrupt_digit;
}
$digit_loop_counter=0;
while ( ($digits_being_entered > 0) && ($digit_loop_counter < $minimum_user_digits) )
{
$digit = chr($AGI->wait_for_digit('10000')); # wait 10 seconds for input, until the pound key is pressed or X digits
if ($digit =~ /\d/)
{
$extension = "$extension$digit";
print STDERR "digit |$digit| extension |$extension|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
if ($pound_finish > 0)
{$digits_being_entered=0;}
}
$digit_loop_counter++;
}
$extension =~ s/\D//gi;
if ($extension > 0) {print STDERR "digit collection done|$digit| extension |$extension|\n";}
}
##### END collect the user id number ###############################################
sub checkresult
{
$pass=0; $fail=0;
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='';
}
@@ -0,0 +1,494 @@
#!/usr/bin/perl
#
# agi-CALLCARD_dial_in.agi version 2.6
#
# This script is designed to allow customers the ability to dial in to a DID and
# enter in a PIN number that would look up their account and send on to a
# specified in-group if pin is valid
#
# user is prompted for their PIN number only (no pound '#' required)
# then the user is forwarded to the active vicidial agent session
#
# can be added as an AGI to a Call Menu, or as below:
# Call Menu Entry: "agi-CALLCARD_dial_in.agi,en---3---callcard_pin_enter---callcard_pin_invalid---default"
# ;agent dial-in:
#exten => 2346,1,Answer ; Answer the line
#exten => 2346,2,AGI(agi-CALLCARD_dial_in.agi,en---3---callcard_pin_enter---callcard_pin_invalid---default)
#exten => 2346,3,Hangup
#
# ; Below are the parameters needed for the script to be run properly
# ; 1. language
# ; - en - English <default>
# ; - es - Spanish
# ; - fr - French, not fully supported
# ; 2. maximum attempts before hangup:
# ; - 3 <default>
# ; 3. audio file enter pin number prompt:
# ; - callcard_pin_enter <default>
# ; 4. audio file invalid pin number prompt:
# ; - callcard_pin_invalid <default>
# ; 5. DID pattern to use for in-group forwarding settings:
# ; - default <default>
# ; - USE-ORIGINATING-DID - this option will look up the DID the customer dialed in on and use those settings
#
# other audio files used:
# - pin-number-accepted
# - vm-youhave
# - callcard_minutes_left
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 100311-1135 - First build
# 130108-1812 - Changes for Asterisk 1.8 compatibility
#
&get_time_now;
$start_epoch = $now_date_epoch;
$script = 'agi-CALLCARD_dial_in.agi';
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
($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";}
$US='_';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ 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/ivrout.$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;
# defaults:
$language = 'en';
$maximum_attempts = '3';
$pin_enter_audio = 'callcard_pin_enter';
$pin_invalid_audio = 'callcard_pin_invalid';
$did_ingroup_settings = 'default';
### 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]);
if (length($ARGV_vars[0]) > 0) {$language = $ARGV_vars[0];}
if (length($ARGV_vars[1]) > 0) {$maximum_attempts = $ARGV_vars[1];}
if (length($ARGV_vars[2]) > 0) {$pin_enter_audio = $ARGV_vars[2];}
if (length($ARGV_vars[3]) > 0) {$pin_invalid_audio = $ARGV_vars[3];}
if (length($ARGV_vars[4]) > 0) {$did_ingroup_settings = $ARGV_vars[4];}
}
if ($language =~ /es/)
{
$audio_suffix='_es';
$AGI->exec("EXEC Set(CHANNEL(language)=$language)");
# $AGI->exec("SetLanguage($language)");
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
}
if ($language =~ /fr/)
{
$audio_suffix='_fr';
$AGI->exec("EXEC Set(CHANNEL(language)=$language)");
# $AGI->exec("SetLanguage($language)");
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
}
if ($language !~ /es|fr/) {$audio_suffix='';}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($V)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid=$unique_id}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D|\'//gi;
$calleridname =~ s/unknown|\'//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
$phone_number=$callerid;
### Grab Server values from the database
$stmtA = "SELECT ext_context,agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$DBext_context = "$aryA[0]";
$DBagi_output = "$aryA[1]";
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';}
$rec_count++;
}
$sthA->finish();
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$entry_chances=0;
$VALID_login=0;
$ACTIVE_login=0;
$VDADremDIALstr='';
while ( ($entry_chances < $maximum_attempts) && ($VALID_login < 1) )
{
$entry_chances++;
&user_password_gather;
###### Check userID and password against vicidial_users table
$stmtA = "SELECT count(*) FROM callcard_accounts where pin='$PIN_number' and status IN('ACTIVE','USED') and balance_minutes > 0;";
$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;
$VALID_login = $aryA[0];
}
$sthA->finish();
if ($AGILOG) {$agi_string = "validate PIN: |$VALID_login|$stmtA|"; &agi_output;}
if ($VALID_login > 0)
{
$AGI->stream_file("pin-number-accepted$audio_suffix");
}
else
{
$AGI->stream_file("$pin_invalid_audio$audio_suffix");
}
}
if ($VALID_login < 1)
{
if ($AGILOG) {$agi_string = "DIAL-IN END: Invalid Pin |$VALID_login|$PIN_number|"; &agi_output;}
$AGI->stream_file("vm-goodbye$audio_suffix");
$AGI->hangup();
$dbhA->disconnect();
exit;
}
else
{
$secX = time();
$PDtarget = ($secX - 30);
($Psec,$Pmin,$Phour,$Pmday,$Pmon,$Pyear,$Pwday,$Pyday,$Pisdst) = localtime($PDtarget);
$Pyear = ($Pyear + 1900);
$Pmon++;
if ($Pmon < 10) {$Pmon = "0$Pmon";}
if ($Pmday < 10) {$Pmday = "0$Pmday";}
if ($Phour < 10) {$Phour = "0$Phour";}
if ($Pmin < 10) {$Pmin = "0$Pmin";}
if ($Psec < 10) {$Psec = "0$Psec";}
$PDtsSQLdate = "$Pyear$Pmon$Pmday$Phour$Pmin$Psec";
###### Check for the current minute balance to play back to the customer in the callcard_accounts table
$stmtA = "SELECT card_id,balance_minutes,inbound_group_id FROM callcard_accounts where pin='$PIN_number';";
$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;
$card_id = $aryA[0];
$balance_minutes = $aryA[1];
$inbound_group_id = $aryA[2];
}
$sthA->finish();
###### Check for the current minute balance to play back to the customer in the callcard_accounts table
$stmtA = "SELECT vdl.did_id,did_pattern FROM vicidial_did_log vdl, vicidial_inbound_dids vid where uniqueid='$uniqueid' and vdl.did_id=vid.did_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 ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$original_did_pattern = $aryA[1];
}
$sthA->finish();
if ($did_ingroup_settings =~ /USE-ORIGINATING-DID/)
{$did_id_search = $original_did_pattern;}
else
{$did_id_search = $did_ingroup_settings;}
$did_id=0;
###### find the in-group settings to use when forwarding this call
$stmtA = "SELECT did_id FROM vicidial_inbound_dids where did_pattern='$did_id_search';";
$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;
$did_id = $aryA[0];
}
$sthA->finish();
##### play customer's balance to them before transferring
$AGI->stream_file("vm-youhave$audio_suffix");
$AGI->say_number("$balance_minutes");
$AGI->stream_file("callcard_minutes_left$audio_suffix");
##### update callcard_accounts_detail record for this account
$stmtA = "UPDATE callcard_accounts_detail set used_time='$now_date' where card_id='$card_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "callcard_accounts_detail update: |$affected_rows|$now_date|$card_id|"; &agi_output;}
##### insert callcard_log record for this call
$stmtA = "INSERT INTO callcard_log set uniqueid='$uniqueid',card_id='$card_id',call_time='$now_date',phone_number='$phone_number',inbound_did='$original_did_pattern',balance_minutes_start='$balance_minutes';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "callcard_log INSERT: |$affected_rows|$stmtA|"; &agi_output;}
### format the remote server dialstring to get the call to the overflow agent meetme room
$forward_extension = "99909*$did_id*$inbound_group_id";
if ($AGILOG) {$agi_string = "Customer $PIN_number sent to $forward_extension"; &agi_output;}
print "SET CONTEXT $ext_context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $forward_extension\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
}
$dbhA->disconnect();
exit;
################################################################################
##### SUBROUTINES ##############################################################
################################################################################
##### BEGIN collect the pin number ######################################
sub user_password_gather
{
################################################################################
# please enter the pin number followed by the pound key
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file("$pin_enter_audio$audio_suffix",'0123456789');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$PIN_number='';
if ($interrupt_digit > 0)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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;}
$PIN_number=$interrupt_digit;
}
$digit_loop_counter=0;
while ( ($digits_being_entered > 0) && ($digit_loop_counter < 8) )
{
$digit = chr($AGI->wait_for_digit('10000')); # wait 10 seconds for input, until the pound key is pressed or 8 digits
if ($digit =~ /\d/)
{
$PIN_number = "$PIN_number$digit";
print STDERR "digit |$digit| PIN_number |$PIN_number|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digits_being_entered=0;
}
$digit_loop_counter++;
}
$PIN_number =~ s/\D//gi;
if ($PIN_number) {print STDERR "digit collection done|$digit| PIN_number |$PIN_number|\n";}
}
##### END collect the pin number ###############################################
sub get_time_now #get the current date and time and epoch for logging call lengths and datetimes
{
($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";
$filedate = "$year$mon$mday$hour$min$sec";
}
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='';
}
sub leading_zero($)
{
$_ = $_[0];
s/^(\d)$/0$1/;
s/^(\d\d)$/0$1/;
return $_;
} # End of the leading_zero() routine.
@@ -0,0 +1,261 @@
#!/usr/bin/perl
#
# agi-CANADA_PRI_CIDname.agi version 0.1
#
# Runs after call goes through IAX loop to send out custom CallerIDname on
# Canadian PRIs that allow dynamic setting of CIDname with call initiation
#
# You need to have lines similar to those below in your extensions.conf file:
#
# ;outbound VICIDIAL calls:
#exten => _91NXXNXXXXXX,1,AGI(call_log.agi,${EXTEN})
#exten => _91NXXNXXXXXX,2,AGI(agi-CANADA_PRI_CIDname.agi,${EXTEN})
#exten => _91NXXNXXXXXX,3,Dial(${TRUNKX}/${EXTEN:1},55,tTo)
#exten => _91NXXNXXXXXX,4,Hangup
#
# Copyright (C) 2009 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 90305-2136 - First build
#
$script = 'agi-CANADA_PRI_CIDname.agi';
$AGILOG=0;
$FD=0; # force debug for testing
($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";
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
### 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++;
}
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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";}
if (!$DIDLOGfile) {$DIDLOGfile = "$PATHlogs/didin.$year-$mon-$mday";}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
if (length($calleridname)>0) {$VLcomments = $calleridname;}
else {$VLcomments = '';}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ( (length($callerid)>20) && ($callerid =~ /\"\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S/) )
{
$calleridname =~ s/^\"//gi;
$calleridname =~ s/\".*$//gi;
}
use DBI;
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
$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,local_gmt FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
$local_gmt = "$aryA[1]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### Grab Server values from the database
$stmtA = "SELECT cmd_line_g,cmd_line_h,cmd_line_i,cmd_line_j FROM vicidial_manager where callerid = '$calleridname' 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;
$sthA->finish();
$account_check = "|$aryA[0]|$aryA[1]|$aryA[2]|$aryA[3]";
if ($account_check =~ /usegroupalias=1/)
{
@data = split(/Account: /,$account_check);
$data[1] =~ s/\|.*//gi;
$account = $data[1];
### Grab callerIDname and number from the database
$stmtA = "SELECT caller_id_name,caller_id_number FROM groups_alias where group_alias_id = '$account' 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;
$sthA->finish();
$caller_id_name = "$aryA[0]";
$caller_id_number = "$aryA[1]";
### set the callerid to the ACQS value(calleridname)
## use these two lines for Asterisk 1.2 tree
$newcallerid = "\"$caller_id_name <$caller_id_number>\"";
$AGI->set_callerid($newcallerid);
## use these two lines for Asterisk 1.0 tree
# print "SET CALLERID \"$calleridname\" <0000000000>\n";
# print "SET CALLERIDNAME \"$calleridname\"\n";
print STDERR "Setting CID \"$newcallerid\"\n";
checkresult($result);
if ($AGILOG) {$agi_string = "callerID changed: newcallerid; &agi_output";}
if ($FD > 0) {print STDERR "callerID changed: newcallerid\n";}
if ($AGILOG) {$agi_string = "AGI Variables: |$extension|$areacode|$callerid|$calleridname|newcallerid|"; &agi_output;}
}
}
}
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='';
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,816 @@
#!/usr/bin/perl
#
# agi-IVR_recording_verification.agi version 2.6
#
# This script is designed to function as a complete automated 3rd party
# verification IVR recording system. This script will work by optionally asking
# for a company ID and/or a customer phone number, then it will play through the
# listed prompts asking for a single digit press (i.e. 1 for a yes or a 3 for a
# no, hash/pound/star/zero/0 are not accepted only 1-9 is valid for these steps).
# All data for these calls will be logged to the vicidial_ivr table as well as
# optionally to a log file in the standard astguiclient log file directory
# and/or STDERR output on the asterisk process. This script uses the
# /etc/astguiclient.conf file for database connection settings, logging data and
# for logfile path information only.
#
# With a modified VDAD agi transfer script, this script could also be used to do
# automated outbound surveys as well. Feature under development.
#
# ; 1. the DNIS or inbound number called
# ; 2. play the recording ID (Y|N) with prompt leading up to it
# ; 3. record this call(Y|N)
# ; 4. ask for a company code(Y|N) with the number of digits in that company code and the prompt
# ; 5. ask for a user code(Y|N) with the number of digits in that user code and the prompt
# ; 6. ask for the customer phone number(Y|N) with the number of digits in that phone number and the prompt (Y-10-85100001)
# ; 7. speak the current date (Y|N) with prompt announcing the date
# ; 8. a dash-delimited list of prompts that expect responses(85100002-85100003)
# ; 9. a "your recording ID is..." prompt (85100004)
# ; 10. logging/output (FILE|STDERR|BOTH|NONE)
#
# ;inbound IVR call:
#exten => 1234,1,Ringing ; call ringing
#exten => 1234,2,Wait(1) ; Wait 1 second for CID delivery from PRI
#exten => 1234,3,Answer ; Answer the line
#exten => 1234,4,AGI(agi-IVR_recording_verification.agi,7274506620---Y-85100004---Y---Y-1-85100016---N---N---Y-85100007---85100009-600--85100012-30--85100013---85100004---BOTH)
#exten => 1234,5,Hangup
#
# ;inbound IVR call from a VICIDIAL transfer:
#exten => _83002*.,1,Ringing ; call ringing
#exten => _83002*.,2,Wait(1) ; Wait 1 second for CID delivery
#exten => _83002*.,3,Answer ; Answer the line
#exten => _83002*.,4,AGI(agi-IVR_recording_verification.agi,7275551234---N---Y---N---N---Y-10-85100001---N---85100002-85100003---85100004---BOTH)
#exten => _83002*.,5,Hangup
#
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 70912-1105 - First build, non-functional
# 70916-2331 - functional alpha version, reads all prompts and logs data, no recording yet
# 70921-1110 - full beta version with recording working
# 71028-1122 - added say datetime as an option
# 71112-0238 - added prompt delays and date announcement message
# 71120-1337 - added playing of recording ID at beginning of session
# 120430-2214 - Converted call to Monitor app to be asterisk 1.8 compatible
# 130108-1816 - Changes for Asterisk 1.8 compatibility
#
&get_time_now;
$start_epoch = $now_date_epoch;
$script = 'agi-IVR_recording_verification.agi';
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
($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";}
$US='_';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ 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/ivrout.$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,ext_context,asterisk_version FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
$ext_context = $aryA[1];
$asterisk_version = $aryA[2];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
if ($ARGV[0] =~ /---/)
{
### list of command-line array arguments:
@ARGV_vars = split(/---/, $ARGV[0]);
$inbound_number = $ARGV_vars[0];
$play_ID = $ARGV_vars[1];
$record_call = $ARGV_vars[2];
$company_ID_ask = $ARGV_vars[3];
$user_ID_ask = $ARGV_vars[4];
$cust_phone_ask = $ARGV_vars[5];
$say_date = $ARGV_vars[6];
$prompts = $ARGV_vars[7];
$last_prompt = $ARGV_vars[8];
$AGI_output = $ARGV_vars[9];
@prompts_list = split(/-/, $prompts);
$prompts_count = $#prompts_list;
if ($play_ID =~ /Y/)
{
@play_IDary = split(/-/, $play_ID);
$play_ID_prompt = $play_IDary[1];
}
if ($company_ID_ask =~ /Y/)
{
@company_ID = split(/-/, $company_ID_ask);
$company_ID_length = $company_ID[1];
$company_ID_prompt = $company_ID[2];
}
if ($user_ID_ask =~ /Y/)
{
@user_ID = split(/-/, $user_ID_ask);
$user_ID_length = $user_ID[1];
$user_ID_prompt = $user_ID[2];
}
if ($cust_phone_ask =~ /Y/)
{
@cust_phone_ID = split(/-/, $cust_phone_ask);
$cust_phone_length = $cust_phone_ID[1];
$cust_phone_prompt = $cust_phone_ID[2];
}
if ($say_date =~ /Y/)
{
@say_date_ID = split(/-/, $say_date);
$say_date_prompt = $say_date_ID[1];
}
if ($AGI_output =~ /STDERR/) {$AGILOG = '1';}
if ($AGI_output =~ /FILE/) {$AGILOG = '2';}
if ($AGI_output =~ /BOTH/) {$AGILOG = '3';}
}
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($V)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
$phone_number=$callerid;
### allow for VICIDIAL transfer data string "83002*3125551212*10000123*TESTCAMP*ABC*1234*"
if ($extension =~ /^832\d\d\*|^833\d\d\*/)
{
@EXT_vars = split(/\*/, $extension);
$referring_extension = $EXT_vars[0]; # initial extension sent
$phone_number = $EXT_vars[1]; # phone number
$lead_id = $EXT_vars[2]; # lead_id in vicidial_list
$campaign_id = $EXT_vars[3]; # campaign id
$product_code = $EXT_vars[4]; # product code
$user = $EXT_vars[5]; # vicidial_user that sent the call here
}
### table structure for data ###
# CREATE TABLE vicidial_ivr (
# ivr_id INT(9) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
# entry_time DATETIME,
# length_in_sec SMALLINT(5) UNSIGNED default '0',
# inbound_number VARCHAR(12),
# recording_id INT(9) UNSIGNED,
# recording_filename VARCHAR(50),
# company_id VARCHAR(12),
# phone_number VARCHAR(12),
# lead_id INT(9) UNSIGNED,
# campaign_id VARCHAR(20),
# product_code VARCHAR(20),
# user VARCHAR(20),
# prompt_audio_1 VARCHAR(20),
# prompt_response_1 TINYINT(1) UNSIGNED default '0',
# prompt_audio_2 VARCHAR(20),
# prompt_response_2 TINYINT(1) UNSIGNED default '0',
# prompt_audio_3 VARCHAR(20),
# prompt_response_3 TINYINT(1) UNSIGNED default '0',
# prompt_audio_4 VARCHAR(20),
# prompt_response_4 TINYINT(1) UNSIGNED default '0',
# prompt_audio_5 VARCHAR(20),
# prompt_response_5 TINYINT(1) UNSIGNED default '0',
# prompt_audio_6 VARCHAR(20),
# prompt_response_6 TINYINT(1) UNSIGNED default '0',
# prompt_audio_7 VARCHAR(20),
# prompt_response_7 TINYINT(1) UNSIGNED default '0',
# prompt_audio_8 VARCHAR(20),
# prompt_response_8 TINYINT(1) UNSIGNED default '0',
# prompt_audio_9 VARCHAR(20),
# prompt_response_9 TINYINT(1) UNSIGNED default '0',
# prompt_audio_10 VARCHAR(20),
# prompt_response_10 TINYINT(1) UNSIGNED default '0',
# prompt_audio_11 VARCHAR(20),
# prompt_response_11 TINYINT(1) UNSIGNED default '0',
# prompt_audio_12 VARCHAR(20),
# prompt_response_12 TINYINT(1) UNSIGNED default '0',
# prompt_audio_13 VARCHAR(20),
# prompt_response_13 TINYINT(1) UNSIGNED default '0',
# prompt_audio_14 VARCHAR(20),
# prompt_response_14 TINYINT(1) UNSIGNED default '0',
# prompt_audio_15 VARCHAR(20),
# prompt_response_15 TINYINT(1) UNSIGNED default '0',
# prompt_audio_16 VARCHAR(20),
# prompt_response_16 TINYINT(1) UNSIGNED default '0',
# prompt_audio_17 VARCHAR(20),
# prompt_response_17 TINYINT(1) UNSIGNED default '0',
# prompt_audio_18 VARCHAR(20),
# prompt_response_18 TINYINT(1) UNSIGNED default '0',
# prompt_audio_19 VARCHAR(20),
# prompt_response_19 TINYINT(1) UNSIGNED default '0',
# prompt_audio_20 VARCHAR(20),
# prompt_response_20 TINYINT(1) UNSIGNED default '0',
# index (phone_number),
# index (entry_time)
# );
### insert record into vicidial_ivr table ###
$stmtA = "INSERT INTO vicidial_ivr (entry_time,length_in_sec,inbound_number,phone_number,lead_id,campaign_id,product_code,user) values('$now_date','0','$inbound_number','$phone_number','$lead_id','$campaign_id','$product_code','$user');";
$affected_rows = $dbhA->do($stmtA);
$cbc=0;
$stmtA = "select LAST_INSERT_ID() LIMIT 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
while ($sthArows > $cbc)
{
@aryA = $sthA->fetchrow_array;
$ivr_id = "$aryA[0]";
$cbc++;
}
$sthA->finish();
if ($AGILOG) {$agi_string = "IVR START- $ivr_id $inbound_number|$record_call|$company_ID_ask|$cust_phone_ask|$prompts|$last_prompt|$AGI_output"; &agi_output;}
$AGI->stream_file('beep');
### if set to play ID at beginning of session ###
if ($play_ID =~ /Y/)
{
$AGI->stream_file("$play_ID_prompt");
$AGI->say_digits("$ivr_id");
sleep(1);
$AGI->stream_file('beep');
$AGI->say_digits("$ivr_id");
sleep(1);
}
### if set to ask for company ID, run that subroutine ###
if ($company_ID_ask =~ /Y/)
{
&company_ID_gather_response;
$company_ID = $totalDTMF;
&get_time_now;
$length_in_sec = ($now_date_epoch - $start_epoch);
$stmtA = "UPDATE vicidial_ivr SET company_id='$company_ID', length_in_sec='$length_in_sec' where ivr_id='$ivr_id';";
if ($AGILOG) {$agi_string = "IVR- $ivr_id company: $company_ID length: $length_in_sec"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
}
### if set to ask for user ID, run that subroutine ###
if ($user_ID_ask =~ /Y/)
{
&user_ID_gather_response;
$user_ID = $totalDTMF;
&get_time_now;
$length_in_sec = ($now_date_epoch - $start_epoch);
$stmtA = "UPDATE vicidial_ivr SET user='$user_ID', length_in_sec='$length_in_sec' where ivr_id='$ivr_id';";
if ($AGILOG) {$agi_string = "IVR- $ivr_id user: $user_ID length: $length_in_sec"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
}
### if set to ask for customer phone number, run that subroutine ###
if ($cust_phone_ask =~ /Y/)
{
&cust_phone_gather_response;
$phone_number = $totalDTMF;
&get_time_now;
$length_in_sec = ($now_date_epoch - $start_epoch);
$stmtA = "UPDATE vicidial_ivr SET phone_number='$phone_number', length_in_sec='$length_in_sec' where ivr_id='$ivr_id';";
if ($AGILOG) {$agi_string = "IVR- $ivr_id phone: $phone_number length: $length_in_sec"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
}
### if set to record this session, start recording ###
if ($record_call =~ /Y/)
{
#$filename = "$inbound_number$US$phone_number$US$ivr_id";
$filename = "$ivr_id";
### code to record call goes here ###
%ast_ver_str = parse_asterisk_version($asterisk_version);
if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6))
{
$AGI->exec("Monitor wav|/var/spool/asterisk/monitor/MIX/$filename|m");
}
else
{
$AGI->exec("Monitor","wav,/var/spool/asterisk/monitor/MIX/$filename,m");
}
### insert record into recording_log table ###
$stmtA = "INSERT INTO recording_log (channel,server_ip,extension,start_time,start_epoch,length_in_sec,filename,lead_id,user,location) values('$channel','$server_ip','$inbound_number','$now_date','start_epoch','0','$filename','$lead_id','$user','$ivr_id');";
$affected_rows = $dbhA->do($stmtA);
$cbc=0;
$stmtA = "select LAST_INSERT_ID() LIMIT 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
while ($sthArows > $cbc)
{
@aryA = $sthA->fetchrow_array;
$recording_id = "$aryA[0]";
$cbc++;
}
$sthA->finish();
$stmtA = "UPDATE vicidial_ivr SET recording_id='$recording_id', recording_filename='$filename' where ivr_id='$ivr_id';";
if ($AGILOG) {$agi_string = "RECORDING- $recording_id $ivr_id START filename: $filename"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
}
### if set, say the current date ###
if ($say_date =~ /Y/)
{
if ($AGILOG) {$agi_string = "SAYING DATETIME $now_date_epoch"; &agi_output;}
if (length($say_date_prompt)>0) {$AGI->stream_file("$say_date_prompt");}
sleep(1);
$AGI->exec("SayUnixtime");
sleep(1);
}
##### Go through the propmts one at a time until done #####
@prompts_list = split(/--/, $prompts);
$prompts_count = $#prompts_list;
$i=0;
$j=1;
while($prompts_count >= $i)
{
$prompt_ary = $prompts_list[$i];
@prompts_specs = split(/-/, $prompt_ary);
$prompt = $prompts_specs[0];
$wait_sec = $prompts_specs[1];
if ($wait_sec < 1) {$wait_sec=10;}
$response = '';
$prompt_name = "prompt_audio_$j";
$response_name = "prompt_response_$j";
sleep(1);
&prompt_gather_response;
$response = $totalDTMF;
&get_time_now;
$length_in_sec = ($now_date_epoch - $start_epoch);
$stmtA = "UPDATE vicidial_ivr SET $prompt_name='$prompt', $response_name='$response', length_in_sec='$length_in_sec' where ivr_id='$ivr_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "IVR- $ivr_id $i prompt: $prompt - $wait_sec response: $response length: $length_in_sec"; &agi_output;}
$i++;
$j++;
}
##### Play the last prompt and say the IVR number #####
$AGI->stream_file("$last_prompt");
$AGI->say_digits("$ivr_id");
&get_time_now;
$length_in_sec = ($now_date_epoch - $start_epoch);
$stmtA = "UPDATE vicidial_ivr SET length_in_sec='$length_in_sec' where ivr_id='$ivr_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "IVR- $ivr_id END prompt: $last_prompt length: $length_in_sec"; &agi_output;}
if ($record_call =~ /Y/)
{
$stmtA = "UPDATE recording_log SET length_in_sec='$length_in_sec' where recording_id='$recording_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "RECORDING- $recording_id length: $length_in_sec"; &agi_output;}
}
sleep(1);
$AGI->stream_file('beep');
$AGI->say_digits("$ivr_id");
sleep(1);
$AGI->stream_file('vm-goodbye');
if ($AGILOG) {$agi_string = "IVR- ID: $ivr_id DONE Exiting"; &agi_output;}
exit;
################################################################################
##### SUBROUTINES ##############################################################
################################################################################
##### BEGIN collect the company ID #############################################
sub company_ID_gather_response
{
$digit='';
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file("$company_ID_prompt",'1234567890');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$digit_loop_counter=0;
$totalDTMF='';
if ($interrupt_digit > 1)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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 < $company_ID_length)
{
$digit = chr($AGI->wait_for_digit('100000')); # wait 100 seconds for input
if ($digit =~ /\d/)
{
$totalDTMF = "$totalDTMF$digit";
print STDERR "digit |$digit| TotalDTMF |$totalDTMF|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digit_loop_counter=$company_ID_length;
}
$digit_loop_counter++;
}
}
##### END collect the company ID ###############################################
##### BEGIN collect the user ID ################################################
sub user_ID_gather_response
{
$digit='';
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file("$user_ID_prompt",'1234567890');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$digit_loop_counter=0;
$totalDTMF='';
if ($interrupt_digit > 1)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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 < $user_ID_length)
{
$digit = chr($AGI->wait_for_digit('100000')); # wait 100 seconds for input
if ($digit =~ /\d/)
{
$totalDTMF = "$totalDTMF$digit";
print STDERR "digit |$digit| TotalDTMF |$totalDTMF|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digit_loop_counter=$user_ID_length;
}
$digit_loop_counter++;
}
}
##### END collect the user ID ##################################################
##### BEGIN collect the customer phone number ##################################
sub cust_phone_gather_response
{
$digit='';
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file("$cust_phone_prompt",'1234567890');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$digit_loop_counter=0;
$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 < $cust_phone_length)
{
$digit = chr($AGI->wait_for_digit('100000')); # wait 100 seconds for input
if ($digit =~ /\d/)
{
$totalDTMF = "$totalDTMF$digit";
print STDERR "digit |$digit| TotalDTMF |$totalDTMF|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digit_loop_counter=$cust_phone_length;
}
$digit_loop_counter++;
}
}
##### END collect the customer phone number ####################################
##### BEGIN collect the response to a prompt ###################################
sub prompt_gather_response
{
$digit='';
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file("$prompt",'123456789');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$digit_loop_counter=0;
$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 < 1)
{
$wait_ms = ($wait_sec * 1000);
$digit = chr($AGI->wait_for_digit("$wait_ms")); # wait number of milli-seconds for input
if ($digit =~ /\d/)
{
$totalDTMF = "$totalDTMF$digit";
print STDERR "digit |$digit| TotalDTMF |$totalDTMF|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digit_loop_counter=-1;
}
$digit_loop_counter++;
}
}
##### END collect the response to a prompt #####################################
sub get_time_now #get the current date and time and epoch for logging call lengths and datetimes
{
($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";
$filedate = "$year$mon$mday$hour$min$sec";
}
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 );
}
@@ -0,0 +1,184 @@
#!/usr/bin/perl
#
# agi-LCR-Route.agi version 2.2.0
#
# This script looks up the NPANXX in the lcr table and sets
# the LCRTRUNK dialplan variable to the carrier string
# with the cheapest rate. If no carrier is found for this NPANXX
# the variable is unchanged so you should set it with the default
# previously.
#
# [globals]
# LCRTRUNK=SIP/provider1 ; default LCR trunk
#
# [default]
# ;outbound VICIDIAL calls:
# exten => _91NXXNXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log)
# exten => _91NXXNXXXXXX,n,AGI(agi-LCR-Route.agi,${EXTEN:2:6})
# exten => _91NXXNXXXXXX,n,Dial(${LCRTRUNK}/${EXTEN:2},,To)
# exten => _91NXXNXXXXXX,n,Hangup
#
# Here is the SQL to create the lcr table:
#
# create table if not exists lcr (
# npanxx mediumint not null,
# rate varchar(10) not null,
# carrier_string varchar(20) not null
# );
# alter table lcr add unique index (npanxx, rate, carrier_string);
#
# A typical npanxx from this table should look like:
#
# mysql> select npanxx,rate,carrier_string from lcr where npanxx='734223';
# +--------+--------+----------------+
# | npanxx | rate | carrier_string |
# +--------+--------+----------------+
# | 734223 | 0.0064 | SIP/provider1 |
# | 734223 | 0.0076 | SIP/provider2 |
# +--------+--------+----------------+
#
# Unfortunately these rate sheets are not in a standard format.
# You will have to write a custom loading script to populate this table.
# An exampe loading script is provided in the extras directory of the
# astguiclient source code called lcr_loader_example.pl
#
#
# Copyright (C) 2009 Michael Cargile <mikec@vicidial.com> LICENSE: AGPLv2
#
# changes:
# 90717-1554 - First Build
# 91129-2209 - formatting fixes
#
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='';
}
$script = 'agi-LCR-Route.agi';
$AGILOG = '0';
($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";}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
}
$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]);
$npanxx = $ARGV_vars[0];
if ($AGILOG) {$agi_string = "Searching for NPANXX = $npanxx"; &agi_output;}
}
# get the cheapest carrier
$stmtA = "SELECT carrier_string, rate FROM lcr WHERE npanxx='$npanxx' ORDER BY rate ASC";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ( $sthArows > 0 )
{
$rec_count=0;
@aryA = $sthA->fetchrow_array;
$carrier_string = "$aryA[0]";
$sthA->finish();
if ($AGILOG) {$agi_string = "Setting LCRTRUNK to $carrier_string"; &agi_output;}
$AGI->set_variable( "LCRTRUNK",$carrier_string );
}
else
{
if ($AGILOG) {$agi_string = "No carrier found for NPANXX = $npanxx. Leaving the LCRTRUNK variable as the default."; &agi_output;}
}
@@ -0,0 +1,675 @@
#!/usr/bin/perl
#
# agi-NVA_recording.agi version 2.12
#
# This script is designed to give recording ability to agents not the using
# ViciDial agent screen
#
# ; 1. logging output (NONE|STDERR|FILE|BOTH)
# ; 2. the ViciDial user ID, if empty it defaults to accountcode(usually phone extension) or vicidial_live_agents user who launched the call
# ; 3. log this call in user_call_log (Y|N) default N
# ; 4. log this call in call_log (Y|N) default N, ONLY NEEDED FOR INBOUND AND INTERSYSTEM CALLS!!!
# ; 5. audio record this call (Y|N) default N
# ; 6. double-log this call in call_log (Y|N) default N, ONLY NEEDED FOR INBOUND CALLMENU FORWARDED CALLS!!!
# ; 7. play the recording ID of this call before recording starts
# ; 8. include the recording ID in the filename
# ; 9. search vicidial_list for phone number dialed (Y|N) default N, assumes 10 digit phone numbers
# ; 10. if 9 is Y, this is search method (ALLLISTS|PHONE) default ALLLISTS, search all lists, use phone setting, CURRENTLY DOES NOTHING
# ; 11. error out and end call if phone number is not found (Y|N) default N
# ; 12. run the phone entry's NVA Call URL (Y|N) default N
# ; 13. if 9 is Y, and phone number is not found, insert into phone's NVA List ID (Y|N) default N
# ; 14. if 13 is Y, override phone's NVA List ID with this list ID when lead is inserted
# ; 15. if 13 is Y, override phone's NVA Phone Code with this phone code when lead is inserted
# ; 16. if 13 is Y, override phone's NVA Status with this status when lead is inserted
#
#
# ;custom dialplan entry example: (similar to the defaultlog Call Menu)
#exten => _X.,1,AGI(agi-NVA_recording.agi,BOTH------Y---N---Y---N---N---N)
#exten => _X.,n,Goto(default,${EXTEN},1)
#exten => _X.,n,Hangup
#
# ;inbound to agent example:
#exten => 5678,1,AGI(agi-NVA_recording.agi,BOTH------Y---Y---Y---N---N---N)
#exten => 5678,n,Goto(vicidial-auto,5678,1)
#exten => 5678,n,Hangup
#
# ; example of dial prefix of 94 in System Settings Custom Dialplan to default log
#exten => _941NXXNXXXXXX,1,Goto(defaultlog,9${EXTEN:2},1)
#
# ; example of using as Call Menu prompt to record with playing of recording id
#agi-NVA_recording.agi,BOTH------Y---N---Y---N---Y---Y
#
# ; example of using as Call Menu prompt to record, search for phone number, run NVA call URL and error if not found
#agi-NVA_recording.agi,BOTH------Y---N---Y---N---N---N---Y---ALLLISTS---Y---Y
#
# ;custom dialplan entry example: (similar to the defaultlog Call Menu) with NVA options
#exten => _X.,1,AGI(agi-NVA_recording.agi,BOTH------Y---N---Y---N---N---N---Y---ALLLISTS---N---Y---Y)
#exten => _X.,n,Goto(default,${EXTEN},1)
#exten => _X.,n,Hangup
#
# Copyright (C) 2015 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 91105-1402 - First build
# 100123-1434 - Added double-log option for CallMenu forwarded calls
# 120430-2214 - Converted call to Monitor app to be asterisk 1.8 compatible
# 130108-1811 - Changes for Asterisk 1.8 compatibility
# 130326-1510 - Added lead_id and user logging from vicidial values
# 141124-2309 - Fixed Fhour variable bug
# 150915-1824 - Added recording ID play and filename options
# 151211-0932 - Added phone search and phone NVA URL features
# 151214-2148 - Added more variables to be used by nva url feature
# 151220-1521 - Added phone NVA List ID option for not found phone numbers
#
&get_time_now;
$script = 'agi-NVA_recording.agi';
$now_date_epoch = time();
$start_epoch = $now_date_epoch;
($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 = "$year-$mon-$mday $hour:$min:$sec";
$filedate = "$year$mon$mday$hour$min$sec";
$US='_';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ 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/nvaout.$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,ext_context,asterisk_version FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
$ext_context = $aryA[1];
$asterisk_version = $aryA[2];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
if ($ARGV[0] =~ /---/)
{
### list of command-line array arguments:
@ARGV_vars = split(/---/, $ARGV[0]);
$AGI_output = $ARGV_vars[0];
if (length($ARGV_vars[1]) > 0)
{$user = $ARGV_vars[1];}
$log_user_call = $ARGV_vars[2];
$log_call = $ARGV_vars[3];
$record_call = $ARGV_vars[4];
$double_log = $ARGV_vars[5];
$play_recid = $ARGV_vars[6];
$file_recid = $ARGV_vars[7];
$search_phone = $ARGV_vars[8];
$search_method = $ARGV_vars[9];
$search_error = $ARGV_vars[10];
$phone_url = $ARGV_vars[11];
$insert_list = $ARGV_vars[12];
$override_list = $ARGV_vars[13];
$override_code = $ARGV_vars[14];
$override_status = $ARGV_vars[15];
if ($AGI_output =~ /STDERR/) {$AGILOG = '1';}
if ($AGI_output =~ /FILE/) {$AGILOG = '2';}
if ($AGI_output =~ /BOTH/) {$AGILOG = '3';}
if ($AGILOG) {$agi_string = "Perl Environment Dump:"; &agi_output;}
if ($AGILOG) {$agi_string = "$AGI_output|$user|$log_call|$record_call|$uniqueid_log|$double_log"; &agi_output;}
}
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
$agi_string = "$1|$2"; &agi_output;
}
}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_accountcode\:\s+(.*)$/) {$accountcode = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D|\'//gi;
$calleridname =~ s/unknown|\'//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if ($calleridname =~ /^V\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d|^Y\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d|^M\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d|^D\S\d\d\d\d\d\dW\d\d\d\d\d\d\d\d\d\dW/)
{
$vla_string='';
$call_type='';
$lead_id='0';
if ($calleridname =~ /^V/)
{
$lead_id = substr($calleridname, 10, 10);
$call_type = 'auto-dial';
}
if ($calleridname =~ /^Y/)
{
$lead_id = substr($calleridname, 10, 10);
$call_type = 'inbound';
}
if ($calleridname =~ /^M/)
{
$lead_id = substr($calleridname, 10, 10);
$call_type = 'manual-dial';
}
if ($calleridname =~ /^D/)
{
$lead_id = substr($calleridname, 9, 10);
$call_type = '3-way';
}
if (length($call_type) > 0)
{
$lead_id = ($lead_id + 0);
$stmtA = "SELECT user,campaign_id FROM vicidial_live_agents where lead_id='$lead_id' order by last_update_time desc 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;
$VLAuser = $aryA[0];
$VLAcampaign = $aryA[1];
if (length($user) < 1)
{$user = $VLAuser;}
$vla_string = "Live agent record found: |$VLAuser|$user|$VLAcampaign|";
}
if ($AGILOG) {$agi_string = "Vicidial $call_type call: |$calleridname|$lead_id| $vla_string"; &agi_output;}
}
else
{
if ($AGILOG) {$agi_string = "Not a Vicidial call: $calleridname"; &agi_output;}
}
}
else
{
if ($AGILOG) {$agi_string = "Not a Vicidial call: $calleridname"; &agi_output;}
}
if (length($user) > 0)
{$accountcode = $user;}
if ( ($search_phone =~ /Y/) || ($phone_url =~ /Y/) )
{
### Grab phone NVA values from the database phones table
$stmtA = "SELECT nva_call_url,nva_search_method,nva_error_filename,nva_new_list_id,nva_new_phone_code,nva_new_status FROM phones where extension='$accountcode' and 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)
{
@aryA = $sthA->fetchrow_array;
$nva_call_url = $aryA[0];
$nva_search_method = $aryA[1];
$nva_error_filename = $aryA[2];
$nva_new_list_id = $aryA[3];
$nva_new_phone_code = $aryA[4];
$nva_new_status = $aryA[5];
}
$sthA->finish();
}
$temp_phone = $extension;
$search_lead_id = 'NOTFOUND';
if ($search_phone =~ /Y/)
{
while (length($temp_phone) > 10)
{$temp_phone =~ s/^.//gi;}
$stmtA = "SELECT lead_id FROM vicidial_list where phone_number='$temp_phone' order by entry_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 ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$search_lead_id = $aryA[0];
if ($AGILOG) {$agi_string = "NVA Search, lead found: $search_lead_id|$temp_phone($extension)"; &agi_output;}
}
else
{
if ($AGILOG) {$agi_string = "NVA Search, lead not found: $temp_phone($extension)"; &agi_output;}
if ($search_error =~ /Y/)
{
if ($AGILOG) {$agi_string = "NVA playing error file then exiting..."; &agi_output;}
$temp_error_filename = 'invalid';
if (length($nva_error_filename) > 0 )
{$temp_error_filename = $nva_error_filename;}
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('silence');
$AGI->stream_file("$temp_error_filename");
sleep(3);
$AGI->hangup();
exit;
}
else
{
if ($insert_list =~ /Y/)
{
if (length($override_list) > 1) {$nva_new_list_id = $override_list;}
if (length($override_code) > 0) {$nva_new_phone_code = $override_code;}
if (length($override_status) > 0) {$nva_new_status = $override_status;}
### insert a record into the vicidial_list table if phone number not found
$stmtA = "INSERT INTO vicidial_list (entry_date,status,user,vendor_lead_code,source_id,list_id,called_since_last_reset,phone_code,phone_number,security_phrase,called_count,gmt_offset_now,comments) values('$now_date','$nva_new_status','$accountcode','','PHONE','$nva_new_list_id','Y','$nva_new_phone_code','$temp_phone','$accountcode','1','0','NVA PHONE INSERT');";
$affected_rows = $dbhA->do($stmtA);
$stmtB = "SELECT LAST_INSERT_ID() LIMIT 1;";
$sthA = $dbhA->prepare($stmtB) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$search_lead_id = $aryA[0];
}
$sthA->finish();
if ($AGILOG) {$agi_string = "NVA Inserted New Lead: |$affected_rows|$search_lead_id|$nva_new_list_id|$nva_new_phone_code|$nva_new_status|"; &agi_output;}
}
}
}
$sthA->finish();
}
if ( ( (length($lead_id)<1) || ($lead_id < 1) ) && ($search_lead_id !~ /NOTFOUND/) )
{$lead_id = $search_lead_id;}
### if set to record this call, start recording ###
if ($record_call =~ /Y/)
{
$filename = "$filedate$US$accountcode$US$extension";
$filename =~ s/\"|\'//gi;
### code to record call goes here ###
### insert record into recording_log table ###
$stmtA = "INSERT INTO recording_log (channel,server_ip,extension,start_time,start_epoch,length_in_sec,filename,lead_id,user,location,vicidial_id) values('$channel','$VARserver_ip','$extension','$now_date','$start_epoch','0','$filename','$lead_id','$accountcode','$filename','$unique_id');";
$affected_rows = $dbhA->do($stmtA);
$stmtB = "SELECT LAST_INSERT_ID() LIMIT 1;";
$sthA = $dbhA->prepare($stmtB) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtB ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$recording_id = $aryA[0];
}
if ($file_recid =~ /Y/)
{
$filename .= "$US$recording_id";
$stmtA = "UPDATE recording_log SET filename='$filename',location='$filename' where recording_id='$recording_id';";
$affected_rows = $dbhA->do($stmtA);
}
if ($play_recid =~ /Y/)
{
$AGI->stream_file('id_number');
$AGI->say_digits("$recording_id");
}
%ast_ver_str = parse_asterisk_version($asterisk_version);
if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6))
{
$AGI->exec("Monitor wav|/var/spool/asterisk/monitor/MIX/$filename");
}
else
{
$AGI->exec("Monitor","wav,/var/spool/asterisk/monitor/MIX/$filename");
}
}
if ( ($phone_url =~ /Y/) && (length($nva_call_url) > 8) )
{
### first, find curl binary
$curlbin = '';
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: cannot do nva URL, curl binary not found"; &agi_output;}
}
}
}
if ( (length($curlbin) > 4) && ($nva_call_url =~ /http/i) )
{
if ( (length($lead_id)> 0) && ($lead_id !~ /NOTFOUND/) )
{
$stmtA = "SELECT lead_id,entry_date,modify_date,status,user,vendor_lead_code,source_id,list_id,phone_number,title,first_name,middle_initial,last_name,address1,address2,address3,city,state,province,postal_code,country_code,gender,date_of_birth,alt_phone,email,security_phrase,comments,called_count,last_local_call_time,rank,owner FROM vicidial_list where lead_id='$lead_id';";
$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;
$entry_date = $aryA[1];
$modify_date = $aryA[2];
$status = $aryA[3];
$user = $aryA[4];
$vendor_lead_code = $aryA[5];
$source_id = $aryA[6];
$list_id = $aryA[7];
$phone_number = $aryA[8];
$title = $aryA[9];
$first_name = $aryA[10];
$middle_initial = $aryA[11];
$last_name = $aryA[12];
$address1 = $aryA[13];
$address2 = $aryA[14];
$address3 = $aryA[15];
$city = $aryA[16];
$state = $aryA[17];
$province = $aryA[18];
$postal_code = $aryA[19];
$country_code = $aryA[20];
$gender = $aryA[21];
$date_of_birth = $aryA[22];
$alt_phone = $aryA[23];
$email = $aryA[24];
$security_phrase = $aryA[25];
$comments = $aryA[26];
$called_count = $aryA[27];
$last_local_call_time = $aryA[28];
$rank = $aryA[29];
$owner = $aryA[30];
}
$sthA->finish();
$stmtA = "SELECT list_description,campaign_id FROM vicidial_lists where list_id='$list_id';";
$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;
$list_description = $aryA[0];
$campaign_id = $aryA[1];
}
$sthA->finish();
}
$nva_call_url =~ s/^VAR|^ //gi;
$nva_call_url =~ s/--A--phone_number--B--/$temp_phone/gi;
$nva_call_url =~ s/--A--uniqueid--B--/$unique_id/gi;
$nva_call_url =~ s/--A--lead_id--B--/$search_lead_id/gi;
$nva_call_url =~ s/--A--extension--B--/$accountcode/gi;
$nva_call_url =~ s/--A--channel--B--/$channel/gi;
$nva_call_url =~ s/--A--server_ip--B--/$VARserver_ip/gi;
$nva_call_url =~ s/--A--lead_id--B--/$lead_id/gi;
$nva_call_url =~ s/--A--entry_date--B--/$entry_date/gi;
$nva_call_url =~ s/--A--modify_date--B--/$modify_date/gi;
$nva_call_url =~ s/--A--status--B--/$status/gi;
$nva_call_url =~ s/--A--user--B--/$user/gi;
$nva_call_url =~ s/--A--vendor_lead_code--B--/$vendor_lead_code/gi;
$nva_call_url =~ s/--A--source_id--B--/$source_id/gi;
$nva_call_url =~ s/--A--list_id--B--/$list_id/gi;
$nva_call_url =~ s/--A--phone_number--B--/$phone_number/gi;
$nva_call_url =~ s/--A--title--B--/$title/gi;
$nva_call_url =~ s/--A--first_name--B--/$first_name/gi;
$nva_call_url =~ s/--A--middle_initial--B--/$middle_initial/gi;
$nva_call_url =~ s/--A--last_name--B--/$last_name/gi;
$nva_call_url =~ s/--A--address1--B--/$address1/gi;
$nva_call_url =~ s/--A--address2--B--/$address2/gi;
$nva_call_url =~ s/--A--address3--B--/$address3/gi;
$nva_call_url =~ s/--A--city--B--/$city/gi;
$nva_call_url =~ s/--A--state--B--/$state/gi;
$nva_call_url =~ s/--A--province--B--/$province/gi;
$nva_call_url =~ s/--A--postal_code--B--/$postal_code/gi;
$nva_call_url =~ s/--A--country_code--B--/$country_code/gi;
$nva_call_url =~ s/--A--gender--B--/$gender/gi;
$nva_call_url =~ s/--A--date_of_birth--B--/$date_of_birth/gi;
$nva_call_url =~ s/--A--alt_phone--B--/$alt_phone/gi;
$nva_call_url =~ s/--A--email--B--/$email/gi;
$nva_call_url =~ s/--A--security_phrase--B--/$security_phrase/gi;
$nva_call_url =~ s/--A--comments--B--/$comments/gi;
$nva_call_url =~ s/--A--called_count--B--/$called_count/gi;
$nva_call_url =~ s/--A--last_local_call_time--B--/$last_local_call_time/gi;
$nva_call_url =~ s/--A--rank--B--/$rank/gi;
$nva_call_url =~ s/--A--owner--B--/$owner/gi;
$nva_call_url =~ s/--A--campaign_id--B--/$campaign_id/gi;
$nva_call_url =~ s/--A--list_description--B--/$list_description/gi;
$nva_call_url =~ s/--A--recording_id--B--/$recording_id/gi;
$nva_call_url =~ s/--A--recording_filename--B--/$filename/gi;
$nva_call_url =~ s/&/\\&/gi;
$nva_call_url =~ s/ /+/gi;
### insert a new url log entry
$SQL_log = "$nva_call_url";
$SQL_log =~ s/;|\||\\//gi;
$stmtA = "INSERT INTO vicidial_url_log SET uniqueid='$unique_id',url_date=NOW(),url_type='nva_phone',url='$SQL_log',url_response='';";
$affected_rows = $dbhA->do($stmtA);
$stmtB = "SELECT LAST_INSERT_ID() LIMIT 1;";
$sthA = $dbhA->prepare($stmtB) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$url_id = $aryA[0];
}
$sthA->finish();
my $secW = time();
@curl_output = `$curlbin $nva_call_url`;
my $secY = time();
my $response_sec = ($secY - $secW);
$k=0;
$full_output='';
foreach (@curl_output)
{
$full_output_raw .= $curl_output[$k];
$k++;
}
$full_output = $full_output_raw;
$full_output =~ s/\D//gi;
### update url log entry
$full_output_raw =~ s/;|\||\\//gi;
$stmtA = "UPDATE vicidial_url_log SET url_response='$full_output_raw|$full_output',response_sec='$response_sec' where url_log_id='$url_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "phone NVA URL response: |$search_lead_id|$full_output|$nva_call_url|$affected_rows|"; &agi_output;}
}
}
### if set to user log this call, insert user_call_log entry ###
if ($log_user_call =~ /Y/)
{
### insert record into user_call_log table ###
$stmtA = "INSERT INTO user_call_log SET user='$accountcode', call_date='$now_date', call_type='PHONE_DIAL', server_ip='$VARserver_ip', phone_number='$extension', number_dialed='$extension', callerid='$callerid', group_alias_id='$unique_id', lead_id='$lead_id';";
$affected_rows = $dbhA->do($stmtA);
}
### if set to log this call, insert call_log entry ###
if ($log_call =~ /Y/)
{
### insert record into call_log table ###
$stmtA = "INSERT INTO call_log SET uniqueid='$unique_id', channel='$channel', channel_group='PHONE_DIAL', server_ip='$VARserver_ip', type='$type', extension='$accountcode', number_dialed='$extension', caller_code='$callerid', start_time='$now_date', start_epoch='$start_epoch';";
$affected_rows = $dbhA->do($stmtA);
}
### if set to double-log this call, insert call_log entry with uniqueid appended with a 99 ###
if ($double_log =~ /Y/)
{
### insert record into call_log table ###
$stmtA = "INSERT INTO call_log SET uniqueid='" . $unique_id . "99', channel='$channel', channel_group='DOUBLE_LOG', server_ip='$VARserver_ip', type='$type', extension='$accountcode', number_dialed='$extension', caller_code='$callerid', start_time='$now_date', start_epoch='$start_epoch';";
$affected_rows = $dbhA->do($stmtA);
}
exit;
sub get_time_now #get the current date and time and epoch for logging call lengths and datetimes
{
($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";
$filedate = "$year$mon$mday$hour$min$sec";
}
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 );
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,735 @@
#!/usr/bin/perl
#
# agi-VDAD_RINGALL.agi version 2.8
#
# NOTE: this script is used for on-hook agents to be connected to customer calls
# when they answer their ringing phones
#
# In the default dialplan context, this is set to the following:
# ; these are used for the ring_all function in VICIDIAL
# exten => _8331*.,1,Playback(sip-silence)
# exten => _8331*.,n,AGI(agi-VDAD_RINGALL.agi,${EXTEN})
# exten => _8331*.,n,AGI(agi-VDAD_RINGALL.agi,${EXTEN})
# exten => _8331*.,n,Hangup
#
# Copyright (C) 2014 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 110303-2325 - First build
# 110324-2328 - Added recording of remote agent calls, per in-group and campaign recording settings
# 110325-1411 - Added user recording override settings checking for remote agent recording
# 121114-1935 - Added INGROUP recording option
# 130108-1808 - Changes for Asterisk 1.8 compatibility
# 140312-2112 - Added CALLID as recording filename variable
# 140421-1448 - Added code to halt ringing of other channels in ring_all NAC method
#
$script = 'agi-VDAD_RINGALL.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$now_num = "$year$mon$mday$hour$min$sec";
$CIDdate = "$mon$mday$hour$min$sec";
$S='*';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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,ext_context,asterisk_version 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];
$ext_context = $aryA[1];
$asterisk_version = $aryA[2];
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 ###
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $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;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
if ( $calleridname =~ /\"/) {$calleridname =~ s/\"//gi;}
if ( (!$callerid) or ($callerid =~ /unknown/) or ( ($calleridname =~ /\d\d\d\d\d\d\d\d\d/) && (length($calleridname) > 16) ) )
{$callerid = $calleridname;}
if ( ($callerid =~ / /) && (length($callerid) > 20) )
{$callerid =~ s/ .*//gi;}
$calleridname = $callerid;
if ($extension =~ /^8331\*\d/)
{
@EXTEN_vars = split(/\*/, $extension);
$auto_call_id = $EXTEN_vars[1];
$call_callerid = $EXTEN_vars[2];
$dial_user = $EXTEN_vars[3];
$phone_exten = $EXTEN_vars[4];
$channel_root = $channel;
$channel_root =~ s/\,.*//gi;
}
}
if ($AGILOG) {$agi_string = "AGI Environment Dump:"; &agi_output;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|$auto_call_id|"; &agi_output;}
if ($AGILOG) {$agi_string = "RING-AGENT AGI STARTED"; &agi_output;}
### Hangup if Local/ channel, since these are usually invalid or voicemail
if ($channel =~ /^Local/)
{
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
if ($AGILOG) {$agi_string = "RING-ALL AGI Local Channel, exiting..."; &agi_output;}
exit;
}
### Check that the call exists, if not then buzz and hangup ###
$stmtA = "SELECT campaign_id,call_type,extension,phone_number,lead_id,callerid FROM vicidial_auto_calls where auto_call_id='$auto_call_id';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VACcount=$sthA->rows;
if ($VACcount > 0)
{
@aryA = $sthA->fetchrow_array;
$VAC_campaign_id = $aryA[0];
$VAC_call_type = $aryA[1];
$VAC_extension = $aryA[2];
$VAC_phone_number = $aryA[3];
$VAC_lead_id = $aryA[4];
$VAC_call_id = $aryA[5];
if ($AGILOG) {$agi_string = "-- VAC Call Found: |$callerid|$VAC_campaign_id|$VAC_call_type|$VAC_extension|$VAC_phone_number|$VAC_lead_id|$auto_call_id|"; &agi_output;}
$sthA->finish();
}
else
{
if ($AGILOG) {$agi_string = "-- VAC Call Not Found, exiting: |$callerid|$auto_call_id|"; &agi_output;}
$AGI->stream_file('buzz');
$AGI->hangup();
exit;
}
### Check that the user exists in vicidial_live_agents, if not then buzz and hangup ###
$stmtA = "SELECT conf_exten,extension,server_ip,ra_user,campaign_id from vicidial_live_agents WHERE user='$dial_user' and status IN('READY','CLOSER');";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VLAcount=$sthA->rows;
if ($VLAcount > 0)
{
@aryA = $sthA->fetchrow_array;
$VLAconf_exten = $aryA[0];
$VLAextension = $aryA[1];
$VLAserver_ip = $aryA[2];
$VLAra_user = $aryA[3];
$VLAcampaign_id = $aryA[4];
if ($AGILOG) {$agi_string = "-- VLA Agent Found: |$callerid|$VLAconf_exten|$VLAextension|$VLAserver_ip|$VLAra_user|$VLAcampaign_id|$auto_call_id|"; &agi_output;}
$sthA->finish();
}
else
{
if ($AGILOG) {$agi_string = "-- VLA Agent Not Found, exiting: |$callerid|$auto_call_id|$dial_user|"; &agi_output;}
$AGI->stream_file('buzz');
$AGI->hangup();
exit;
}
$stmtA = "SELECT user,extension,conf_exten,server_ip FROM vicidial_live_agents where ring_callerid='$call_callerid';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$orAGENTct=0;
$RINGct=0;
$user_phone='';
while ($sthArows > $RINGct)
{
@aryA = $sthA->fetchrow_array;
$ringVLA_user[$RINGct] = $aryA[0];
$ringVLA_exten[$RINGct] = $aryA[1];
$ringVLA_conf_exten[$RINGct] = $aryA[2];
$ringVLA_server_ip[$RINGct] = $aryA[3];
$ring_user = $aryA[0];
if ($AGILOG) {$agi_string = "-- Ringing agents for this call: |$call_callerid|$RINGct|$ringVLA_user[$RINGct]|$ringVLA_exten[$RINGct]|$ringVLA_conf_exten[$RINGct]|$ringVLA_server_ip[$RINGct]|"; &agi_output;}
if ($dial_user =~ /^$ring_user$/)
{$user_phone=$ringVLA_exten[$RINGct];}
else
{
$orVLA_user[$orAGENTct] = $aryA[0];
$orVLA_exten[$orAGENTct] = $aryA[1];
$orVLA_conf_exten[$orAGENTct] = $aryA[2];
$orVLA_server_ip[$orAGENTct] = $aryA[3];
if ($orVLA_exten[$orAGENTct] =~ /^R\//)
{$orVLA_exten[$orAGENTct] = "Local/" . $orVLA_conf_exten[$orAGENTct] . "\@default";}
$orAGENTct++;
}
$RINGct++;
}
$sthA->finish();
if ($AGILOG) {$agi_string = "-- Ringing stats: |$call_callerid|$RINGct|$orAGENTct|$user_phone|"; &agi_output;}
### Check that the call has not been grabbed already, if it has then buzz and hangup ###
$stmtA = "SELECT count(*) FROM vicidial_auto_calls where auto_call_id='$auto_call_id' and agent_grab='';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$NAGcount=$sthA->rows;
if ($NAGcount > 0)
{
@aryA = $sthA->fetchrow_array;
$not_grabbed_count = $aryA[0];
$sthA->finish();
if ($not_grabbed_count > 0)
{
if ($VLAextension =~ /^R\//)
{
### BEGIN If remote agent, then reserve a vicidial_conferences session on their server to send the calls to ###
$stmtA="SELECT count(*) FROM vicidial_conferences where server_ip='$VLAserver_ip' and ((extension='') or (extension is null)) and conf_exten != '$VLAconf_exten';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$AVCcount=$sthA->rows;
if ($AVCcount > 0)
{
@aryA = $sthA->fetchrow_array;
$available_sessions = $aryA[0];
$sthA->finish();
if ($available_sessions > 0)
{
$stmtA="UPDATE vicidial_conferences set extension='3WAY_$dial_user', leave_3way='1', leave_3way_datetime='$now_date' where server_ip='$VLAserver_ip' and ((extension='') or (extension is null)) and conf_exten != '$VLAconf_exten' limit 1;";
$AVCaffected_rows = $dbhA->do($stmtA);
if ($AVCaffected_rows > 0)
{
$stmtA="SELECT conf_exten from vicidial_conferences where server_ip='$VLAserver_ip' and extension='3WAY_$dial_user' and leave_3way_datetime='$now_date' and conf_exten != '$VLAconf_exten';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$SVCcount=$sthA->rows;
if ($SVCcount > 0)
{
@aryA = $sthA->fetchrow_array;
$VLAconf_exten = $aryA[0];
$sthA->finish();
if ($AGILOG) {$agi_string = "-- AVC Session Reserved: |$callerid|$auto_call_id|$dial_user|3WAY_$dial_user|$now_date|$VLAconf_exten|"; &agi_output;}
### get the recording settings for the campaign that this remote agent is logged into
if (length($VLAcampaign_id) > 0)
{
$stmtA = "SELECT campaign_recording,campaign_rec_filename FROM vicidial_campaigns where campaign_id='$VLAcampaign_id';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VCRcount=$sthA->rows;
if ($VCRcount > 0)
{
@aryA = $sthA->fetchrow_array;
$campaign_recording = $aryA[0];
$campaign_rec_filename = $aryA[1];
}
$sthA->finish();
}
### look for the recording settings for the start user of this remote agent
if (length($VLAra_user) > 0)
{
$stmtA = "SELECT vicidial_recording_override,vicidial_recording FROM vicidial_users where user='$VLAra_user';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsVUrec=$sthA->rows;
if ($sthArowsVUrec > 0)
{
@aryA = $sthA->fetchrow_array;
if ($aryA[0] !~ /DISABLED/)
{$campaign_recording = $aryA[0];}
if ($aryA[1] < 1)
{$campaign_recording = 'NONE';}
}
$sthA->finish();
}
### if recording is enabled then start recording on this call before sending to a remote agent
if ($campaign_recording =~ /ALLCALLS|ALLFORCE/)
{
$stmtA = "SELECT vendor_lead_code FROM vicidial_list where lead_id='$VAC_lead_id';";
$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;
$vendor_lead_code = $aryA[0];
}
$sthA->finish();
# get date/time
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$Tyear = ($year - 2000);
$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";
$recdate = "$year$mon$mday-$hour$min$sec";
$tinydate = "$Tyear$mon$mday$hour$min$sec";
$campaign_rec_filename =~ s/CAMPAIGN/$VLAcampaign_id/gi;
$campaign_rec_filename =~ s/INGROUP/$VAC_campaign_id/gi;
$campaign_rec_filename =~ s/CUSTPHONE/$VAC_phone_number/gi;
$campaign_rec_filename =~ s/FULLDATE/$recdate/gi;
$campaign_rec_filename =~ s/TINYDATE/$tinydate/gi;
$campaign_rec_filename =~ s/EPOCH/$now_date_epoch/gi;
$campaign_rec_filename =~ s/AGENT/$dial_user/gi;
$campaign_rec_filename =~ s/VENDORLEADCODE/$vendor_lead_code/gi;
$campaign_rec_filename =~ s/LEADID/$VAC_lead_id/gi;
$campaign_rec_filename =~ s/CALLID/$VAC_call_id/gi;
$campaign_rec_filename =~ s/\"|\'//gi;
%ast_ver_str = parse_asterisk_version($asterisk_version);
if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6))
{
$AGI->exec("Monitor wav|/var/spool/asterisk/monitor/MIX/$campaign_rec_filename");
}
else
{
$AGI->exec("Monitor","wav,/var/spool/asterisk/monitor/MIX/$campaign_rec_filename");
}
### insert record into recording_log table ###
$stmtA = "INSERT INTO recording_log (channel,server_ip,extension,start_time,start_epoch,length_in_sec,filename,lead_id,user,location,vicidial_id) values('$channel','$VARserver_ip','$VAC_phone_number','$now_date','$now_date_epoch','0','$campaign_rec_filename','$VAC_lead_id','$dial_user','$campaign_rec_filename','$uniqueid');";
$RLRAaffected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- REMOTE RECORDING STARTED : |$RLRAaffected_rows|$campaign_rec_filename|$stmtA|"; &agi_output;}
}
}
else
{
if ($AGILOG) {$agi_string = "-- AVC No Available Sessions(SELECT3), exiting: |$VLAserver_ip|$auto_call_id|$dial_user|$VLAextension$now_num|"; &agi_output;}
$AGI->stream_file('buzz');
$AGI->hangup();
exit;
}
}
else
{
if ($AGILOG) {$agi_string = "-- AVC No Available Sessions(UPDATE), exiting: |$VLAserver_ip|$auto_call_id|$dial_user|"; &agi_output;}
$AGI->stream_file('buzz');
$AGI->hangup();
exit;
}
}
else
{
if ($AGILOG) {$agi_string = "-- AVC No Available Sessions(SELECT2), exiting: |$VLAserver_ip|$auto_call_id|$dial_user|"; &agi_output;}
$AGI->stream_file('buzz');
$AGI->hangup();
exit;
}
}
else
{
if ($AGILOG) {$agi_string = "-- AVC No Available Sessions(SELECT), exiting: |$VLAserver_ip|$auto_call_id|$dial_user|"; &agi_output;}
$AGI->stream_file('buzz');
$AGI->hangup();
exit;
}
### END If remote agent, then reserve a vicidial_conferences session on their server to send the calls to ###
}
### Try to grab the call for this agent, if already grabbed then buzz and hangup ###
$stmtA = "UPDATE vicidial_auto_calls SET agent_grab='$dial_user',agent_grab_extension='$VLAconf_exten' where auto_call_id='$auto_call_id' and agent_grab='';";
$AGaffected_rows = $dbhA->do($stmtA);
if ($AGaffected_rows > 0)
{
if ($AGILOG) {$agi_string = "-- VAC Call Grabbed: |$callerid|$auto_call_id|$dial_user|$AGaffected_rows|"; &agi_output;}
### Check if this was a RING_ALL method ###
$VIG_next_agent_call='';
$stmtA = "SELECT next_agent_call FROM vicidial_inbound_groups where group_id='$VAC_campaign_id';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VIGcount=$sthA->rows;
if ($VIGcount > 0)
{
@aryA = $sthA->fetchrow_array;
$VIG_next_agent_call = $aryA[0];
if ($AGILOG) {$agi_string = "-- Check for in-group next agent call setting: |$callerid|$VAC_campaign_id|$VIG_next_agent_call|"; &agi_output;}
$sthA->finish();
}
if ( ($VIG_next_agent_call =~ /ring_all/i) && ($orAGENTct > 0) )
{
### gather list of ringing channels
$stmtA = "SELECT channel,server_ip FROM live_sip_channels where extension='ring';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$LSC_channel[$rec_count] = $aryA[0];
$LSC_server_ip[$rec_count] = $aryA[1];
$LSC_channelREG[$rec_count] = $aryA[0];
$LSC_channelREG[$rec_count] =~ s/\*/STARSYM/gi;
$LSC_channelREG[$rec_count] =~ s/\@/ATSYM/gi;
if ($AGILOG) {$agi_string = "-- Other ringing channels: |$rec_count|$LSC_channel[$rec_count]|$LSC_server_ip[$rec_count]|"; &agi_output;}
$rec_count++;
}
$sthA->finish();
### go through other-agent ringing agent records looking for matches to hang up
if ($rec_count > 0)
{
$orct=0;
foreach(@orVLA_exten)
{
$exten_match='';
if ($orVLA_exten[$orct] =~ /^Local\//)
{
$orVLA_exten[$orct] =~ s/^Local\/|\@.*//gi;
$exten_match = "STARSYM" . $orVLA_exten[$orct] . "ATSYM";
}
if ($orVLA_exten[$orct] =~ /^SIP/i)
{
$orVLA_exten[$orct] =~ s/^SIP\///gi;
$stmtA = "SELECT dialplan_number FROM phones where extension='$orVLA_exten[$orct]' and server_ip='$orVLA_server_ip[$orct]' and protocol='SIP';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$Pcount=$sthA->rows;
if ($Pcount > 0)
{
@aryA = $sthA->fetchrow_array;
$Pdialplan_number = $aryA[0];
$exten_match = "STARSYM" . $Pdialplan_number . "ATSYM";
}
$sthA->finish();
}
if ($orVLA_exten[$orct] =~ /^IAX/i)
{
$orVLA_exten[$orct] =~ s/^IAX2\/|^IAX\///gi;
$stmtA = "SELECT dialplan_number FROM phones where extension='$orVLA_exten[$orct]' and server_ip='$orVLA_server_ip[$orct]' and protocol='IAX2';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$Pcount=$sthA->rows;
if ($Pcount > 0)
{
@aryA = $sthA->fetchrow_array;
$Pdialplan_number = $aryA[0];
$exten_match = "STARSYM" . $Pdialplan_number . "ATSYM";
}
$sthA->finish();
}
if ($orVLA_exten[$orct] =~ /^Zap|^DAHDI/i)
{
$orVLA_exten[$orct] =~ s/^Zap\/|^DAHDI\///gi;
$stmtA = "SELECT dialplan_number FROM phones where extension='$orVLA_exten[$orct]' and server_ip='$orVLA_server_ip[$orct]' and protocol='Zap';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$Pcount=$sthA->rows;
if ($Pcount > 0)
{
@aryA = $sthA->fetchrow_array;
$Pdialplan_number = $aryA[0];
$exten_match = "STARSYM" . $Pdialplan_number . "ATSYM";
}
$sthA->finish();
}
# if ($AGILOG) {$agi_string = "-- Check ORC: |$callerid|$orct|$exten_match|$orVLA_exten[$orct]|$orVLA_exten[$orct]|"; &agi_output;}
if (length($exten_match) > 2)
{
$lscct=0;
foreach(@LSC_channel)
{
# if ($AGILOG) {$agi_string = "-- Check LSC: |$callerid|$orct|$lscct|$exten_match|$LSC_channel[$lscct]|$LSC_channelREG[$lscct]|$orVLA_exten[$orct]|$orVLA_exten[$orct]|"; &agi_output;}
if ($LSC_channelREG[$lscct] =~ /$exten_match/)
{
if ($AGILOG) {$agi_string = "-- Chan to hangup: |$callerid|$exten_match|$LSC_channel[$lscct]|$LSC_server_ip[$lscct]|"; &agi_output;}
### send hangup command for channel
$VHqueryCID = "RGHANGUP$CIDdate$lscct";
$stmtA = "INSERT INTO vicidial_manager values('','','$now_date','NEW','N','$VARserver_ip','','Hangup','$VHqueryCID','Channel: $LSC_channel[$lscct]','','','','','','','','','')";
$AGaffected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- Other Ringing Hangup Sent: |$callerid|$AGaffected_rows|$LSC_channel[$lscct]|$VHqueryCID|"; &agi_output;}
}
$lscct++;
}
}
$orct++;
}
}
}
### send agent to their session ###
if($VLAserver_ip =~ m/(\S+)\.(\S+)\.(\S+)\.(\S+)/ )
{
$a = leading_zero($1);
$b = leading_zero($2);
$c = leading_zero($3);
$d = leading_zero($4);
$VLA_DIALstr = "$a$S$b$S$c$S$d$S";
}
$VLA_DIALstr .= "7$VLAconf_exten";
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
if ($AGILOG) {$agi_string = "-- Ring-Agent Sending Call: |$callerid|$auto_call_id|$dial_user|$VLA_DIALstr|"; &agi_output;}
print "SET CONTEXT $ext_context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $VLA_DIALstr\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
$dbhA->disconnect();
exit;
}
else
{
if ($AGILOG) {$agi_string = "-- VAC Call Already Grabbed(UPDATE2), exiting: |$callerid|$auto_call_id|$dial_user|$AGaffected_rows|"; &agi_output;}
$AGI->stream_file('buzz');
$AGI->hangup();
exit;
}
}
else
{
if ($AGILOG) {$agi_string = "-- VAC Call Already Grabbed(UPDATE), exiting: |$callerid|$auto_call_id|$dial_user|$AGaffected_rows|"; &agi_output;}
$AGI->stream_file('buzz');
$AGI->hangup();
exit;
}
}
else
{
if ($AGILOG) {$agi_string = "-- VAC Call Already Grabbed(SELECT), exiting: |$callerid|$auto_call_id|$dial_user|$AGaffected_rows|"; &agi_output;}
$AGI->stream_file('buzz');
$AGI->hangup();
exit;
}
if ($AGILOG) {$agi_string = "-- sleeping: |$callerid|$auto_call_id|"; &agi_output;}
sleep(10);
exit;
$dbhA->disconnect();
$AGI->stream_file('sip-silence');
if ($AGILOG) {$agi_string = "-- Exiting Ring-Agent AGI: |$callerid|"; &agi_output;}
exit;
sub agi_output
{
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$now_date|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$now_date|$script|$agi_string\n";}
$agi_string='';
}
sub checkresult
{
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/)
{
$res =~ /result=(-?\d+)/;
if (!length($1))
{
# print STDERR "FAIL ($res)\n";
$fail++;
}
else
{
# print STDERR "PASS ($1)\n";
$pass++;
}
}
else
{
# print STDERR "FAIL (unexpected result '$res')\n";
$fail++;
}
}
sub leading_zero($)
{
$_ = $_[0];
s/^(\d)$/0$1/;
s/^(\d\d)$/0$1/;
return $_;
} # End of the leading_zero() routine.
# 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 );
}
@@ -0,0 +1,814 @@
#!/usr/bin/perl
#
# agi-VDAD_inbound_calltime_check.agi version 2.12
#
# Runs when a call comes in from an inbound call. This script will check the
# settings of the defined calltime scheme in VICIDIAL and either send the call
# to the after-hours method for the defined IN-GROUP or exit to let the call
# continue. This script is also used by Call Menus.
#
# You need to put lines similar to those below in your extensions.conf file:
# ; Below are the parameters needed for the script to be run properly
# ; 1. the in-group to take settings from
# ; 2. whether to log the call into the vicidial_auto_calls table:
# ; - YES - insert the call as status IVR
# ; - NO - do not insert call into vac table
# ; 3. note to put in the comment_b field when record inserted into the
# ; live_inbound_log table, no spaces in this field, use underscore '_'
# ; default if not populated is NONE
# ; 4. call time scheme override
# ; 5. call route after hours override
# ; 6. call route value after hours override
# ; 7. call route context after hours override
# ; 8. vicidial_list query qualification (YES/NO, default is NO)
# ; * only works with lead_id-populated calleridname phone calls.
# ; This option allows you to specify a SQL fragment used to do a count(*)
# ; against the vicidial_list table for the lead and other field values
# ; This feature will look for the qualify_sql in the cacll menu record
# ;
# ;inbound calls check calltime:
#exten => 1234,1,Answer ; Answer the line
#exten => 1234,2,AGI(agi-VDAD_inbound_calltime_check.agi,INBOUND-----YES-----START-----24hours-----EXTENSION-----101-----default-----NO)
#exten => 1234,3,Hangup
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 80525-0144 - First Build
# 81015-0305 - Added drop logging
# 81015-2009 - Added more logging and NOTE option
# 81017-0238 - Fixed duplication bug for vac in multi-entry dialplans
# 90504-1555 - Added call time scheme override
# 90621-1130 - Fixed issue when no call time is specified
# 91122-2353 - Added QueueMetrics logging as IVR INFO entries
# 101219-2110 - Added call time overflow
# 110525-1347 - Added compatibility for outbound IVR logging
# 111229-1716 - Changed call time overflow to look at previous day stop time
# 120517-1257 - Added CALLMENU timeout option
# 120706-1659 - Added Qualify SQL option
# 120719-1411 - Fixed issue with inbound IVR calls not showing up in real-time screen
# 120730-0727 - Fixed issue with non-populating phone number
# 121124-1414 - Added call times holidays function
# 130108-1807 - Changes for Asterisk 1.8 compatibility
# 130925-1826 - Added variable filter to prevent DID SQL injection attack
# 140126-1141 - Added VMAIL_NO_INST options
# 161102-1038 - Fixed QM partition problem
#
$script = 'agi-VDAD_inbound_calltime_check.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$hm = "$hour$min";
$hm = ($hm + 0);
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$CLInow_date = "$year-$mon-$mday\\ $hour:$min:$sec";
$YMD = "$year-$mon-$mday";
$start_time=$now_date;
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec";
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$SQLdateBEGIN = $SQLdate;
$BDtarget = ($now_date_epoch + 600);
($Bsec,$Bmin,$Bhour,$Bmday,$Bmon,$Byear,$Bwday,$Byday,$Bisdst) = localtime($BDtarget);
$Byear = ($Byear + 1900);
$Bmon++;
if ($Bmon < 10) {$Bmon = "0$Bmon";}
if ($Bmday < 10) {$Bmday = "0$Bmday";}
if ($Bhour < 10) {$Bhour = "0$Bhour";}
if ($Bmin < 10) {$Bmin = "0$Bmin";}
if ($Bsec < 10) {$Bsec = "0$Bsec";}
$last_update_time = "$Byear$Bmon$Bmday$Bhour$Bmin$Bsec";
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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";}
if (!$PRSLOGfile) {$PRSLOGfile = "$PATHlogs/prsout.$year-$mon-$mday";}
if (!$PRSTESTfile) {$PRSTESTfile = "$PATHlogs/prstest.$year-$mon-$mday";}
use DBI;
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
}
$sthA->finish();
#############################################
##### START QUEUEMETRICS LOGGING LOOKUP #####
$stmtA = "SELECT enable_queuemetrics_logging,queuemetrics_server_ip,queuemetrics_dbname,queuemetrics_login,queuemetrics_pass,queuemetrics_log_id,queuemetrics_eq_prepend,call_menu_qualify_enabled 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;
$enable_queuemetrics_logging = $aryA[0];
$queuemetrics_server_ip = $aryA[1];
$queuemetrics_dbname = $aryA[2];
$queuemetrics_login= $aryA[3];
$queuemetrics_pass = $aryA[4];
$queuemetrics_log_id = $aryA[5];
$queuemetrics_eq_prepend = $aryA[6];
$call_menu_qualify_enabled = $aryA[7];
}
$sthA->finish();
##### END QUEUEMETRICS LOGGING LOOKUP #####
###########################################
### 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]);
$channel_group = $ARGV_vars[0];
$log_to_vac = $ARGV_vars[1];
$note = $ARGV_vars[2];
if (length($note)<1) {$note = 'NONE';}
$call_time_override = $ARGV_vars[3];
$route_override = $ARGV_vars[4];
$route_value_override = $ARGV_vars[5];
$route_context_override = $ARGV_vars[6];
$query_qualification = $ARGV_vars[7];
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_priority\:\s+(.*)$/) {$priority = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
$callerid =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$calleridname =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$extension =~ s/\'|\"|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$outboundIVR=0;
$ingroupIVR=0;
$lead_id='';
if ($calleridname =~ /^V\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d|^Y\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/)
{
$stmtA = "SELECT campaign_id,lead_id FROM vicidial_auto_calls where callerid='$calleridname';";
$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_id = $aryA[0];
$lead_id = $aryA[1];
}
else
{
$lead_id = substr($calleridname, 10, 10);
$lead_id = ($lead_id + 0);
$callerid =~ s/\D|\'//gi;
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
$phone_code='1';
}
$sthA->finish();
if ($calleridname =~ /^V\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/)
{$outboundIVR=1;}
if ($calleridname =~ /^Y\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/)
{$ingroupIVR=1;}
if (length($phone_number) < 6)
{
$stmtA = "SELECT phone_number FROM vicidial_list where lead_id='$lead_id';";
$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;
$phone_number = $aryA[0];
}
$sthA->finish();
}
$callerid = $calleridname;
}
else
{
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D|\'//gi;
$calleridname =~ s/unknown|\'//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
if (length($calleridname)>0) {$VLcomments = $calleridname;}
else {$VLcomments = '';}
}
if (length($callerid)<8) {$callerid = $parked_by;}
if (length($pin)>0) {$callerid = $pin;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
if (length($pin) < 1) {$pin=$inbound_number;}
$fronter = $pin;
if ($AGILOG) {$agi_string = "+++++ INBOUND CALL VDCL STARTED : |$channel_group|$callerid-$pin|$now_date"; &agi_output;}
$VDADphone='';
$VDADphone_code='';
if ($channel =~ /Local/i)
{
if ($AGILOG) {$agi_string = "+++++ VDAD START LOCAL CHANNEL: EXITING- $priority"; &agi_output;}
exit;
}
### Grab Server values from the database
$cbc=0;
$stmtA = "SELECT voicemail_dump_exten,ext_context,answer_transfer_agent,local_gmt,asterisk_version,max_vicidial_trunks,voicemail_dump_exten_no_inst 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;
while ($sthArows > $cbc)
{
@aryA = $sthA->fetchrow_array;
$DBvoicemail_dump_exten = $aryA[0];
$DBext_context = $aryA[1];
$DBanswer_transfer_agent = $aryA[2];
$DBSERVER_GMT = $aryA[3];
$DBasterisk_version = $aryA[4];
$DBmax_vicidial_trunks = $aryA[5];
$voicemail_dump_exten_no_inst = $aryA[6];
if ($DBvoicemail_dump_exten) {$voicemail_dump_exten = $DBvoicemail_dump_exten;}
if ($DBext_context) {$ext_context = $DBext_context;}
if ($DBanswer_transfer_agent) {$answer_transfer_agent = $DBanswer_transfer_agent;}
if ($DBSERVER_GMT) {$SERVER_GMT = $DBSERVER_GMT;}
if ($DBasterisk_version) {$AST_ver = $DBasterisk_version;}
if ($DBmax_vicidial_trunks) {$max_vicidial_trunks = $DBmax_vicidial_trunks;}
$cbc++;
}
$sthA->finish();
if (length($channel_group) > 1)
{
### Grab inbound groups values from the database
$cbc=0;
$stmtA = "SELECT call_time_id,after_hours_action,after_hours_message_filename,after_hours_exten,after_hours_voicemail,welcome_message_filename,moh_context,onhold_prompt_filename,prompt_interval,agent_alert_exten,agent_alert_delay,drop_call_seconds,drop_action,drop_exten,next_agent_call,voicemail_ext,queue_priority,drop_inbound_group,afterhours_xfer_group FROM vicidial_inbound_groups where group_id = '$channel_group';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
while ($sthArows > $cbc)
{
@aryA = $sthA->fetchrow_array;
$call_time_id = $aryA[0];
$after_hours_action = $aryA[1];
$after_hours_message_filename = $aryA[2];
$after_hours_exten = $aryA[3];
$after_hours_voicemail = $aryA[4];
$welcome_message_filename = $aryA[5];
$moh_context = $aryA[6];
$onhold_prompt_filename = $aryA[7];
$prompt_interval = $aryA[8];
$agent_alert_exten = $aryA[9];
$agent_alert_delay = $aryA[10];
$drop_call_seconds = $aryA[11];
$DROP_TIME = $drop_call_seconds;
$drop_action = $aryA[12];
$drop_exten = $aryA[13];
$CAMP_callorder = $aryA[14];
$VDADvoicemail_ext = $aryA[15];
$VDADvoicemail_ext =~ s/\D//gi;
$queue_priority = $aryA[16];
$drop_inbound_group = $aryA[17];
$afterhours_xfer_group = $aryA[18];
$cbc++;
}
$sthA->finish();
}
if (length($call_time_override) > 1)
{
$call_time_id = $call_time_override;
}
if (length($route_override) > 1)
{
$after_hours_action = $route_override;
}
if (length($route_value_override) > 1)
{
$after_hours_message_filename = $route_value_override;
$after_hours_exten = $route_value_override;
$after_hours_voicemail = $route_value_override;
}
if (length($route_context_override) > 1)
{
$ext_context = $route_context_override;
}
if ($wday==0)
{
$daySQL=',ct_sunday_start,ct_sunday_stop';
$yestSQL=',ct_saturday_start,ct_saturday_stop';
}
if ($wday==1)
{
$daySQL=',ct_monday_start,ct_monday_stop';
$yestSQL=',ct_sunday_start,ct_sunday_stop';
}
if ($wday==2)
{
$daySQL=',ct_tuesday_start,ct_tuesday_stop';
$yestSQL=',ct_monday_start,ct_monday_stop';
}
if ($wday==3)
{
$daySQL=',ct_wednesday_start,ct_wednesday_stop';
$yestSQL=',ct_tuesday_start,ct_tuesday_stop';
}
if ($wday==4)
{
$daySQL=',ct_thursday_start,ct_thursday_stop';
$yestSQL=',ct_wednesday_start,ct_wednesday_stop';
}
if ($wday==5)
{
$daySQL=',ct_friday_start,ct_friday_stop';
$yestSQL=',ct_thursday_start,ct_thursday_stop';
}
if ($wday==6)
{
$daySQL=',ct_saturday_start,ct_saturday_stop';
$yestSQL=',ct_friday_start,ct_friday_stop';
}
$ct_default_start = '0';
$ct_default_stop = '9999';
### Grab call_times values from the database
$stmtA = "SELECT ct_default_start,ct_default_stop $daySQL $yestSQL,ct_holidays FROM vicidial_call_times where call_time_id = '$call_time_id';";
$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;
$ct_default_start = $aryA[0];
$ct_default_stop = $aryA[1];
$ct_day_start = $aryA[2];
$ct_day_stop = $aryA[3];
$ct_yest_start = $aryA[4];
$ct_yest_stop = $aryA[5];
$ct_holidays = $aryA[6];
$sthA->finish();
if ( ($ct_yest_start < 1) && ($ct_yest_stop < 1) )
{
$ct_yest_start = $ct_default_start;
$ct_yest_stop = $ct_default_stop;
}
if ( ($ct_day_start > 0) || ($ct_day_stop > 0) )
{
$ct_default_start = $ct_day_start;
$ct_default_stop = $ct_day_stop;
}
}
if (length($ct_holidays) > 2)
{
$stmtA = "SELECT count(*) from vicidial_call_time_holidays where holiday_date='$YMD' and holiday_status='ACTIVE';";
if ($DBX) {print " |$stmtA|\n";}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
@aryA = $sthA->fetchrow_array;
$holiday_today_count = $aryA[0];
if ($AGILOG) {$agi_string = "Holiday check: |$holiday_today_count|$stmtA|$ct_holidays|"; &agi_output;}
$ct_hrs=0;
$b=0;
if ($holiday_today_count > 0)
{
@holiday_rules = split(/\|/,$ct_holidays);
$ct_hrs = ($#holiday_rules - 0);
while($ct_hrs >= $b)
{
if (length($holiday_rules[$b])>1)
{
$stmtA = "SELECT holiday_id,holiday_date,holiday_name,ct_default_start,ct_default_stop,default_afterhours_filename_override from vicidial_call_time_holidays where holiday_id='$holiday_rules[$b]' and holiday_status='ACTIVE' and holiday_date='$YMD';";
if ($DBX) {print " |$stmtA|\n";}
$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;
$holiday_id = $aryA[0];
$holiday_date = $aryA[1];
$holiday_name = $aryA[2];
$ct_default_start = $aryA[3];
$ct_default_stop = $aryA[4];
$default_afterhours_filename_override = $aryA[5];
if ($AGILOG) {$agi_string = "Active Holiday found! |$holiday_id|$holiday_date|$holiday_name|$ct_default_start|$ct_default_stop|$default_afterhours_filename_override|"; &agi_output;}
}
$sthA->finish();
}
$b++;
}
}
}
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
##### BEGIN AFTER HOURS CHECK #####
$ct_stop_overflow=0; # allow for overflow time, past midnight
if ($ct_yest_stop > 2400)
{$ct_stop_overflow = ($ct_yest_stop - 2400);}
if ( ( ($hm < $ct_default_start) || ($hm > $ct_default_stop) ) && ($hm >= $ct_stop_overflow) )
{
$VHqueryCID = "VA$CIDdate$hour$min$sec$sec";
if ($outboundIVR > 0)
{
$stmtA = "DELETE FROM vicidial_auto_calls where callerid='$callerid' and campaign_id='$campaign_id' and server_ip='$VARserver_ip' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- AH VDAC vac record deleted: |$affected_rows|$campaign_id|$callerid|$call_time_id|"; &agi_output;}
$stmtA = "INSERT INTO vicidial_outbound_ivr_log (uniqueid,caller_code,event_date,campaign_id,lead_id,menu_id,menu_action) values('$uniqueid','$callerid','$SQLdate','$campaign_id','$lead_id','$context','AFTERHOURSDROP')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VOIL insert: |$affected_rowsL|$uniqueid|$callerid|$campaign_id|$lead_id|$context|"; &agi_output;}
}
else
{
$stmtA = "DELETE FROM vicidial_auto_calls where callerid='$callerid' and uniqueid='$uniqueid' and server_ip='$VARserver_ip' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- AH VDAC vac record deleted: |$affected_rows|$uniqueid|$callerid|$call_time_id|"; &agi_output;}
$stmtA = "INSERT INTO live_inbound_log (uniqueid,channel,server_ip,caller_id,extension,phone_ext,start_time,comment_a,comment_b,comment_c,comment_d,comment_e) values('$uniqueid','$channel','$VARserver_ip','$callerid','$extension','$phone_number','$SQLdate','$channel_group','$note','AFTERHOURSDROP','$context','$priority')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- AH LIL insert: |$affected_rowsL|$uniqueid|$callerid|$extension|"; &agi_output;}
}
### QueueMetrics logging if enabled
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 QueueMetrics DATABASE: $queuemetrics_server_ip|$queuemetrics_dbname\n";}
$stmtB = "INSERT INTO queue_log SET `partition`='P01',time_id='$now_date_epoch',call_id='$uniqueid',queue='NONE',agent='NONE',verb='INFO',data1='IVR',data2='$context',serverid='$queuemetrics_log_id';";
if ($AGILOG) {$agi_string = "|$stmtB|"; &agi_output;}
$Baffected_rows = $dbhB->do($stmtB);
$dbhB->disconnect();
}
if ($after_hours_action =~ /EXTENSION|VOICEMAIL|IN_GROUP|CALLMENU/)
{
if ($after_hours_action =~ /CALLMENU/)
{
$DROPexten = 's';
$ext_context = "$after_hours_exten";
}
if ($after_hours_action =~ /EXTENSION/)
{
$DROPexten = "$after_hours_exten";
}
if ($after_hours_action =~ /VOICEMAIL|VMAIL_NO_INST/)
{
if ($drop_action =~ /VMAIL_NO_INST/)
{$voicemail_dump_exten = $voicemail_dump_exten_no_inst;}
$DROPexten = "$voicemail_dump_exten$after_hours_voicemail";
}
if ($after_hours_action =~ /IN_GROUP/)
{ # 90009*CL_uk3survy_*8301*10000123*universal*7275551212*1234*"
$S='*';
$DROPexten = "90009*$afterhours_xfer_group$S$S$insert_lead_id$S$S$phone_number$S$fronter$S";
}
if (length($DROPexten)>0)
{ ### if DROP extension is defined then send the dropped call there instead of hangup
$AGI->stream_file('sip-silence'); # stop music-on-hold process
$AGI->stream_file('sip-silence'); # stop music-on-hold process
sleep(1);
if ($AGILOG) {$agi_string = "exiting the VDAD app after hours, transferring call to $DROPexten |$hm|$ct_default_start|$ct_default_stop|$ct_stop_overflow|"; &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);
}
}
if ($after_hours_action =~ /MESSAGE|HANGUP/)
{
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file("$after_hours_message_filename");
sleep(1);
### insert a NEW record to the vicidial_manager table to hangup the channel
$stmtA = "INSERT INTO vicidial_manager values('','','$SQLdate','NEW','N','$VARserver_ip','','Hangup','$VHqueryCID','Channel: $channel','','','','','','','','','')";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDCL call_hungup after hours: |$VHqueryCID|$VDADconf_exten|$channel|insert to vicidial_manager"; &agi_output;}
}
$dbhA->disconnect();
exit;
}
##### END AFTER HOURS CHECK #####
##### BEGIN QUALIFY SQL CHECK #####
if ( ($call_menu_qualify_enabled > 0) && ($query_qualification =~ /YES/) && ( ($outboundIVR > 0) || ($ingroupIVR > 0) ) )
{
$qualify_count=0;
$stmtA = "SELECT qualify_sql FROM vicidial_call_menu where menu_id='$context';";
$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;
$qualify_sql = $aryA[0];
}
$sthA->finish();
if (length($qualify_sql) > 5)
{
$lead_id = substr($calleridname, 10, 10);
$lead_id = ($lead_id + 0);
$stmtA = "SELECT count(*) FROM vicidial_list where lead_id='$lead_id' and $qualify_sql;";
$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;
$qualify_count = $aryA[0];
}
$sthA->finish();
if ($AGILOG) {$agi_string = "Exiting the TimeCheck App Qualify SQL |$qualify_count|$lead_id|$context|$calleridname|$stmtA|"; &agi_output;}
if ($qualify_count < 1)
{
$AGI->stream_file('sip-silence'); # stop music-on-hold process
$AGI->stream_file('sip-silence'); # stop music-on-hold process
# sleep for one tenth of a second
usleep(1*100*1000);
if ($AGILOG) {$agi_string = " TimeCheck App Qualify SQL FAIL, transferring call to D |$qualify_count|$lead_id|$context|$calleridname|"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION D\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
}
}
}
##### END QUALIFY SQL CHECK #####
### insert an IVR record to the vicidial_auto_calls table
if ($outboundIVR > 0)
{
$stmtA = "INSERT INTO vicidial_outbound_ivr_log (uniqueid,caller_code,event_date,campaign_id,lead_id,menu_id,menu_action) values('$uniqueid','$callerid','$SQLdate','$campaign_id','$lead_id','$context','')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VOIL insert: |$affected_rowsL|$uniqueid|$callerid|$campaign_id|$lead_id|$context|"; &agi_output;}
$stmtA = "UPDATE vicidial_auto_calls SET last_update_time='$last_update_time',status='IVR' where callerid='$callerid';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsV = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VAC update: |$affected_rowsV|$uniqueid|$callerid|$last_update_time|"; &agi_output;}
}
else
{
if ($log_to_vac =~ /YES/)
{
if ($ingroupIVR > 0)
{
$stmtA = "UPDATE vicidial_auto_calls SET last_update_time='$last_update_time',status='IVR' where callerid='$callerid';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsV = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VAC update: |$affected_rowsV|$uniqueid|$callerid|$last_update_time|"; &agi_output;}
if ($affected_rowsV < 1)
{
$stmtA = "INSERT INTO vicidial_auto_calls (server_ip,campaign_id,lead_id,status,uniqueid,callerid,channel,phone_code,phone_number,call_time,call_type,stage,queue_priority,last_update_time) values('$VARserver_ip','$channel_group','$lead_id','IVR','$uniqueid','$callerid','$channel','$phone_code','$phone_number','$SQLdate','IN','IVR-0','0','$last_update_time')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsV = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VAC insert: |$affected_rowsV|$uniqueid|$callerid|$extension|$lead_id|"; &agi_output;}
}
}
else
{
$stmtA = "DELETE FROM vicidial_auto_calls where callerid='$callerid' and uniqueid='$uniqueid' and server_ip='$VARserver_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAC vac record deleted: |$affected_rows| $uniqueid|$callerid|"; &agi_output;}
$stmtA = "INSERT INTO vicidial_auto_calls (server_ip,campaign_id,lead_id,status,uniqueid,callerid,channel,phone_code,phone_number,call_time,call_type,stage,queue_priority,last_update_time) values('$VARserver_ip','$channel_group','0','IVR','$uniqueid','$callerid','$channel','$phone_code','$phone_number','$SQLdate','IN','IVR-0','$queue_priority','$last_update_time')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsV = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VAC insert: |$affected_rowsV|$uniqueid|$callerid|$extension|"; &agi_output;}
}
}
$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','$phone_number','$SQLdate','$channel_group','$note','$context','$priority')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- LIL insert: |$affected_rowsL|$uniqueid|$callerid|$extension|"; &agi_output;}
}
### QueueMetrics logging if enabled
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 QueueMetrics DATABASE: $queuemetrics_server_ip|$queuemetrics_dbname\n";}
if ($outboundIVR > 0)
{$uniqueid = $caller_id;}
$stmtB = "INSERT INTO queue_log SET `partition`='P01',time_id='$now_date_epoch',call_id='$uniqueid',queue='NONE',agent='NONE',verb='INFO',data1='IVR',data2='$context',serverid='$queuemetrics_log_id';";
if ($AGILOG) {$agi_string = "|$stmtB|"; &agi_output;}
$Baffected_rows = $dbhB->do($stmtB);
$dbhB->disconnect();
}
$sthA->finish();
$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='';
}
@@ -0,0 +1,240 @@
#!/usr/bin/perl
#
# agi-VDAD_pin_IVR.agi version 2.0.5 *DBI-version*
#
# At the end of a call, the agent transfers customer to this script
#
# This script plays a beep then plays the first portion of the message
# then logs the portion as listened to in the vicidial_list_pins table
# then plays second portion and hangs up.
#
# IN THE CAMPAIGN OR IN-GROUP NUMBER PRESET FIELD:
# AXFER83209
#
# ON THE SERVER ORIGINATING THE CALL:
#;outbound IVR play VICIDIAL calls:
#exten => _983209.,1,AGI(call_log.agi,${EXTEN})
#exten => _983209.,2,Dial(${TRUNKY}/${EXTEN:1},60)
#exten => _983209.,3,Hangup
#
# ON THE SERVER THAT HAS THIS SCRIPT:
#;inbound IVR play VICIDIAL calls:
#exten => _83209.,1,Answer
#exten => _83209.,2,AGI(agi-VDAD_pin_IVR.agi,${EXTEN})
#exten => _83209.,3,Hangup
#
# Copyright (C) 2008 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 60802-1304 - first build
# 60817-1113 - added output options check from database
#
$script = 'agi-VDAD_pin_IVR.agi';
$first_audio_file = '85100003';
$second_audio_file = '85100004';
$goodbye_audio_file = 'US_reminder_goodbye';
#$first_audio_file = 'US_reminder_message';
#$second_audio_file = 'US_reminder_options';
#$goodbye_audio_file = 'US_reminder_goodbye';
### set defaults for testing
$referring_extension = '83209';
$phone_number = '9999999999';
$lead_id = '999999999';
$campaign_id = 'TESTCAMP';
$product_code = 'ABC';
$user = '1234';
$pin = '0';
($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";}
$SQLdate = "$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 = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n [-q] = quiet\n [-t] = test\n [-debug] = verbose debug messages\n\n";
}
else
{
if ($args =~ /-V/i)
{
$V=1;
}
if ($args =~ /-debug/i)
{
$DG=1;
}
if ($args =~ /-q/i)
{
$q=1;
$Q=1;
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
}
}
$|=1;
while(<STDIN>) {
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
### allow for internal transfer data string "83009*3125551212*10000123*TESTCAMP*ABC*1234*"
if ($extension =~ /^8320\d\*/)
{
@EXT_vars = split(/\*/, $extension);
$referring_extension = $EXT_vars[0]; # initial extension sent
$phone_number = $EXT_vars[1]; # phone number
$lead_id = $EXT_vars[2]; # lead_id in vicidial_list
$campaign_id = $EXT_vars[3]; # campaign id
$product_code = $EXT_vars[4]; # product code
$user = $EXT_vars[5]; # vicidial_user that sent the call here
}
}
if ($AGILOG) {$agi_string = "INBOUND IVR PLAY CALL VDCL STARTED"; &agi_output;}
$AGI->stream_file('beep');
sleep(1);
$AGI->stream_file("$first_audio_file");
### insert a record into the vicidial_list_pins table
$stmtA = "INSERT INTO vicidial_list_pins (entry_time,phone_number,lead_id,campaign_id,product_code,user,digits) values('$SQLdate','$phone_number','$lead_id','$campaign_id','$product_code','$user','IVR');";
$affected_rows = $dbhA->do($stmtA);
$insert_pin_id = $dbhA->{'mysql_insertid'};
if ($AGILOG) {$agi_string = "|$stmtA|$insert_pin_id|$affected_rows|"; &agi_output;}
$dbhA->disconnect();
$AGI->stream_file("$second_audio_file");
sleep(1);
$AGI->stream_file("$goodbye_audio_file");
exit;
sub agi_output
{
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$now_date|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$now_date|$script|$agi_string\n";}
$agi_string='';
}
@@ -0,0 +1,673 @@
#!/usr/bin/perl
#
# agi-VDADautoREMINDER.agi version 2.6
#
# runs when a call comes in from the VICIDIAL auto_dialer. This script will
# send the calls out to specified voicemail boxes in if called person presses key.
# The voicemail box is defined per-lead in the vicidial_list.security_phrase field
# This campaign does not send calls to live agents.
#
# Call statuses from this script:
# N- Call was picked up, didn't finish initial message
# MP- Initial message was played
# VM- call was sent to voicemail
# CALLBK- customer selected to be called back
#
# It is recommended that you run this campaign at a dial level of 1.0
# It is recommended that you use remote_agents for activation of this script
#
# You need to put lines similar to those below in your extensions.conf file:
#
# ;VICIDIAL_auto_dialer transfer script:
# exten => 8372,1,AGI(call_log.agi,${EXTEN})
# exten => 8372,2,AGI(agi-VDADautoREMINDER.agi,${EXTEN})
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: GPLv2
#
# CHANGES
# 60313-1626 - First build
# 60810-1729 - Changed to DBI
# - changed to use /etc/astguiclient.conf for configs
# 60818-1144 - added output options check from database
# 130108-1814 - Changes for Asterisk 1.8 compatibility
#
$script = 'agi-VDADautoREMINDER.agi';
##### AUDIO FILES IN THIS PROGRAM #####
$message_audio_file = 'US_reminder_message';
$options_audio_file = 'US_reminder_options';
# $voicemail_xfer_file = 'US_reminder_voicemail'; not used
$callback_audio_file = 'US_reminder_callback';
$goodbye_audio_file = 'US_reminder_goodbye';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$start_time=$now_date;
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec"; #20060310100402
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$SQLdateBEGIN = $SQLdate;
$BDtarget = ($secX - 5);
($Bsec,$Bmin,$Bhour,$Bmday,$Bmon,$Byear,$Bwday,$Byday,$Bisdst) = localtime($BDtarget);
$Byear = ($Byear + 1900);
$Bmon++;
if ($Bmon < 10) {$Bmon = "0$Bmon";}
if ($Bmday < 10) {$Bmday = "0$Bmday";}
if ($Bhour < 10) {$Bhour = "0$Bhour";}
if ($Bmin < 10) {$Bmin = "0$Bmin";}
if ($Bsec < 10) {$Bsec = "0$Bsec";}
$BDtsSQLdate = "$Byear$Bmon$Bmday$Bhour$Bmin$Bsec";
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n [-q] = quiet\n [-t] = test\n [-debug] = verbose debug messages\n\n";
}
else
{
if ($args =~ /-V/i)
{
$V=1;
}
if ($args =~ /-debug/i)
{
$DG=1;
}
if ($args =~ /-dbAVS/i)
{
$DGA=1;
}
if ($args =~ /-q/i)
{
$q=1;
$Q=1;
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
}
}
$|=1;
while(<STDIN>) {
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;}
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";
$result = <STDIN>;
checkresult($result);
if ($AGILOG) {$agi_string = "callerID changed: $callerid"; &agi_output;}
}
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";
$result = <STDIN>;
checkresult($result);
if ($AGILOG) {$agi_string = "callerID changed: $callerid"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Environment Dump:"; &agi_output;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
$VDADcampaign='';
$VDADphone='';
$VDADphone_code='';
$callerid =~ s/\"//gi;
$CIDlead_id = $callerid;
$CIDlead_id = substr($CIDlead_id, 11, 9);
$CIDlead_id = ($CIDlead_id + 0);
if ($AGILOG) {$agi_string = "+++++ VDAD START : |$CIDlead_id|$now_date|"; &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;
}
sleep(1);
$AGI->stream_file('beep');
### Grab Server values from the database
$stmtA = "SELECT voicemail_dump_exten,ext_context,answer_transfer_agent,local_gmt,asterisk_version,max_vicidial_trunks FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$DBvoicemail_dump_exten = "$aryA[0]";
$DBext_context = "$aryA[1]";
$DBanswer_transfer_agent = "$aryA[2]";
$DBSERVER_GMT = "$aryA[3]";
$DBasterisk_version = "$aryA[4]";
$DBmax_vicidial_trunks = "$aryA[5]";
if ($DBvoicemail_dump_exten) {$voicemail_dump_exten = $DBvoicemail_dump_exten;}
if ($DBext_context) {$ext_context = $DBext_context;}
if ($DBanswer_transfer_agent) {$answer_transfer_agent = $DBanswer_transfer_agent;}
if ($DBSERVER_GMT) {$SERVER_GMT = $DBSERVER_GMT;}
if ($DBasterisk_version) {$AST_ver = $DBasterisk_version;}
if ($DBmax_vicidial_trunks) {$max_vicidial_trunks = $DBmax_vicidial_trunks;}
$rec_count++;
}
$sthA->finish();
### Grab call parameters from vicidial_auto_calls table
$stmtA = "UPDATE vicidial_auto_calls set uniqueid='$unique_id', channel='$channel',status='LIVE',stage='LIVE-0' where callerid='$callerid' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD : |$affected_rows|update of vac table: $callerid\n|$stmtA|"; &agi_output;}
if ($affected_rows > 0)
{
$stmtA = "SELECT campaign_id,phone_number,phone_code,lead_id,call_time FROM vicidial_auto_calls where callerid='$callerid' order by call_time desc limit 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$VDADcampaign = "$aryA[0]";
$VDADphone = "$aryA[1]";
$VDADphone_code = "$aryA[2]";
$VDADlead_id = "$aryA[3]";
$VDADcall_time = "$aryA[4]";
$rec_count++;
}
$sthA->finish();
$stmtA = "INSERT INTO vicidial_log (uniqueid,lead_id,campaign_id,call_date,start_epoch,status,phone_code,phone_number,user,processed) values('$uniqueid','$CIDlead_id','$VDADcampaign','$SQLdate','$now_date_epoch','N','$VDADphone_code','$VDADphone','VDAD','N')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD : |$VDADlead_id|$CIDlead_id|insert to vicidial_log: $uniqueid"; &agi_output;}
}
######### REMINDER CHOICE FROM RECORDINGS ########
&reminder_choice;
if ($pin < 1)
{
&reminder_choice;
if ($pin < 1)
{
$AGI->stream_file("$goodbye_audio_file");
$stmtA = "DELETE FROM vicidial_auto_calls where callerid='$callerid' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|"; &agi_output;}
$end_date_epoch = time();
$length_in_sec = ($end_date_epoch - $now_date_epoch);
$stmtA = "UPDATE vicidial_log set end_epoch='$end_date_epoch', length_in_sec='$length_in_sec' where uniqueid='$uniqueid' and lead_id='$CIDlead_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|$end_date_epoch|$now_date_epoch|$length_in_sec|"; &agi_output;}
$VHqueryCID = "VHNGUP$tsSQLdate";
### 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);
if ($AGILOG) {$agi_string = "-- VDAD call_hungup timout: |$VHqueryCID|$VDADconf_exten|$channel|insert to vicidial_manager"; &agi_output;}
sleep(1);
exit;
}
}
if ($AGILOG) {$agi_string = "+++++ VDAD STATUS : pressed $pin|$unique_id|$channel|$extension|$type|$callerid|$CIDlead_id|$now_date"; &agi_output;}
if ($pin !~ /^1|^2/) {exit;}
if (!$DB_port) {$DB_port='3306';}
if ($pin =~ /^1|^2/)
{
if ($pin == "1") ### send call to voicemail
{
# message can be left on agent vmail box
# # Thank you for your response, we will now transfer you to your agent's voicemail box.
# $AGI->stream_file("$voicemail_xfer_file");
$stmtA = "UPDATE vicidial_auto_calls set status='XFER', stage='XFER-$drop_timer' where callerid='$callerid';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD XFER : |$affected_rows|update of vac table: $callerid\n|$stmtA|"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='VM' where lead_id = '$CIDlead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_list update: |$affected_rows|$CIDlead_id|XFER"; &agi_output;}
($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";}
$end_date_epoch = time();
$length_in_sec = ($end_date_epoch - $now_date_epoch);
$now_date = "$year-$mon-$mday $hour:$min:$sec";
if ($AGILOG) {$agi_string = "XXXXXXXXXX VDAD transferred: start|stop $start_time|$now_date"; &agi_output;}
$stmtA = "UPDATE vicidial_log set status='VM', end_epoch='$end_date_epoch', length_in_sec='$length_in_sec' where uniqueid='$uniqueid' and lead_id='$CIDlead_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vac record updated: |$affected_rows|$VDADcampaign|"; &agi_output;}
$VMAIL_box=0;
### Grab Server values from the database
$stmtA = "SELECT security_phrase FROM vicidial_list where lead_id = '$CIDlead_id';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$VMAIL_box = "$aryA[0]";
$rec_count++;
}
$sthA->finish();
### SEND CALL TO VOICEMAIL BOX ###
if ($AGILOG) {$agi_string = "exiting the VDAD app, transferring call to $voicemail_dump_exten$VMAIL_box"; &agi_output;}
print "SET CONTEXT $ext_context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $voicemail_dump_exten$VMAIL_box\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
}
if ($pin == "2") ### mark call as a CALLBK
{
# Thank you for your response, your agent will be contacting you shortly.
$stmtA = "DELETE from vicidial_auto_calls where callerid='$callerid';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD DONE : |$affected_rows|delete of vac table: $callerid\n|$stmtA|"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='CALLBK' where lead_id = '$CIDlead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_list update: |$affected_rows|$CIDlead_id|XFER"; &agi_output;}
($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";}
$end_date_epoch = time();
$length_in_sec = ($end_date_epoch - $now_date_epoch);
$now_date = "$year-$mon-$mday $hour:$min:$sec";
if ($AGILOG) {$agi_string = "XXXXXXXXXX VDAD transferred: start|stop $start_time|$now_date"; &agi_output;}
$stmtA = "UPDATE vicidial_log set status='CALLBK', end_epoch='$end_date_epoch', length_in_sec='$length_in_sec' where uniqueid='$uniqueid' and lead_id='$CIDlead_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vac record updated: |$affected_rows|$VDADcampaign|"; &agi_output;}
$AGI->stream_file("$callback_audio_file");
$VHqueryCID = "VHNGUP$tsSQLdate";
### 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);
if ($AGILOG) {$agi_string = "-- VDAD call_hungup timout: |$VHqueryCID|$VDADconf_exten|$channel|insert to vicidial_manager"; &agi_output;}
sleep(1);
exit;
}
} ### end if pressed 1,2
else ### user pressed digit other than 1 or 2
{
exit;
}
$dbhA->close;
exit;
sub reminder_choice
{
$digit='';
undef $digit;
$interrupt_digit='';
undef $interrupt_digit;
# Hello, this is a courtesy call from ACME Industries reminding you that the deadline for the submission of orders for the June 5th batch delivery is tomorrow, March 10th:
# second audio file
# If you would like to leave a message for your agent please press 1.
# If you would like to have your agent call you back please press 2.
# third audio file
# Thank you, Goodbye
######### PLAY THE MESSAGE FILE THEN WAIT 2 SECONDS FOR DIGITS ############
$interrupt_digit = $AGI->stream_file("$message_audio_file",'12');
if ($AGILOG) {$agi_string = "interrupt_digit |$interrupt_digit|"; &agi_output;}
$digits_being_entered=1;
$digit_loop_counter=0;
$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++;
}
$channel_status = $AGI->channel_status("$channel");
if ($AGILOG) {$agi_string = "SSSSSSSSSS Channel Status: $channel_status"; &agi_output;}
if ($channel_status == 6)
{
$stmtA = "UPDATE vicidial_log set status='MP' where uniqueid = '$uniqueid' and lead_id='$CIDlead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_log update: N|$affected_rows|$uniqueid"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='MP' where lead_id = '$CIDlead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_list update: N|$affected_rows|$CIDlead_id"; &agi_output;}
}
while ($digit_loop_counter < 1)
{
$digit = chr($AGI->wait_for_digit('2000')); # wait 2 seconds for input or until digit 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=1;
}
$digit_loop_counter++;
}
$totalDTMF =~ s/\D//gi;
$pin = $totalDTMF;
if ($totalDTMF)
{
if ($AGILOG) {$agi_string = "digit |$digit| TotalDTMF |$totalDTMF|"; &agi_output;}
return;
}
######### PLAY THE OPTIONS FILE THEN WAIT 5 SECONDS FOR DIGITS ############
$interrupt_digit = $AGI->stream_file("$options_audio_file",'12');
if ($AGILOG) {$agi_string = "interrupt_digit |$interrupt_digit|"; &agi_output;}
$digits_being_entered=1;
$digit_loop_counter=0;
$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 < 1)
{
$digit = chr($AGI->wait_for_digit('10000')); # wait 10 seconds for input or until digit 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=1;
}
$digit_loop_counter++;
}
$totalDTMF =~ s/\D//gi;
$pin = $totalDTMF;
if ($totalDTMF)
{
if ($AGILOG) {$agi_string = "digit |$digit| TotalDTMF |$totalDTMF|"; &agi_output;}
return;
}
}
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='';
}
@@ -0,0 +1,738 @@
#!/usr/bin/perl
#
# agi-VDADautoREMINDERxfer.agi version 2.6
#
# runs when a call comes in from the VICIDIAL auto_dialer. This script will
# send the calls out to specified voicemail boxes or specified extensions if
# called person presses specified key(1,2,3).
# The voicemail box is defined per-lead in the vicidial_list.security_phrase field
# The exten xfer number is defined per-lead in the vicidial_list.comments field
#
# Call statuses from this script:
# N- Call was picked up, didn't finish initial message
# MP- Initial message was played
# VM- call was sent to voicemail
# XFER- call was sent to specified extension
# CALLBK- customer selected to be called back
#
# It is recommended that you run this campaign at a dial level of 1.0
# It is recommended that you use remote_agents for activation of this script
#
# You need to put lines similar to those below in your extensions.conf file:
#
# ;VICIDIAL_auto_dialer transfer script:
# exten => 8372,1,AGI(call_log.agi,${EXTEN})
# exten => 8372,2,AGI(agi-VDADautoREMINDERxfer.agi,${EXTEN})
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: GPLv2
#
# CHANGES
# 60511-1214 - First build
# 60810-1729 - Changed to DBI
# - changed to use /etc/astguiclient.conf for configs
# 60818-1144 - added output options check from database
# 130108-1812 - Changes for Asterisk 1.8 compatibility
#
$script = 'agi-VDADautoREMINDERxfer.agi';
##### AUDIO FILES IN THIS PROGRAM #####
$message_audio_file = 'US_reminder_message';
$options_audio_file = 'US_reminder_options';
# $voicemail_xfer_file = 'US_reminder_voicemail'; not used
$callback_audio_file = 'US_reminder_callback';
$goodbye_audio_file = 'US_reminder_goodbye';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$start_time=$now_date;
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec"; #20060310100402
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$SQLdateBEGIN = $SQLdate;
$BDtarget = ($secX - 5);
($Bsec,$Bmin,$Bhour,$Bmday,$Bmon,$Byear,$Bwday,$Byday,$Bisdst) = localtime($BDtarget);
$Byear = ($Byear + 1900);
$Bmon++;
if ($Bmon < 10) {$Bmon = "0$Bmon";}
if ($Bmday < 10) {$Bmday = "0$Bmday";}
if ($Bhour < 10) {$Bhour = "0$Bhour";}
if ($Bmin < 10) {$Bmin = "0$Bmin";}
if ($Bsec < 10) {$Bsec = "0$Bsec";}
$BDtsSQLdate = "$Byear$Bmon$Bmday$Bhour$Bmin$Bsec";
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n [-q] = quiet\n [-t] = test\n [-debug] = verbose debug messages\n\n";
}
else
{
if ($args =~ /-V/i)
{
$V=1;
}
if ($args =~ /-debug/i)
{
$DG=1;
}
if ($args =~ /-dbAVS/i)
{
$DGA=1;
}
if ($args =~ /-q/i)
{
$q=1;
$Q=1;
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
}
}
$|=1;
while(<STDIN>) {
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;}
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";
$result = <STDIN>;
checkresult($result);
if ($AGILOG) {$agi_string = "callerID changed: $callerid"; &agi_output;}
}
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";
$result = <STDIN>;
checkresult($result);
if ($AGILOG) {$agi_string = "callerID changed: $callerid"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Environment Dump:"; &agi_output;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
$VDADcampaign='';
$VDADphone='';
$VDADphone_code='';
$callerid =~ s/\"//gi;
$CIDlead_id = $callerid;
$CIDlead_id = substr($CIDlead_id, 11, 9);
$CIDlead_id = ($CIDlead_id + 0);
if ($AGILOG) {$agi_string = "+++++ VDAD START : |$CIDlead_id|$now_date|"; &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;
}
sleep(1);
$AGI->stream_file('beep');
### Grab Server values from the database
$stmtA = "SELECT voicemail_dump_exten,ext_context,answer_transfer_agent,local_gmt,asterisk_version,max_vicidial_trunks FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$DBvoicemail_dump_exten = "$aryA[0]";
$DBext_context = "$aryA[1]";
$DBanswer_transfer_agent = "$aryA[2]";
$DBSERVER_GMT = "$aryA[3]";
$DBasterisk_version = "$aryA[4]";
$DBmax_vicidial_trunks = "$aryA[5]";
if ($DBvoicemail_dump_exten) {$voicemail_dump_exten = $DBvoicemail_dump_exten;}
if ($DBext_context) {$ext_context = $DBext_context;}
if ($DBanswer_transfer_agent) {$answer_transfer_agent = $DBanswer_transfer_agent;}
if ($DBSERVER_GMT) {$SERVER_GMT = $DBSERVER_GMT;}
if ($DBasterisk_version) {$AST_ver = $DBasterisk_version;}
if ($DBmax_vicidial_trunks) {$max_vicidial_trunks = $DBmax_vicidial_trunks;}
$rec_count++;
}
$sthA->finish();
### Grab call parameters from vicidial_auto_calls table
$stmtA = "UPDATE vicidial_auto_calls set uniqueid='$unique_id', channel='$channel',status='LIVE',stage='LIVE-0' where callerid='$callerid' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD : |$affected_rows|update of vac table: $callerid\n|$stmtA|"; &agi_output;}
if ($affected_rows > 0)
{
$stmtA = "SELECT campaign_id,phone_number,phone_code,lead_id,call_time FROM vicidial_auto_calls where callerid='$callerid' order by call_time desc limit 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$VDADcampaign = "$aryA[0]";
$VDADphone = "$aryA[1]";
$VDADphone_code = "$aryA[2]";
$VDADlead_id = "$aryA[3]";
$VDADcall_time = "$aryA[4]";
$rec_count++;
}
$sthA->finish();
$stmtA = "INSERT INTO vicidial_log (uniqueid,lead_id,campaign_id,call_date,start_epoch,status,phone_code,phone_number,user,processed) values('$uniqueid','$CIDlead_id','$VDADcampaign','$SQLdate','$now_date_epoch','N','$VDADphone_code','$VDADphone','VDAD','N')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD : |$VDADlead_id|$CIDlead_id|insert to vicidial_log: $uniqueid"; &agi_output;}
}
######### REMINDER CHOICE FROM RECORDINGS ########
&reminder_choice;
if ($pin < 1)
{
&reminder_choice;
if ($pin < 1)
{
$AGI->stream_file("$goodbye_audio_file");
$stmtA = "DELETE FROM vicidial_auto_calls where callerid='$callerid' order by call_time desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|"; &agi_output;}
$end_date_epoch = time();
$length_in_sec = ($end_date_epoch - $now_date_epoch);
$stmtA = "UPDATE vicidial_log set end_epoch='$end_date_epoch', length_in_sec='$length_in_sec' where uniqueid='$uniqueid' and lead_id='$CIDlead_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vac record deleted: |$affected_rows|$VDADcampaign|$end_date_epoch|$now_date_epoch|$length_in_sec|"; &agi_output;}
$VHqueryCID = "VHNGUP$tsSQLdate";
### 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);
if ($AGILOG) {$agi_string = "-- VDAD call_hungup timout: |$VHqueryCID|$VDADconf_exten|$channel|insert to vicidial_manager"; &agi_output;}
sleep(1);
exit;
}
}
if ($AGILOG) {$agi_string = "+++++ VDAD STATUS : pressed $pin|$unique_id|$channel|$extension|$type|$callerid|$CIDlead_id|$now_date"; &agi_output;}
if ($pin !~ /^1|^2|^3/) {exit;}
if (!$DB_port) {$DB_port='3306';}
if ($pin =~ /^1|^2|^3/)
{
if ($pin == "1") ### send call to voicemail
{
# message can be left on agent vmail box
# # Thank you for your response, we will now transfer you to your agent's voicemail box.
# $AGI->stream_file("$voicemail_xfer_file");
$stmtA = "UPDATE vicidial_auto_calls set status='XFER', stage='XFER-$drop_timer' where callerid='$callerid';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD XFER : |$affected_rows|update of vac table: $callerid\n|$stmtA|"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='VM' where lead_id = '$CIDlead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_list update: |$affected_rows|$CIDlead_id|XFER"; &agi_output;}
($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";}
$end_date_epoch = time();
$length_in_sec = ($end_date_epoch - $now_date_epoch);
$now_date = "$year-$mon-$mday $hour:$min:$sec";
if ($AGILOG) {$agi_string = "XXXXXXXXXX VDAD transferred: start|stop $start_time|$now_date"; &agi_output;}
$stmtA = "UPDATE vicidial_log set status='VM', end_epoch='$end_date_epoch', length_in_sec='$length_in_sec' where uniqueid='$uniqueid' and lead_id='$CIDlead_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vac record updated: |$affected_rows|$VDADcampaign|"; &agi_output;}
$VMAIL_box=0;
### Grab Server values from the database
$stmtA = "SELECT security_phrase FROM vicidial_list where lead_id = '$CIDlead_id';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$VMAIL_box = "$aryA[0]";
$rec_count++;
}
$sthA->finish();
### SEND CALL TO VOICEMAIL BOX ###
if ($AGILOG) {$agi_string = "exiting the VDAD app, transferring call to $voicemail_dump_exten$VMAIL_box"; &agi_output;}
print "SET CONTEXT $ext_context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $voicemail_dump_exten$VMAIL_box\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
}
if ($pin == "2") ### mark call as a CALLBK
{
# Thank you for your response, your agent will be contacting you shortly.
$stmtA = "DELETE from vicidial_auto_calls where callerid='$callerid';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD DONE : |$affected_rows|delete of vac table: $callerid\n|$stmtA|"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='CALLBK' where lead_id = '$CIDlead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_list update: |$affected_rows|$CIDlead_id|XFER"; &agi_output;}
($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";}
$end_date_epoch = time();
$length_in_sec = ($end_date_epoch - $now_date_epoch);
$now_date = "$year-$mon-$mday $hour:$min:$sec";
if ($AGILOG) {$agi_string = "XXXXXXXXXX VDAD transferred: start|stop $start_time|$now_date"; &agi_output;}
$stmtA = "UPDATE vicidial_log set status='CALLBK', end_epoch='$end_date_epoch', length_in_sec='$length_in_sec' where uniqueid='$uniqueid' and lead_id='$CIDlead_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vac record updated: |$affected_rows|$VDADcampaign|"; &agi_output;}
$AGI->stream_file("$callback_audio_file");
$VHqueryCID = "VHNGUP$tsSQLdate";
### 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);
if ($AGILOG) {$agi_string = "-- VDAD call_hungup timout: |$VHqueryCID|$VDADconf_exten|$channel|insert to vicidial_manager"; &agi_output;}
sleep(1);
exit;
}
if ($pin == "3") ### send call to extension
{
# call can be sent to extension
# # Thank you for your response, we will now transfer you to your agent's voicemail box.
# $AGI->stream_file("$voicemail_xfer_file");
$stmtA = "UPDATE vicidial_auto_calls set status='XFER' where callerid='$callerid';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD XFER : |$affected_rows|update of vac table: $callerid\n|$stmtA|"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='XFER' where lead_id = '$CIDlead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_list update: |$affected_rows|$CIDlead_id|XFER"; &agi_output;}
($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";}
$end_date_epoch = time();
$length_in_sec = ($end_date_epoch - $now_date_epoch);
$now_date = "$year-$mon-$mday $hour:$min:$sec";
if ($AGILOG) {$agi_string = "XXXXXXXXXX VDAD transferred: start|stop $start_time|$now_date"; &agi_output;}
$stmtA = "UPDATE vicidial_log set status='XFER', end_epoch='$end_date_epoch', length_in_sec='$length_in_sec' where uniqueid='$uniqueid' and lead_id='$CIDlead_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vac record updated: |$affected_rows|$VDADcampaign|"; &agi_output;}
$VMAIL_box=0;
### Grab Server values from the database
$stmtA = "SELECT comments FROM vicidial_list where lead_id = '$CIDlead_id';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$XFER_exten = "$aryA[0]";
$rec_count++;
}
$sthA->finish();
### SEND CALL TO VOICEMAIL BOX ###
if ($AGILOG) {$agi_string = "exiting the VDAD app, transferring call to $XFER_exten"; &agi_output;}
print "SET CONTEXT $ext_context\n"
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $XFER_exten\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
}
} ### end if pressed 1,2,3
else ### user pressed digit other than 1 or 2 or 3
{
exit;
}
$dbhA->close;
exit;
sub reminder_choice
{
$digit='';
undef $digit;
$interrupt_digit='';
undef $interrupt_digit;
# Hello, this is a courtesy call from ACME Industries reminding you that the deadline for the submission of orders for the June 5th batch delivery is tomorrow, March 10th:
# second audio file
# If you would like to leave a message for your agent please press 1.
# If you would like to have your agent call you back please press 2.
# third audio file
# Thank you, Goodbye
######### PLAY THE MESSAGE FILE THEN WAIT 2 SECONDS FOR DIGITS ############
$interrupt_digit = $AGI->stream_file("$message_audio_file",'123');
if ($AGILOG) {$agi_string = "interrupt_digit |$interrupt_digit|"; &agi_output;}
$digits_being_entered=1;
$digit_loop_counter=0;
$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++;
}
$channel_status = $AGI->channel_status("$channel");
if ($AGILOG) {$agi_string = "SSSSSSSSSS Channel Status: $channel_status"; &agi_output;}
if ($channel_status == 6)
{
$stmtA = "UPDATE vicidial_log set status='MP' where uniqueid = '$uniqueid' and lead_id='$CIDlead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_log update: N|$affected_rows|$uniqueid"; &agi_output;}
$stmtA = "UPDATE vicidial_list set status='MP' where lead_id = '$CIDlead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_list update: N|$affected_rows|$CIDlead_id"; &agi_output;}
}
while ($digit_loop_counter < 1)
{
$digit = chr($AGI->wait_for_digit('2000')); # wait 2 seconds for input or until digit 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=1;
}
$digit_loop_counter++;
}
$totalDTMF =~ s/\D//gi;
$pin = $totalDTMF;
if ($totalDTMF)
{
if ($AGILOG) {$agi_string = "digit |$digit| TotalDTMF |$totalDTMF|"; &agi_output;}
return;
}
######### PLAY THE OPTIONS FILE THEN WAIT 5 SECONDS FOR DIGITS ############
$interrupt_digit = $AGI->stream_file("$options_audio_file",'123');
if ($AGILOG) {$agi_string = "interrupt_digit |$interrupt_digit|"; &agi_output;}
$digits_being_entered=1;
$digit_loop_counter=0;
$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 < 1)
{
$digit = chr($AGI->wait_for_digit('10000')); # wait 10 seconds for input or until digit 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=1;
}
$digit_loop_counter++;
}
$totalDTMF =~ s/\D//gi;
$pin = $totalDTMF;
if ($totalDTMF)
{
if ($AGILOG) {$agi_string = "digit |$digit| TotalDTMF |$totalDTMF|"; &agi_output;}
return;
}
}
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='';
}
@@ -0,0 +1,265 @@
#!/usr/bin/perl
#
# agi-VDADfixCXFER.agi version 2.6
#
# runs when a Consultative transfer is released by the vicidial fronter as the
# call arrives on another channel so that the vicidial_live_agents record is
# updated to be accurate.
#
# You need to put lines similar to those below in your extensions.conf file:
#
# ;VICIDIAL Consultative Xfer fix script:
# exten => _8600XXX*.,1,AGI(agi-VDADfixCXFER.agi)
# exten => _010*010*010*015*8600XXX*.,1,AGI(agi-VDADfixCXFER.agi)
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG:
# 60809-1749 - First build
# 60817-1122 - Added output options check from database
# 70212-1252 - Fixed issue with Local/ channel transfers on same server
# 130108-1812 - Changes for Asterisk 1.8 compatibility
#
$script = 'agi-VDADfixCXFER.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$SQLdate = "$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 = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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]);
if ($args =~ /--help/i)
{
print "allowed run time options:\n [-q] = quiet\n [-t] = test\n [-debug] = verbose debug messages\n\n";
}
else
{
if ($args =~ /-V/i)
{
$V=1;
}
if ($args =~ /-debug/i)
{
$DG=1;
}
if ($args =~ /-dbAVS/i)
{
$DGA=1;
}
if ($args =~ /-q/i)
{
$q=1;
$Q=1;
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
}
}
$|=1;
while(<STDIN>)
{
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_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
}
# 010*010*011*011*
$extension =~ s/^\d\d\d\*\d\d\d\*\d\d\d\*\d\d\d\*//gi;
@EXTEN = split(/\*/, $extension);
$conf_exten = $EXTEN[0];
$lead_id = $EXTEN[1];
$user = $EXTEN[2];
$phone_code = $EXTEN[3];
$phone_number = $EXTEN[4];
$campaign_id = $EXTEN[5];
if ($AGILOG) {$agi_string = "AGI Environment Dump:"; &agi_output;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|$calleridname|$priority|"; &agi_output;}
if ($AGILOG) {$agi_string = "CXFERfix : $lead_id $user $channel $uniqueid"; &agi_output;}
$CIDlead = sprintf("%010s", $lead_id);
$CIDlead = "C123412345$CIDlead";
print "SET CALLERID $CIDlead\n";
$result = <STDIN>;
checkresult($result);
if ($AGILOG) {$agi_string = "callerID changed: $CIDlead"; &agi_output;}
########## FIND AND UPDATE vicidial_live_agents ##########
$stmtA = "UPDATE vicidial_live_agents SET channel='$channel',call_server_ip='$VARserver_ip',uniqueid='$uniqueid' where user='$user' and lead_id='$lead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_live_agents update: |$affected_rows|$lead_id|"; &agi_output;}
########## INSERT NEW vicidial_auto_calls record ##########
$stmtA = "INSERT INTO vicidial_auto_calls SET channel='$channel',server_ip='$VARserver_ip',uniqueid='$uniqueid',campaign_id='$campaign_id',status='CLOSER',lead_id='$lead_id',phone_code='$phone_code',phone_number='$phone_number',call_time='$SQLdate',call_type='IN',callerid='$CIDlead';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VDAD vicidial_auto_calls insert: |$affected_rows|$lead_id|"; &agi_output;}
$dbhA->disconnect();
if ($AGILOG) {$agi_string = "exiting the CXFERfix app, transferring call to $conf_exten"; &agi_output;}
#print "SET CONTEXT $ext_context\n";
# checkresult($result);
print "SET EXTENSION $conf_exten\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
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='';
}
@@ -0,0 +1,456 @@
#!/usr/bin/perl
#
# NOTE: IT IS RECOMMENDED THAT YOU USE cm_dnc.agi THROUGH A CALL MENU INSTEAD!
#
# agi-VDADinbound_NI_DNC_CIDlookup.agi version 2.0.5 *DBI-version*
#
# runs when a call comes in from an inbound call. This script will
# play a message and take input to automatically change customer lead to NI or DNC.
# *** This version detects inbound callerID over PRI ***
#
# Flag Options:
# 1- default to insert into the vicidial_dnc table for DNC selections (Default=YES)
# 2- campaign to take dnc settings from(overrides option 1)
#
# ;inbound call from outbound CID callbacks from VICIDIAL calls:
#exten => 1234,1,Ringing ; call ringing
#exten => 1234,2,Wait(1) ; Wait 1 second for CID delivery from PRI
#exten => 1234,3,Answer ; Answer the line
#exten => 1234,4,AGI(agi-VDADinbound_NI_DNC_CIDlookup.agi,YES-----TESTCAMP)
#exten => 1234,5,Hangup
#
# Copyright (C) 2015 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 60914-1051 - First draft
# 80909-0614 - Added optional field for campaign so that vicidial_campaign_dnc could be used
# 150928-1822 - Added dnc logging
#
$script = 'agi-VDADinbound_NI_DNC_CIDlookup.agi';
### number of seconds to wait until you drop a waiting call
$DROP_TIME = 360;
### files to play for message of not interested or DNC and your request has been processed
$prompt_file = 'not_interested_or_dnc';
$processed_file = 'request_has_been_processed';
$goodbye_audio_file = 'US_reminder_goodbye';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$start_time=$now_date;
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec";
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$SQLdateBEGIN = $SQLdate;
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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]);
$dnc_default = $ARGV_vars[0];
$campaign_id = $ARGV_vars[1];
}
if (length($dnc_default) < 2)
{$dnc_default = 'YES';}
$|=1;
while(<STDIN>) {
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_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
if (length($calleridname)>0) {$VLcomments = $calleridname;}
else {$VLcomments = '';}
# if ($channel =~ /^SIP/) {$channel =~ s/-.*//gi;}
# if ($channel =~ /^Zap\//) {$channel =~ s/-\d$//gi;}
if (length($callerid)<10) {$callerid = $parked_by;}
if (length($pin)>0) {$callerid = $pin;}
### allow for external callerid to be collected
# if ($extension =~ /\*\d\d\d\d\d\d\d\d\d\d\*/)
# {
# @EXT_vars = split(/\*/, $extension);
#
# $referring_extension = $EXT_vars[0]; # initial extension sent
# $channel_group = $EXT_vars[1]; # name of the parked group
# $inbound_number = $EXT_vars[2]; # extension to send call to after parsing
# $parked_by = $EXT_vars[3]; # leadID
# $park_extension = $EXT_vars[4]; # filename of the on-hold music file
# $comment_d = $EXT_vars[5]; # N/A
# $comment_e = $EXT_vars[6]; # N/A
#
# $PADlead_id = sprintf("%09s", $parked_by); while (length($PADlead_id) > 9) {chop($PADlead_id);}
# # JmmddhhmmssLLLLLLLLL
# $JqueryCID = "J$CIDdate$PADlead_id";
# $callerid = $JqueryCID;
# ### set the callerid to the filename of the audio for on-hold
# print "SET CALLERID $JqueryCID\n";
# checkresult($result);
# print STDERR "callerID changed: $JqueryCID\n";
# }
}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
$AGI->stream_file('beep');
&enter_pin_number;
if ( (length($pin)<1) || ($pin =~ /9/) )
{&enter_pin_number;}
if ( (length($pin)<1) || ($pin =~ /9/) )
{&enter_pin_number;}
if ( (length($pin)<1) || ($pin =~ /9/) )
{&enter_pin_number;}
if ( (length($pin)<1) || ($pin =~ /9/) )
{&enter_pin_number;}
if ($pin =~ /2/) # set the phone_number to NI
{
### Check to see if the number is in the system ###
$stmtA= "SELECT count(*) from vicidial_list where phone_number='$phone_number';";
$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;
$lead_in_system = "$aryA[0]";
$sthA->finish();
### update all records for the phone_number in vicidial_list to NI (Not Interested)
$stmtA = "UPDATE vicidial_list SET status='NI' where phone_number='$phone_number';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
$AGI->stream_file("$processed_file");
}
if ($pin =~ /3/) # set the phone_number to DNC
{
### Check to see if the number is in the system ###
$stmtA= "SELECT count(*) from vicidial_list where phone_number='$phone_number';";
$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;
$lead_in_system = "$aryA[0]";
$sthA->finish();
### update all records for the phone_number in vicidial_list to NI (Not Interested)
$stmtA = "UPDATE vicidial_list SET status='DNC' where phone_number='$phone_number';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
if (length($campaign_id)>1)
{
### Grab DNC settings from campaign
$stmtA = "SELECT use_internal_dnc,use_campaign_dnc FROM vicidial_campaigns where campaign_id = '$campaign_id';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@aryA = $sthA->fetchrow_array;
$use_internal_dnc = "$aryA[0]";
$use_campaign_dnc = "$aryA[1]";
$sthA->finish();
if ($use_internal_dnc =~ /Y/)
{
### add the number to the vicidial_dnc table
$stmtA = "INSERT INTO vicidial_dnc SET phone_number='$phone_number';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
$stmtA="INSERT INTO vicidial_dnc_log SET phone_number='$phone_number', campaign_id='-SYSINT-', action='add', action_date=NOW(), user='OLDAGI';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
if ($use_campaign_dnc =~ /Y/)
{
### add the number to the vicidial_campaign_dnc table
$stmtA = "INSERT INTO vicidial_campaign_dnc SET phone_number='$phone_number',campaign_id='$campaign_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
$stmtA="INSERT INTO vicidial_dnc_log SET phone_number='$phone_number', campaign_id='$campaign_id', action='add', action_date=NOW(), user='OLDAGI';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
}
else
{
if ($dnc_default =~ /YES/)
{
### add the number to the vicidial_dnc table
$stmtA = "INSERT INTO vicidial_dnc SET phone_number='$phone_number';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
}
$AGI->stream_file("$processed_file");
}
$dbhA->disconnect();
$AGI->stream_file("$goodbye_audio_file");
exit;
sub enter_pin_number
{
# if you are not interested in this program press 2
# if you would not like to be contacted by us again press 3
# if you would like us to try to get in contact with you hangup
$interrupt_digit='';
undef $interrupt_digit;
$interrupt_digit = $AGI->stream_file("$prompt_file",'239');
if ($AGILOG) {$agi_string = "interrupt_digit |$interrupt_digit|"; &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=0;
#while ( ($digits_being_entered) && ($digit_loop_counter < 20) )
# {
# $digit = chr($AGI->wait_for_digit('30000')); # wait 30 seconds for input or until the pound key is pressed
# if ($digit =~ /\d/)
# {
# $totalDTMF = "$totalDTMF$digit";
# print STDERR "digit |$digit| TotalDTMF |$totalDTMF|\n";
# $AGI->say_digits("$digit");
# undef $digit;
# }
# else
# {
# $digits_being_entered=0;
# }
#
# $digit_loop_counter++;
# }
#while ( ($digit_loop_counter < 4) )
# {
# $digit = chr($AGI->wait_for_digit('10000')); # wait 10 seconds for input or until the pound 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=4;
# }
#
# $digit_loop_counter++;
# }
$totalDTMF =~ s/\D//gi;
$pin = $totalDTMF;
if ($totalDTMF) {if ($AGILOG) {$agi_string = "digit |$digit| TotalDTMF |$totalDTMF|"; &agi_output;}}
}
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='';
}
@@ -0,0 +1,293 @@
#!/usr/bin/perl
#
# agi-VDADlisten_DTMF.agi version 2.0.5 *DBI-version*
#
# To be initiated by an agent so during a call. Agent will click a PIN NUMBER
# link on a web form webpage that will Originate a new call to this script
#
# This script plays a beep and waits for entry of 4 digits then inserts record
#
# ***** THIS SCRIPT ONLY WORKS WITH A CROSSOVER T1 CABLE FROM ONE T1 PORT *****
# ***** TO ANOTHER T1 PORT WHETHER ON THE SAME SERVER OR DIFFERENT ONE *****
#
# IN THE CAMPAIGN OR IN-GROUP NUMBER PRESET FIELD:
# AXFER83009
#
# ON THE SERVER ORIGINATING THE CALL:
#;outbound DTMF VICIDIAL calls:
#exten => _983009.,1,AGI(call_log.agi,${EXTEN})
#exten => _983009.,2,Dial(${TRUNKY}/${EXTEN:1},60)
#exten => _983009.,3,Hangup
#
# ON THE SERVER THAT HAS THIS SCRIPT:
#;inbound DTMF VICIDIAL calls:
#exten => _83009.,1,AGI(agi-VDADlisten_DTMF.agi,${EXTEN})
#exten => _83009.,2,Hangup
#
# Copyright (C) 2008 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 60206-1434 first build
# 60207-1205 - added database records entries/modifications
# 60207-1507 - added ability to send AMs to campaign-defined message to leave
# 60731-1536 - changed to use DBI-DBD::mysql
# - changed to use /etc/astguiclient.conf for configs
# 60817-1113 - added output options check from database
# 70806-1619 - added HeavyDTMF check and filter
#
$script = 'agi-VDADlisten_DTMF.agi';
$heavyDTMFcheck = 1; # set to 1 to check for heavy DTMF double-tones
### set defaults for testing
$referring_extension = '83009';
$phone_number = '9999999999';
$lead_id = '999999999';
$campaign_id = 'TESTCAMP';
$product_code = 'ABC';
$user = '1234';
$pin = '0';
($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";}
$SQLdate = "$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 = <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 Time::HiRes qw(gettimeofday);
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n [-q] = quiet\n [-t] = test\n [-debug] = verbose debug messages\n\n";
}
else
{
if ($args =~ /-V/i)
{
$V=1;
}
if ($args =~ /-debug/i)
{
$DG=1;
}
if ($args =~ /-q/i)
{
$q=1;
$Q=1;
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
}
}
$|=1;
while(<STDIN>) {
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
### allow for internal transfer data string "83009*3125551212*10000123*TESTCAMP*ABC*1234*"
if ($extension =~ /^8300\d\*/)
{
@EXT_vars = split(/\*/, $extension);
$referring_extension = $EXT_vars[0]; # initial extension sent
$phone_number = $EXT_vars[1]; # phone number
$lead_id = $EXT_vars[2]; # lead_id in vicidial_list
$campaign_id = $EXT_vars[3]; # campaign id
$product_code = $EXT_vars[4]; # product code
$user = $EXT_vars[5]; # vicidial_user that sent the call here
}
}
if ($AGILOG) {$agi_string = "INBOUND DTMF CALL VDCL STARTED"; &agi_output;}
&enter_pin_number;
if (length($pin) < 4) {$AGI->stream_file('buzz');}
else {$AGI->stream_file('ding');}
### insert a record into the vicidial_list_pins table
$stmtA = "INSERT INTO vicidial_list_pins (entry_time,phone_number,lead_id,campaign_id,product_code,user,digits) values('$SQLdate','$phone_number','$lead_id','$campaign_id','$product_code','$user','$pin');";
$affected_rows = $dbhA->do($stmtA);
$insert_pin_id = $dbhA->{'mysql_insertid'};
if ($AGILOG) {$agi_string = "|$stmtA|$insert_pin_id|$affected_rows|"; &agi_output;}
$dbhA->disconnect();
exit;
sub enter_pin_number
{
$lastdigit='';
$lastdigittime='';
$AGI->stream_file('beep');
while ( ($digit_loop_counter < 4) )
{
$digit = chr($AGI->wait_for_digit('30000')); # wait 30 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
# get seconds and microseconds since the epoch
($s, $usec) = gettimeofday();
$Susec = sprintf("%06s", $usec);
$utime = "$s$Susec";
if (length($lastdigittime)<1) {$lastdigittime = $utime; $lastdigit = 99; $difftime = 0;}
else
{
$difftime = ($utime - $lastdigittime);
}
print STDERR "$s$Susec - $digit - $lastdigittime - $difftime\n";
if ( ($difftime < 200000) && ($digit == $lastdigit) && ($heavyDTMFcheck>0) )
{
print STDERR "HEAVY DTMF DETECTED AND IGNORED: $digit - $lastdigit - $difftime\n";
$digit_loop_counter = ($digit_loop_counter - 1);
}
else
{
$totalDTMF = "$totalDTMF$digit";
if ($AGILOG) {$agi_string = "digit |$digit| TotalDTMF |$totalDTMF|"; &agi_output;}
# $AGI->say_digits("$digit");
}
$lastdigittime = $utime; $lastdigit = $digit;
undef $digit;
}
else
{
$digit_loop_counter=4;
}
$digit_loop_counter++;
}
$totalDTMF =~ s/\D//gi;
$pin = $totalDTMF;
if ($totalDTMF)
{
if ($AGILOG) {$agi_string = "digit |$digit| TotalDTMF |$totalDTMF|"; &agi_output;}
}
# $AGI->say_digits("$pin");
}
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='';
}
@@ -0,0 +1,175 @@
#!/usr/bin/perl
#
# agi-VDADselective_CID.agi version 0.1 *NO DB Connection*
#
# Runs before a call is placed outbound to filter outgoing callerIDnumber
#
# You need to put lines similar to those below in your extensions.conf file:
#
# ;outbound VICIDIAL calls:
#exten => _91NXXNXXXXXX,1,AGI(call_log.agi,${EXTEN})
#exten => _91NXXNXXXXXX,2,AGI(agi-VDADselective_CID.agi,${EXTEN})
#exten => _91NXXNXXXXXX,3,Dial(${TRUNKX}/${EXTEN:1},55,tTo)
#exten => _91NXXNXXXXXX,4,Hangup
#
# Copyright (C) 2008 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 60918-1042 - First build
# 71012-1239 - changed method for getting areacode
#
$script = 'agi-VDADselective_CID.agi';
$AGILOG=0;
$FD=0; # force debug for testing
# CLEAR AREA CODE LISTINGS:
# Florida: 239|305|321|352|386|407|561|689|727|754|772|786|813|836|850|861|863|904|941|954
$clear_area_codes = '239|305|321|352|386|407|561|689|727|754|772|786|813|836|850|861|863|904|941|954';
($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";
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
### 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++;
}
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
if (length($calleridname)>0) {$VLcomments = $calleridname;}
else {$VLcomments = '';}
}
$areacode = substr($extension, -10, 3);
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($areacode !~ /$clear_area_codes/)
{
if ( (length($callerid)>20) && ($callerid =~ /\"\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S/) )
{
$calleridname =~ s/^\"//gi;
$calleridname =~ s/\".*$//gi;
}
### set the callerid to the ACQS value(calleridname)
## use these two lines for Asterisk 1.2 tree
$newcallerid = "\"$calleridname <0000000000>\"";
$AGI->set_callerid($newcallerid);
## use these two lines for Asterisk 1.0 tree
# print "SET CALLERID \"$calleridname\" <0000000000>\n";
# print "SET CALLERIDNAME \"$calleridname\"\n";
print STDERR "Setting CID \"$newcallerid\"\n";
checkresult($result);
if ($AGILOG) {$agi_string = "callerID changed: \"$calleridname\" \<0000000000\>"; &agi_output;}
if ($FD > 0) {print STDERR "callerID changed: \"$calleridname\" \<0000000000\> |$areacode|\n";}
}
else
{
if ($FD > 0) {print STDERR "callerID NOT changed: \"$calleridname\" <$callerid> |$areacode|\n";}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$extension|$areacode|$callerid|$calleridname|"; &agi_output;}
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='';
}
@@ -0,0 +1,231 @@
#!/usr/bin/perl
#
# agi-VDADselective_CID_hangup.agi version 2.6
#
# Will hangup a call if it is not within the specified area codes
#
# You need to put lines similar to those below in your extensions.conf file:
#
# ;outbound VICIDIAL calls:
#exten => 8352,1,AGI(agi-VDADselective_CID_hangup.agi,${EXTEN})
#exten => 8352,2,Playback(85100001)
#exten => 8352,3,Hangup
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 60918-1151 - First build
# 100903-0041 - Changed lead_id max length to 10 digits
# 130108-1813 - Changes for Asterisk 1.8 compatibility
#
$script = 'agi-VDADselective_CID_hangup.agi';
$AGILOG=1;
# CLEAR AREA CODE LISTINGS:
# Florida: 239|305|321|352|386|407|561|689|727|754|772|786|813|836|850|861|863|904|941|954
$clear_area_codes = '239|305|321|352|386|407|561|689|727|754|772|786|813|836|850|861|863|904|941|954';
($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 = <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;
### 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++;
}
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
}
$CIDlead_id = $calleridname;
$CIDlead_id = substr($CIDlead_id, 10, 10);
$CIDlead_id = ($CIDlead_id + 0);
$stmtA = "SELECT phone_number FROM vicidial_list where lead_id = '$CIDlead_id' limit 1;";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$phone_number = "$aryA[0]";
$rec_count++;
}
$sthA->finish();
$areacode = $phone_number;
if (length($areacode) > 10)
{
$areacode =~ s/^91|^991|^981|^971|^961|^951//gi;
$areacode =~ s/^1//gi;
}
$areacode =~ s/\d\d\d\d\d\d\d$//gi;
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($areacode !~ /$clear_area_codes/)
{
print "SET HANGUP $channel\n";
$result = <STDIN>;
checkresult($result);
if ($AGILOG) {$agi_string = "channel Hungup: $channel"; &agi_output;}
print "SET EXTENSION $extension\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 3\n";
$result = <STDIN>;
checkresult($result);
}
if ($AGILOG) {$agi_string = "AGI Variables: |$extension|$areacode|$phone_number|$callerid|$calleridname|$channel|"; &agi_output;}
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='';
}
+159
View File
@@ -0,0 +1,159 @@
#!/usr/bin/perl
#
# agi-dtmf.agi - script for playing DTMF tones or signals received as the callerid field or in the command CLI
#
# DTMF sound files must be in /var/lib/asterisk/sounds for this to work
#
# Accepted values are: 1 2 3 4 5 6 7 8 9 0 # * ,
# comma means pause for 1 second (use 'S' for pause in CLI mode)
#
# exten => 8500998,1,Answer
# exten => 8500998,2,Playback(silence)
# exten => 8500998,3,AGI(agi-dtmf.agi)
#; exten => 8500998,3,AGI(agi-dtmf.agi,signalonly) ; optional signal only DTMF
# exten => 8500998,4,Hangup
#
# Can also be used in a Call Menu: agi-dtmf.agi,signalonly---12345 # optional signal only DTMF with CLI-defined DTMF values
#
# Copyright (C) 2014 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGES
# 90312-1534 - Added signalonly option
# 140611-1330 - Added CLI dtmf variable option
#
$signalonly=0;
$cli_vars_set=0;
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
### list of command-line array arguments:
@ARGV_vars = split(/---/, $ARGV[0]);
$signalonly = $ARGV_vars[0];
$cli_vars = $ARGV_vars[1];
}
if ($signalonly =~ /signalonly/)
{$signalonly=1;}
if (length($cli_vars) > 0)
{$cli_vars_set=1;}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if (/^agi_(\w+)\:\s+(.*)$/)
{$AGI{$1} = $2;}
if (/^agi_callerid\:\s+(.*)$/) {$caller_id = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$caller_idname = $1;}
}
print STDERR "AGI Environment Dump:\n";
foreach $i (sort keys %AGI) {
print STDERR " -- $i = $AGI{$i}\n";
}
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use Asterisk::AGI;
my $agi = new Asterisk::AGI;
my $clid = $agi->get_variable('CALLERID');
my $clidname = $agi->get_variable('CALLERIDNAME');
print STDERR "X. |$clid|$caller_id|$clidname| |$signalonly|$cli_vars_set|$cli_vars|\n";
### sleep for 5 tenths of a second
usleep(1*500*1000);
print "STREAM FILE silence \"\"\n";
$caller_id = "$caller_id$caller_idname";
if ($cli_vars_set > 0)
{$caller_id = $cli_vars;}
@CALLERID_DIGITS = split(//, $caller_id);
foreach (@CALLERID_DIGITS)
{
if ($CALLERID_DIGITS[$g] =~ /\d/)
{
if ($signalonly > 0)
{print "EXEC SendDTMF $CALLERID_DIGITS[$g] \"\"\n";}
else
{print "STREAM FILE $CALLERID_DIGITS[$g] \"\"\n";}
print STDERR "DIGIT: $CALLERID_DIGITS[$g]\n";
}
else
{
if ($CALLERID_DIGITS[$g] =~ /\#/)
{
if ($signalonly > 0)
{print "EXEC SendDTMF \# \"\"\n";}
else
{print "STREAM FILE hash \"\"\n";}
}
if ($CALLERID_DIGITS[$g] =~ /\*/)
{
if ($signalonly > 0)
{print "EXEC SendDTMF \* \"\"\n";}
else
{print "STREAM FILE star \"\"\n";}
}
if ($CALLERID_DIGITS[$g] =~ /\,|S/)
{sleep(1);}
print STDERR "NON-DIGIT: $CALLERID_DIGITS[$g]\n";
}
$g++;
### sleep for 20 hundredths of a second
usleep(1*150*1000);
print "STREAM FILE silence \"\"\n";
### sleep for 10 hundredths of a second
usleep(1*100*1000);
}
print "STREAM FILE silence \"\"\n";
$result = <STDIN>;
checkresult($result);
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++;
}
}
@@ -0,0 +1,544 @@
#!/usr/bin/perl
#
# agi-phone_monitor.agi version 2.8
#
# This script is designed to allow managers to listen to agent sessions by
# dialing a phone exten number or user ID number. For this to work, the user ID
# or phone extension must be only digits. If you are using the phone extension,
# then all phone extensions on the system must be unique.
#
# user is prompted for a user ID or phone login then press #
# then the user is forwarded to monitor the active vicidial agent session
#
# ; settings for this script:
# ; 1. USER, PHONE or PLOGIN, lookup by user id, phone extension or phone login (default is USER)
# ; 2. Y or N, log in api log (default is N)
# ; 3. BARGE or LISTEN, (default is LISTEN)
# ; 4. Prepopulated ID, for use in context by itself
#
# can be added as an AGI to a Call Menu, or just a direct extension transfer:
#
# ; call menu AGI with options:
# agi-phone_monitor.agi,USER---N---LISTEN---
#
# ; or as extension transfer to "up_monitor_exit" context and "s" extension
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 130401-0724 - First build
# 130520-1013 - Added PLOGIN lookup option and no-prompt extension feature
# 130710-1658 - Small change to allow non-hangup between agent calls
# 130925-1824 - Added variable filter to prevent DID SQL injection attack
#
&get_time_now;
$start_epoch = $now_date_epoch;
$script = 'agi-phone_monitor.agi';
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
($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";}
$US='_';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ 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/phone_monitor.$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;
### 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]);
$user_phone = $ARGV_vars[0];
$api_log = $ARGV_vars[1];
$barge_listen = $ARGV_vars[2];
$prepop_id = $ARGV_vars[3];
}
if ( (length($user_phone) < 1) || ($user_phone !~ /USER|PHONE|PLOGIN/) )
{$user_phone = 'USER';}
if ( (length($api_log) < 1) || ($api_log !~ /Y|N/) )
{$api_log = 'N';}
if ( (length($barge_listen) < 1) || ($barge_listen !~ /BARGE|LISTEN/) )
{$barge_listen = 'LISTEN';}
### END parsing run-time options ###
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($V)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
$callerid =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$calleridname =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$extension =~ s/\'|\"|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
$phone_number=$callerid;
### Grab Server values from the database
$stmtA = "SELECT ext_context,agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$DBext_context = $aryA[0];
$DBagi_output = $aryA[1];
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';}
$rec_count++;
}
$sthA->finish();
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$entry_chances=0;
$VALID_login=0;
$ACTIVE_login=0;
$VDADremDIALstr='';
while ( ($entry_chances < 3) && ($VALID_login < 1) )
{
$entry_chances++;
if (length($prepop_id)<2)
{
&user_phone_gather;
}
else
{$PIN_number = $prepop_id;}
###### Check userID and password against vicidial_users table
$stmtA = "SELECT count(*) FROM vicidial_users where user='$PIN_number' and active='Y';";
if ($user_phone =~ /PHONE/)
{$stmtA = "SELECT count(*) FROM phones where extension='$PIN_number' and active='Y';";}
if ($user_phone =~ /PLOGIN/)
{$stmtA = "SELECT count(*) FROM phones where login='$PIN_number' and active='Y';";}
$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;
$VALID_login = $aryA[0];
}
$sthA->finish();
if ($VALID_login > 0)
{
$AGI->stream_file('pin-number-accepted');
}
else
{
if ($api_log =~ /Y/)
{
$stmtA="INSERT INTO vicidial_api_log set user='$calleridname',agent_user='$PIN_number',function='phone_monitor',value='',result='ERROR',result_reason='No user found',source='monitor',data='$calleridname|$callerid',api_date='$now_date',api_script='$script',run_time='0';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "API LOG INSERT $affected_rows|$stmtA|"; &agi_output;}
}
$AGI->stream_file('pin-invalid');
}
}
if ($VALID_login < 1)
{
if ($AGILOG) {$agi_string = "PHONE MONITOR END: Invalid Login |$VALID_login|$PIN_number|"; &agi_output;}
if ($use_call_menu =~ /Y/)
{
if ($AGILOG) {$agi_string = "exiting the agent dial-in app, transferring call to B @ $context"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION B\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
}
else
{
$AGI->stream_file('vm-goodbye');
$AGI->hangup();
$dbhA->disconnect();
}
exit;
}
else
{
$secX = time();
$PDtarget = ($secX - 30);
($Psec,$Pmin,$Phour,$Pmday,$Pmon,$Pyear,$Pwday,$Pyday,$Pisdst) = localtime($PDtarget);
$Pyear = ($Pyear + 1900);
$Pmon++;
if ($Pmon < 10) {$Pmon = "0$Pmon";}
if ($Pmday < 10) {$Pmday = "0$Pmday";}
if ($Phour < 10) {$Phour = "0$Phour";}
if ($Pmin < 10) {$Pmin = "0$Pmin";}
if ($Psec < 10) {$Psec = "0$Psec";}
$PDtsSQLdate = "$Pyear$Pmon$Pmday$Phour$Pmin$Psec";
###### Check if user is logged in, vicidial_live_agents table
$stmtA = "SELECT count(*) FROM vicidial_live_agents where user='$PIN_number' and last_update_time > \"$PDtsSQLdate\";";
if ($user_phone =~ /PHONE/)
{$stmtA = "SELECT count(*) FROM vicidial_live_agents where extension LIKE \"%/$PIN_number\" and last_update_time > \"$PDtsSQLdate\";";}
if ($user_phone =~ /PLOGIN/)
{
$PLOGIN_extension='XXXXXXXXXXXXXXXXXX';
$PLOGIN_server_ip='1.1.1.1';
$stmtA = "SELECT extension,server_ip FROM phones where login='$PIN_number' and active='Y';";
$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;
$PLOGIN_extension = $aryA[0];
$PLOGIN_server_ip = $aryA[1];
}
$sthA->finish();
if ($AGILOG) {$agi_string = "PLOGIN DEBUG: |$PLOGIN_extension|$PLOGIN_server_ip|$stmtA|"; &agi_output;}
$stmtA = "SELECT count(*) FROM vicidial_live_agents where extension LIKE \"%/$PLOGIN_extension\" and server_ip='$PLOGIN_server_ip' and last_update_time > \"$PDtsSQLdate\";";
}
$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;
$ACTIVE_login = "$aryA[0]";
}
$sthA->finish();
if ($ACTIVE_login < 1)
{
if ($AGILOG) {$agi_string = "PHONE MONIOR END: Inactive Login |$VALID_login|$PIN_number|$PASS_word| |$ACTIVE_login|$PDtsSQLdate|$stmtA|"; &agi_output;}
if ($api_log =~ /Y/)
{
$stmtA="INSERT INTO vicidial_api_log set user='$calleridname',agent_user='$PIN_number',function='phone_monitor',value='',result='ERROR',result_reason='Inactive Login',source='monitor',data='$calleridname|$callerid',api_date='$now_date',api_script='$script',run_time='0';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "API LOG INSERT $affected_rows|$stmtA|"; &agi_output;}
}
$AGI->stream_file('login-fail');
$AGI->stream_file('vm-goodbye');
$AGI->hangup();
$dbhA->disconnect();
exit;
}
else
{
$stmtA = "SELECT conf_exten,extension,server_ip from vicidial_live_agents WHERE user='$PIN_number' and last_update_time > \"$PDtsSQLdate\" limit 1;";
if ($user_phone =~ /PHONE/)
{$stmtA = "SELECT conf_exten,extension,server_ip FROM vicidial_live_agents where extension LIKE \"%/$PIN_number\" and last_update_time > \"$PDtsSQLdate\" limit 1;";}
if ($user_phone =~ /PLOGIN/)
{
$PLOGIN_extension='XXXXXXXXXXXXXXXXXX';
$PLOGIN_server_ip='1.1.1.1';
$stmtA = "SELECT extension,server_ip FROM phones where login='$PIN_number' and active='Y';";
$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;
$PLOGIN_extension = $aryA[0];
$PLOGIN_server_ip = $aryA[1];
}
$sthA->finish();
$stmtA = "SELECT conf_exten,extension,server_ip FROM vicidial_live_agents where extension LIKE \"%/$PLOGIN_extension\" and server_ip='$PLOGIN_server_ip' and last_update_time > \"$PDtsSQLdate\" limit 1;";
}
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_countCUSTDATA=0;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$VDADconf_exten = $aryA[0];
$VDADextension = $aryA[1];
$VDADserver_ip = $aryA[2];
}
$sthA->finish();
### format the remote server dialstring to get the call to the overflow agent meetme room
$S='*';
if( $VDADserver_ip =~ m/(\S+)\.(\S+)\.(\S+)\.(\S+)/ )
{
$a = leading_zero($1);
$b = leading_zero($2);
$c = leading_zero($3);
$d = leading_zero($4);
# use double-star prefix to go through native bridge IAX path
$VDADremDIALstr = "$S$S$a$S$b$S$c$S$d$S";
}
$barge_listen_prefix = '58';
if($barge_listen =~ /BARGE/)
{$barge_listen_prefix = '59';}
$VDADremDIALstr .= "$barge_listen_prefix$VDADconf_exten";
if ($api_log =~ /Y/)
{
$stmtA="INSERT INTO vicidial_api_log set user='$calleridname',agent_user='$PIN_number',function='phone_monitor',value='',result='SUCCESS',result_reason='',source='monitor',data='$VDADconf_exten|$VDADextension|$VDADserver_ip|$calleridname|$callerid',api_date='$now_date',api_script='$script',run_time='0';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "API LOG INSERT $affected_rows|$stmtA|"; &agi_output;}
}
if ($AGILOG) {$agi_string = "Agent $PIN_number sent to $VDADremDIALstr"; &agi_output;}
print "SET CONTEXT $ext_context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $VDADremDIALstr\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
}
}
$dbhA->disconnect();
exit;
################################################################################
##### SUBROUTINES ##############################################################
################################################################################
##### BEGIN collect the user and password ######################################
sub user_phone_gather
{
################################################################################
# please enter the pin number followed by the pound key
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file('ld_welcome_pin_number','0123456789');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$PIN_number='';
if ($interrupt_digit > 0)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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;}
$PIN_number=$interrupt_digit;
}
$digit_loop_counter=0;
while ( ($digits_being_entered > 0) && ($digit_loop_counter < 20) )
{
$digit = chr($AGI->wait_for_digit('10000')); # wait 10 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
$PIN_number = "$PIN_number$digit";
print STDERR "digit |$digit| PIN_number |$PIN_number|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digits_being_entered=0;
}
$digit_loop_counter++;
}
$PIN_number =~ s/\D//gi;
if ($PIN_number) {print STDERR "digit |$digit| PIN_number |$PIN_number|\n";}
}
##### END collect the user and password ###############################################
sub get_time_now #get the current date and time and epoch for logging call lengths and datetimes
{
($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";
$filedate = "$year$mon$mday$hour$min$sec";
}
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='';
}
sub leading_zero($)
{
$_ = $_[0];
s/^(\d)$/0$1/;
s/^(\d\d)$/0$1/;
return $_;
} # End of the leading_zero() routine.
@@ -0,0 +1,539 @@
#!/usr/bin/perl
#
# agi-record_prompts.agi version 2.12
#
# for recording prompts to GSM file over the phone
# Saves recordings with 8-digit filenames to be played when exten is dialed
#
# ; prompts for recording AGI script, ID is 4321
# ; first variable is format (gsm/wav)
# ; second variable is timeout in milliseconds (default is 360000 [6 minutes])
# exten => 8167,1,Answer
# exten => 8167,2,AGI(agi-record_prompts.agi,wav-----360000)
# exten => 8167,3,Hangup
# exten => 8168,1,Answer
# exten => 8168,2,AGI(agi-record_prompts.agi,gsm-----360000)
# exten => 8168,3,Hangup
#
# ; playback of recorded prompts
# exten => _851XXXXX,1,Answer
# exten => _851XXXXX,2,Playback(${EXTEN})
# exten => _851XXXXX,3,Hangup
#
# GSM Sound Files used:
# - ld_welcome_pin_number
# - ld_invalid_pin_number
# - vm-rec-generic
# - auth-thankyou
# - vm-review
# - vm-msgsaved
# - vm-goodbye
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 71226-1303 - Added option to change format GSM/WAV and timeout through flags
# 90519-1019 - Changed formatting to conform to other scripts
# 130108-1815 - Changes for Asterisk 1.8 compatibility
# 161029-2239 - Changed to database storage for prompt count
#
$script = 'agi-record_prompts.agi';
&get_time_now;
$US='_';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
### list of command-line array arguments:
@ARGV_vars = split(/-----/, $ARGV[0]);
$format = $ARGV_vars[0];
$timeout = $ARGV_vars[1];
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($V)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1;}
}
if ($format =~ /WAV/i) {$format = 'wav';}
else {$format = 'gsm';}
if ($timeout < 1) {$timeout = 360000;} # default is 6 minutes
$unique_id_out = $unique_id;
@NEW_ID = split(/\./, $unique_id_out);
$NEW_ID_DIF = '.0';
$unique_id_out = "$NEW_ID[0]$NEW_ID_DIF$NEW_ID[1]";
$pin='';
$stop_loop=0;
$quit_program=0;
$loop_counter=0;
$REC_id = 85100000;
$REC_next = 0;
$rec_prompt_count=1;
$rec_prompt_count_next=0;
### Gather current rec_prompt_count from system_settings ###
$stmtA= "SELECT rec_prompt_count from system_settings;";
$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;
$rec_prompt_count = $aryA[0];
$rec_prompt_count_next = ($rec_prompt_count + 1);
}
$sthA->finish();
if (-e "/prompt_count.txt")
{
open(test, "/prompt_count.txt") || die "can't open /prompt_count.txt: $!\n";
@test = <test>;
close(test);
$test[0] = ($test[0] + 0);
if ($rec_prompt_count > $test[0])
{$test[0] = $rec_prompt_count;}
if ($rec_prompt_count < $test[0])
{
$rec_prompt_count = $test[0];
### update the rec_prompt_count in system_settings
$stmtA = "UPDATE system_settings SET rec_prompt_count='$rec_prompt_count';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
$REC_next = ($test[0] + 1);
$REC_id = ($REC_id + $REC_next);
}
else
{
open(test, ">/prompt_count.txt") || die "can't open /prompt_count.txt: $!\n";
print test "$rec_prompt_count";
close(test);
$REC_id = ($REC_id + $rec_prompt_count);
}
$session_recording = "$REC_id";
print STDERR "Recording ID: $REC_id\n";
&welcome_1;
print STDERR "DONE Exiting...\n";
exit;
##### SUBROUTINES ########################################################
##### steps ########################################################
sub welcome_1
{
##### Play welcome message and capture PIN ########################################################
while ( (length($pin) ne 4) && (!$stop_loop) )
{
&enter_pin_number;
&log_transfer;
$loop_counter++;
if ($loop_counter > 3) {$stop_loop++; $quit_program++;}
print STDERR "\nPIN|$pin|\n";
}
##### Check PIN account in database ########################################################
$rec_count=0;
&lookup_account;
if (!$rec_count)
{
# please enter the pin number followed by the pound key
$AGI->stream_file('ld_invalid_pin_number');
$quit_program++;
}
##### quit program if error ########################################################
if ($quit_program)
{
print STDERR "\nexiting the ping app\n";
print "SET CONTEXT demo\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION 8158\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 3\n";
$result = <STDIN>;
checkresult($result);
exit;
}
### update the rec_prompt_count in system_settings
$stmtA = "UPDATE system_settings SET rec_prompt_count='$REC_next';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
open(test, ">/prompt_count.txt") || die "can't open /prompt_count.txt: $!\n";
print test "$REC_next";
close(test);
&record_prompts;
}
sub record_prompts
{
$AGI->stream_file('beep');
print STDERR "\nrecord_prompts AGI welcome\n";
$AGI->stream_file('vm-rec-generic');
$AGI->stream_file('beep');
$digit='';
$interrupt_digit='';
$interrupt_digit = $AGI->record_file("$session_recording", "$format", '123456789*#', "$timeout", 1);
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$digit_loop_counter=0;
$totalDTMF='';
if ($interrupt_digit > 1)
{
if ($interrupt_digit == 35) {$interrupt_digit='#';}
if ($interrupt_digit == 42) {$interrupt_digit='*';}
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++;
}
$AGI->stream_file('beep');
if (length($totalDTMF) > 0) {print STDERR "digit |$digit| TotalDTMF |$totalDTMF|\n";}
&verify_recording;
}
sub verify_recording
{
$digit='';
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file('vm-review','123456789');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$digit_loop_counter=0;
$totalDTMF='';
if ($interrupt_digit > 1)
{
if ($interrupt_digit == 35) {$interrupt_digit='#';}
if ($interrupt_digit == 42) {$interrupt_digit='*';}
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 < 1)
{
$digit = chr($AGI->wait_for_digit('2000000')); # wait 0.2 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
$totalDTMF = "$totalDTMF$digit";
print STDERR "digit |$digit| TotalDTMF |$totalDTMF|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digit_loop_counter=1;
}
$digit_loop_counter++;
}
$totalDTMF =~ s/\D//gi;
$pin = $totalDTMF;
if (length($pin)< 1)
{
&verify_recording;
}
else
{
if ($pin == '1')
{
$AGI->stream_file('auth-thankyou');
$AGI->say_digits("$REC_id");
$AGI->stream_file('beep');
$AGI->say_digits("$REC_id");
$AGI->stream_file('vm-goodbye');
$AGI->stream_file('silence');
exit;
}
if ($pin == '2')
{
$AGI->stream_file("$session_recording");
&verify_recording;
}
if ($pin == '3')
{
&record_prompts;
}
}
}
##### SUBROUTINES PROCESSES ########################################################
sub log_transfer
{
# nothing
}
sub lookup_account
{
if ($pin eq '4321')
{
$rec_count++;
}
}
sub get_time_now #get the current date and time and epoch for logging call lengths and datetimes
{
($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";
}
sub enter_pin_number
{
# please enter the pin number followed by the pound key
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$interrupt_digit='';
$interrupt_digit = $AGI->stream_file('ld_welcome_pin_number','123456789');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$totalDTMF='';
if ($interrupt_digit > 0)
{
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=0;
while ( ($digits_being_entered) && ($digit_loop_counter < 20) )
{
$digit = chr($AGI->wait_for_digit('90000')); # wait 90 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
$totalDTMF = "$totalDTMF$digit";
print STDERR "digit |$digit| TotalDTMF |$totalDTMF|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digits_being_entered=0;
}
$digit_loop_counter++;
}
$totalDTMF =~ s/\D//gi;
$pin = $totalDTMF;
if ($totalDTMF) {print STDERR "digit |$digit| TotalDTMF |$totalDTMF|\n";}
}
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='';
}
@@ -0,0 +1,400 @@
#!/usr/bin/perl
#
# agi-set_variables.agi version 2.10
#
# runs after a call_log before call is placed out the trunk and sets all
# vicidial_list fields as variables for the call
#
# You need to put lines similar to those below in your extensions.conf file:
#
# ; VICIDIAL_auto_dialer transfer script AMD with Load Balanced:
# exten => _91NXXNXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log)
# exten => _91NXXNXXXXXX,n,AGI(agi-set_variables.agi,)
# exten => _91NXXNXXXXXX,n,Dial(${TESTSIPTRUNK}/${EXTEN:2},,tTor)
# exten => _91NXXNXXXXXX,n,Hangup
#
# Copyright (C) 2014 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 101118-1409 - First build
# 101125-2115 - Added parsing for 3-way calls
# 110404-1604 - Added dial_timeout and cpd_amd_action variables
# 141211-1643 - Added cpd_unknown_action
#
$script = 'agi-set_variables.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
}
$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(<STDIN>)
{
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/) ) or ( (length($calleridname)>17) && ($calleridname =~ /\d\d\d\d\d\dW\d\d\d\d\d\d\d\d\d\dW$/) ) )
{
$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;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
$VDADcampaign='';
$VDADphone='';
$VDADphone_code='';
$auto_dial_timeout='60';
$cpd_amd_action='DISABLED';
$cpd_unknown_action='DISABLED';
$callerid =~ s/\"//gi;
$callerid =~ s/ .*//gi;
$CIDlead_id = $callerid;
if ($CIDlead_id =~ /W\d\d\d\d\d\d\d\d\d\dW$/)
{
@CIDlead_id_array = split(/W/, $CIDlead_id);
$CIDlead_id = $CIDlead_id_array[1];
}
else
{
$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 = "+++++ VARIABLE SET START : |$CIDlead_id|$now_date|$AST_ver|$priority|$calleridname|"; &agi_output;}
########## FIND vicidial_auto_calls record ##########
$stmtA = "SELECT campaign_id,phone_number FROM vicidial_auto_calls where callerid='$callerid' order by auto_call_id 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;
$campaign_id = $aryA[0];
$dialed_number = $aryA[1];
$sthA->finish();
}
$stmtA = "SELECT dial_timeout,cpd_amd_action,cpd_unknown_action FROM vicidial_campaigns where campaign_id='$campaign_id' 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;
$auto_dial_timeout = $aryA[0];
# only set if auto-dial call
if ($callerid =~ /^V/)
{
$cpd_amd_action = $aryA[1];
$cpd_unknown_action = $aryA[2];
}
$sthA->finish();
}
$stmtA = "SELECT lead_id,entry_date,modify_date,status,user,vendor_lead_code,source_id,list_id,phone_number,title,first_name,middle_initial,last_name,address1,address2,address3,city,state,province,postal_code,country_code,gender,date_of_birth,alt_phone,email,security_phrase,comments,called_count,last_local_call_time,rank,owner FROM vicidial_list where lead_id='$VD_lead_id';";
$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;
$lead_id = $aryA[0];
$entry_date = $aryA[1];
$modify_date = $aryA[2];
$status = $aryA[3];
$user = $aryA[4];
$vendor_lead_code = $aryA[5];
$source_id = $aryA[6];
$list_id = $aryA[7];
$phone_number = $aryA[8];
$title = $aryA[9];
$first_name = $aryA[10];
$middle_initial = $aryA[11];
$last_name = $aryA[12];
$address1 = $aryA[13];
$address2 = $aryA[14];
$address3 = $aryA[15];
$city = $aryA[16];
$state = $aryA[17];
$province = $aryA[18];
$postal_code = $aryA[19];
$country_code = $aryA[20];
$gender = $aryA[21];
$date_of_birth = $aryA[22];
$alt_phone = $aryA[23];
$email = $aryA[24];
$security_phrase = $aryA[25];
$comments = $aryA[26];
$called_count = $aryA[27];
$last_local_call_time = $aryA[28];
$rank = $aryA[29];
$owner = $aryA[30];
}
$sthA->finish();
$lead_id =~ s/ /+/gi;
$entry_date =~ s/ /+/gi;
$modify_date =~ s/ /+/gi;
$status =~ s/ /+/gi;
$user =~ s/ /+/gi;
$vendor_lead_code =~ s/ /+/gi;
$source_id =~ s/ /+/gi;
$list_id =~ s/ /+/gi;
$phone_number =~ s/ /+/gi;
$title =~ s/ /+/gi;
$first_name =~ s/ /+/gi;
$middle_initial =~ s/ /+/gi;
$last_name =~ s/ /+/gi;
$address1 =~ s/ /+/gi;
$address2 =~ s/ /+/gi;
$address3 =~ s/ /+/gi;
$city =~ s/ /+/gi;
$state =~ s/ /+/gi;
$province =~ s/ /+/gi;
$postal_code =~ s/ /+/gi;
$country_code =~ s/ /+/gi;
$gender =~ s/ /+/gi;
$date_of_birth =~ s/ /+/gi;
$alt_phone =~ s/ /+/gi;
$email =~ s/ /+/gi;
$security_phrase =~ s/ /+/gi;
$comments =~ s/ /+/gi;
$called_count =~ s/ /+/gi;
$last_local_call_time =~ s/ /+/gi;
$rank =~ s/ /+/gi;
$owner =~ s/ /+/gi;
$campaign_id =~ s/ /+/gi;
$dialed_number =~ s/ /+/gi;
$AGI->exec("EXEC Set(_lead_id=$lead_id)");
$AGI->exec("EXEC Set(_entry_date=$entry_date)");
$AGI->exec("EXEC Set(_modify_date=$modify_date)");
$AGI->exec("EXEC Set(_status=$status)");
$AGI->exec("EXEC Set(_user=$user)");
$AGI->exec("EXEC Set(_vendor_lead_code=$vendor_lead_code)");
$AGI->exec("EXEC Set(_source_id=$source_id)");
$AGI->exec("EXEC Set(_list_id=$list_id)");
$AGI->exec("EXEC Set(_phone_number=$phone_number)");
$AGI->exec("EXEC Set(_title=$title)");
$AGI->exec("EXEC Set(_first_name=$first_name)");
$AGI->exec("EXEC Set(_middle_initial=$middle_initial)");
$AGI->exec("EXEC Set(_last_name=$last_name)");
$AGI->exec("EXEC Set(_address1=$address1)");
$AGI->exec("EXEC Set(_address2=$address2)");
$AGI->exec("EXEC Set(_address3=$address3)");
$AGI->exec("EXEC Set(_city=$city)");
$AGI->exec("EXEC Set(_state=$state)");
$AGI->exec("EXEC Set(_province=$province)");
$AGI->exec("EXEC Set(_postal_code=$postal_code)");
$AGI->exec("EXEC Set(_country_code=$country_code)");
$AGI->exec("EXEC Set(_gender=$gender)");
$AGI->exec("EXEC Set(_date_of_birth=$date_of_birth)");
$AGI->exec("EXEC Set(_alt_phone=$alt_phone)");
$AGI->exec("EXEC Set(_email=$email)");
$AGI->exec("EXEC Set(_security_phrase=$security_phrase)");
$AGI->exec("EXEC Set(_comments=$comments)");
$AGI->exec("EXEC Set(_called_count=$called_count)");
$AGI->exec("EXEC Set(_last_local_call_time=$last_local_call_time)");
$AGI->exec("EXEC Set(_rank=$rank)");
$AGI->exec("EXEC Set(_owner=$owner)");
$AGI->exec("EXEC Set(_campaign_id=$campaign_id)");
$AGI->exec("EXEC Set(_dialed_number=$dialed_number)");
$AGI->exec("EXEC Set(_auto_dial_timeout=$auto_dial_timeout)");
$AGI->exec("EXEC Set(_cpd_amd_action=$cpd_amd_action)");
$AGI->exec("EXEC Set(_cpd_unknown_action=$cpd_unknown_action)");
$dbhA->disconnect();
if ($AGILOG) {$agi_string = "+++++ VARIABLE SET DONE EXITING : |$CIDlead_id|$now_date|$calleridname|$phone_number|"; &agi_output;}
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='';
}
@@ -0,0 +1,294 @@
#!/usr/bin/perl
#
# call_inbound.agi version 2.6
#
# runs at the beginning and ending of every inbound call received
#
# You need to put lines similar to those below in your extensions.conf file:
#
# parameters for call_inbound.agi (7 fields separated by five dashes "-----"):
# 1. the extension of the phone to ring as defined in the asterisk.phones table
# 2. the phone number that was called, for the live_inbound/_log entry
# 3. a text description of the number that was called in
# 4-7. optional fields, they are also passed as fields in the GUI to web browser
#
# ;inbound calls:
#exten => _*NXXNXXXXXX*3429,3,AGI(call_inbound.agi,spa2000-----8005553429-----Inbound 800-----x-----y-----z-----w)
#
#
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 60731-1435 - changed to use DBI-DBD::mysql
# - changed to use /etc/astguiclient.conf for configs
# 60817-1102 - added output options check from database
# 130108-1838 - Changes for Asterisk 1.8 compatibility
#
$script = 'call_inbound.agi';
$US='_';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$Y = substr($year, 0, 1);
$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";
$filedate = "$US$Y$mon$mday$hour$min$sec$US";
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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]);
$phone_ext = $ARGV_vars[0];
$inbound_number = $ARGV_vars[1];
$comment_a = $ARGV_vars[2];
$comment_b = $ARGV_vars[3];
$comment_c = $ARGV_vars[4];
$comment_d = $ARGV_vars[5];
$comment_e = $ARGV_vars[6];
if ($args =~ /--help/i)
{
print "allowed run time options:\n [-q] = quiet\n [-t] = test\n [-debug] = verbose debug messages\n\n";
}
else
{
if ($args =~ /-V/i)
{
$V=1;
}
if ($args =~ /-debug/i)
{
$DG=1;
}
if ($args =~ /-dbAVS/i)
{
$DGA=1;
}
if ($args =~ /-q/i)
{
$q=1;
$Q=1;
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
}
}
$|=1;
while(<STDIN>) {
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $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;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
if ( $calleridname =~ /\"/) {$calleridname =~ s/\"//gi;}
if ( (length($calleridname)>5) && ( (!$callerid) or ($callerid =~ /unknown|private|00000000/i) or ($callerid =~ /5551212/) ) )
{$callerid = $calleridname;}
### allow for ANI being sent with the DNIS "*3125551212*9999*"
if ($extension =~ /^\*\d\d\d\d\d\d\d\d\d\d\*/)
{
$callerid = $extension;
$callerid =~ s/\*\d\d\d\d\*$//gi;
$callerid =~ s/\*\d\d\d\d$//gi;
$callerid =~ s/^\*//gi;
$extension =~ s/^\*\d\d\d\d\d\d\d\d\d\d\*//gi;
$extension =~ s/\*$//gi;
### set the callerid if sent with DNIS
print "SET CALLERID $callerid\n";
$result = <STDIN>;
checkresult($result);
}
}
if ($AGILOG) {$agi_string = "AGI Environment Dump:"; &agi_output;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
$callerid = "\"$calleridname\" <$callerid>";
if ($extension =~ /h/i) {$stage = 'END';}
else {$stage = 'START';}
### call start stage
if ($stage =~ /START/)
{
if ($AGILOG) {$agi_string = "+++++ CALL INBOUND START : |$now_date|"; &agi_output;}
# if ($channel =~ /^SIP/) {$channel =~ s/-.*//gi;}
# if ($channel =~ /^Zap\//) {$channel =~ s/-\d$//gi;}
$stmtA = "INSERT INTO live_inbound (uniqueid,channel,server_ip,caller_id,extension,phone_ext,start_time,inbound_number,comment_a,comment_b,comment_c,comment_d,comment_e) values('$unique_id','$channel','$VARserver_ip','$callerid','$extension','$phone_ext','$now_date','$inbound_number','$comment_a','$comment_b','$comment_c','$comment_d','$comment_e')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
$stmtA = "INSERT INTO live_inbound_log (uniqueid,channel,server_ip,caller_id,extension,phone_ext,start_time,inbound_number,comment_a,comment_b,comment_c,comment_d,comment_e) values('$unique_id','$channel','$VARserver_ip','$callerid','$extension','$phone_ext','$now_date','$inbound_number','$comment_a','$comment_b','$comment_c','$comment_d','$comment_e')";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
$dbhA->disconnect();
}
### call end stage
else
{
if ($AGILOG) {$agi_string = "CALL INBOUND HUNG UP; deleting live_inbound record for $unique_id"; &agi_output;}
$stmtA = "DELETE from live_inbound where uniqueid='$unique_id' and server_ip='$VARserver_ip'";
$affected_rows = $dbhA->do($stmtA);
$dbhA->disconnect();
if ($AGILOG) {$agi_string = "+++++ CALL INBOUND HUNGUP: |$unique_id|$affected_rows|"; &agi_output;}
}
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='';
}
@@ -0,0 +1,339 @@
#!/usr/bin/perl
#
# cepstral_generate.pl version 2.2.0
#
# Text-To-Speech files will be cached for later use.
#
# Call this script like this:
# /var/lib/asterisk/agi-bin/cepstral_generate.pl --debug --voice=Allison-8kHz --dialog=Hello\ There
#
# Copyright (C) 2009 Matt Florell, Mike Cargile <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGES:
# 90406-1058 - First Build
# 90410-1458 - Fixed generate bug, added conf path variables
#
# Cepstral paths
$PATHvoices = '/tmp/swift_voices';
$PATHswift = '/opt/swift/bin/swift';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
$i++;
}
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [-t] = test\n";
print " [-debug] = verbose debug messages\n";
print " [-debugX] = Extra-verbose debug messages\n";
print " [-voice=Allison-8kHz] = Cepstral voice to use(Allison-8kHz is default)\n\n";
print " [-dialog=Hello] = Message to generate\n\n";
print " (This must be the LAST option)\n\n";
}
else
{
if ($args =~ /-debug/i)
{
$DB=1; # Debug flag
}
if ($args =~ /--debugX/i)
{
$DBX=1;
print "\n----- SUPER-DUPER DEBUGGING -----\n\n";
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
if ($args =~ /-voice=/i)
{
@data_in = split(/-voice=/,$args);
$voice = $data_in[1];
$voice =~ s/ .*//gi;
if ($DBX > 0) {print "\n----- VOICE: $voice -----\n\n";}
}
else
{$voice = 'Allison-8kHz';}
if ($args =~ /-dialog=/i)
{
@data_in = split(/-dialog=/,$args);
$dialog = $data_in[1];
$dialog =~ s/\n|\r|\l|\t//gi;
if ($DBX > 0) {print "\n----- DIALOG: $dialog -----\n\n";}
}
else
{$dialog = '';}
}
}
else
{
# print "no command line options set\n";
}
### end parsing run-time options ###
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
$SQL_date = "$year-$mon-$mday $hour:$min:$sec";
use Digest::MD5 qw(md5_hex);
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
#my @voice = &get_cep_voice(2);
if (length($dialog) > 1)
{
$enc = md5_hex("$dialog-$voice"); # the hash
$enc_ftl = substr($enc, 0, 2); # first letter of hash
$enc_file = "tts/" . $enc_ftl . "/tts-" . $enc . ".wav";
if ($DB > 0)
{print "$SQL_date - Creating $dialog - $voice file: $enc_file\n";}
# &say_cepstral("$dialog","$voice");
&gen_cepstral("$dialog","$voice");
}
exit;
# EXAMPLES
#&say_cepstral("Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not hallow -- this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us -- that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion -- that we here highly resolve that these dead shall not have died in vain -- that this nation, under God, shall have a new birth of freedom -- and that government of the people, by the people, for the people, shall not perish from the earth.",$voice[0]);
#&say_cepstral("Welcome to the VEECHEE DIAL open source call center suite",$voice[0]);
# function to get a voice that is currently installed
# takes and integer
# the integer needs to be greater than 0
# returns an array with the following info in this order
# Voice
# Version
# Lic?
# Gender
# Age
# Language
# Sample Rate
sub get_cep_voice {
my $number = $_[0];
if ($number <= 0) {
return 0; # failure
}
my $cepstral_app = "$PATHswift";
my $command = $cepstral_app.' --voices | tail +8 | tr -d " " > '.$PATHvoices;
system( $command ); # Ask swift for the voices
my @voice;
my @voice_lines;
my $voice_count;
open(VFILE,"$PATHvoices"); # read in the file with the voices
@voice_lines = <VFILE>;
close(VFILE);
#unlink("/tmp/swift_vioces"); # delete the file with the voices
# find the correct voice
foreach my $voice_line(@voice_lines) {
chomp($voice_line);
$voice_count++;
if ($voice_count == $number) {
@voice = split(/\|/,$voice_line);
}
}
# return it
return @voice;
}
# Function to return the number of voices that are installed
# Returns an int
sub get_cep_num_voices {
my $cepstral_app = "$PATHswift";
my $command = $cepstral_app.' --voices | tail +8 | tr -d " " > '.$PATHvoices;
system( $command ); # Ask swift for the voices
my @voice_lines;
my $number = 0;
# read in the file with the voices
open(VFILE,"$PATHvoices");
@voice_lines = <VFILE>;
close(VFILE);
#unlink("/tmp/swift_vioces"); # delete it
foreach (@voice_lines) {
$number++;
}
return $number;
}
# Function to pregenerate TTS file
# First option is the text
# Second option is the voice
sub gen_cepstral {
my $text = $_[0]; # the text to play
my $voice = $_[1]; # voice to use
# hash of the text
my $hash = md5_hex("$text-$voice"); # the hash
my $hash_ftl = substr($hash, 0, 2); # first two letters of hash
# Directories that hold everything
my $astsounddir = $PATHsounds; # asterisk sound directory
my $ttssounddir = $astsounddir."/tts";
my $astsubdir = "tts/".$hash_ftl; # sub directory that holds the file
my $sounddir = $astsounddir . "/" . $astsubdir; # full path to the directory
# Wave File to play
my $wavefile = "tts-".$hash; # wave file without the .wav at the end
my $wavepath = $sounddir."/".$wavefile.".wav"; # full path to the wavefile
my $astwavpath = $astsubdir."/".$wavefile; # asterisk path to .wav file without .wav
# text file of words to say
my $textfile = "tts-text-".$hash.".txt"; # file to hold the words to say
my $textpath = $sounddir."/".$textfile; # full path to the text file
# generate the tts
if (!(&real_gen_cepstral($text, $voice, $ttssounddir, $sounddir, $wavepath, $textpath))) {
#TODO print an error message somewhere
return 0; # failure
}
return 1; # success
}
# Function to play TTS file
# Will generate TTS file if it is not pregenerated
# First option is the text
# Second option is the voice
sub say_cepstral {
my $text = $_[0]; # the text to play
my $voice = $_[1]; # voice to use
my %input = $AGI->ReadParse();
# hash of the text
my $hash = md5_hex("$text-$voice"); # the hash
my $hash_ftl = substr($hash, 0, 2); # first letter of hash
# Directories that hold everything
my $astsounddir = $PATHsounds; # asterisk sound directory
my $ttssounddir = $astsounddir."/tts";
my $astsubdir = "tts/".$hash_ftl; # sub directory that holds the file
my $sounddir = $astsounddir."/".$astsubdir; # full path to the directory
# Wave File to play
my $wavefile = "tts-".$hash; # wave file without the .wav at the end
my $wavepath = $sounddir."/".$wavefile.".wav"; # full path to the wavefile
my $astwavpath = $astsubdir."/".$wavefile; # asterisk path to .wav file without .wav
# text file of words to say
my $textfile = "tts-text-".$hash.".txt"; # file to hold the words to say
my $textpath = $sounddir."/".$textfile; # full path to the text file
# generate the tts
if (!(&real_gen_cepstral($text, $voice, $ttssounddir, $sounddir, $wavepath, $textpath))) {
#TODO print an error message somewhere
return 0; # failure
}
# wait up to a second
# for the sound file to appear
# and the textfile to be deleted
# This is for concurrency issues
my $i = 0;
while ( ($i < 100) && !(-f $wavepath) && (-f $textpath) ) {
usleep(10000);
$i++;
}
$AGI->stream_file($astwavpath); # play the tts
return 1; # success
}
# This is a helper function do not call it directly
sub real_gen_cepstral {
my $text = $_[0];
my $voice = $_[1];
my $ttssounddir = $_[2];
my $sounddir = $_[3];
my $wavepath = $_[4];
my $textpath = $_[5];
# Cepstral commnad and options
my $cepstral_app = "$PATHswift"; # the executable
my $cepstral_opt = "-p speech/rate=140"; # the command line options
# Make sure the tts directory is there
if (!(-d $ttssounddir)) {
if (!(mkdir($ttssounddir))) {
#TODO print an error message somewhere
return 0; # failure - cannot make the tts directory
}
}
# Make sure the sub directory is there
if (!(-d $sounddir)) {
if (!(mkdir($sounddir))) {
#TODO print an error message somewhere
return 0; # failure - cannot make the sub directory
}
}
# check if both the wav file and the text file do not exists
if (!( -f $wavepath ) && !( -f $textpath )) {
# write to the text file whats to be said
open(fileOUT, ">$textpath");
print fileOUT "$text";
close(fileOUT);
# build the command to call cepstral and give it the text file to generate
my $command=$cepstral_app." ".$cepstral_opt." -n ".$voice." -o ".$wavepath." -f ".$textpath." > /dev/null";
# execute the command
system($command);
# delete the text file
unlink($textpath);
}
return 1; # success
}
+375
View File
@@ -0,0 +1,375 @@
#!/usr/bin/perl
#
# cm.agi version 2.12
#
# Used by Call Menus to log digit presses if enabled in the settings. You should
# not need to manually use this script, it is used by the dialplan builder.
#
# You need to put lines similar to those below in your extensions.conf file:
# ; Below are the parameters needed for the script to be run properly
# ; 1. the in-group to take settings from
# ; 2. digit pressed
# ; 3. field(in vicidial_list) to update with DTMF pressed (only if lead_id populated)
# ; 4. alt-log(enable alternate logging)
# ; 5. question number used if alt-logging is enabled
# ;
# ;inbound calls check calltime:
#exten => 1,1,AGI(cm.agi,INBOUND-----1-----province----------)
#exten => 1,2,...
#
# ;to allow for multi-digit entries, put similar entry in the Custom Dialplan Entry:
#exten => _XXXXX,1,AGI(cm.agi,INBOUND-----${EXTEN}-----postal_code)
#exten => _XXXXX,n,Goto(next_callmenu_here,s,1)
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 110525-2100 - First Build
# 111003-2150 - Added field to update
# 120730-0729 - Changed to allow inbound logging when lead is defined
# 130925-1822 - Added variable filter to prevent DID SQL injection attack
# 130926-1547 - Added new queue_log IVR entries for QM
# 160305-2244 - Added Alt IVR Logging options
# 161102-1039 - Fixed QM partition problem
#
$script = 'cm.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$vicidial_list_fields = '|vendor_lead_code|source_id|phone_code|title|first_name|middle_initial|last_name|address1|address2|address3|city|state|province|postal_code|country_code|alt_phone|email|security_phrase|comments|rank|owner|status|user|q01|q02|q03|q04|q05|q06|q07|q08|q09|q10|q11|q12|q13|q14|q15|q16|q17|q18|q19|q20|q21|q22|q23|q24|q25|q26|q27|q28|q29|q30|q31|q32|q33|q34|q35|q36|q37|q38|q39|q40|q41|q42|q43|q44|q45|q46|q47|q48|q49|q50|q51|q52|q53|q54|q55|q56|q57|q58|q59|q60|q61|q62|q63|q64|q65|q66|q67|q68|q69|q70|q71|q72|q73|q74|q75|q76|q77|q78|q79|q80|q81|q82|q83|q84|q85|q86|q87|q88|q89|q90|q91|q92|q93|q94|q95|q96|q97|q98|q99|';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
}
$sthA->finish();
#############################################
##### START QUEUEMETRICS LOGGING LOOKUP #####
$stmtA = "SELECT enable_queuemetrics_logging,queuemetrics_server_ip,queuemetrics_dbname,queuemetrics_login,queuemetrics_pass,queuemetrics_log_id,queuemetrics_eq_prepend 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;
$enable_queuemetrics_logging = $aryA[0];
$queuemetrics_server_ip = $aryA[1];
$queuemetrics_dbname = $aryA[2];
$queuemetrics_login= $aryA[3];
$queuemetrics_pass = $aryA[4];
$queuemetrics_log_id = $aryA[5];
$queuemetrics_eq_prepend = $aryA[6];
}
$sthA->finish();
##### END QUEUEMETRICS LOGGING LOOKUP #####
###########################################
### 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]);
$channel_group = $ARGV_vars[0];
$dtmf = $ARGV_vars[1];
$field = $ARGV_vars[2];
$alt_logging = $ARGV_vars[3];
$alt_question = $ARGV_vars[4];
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_priority\:\s+(.*)$/) {$priority = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
$callerid =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$calleridname =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$extension =~ s/\'|\"|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$outboundIVR=0;
$fieldUPDATE=0;
if ($calleridname =~ /^V\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/)
{
$phone_number = $callerid;
$callerid = $calleridname;
$outboundIVR=1;
$stmtA = "SELECT campaign_id,lead_id FROM vicidial_auto_calls where callerid='$callerid';";
$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_id = $aryA[0];
$lead_id = $aryA[1];
}
$sthA->finish();
}
elsif ($calleridname =~ /^Y\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/)
{
$lead_id = substr($calleridname, 10, 10);
$lead_id = ($lead_id + 0);
$phone_number = $callerid;
$callerid = $calleridname;
$stmtA = "SELECT campaign_id FROM vicidial_auto_calls where callerid='$callerid';";
$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_id = $aryA[0];
}
$sthA->finish();
if ( (length($field)>2) && ($vicidial_list_fields =~ /\|$field\|/) )
{
$fieldUPDATE=1;
}
}
else
{
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D|\'//gi;
$calleridname =~ s/unknown|\'//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
if (length($calleridname)>0) {$VLcomments = $calleridname;}
else {$VLcomments = '';}
}
if (length($callerid)<8) {$callerid = $parked_by;}
if (length($pin)>0) {$callerid = $pin;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
if (length($pin) < 1) {$pin=$inbound_number;}
$fronter = $pin;
if ($AGILOG) {$agi_string = "+++++ DTMF LOG STARTED : |$channel_group|$callerid-$pin|$now_date"; &agi_output;}
$VDADphone='';
$VDADphone_code='';
if ($channel =~ /Local/i)
{
if ($AGILOG) {$agi_string = "+++++ VDAD START LOCAL CHANNEL: EXITING- $priority"; &agi_output;}
exit;
}
### insert an IVR record to the vicidial_auto_calls table
if ($outboundIVR > 0)
{
$stmtA = "INSERT INTO vicidial_outbound_ivr_log (uniqueid,caller_code,event_date,campaign_id,lead_id,menu_id,menu_action) values('$uniqueid','$callerid','$now_date','$campaign_id','$lead_id','$context>$dtmf','$dtmf');";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VOIL insert: |$affected_rowsL|$uniqueid|$callerid|$campaign_id|$lead_id|$context|"; &agi_output;}
if ( (length($field)>2) && ($vicidial_list_fields =~ /\|$field\|/) )
{
if ( ($field =~ /^q/i) && ($dtmf !~ /[0-9]/) )
{
if ($AGILOG) {$agi_string = "-- VL non-update: |$field|$dtmf|$lead_id|$context|"; &agi_output;}
}
else
{
$stmtA = "UPDATE vicidial_list SET $field='$dtmf' where lead_id='$lead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VL update: |$affected_rowsL|$field|$dtmf|$lead_id|$context|"; &agi_output;}
}
}
}
else
{
if ($fieldUPDATE > 0)
{
if ( ($field =~ /^q/i) && ($dtmf !~ /[0-9]/) )
{
if ($AGILOG) {$agi_string = "-- VL non-update: |$field|$dtmf|$lead_id|$context|"; &agi_output;}
}
else
{
$stmtA = "UPDATE vicidial_list SET $field='$dtmf' where lead_id='$lead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VL update: |$affected_rowsL|$field|$dtmf|$lead_id|$context|"; &agi_output;}
}
}
$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','$phone_number','$now_date','$channel_group','$dtmf','$context>$dtmf','$priority');";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- LIL insert: |$affected_rowsL|$uniqueid|$callerid|$extension|"; &agi_output;}
}
if ( ($alt_logging =~ /1/) && ($alt_question =~ /\d/) )
{
$stmtA = "INSERT INTO vicidial_ivr_response (btn,lead_id,question,response,uniqueid,campaign) values('$phone_number','$lead_id','$alt_question','$dtmf','$uniqueid','$campaign_id');";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsAI = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VIR insert: |$affected_rowsAI|$uniqueid|$phone_number|$lead_id|"; &agi_output;}
}
### QueueMetrics logging if enabled
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 QueueMetrics DATABASE: $queuemetrics_server_ip|$queuemetrics_dbname\n";}
if ($outboundIVR > 0)
{$uniqueid = $caller_id;}
$stmtB = "INSERT INTO queue_log SET `partition`='P01',time_id='$now_date_epoch',call_id='$uniqueid',queue='NONE',agent='NONE',verb='INFO',data1='IVRAPPEND',data2='$dtmf',data3='$context',serverid='$queuemetrics_log_id';";
if ($AGILOG) {$agi_string = "|$stmtB|"; &agi_output;}
$Baffected_rows = $dbhB->do($stmtB);
$dbhB->disconnect();
}
$sthA->finish();
$dbhA->disconnect();
exit;
sub agi_output
{
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$now_date|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$now_date|$script|$agi_string\n";}
$agi_string='';
}
@@ -0,0 +1,339 @@
#!/usr/bin/perl
#
# cm_areacode.agi version 2.12
#
# Designed to work with Call Menus to allow searching of the areacode of the
# caller ID phone number the customer called in on, to be searched within the
# vicidial_phone_codes table to gather the state, then search the
# vicidial_inbound_dids table for that state in the did_carrier_description
# field and send the call on to the did that matches.
#
# If areacode is not found call will go to the 'D' option in the call menu
# If state DID is not found call will go to the 'C' option in the call menu
#
# Flag Options:
# 1- Country code to search the areacode within, default 1
# 2- Length of areacode in digits, default 3
# 3- DID prefix to filter by in searching for DIDs, default 999
#
# example of what to set in the Call Menu:
# Set the prompt to "sip-silence"
# Set the Timeout to 1 second
# Option: "Timeout" Route: "AGI" AGI: "cm_areacode.agi,1---3---999"
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 160610-0713 - First build
#
$script = 'cm_areacode.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$start_time=$now_date;
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec";
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$SQLdateBEGIN = $SQLdate;
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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]);
$country_code = $ARGV_vars[0];
$ac_length = $ARGV_vars[1];
$did_prefix = $ARGV_vars[2];
}
if (length($country_code) < 1)
{$country_code = '1';}
if (length($ac_length) < 1)
{$ac_length = '3';}
if (length($did_prefix) < 1)
{$did_prefix = '999';}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
$callerid =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$calleridname =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$extension =~ s/\'|\"|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
if (length($calleridname)>0) {$VLcomments = $calleridname;}
else {$VLcomments = '';}
if (length($callerid)<10) {$callerid = $parked_by;}
if (length($pin)>0) {$callerid = $pin;}
$phone_ac = substr($phone_number, 0, $ac_length);
}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid| |$country_code|$phone_number($phone_ac)|$ac_length|"; &agi_output;}
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$g=0;
$state='';
### only perform search if minimum digits entered is valid ###
if (length($phone_ac) >= $ac_length)
{
### search for state using areacode of caller id number ###
$stmtA= "SELECT state from vicidial_phone_codes where country_code='$country_code' and areacode='$phone_ac';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($AGILOG) {$agi_string = "$sthArows|$stmtA|"; &agi_output;}
while ($sthArows > $g)
{
@aryA = $sthA->fetchrow_array;
$state = $aryA[0];
$g++;
}
$sthA->finish();
}
# State not found, send call to 'D' option in call menu
if ($g < 1)
{
if ($AGILOG) {$agi_string = "entry not found($phone_ac), exiting the cm_areacode.agi app, transferring call to D @ $context"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION D\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
}
### search for DID using found state and optional DID prefix ###
$DID_prefixSQL='';
$new_did='';
if (length($did_prefix)>0) {$DID_prefixSQL = "and did_pattern LIKE \"$did_prefix%\"";}
$stmtA= "SELECT did_pattern from vicidial_inbound_dids where did_carrier_description LIKE \"$state%\" $DID_prefixSQL;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($AGILOG) {$agi_string = "$sthArows|$stmtA|"; &agi_output;}
$g=0;
while ($sthArows > $g)
{
@aryA = $sthA->fetchrow_array;
$new_did = $aryA[0];
$g++;
}
$sthA->finish();
$dbhA->disconnect();
# DID not found, send call to 'C' option in call menu
if ($g < 1)
{
if ($AGILOG) {$agi_string = "entry not found($state|$phone_ac), exiting the cm_areacode.agi app, transferring call to C @ $context"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION C\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
}
else
{
$AGI->exec("EXEC Set(_state=$state)");
if ($AGILOG) {$agi_string = "entry found($state|$phone_ac), exiting the cm_areacode.agi app, transferring call to $new_did @ trunkinbound"; &agi_output;}
print "SET CONTEXT trunkinbound\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $new_did\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
}
##### SUBROUTINES #####
sub agi_output
{
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$now_date|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$now_date|$script|$agi_string\n";}
$agi_string='';
}
sub checkresult
{
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/)
{
$res =~ /result=(-?\d+)/;
if (!length($1))
{
# print STDERR "FAIL ($res)\n";
$fail++;
}
else
{
# print STDERR "PASS ($1)\n";
$pass++;
}
}
else
{
# print STDERR "FAIL (unexpected result '$res')\n";
$fail++;
}
}
+149
View File
@@ -0,0 +1,149 @@
#!/usr/bin/perl
#
# cm_date.agi version 2.6
#
# Can be used in a call menu prompt to play a date string as defined by the settings below
#
# ; Below are the parameters needed for the script to be run properly
# ; the "SAY DATETIME" parameters for what to say separated by three dashes
# ; 1. offset from current epoch in seconds, positive or negative
# ; 1 hour is 3600
# ; 1 day is 86400
# ; 1 week is 604800
# ; 30 days is 2592000
# ; 1 year is 31536000
# ; 2. format of the date to say, i.e. "ABdY":
# ; A: Day of the week
# ; B: Month (Full Text)
# ; m: Month (Numeric)
# ; d: Day of the month
# ; Y: Year
# ; I: Hour (12-hour format)
# ; H: Hour (24-hour format)
# ; M: Minutes
# ; P: AM/PM
# ; Q: Shorthand for Today, Yesterday or ABdY
# ; R: Shorthand for HM
# ; S: Seconds
# ; T: Timezone
#
# ;inbound calls check calltime:
# ; (this example is for yesterday and says "Monday March 25th 2013")
# cm_date.agi,-86400---ABdY
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 130326-1718 - First Build
#
$script = 'cm_date.agi';
$now_date_epoch = time();
$now_date = time();
$AGILOG = '1'; # 1=STDERR output
$exten='';
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
### 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]);
$epoch_offset = $ARGV_vars[0];
$datetime_format = $ARGV_vars[1];
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
}
$new_epoch = ($now_date_epoch + $epoch_offset);
if ($AGILOG) {$agi_string = "Date Epoch: |$now_date_epoch|$epoch_offset|$new_epoch| Format: |$datetime_format|"; &agi_output;}
# SAY DATETIME <time> <escape digits> [format] [timezone]
print "SAY DATETIME $new_epoch 0 \"$datetime_format\"\n"; checkresult($result);
exit;
sub checkresult
{
$pass=0;
$fail=0;
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/)
{
$res =~ /result=(-?\d+)/;
if (!length($1))
{
# print STDERR "FAIL ($res|$1)\n";
$fail++;
}
else
{
# print STDERR "PASS ($res|$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='';
}
+371
View File
@@ -0,0 +1,371 @@
#!/usr/bin/perl
#
# cm_dnc.agi version 2.12
#
# Designed to work with Cell Menus to allow setting of a number as DNC or NI
# This script is meant as a replacecment for the agi-VDADinbound_NI_DNC_CIDlookup.agi
# script. It is designed to work easily in the Call Menu framework, it plays no
# audio itself, and it has more options.
#
# Flag Options:
# 1- run as DNC status or NI status (Default=NI)
# 2- default to insert into the vicidial_dnc table for DNC selections (Default=YES)
# 3- campaign to take dnc settings from(overrides option 2)
# 4- call menu option to send the call to after executing (Default=B)
# 5- if option 3 is used, search for lead in campaign lists or whole system(CAMP or SYS) (Default=SYS)
#
# example of what to put in the AGI entry for a Call Menu AGI route:
# cm_dnc.agi,DNC---YES---TESTCAMP---B---CAMP
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 121109-1623 - First draft
# 130108-1817 - Changes for Asterisk 1.8 compatibility
# 130925-1825 - Added variable filter to prevent DID SQL injection attack
# 150928-1822 - Added dnc logging
#
$script = 'cm_dnc.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$start_time=$now_date;
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec";
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$SQLdateBEGIN = $SQLdate;
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
if ($AGILOG) {$agi_string = "Perl Environment Dump:"; &agi_output;}
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
if ($AGILOG) {$agi_string = "$i|$ARGV[$i]"; &agi_output;}
$i++;
}
### list of command-line array arguments:
@ARGV_vars = split(/---/, $ARGV[0]);
$new_status = $ARGV_vars[0];
$dnc_default = $ARGV_vars[1];
$campaign_id = $ARGV_vars[2];
$next_step = $ARGV_vars[3];
$camp_sys = $ARGV_vars[4];
}
if (length($new_status) < 1)
{$new_status = 'NI';}
if (length($dnc_default) < 2)
{$dnc_default = 'YES';}
if (length($next_step) < 1)
{$next_step = 'B';}
if (length($camp_sys) < 2)
{$camp_sys = 'SYS';}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
$callerid =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$calleridname =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$extension =~ s/\'|\"|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
if (length($calleridname)>0) {$VLcomments = $calleridname;}
else {$VLcomments = '';}
if (length($callerid)<10) {$callerid = $parked_by;}
if (length($pin)>0) {$callerid = $pin;}
}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
# if campaign is used and selected for search, find the lists in the campaign
$listSQL='';
if ( (length($campaign_id) > 0) && ($camp_sys =~ /CAMP/) )
{
$cbc=0;
$SlistsSQL='';
$stmtA = "SELECT list_id FROM vicidial_lists where campaign_id='$campaign_id' limit 1000;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($AGILOG) {$agi_string = "$sthArows|$stmtA|"; &agi_output;}
while ($sthArows > $cbc)
{
@aryA = $sthA->fetchrow_array;
$SlistsSQL .= "'$aryA[0]',";
$cbc++;
}
$sthA->finish();
chop($SlistsSQL);
if (length($SlistsSQL)<3)
{$SlistsSQL = "''";}
if (length($SlistsSQL)>1)
{$listSQL = "and list_id IN($SlistsSQL)";}
}
### Gather the lead IDs of the leads with this phone number ###
$stmtA= "SELECT lead_id from vicidial_list where phone_number='$phone_number' $listSQL;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($AGILOG) {$agi_string = "$sthArows|$stmtA|"; &agi_output;}
$g=0;
$SleadsSQL='';
while ($sthArows > $g)
{
@aryA = $sthA->fetchrow_array;
$SleadsSQL .= "'$aryA[0]',";
$g++;
}
$sthA->finish();
chop($SleadsSQL);
### process for NI path
if ($new_status =~ /NI/) # set the phone_number to NI
{
if ($g > 0)
{
### update all records for the phone_number in vicidial_list to NI (Not Interested)
$stmtA = "UPDATE vicidial_list SET status='NI' where lead_id IN($SleadsSQL);";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
}
### process for DNC path
if ($new_status =~ /DNC/) # set the phone_number to DNC
{
if ($g > 0)
{
### update all records for the phone_number in vicidial_list to NI (Not Interested)
$stmtA = "UPDATE vicidial_list SET status='DNC' where lead_id IN($SleadsSQL);";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
if (length($campaign_id)>1)
{
### Grab DNC settings from campaign
$stmtA = "SELECT use_internal_dnc,use_campaign_dnc FROM vicidial_campaigns where campaign_id = '$campaign_id';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@aryA = $sthA->fetchrow_array;
$use_internal_dnc = $aryA[0];
$use_campaign_dnc = $aryA[1];
$sthA->finish();
if ( ($use_internal_dnc =~ /Y|AREACODE/) && ($dnc_default =~ /YES/) )
{
### add the number to the vicidial_dnc table
$stmtA = "INSERT IGNORE INTO vicidial_dnc SET phone_number='$phone_number';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
$stmtA="INSERT INTO vicidial_dnc_log SET phone_number='$phone_number', campaign_id='-SYSINT-', action='add', action_date=NOW(), user='CMAGI';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
if ($use_campaign_dnc =~ /Y|AREACODE/)
{
### add the number to the vicidial_campaign_dnc table
$stmtA = "INSERT IGNORE INTO vicidial_campaign_dnc SET phone_number='$phone_number',campaign_id='$campaign_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
$stmtA="INSERT INTO vicidial_dnc_log SET phone_number='$phone_number', campaign_id='$campaign_id', action='add', action_date=NOW(), user='CMAGI';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
}
else
{
if ($dnc_default =~ /YES/)
{
### add the number to the vicidial_dnc table
$stmtA = "INSERT INTO vicidial_dnc SET phone_number='$phone_number';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
}
}
$dbhA->disconnect();
if ($AGILOG) {$agi_string = "exiting the cm_dnc app, transferring call to $next_step:$context |$phone_number|"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $next_step\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
sub agi_output
{
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$now_date|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$now_date|$script|$agi_string\n";}
$agi_string='';
}
sub checkresult
{
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/)
{
$res =~ /result=(-?\d+)/;
if (!length($1))
{
# print STDERR "FAIL ($res)\n";
$fail++;
}
else
{
# print STDERR "PASS ($1)\n";
$pass++;
}
}
else
{
# print STDERR "FAIL (unexpected result '$res')\n";
$fail++;
}
}
@@ -0,0 +1,387 @@
#!/usr/bin/perl
#
# cm_dnc_new.agi version 2.12
#
# Designed to work with Cell Menus to allow setting of a number as DNC or NI
# This script is meant as a replacecment for the agi-VDADinbound_NI_DNC_CIDlookup.agi
# script. It is designed to work easily in the Call Menu framework, it plays no
# audio itself, and it has more options.
#
# Flag Options:
# 1- run as DNC status or ANY OTHER status (Default=NI)
# 2- default to insert into the vicidial_dnc table for DNC selections (Default=YES)
# 3- campaigns to take dnc settings from(overrides option 2) multiple campaigns separated by single dash
# 4- call menu option to send the call to after executing (Default=B)
# 5- if option 3 is used, search for lead in campaign lists or whole system(CAMP or SYS) (Default=SYS)
# 6- optional audio store file to play
#
# example of what to put in the AGI entry for a Call Menu AGI route:
# cm_dnc_new.agi,DNC---YES---TESTCAMP---B---CAMP---auth-thankyou
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 121109-1623 - First draft
# 130108-1817 - Changes for Asterisk 1.8 compatibility
# 130925-1825 - Added variable filter to prevent DID SQL injection attack
# 150928-1822 - Added dnc logging
# 160825-1117 - modifications allowing for a lead to be updated to any
# disposition, not just NI/DNC. Also, modified to use multiple
# campaigns for lead lookups and an option to play an audio file
# without redirecting
#
$script = 'cm_dnc_new.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$start_time=$now_date;
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec";
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$SQLdateBEGIN = $SQLdate;
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
$AGILOG='3';
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
if ($AGILOG) {$agi_string = "Perl Environment Dump:"; &agi_output;}
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
if ($AGILOG) {$agi_string = "$i|$ARGV[$i]"; &agi_output;}
$i++;
}
### list of command-line array arguments:
@ARGV_vars = split(/---/, $ARGV[0]);
$new_status = $ARGV_vars[0];
$dnc_default = $ARGV_vars[1];
$campaign_id = $ARGV_vars[2];
$next_step = $ARGV_vars[3];
$camp_sys = $ARGV_vars[4];
$audio_file = $ARGV_vars[5];
}
if (length($new_status) < 1)
{$new_status = 'NI';}
if (length($dnc_default) < 2)
{$dnc_default = 'YES';}
if (length($next_step) < 1)
{$next_step = 'B';}
if (length($camp_sys) < 2)
{$camp_sys = 'SYS';}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
$callerid =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$calleridname =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$extension =~ s/\'|\"|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
if (length($calleridname)>0) {$VLcomments = $calleridname;}
else {$VLcomments = '';}
if (length($callerid)<10) {$callerid = $parked_by;}
if (length($pin)>0) {$callerid = $pin;}
}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
# if campaign is used and selected for search, find the lists in the campaign
$listSQL='';
if ( (length($campaign_id) > 0) && ($camp_sys =~ /CAMP/) )
{
# Multiple campaigns should be separated by a SINGLE DASH if more than one should be used for looking up leads
$campaign_id=~s/\-/\',\'/gi;
$cbc=0;
$SlistsSQL='';
$stmtA = "SELECT list_id FROM vicidial_lists where campaign_id in ('$campaign_id') limit 1000;";
print "\n\n$stmtA\n\n";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($AGILOG) {$agi_string = "$sthArows|$stmtA|"; &agi_output;}
while ($sthArows > $cbc)
{
@aryA = $sthA->fetchrow_array;
$SlistsSQL .= "'$aryA[0]',";
$cbc++;
}
$sthA->finish();
chop($SlistsSQL);
if (length($SlistsSQL)<3)
{$SlistsSQL = "''";}
if (length($SlistsSQL)>1)
{$listSQL = "and list_id IN($SlistsSQL)";}
}
### Gather the lead IDs of the leads with this phone number ###
$stmtA= "SELECT lead_id from vicidial_list where phone_number='$phone_number' $listSQL;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($AGILOG) {$agi_string = "$sthArows|$stmtA|"; &agi_output;}
$g=0;
$SleadsSQL='';
while ($sthArows > $g)
{
@aryA = $sthA->fetchrow_array;
$SleadsSQL .= "'$aryA[0]',";
$g++;
}
$sthA->finish();
chop($SleadsSQL);
### process for NI path
# JCJ changd 8/23 to update all leads regardless of status if status>0
# JCJ REMOVED if ($new_status =~ /NI|IVDQ/) # set the phone_number to NI
if (length($new_status)>0)
{
if ($g > 0)
{
### update all records for the phone_number in vicidial_list to NI (Not Interested), or whatever the new disposition is set to
$stmtA = "UPDATE vicidial_list SET status='$new_status' where lead_id IN($SleadsSQL);";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
}
### process for DNC path
if ($new_status =~ /DNC/) # set the phone_number to DNC
{
# JCJ - Removed because we're doing this on all calls for the above section
# if ($g > 0)
# {
### update all records for the phone_number in vicidial_list to NI (Not Interested)
# $stmtA = "UPDATE vicidial_list SET status='DNC' where lead_id IN($SleadsSQL);";
# $affected_rows = $dbhA->do($stmtA);
# if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
# }
if (length($campaign_id)>1)
{
### Grab DNC settings from campaign
$stmtA = "SELECT use_internal_dnc,use_campaign_dnc FROM vicidial_campaigns where campaign_id = '$campaign_id';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@aryA = $sthA->fetchrow_array;
$use_internal_dnc = $aryA[0];
$use_campaign_dnc = $aryA[1];
$sthA->finish();
if ( ($use_internal_dnc =~ /Y|AREACODE/) && ($dnc_default =~ /YES/) )
{
### add the number to the vicidial_dnc table
$stmtA = "INSERT IGNORE INTO vicidial_dnc SET phone_number='$phone_number';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
$stmtA="INSERT INTO vicidial_dnc_log SET phone_number='$phone_number', campaign_id='-SYSINT-', action='add', action_date=NOW(), user='CMAGI';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
if ($use_campaign_dnc =~ /Y|AREACODE/)
{
### add the number to the vicidial_campaign_dnc table
$stmtA = "INSERT IGNORE INTO vicidial_campaign_dnc SET phone_number='$phone_number',campaign_id='$campaign_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
$stmtA="INSERT INTO vicidial_dnc_log SET phone_number='$phone_number', campaign_id='$campaign_id', action='add', action_date=NOW(), user='CMAGI';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
}
else
{
if ($dnc_default =~ /YES/)
{
### add the number to the vicidial_dnc table
$stmtA = "INSERT INTO vicidial_dnc SET phone_number='$phone_number';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "$affected_rows|$stmtA|"; &agi_output;}
}
}
}
$dbhA->disconnect();
if (length($audio_file)>0) {
$AGI->exec("playback","$audio_file");
}
if ($AGILOG) {$agi_string = "exiting the cm_dnc app, transferring call to $next_step:$context |$phone_number|"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $next_step\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
sub agi_output
{
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$now_date|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$now_date|$script|$agi_string\n";}
$agi_string='';
}
sub checkresult
{
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/)
{
$res =~ /result=(-?\d+)/;
if (!length($1))
{
# print STDERR "FAIL ($res)\n";
$fail++;
}
else
{
# print STDERR "PASS ($1)\n";
$pass++;
}
}
else
{
# print STDERR "FAIL (unexpected result '$res')\n";
$fail++;
}
}
+647
View File
@@ -0,0 +1,647 @@
#!/usr/bin/perl
#
# cm_lookup.agi version 2.6
#
# for use with a Call Menu in the custom dialplan section.
#
# ; settings for this script:
# ; 1. The vicidial_list field to do a lookup on ('vendor_lead_code' is default)
# ; 2. Type of lookup to do: (default is SYSTEM)
# ; SYSTEM will search the entire system
# ; CAMPAIGNLISTS will search inside all of the active lists within the campaign
# ; CAMPLISTSALL will search inside all of the active and inactive lists within the campaign
# ; LIST will search only within the specified List ID
# ; 3. If CAMPAIGN or LIST is used above, this is the campaign_id or list_id to be used
# ; 4. TTS confirmation of name (1 for yes, 2 for no) put in TTS prompt ID
# ; 5. Update the vicidial_list record phone number with the callerID of the caller:
# ; Y - update the record with the phone number
# ; N - Do nothing (default)
# ; 6. Update lead's address3 field to the uniqueid of the call
# ; Y - update the record with the uniqueid
# ; N - Do nothing (default)
# ; 7. Update the lead's record with the call's agent_user_id variable
# ; Y - update the lead record's 'user' field with the agent_user_id variable
# ; COMMENTS - update the lead record's 'comments' field with the agent_user_id variable
# ; N - Do nothing (default)
# ; 8. Update the lead's record with the call's title variable
# ; Y - update the lead record's 'title' field with the call's title variable
# ; N - Do nothing (default)
#
# Found entries will send the call to the 'A' option in the source call menu
# Not-Found entries will send the call to the 'B' option in the source call menu
#
#; example with 8-digit vendor lead codes
# exten => _XXXXXXXX,1,AGI(cm_lookup.agi,vendor_lead_code---CAMPLISTSALL---TESTCAMP---lastname_oneyestwono---N---N---Y---N)
#
#; example with 8-digit vendor lead codes
# exten => _XXXXXXXX,1,AGI(cm_lookup.agi,vendor_lead_code---CAMPLISTSALL---TESTCAMP---lastname_oneyestwono---N---N---Y---N)
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 111004-1450 - First Build
# 111212-1507 - Added update of vicidial_list phone_number with caller callerid number option
# 120511-1508 - Added option for 'address3' uniqueid update and 'user' agent_user_id field update if AGENT-dial-in AGI is used beforoe this AGI
# 120604-1311 - Added title call variable option
# 120824-1221 - Added filtering for non-digits in extension, and example of variable-digit account number
# 130108-1817 - Changes for Asterisk 1.8 compatibility
#
$script = 'cm_lookup.agi';
$S='*';
$US='_';
$vicidial_list_fields = '|lead_id|vendor_lead_code|source_id|list_id|gmt_offset_now|called_since_last_reset|phone_code|phone_number|title|first_name|middle_initial|last_name|address1|address2|address3|city|state|province|postal_code|country_code|gender|date_of_birth|alt_phone|email|security_phrase|comments|called_count|last_local_call_time|rank|owner|status|entry_date|entry_list_id|modify_date|user|q01|q02|q03|q04|q05|q06|q07|q08|q09|q10|q11|q12|q13|q14|q15|q16|q17|q18|q19|q20|q21|q22|q23|q24|q25|q26|q27|q28|q29|q30|q31|q32|q33|q34|q35|q36|q37|q38|q39|q40|q41|q42|q43|q44|q45|q46|q47|q48|q49|q50|q51|q52|q53|q54|q55|q56|q57|q58|q59|q60|q61|q62|q63|q64|q65|q66|q67|q68|q69|q70|q71|q72|q73|q74|q75|q76|q77|q78|q79|q80|q81|q82|q83|q84|q85|q86|q87|q88|q89|q90|q91|q92|q93|q94|q95|q96|q97|q98|q99|';
($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";
$CLInow_date = "$year-$mon-$mday\\ $hour:$min:$sec";
$start_time=$now_date;
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec";
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$SQLdateBEGIN = $SQLdate;
while (length($CIDdate) > 9) {$CIDdate =~ s/^.//gi;} # 0902235959 changed to 902235959
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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";}
if (!$CEPLOGfile) {$CEPLOGfile = "$PATHlogs/Cepstral.$year-$mon-$mday";}
use DBI;
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
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,local_gmt 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];
$local_gmt = $aryA[1];
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]);
$field = $ARGV_vars[0];
$search_method = $ARGV_vars[1];
$search_id = $ARGV_vars[2];
$tts_prompt = $ARGV_vars[3];
$phone_update = $ARGV_vars[4];
$uniqueid_address3 = $ARGV_vars[5];
$agent_id_update = $ARGV_vars[6];
$title_update = $ARGV_vars[7];
}
if ( (length($field) < 2) || ($vicidial_list_fields !~ /\|$field\|/) )
{$field = 'vendor_lead_code';}
if (length($search_method) < 1)
{$search_method = 'SYSTEM';}
if (length($search_id) < 1)
{$search_method = 'SYSTEM';}
### END parsing run-time options ###
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_priority\:\s+(.*)$/) {$priority = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D|\'//gi;
$calleridname =~ s/unknown|\'//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
# remove non-digits from extension
$extension =~ s/\D//gi;
$agent_user_id = $AGI->get_variable('agent_user_id');
$call_var_title = $AGI->get_variable('title');
if ( ($AGILOG) && (length($agent_user_id)>0) ) {$agi_string = "user id AGI variables: |$agent_user_id|$call_var_title|"; &agi_output;}
$listSQL = '';
if ($search_method =~ /LIST$/)
{$listSQL = "and list_id='$search_id'";}
if ($search_method =~ /CAMPAIGNLISTS$|CAMPLISTSALL$/)
{
$activeSQL='';
if ($search_method =~ /CAMPAIGNLISTS$/)
{$activeSQL = "where active='Y'";}
### Grab all active lists associated with campaign_id
$cbc=0;
$SlistsSQL='';
$stmtA = "SELECT list_id FROM vicidial_lists where campaign_id='$search_id' $activeSQL limit 1000;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
while ($sthArows > $cbc)
{
@aryA = $sthA->fetchrow_array;
$SlistsSQL .= "'$aryA[0]',";
$cbc++;
}
$sthA->finish();
chop($SlistsSQL);
if (length($SlistsSQL)>3)
{$listSQL = "and list_id IN($SlistsSQL)";}
}
if ($AGILOG) {$agi_string = "searching for account by $field|$search_method|$search_id|$extension"; &agi_output;}
$found_extension='B';
$found_priority='1';
$stmtA= "SELECT lead_id,phone_number,first_name,last_name from vicidial_list where $field='$extension' $listSQL order by last_local_call_time desc 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;
$lead_id = $aryA[0];
$phone_number = $aryA[1];
$first_name = $aryA[2];
$last_name = $aryA[3];
$sthA->finish();
$found_extension='A';
$found_priority='1';
$confirmation=1;
### BEGIN if TTS prompt is defined, generate it and wait for "1 for yes or 2 for no" response
### if no response or no match then continue on as if nothing played
if (length($tts_prompt)>1)
{
if ($AGILOG) {$agi_string = "-- TTS : |$tts_prompt|"; &agi_output;}
$stmtA = "SELECT lead_id,entry_date,modify_date,status,user,vendor_lead_code,source_id,list_id,phone_number,title,first_name,middle_initial,last_name,address1,address2,address3,city,state,province,postal_code,country_code,gender,date_of_birth,alt_phone,email,security_phrase,comments,called_count,last_local_call_time,rank,owner FROM vicidial_list where lead_id='$lead_id';";
$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;
$TTS_lead_id = $aryA[0];
$TTS_entry_date = $aryA[1];
$TTS_modify_date = $aryA[2];
$TTS_status = $aryA[3];
$TTS_user = $aryA[4];
$TTS_vendor_lead_code = $aryA[5];
$TTS_source_id = $aryA[6];
$TTS_list_id = $aryA[7];
$TTS_phone_number = $aryA[8];
$TTS_title = $aryA[9];
$TTS_first_name = $aryA[10];
$TTS_middle_initial = $aryA[11];
$TTS_last_name = $aryA[12];
$TTS_address1 = $aryA[13];
$TTS_address2 = $aryA[14];
$TTS_address3 = $aryA[15];
$TTS_city = $aryA[16];
$TTS_state = $aryA[17];
$TTS_province = $aryA[18];
$TTS_postal_code = $aryA[19];
$TTS_country_code = $aryA[20];
$TTS_gender = $aryA[21];
$TTS_date_of_birth = $aryA[22];
$TTS_alt_phone = $aryA[23];
$TTS_email = $aryA[24];
$TTS_security_phrase = $aryA[25];
$TTS_comments = $aryA[26];
$TTS_called_count = $aryA[27];
$TTS_last_local_call_time = $aryA[28];
$TTS_rank = $aryA[29];
$TTS_owner = $aryA[30];
}
$sthA->finish();
$stmtA = "SELECT tts_text,tts_voice FROM vicidial_tts_prompts where tts_id='$tts_prompt';";
$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;
$TTS_voice = $aryA[1];
$TTS_text = $aryA[0];
### BEGIN replace variables with record values ###
$TTS_text =~ s/--A--lead_id--B--/$TTS_lead_id/gi;
$TTS_text =~ s/--A--entry_date--B--/$TTS_entry_date/gi;
$TTS_text =~ s/--A--modify_date--B--/$TTS_modify_date/gi;
$TTS_text =~ s/--A--status--B--/$TTS_status/gi;
$TTS_text =~ s/--A--user--B--/$TTS_user/gi;
$TTS_text =~ s/--A--vendor_lead_code--B--/$TTS_vendor_lead_code/gi;
$TTS_text =~ s/--A--source_id--B--/$TTS_source_id/gi;
$TTS_text =~ s/--A--list_id--B--/$TTS_list_id/gi;
$TTS_text =~ s/--A--phone_number--B--/$TTS_phone_number/gi;
$TTS_text =~ s/--A--title--B--/$TTS_title/gi;
$TTS_text =~ s/--A--first_name--B--/$TTS_first_name/gi;
$TTS_text =~ s/--A--middle_initial--B--/$TTS_middle_initial/gi;
$TTS_text =~ s/--A--last_name--B--/$TTS_last_name/gi;
$TTS_text =~ s/--A--address1--B--/$TTS_address1/gi;
$TTS_text =~ s/--A--address2--B--/$TTS_address2/gi;
$TTS_text =~ s/--A--address3--B--/$TTS_address3/gi;
$TTS_text =~ s/--A--city--B--/$TTS_city/gi;
$TTS_text =~ s/--A--state--B--/$TTS_state/gi;
$TTS_text =~ s/--A--province--B--/$TTS_province/gi;
$TTS_text =~ s/--A--postal_code--B--/$TTS_postal_code/gi;
$TTS_text =~ s/--A--country_code--B--/$TTS_country_code/gi;
$TTS_text =~ s/--A--gender--B--/$TTS_gender/gi;
$TTS_text =~ s/--A--date_of_birth--B--/$TTS_date_of_birth/gi;
$TTS_text =~ s/--A--alt_phone--B--/$TTS_alt_phone/gi;
$TTS_text =~ s/--A--email--B--/$TTS_email/gi;
$TTS_text =~ s/--A--security_phrase--B--/$TTS_security_phrase/gi;
$TTS_text =~ s/--A--comments--B--/$TTS_comments/gi;
$TTS_text =~ s/--A--called_count--B--/$TTS_called_count/gi;
$TTS_text =~ s/--A--last_local_call_time--B--/$TTS_last_local_call_time/gi;
$TTS_text =~ s/--A--rank--B--/$TTS_rank/gi;
$TTS_text =~ s/--A--owner--B--/$TTS_owner/gi;
### END replace variables with record values ###
### BEGIN check for --C-- and --D-- tags for static file replacement
if ( ($TTS_text =~ /--C--/) || ($TTS_text =~ /--D--/) )
{
$Cdash='--C--';
$Ddash='--D--';
@static_check = split(/--C--/,$TTS_text);
$sc=0;
$sr=0;
foreach(@static_check)
{
if ($sc > 0)
{
$static_check[$sc] =~ s/--D-.*//gi;
$static_check_lc = lc($static_check[$sc]);
print STDERR " Checking For Static Replacement: $static_check[$sc]|$static_check_lc$wav\n";
$static_found=0;
if (-e "/var/lib/asterisk/sounds/tts_static/$static_check_lc$wav")
{
$CDstatic = "<audio src='/var/lib/asterisk/sounds/tts_static/$static_check_lc$wav' /> ";
$static_found++;
}
else
{
if (-e "/var/lib/asterisk/sounds/$static_check_lc$wav")
{
$CDstatic = "<audio src='/var/lib/asterisk/sounds/$static_check_lc$wav' /> ";
$static_found++;
}
else
{
$firsttwo = substr($static_check_lc, 0, 2);
if (-e "/var/lib/asterisk/sounds/tts_static/$firsttwo/$static_check_lc$wav")
{
$CDstatic = "<audio src='/var/lib/asterisk/sounds/tts_static/$firsttwo/$static_check_lc$wav' /> ";
$static_found++;
}
}
}
if ($static_found > 0)
{
$CDmatch = "$Cdash$static_check[$sc]$Ddash";
$TTS_text =~ s/$CDmatch/$CDstatic/gi;
print STDERR " Static Replacement Found: $CDmatch|$CDstatic\n";
$sr++;
}
}
$sc++;
}
$TTS_text =~ s/--C--|--D--//gi;
print STDERR "\nStatic Replacements Found: $sc|$sr\n";
}
### END check for --C-- and --D-- tags for static file replacement
### filter input for CLI-safe characters
$TTS_text =~ s/[^,\.\<\>\'\/\=\_\-\: 0-9a-zA-Z]//gi;
$TTS_textRAW = $TTS_text;
$TTS_text =~ s/ /\\ /gi;
$TTS_text =~ s/\./\\./gi;
$TTS_text =~ s/\=/\\=/gi;
$TTS_text =~ s/\</\\</gi;
$TTS_text =~ s/\>/\\>/gi;
$TTS_text =~ s/\//\\\//gi;
$TTS_text =~ s/\n|\r/ /gi;
$TTS_text =~ s/\'/\\'/gi;
# $voice = 'Allison-8kHz'; # override the voice to Allison-8k
print STDERR "\nGenerating: $TTS_text - $TTS_voice\n";
### send command to generate cepstral TTS audio file
`$PATHagi/cepstral_generate.pl --debug --voice=$TTS_voice --dialog=$TTS_text >> $CEPLOGfile `;
use Digest::MD5 qw(md5_hex);
$enc = md5_hex("$TTS_textRAW-$TTS_voice"); # the hash
$enc_ftl = substr($enc, 0, 2); # first letter of hash
$TTS_filename_path = $PATHsounds . "/tts/" . $enc_ftl . "/tts-" . $enc;
print STDERR "\nfilename: $TTS_filename_path\n";
$confirm_entry_prompt = $TTS_filename_path;
$confirmation=0;
$confirmation_chances=0;
$ms_delay='6000';
while ( ($confirmation_chances < 2) && ($confirmation < 1) )
{
$confirmation_chances++;
&confirm_entry;
if ($ANSWER_confirm > 1)
{
$found_extension='B';
$found_priority='1';
$confirmation_chances=99;
if ($AGILOG) {$agi_string = "account not confirmed: $ANSWER_confirm|$lead_id"; &agi_output;}
}
if ( ($ANSWER_confirm > 0) && ($ANSWER_confirm < 2) )
{
$confirmation=1;
}
}
}
$sthA->finish();
}
### END if TTS prompt is defined, generate it and wait for "1 for yes or 2 for no" response
# YmddhhmmssLLLLLLLLLL CID format
$PADlead_id = sprintf("%010s", $lead_id); while (length($PADlead_id) > 10) {chop($PADlead_id);}
$YqueryCID = "Y$CIDdate$PADlead_id";
$Ynewcallerid = "\"$YqueryCID <$callerid>\"";
if ($AGILOG) {$agi_string = "account found: $lead_id|$phone_number|$first_name|$last_name|$Ynewcallerid"; &agi_output;}
$AGI->set_callerid($Ynewcallerid);
if ($confirmation > 0)
{
$phone_update_SQL='';
$user_update_SQL='';
$uniqueid_address3_SQL='';
$title_update_SQL='';
if ($phone_update =~ /Y/i)
{
if ( (length($callerid) > 6) && ($callerid !~ /unknown|private/i) )
{$phone_update_SQL = ",phone_number='$callerid'";}
else
{
if ($AGILOG) {$agi_string = "-- CMLOOKUP vl record failed: Invalid CIDnumber - $callerid|$phone_number"; &agi_output;}
}
}
if ($uniqueid_address3 =~ /Y/)
{$uniqueid_address3_SQL = ",address3='$uniqueid'";}
if ( (length($call_var_title) > 0) && ($title_update =~ /Y/i) )
{$title_update_SQL = ",title='$call_var_title'";}
if (length($agent_user_id) > 1)
{
if ($agent_id_update =~ /COMMENT/i)
{$user_update_SQL = ",comments='$agent_user_id'";}
if ($agent_id_update =~ /Y/i)
{$user_update_SQL = ",user='$agent_user_id'";}
}
$stmtA = "UPDATE vicidial_list SET modify_date=NOW() $phone_update_SQL $user_update_SQL $uniqueid_address3_SQL $title_update_SQL where lead_id='$lead_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- CMLOOKUP vl record updated: |$affected_rows| $lead_id|$callerid|$phone_number|$first_name|$last_name|$agent_user_id|$call_var_title|$uniqueid|"; &agi_output;}
}
}
else
{
$sthA->finish();
$INVCOUNT = $AGI->get_variable(INVCOUNT);
$INVCOUNT = ($INVCOUNT + 1);
$INVCOUNT_set = $AGI->set_variable('INVCOUNT', "$INVCOUNT");
if ($AGILOG) {$agi_string = "account not found: $INVCOUNT"; &agi_output;}
}
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
if ($AGILOG) {$agi_string = "exiting the cm_lookup.agi app, transferring call to $found_extension @ $context + $found_priority"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $found_extension\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY $found_priority\n";
$result = <STDIN>;
checkresult($result);
exit;
######### SUBROUTINES #################
sub checkresult
{
$pass=0; $fail=0;
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='';
}
##### BEGIN confirm entry, 1 or 2 ######################################
sub confirm_entry
{
$interrupt_digit='';
$audio_file = "$confirm_entry_prompt";
if ($language =~ /es/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_es';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
else
{$audio_suffix='';}
$interrupt_digit = $AGI->stream_file("$audio_file$audio_suffix",'12');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$ANSWER_confirm='';
if ($interrupt_digit > 0)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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;}
$ANSWER_confirm=$interrupt_digit;
}
if (length($ANSWER_confirm) < 1)
{
$digit_loop_counter=0;
while ( ($digits_being_entered > 0) && ($digit_loop_counter < 1) )
{
$digit = chr($AGI->wait_for_digit("$ms_delay")); # wait 10 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
$ANSWER_confirm = "$ANSWER_confirm$digit";
print STDERR "digit |$digit| ANSWER_confirm |$ANSWER_confirm|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digits_being_entered=0;
}
$digit_loop_counter++;
}
}
$ANSWER_confirm =~ s/\D//gi;
if ($ANSWER_confirm) {print STDERR "digit |$digit| ANSWER_confirm |$ANSWER_confirm|\n";}
}
##### END confirm entry ######################################
+332
View File
@@ -0,0 +1,332 @@
#!/usr/bin/perl
#
# cm_postal.agi version 2.12
#
# Designed to work with Cell Menus to allow searching of the number entered by
# the customer to be searched within the vicidial_postal_codes table to gather
# the state, then search the vicidial_inbound_dids table for that state in the
# did_carrier_description field and send the call on to the did that matches.
#
# If postal code is not found call will go to the 'D' option in the call menu
# If state DID is not found call will go to the 'C' option in the call menu
#
# Flag Options:
# 1- minimum number of digits allowed in postal code, default 5
# 2- DID prefix to filter by in searching for DIDs, default 999
#
# example of what to put in the Custom Dialplan entry for a Call Menu:
#exten => _XXXXX,1,AGI(cm_postal.agi,5---999)
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 160517-0236 - First build
#
$script = 'cm_postal.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$start_time=$now_date;
$CIDdate = "$mon$mday$hour$min$sec";
$tsSQLdate = "$year$mon$mday$hour$min$sec";
$SQLdate = "$year-$mon-$mday $hour:$min:$sec";
$SQLdateBEGIN = $SQLdate;
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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]);
$postal_length = $ARGV_vars[0];
$did_prefix = $ARGV_vars[1];
}
if (length($postal_length) < 1)
{$postal_length = 5;}
if (length($did_prefix) < 1)
{$did_prefix = '999';}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
$callerid =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$calleridname =~ s/\'|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
$extension =~ s/\'|\"|\\\\|\\\|\\|\\;|\\\;|\;|;//gi;
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
if (length($calleridname)>0) {$VLcomments = $calleridname;}
else {$VLcomments = '';}
if (length($callerid)<10) {$callerid = $parked_by;}
if (length($pin)>0) {$callerid = $pin;}
}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$g=0;
$state='';
### only perform search if minimum digits entered is valid ###
if (length($extension) >= $postal_length)
{
### search for state using entered postal code ###
$stmtA= "SELECT state from vicidial_postal_codes where postal_code='$extension';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($AGILOG) {$agi_string = "$sthArows|$stmtA|"; &agi_output;}
while ($sthArows > $g)
{
@aryA = $sthA->fetchrow_array;
$state = $aryA[0];
$g++;
}
$sthA->finish();
}
# State not found, send call to 'D' option in call menu
if ($g < 1)
{
if ($AGILOG) {$agi_string = "entry not found($extension), exiting the cm_postal.agi app, transferring call to D @ $context"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION D\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
}
### search for DID using found state and optional DID prefix ###
$DID_prefixSQL='';
$new_did='';
if (length($did_prefix)>0) {$DID_prefixSQL = "and did_pattern LIKE \"$did_prefix%\"";}
$stmtA= "SELECT did_pattern from vicidial_inbound_dids where did_carrier_description LIKE \"$state%\" $DID_prefixSQL;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($AGILOG) {$agi_string = "$sthArows|$stmtA|"; &agi_output;}
$g=0;
while ($sthArows > $g)
{
@aryA = $sthA->fetchrow_array;
$new_did = $aryA[0];
$g++;
}
$sthA->finish();
$dbhA->disconnect();
# DID not found, send call to 'C' option in call menu
if ($g < 1)
{
if ($AGILOG) {$agi_string = "entry not found($state|$extension), exiting the cm_postal.agi app, transferring call to C @ $context"; &agi_output;}
print "SET CONTEXT $context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION C\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
}
else
{
$AGI->exec("EXEC Set(_state=$state)");
$AGI->exec("EXEC Set(_postal_code=$extension)");
if ($AGILOG) {$agi_string = "entry found($state|$extension), exiting the cm_postal.agi app, transferring call to $new_did @ trunkinbound"; &agi_output;}
print "SET CONTEXT trunkinbound\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $new_did\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
}
##### SUBROUTINES #####
sub agi_output
{
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$now_date|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$now_date|$script|$agi_string\n";}
$agi_string='';
}
sub checkresult
{
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/)
{
$res =~ /result=(-?\d+)/;
if (!length($1))
{
# print STDERR "FAIL ($res)\n";
$fail++;
}
else
{
# print STDERR "PASS ($1)\n";
$pass++;
}
}
else
{
# print STDERR "FAIL (unexpected result '$res')\n";
$fail++;
}
}
@@ -0,0 +1,390 @@
#!/usr/bin/perl
#
# cm_speak_var.agi version 2.10
#
# runs after a call has lead_id assigned to it, speaks letters/numbers
#
# You need to put lines similar to those below in your Custom Dialplan:
#
# exten => 8412,1,Answer
# exten => 8412,n,AGI(cm_speak_var.agi,say_digits---security_phrase)
# exten => 8412,n,Hangup
#
# CLI FLAG OPTIONS:
# 1. function: (say_digits, say_number, say_alpha, say_datetime, say_phonetic, stream_file)
# 2. field: (any vicidial_list field)
#
# Copyright (C) 2014 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 140619-2005 - first build
#
$script = 'cm_speak_var.agi';
$CM_LOG = 1; # set to 1 for logfile
($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 = <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 (!$CMLOGfile) {$CMLOGfile = "$PATHlogs/cmout.$year-$mon-$mday";}
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_function = $ARGV_vars[0];
$CLI_field = $ARGV_vars[1];
}
$|=1;
while(<STDIN>)
{
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;
}
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;
}
if ($AGILOG) {$agi_string = "AGI Environment Dump:"; &agi_output;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
$callerid =~ s/\"//gi;
$callerid =~ s/ .*//gi;
$CIDlead_id = $callerid;
if ( ($calleridname =~ /^DC/) && ($calleridname =~ /\d\d\d\d\d\d\d\d\d\dW$/) ) #DC234728W0001010141W
{$CIDlead_id = substr($calleridname, 9, 10);}
else
{$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 = "+++++ cm_speak_var START : |$CLI_function|$CLI_field|$CIDlead_id|$now_date|$AST_ver|$priority|$calleridname|"; &agi_output;}
if ($CM_LOG)
{
open(Lout, ">>$CMLOGfile")
|| die "Can't open $CMLOGfile: $!\n";
print Lout "$now_date|$VD_lead_id| |$CLI_function|$CLI_field|$calleridnum|$callerid|\n";
close(Lout);
}
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$stmtA = "SELECT lead_id,entry_date,modify_date,status,user,vendor_lead_code,source_id,list_id,phone_number,title,first_name,middle_initial,last_name,address1,address2,address3,city,state,province,postal_code,country_code,gender,date_of_birth,alt_phone,email,security_phrase,comments,called_count,last_local_call_time,rank,owner FROM vicidial_list where lead_id='$VD_lead_id';";
$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;
$CM_lead_id = $aryA[0];
$CM_entry_date = $aryA[1];
$CM_modify_date = $aryA[2];
$CM_status = $aryA[3];
$CM_user = $aryA[4];
$CM_vendor_lead_code = $aryA[5];
$CM_source_id = $aryA[6];
$CM_list_id = $aryA[7];
$CM_phone_number = $aryA[8];
$CM_title = $aryA[9];
$CM_first_name = $aryA[10];
$CM_middle_initial = $aryA[11];
$CM_last_name = $aryA[12];
$CM_address1 = $aryA[13];
$CM_address2 = $aryA[14];
$CM_address3 = $aryA[15];
$CM_city = $aryA[16];
$CM_state = $aryA[17];
$CM_province = $aryA[18];
$CM_postal_code = $aryA[19];
$CM_country_code = $aryA[20];
$CM_gender = $aryA[21];
$CM_date_of_birth = $aryA[22];
$CM_alt_phone = $aryA[23];
$CM_email = $aryA[24];
$CM_security_phrase = $aryA[25];
$CM_comments = $aryA[26];
$CM_called_count = $aryA[27];
$CM_last_local_call_time = $aryA[28];
$CM_rank = $aryA[29];
$CM_owner = $aryA[30];
}
$sthA->finish();
if ($CLI_field =~ /lead_id/) {$field_value = $CM_lead_id;}
if ($CLI_field =~ /entry_date/) {$field_value = $CM_entry_date;}
if ($CLI_field =~ /modify_date/) {$field_value = $CM_modify_date;}
if ($CLI_field =~ /status/) {$field_value = $CM_status;}
if ($CLI_field =~ /user/) {$field_value = $CM_user;}
if ($CLI_field =~ /vendor_lead_code/) {$field_value = $CM_vendor_lead_code;}
if ($CLI_field =~ /source_id/) {$field_value = $CM_source_id;}
if ($CLI_field =~ /list_id/) {$field_value = $CM_list_id;}
if ($CLI_field =~ /phone_number/) {$field_value = $CM_phone_number;}
if ($CLI_field =~ /title/) {$field_value = $CM_title;}
if ($CLI_field =~ /first_name/) {$field_value = $CM_first_name;}
if ($CLI_field =~ /middle_initial/) {$field_value = $CM_middle_initial;}
if ($CLI_field =~ /last_name/) {$field_value = $CM_last_name;}
if ($CLI_field =~ /address1/) {$field_value = $CM_address1;}
if ($CLI_field =~ /address2/) {$field_value = $CM_address2;}
if ($CLI_field =~ /address3/) {$field_value = $CM_address3;}
if ($CLI_field =~ /city/) {$field_value = $CM_city;}
if ($CLI_field =~ /state/) {$field_value = $CM_state;}
if ($CLI_field =~ /province/) {$field_value = $CM_province;}
if ($CLI_field =~ /postal_code/) {$field_value = $CM_postal_code;}
if ($CLI_field =~ /country_code/) {$field_value = $CM_country_code;}
if ($CLI_field =~ /gender/) {$field_value = $CM_gender;}
if ($CLI_field =~ /date_of_birth/) {$field_value = $CM_date_of_birth;}
if ($CLI_field =~ /alt_phone/) {$field_value = $CM_alt_phone;}
if ($CLI_field =~ /email/) {$field_value = $CM_email;}
if ($CLI_field =~ /security_phrase/) {$field_value = $CM_security_phrase;}
if ($CLI_field =~ /comments/) {$field_value = $CM_comments;}
if ($CLI_field =~ /called_count/) {$field_value = $CM_called_count;}
if ($CLI_field =~ /last_local_call_time/) {$field_value = $CM_last_local_call_time;}
if ($CLI_field =~ /rank/) {$field_value = $CM_rank;}
if ($CLI_field =~ /owner/) {$field_value = $CM_owner;}
if ($CLI_function =~ /say_digits/)
{
$AGI->say_digits("$field_value");
}
if ($CLI_function =~ /say_number/)
{
$AGI->say_number("$field_value");
}
if ($CLI_function =~ /say_alpha/)
{
$AGI->say_alpha("$field_value");
}
if ($CLI_function =~ /say_datetime/)
{
$AGI->say_datetime("$field_value");
}
if ($CLI_function =~ /say_phonetic/)
{
$AGI->say_phonetic("$field_value");
}
if ($CLI_function =~ /stream_file/)
{
$AGI->stream_file("$field_value");
}
$dbhA->disconnect();
#$AGI->hangup($channel);
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 );
}
@@ -0,0 +1,352 @@
#!/usr/bin/perl
#
# cm_status_dial.agi version 2.6
#
# Used as a Call Menu AGI option route to alter status of a lead before dialing.
# The lead is only updated if the call is tagged with a lead_id before this script.
#
# You need to put lines similar to those below in your extensions.conf file:
# ; Below are the parameters needed for the script to be run properly
# ; 1. the status to change the lead to
# ; 2. the phone number or extension to dial
# ; 3. the context to dial in
# ;
# ;inbound calls check calltime:
#cm_status_dial.agi,XFER-----917275551212-----default
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 120909-2301 - First Build
# 120924-0637 - Added log updating
# 130108-1820 - Changes for Asterisk 1.8 compatibility
#
$script = 'cm_status_dial.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = "$aryA[0]";
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
}
$sthA->finish();
#############################################
##### START QUEUEMETRICS LOGGING LOOKUP #####
$stmtA = "SELECT enable_queuemetrics_logging,queuemetrics_server_ip,queuemetrics_dbname,queuemetrics_login,queuemetrics_pass,queuemetrics_log_id,queuemetrics_eq_prepend 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;
$enable_queuemetrics_logging = $aryA[0];
$queuemetrics_server_ip = $aryA[1];
$queuemetrics_dbname = $aryA[2];
$queuemetrics_login= $aryA[3];
$queuemetrics_pass = $aryA[4];
$queuemetrics_log_id = $aryA[5];
$queuemetrics_eq_prepend = $aryA[6];
}
$sthA->finish();
##### END QUEUEMETRICS LOGGING LOOKUP #####
###########################################
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
if ($AGILOG) {$agi_string = "Perl Environment Dump:"; &agi_output;}
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
if ($AGILOG) {$agi_string = "$i|$ARGV[$i]"; &agi_output;}
$i++;
}
### list of command-line array arguments:
@ARGV_vars = split(/-----/, $ARGV[0]);
$new_status = $ARGV_vars[0];
$dial_extension = $ARGV_vars[1];
$dial_context = $ARGV_vars[2];
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_priority\:\s+(.*)$/) {$priority = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
$outboundIVR=0;
$fieldUPDATE=0;
if ($calleridname =~ /^V\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/)
{
$phone_number = $callerid;
$callerid = $calleridname;
$outboundIVR=1;
$stmtA = "SELECT campaign_id,lead_id FROM vicidial_auto_calls where callerid='$callerid';";
$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_id = $aryA[0];
$lead_id = $aryA[1];
}
$sthA->finish();
}
elsif ($calleridname =~ /^Y\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/)
{
$lead_id = substr($calleridname, 10, 10);
$lead_id = ($lead_id + 0);
$phone_number = $callerid;
$callerid = $calleridname;
$fieldUPDATE=1;
}
else
{
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D|\'//gi;
$calleridname =~ s/unknown|\'//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
if (length($calleridname)>0) {$VLcomments = $calleridname;}
else {$VLcomments = '';}
}
if (length($callerid)<8) {$callerid = $parked_by;}
if (length($pin)>0) {$callerid = $pin;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
if (length($pin) < 1) {$pin=$inbound_number;}
$fronter = $pin;
if ($AGILOG) {$agi_string = "+++++ STATUS DIAL LOG STARTED : |$channel_group|$callerid-$pin|$now_date"; &agi_output;}
$VDADphone='';
$VDADphone_code='';
if ($channel =~ /Local/i)
{
if ($AGILOG) {$agi_string = "+++++ STATUS DIAL START LOCAL CHANNEL: EXITING- $priority"; &agi_output;}
exit;
}
### insert an IVR record to the vicidial_auto_calls table
if ($outboundIVR > 0)
{
$stmtA = "UPDATE vicidial_list SET status='$new_status' where lead_id='$lead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VL update: |$affected_rowsL|$new_status|$dtmf|$lead_id|$context|"; &agi_output;}
$stmtA = "UPDATE vicidial_log SET status='$new_status' where lead_id='$lead_id' order by call_date desc limit 1;";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VLOG update: |$affected_rowsL|$new_status|$dtmf|$lead_id|$context|"; &agi_output;}
}
else
{
if ($fieldUPDATE > 0)
{
$stmtA = "UPDATE vicidial_list SET status='$new_status' where lead_id='$lead_id';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VL update: |$affected_rowsL|$new_status|$dtmf|$lead_id|$context|"; &agi_output;}
$stmtA = "UPDATE vicidial_closer_log SET status='$new_status' where lead_id='$lead_id' order by call_date desc limit 1;";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rowsL = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- VCLOG update: |$affected_rowsL|$new_status|$dtmf|$lead_id|$context|"; &agi_output;}
}
}
### QueueMetrics logging if enabled
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;
$stmtB = "UPDATE queue_log SET data1='$new_status' where call_id='$calleridname' and verb='CALLSTATUS' order by time_id desc limit 1;";
if ($AGILOG) {$agi_string = "|$stmtB|"; &agi_output;}
$Baffected_rows = $dbhB->do($stmtB);
$dbhB->disconnect();
if ($DBX) {print "QueueMetrics UPDATE: $queuemetrics_server_ip|$queuemetrics_dbname|$calleridname|$new_status\n";}
}
$sthA->finish();
$dbhA->disconnect();
if ($AGILOG) {$agi_string = " Status Dial, transferring call |$dial_extension|$dial_context|$lead_id|$calleridname|"; &agi_output;}
print "SET CONTEXT $dial_context\n";
$result = <STDIN>;
checkresult($result);
print "SET EXTENSION $dial_extension\n";
$result = <STDIN>;
checkresult($result);
print "SET PRIORITY 1\n";
$result = <STDIN>;
checkresult($result);
exit;
sub agi_output
{
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$now_date|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$now_date|$script|$agi_string\n";}
$agi_string='';
}
sub checkresult
{
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/)
{
$res =~ /result=(-?\d+)/;
if (!length($1))
{
# print STDERR "FAIL ($res)\n";
$fail++;
}
else
{
# print STDERR "PASS ($1)\n";
$pass++;
}
}
else
{
# print STDERR "FAIL (unexpected result '$res')\n";
$fail++;
}
}
@@ -0,0 +1,123 @@
#!/usr/bin/perl
#
# debug_speak.agi version 2.0.5
#
# runs during any extension and speaks the extension sent to it while
# printing the extension as well as lots of info about the call to STDERR
#
# You need to put lines similar to those below in your extensions.conf file:
#
# ;inbound errors with speaking of extension:
#exten => _XXXX,1,AGI(debug_speak.agi,${EXTEN})
#exten => _XXXX,3,Hangup
#
# Copyright (C) 2008 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
$V = 1; # set to 1 for verbose mode
$CLIOUT = 1; # set to 1 for printing 1 line to STDERR
$SPEAK = 1; # set to 1 for saying invalid digits
($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";
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
if ($CLIOUT) {print STDERR "Perl Environment Dump:\n";}
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
if ($CLIOUT) {print STDERR "$i|$ARGV[$i]|\n";}
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n [-q] = quiet\n [-t] = test\n [-debug] = verbose debug messages\n\n";
}
else
{
if ($args =~ /-V/i)
{
$V=1;
}
if ($args =~ /-debug/i)
{
$DG=1;
}
if ($args =~ /-dbAVS/i)
{
$DGA=1;
}
if ($args =~ /-q/i)
{
$q=1;
$Q=1;
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
}
}
else
{
if ($V) {print "no command line options set\n";}
}
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$|=1;
while(<STDIN>) {
chomp;
last unless length($_);
if ($V)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $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;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
if ($V)
{
if ($V) {print STDERR "AGI Environment Dump:\n";}
foreach $i (sort keys %AGI) {
if ($V) {print STDERR " -- $i = $AGI{$i}\n";}
}
}
if ($CLIOUT) {print STDERR "****** DEBUG: |$unique_id|$channel|$extension|$type|$callerid|$calleridname|\n";}
if ($SPEAK)
{
$AGI->stream_file('beep');
sleep(1);
$AGI->say_digits("$extension");
}
exit;
@@ -0,0 +1,174 @@
#!/usr/bin/perl
# getAGENTchannel.agi by Omar Rodriguez www.ItContinental.com
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
# This script is able to return the name of the channel that belongs to the agent,
# to allow administrators to whisper to the agents
# Has been made using Vicidial code as Base
# CHANGELOG:
# 150728-1315 - First build
# 150804-0944 - Rewritten to work on multi-server systems and with different dialplan
# 160523-2352 - Fixed issue with local channels in session
#
$script = 'getAGENTchannel.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
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,local_gmt 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];
$local_gmt = $aryA[1];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
}
$sthA->finish();
$agent_zap_channel = "101";
########## FIND playfilename ##########
$|=1;
while(<STDIN>)
{
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_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
}
if (length($extension) > 7)
{$extension = substr($extension, -7);}
if ($AGILOG) {$agi_string = "Agent session: $extension| Channel: $channel| CID: $calleridname <$callerid>|"; &agi_output;}
#$stmtA = "SELECT channel FROM vicidial_live_agents WHERE conf_exten = '$canal' AND ifnull(trim(channel), '') <> '' and (channel in (select channel from live_channels) or comments='MANUAL') LIMIT 1";
$stmtA = "SELECT channel FROM live_sip_channels WHERE server_ip='$VARserver_ip' AND extension=right('$extension',7) AND ifnull(trim(channel), '') <> '' limit 10;";
#$AGI->verbose($stmtA);
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$s=0;
while ($sthArows > $s)
{
@aryA = $sthA->fetchrow_array;
# channel priority(highest to lowest): SIP, IAX, Local
if ($aryA[0] =~ /^SIP/i)
{$agent_zap_channel = $aryA[0];}
if ( ($aryA[0] =~ /^IAX/i) && ( (length($agent_zap_channel) < 4) || ($agent_zap_channel =~ /^Local/i) ) )
{$agent_zap_channel = $aryA[0];}
if ( ($aryA[0] =~ /^Local/i) && (length($agent_zap_channel) < 4) )
{$agent_zap_channel = $aryA[0];}
$s++;
}
$sthA->finish();
if ($AGILOG) {$agi_string = "$sthArows|$agent_zap_channel|$stmtA|"; &agi_output;}
#$AGI->verbose("agent_zap_channel: $agent_zap_channel");
$AGI->set_variable('agent_zap_channel', $agent_zap_channel);
exit;
sub agi_output
{
($Lsec,$Lmin,$Lhour,$Lmday,$Lmon,$Lyear,$Lwday,$Lyday,$Lisdst) = localtime(time);
if ($Lhour < 10) {$Lhour = "0$Lhour";}
if ($Lmin < 10) {$Lmin = "0$Lmin";}
if ($Lsec < 10) {$Lsec = "0$Lsec";}
$LOGtime = "$Lhour:$Lmin:$Lsec";
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$LOGtime|$LOGtime|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$LOGtime|$LOGtime|$script|$agi_string\n";}
$agi_string='';
}
@@ -0,0 +1,139 @@
#!/usr/bin/perl
#
# invalid_speak.agi version 2.0.5
#
# runs during an invalid extension and speaks the extension sent to it while printing to STDERR
#
# You need to put lines similar to those below in your extensions.conf file:
#
# ;inbound errors with speaking of extension:
#exten => _XXXX,1,AGI(invalid_speak.agi,${EXTEN})
#exten => _XXXX,2,Playback(invalid)
#exten => _XXXX,3,Hangup
#
#exten => _*XXXXXXXXXX*XXXX,1,AGI(invalid_speak.agi,${EXTEN})
#exten => _*XXXXXXXXXX*XXXX,2,Playback(invalid)
#exten => _*XXXXXXXXXX*XXXX,3,Hangup
#
#exten => _*XXXXXXXXXX*XXXX*,1,AGI(invalid_speak.agi,${EXTEN})
#exten => _*XXXXXXXXXX*XXXX*,2,Playback(invalid)
#exten => _*XXXXXXXXXX*XXXX*,3,Hangup
#
#exten => _**XXXX,1,AGI(invalid_speak.agi,${EXTEN})
#exten => _**XXXX,2,Playback(invalid)
#exten => _**XXXX,3,Hangup
#
#exten => _**XXXX*,1,AGI(invalid_speak.agi,${EXTEN})
#exten => _**XXXX*,2,Playback(invalid)
#exten => _**XXXX*,3,Hangup
#
#
# Copyright (C) 2008 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
$V = 0; # set to 1 for verbose mode
$CLIOUT = 1; # set to 1 for printing 1 line to STDERR
$SPEAK = 1; # set to 1 for saying invalid digits
($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";
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
if ($V) {print STDERR "Perl Environment Dump:\n";}
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
if ($V) {print STDERR "$i|$ARGV[$i]|\n";}
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n [-q] = quiet\n [-t] = test\n [-debug] = verbose debug messages\n\n";
}
else
{
if ($args =~ /-V/i)
{
$V=1;
}
if ($args =~ /-debug/i)
{
$DG=1;
}
if ($args =~ /-dbAVS/i)
{
$DGA=1;
}
if ($args =~ /-q/i)
{
$q=1;
$Q=1;
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
}
}
else
{
if ($V) {print "no command line options set\n";}
}
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$|=1;
while(<STDIN>) {
chomp;
last unless length($_);
if ($V)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $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;}
}
if ($V)
{
if ($V) {print STDERR "AGI Environment Dump:\n";}
foreach $i (sort keys %AGI) {
if ($V) {print STDERR " -- $i = $AGI{$i}\n";}
}
}
if ($CLIOUT) {print STDERR "****** INVALID EXTENSION: |$unique_id|$channel|$extension|$type|$callerid|\n";}
if ($SPEAK)
{
$AGI->stream_file('beep');
sleep(1);
$AGI->say_digits("$extension");
}
exit;
+363
View File
@@ -0,0 +1,363 @@
#!/usr/bin/perl
#
# park_CID.agi version 2.6
#
# runs before the park extension to populate the parked_channels entry with the channel's callerid
#
# You need to put lines similar to those below in your extensions.conf file:
#
# ;outbound dialing:
# exten => 8301,1,Answer
# exten => 8301,2,AGI(park_CID.agi)
# exten => 8301,3,Playback(park)
# exten => 8301,4,Hangup
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 60731-1423 - changed to use DBI-DBD::mysql
# - changed to use /etc/astguiclient.conf for configs
# 60815-1256 - added output options check from database
# 90909-0922 - Fixed calleridname issue
# 101004-1012 - Changed park to Music On Hold, added option for park on AGI
# 130108-1817 - Changes for Asterisk 1.8 compatibility
#
$script = 'park_CID.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) )
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) )
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) )
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) )
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) )
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) )
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) )
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) )
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
if (!$VARDB_port) {$VARDB_port='3306';}
if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";}
use DBI;
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
### 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++;
}
if ($args =~ />| |\"/i)
{
@CID = split(/-----/, $args);
$fullCID=1;
$callerid = $CID[2];
$calleridname = $CID[3];
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n [-q] = quiet\n [-t] = test\n [-debug] = verbose debug messages\n\n";
}
else
{
if ($args =~ /-V/i)
{
$V=1;
}
if ($args =~ /-debug/i)
{
$DG=1;
}
if ($args =~ /-dbAVS/i)
{
$DGA=1;
}
if ($args =~ /-q/i)
{
$q=1;
$Q=1;
}
if ($args =~ /-t/i)
{
$TEST=1;
$T=1;
}
}
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (!$fullCID) # if no fullCID sent
{
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
if ( $calleridname =~ /\"/) {$calleridname =~ s/\"//gi;}
if ( (!$callerid) or ($callerid =~ /unknown/) or ( ($calleridname =~ /\d\d\d\d\d\d\d\d\d/) && (length($calleridname) > 16) ) )
{$callerid = $calleridname;}
if ( ($callerid =~ / /) && (length($callerid) > 20) )
{$callerid =~ s/ .*//gi;}
### allow for ANI being sent with the DNIS "*3125551212*9999*"
if ($extension =~ /^\*\d\d\d\d\d\d\d\d\d\d\*/)
{
$callerid = $extension;
$callerid =~ s/\*\d\d\d\d\*$//gi;
$callerid =~ s/^\*//gi;
$extension =~ s/^\*\d\d\d\d\d\d\d\d\d\d\*//gi;
$extension =~ s/\*$//gi;
}
$calleridname = $callerid;
}
}
if ($AGILOG) {$agi_string = "AGI Environment Dump:"; &agi_output;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
if ($AGILOG) {$agi_string = "CALL BEING PARKED"; &agi_output;}
$stmtA = "UPDATE parked_channels set channel_group='$callerid' where server_ip='$VARserver_ip' and channel='$channel';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- Park record updated: |$affected_rows| |$callerid|$channel|$VARserver_ip"; &agi_output;}
$VACcount=0;
$VAC_campaign_id='';
$VAC_call_type='';
$VAC_extension='';
$VLAcount=0;
$VLA_user='';
$VLA_campaign_id='';
$VCcount=0;
$park_context='default';
$MOHfiles=0;
$stmtA = "SELECT campaign_id,call_type,extension FROM vicidial_auto_calls where callerid='$callerid';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VACcount=$sthA->rows;
if ($VACcount > 0)
{
@aryA = $sthA->fetchrow_array;
$VAC_campaign_id = $aryA[0];
$VAC_call_type = $aryA[1];
$VAC_extension = $aryA[2];
}
$sthA->finish();
if ($VACcount > 0)
{
$stmtA = "SELECT user,campaign_id FROM vicidial_live_agents where callerid='$callerid';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VLAcount=$sthA->rows;
if ($VLAcount > 0)
{
@aryA = $sthA->fetchrow_array;
$VLA_user = $aryA[0];
$VLA_campaign_id = $aryA[1];
}
$sthA->finish();
if ($VLAcount > 0)
{
$stmtA = "SELECT park_file_name,ivr_park_call_agi FROM vicidial_campaigns where campaign_id='$VLA_campaign_id';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VCcount=$sthA->rows;
if ($VCcount > 0)
{
@aryA = $sthA->fetchrow_array;
$park_context = $aryA[0];
$VC_ivr_park_call_agi = $aryA[1];
}
$sthA->finish();
$stmtA = "SELECT count(*) FROM vicidial_music_on_hold_files where moh_id='$park_context';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$MOHcount=$sthA->rows;
if ($MOHcount > 0)
{
@aryA = $sthA->fetchrow_array;
$MOHfiles = $aryA[0];
}
$sthA->finish();
if ($MOHfiles< 1)
{
if ($AGILOG) {$agi_string = "-- Context empty, switching to default: |$park_context|$MOHcount|$MOHfiles| |$callerid|"; &agi_output;}
$park_context = 'default';
}
### call was parked to an IVR, launch the AGI script
if ( ($VCcount > 0) && ($VAC_extension =~ /PARK_IVR/) && (length($VC_ivr_park_call_agi)>2) )
{
if ($AGILOG) {$agi_string = "-- Starting AGI: |$VC_ivr_park_call_agi| |$callerid|"; &agi_output;}
print "EXEC AGI $VC_ivr_park_call_agi\n";
checkresult($result);
if ($AGILOG) {$agi_string = "-- AGI Done: |$callerid|"; &agi_output;}
}
}
}
$dbhA->disconnect();
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
if ($AGILOG) {$agi_string = "-- Starting MoH: |$park_context| |$callerid|"; &agi_output;}
print "SET MUSIC ON $park_context\n";
$result = <STDIN>;
checkresult($result);
sleep(360);
if ($AGILOG) {$agi_string = "-- MoH Done: |$callerid|"; &agi_output;}
exit;
sub agi_output
{
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$now_date|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$now_date|$script|$agi_string\n";}
$agi_string='';
}
sub checkresult
{
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/)
{
$res =~ /result=(-?\d+)/;
if (!length($1))
{
# print STDERR "FAIL ($res)\n";
$fail++;
}
else
{
# print STDERR "PASS ($1)\n";
$pass++;
}
}
else
{
# print STDERR "FAIL (unexpected result '$res')\n";
$fail++;
}
}
@@ -0,0 +1,728 @@
#!/usr/bin/perl
#
# park_call_IVR_cf_collect.agi version 2.12
#
# NOTE: this script is to be used with the Park Call IVR feature in campaigns.
# The purpose of this script is to allow the agent to park a call on this IVR
# and have the customer enter in sensitive numbers. This script should not
# require any modification to work.
#
# Defined in the Park Call AGI IVR field of a campaign, this script will ask
# customer for their ID and then populate it in the custom fiels defined in the
# variable below and then send the call back to the agent. If the customer
# enters nothing X number of times then the call can be kicked out to a separate
# in-group
#
# Here is a list of the variables that you can set:
# 1. Language - default: en (English), other options are es-Spanish, fr-French
# 2. First prompt - default: please_enter_id_number
# 3. You-Entered prompt - default: you-entered
# 4. Confirmation prompt - default: confirm_id_number
# 5. Thank you prompt - default: auth-thankyou
# 6. Invalid prompt - default: buzz
# 7. Attempts before kick-out - default: 2
# 8. Kick-out prompt - default: outside-transfer
# 9. Kick-out In-Group
# 10. Custom Field to populate
#
# Example Park Call AGI IVR field:
# park_call_IVR_cf_collect.agi,en---please_enter_id_number---you-entered---confirm_id_number---auth-thankyou---buzz---2---outside-transfer---TEST_IN---test2
#
# Copyright (C) 2015 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 150814-1119 - First build based on park_call_IVR_example.agi script
#
$script = 'park_call_IVR_cf_collect.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$S='*';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
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,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];
$ext_context = $aryA[1];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
}
$sthA->finish();
### Grab System Settings from the database
$stmtA = "SELECT sounds_web_server 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;
$sounds_web_server = $aryA[0];
}
$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]);
$language = $ARGV_vars[0];
$first_prompt = $ARGV_vars[1];
$you_entered_prompt = $ARGV_vars[2];
$confirmation_prompt = $ARGV_vars[3];
$thank_you_prompt = $ARGV_vars[4];
$invalid_prompt = $ARGV_vars[5];
$kickout_attempts = $ARGV_vars[6];
$kickout_prompt = $ARGV_vars[7];
$kickout_ingroup = $ARGV_vars[8];
$custom_field = $ARGV_vars[9];
}
if (length($language)<1) {$language='en';}
if (length($first_prompt)<1) {$first_prompt='please_enter_id_number';}
if (length($you_entered_prompt)<1) {$you_entered_prompt='you-entered';}
if (length($confirmation_prompt)<1) {$confirmation_prompt='confirm_id_number';}
if (length($thank_you_prompt)<1) {$thank_you_prompt='auth-thankyou';}
if (length($invalid_prompt)<1) {$invalid_prompt='buzz';}
if (length($kickout_attempts)<1) {$kickout_attempts='2';}
if (length($kickout_prompt)<1) {$kickout_prompt='outside-transfer';}
if (length($custom_field)<1) {$custom_field='test';}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $1;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (!$fullCID) # if no fullCID sent
{
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
if ( $calleridname =~ /\"/) {$calleridname =~ s/\"//gi;}
if ( (!$callerid) or ($callerid =~ /unknown/) or ( ($calleridname =~ /\d\d\d\d\d\d\d\d\d/) && (length($calleridname) > 16) ) )
{$callerid = $calleridname;}
if ( ($callerid =~ / /) && (length($callerid) > 20) )
{$callerid =~ s/ .*//gi;}
### allow for ANI being sent with the DNIS "*3125551212*9999*"
if ($extension =~ /^\*\d\d\d\d\d\d\d\d\d\d\*/)
{
$callerid = $extension;
$callerid =~ s/\*\d\d\d\d\*$//gi;
$callerid =~ s/^\*//gi;
$extension =~ s/^\*\d\d\d\d\d\d\d\d\d\d\*//gi;
$extension =~ s/\*$//gi;
}
$calleridname = $callerid;
}
}
if ($AGILOG) {$agi_string = "AGI Environment Dump:"; &agi_output;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
if ($AGILOG) {$agi_string = "PARKED CALL IVR STARTED: |$custom_field|"; &agi_output;}
$stmtA = "UPDATE parked_channels set channel_group='$callerid' where server_ip='$VARserver_ip' and channel='$channel';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- Park record updated: |$affected_rows| |$callerid|$channel|$VARserver_ip"; &agi_output;}
$VACcount=0;
$VAC_campaign_id='';
$VAC_call_type='';
$VAC_extension='';
$VLAcount=0;
$VLA_user='';
$VLA_campaign_id='';
$VCcount=0;
$MOHfiles=0;
$stmtA = "SELECT campaign_id,call_type,extension,phone_number,lead_id FROM vicidial_auto_calls where callerid='$callerid';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VACcount=$sthA->rows;
if ($VACcount > 0)
{
@aryA = $sthA->fetchrow_array;
$VAC_campaign_id = $aryA[0];
$VAC_call_type = $aryA[1];
$VAC_extension = $aryA[2];
$VAC_phone_number = $aryA[3];
$VAC_lead_id = $aryA[4];
if ($AGILOG) {$agi_string = "-- VAC Call Found: |$callerid|$VAC_campaign_id|$VAC_call_type|$VAC_extension|$VAC_phone_number|$VAC_lead_id|"; &agi_output;}
}
$sthA->finish();
if ($VACcount > 0)
{
$stmtA = "SELECT user,campaign_id,server_ip,conf_exten FROM vicidial_live_agents where callerid='$callerid';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VLAcount=$sthA->rows;
if ($VLAcount > 0)
{
@aryA = $sthA->fetchrow_array;
$VLA_user = $aryA[0];
$VLA_campaign_id = $aryA[1];
$VLA_server_ip = $aryA[2];
$VLA_conf_exten = $aryA[3];
}
$sthA->finish();
if ($VLAcount > 0)
{
if ($AGILOG) {$agi_string = "-- Starting Gather Data: |$VLA_user|$VLA_campaign_id|$kickout_attempts| |$callerid|"; &agi_output;}
### BEGIN prompt for customer ID number ($customer_id_number) ###
$customer_id_number='';
$variable='';
$confirmation=0;
$confirmation_chances=0;
$collect_digits='20';
$ms_delay='8000';
$variable_entry_prompt = $first_prompt;
$confirm_entry_prompt = $you_entered_prompt;
while ( ($confirmation_chances < $kickout_attempts) && ($confirmation < 1) )
{
$entry_chances=0;
while ( ($entry_chances < $kickout_attempts) && (length($variable) < 1) )
{
$entry_chances++;
&customer_variable_gather;
$customer_id_number = $variable;
if ( (length($customer_id_number) < 1) || (length($customer_id_number) > 20) )
{
if ($AGILOG) {$agi_string = "-- CUSTOMER ID GATHER FAIL : |$customer_id_number|"; &agi_output;}
$audio_file = $invalid_prompt; &play_audio;
$variable='';
}
}
$confirmation_chances++;
if ( (length($customer_id_number) > 0) || (length($customer_id_number) <= 20) )
{
$audio_file = $confirm_entry_prompt; &play_audio;
$AGI->say_digits("$variable");
&confirm_entry;
if ($ANSWER_confirm > 1)
{$variable='';}
if ( ($ANSWER_confirm > 0) && ($ANSWER_confirm < 2) )
{$confirmation=1;}
}
else
{
if ($entry_chances >= $kickout_attempts)
{$confirmation_chances=$kickout_attempts;}
}
}
### customer ID confirmed, update in vicidial_list and tag agent for update
if ($confirmation > 0)
{
$stmtA = "SELECT list_id FROM vicidial_list where lead_id='$VAC_lead_id';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VACcount=$sthA->rows;
if ($VACcount > 0)
{
@aryA = $sthA->fetchrow_array;
$VL_list_id = $aryA[0];
if ($AGILOG) {$agi_string = "-- VL List Found: |$VL_list_id|$callerid|$VAC_lead_id|"; &agi_output;}
}
$sthA->finish();
### find wget binary
$wgetbin = '';
if ( -e ('/bin/wget')) {$wgetbin = '/bin/wget';}
else
{
if ( -e ('/usr/bin/wget')) {$wgetbin = '/usr/bin/wget';}
else
{
if ( -e ('/usr/local/bin/wget')) {$wgetbin = '/usr/local/bin/wget';}
else
{
print "Can't find wget binary! Exiting...\n";
exit;
}
}
}
### URL to be sent to populate the custom field value that was collected from the customer
$parse_url = "http://$sounds_web_server/agc/update_cf_ivr.php\?lead_id=$VAC_lead_id&caller_id=$callerid&list_id=$VL_list_id&field=$custom_field&value=$customer_id_number&user=$VLA_user";
### insert a new url log entry
$SQL_log = "$parse_url";
$SQL_log =~ s/;|\||\\//gi;
$stmtA = "INSERT INTO vicidial_url_log SET uniqueid='$uniqueid',url_date='$now_date',url_type='park_ivr_cf',url='$SQL_log',url_response='';";
$affected_rows = $dbhA->do($stmtA);
$stmtB = "SELECT LAST_INSERT_ID() LIMIT 1;";
$sthA = $dbhA->prepare($stmtB) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$url_id = $aryA[0];
}
$sthA->finish();
$url = $parse_url;
$url =~ s/'/\\'/gi;
$url =~ s/"/\\"/gi;
$url =~ s/ /+/gi;
$url =~ s/&/\\&/gi;
$url =~ s/\?/\\?/gi;
my $secW = time();
`$wgetbin --no-check-certificate --output-document=/tmp/ASUBtmpD$US$url_id$US$secX --output-file=/tmp/ASUBtmpF$US$url_id$US$secX $url `;
# $event_string="$function|$wgetbin --no-check-certificate --output-document=/tmp/ASUBtmpD$US$url_id$US$secX --output-file=/tmp/ASUBtmpF$US$url_id$US$secX $url|";
my $secY = time();
my $response_sec = ($secY - $secW);
open(Wdoc, "/tmp/ASUBtmpD$US$url_id$US$secX") || die "can't open /tmp/ASUBtmpD$US$url_id$US$secX: $!\n";
@Wdoc = <Wdoc>;
close(Wdoc);
$i=0;
$Wdocline_cat='';
foreach(@Wdoc)
{
$Wdocline = $Wdoc[$i];
$Wdocline =~ s/\n|\r/!/gi;
$Wdocline =~ s/ |\t|\'|\`//gi;
$Wdocline_cat .= "$Wdocline";
$i++;
}
if (length($Wdocline_cat)<1)
{$Wdocline_cat='<RESPONSE EMPTY>';}
open(Wfile, "/tmp/ASUBtmpF$US$url_id$US$secX") || die "can't open /tmp/ASUBtmpF$US$url_id$US$secX: $!\n";
@Wfile = <Wfile>;
close(Wfile);
$i=0;
$Wfileline_cat='';
foreach(@Wfile)
{
$Wfileline = $Wfile[$i];
$Wfileline =~ s/\n|\r/!/gi;
$Wfileline =~ s/ |\t|\'|\`//gi;
$Wfileline_cat .= "$Wfileline";
$i++;
}
if (length($Wfileline_cat)<1)
{$Wfileline_cat='<HEADER EMPTY>';}
### update url log entry
$stmtA = "UPDATE vicidial_url_log SET url_response='$Wdocline_cat|$Wfileline_cat',response_sec='$response_sec' where url_log_id='$url_id';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print "$affected_rows|$stmtA\n";}
sleep(1);
$stmtA = "UPDATE vicidial_live_agents set external_update_fields='1',external_update_fields_data='formreload' where user='$VLA_user';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- Agent data update triggered: |$affected_rows| |$callerid|$stmtA|"; &agi_output;}
}
### no valid customer ID received, send customer to kickout in-group if defined
if ( ($confirmation < 1) && (length($kickout_ingroup)>0) )
{
$audio_file = $kickout_prompt; &play_audio;
sleep(1);
$stmtA = "UPDATE vicidial_live_agents set external_transferconf='LOCAL_CLOSER---$kickout_ingroup' where user='$VLA_user';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- AGI Done, kick-out, sending call to kickout ingroup: |$affected_rows| |$callerid|$kickout_ingroup|$stmtA"; &agi_output;}
}
### END prompt for customer ID number ($customer_id_number) ###
else
{
### send API command to have agent grab call back
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$stmtA = "UPDATE vicidial_live_agents set external_park='GRAB_IVR_CUSTOMER' where user='$VLA_user';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- AGI Done, sending call back to agent: |$affected_rows| |$callerid|$stmtA|$VLA_user|"; &agi_output;}
}
}
}
else
{
if ($AGILOG) {$agi_string = "-- Call Not Found in vicidial_auto_calls: |$callerid|"; &agi_output;}
}
$dbhA->disconnect();
$AGI->stream_file('sip-silence');
if ($AGILOG) {$agi_string = "-- Exiting Park Call IVR: |$callerid|"; &agi_output;}
exit;
sub agi_output
{
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$now_date|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$now_date|$script|$agi_string\n";}
$agi_string='';
}
sub checkresult
{
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/)
{
$res =~ /result=(-?\d+)/;
if (!length($1))
{
# print STDERR "FAIL ($res)\n";
$fail++;
}
else
{
# print STDERR "PASS ($1)\n";
$pass++;
}
}
else
{
# print STDERR "FAIL (unexpected result '$res')\n";
$fail++;
}
}
sub leading_zero($)
{
$_ = $_[0];
s/^(\d)$/0$1/;
s/^(\d\d)$/0$1/;
return $_;
} # End of the leading_zero() routine.
### play audio, check for existing other language if defined ###
sub play_audio
{
if ($language =~ /es/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_es';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
elsif ($language =~ /fr/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_fr';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
else
{$audio_suffix='';}
$AGI->stream_file("$audio_file$audio_suffix");
}
##### BEGIN collect the customer variable ###############################################
sub customer_variable_gather
{
$interrupt_digit='';
$audio_file = "$variable_entry_prompt";
if ($language =~ /es/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_es';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
elsif ($language =~ /fr/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_fr';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
else
{$audio_suffix='';}
$interrupt_digit = $AGI->stream_file("$audio_file$audio_suffix",'0123456789');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$PASS_word='';
if ($interrupt_digit > 0)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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;}
$PASS_word=$interrupt_digit;
}
$digit_loop_counter=0;
while ($digits_being_entered > 0)
{
$digit = chr($AGI->wait_for_digit('8000')); # wait 8 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
$PASS_word = "$PASS_word$digit";
print STDERR "digit |$digit| PASS_word |$PASS_word|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digits_being_entered=0;
}
if ( (length($PASS_word)) >= $collect_digits)
{
$digits_being_entered=0;
}
$digit_loop_counter++;
}
$PASS_word =~ s/\D//gi;
$variable = $PASS_word;
if ($PASS_word) {print STDERR "digit |$digit| PASS_word |$PASS_word| variable |$variable|\n";}
$collect_digits='99';
}
##### END collect the customer variable ###############################################
##### BEGIN confirm entry ######################################
sub confirm_entry
{
$interrupt_digit='';
$audio_file = "$confirmation_prompt";
if ($language =~ /es/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_es';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
elsif ($language =~ /fr/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_fr';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
else
{$audio_suffix='';}
$interrupt_digit = $AGI->stream_file("$audio_file$audio_suffix",'12');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$ANSWER_confirm='';
if ($interrupt_digit > 0)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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;}
$ANSWER_confirm=$interrupt_digit;
}
if (length($ANSWER_confirm) < 1)
{
$digit_loop_counter=0;
while ( ($digits_being_entered > 0) && ($digit_loop_counter < 1) )
{
$digit = chr($AGI->wait_for_digit("$ms_delay")); # wait 10 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
$ANSWER_confirm = "$ANSWER_confirm$digit";
print STDERR "digit |$digit| ANSWER_confirm |$ANSWER_confirm|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digits_being_entered=0;
}
$digit_loop_counter++;
}
}
$ANSWER_confirm =~ s/\D//gi;
if ($ANSWER_confirm) {print STDERR "digit |$digit| ANSWER_confirm |$ANSWER_confirm|\n";}
}
##### END confirm entry ######################################
@@ -0,0 +1,611 @@
#!/usr/bin/perl
#
# park_call_IVR_example.agi version 2.4
#
# NOTE: this script is an example of how you can use a custom AGI script with
# the new Park Call IVR feature in campaigns. You will most likely need to
# significantly alter this script to suit your specific needs
#
# Defined in the Park Call AGI IVR field of a campaign, this script will ask
# customer for their ID and then populate it in the vicidial_list table and then
# send the call back to the agent. If the customer enters nothing X number of
# times then the call can be kicked out to a separate in-group
#
# Here is a list of the variables that you can set:
# 1. Language - default: en (English), other options are es-Spanish, fr-French
# 2. First prompt - default: please_enter_id_number
# 3. You-Entered prompt - default: you-entered
# 4. Confirmation prompt - default: confirm_id_number
# 5. Thank you prompt - default: auth-thankyou
# 6. Invalid prompt - default: buzz
# 7. Attempts before kick-out - default: 2
# 8. Kick-out prompt - default: outside-transfer
# 9. Kick-out In-Group
#
# Example Park Call AGI IVR field:
# park_call_IVR_example.agi|en---please_enter_id_number---you-entered---confirm_id_number---auth-thankyou---buzz---2---outside-transfer---TEST_IN
#
# Copyright (C) 2010 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 101004-1132 - First build
#
$script = 'park_call_IVR_example.agi';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$S='*';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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,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;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
$ext_context = $aryA[1];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$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]);
$language = $ARGV_vars[0];
$first_prompt = $ARGV_vars[1];
$you_entered_prompt = $ARGV_vars[2];
$confirmation_prompt = $ARGV_vars[3];
$thank_you_prompt = $ARGV_vars[4];
$invalid_prompt = $ARGV_vars[5];
$kickout_attempts = $ARGV_vars[6];
$kickout_prompt = $ARGV_vars[7];
$kickout_ingroup = $ARGV_vars[8];
}
if (length($language)<1) {$language='en';}
if (length($first_prompt)<1) {$first_prompt='please_enter_id_number';}
if (length($you_entered_prompt)<1) {$you_entered_prompt='you-entered';}
if (length($confirmation_prompt)<1) {$confirmation_prompt='confirm_id_number';}
if (length($thank_you_prompt)<1) {$thank_you_prompt='auth-thankyou';}
if (length($invalid_prompt)<1) {$invalid_prompt='buzz';}
if (length($kickout_attempts)<1) {$kickout_attempts='2';}
if (length($kickout_prompt)<1) {$kickout_prompt='outside-transfer';}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($AGILOG)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (!$fullCID) # if no fullCID sent
{
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
if ( $calleridname =~ /\"/) {$calleridname =~ s/\"//gi;}
if ( (!$callerid) or ($callerid =~ /unknown/) or ( ($calleridname =~ /\d\d\d\d\d\d\d\d\d/) && (length($calleridname) > 16) ) )
{$callerid = $calleridname;}
if ( ($callerid =~ / /) && (length($callerid) > 20) )
{$callerid =~ s/ .*//gi;}
### allow for ANI being sent with the DNIS "*3125551212*9999*"
if ($extension =~ /^\*\d\d\d\d\d\d\d\d\d\d\*/)
{
$callerid = $extension;
$callerid =~ s/\*\d\d\d\d\*$//gi;
$callerid =~ s/^\*//gi;
$extension =~ s/^\*\d\d\d\d\d\d\d\d\d\d\*//gi;
$extension =~ s/\*$//gi;
}
$calleridname = $callerid;
}
}
if ($AGILOG) {$agi_string = "AGI Environment Dump:"; &agi_output;}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;}
if ($AGILOG) {$agi_string = "PARKED CALL IVR STARTED"; &agi_output;}
$stmtA = "UPDATE parked_channels set channel_group='$callerid' where server_ip='$VARserver_ip' and channel='$channel';";
if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;}
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- Park record updated: |$affected_rows| |$callerid|$channel|$VARserver_ip"; &agi_output;}
$VACcount=0;
$VAC_campaign_id='';
$VAC_call_type='';
$VAC_extension='';
$VLAcount=0;
$VLA_user='';
$VLA_campaign_id='';
$VCcount=0;
$MOHfiles=0;
$stmtA = "SELECT campaign_id,call_type,extension,phone_number,lead_id FROM vicidial_auto_calls where callerid='$callerid';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VACcount=$sthA->rows;
if ($VACcount > 0)
{
@aryA = $sthA->fetchrow_array;
$VAC_campaign_id = $aryA[0];
$VAC_call_type = $aryA[1];
$VAC_extension = $aryA[2];
$VAC_phone_number = $aryA[3];
$VAC_lead_id = $aryA[4];
if ($AGILOG) {$agi_string = "-- VAC Call Found: |$callerid|$VAC_campaign_id|$VAC_call_type|$VAC_extension|$VAC_phone_number|$VAC_lead_id|"; &agi_output;}
}
$sthA->finish();
if ($VACcount > 0)
{
$stmtA = "SELECT user,campaign_id,server_ip,conf_exten FROM vicidial_live_agents where callerid='$callerid';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$VLAcount=$sthA->rows;
if ($VLAcount > 0)
{
@aryA = $sthA->fetchrow_array;
$VLA_user = $aryA[0];
$VLA_campaign_id = $aryA[1];
$VLA_server_ip = $aryA[2];
$VLA_conf_exten = $aryA[3];
}
$sthA->finish();
if ($VLAcount > 0)
{
if ($AGILOG) {$agi_string = "-- Starting Gather Data: |$VLA_user|$VLA_campaign_id|$kickout_attempts| |$callerid|"; &agi_output;}
### BEGIN prompt for customer ID number ($customer_id_number) ###
$customer_id_number='';
$variable='';
$confirmation=0;
$confirmation_chances=0;
$collect_digits='20';
$ms_delay='8000';
$variable_entry_prompt = $first_prompt;
$confirm_entry_prompt = $you_entered_prompt;
while ( ($confirmation_chances < $kickout_attempts) && ($confirmation < 1) )
{
$entry_chances=0;
while ( ($entry_chances < $kickout_attempts) && (length($variable) < 1) )
{
$entry_chances++;
&customer_variable_gather;
$customer_id_number = $variable;
if ( (length($customer_id_number) < 1) || (length($customer_id_number) > 20) )
{
if ($AGILOG) {$agi_string = "-- CUSTOMER ID GATHER FAIL : |$customer_id_number|"; &agi_output;}
$audio_file = $invalid_prompt; &play_audio;
$variable='';
}
}
$confirmation_chances++;
if ( (length($customer_id_number) > 0) || (length($customer_id_number) <= 20) )
{
$audio_file = $confirm_entry_prompt; &play_audio;
$AGI->say_digits("$variable");
&confirm_entry;
if ($ANSWER_confirm > 1)
{$variable='';}
if ( ($ANSWER_confirm > 0) && ($ANSWER_confirm < 2) )
{$confirmation=1;}
}
else
{
if ($entry_chances >= $kickout_attempts)
{$confirmation_chances=$kickout_attempts;}
}
}
### customer ID confirmed, update in vicidial_list and tag agent for update
if ($confirmation > 0)
{
$stmtA = "UPDATE vicidial_list set vendor_lead_code='$customer_id_number' where lead_id='$VAC_lead_id';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- Lead record updated: |$affected_rows| |$callerid|$stmtA|"; &agi_output;}
$stmtA = "UPDATE vicidial_live_agents set external_update_fields='1',external_update_fields_data='vendor_lead_code' where user='$VLA_user';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- Agent data update triggered: |$affected_rows| |$callerid|$stmtA|"; &agi_output;}
}
### no valid customer ID received, send customer to kickout in-group if defined
if ( ($confirmation < 1) && (length($kickout_ingroup)>0) )
{
$audio_file = $kickout_prompt; &play_audio;
sleep(1);
$stmtA = "UPDATE vicidial_live_agents set external_transferconf='LOCAL_CLOSER---$kickout_ingroup' where user='$VLA_user';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- AGI Done, kick-out, sending call to kickout ingroup: |$affected_rows| |$callerid|$kickout_ingroup|$stmtA"; &agi_output;}
}
### END prompt for customer ID number ($customer_id_number) ###
else
{
### send API command to have agent grab call back
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$stmtA = "UPDATE vicidial_live_agents set external_park='GRAB_IVR_CUSTOMER' where user='$VLA_user';";
$affected_rows = $dbhA->do($stmtA);
if ($AGILOG) {$agi_string = "-- AGI Done, sending call back to agent: |$affected_rows| |$callerid|$stmtA|$VLA_user|"; &agi_output;}
}
}
}
else
{
if ($AGILOG) {$agi_string = "-- Call Not Found in vicidial_auto_calls: |$callerid|"; &agi_output;}
}
$dbhA->disconnect();
$AGI->stream_file('sip-silence');
if ($AGILOG) {$agi_string = "-- Exiting Park Call IVR: |$callerid|"; &agi_output;}
exit;
sub agi_output
{
if ($AGILOG >=2)
{
### open the log file for writing ###
open(Lout, ">>$AGILOGfile")
|| die "Can't open $AGILOGfile: $!\n";
print Lout "$now_date|$script|$agi_string\n";
close(Lout);
}
### send to STDERR writing ###
if ( ($AGILOG == '1') || ($AGILOG == '3') )
{print STDERR "$now_date|$script|$agi_string\n";}
$agi_string='';
}
sub checkresult
{
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/)
{
$res =~ /result=(-?\d+)/;
if (!length($1))
{
# print STDERR "FAIL ($res)\n";
$fail++;
}
else
{
# print STDERR "PASS ($1)\n";
$pass++;
}
}
else
{
# print STDERR "FAIL (unexpected result '$res')\n";
$fail++;
}
}
sub leading_zero($)
{
$_ = $_[0];
s/^(\d)$/0$1/;
s/^(\d\d)$/0$1/;
return $_;
} # End of the leading_zero() routine.
### play audio, check for existing other language if defined ###
sub play_audio
{
if ($language =~ /es/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_es';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
elsif ($language =~ /fr/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_fr';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
else
{$audio_suffix='';}
$AGI->stream_file("$audio_file$audio_suffix");
}
##### BEGIN collect the customer variable ###############################################
sub customer_variable_gather
{
$interrupt_digit='';
$audio_file = "$variable_entry_prompt";
if ($language =~ /es/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_es';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
elsif ($language =~ /fr/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_fr';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
else
{$audio_suffix='';}
$interrupt_digit = $AGI->stream_file("$audio_file$audio_suffix",'0123456789');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$PASS_word='';
if ($interrupt_digit > 0)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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;}
$PASS_word=$interrupt_digit;
}
$digit_loop_counter=0;
while ($digits_being_entered > 0)
{
$digit = chr($AGI->wait_for_digit('8000')); # wait 8 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
$PASS_word = "$PASS_word$digit";
print STDERR "digit |$digit| PASS_word |$PASS_word|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digits_being_entered=0;
}
if ( (length($PASS_word)) >= $collect_digits)
{
$digits_being_entered=0;
}
$digit_loop_counter++;
}
$PASS_word =~ s/\D//gi;
$variable = $PASS_word;
if ($PASS_word) {print STDERR "digit |$digit| PASS_word |$PASS_word| variable |$variable|\n";}
$collect_digits='99';
}
##### END collect the customer variable ###############################################
##### BEGIN confirm entry ######################################
sub confirm_entry
{
$interrupt_digit='';
$audio_file = "$confirmation_prompt";
if ($language =~ /es/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_es';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
elsif ($language =~ /fr/)
{
$file_extension_gsm='.gsm';
$file_extension_wav='.wav';
$audio_suffix='_fr';
if ( (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_gsm")) || (-e ("$PATHsounds/$audio_file$audio_suffix$file_extension_wav")) )
{$donothing=1;}
else
{$audio_suffix='';}
}
else
{$audio_suffix='';}
$interrupt_digit = $AGI->stream_file("$audio_file$audio_suffix",'12');
print STDERR "interrupt_digit |$interrupt_digit|\n";
$digits_being_entered=1;
$ANSWER_confirm='';
if ($interrupt_digit > 0)
{
# if ($interrupt_digit == 35) {$interrupt_digit='#';}
# if ($interrupt_digit == 42) {$interrupt_digit='*';}
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;}
$ANSWER_confirm=$interrupt_digit;
}
if (length($ANSWER_confirm) < 1)
{
$digit_loop_counter=0;
while ( ($digits_being_entered > 0) && ($digit_loop_counter < 1) )
{
$digit = chr($AGI->wait_for_digit("$ms_delay")); # wait 10 seconds for input or until the pound key is pressed
if ($digit =~ /\d/)
{
$ANSWER_confirm = "$ANSWER_confirm$digit";
print STDERR "digit |$digit| ANSWER_confirm |$ANSWER_confirm|\n";
# $AGI->say_digits("$digit");
undef $digit;
}
else
{
$digits_being_entered=0;
}
$digit_loop_counter++;
}
}
$ANSWER_confirm =~ s/\D//gi;
if ($ANSWER_confirm) {print STDERR "digit |$digit| ANSWER_confirm |$ANSWER_confirm|\n";}
}
##### END confirm entry ######################################
@@ -0,0 +1,265 @@
#!/usr/bin/perl
#
# phone_alt_CID.agi
#
# Changes the CID number on calls that pass through it to the Alternate defined
# in the 'phones' record for the phone that placed the call
#
# You need to have lines similar to those below in your Custom Dialplan:
#
#;use alternate CID, if defined:
#exten => _91NXXNXXXXXX,1,AGI(phone_alt_CID.agi,${EXTEN})
#exten => _91NXXNXXXXXX,n,Goto(default,${EXTEN},1)
#
# The easiest way to set this up for a phone is to create a new Call Menu and
# then put the above Custom Dialplan into it, then set the Phone's
# 'phone context' to the call menu ID that you just created.
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# changes:
# 160527-1415 - First build
#
$script = 'phone_alt_CID.agi';
$AGILOG=1;
$FD=0; # force debug for testing
($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";
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
### 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++;
}
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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/phonealt.$year-$mon-$mday";}
$|=1;
while(<STDIN>)
{
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_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
if (/^agi_type\:\s+(.*)$/) {$type = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
if (/^agi_accountcode\:\s+(.*)$/) {$accountcode = $1;}
}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
if (length($callerid)>0) {$phone_number = $callerid;}
else {$phone_number = '';}
if (length($calleridname)>0) {$VLcomments = $calleridname;}
else {$VLcomments = '';}
foreach $i (sort keys %AGI)
{
if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;}
}
if ( (length($callerid)>20) && ($callerid =~ /\"\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S/) )
{
$calleridname =~ s/^\"//gi;
$calleridname =~ s/\".*$//gi;
}
use DBI;
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
$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,local_gmt FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
$AGILOG = '0';
@aryA = $sthA->fetchrow_array;
$DBagi_output = $aryA[0];
$local_gmt = $aryA[1];
if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';}
if ($DBagi_output =~ /FILE/) {$AGILOG = '2';}
if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';}
$rec_count++;
}
$sthA->finish();
$phone_extension = $channel;
$phone_extension =~ s/^SIP\/|^IAX\/|^IAX2\///gi;
$phone_extension =~ s/-.*//gi;
if ($AGILOG) {$agi_string = "Phone Account: ($phone_extension)"; &agi_output;}
### Grab Server values from the database
$stmtA = "SELECT outbound_cid,outbound_alt_cid,fullname FROM phones where extension = '$phone_extension' and 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)
{
@aryA = $sthA->fetchrow_array;
$sthA->finish();
$outbound_cid = $aryA[0];
$outbound_alt_cid = $aryA[1];
$fullname = $aryA[2];
if (length($outbound_alt_cid) > 1)
{
### set the callerid to the ACQS value(calleridname)
$newcallerid = "\"$fullname <$outbound_alt_cid>\"";
$AGI->set_callerid($newcallerid);
print STDERR "Setting Alternate CID \"$newcallerid\"\n";
checkresult($result);
if ($AGILOG) {$agi_string = "callerID changed: $newcallerid"; &agi_output;}
if ($FD > 0) {print STDERR "callerID changed: newcallerid\n";}
}
else
{
if ($AGILOG) {$agi_string = "callerID not changed: Alt CID invalid ($outbound_alt_cid)"; &agi_output;}
}
if ($AGILOG) {$agi_string = "AGI Variables: |$extension|$accountcode|$channel|$areacode|$callerid|$calleridname|$newcallerid|"; &agi_output;}
}
else
{
if ($AGILOG) {$agi_string = "ERROR: phone entry not found: |$phone_extension|$VARserver_ip|$channel|"; &agi_output;}
}
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='';
}
@@ -0,0 +1,283 @@
#!/usr/bin/perl
#
# timer_rebeep.agi
#
# This script is designed to be launched from the in-group/campaign timer
# setting to set another trigger event for the next X seconds. Often used for
# calls that need to have a periodic beep signifying that the call is being
# recorded
#
# Just add the following to the System Settings Custom Dialplan Entry
# and set rebuild conf=Y
# exten => 8399,1,Answer
# exten => 8399,n,Wait(1)
# exten => 8399,n,Playback(beep)
# exten => 8399,n,AGI(timer_rebeep.agi,20---D1_DIAL_QUIET)
# exten => 8399,n,Hangup
#
# ; Below are the parameters needed for the script to be run properly
# ; 1. seconds delay before next trigger goes
# ; 2. timer action to launch
#
# Then set the in-groups/campaigns that you want to have this enabled
# "Timer Action" = D1_DIAL_QUIET
# "Timer Action Seconds" = 20
# "Transfer Conf Number 1" = 8399
#
# Copyright (C) 2014 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 111227-1418 - First build
# 141124-2309 - Fixed Fhour variable bug
#
$US='_';
&get_time_now;
$start_epoch = $now_date_epoch;
$script = 'timer_rebeep.agi';
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$now_day = "$year-$mon-$mday";
($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";}
$US='_';
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) )
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) )
{$PATHagi = $line; $PATHagi =~ 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/rebeep.$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;
# defaults:
$AGILOG = 2;
$seconds_delay = '20';
$timer_action = 'D1_DIAL_QUIET';
### 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]);
if (length($ARGV_vars[0]) > 0) {$seconds_delay = $ARGV_vars[0];}
if (length($ARGV_vars[1]) > 0) {$timer_action = $ARGV_vars[1];}
}
$|=1;
while(<STDIN>)
{
chomp;
last unless length($_);
if ($V)
{
if (/^agi_(\w+)\:\s+(.*)$/)
{
$AGI{$1} = $2;
}
}
if (/^agi_context\:\s+(.*)$/) {$context = $1;}
if (/^agi_priority\:\s+(.*)$/) {$priority = $1;}
if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $1;}
if (/^agi_channel\:\s+(.*)$/) {$channel = $1;}
if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;}
if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;}
if (/^agi_extension\:\s+(.*)$/) {$extension = $1;}
}
if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) )
{
$calleridname = $callerid;
$calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi;
$calleridname =~ s/\"|\" //gi;
}
$callerid =~ s/\D//gi;
$calleridname =~ s/unknown//gi;
if ( (!$callerid) or ($callerid =~ /unknown/) )
{$callerid = $calleridname;}
$phone_number=$callerid;
### Grab vicidial_manager record
$man_id='';
$stmtA = "SELECT man_id,entry_date,cmd_line_d,server_ip FROM vicidial_manager where callerid='$calleridname' order by man_id desc 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;
$man_id = $aryA[0];
$entry_date = $aryA[1];
$EXTsession = $aryA[2];
$EXTsession =~ s/Exten: //gi;
while (length($EXTsession) > 7) {$EXTsession =~ s/^.//gi;}
$EXTserver_ip = $aryA[3];
}
$sthA->finish();
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
$AGI->stream_file('sip-silence');
if (length($man_id) > 0)
{
$stmtA = "SELECT user,UNIX_TIMESTAMP(last_call_time) FROM vicidial_live_agents where server_ip='$EXTserver_ip' and conf_exten='$EXTsession' order by last_update_time desc 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;
$user = $aryA[0];
$last_call_time = $aryA[1];
$call_length = ($now_date_epoch - $last_call_time);
$next_length = ($call_length + $seconds_delay - 4);
$sthA->finish();
### update the agent live record for the next timer trigger
$stmtA="UPDATE vicidial_live_agents set external_timer_action='$timer_action',external_timer_action_message='',external_timer_action_seconds='$next_length' where user='$user' and conf_exten='$EXTsession' and server_ip='$EXTserver_ip';";
$affected_rows = $dbhA->do($stmtA);
print STDERR "|$affected_rows|$man_id|$entry_date|$timer_action|$next_length|$EXTserver_ip|$EXTsession|$stmtA|\n";
}
else
{
$sthA->finish();
print STDERR "|ERROR|$man_id|$entry_date|$timer_action|$seconds_delay|$EXTserver_ip|$EXTsession|\n";
}
}
else
{
print STDERR "|ERROR|$man_id|$entry_date|$timer_action|$seconds_delay|$EXTserver_ip|$EXTsession|\n";
}
$dbhA->disconnect();
exit;
#######################
##### Subroutines #####
sub get_time_now #get the current date and time and epoch for logging call lengths and datetimes
{
($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) {$Fhour = "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";
$filedate = "$year$mon$mday$hour$min$sec";
}
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='';
}
sub leading_zero($)
{
$_ = $_[0];
s/^(\d)$/0$1/;
s/^(\d\d)$/0$1/;
return $_;
} # End of the leading_zero() routine.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,458 @@
#!/usr/bin/perl
#
# ADMIN_area_code_populate.pl version 2.12
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# Description:
# server application that allows load areacodes into to asterisk list database
#
# CHANGES
# 60615-1514 - Changed to ignore the header row
# 60807-1003 - Changed to DBI
# - changed to use /etc/astguiclient.conf for configs
# 61122-1902 - Added GMT_USA_zip.txt data import for USA postal GMT data
# 80416-1017 - Added download of phone codes from remote host
# 90129-0932 - Added optional NANPA prefix/time date import "--load-NANPA-prefix" flag
# 90131-0933 - Added purge-table option to clear out old records before adding new ones
# 90204-0806 - Added duplicate check to nanpa list loading
# 90317-2353 - Added city, state, postal_code, country to nanpa format
# 100902-1536 - Move old data files if wgetting new ones
# 110424-0735 - Added timezone abbreviation column
# 130419-1237 - Added lata_type field to NANPA file format
# 150203-1751 - code cleanup
# 151228-1043 - Added ISO-TLD table and import
# 160611-0933 - Added more documentation
#
# default path to astguiclient configuration file:
$PATHconf = "/etc/astguiclient.conf";
$domain = "http://phonecodes.vicidial.com";
#$URL1 = "$domain/phone_codes_GMT-latest.txt";
$URL1 = "$domain/phone_codes_GMT-latest-24.txt";
$URL2 = "$domain/GMT_USA_zip-latest.txt";
$URL3 = "$domain/country_ISO_TLD-latest.txt";
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help|-h/i)
{
print "allowed run time options:\n";
print " [-q] = quiet\n";
print " [--test] = test\n";
print " [--debug] = debug output\n";
print " [--use-local-files] = Do not download files, use local copies\n";
print " [--load-NANPA-prefix] = Only loads the special NANPA list into the database\n";
print " NOTE: NANPA data must be purchased from 'http://vicidial.org/store.php'\n";
print " [--purge-table] = Purges the table to be inserted before inserting\n";
print "\n";
print " Files used by this script are:\n";
print " phone_codes_GMT-latest-24.txt - Phone codes and country codes with time zone data\n";
print " GMT_USA_zip-latest.txt - USA zip code and time zone data\n";
print " country_ISO_TLD-latest.txt - Country code ISO and TLD data\n";
print " NANPA_prefix-latest.txt - North American areacode, prefix and time zone data\n";
print "\n";
print " Update schedules for data files:\n";
print " phone_codes - Usually a few times a year, as areacodes in North America are added\n";
print " GMT_USA_zip - About once per year\n";
print " country_ISO_TLD - Only when country code data changes, not frequently\n";
print " NANPA_prefix - About once per year\n";
print "\n";
exit;
}
else
{
if ($args =~ /-debug/i)
{
$DB=1;
print "\n----- DEBUGGING -----\n\n";
}
if ($args =~ /-debugX/i)
{
$DBX=1;
print "\n----- SUPER-DUPER DEBUGGING -----\n\n";
}
else {$DBX=0;}
if ($args =~ /-q/i)
{
$q=1;
}
if ($args =~ /-test/i)
{
$T=1;
$TEST=1;
print "\n----- TESTING -----\n\n";
}
if ($args =~ /--use-local-files/i)
{
$use_local_files=1;
print "\n----- USING LOCAL DATA FILES -----\n\n";
}
if ($args =~ /--load-NANPA-prefix/i)
{
$nanpa_load=1;
print "\n----- NANPA PHONE PREFIX DATA LOAD -----\n\n";
}
if ($args =~ /--purge-table/i)
{
$purge_table=1;
print "\n----- PURGE TABLE BEFORE DATA LOAD -----\n\n";
}
}
}
else
{
print "no command line options set\n";
$args = "";
$i=0;
$forcelistid = '';
$format='standard';
}
### end parsing run-time options ###
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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++;
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
$slash_star = '\*';
use Time::HiRes ('gettimeofday','usleep','sleep'); # needed to have perl sleep in increments of less than one second
use DBI;
if (!$VARDB_port) {$VARDB_port='3306';}
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
if ($nanpa_load > 0)
{
#### load special North American phone code prefix table ####
# LONG # NPA,NXX,,,,LTYPE,,STATE,COUNTRY,,,,,RC,TZ,DST,ZIP,,,,,,,,,,,LATITUDE,LONGITUDE,,,,,,,
# SHORT # NPA,NXX,TZ,DST,LATITUDE,LONGITUDE,CITY,STATE,POSTAL_CODE,COUNTRY,LTYPE
#### BEGIN vicidial_nanpa_prefix_codes population from NANPA_prefix-latest.txt file ####
open(prefixfile, "$PATHhome/NANPA_prefix-latest.txt") || die "can't open $PATHhome/NANPA_prefix-latest.txt: $!\n";
@prefixfile = <prefixfile>;
close(prefixfile);
if ( ($purge_table > 0) && ($#prefixfile > 10) )
{
print "\n----- PURGING DATA IN vicidial_nanpa_prefix_codes TABLE -----\n\n";
$stmtA = "DELETE from vicidial_nanpa_prefix_codes;";
if($DB){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA);
$stmtA = "OPTIMIZE table vicidial_nanpa_prefix_codes;";
if($DB){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA);
}
$pc=0; $full_file=0; $dup_count=0; $ins_count=0; $dup_list='';
$ins_stmt="insert into vicidial_nanpa_prefix_codes VALUES ";
foreach (@prefixfile)
{
@row=split(/,/, $prefixfile[$pc]);
if ($#row > 20)
{$full_file++;}
if ( ($prefixfile[$pc] !~ /XXXXX/) && ($prefixfile[$pc] !~ /^\D|^0|^1/) )
{
$prefixfile[$pc] =~ s/\r|\n|\t| $//gi;
$pc++;
$temp_insert='';
$dup_check=0;
if ($full_file > 0)
{
if ($row[14] !~ /XX/)
{
$row[13] =~ s/\(.*//gi;
$row[13] =~ s/ $//gi;
$row[13] =~ s/\'/\\\'/gi;
$row[14] =~ s/NT/-3.50/gi;
$row[14] =~ s/AT/-4.00/gi;
$row[14] =~ s/ET/-5.00/gi;
$row[14] =~ s/CT/-6.00/gi;
$row[14] =~ s/MT/-7.00/gi;
$row[14] =~ s/PT/-8.00/gi;
$row[14] =~ s/AK/-9.00/gi;
$row[14] =~ s/HT/-10.00/gi;
$row[14] =~ s/AS/-11.00/gi;
$row[14] =~ s/CH/10.00/gi;
$row[15] =~ s/X/N/gi;
$temp_insert="('$row[0]', '$row[1]', '$row[14]', '$row[15]', '$row[27]', '$row[28]', '$row[13]', '$row[7]', '$row[16]', '$row[8]', '$row[5]'), ";
}
}
else
{
$row[6] =~ s/\'/\\\'/gi;
$row[9] =~ s/\r|\n|\t| $//gi;
$temp_insert="('$row[0]', '$row[1]', '$row[2]', '$row[3]', '$row[4]', '$row[5]', '$row[6]', '$row[7]', '$row[8]', '$row[9]', '$row[10]'), ";
}
$stmtA = "SELECT count(*) FROM vicidial_nanpa_prefix_codes where areacode='$row[0]' and prefix='$row[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;
$dup_check = $aryA[0];
}
$sthA->finish();
if ($dup_check < 1)
{
if ($dup_list =~ /$row[0]$row[1]\|/)
{$dup_count++;}
else
{
$dup_list .= "$row[0]$row[1]|";
$ins_stmt .= "$temp_insert";
$ins_count++;
}
}
else
{$dup_count++;}
if ($pc =~ /000$/)
{
chop($ins_stmt);
chop($ins_stmt);
$affected_rows = $dbhA->do($ins_stmt) || die "can't execute query: |$ins_stmt| $!\n";
$ins_stmt="insert into vicidial_nanpa_prefix_codes VALUES ";
print STDERR "$pc Lines $ins_count Inserted $dup_count Duplicates\r";
$dup_list='';
}
}
else
{$pc++;}
}
chop($ins_stmt);
chop($ins_stmt);
$affected_rows = $dbhA->do($ins_stmt);
$ins_stmt="insert into vicidial_nanpa_prefix_codes VALUES ";
print STDERR "$pc Lines $ins_count Inserted $dup_count Duplicates\n";
#### END vicidial_nanpa_prefix_codes population ####
}
else
{
#### download the latest phone code table ####
chdir("$PATHhome");
if ($use_local_files < 1)
{
$wget = `which wget`;
print "$wget\n";
if ( $wget eq "" )
{
print STDERR "Please install the wget command\n";
exit();
}
print STDERR "Downloading latest phone codes tables\n";
# move old files
`mv -f $PATHhome/phone_codes_GMT-latest-24.txt $PATHhome/phone_codes_GMT-latest-24-old.txt`;
`mv -f $PATHhome/GMT_USA_zip-latest.txt $PATHhome/GMT_USA_zip-latest-old.txt`;
`mv -f $PATHhome/country_ISO_TLD-latest.txt $PATHhome/country_ISO_TLD-latest-old.txt`;
# get files
`wget $URL1`;
`wget $URL2`;
`wget $URL3`;
}
#### BEGIN vicidial_phone_codes population from phone_codes_GMT-latest-24.txt file ####
open(codefile, "$PATHhome/phone_codes_GMT-latest-24.txt") || die "can't open $PATHhome/phone_codes_GMT-latest-24.txt: $!\n";
@codefile = <codefile>;
close(codefile);
if ( ($purge_table > 0) && ($#codefile > 10) )
{
print "\n----- PURGING DATA IN vicidial_phone_codes TABLE -----\n\n";
$stmtA = "DELETE from vicidial_phone_codes;";
if($DB){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA);
$stmtA = "OPTIMIZE table vicidial_phone_codes;";
if($DB){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA);
}
$pc=0;
$ins_stmt="insert into vicidial_phone_codes VALUES ";
foreach (@codefile)
{
@row=split(/\t/, $codefile[$pc]);
if ($codefile[$pc] !~ /GEOGRAPHIC DESCRIPTION/)
{
$pc++;
$row[8] =~ s/\r|\n|\t| $//gi;
$row[7] =~ s/\r|\n|\t| $//gi;
$row[6] =~ s/\r|\n|\t| $//gi;
$row[5] =~ s/\r|\n|\t| $//gi;
$row[4] =~ s/\r|\n|\t| $//gi;
$row[3] =~ s/\r|\n|\t| $//gi;
$row[2] =~ s/\r|\n|\t| $//gi;
$row[1] =~ s/\r|\n|\t| $//gi;
$row[0] =~ s/\r|\n|\t| $//gi;
$ins_stmt.="('$row[0]', '$row[1]', '$row[2]', '$row[3]', '$row[4]', '$row[5]', '$row[6]', '$row[7]', '$row[8]'), ";
if ($pc =~ /00$/)
{
chop($ins_stmt);
chop($ins_stmt);
$affected_rows = $dbhA->do($ins_stmt) || die "can't execute query: |$ins_stmt| $!\n";
$ins_stmt="insert into vicidial_phone_codes VALUES ";
print STDERR "$pc\r";
}
}
else {$pc++;}
}
chop($ins_stmt);
chop($ins_stmt);
$affected_rows = $dbhA->do($ins_stmt);
$ins_stmt="insert into vicidial_phone_codes VALUES ";
print STDERR "$pc\n";
#### END vicidial_phone_codes population ####
#### BEGIN vicidial_postal_codes population from GMT_USA_zip-latest.txt file ####
open(zipfile, "$PATHhome/GMT_USA_zip-latest.txt") || die "can't open $PATHhome/GMT_USA_zip-latest.txt: $!\n";
@zipfile = <zipfile>;
close(zipfile);
if ( ($purge_table > 0) && ($#zipfile > 10) )
{
print "\n----- PURGING DATA IN vicidial_postal_codes TABLE -----\n\n";
$stmtA = "DELETE from vicidial_postal_codes;";
if($DB){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA);
$stmtA = "OPTIMIZE table vicidial_postal_codes;";
if($DB){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA);
}
$pc=0;
$ins_stmt="insert into vicidial_postal_codes VALUES ";
foreach (@zipfile)
{
@row=split(/\t/, $zipfile[$pc]);
$pc++;
$row[0] =~ s/\r|\n|\t| $//gi;
$row[1] =~ s/\r|\n|\t| $//gi;
$row[2] =~ s/\r|\n|\t| $//gi;
$row[3] =~ s/\r|\n|\t| $//gi;
if ($row[3] =~ /Y/i) {$DST_range = 'SSM-FSN';}
else {$DST_range = '';}
$ins_stmt.="('$row[0]', '$row[1]', '$row[2]', '$row[3]', '$DST_range', 'USA', '1'), ";
if ($pc =~ /00$/)
{
chop($ins_stmt);
chop($ins_stmt);
$affected_rows = $dbhA->do($ins_stmt) || die "can't execute query: |$ins_stmt| $!\n";
$ins_stmt="insert into vicidial_postal_codes VALUES ";
print STDERR "$pc\r";
}
}
chop($ins_stmt);
chop($ins_stmt);
$affected_rows = $dbhA->do($ins_stmt);
$ins_stmt="insert into vicidial_postal_codes VALUES ";
print STDERR "$pc\n";
#### END vicidial_postal_codes population ####
#### BEGIN vicidial_country_iso_tld population from GMT_USA_zip-latest.txt file ####
open(isofile, "$PATHhome/country_ISO_TLD-latest.txt") || die "can't open $PATHhome/country_ISO_TLD-latest.txt: $!\n";
@isofile = <isofile>;
close(isofile);
if ( ($purge_table > 0) && ($#isofile > 10) )
{
print "\n----- PURGING DATA IN vicidial_country_iso_tld TABLE -----\n\n";
$stmtA = "DELETE from vicidial_country_iso_tld;";
if($DB){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA);
$stmtA = "OPTIMIZE table vicidial_country_iso_tld;";
if($DB){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA);
}
$pc=0;
$ins_stmt="insert into vicidial_country_iso_tld VALUES ";
foreach (@isofile)
{
@row=split(/\t/, $isofile[$pc]);
$pc++;
$row[0] =~ s/\r|\n|\t| $//gi;
$row[1] =~ s/\r|\n|\t| $//gi;
$row[2] =~ s/\r|\n|\t| $//gi;
$row[3] =~ s/\r|\n|\t| $//gi;
$row[4] =~ s/\r|\n|\t| $//gi;
$ins_stmt.="(\"$row[0]\", '$row[1]', '$row[2]', '$row[3]', '$row[4]'), ";
if ($pc =~ /00$/)
{
chop($ins_stmt);
chop($ins_stmt);
$affected_rows = $dbhA->do($ins_stmt) || die "can't execute query: |$ins_stmt| $!\n";
$ins_stmt="insert into vicidial_country_iso_tld VALUES ";
print STDERR "$pc\r";
}
}
chop($ins_stmt);
chop($ins_stmt);
$affected_rows = $dbhA->do($ins_stmt);
$ins_stmt="insert into vicidial_country_iso_tld VALUES ";
print STDERR "$pc\n";
#### END vicidial_country_iso_tld population ####
}
$dbhA->disconnect();
exit;
@@ -0,0 +1,786 @@
#!/usr/bin/perl
#
# ADMIN_audio_store_sync.pl version 2.12
#
# DESCRIPTION:
# syncronizes audio between audio store and this server
#
#
# Copyright (C) 2015 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 90513-0458 - First Build
# 90518-2107 - Added force-upload option
# 90831-1349 - Added music-on-hold sync
# 100621-1018 - Added admin_web_directory variable use
# 100824-0032 - Fixed issue with first MoH file being skipped when playing in non-random order
# 101217-2137 - Small fix for admin directories not directly off of the webroot
# 121019-0729 - Added audio_store_purge feature
# 141124-2309 - Fixed Fhour variable bug
# 141125-1555 - Added audio_store_details audio file info gathering and DB population
# 150712-2210 - Added touch of conf files to Asterisk will notice changes
#
# constants
$SYSLOG=1; # log to a logfile
$DB=0;
$US='__';
$MT[0]='';
$uploaded=0;
$downloaded=0;
$force_moh_rebuild=0;
$new_file_moh_rebuild=0;
$secT = time();
$now_date_epoch = $secT;
($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";}
$file_date = "$year-$mon-$mday";
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$VDL_date = "$year-$mon-$mday 00:00:01";
$inactive_epoch = ($secT - 60);
$HHMM = "$hour$min";
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options(must stay in this order):\n";
print " [--debug] = debug\n";
print " [--debugX] = super debug\n";
print " [-t] = test\n";
print " [--upload] = upload audio not found on audio store\n";
print " [--force-download] = force download of everything from audio store\n";
print " [--force-upload] = force upload of all local audio files to the audio store\n";
print " [--settings-override] = ignore database settings and run sync anyway\n";
print " [--force-moh-rebuild] = ignore database settings and rebuild Music On Hold\n";
print " [--gather-details] = gathers audio file details and populates audio_store_details table\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1;
print "\n----- DEBUG -----\n\n";
}
if ($args =~ /-upload/i)
{
$upload=1;
if ($DB) {print "\n----- UPLOAD -----\n\n";}
}
if ($args =~ /--force-download/i)
{
$force_download=1;
if ($DB) {print "\n----- FORCE DOWNLOAD -----\n\n";}
}
if ($args =~ /--force-upload/i)
{
$force_upload=1;
if ($DB) {print "\n----- FORCE UPLOAD -----\n\n";}
}
if ($args =~ /--settings-override/i)
{
$settings_override=1;
if ($DB) {print "\n----- SETTINGS OVERRIDE -----\n\n";}
}
if ($args =~ /--force-moh-rebuild/i)
{
$force_moh_rebuild=1;
if ($DB) {print "\n----- FORCE MUSIC ON HOLD REBUILD -----\n\n";}
}
if ($args =~ /--gather-details/i)
{
$gather_details=1;
if ($DB) {print "\n----- GATHER AUDIO FILE DETAILS -----\n\n";}
}
if ($args =~ /--debugX/i)
{
$DBX=1;
if ($DB) {print "\n----- SUPER DEBUG -----\n\n";}
}
if ($args =~ /-t/i)
{
$T=1; $TEST=1;
if ($DB) {print "\n-----TESTING -----\n\n";}
}
}
}
else
{
# print "no command line options set\n";
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 (!$VASLOGfile) {$VASLOGfile = "$PATHlogs/audiostore.$year-$mon-$mday";}
if (!$VARDB_port) {$VARDB_port='3306';}
use DBI;
$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 active_asterisk_server,audio_store_purge 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)
{
@aryA = $sthA->fetchrow_array;
$active_asterisk_server = $aryA[0];
$audio_store_purge = $aryA[1];
}
$sthA->finish();
### Grab system_settings values from the database
$web_prefix='';
$stmtA = "SELECT sounds_central_control_active,sounds_web_server,sounds_web_directory,admin_web_directory 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;
$sounds_central_control_active = $aryA[0];
$sounds_web_server = $aryA[1];
$sounds_web_directory = $aryA[2];
$admin_web_directory = $aryA[3];
if ($admin_web_directory =~ /\//)
{
$web_prefix = $admin_web_directory;
$web_prefix =~ s/\/.*/\//gi;
}
}
$sthA->finish();
if ( ( ($sounds_central_control_active < 1) || ($active_asterisk_server !~ /Y/) ) && ($settings_override < 1) )
{
print "Audio Sync Settings not active, Exiting\n";
exit;
}
$stmtA="UPDATE servers SET sounds_update='N' where server_ip='$VARserver_ip';";
$affected_rows = $dbhA->do($stmtA);
$gsm='.gsm';
$wav='.wav';
$ulaw='.ulaw';
$audio_file_deleted=0;
if (length($audio_store_purge) > 0)
{
if ($DB) {print "starting audio file deletion process...\n";}
$stmtA="UPDATE servers SET audio_store_purge='' where server_ip='$VARserver_ip';";
$affected_rows = $dbhA->do($stmtA);
@purge_data = split(/\n/, $audio_store_purge);
$i=0;
foreach(@purge_data)
{
if (length($purge_data[$i])>0)
{
if ( -e ("/var/lib/asterisk/sounds/$purge_data[$i]$wav"))
{`rm -f /var/lib/asterisk/sounds/$purge_data[$i]$wav`; $audio_file_deleted++;}
if ( -e ("/var/lib/asterisk/sounds/$purge_data[$i]$gsm"))
{`rm -f /var/lib/asterisk/sounds/$purge_data[$i]$gsm`; $audio_file_deleted++;}
if ( -e ("/var/lib/asterisk/sounds/$purge_data[$i]$ulaw"))
{`rm -f /var/lib/asterisk/sounds/$purge_data[$i]$ulaw`; $audio_file_deleted++;}
if ($audio_file_deleted < 1)
{if ($DB) {print "no audio file deleted: $purge_data[$i]|$i\n";}}
if ($DBX>0) {print "audio file delete process: $purge_data[$i]|$i|$audio_file_deleted\n";}
}
$i++;
}
if ($DB) {print "total audio files deleted: $audio_file_deleted|$i\n";}
}
### find wget binary
$wgetbin = '';
if ( -e ('/bin/wget')) {$wgetbin = '/bin/wget';}
else
{
if ( -e ('/usr/bin/wget')) {$wgetbin = '/usr/bin/wget';}
else
{
if ( -e ('/usr/local/bin/wget')) {$wgetbin = '/usr/local/bin/wget';}
else
{
print "Can't find wget binary! Exiting...\n";
exit;
}
}
}
### find curl binary
$curlbin = '';
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
{
print "Can't find curl binary! Exiting...\n";
exit;
}
}
}
$URL = "http://$sounds_web_server/$admin_web_directory/audio_store.php?action=LIST&audio_server_ip=$VARserver_ip";
$URL =~ s/&/\\&/gi;
if ($DB)
{print "\n$URL\n";}
$audio_list_file = '/tmp/audio_store_list.txt';
`rm -f $audio_list_file`;
`$wgetbin -q --output-document=$audio_list_file $URL `;
open(list, "$audio_list_file") || die "can't open $audio_list_file: $!\n";
@list = <list>;
close(list);
opendir(sounds, "$PATHsounds");
@sounds= readdir(sounds);
closedir(sounds);
####### BEGIN download of audio files
if ($DB > 0) {print "REMOTE AUDIO FILES:\n";}
$i=0;
while ($i <= $#list)
{
chomp($list[$i]);
@file_data = split(/\t/, $list[$i]);
$filename = $file_data[1];
$filedate = $file_data[2];
$filesize = $file_data[3];
$fileepoch = $file_data[4];
if ($DB > 0) {print "$i $filename $filedate $filesize $fileepoch\n";}
$k=0;
$found_file=0;
while ($k <= $#sounds)
{
chomp($sounds[$k]);
$soundname = $sounds[$k];
$soundsize = (-s "$PATHsounds/$sounds[$k]");
if ( ($filename eq "$soundname") && ($filesize eq "$soundsize") )
{
$found_file++;
}
$k++;
}
if ( ($found_file < 1) || ($force_download > 0) )
{
`$wgetbin -q --output-document=$PATHsounds/$filename http://$sounds_web_server/$web_prefix$sounds_web_directory/$filename`;
$event_string = "DOWNLOADING: $filename $filesize";
if ($DB > 0) {print " $event_string\n";}
&event_logger;
$downloaded++;
$new_file_moh_rebuild++;
}
else
{
if ($DB > 0) {print " FILE FOUND: $filename\n";}
}
$i++;
}
####### END download of audio files
$total_files = $i;
`rm -f $audio_list_file`;
`$wgetbin -q --output-document=$audio_list_file $URL `;
open(list, "$audio_list_file") || die "can't open $audio_list_file: $!\n";
@list = <list>;
close(list);
opendir(sounds, "$PATHsounds");
@sounds= readdir(sounds);
closedir(sounds);
####### BEGIN upload of audio files
if ($upload > 0)
{
if ($DB > 0) {print "LOCAL AUDIO FILES:\n";}
$k=0;
while ($k <= $#sounds)
{
chomp($sounds[$k]);
if ($sounds[$k] =~ /\.wav$|\.gsm$/)
{
$soundname = $sounds[$k];
$sounddate = (-M "$PATHsounds/$sounds[$k]");
$soundsize = (-s "$PATHsounds/$sounds[$k]");
$soundsec = ($sounddate * 86400);
$soundepoch = ($secT - $soundsec);
if ($DB > 0) {print "$k $soundname $sounddate $soundsize $soundepoch\n";}
$i=0;
$found_file=0;
while ($i <= $#list)
{
chomp($list[$i]);
@file_data = split(/\t/, $list[$i]);
$filename = $file_data[1];
$filedate = $file_data[2];
$filesize = $file_data[3];
$fileepoch = $file_data[4];
if ( ($filename eq "$soundname") && ($filesize eq "$soundsize") )
{
$found_file++;
}
$i++;
}
if ( ($found_file < 1) || ($force_upload > 0) )
{
$curloptions = "-s 'http://$sounds_web_server/$admin_web_directory/audio_store.php?action=AUTOUPLOAD&audio_server_ip=$VARserver_ip' -F \"audiofile=\@$PATHsounds/$soundname\"";
`$curlbin $curloptions`;
$event_string = "UPLOADING: $soundname $soundsize";
if ($DB > 0) {print " $event_string\n|$curlbin $curloptions|\n";}
&event_logger;
$uploaded++;
}
else
{
if ($DB > 0) {print " FILE FOUND: $soundname\n";}
}
}
$k++;
}
}
####### END upload of audio files
###### If audio was uploaded from this server, set all other servers to update sounds next minute
if ($uploaded > 0)
{
$stmtA="UPDATE servers SET sounds_update='Y' where server_ip NOT IN('$VARserver_ip');";
$affected_rows = $dbhA->do($stmtA);
}
###### BEGIN GATHER AUDIO FILE DETAILS #####
if ($gather_details > 0)
{
$gsm_count=0;
$wav_count=0;
$new_count=0;
$old_count=0;
$update_count=0;
$i=0;
while ($i <= $#list)
{
chomp($list[$i]);
@file_data = split(/\t/, $list[$i]);
$filename = $file_data[1];
$filedate = $file_data[2];
$filesize = $file_data[3];
$fileepoch = $file_data[4];
if ($DB > 0) {print "$i $filename $filedate $filesize $fileepoch\n";}
$allowed_format=0;
if ($filesize > 0)
{
if ($filename =~ /\.wav$/)
{
$allowed_format++;
$wav_count++;
$audio_format='wav';
$audio_length = ($filesize / 16000);
$audio_length = sprintf("%.0f", $audio_length);
}
if ($filename =~ /\.gsm$/)
{
$allowed_format++;
$gsm_count++;
$audio_format='gsm';
$audio_length = ($filesize / 1650);
$audio_length = sprintf("%.0f", $audio_length);
}
if ($allowed_format > 0)
{
$stmtA = "SELECT audio_format,audio_filesize,audio_length FROM audio_store_details where audio_filename = '$filename';";
$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;
$asd_format = $aryA[0];
$asd_filesize = $aryA[1];
$asd_length = $aryA[2];
if ( ($asd_format eq "$audio_format") && ($asd_filesize eq "$filesize") && ($asd_length eq "$audio_length") )
{
$old_count++;
if ($DB > 0) {print "$i audio file details unchanged: $filename - |$audio_format|$filesize|$audio_length|\n";}
}
else
{
$update_count++;
$stmtA="UPDATE audio_store_details SET audio_format='$audio_format',audio_filesize='$filesize',audio_length='$audio_length',audio_epoch='$fileepoch' where audio_filename='$filename';";
$affected_rows = $dbhA->do($stmtA);
if ($DBX > 0) {print " $affected_rows|$stmtA|\n";}
}
}
else
{
$new_count++;
$stmtA="INSERT INTO audio_store_details SET audio_filename='$filename',audio_format='$audio_format',audio_filesize='$filesize',audio_length='$audio_length',audio_epoch='$fileepoch';";
$affected_rows = $dbhA->do($stmtA);
if ($DBX > 0) {print " $affected_rows|$stmtA|\n";}
}
$sthA->finish();
}
else
{
if ($DB > 0) {print "$i format is not allowed: $filename\n";}
}
}
else
{
if ($DB > 0) {print "$i filesize is zero: $filename ($filesize)\n";}
}
$i++;
}
if($DB)
{
print "Gather Details Summary:\n";
print "GSM files: $gsm_count\n";
print "WAV files: $wav_count\n";
print "NEW entries: $new_count\n";
print "OLD entries: $old_count\n";
print "UPDATED entries: $update_count\n";
print "TOTAL: $i\n";
print "\n";
}
}
###### END GATHER AUDIO FILE DETAILS #####
###### BEGIN Music on hold rebuild #####
$wav = '.wav';
$gsm = '.gsm';
$stmtA = "SELECT rebuild_music_on_hold 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)
{
@aryA = $sthA->fetchrow_array;
$rebuild_music_on_hold = $aryA[0];
}
$sthA->finish();
if ( ($force_moh_rebuild > 0) || ($new_file_moh_rebuild > 0) || ($rebuild_music_on_hold =~ /Y/i) )
{
$stmtA="UPDATE servers SET rebuild_music_on_hold='N' where server_ip = '$VARserver_ip';";
$affected_rows = $dbhA->do($stmtA);
### Find music on hold contexts to remove
$stmtA = "SELECT moh_id FROM vicidial_music_on_hold where remove='Y' and moh_id NOT IN('astdb','sounds','agi-bin','keys');";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsM=$sthA->rows;
@remove_moh_id=@MT;
$j=0;
while ($sthArowsM > $j)
{
@aryA = $sthA->fetchrow_array;
$remove_moh_id[$j] = $aryA[0];
$j++;
}
$sthA->finish();
### Remove flagged music on hold contexts
$j=0;
while ($sthArowsM > $j)
{
$stmtA="DELETE from vicidial_music_on_hold where moh_id='$remove_moh_id[$j]' and remove='Y' and moh_id NOT IN('astdb','sounds','agi-bin','keys');";
$affected_rowsX = $dbhA->do($stmtA);
$stmtB="DELETE from vicidial_music_on_hold_files where moh_id='$remove_moh_id[$j]' and moh_id NOT IN('astdb','sounds','agi-bin','keys');";
$affected_rowsY = $dbhA->do($stmtB);
if ($affected_rowsX > 0)
{`rm -fr /var/lib/asterisk/$remove_moh_id[$j]`;}
if ($DBX)
{
print "Deleting Existing MoH: $affected_rowsX|$affected_rowsY|$stmtA|$stmtB|rm -fr /var/lib/asterisk/$remove_moh_id[$j]\n";
}
$j++;
}
### Find active music on hold contexts
$stmtA = "SELECT moh_id,moh_name,random FROM vicidial_music_on_hold where active='Y' and moh_id NOT IN('astdb','sounds','agi-bin','keys');";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsC=$sthA->rows;
@remove_moh_id=@MT;
$j=0;
while ($sthArowsC > $j)
{
@aryA = $sthA->fetchrow_array;
$moh_id[$j] = $aryA[0];
$moh_name[$j] = $aryA[1];
$random[$j] = $aryA[2];
$j++;
}
$sthA->finish();
### Go through each context and check the files in the folders
$j=0;
while ($sthArowsC > $j)
{
$filelist_names = '|';
$MoH_directory = "/var/lib/asterisk/$moh_id[$j]";
### Check if directory exists, if not, create it
if ( -e ("$MoH_directory")) {$mohpath = "$MoH_directory";}
else
{
`mkdir $MoH_directory`;
$mohpath = "$MoH_directory";
if ($DBX)
{
print "Creating New MoH: $MoH_directory\n";
}
}
opendir(sounds, "$PATHsounds");
@sounds= readdir(sounds);
closedir(sounds);
if (!-e "$MoH_directory/0000_sip-silence.gsm")
{`cp $PATHsounds/sip-silence.gsm $MoH_directory/0000_sip-silence.gsm`;}
### copy over files that are not in place currently
$stmtA = "SELECT filename,rank FROM vicidial_music_on_hold_files where moh_id='$moh_id[$j]' order by rank;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsF=$sthA->rows;
@remove_moh_id=@MT;
$m=0;
while ($sthArowsF > $m)
{
@aryA = $sthA->fetchrow_array;
$filename[$m] = $aryA[0];
$rank[$m] = $aryA[1];
$filerank[$m] = sprintf("%04d",$rank[$m]) . "_";
$fileexists[$m] = 0;
$filesize_moh[$m] = 0;
$filesize_original[$m] = 0;
$filelist_names .= "$filerank[$m]$filename[$m]|";
if ( (-e "$MoH_directory/$filerank[$m]$filename[$m]$wav") || (-e "$MoH_directory/$filerank[$m]$filename[$m]$gsm") )
{
if (-e "$MoH_directory/$filerank[$m]$filename[$m]$wav")
{
$temp_filesize_moh = (-s "$MoH_directory/$filerank[$m]$filename[$m]$wav");
$temp_filesize_original = (-s "$PATHsounds/$filename[$m]$wav");
$filesize_moh[$m] = ($filesize_moh[$m] + $temp_filesize_moh);
$filesize_original[$m] = ($filesize_original[$m] + $temp_filesize_original);
if ($DBX)
{
print "WAV check existing:\n";
print "$temp_filesize_moh|$filesize_moh[$m]|$MoH_directory/$filerank[$m]$filename[$m]$wav\n";
print "$temp_filesize_original|$filesize_original[$m]|$PATHsounds/$filename[$m]$wav\n";
}
}
if (-e "$MoH_directory/$filerank[$m]$filename[$m]$gsm")
{
$temp_filesize_moh = (-s "$MoH_directory/$filerank[$m]$filename[$m]$gsm");
$temp_filesize_original = (-s "$PATHsounds/$filename[$m]$gsm");
$filesize_moh[$m] = ($filesize_moh[$m] + $temp_filesize_moh);
$filesize_original[$m] = ($filesize_original[$m] + $temp_filesize_original);
if ($DBX)
{
print "GSM check existing:\n";
print "$temp_filesize_moh|$filesize_moh[$m]|$MoH_directory/$filerank[$m]$filename[$m]$gsm\n";
print "$temp_filesize_original|$filesize_original[$m]|$PATHsounds/$filename[$m]$gsm\n";
}
}
if ( ($filesize_moh[$m] == $filesize_original[$m]) && ($filesize_moh[$m] > 0) )
{$fileexists[$m]++;}
}
if ($fileexists[$m] < 1)
{
$d=0;
foreach(@sounds)
{
if ($sounds[$d] =~ /^$filename[$m]\./)
{
`cp $PATHsounds/$sounds[$d] $MoH_directory/$filerank[$m]$sounds[$d]`;
$fileexists[$m]++;
if ($DBX)
{print "Copy new file: $PATHsounds/$sounds[$d] $MoH_directory/$filerank[$m]$sounds[$d]\n";}
}
$d++;
}
}
$m++;
}
$sthA->finish();
opendir(mohdir, "$MoH_directory");
@MoH_files= readdir(mohdir);
closedir(mohdir);
### Check for files not in MoH context and delete them
$d=0;
foreach(@MoH_files)
{
$MoH_files_check[$d] = $MoH_files[$d];
$MoH_files_check[$d] =~ s/\..*$//gi;
if ($DBX)
{print "Checking file: $MoH_files[$d] $MoH_files_check[$d] $filelist_names\n";}
if ( (length($MoH_files[$d]) > 4) && (-f "$MoH_directory/$MoH_files[$d]") && ($filelist_names !~ /\|$MoH_files_check[$d]\|/) && ($MoH_files_check[$d] !~ /^0000_/) )
{
`rm -f $MoH_directory/$MoH_files[$d]`;
if ($DBX)
{print "Deleting file: $MoH_directory/$MoH_files[$d] $filelist_names\n";}
}
$d++;
}
$j++;
}
### reloading moh in Asterisk
if ($DBX)
{print "reloading moh in asterisk\n";}
# Asterisk 11 will only reload a config file once after it's a time changes, so we need to touch conf files
`touch /etc/asterisk/musiconhold.conf`;
`touch /etc/asterisk/musiconhold-vicidial.conf`;
`screen -XS asterisk eval 'stuff "moh reload\015"'`;
}
###### END Music on hold rebuild #####
if($DB)
{
print "AUDIO FILES ON SERVER: $total_files\n";
print "NEW DOWNLOADED: $downloaded\n";
print "NEW UPLOADED: $uploaded\n\n";
### calculate time to run script ###
$secY = time();
$secZ = ($secY - $secT);
if (!$q) {print "DONE. Script execution time in seconds: $secZ\n";}
}
$dbhA->disconnect();
exit;
sub event_logger
{
if ($SYSLOG)
{
### open the log file for writing ###
open(Lout, ">>$VASLOGfile")
|| die "Can't open $VASLOGfile: $!\n";
print Lout "$now_date|$event_string|\n";
close(Lout);
}
$event_string='';
}
@@ -0,0 +1,604 @@
#!/usr/bin/perl
#
# ADMIN_backup.pl version 2.12
#
# DESCRIPTION:
# Backs-up the asterisk database, conf/agi/sounds/bin files
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
#
# 80316-2211 - First Build
# 80317-1609 - Added Sangoma conf file backup and changed FTP settings
# 80328-0135 - Do not attempt to archive /etc/my.cnf is --without-db flag is set
# 80611-0549 - Added DB option to backup all tables except for log tables
# 90620-1851 - Moved mysqldump bin lookup to database backup section
# 100211-0910 - Added crontab backup and voicemail backup option
# 100817-1202 - Fixed test option bug
# 101208-0452 - Added checks for zaptel and dahdi conf files
# 141103-1505 - Added option to export without leads, logs, servers or phones
# 141124-2309 - Fixed Fhour variable bug
# 150418-1801 - Added --db_raw_files_copy flag, issue #839
# 151006-1337 - Added archive_path flag, issue #896
# 160510-2249 - Added --db-without-archives flag, issue #945
# 160719-1415 - Added --dbs-selected=XXX---YYY option
# 161030-0847 - Added CLI ftp options, Issue #442
#
$secT = time();
$secX = time();
($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";}
$file_date = "$year-$mon-$mday";
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$VDL_date = "$year-$mon-$mday 00:00:01";
$db_raw_files_copy=0;
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 =~ /^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;}
if ( ($line =~ /^VARREPORT_host/) && ($CLIREPORT_host < 1) )
{$VARREPORT_host = $line; $VARREPORT_host =~ s/.*=//gi;}
if ( ($line =~ /^VARREPORT_user/) && ($CLIREPORT_user < 1) )
{$VARREPORT_user = $line; $VARREPORT_user =~ s/.*=//gi;}
if ( ($line =~ /^VARREPORT_pass/) && ($CLIREPORT_pass < 1) )
{$VARREPORT_pass = $line; $VARREPORT_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARREPORT_port/) && ($CLIREPORT_port < 1) )
{$VARREPORT_port = $line; $VARREPORT_port =~ s/.*=//gi;}
if ( ($line =~ /^VARREPORT_dir/) && ($CLIREPORT_dir < 1) )
{$VARREPORT_dir = $line; $VARREPORT_dir =~ s/.*=//gi;}
$i++;
}
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [--db-only] = only backup the database\n";
print " [--db-settings-only] = only backup the database without leads, logs, servers or phones\n";
print " [--db-without-logs] = do not backup the log tables in the database\n";
print " [--db-without-archives] = do not backup the archive tables in the database\n";
print " [--dbs-selected=X] = backup only selected databases, default uses conf file db only\n";
print " to backup databases X and Y, use X---Y, can use --ALL-- for all dbs on server\n";
print " you can use --ALLNS-- for all non-mysql dbs(will ignore 'test', 'mysql','information_schema')\n";
print " This feature will NOT work with '--db_raw_files_copy' option\n";
print " [--conf-only] = only backup the asterisk conf files\n";
print " [--without-db] = do not backup the database\n";
print " [--without-conf] = do not backup the conf files\n";
print " [--without-web] = do not backup web files\n";
print " [--without-sounds] = do not backup asterisk sounds\n";
print " [--without-voicemail] = do not backup asterisk voicemail\n";
print " [--without-crontab] = do not backup crontab\n";
print " [--ftp-transfer] = Transfer backup to the 'REPORTS' FTP server\n";
print " [--ftp-server=XXXXXXXX] = OVERRIDE FTP server to send file to\n";
print " [--ftp-login=XXXXXXXX] = OVERRIDE FTP user\n";
print " [--ftp-pass=XXXXXXXX] = OVERRIDE FTP pass\n";
print " [--ftp-dir=XXXXXXXX] = OVERRIDE remote FTP server directory to post files to\n";
print " [--debugX] = super debug\n";
print " [--debug] = debug\n";
print " [--test] = test\n";
print " [--db_raw_files_copy] = if set the backup won't be a mysql dump. It will tar the /var/lib/mysql folder. WARNING, THIS OPTION WILL STOP THE MYSQL SERVER!\n";
print " [--archive_path=/PATH/FROM/ROOT] = absolute path to store the resulting backup\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1; $FTPdebug=1;
print "\n----- DEBUG -----\n\n";
}
if ($args =~ /--debugX/i)
{
$DBX=1;
print "\n----- SUPER DEBUG -----\n\n";
}
if ($args =~ /--test/i)
{
$T=1; $TEST=1;
print "\n-----TESTING -----\n\n";
}
if ($args =~ /--db-settings-only/i)
{
$db_settings_only=1;
print "\n----- Backup Database Settings Only -----\n\n";
}
if ($args =~ /--db-only/i)
{
$db_only=1;
print "\n----- Backup Database Only -----\n\n";
}
if ($args =~ /--db-without-logs/i)
{
$db_without_logs=1;
print "\n----- Backup Database Without Logs -----\n\n";
}
if ($args =~ /--db-without-archives/i)
{
$db_without_archives=1;
print "\n----- Backup Database Without Archives -----\n\n";
}
if ($args =~ /--dbs-selected=/i)
{
@data_in = split(/--dbs-selected=/,$args);
$dbs_selected = $data_in[1];
$dbs_selected =~ s/ .*//gi;
if ($q < 1) {print "\n----- DATABASES SELECTED: $dbs_selected -----\n\n";}
}
else
{$dbs_selected = '';}
if ($args =~ /--conf-only/i)
{
$conf_only=1;
print "\n----- Conf Files Backup Only -----\n\n";
}
if ($args =~ /--without-db/i)
{
$without_db=1;
print "\n----- No Database Backup -----\n\n";
}
if ($args =~ /--without-conf/i)
{
$without_conf=1;
print "\n----- No Conf Files Backup -----\n\n";
}
if ($args =~ /--without-sounds/i)
{
$without_sounds=1;
print "\n----- No Sounds Backup -----\n\n";
}
if ($args =~ /--without-web/i)
{
$without_web=1;
print "\n----- No web files Backup -----\n\n";
}
if ($args =~ /--without-voicemail/i)
{
$without_voicemail=1;
print "\n----- No voicemail files Backup -----\n\n";
}
if ($args =~ /--without-crontab/i)
{
$without_crontab=1;
print "\n----- No crontab Backup -----\n\n";
}
if ($args =~ /--ftp-transfer/i)
{
$ftp_transfer=1;
print "\n----- FTP transfer -----\n\n";
}
if ($args =~ /--db_raw_files_copy/i)
{
$db_raw_files_copy = 1;
print "\n----- DB raw files copy -----\n\n";
}
if ($args =~ /--archive_path=/i)
{
@data_in = split(/--archive_path=/,$args);
$ARCHIVEpath = $data_in[1];
$ARCHIVEpath =~ s/ .*$//gi;
print "\n----- Archive path set to $ARCHIVEpath -----\n\n";
}
if ($args =~ /--ftp-server=/i)
{
@data_in = split(/--ftp-server=/,$args);
$VARREPORT_host = $data_in[1];
$VARREPORT_host =~ s/ .*//gi;
$VARREPORT_host =~ s/:/,/gi;
if ($DB > 0) {print "\n----- FTP SERVER: $VARREPORT_host -----\n\n";}
}
if ($args =~ /--ftp-login=/i)
{
@data_in = split(/--ftp-login=/,$args);
$VARREPORT_user = $data_in[1];
$VARREPORT_user =~ s/ .*//gi;
$VARREPORT_user =~ s/:/,/gi;
if ($DB > 0) {print "\n----- FTP LOGIN: $VARREPORT_user -----\n\n";}
}
if ($args =~ /--ftp-pass=/i)
{
@data_in = split(/--ftp-pass=/,$args);
$VARREPORT_pass = $data_in[1];
$VARREPORT_pass =~ s/ .*//gi;
$VARREPORT_pass =~ s/:/,/gi;
if ($DB > 0) {print "\n----- FTP PASS: <SET> -----\n\n";}
}
if ($args =~ /--ftp-dir=/i)
{
@data_in = split(/--ftp-dir=/,$args);
$VARREPORT_dir = $data_in[1];
$VARREPORT_dir =~ s/ .*//gi;
$VARREPORT_dir =~ s/:/,/gi;
if ($DB > 0) {print "\n----- FTP DIR: $VARREPORT_dir -----\n\n";}
}
}
}
else
{
print "no command line options set\n";
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$ARCHIVEpath) {$ARCHIVEpath = "$PATHlogs/archive";}
if (!$VARDB_port) {$VARDB_port='3306';}
### find tar binary to do the archiving
$tarbin = '';
if ( -e ('/usr/bin/tar')) {$tarbin = '/usr/bin/tar';}
else
{
if ( -e ('/usr/local/bin/tar')) {$tarbin = '/usr/local/bin/tar';}
else
{
if ( -e ('/bin/tar')) {$tarbin = '/bin/tar';}
else
{
print "Can't find tar binary! Exiting...\n";
exit;
}
}
}
### find gzip binary to do the archiving
$gzipbin = '';
if ( -e ('/usr/bin/gzip')) {$gzipbin = '/usr/bin/gzip';}
else
{
if ( -e ('/usr/local/bin/gzip')) {$gzipbin = '/usr/local/bin/gzip';}
else
{
if ( -e ('/bin/gzip')) {$gzipbin = '/bin/gzip';}
else
{
print "Can't find gzip binary! Exiting...\n";
exit;
}
}
}
$conf='_CONF_';
$sangoma='_SANGOMA_';
$linux='_LINUX_';
$bin='_BIN_';
$web='_WEB_';
$sounds='_SOUNDS_';
$voicemail='_VOICEMAIL_';
$all='_ALL_';
$tar='.tar';
$gz='.gz';
$sgSTRING='';
`cd $ARCHIVEpath`;
`mkdir $ARCHIVEpath/temp`;
if ( ($without_db < 1) && ($conf_only < 1) )
{
if ($db_raw_files_copy < 1)
{
### find mysqldump binary to do the database dump
print "\n----- Mysql dump -----\n\n";
$mysqldumpbin = '';
if ( -e ('/usr/bin/mysqldump')) {$mysqldumpbin = '/usr/bin/mysqldump';}
else
{
if ( -e ('/usr/local/mysql/bin/mysqldump')) {$mysqldumpbin = '/usr/local/mysql/bin/mysqldump';}
else
{
if ( -e ('/bin/mysqldump')) {$mysqldumpbin = '/bin/mysqldump';}
else
{
print "Can't find mysqldump binary! MySQL backups will not work...\n";
}
}
}
use DBI;
$dbs_to_backup[0]="$VARDB_database";
if (length($dbs_selected)> 0)
{
if ($dbs_selected =~ /--ALL--|--ALLNS--/)
{
if ($DBX > 0) {print "DBX- ALL DATABASES OPTION ENABLED! GATHERING DBS...\n";}
### connect to MySQL database defined in the conf file so we can get database list
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
$stmtA = "show databases;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$dbArows=$sthA->rows;
$db_ct=0;
$db_s_ct=0;
while ($dbArows > $db_ct)
{
@aryA = $sthA->fetchrow_array;
if ($dbs_selected =~ /--ALLNS--/)
{
if ($aryA[0] !~ /^test$|^mysql$|^information_schema$/)
{
$dbs_to_backup[$db_s_ct] = $aryA[0];
$db_s_ct++;
if ($DBX > 0) {print "DBX- database $db_ct($db_s_ct): $aryA[0]\n";}
}
}
else
{
$dbs_to_backup[$db_s_ct] = $aryA[0];
$db_s_ct++;
if ($DBX > 0) {print "DBX- database $db_ct($db_s_ct): $aryA[0]\n";}
}
$db_ct++;
}
$sthA->finish;
$dbhA->disconnect;
}
else
{
if ($dbs_selected =~ /---/)
{
@dbs_to_backup = split(/---/,$dbs_selected);
if ($DBX > 0) {printf "DBX- databases %d\n", $#dbs_to_backup + 1;}
}
else
{$dbs_to_backup[0]="$dbs_selected";}
}
}
$c=0;
while ($c <= $#dbs_to_backup)
{
$temp_dbname = $dbs_to_backup[$c];
if ($DBX > 0) {print "DBX- starting to backup database $c: $temp_dbname\n";}
### BACKUP THE MYSQL FILES ON THE DB SERVER ###
### connect to MySQL database defined in the conf file
$dbhA = DBI->connect("DBI:mysql:$temp_dbname:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
$stmtA = "show tables;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
$log_tables='';
$archive_tables='';
$regular_tables='';
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
if ($aryA[0] =~ /_archive/)
{
$archive_tables .= " $aryA[0]";
}
elsif ($aryA[0] =~ /_log|server_performance|vicidial_ivr|vicidial_hopper|vicidial_manager|web_client_sessions|imm_outcomes/)
{
$log_tables .= " $aryA[0]";
}
elsif ($aryA[0] =~ /server|^phones|conferences|stats|vicidial_list$|^custom/)
{
$regular_tables .= " $aryA[0]";
}
else
{
$conf_tables .= " $aryA[0]";
}
$rec_count++;
}
$sthA->finish();
if ($db_without_logs)
{
$dump_non_log_command = "$mysqldumpbin --user=$VARDB_user --password=$VARDB_pass --lock-tables --flush-logs $temp_dbname $regular_tables $conf_tables | $gzipbin > $ARCHIVEpath/temp/$VARserver_ip$temp_dbname$wday.gz";
$dump_log_command = "$mysqldumpbin --user=$VARDB_user --password=$VARDB_pass --lock-tables --flush-logs --no-data --no-create-db $temp_dbname $log_tables $archive_tables | $gzipbin > $ARCHIVEpath/temp/LOGS_$VARserver_ip$temp_dbname$wday.gz";
if ($DBX) {print "$dump_non_log_command\nDEBUG: LOG EXPORT COMMAND(not run): $dump_log_command\n";}
`$dump_non_log_command`;
}
elsif ($db_without_archives)
{
$dump_non_archive_command = "$mysqldumpbin --user=$VARDB_user --password=$VARDB_pass --lock-tables --flush-logs $temp_dbname $regular_tables $conf_tables $log_tables | $gzipbin > $ARCHIVEpath/temp/$VARserver_ip$temp_dbname$wday.gz";
$dump_archive_command = "$mysqldumpbin --user=$VARDB_user --password=$VARDB_pass --lock-tables --flush-logs --no-data --no-create-db $temp_dbname $archive_tables | $gzipbin > $ARCHIVEpath/temp/ARCHIVES_$VARserver_ip$temp_dbname$wday.gz";
if ($DBX) {print "$dump_non_archive_command\nDEBUG: ARCHIVE EXPORT COMMAND(not run): $dump_archive_command\n";}
`$dump_non_archive_command`;
}
elsif ($db_settings_only)
{
$dump_non_log_command = "$mysqldumpbin --user=$VARDB_user --password=$VARDB_pass --lock-tables --flush-logs $temp_dbname $conf_tables | $gzipbin > $ARCHIVEpath/temp/SETTINGSONLY_$VARserver_ip$temp_dbname$wday.gz";
$dump_log_command = "$mysqldumpbin --user=$VARDB_user --password=$VARDB_pass --lock-tables --flush-logs --no-data --no-create-db $temp_dbname $log_tables $archive_tables $regular_tables | $gzipbin > $ARCHIVEpath/temp/LOGS_$VARserver_ip$temp_dbname$wday.gz";
if ($DBX) {print "$dump_non_log_command\nNOT ARCHIVED: $dump_log_command\n";}
`$dump_non_log_command`;
}
else
{
if ($DBX) {print "$mysqldumpbin --user=$VARDB_user --password=$VARDB_pass --lock-tables --flush-logs $temp_dbname | $gzipbin > $ARCHIVEpath/temp/$VARserver_ip$temp_dbname$wday.gz\n";}
`$mysqldumpbin --user=$VARDB_user --password=$VARDB_pass --lock-tables --flush-logs $temp_dbname | $gzipbin > $ARCHIVEpath/temp/$VARserver_ip$temp_dbname$wday.gz`;
}
$c++;
}
}
else
{
print "\n----- Mysql Raw Copy -----\n\n";
`service mysql stop`;
`$tarbin -zcvf $ARCHIVEpath/temp/"$VARserver_ip"_mysql_raw_"$wday".tar.gz /var/lib/mysql/test /var/lib/mysql/mysql /var/lib/mysql/performance_schema /var/lib/mysql/asterisk`;
`service mysql start`;
}
}
if ( ($without_conf < 1) && ($db_only < 1) )
{
### BACKUP THE ASTERISK CONF FILES ON THE SERVER ###
$zapdahdi='';
if (-e "/etc/zaptel.conf") {$zapdahdi .= " /etc/zaptel.conf";}
if (-e "/etc/dahdi/system.conf") {$zapdahdi .= " /etc/dahdi";}
if ($DBX) {print "$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$conf$wday$tar /etc/astguiclient.conf $zapdahdi /etc/asterisk\n";}
`$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$conf$wday$tar /etc/astguiclient.conf $zapdahdi /etc/asterisk`;
### BACKUP THE WANPIPE CONF FILES(if there are any) ###
if ( -e ('/etc/wanpipe/wanpipe1.conf'))
{
$sgSTRING = '/etc/wanpipe/wanpipe1.conf ';
if ( -e ('/etc/wanpipe/wanpipe2.conf')) {$sgSTRING .= '/etc/wanpipe/wanpipe2.conf ';}
if ( -e ('/etc/wanpipe/wanpipe3.conf')) {$sgSTRING .= '/etc/wanpipe/wanpipe3.conf ';}
if ( -e ('/etc/wanpipe/wanpipe4.conf')) {$sgSTRING .= '/etc/wanpipe/wanpipe4.conf ';}
if ( -e ('/etc/wanpipe/wanpipe5.conf')) {$sgSTRING .= '/etc/wanpipe/wanpipe5.conf ';}
if ( -e ('/etc/wanpipe/wanpipe6.conf')) {$sgSTRING .= '/etc/wanpipe/wanpipe6.conf ';}
if ( -e ('/etc/wanpipe/wanpipe7.conf')) {$sgSTRING .= '/etc/wanpipe/wanpipe7.conf ';}
if ( -e ('/etc/wanpipe/wanpipe8.conf')) {$sgSTRING .= '/etc/wanpipe/wanpipe8.conf ';}
if ( -e ('/etc/wanpipe/wanrouter.rc')) {$sgSTRING .= '/etc/wanpipe/wanrouter.rc ';}
if ($DBX) {print "$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$sangoma$wday$tar $sgSTRING\n";}
`$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$sangoma$wday$tar $sgSTRING`;
}
### BACKUP OTHER CONF FILES ON THE SERVER ###
$files = "";
if ($without_db < 1)
{
if ( -e ('/etc/my.cnf')) {$files .= "/etc/my.cnf ";}
}
if ($without_crontab < 1)
{
`crontab -l > /etc/crontab_snapshot`;
if ( -e ('/etc/crontab_snapshot')) {$files .= "/etc/crontab_snapshot ";}
}
if ( -e ('/etc/hosts')) {$files .= "/etc/hosts ";}
if ( -e ('/etc/rc.d/rc.local')) {$files .= "/etc/rc.d/rc.local ";}
if ( -e ('/etc/resolv.conf')) {$files .= "/etc/resolv.conf ";}
if ($DBX) {print "$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$linux$wday$tar $files\n";}
`$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$linux$wday$tar $files`;
}
if ( ($conf_only < 1) && ($db_only < 1) && ($without_web < 1) )
{
### BACKUP THE WEB FILES ON THE SERVER ###
if ($DBX) {print "$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$web$wday$tar $PATHweb\n";}
`$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$web$wday$tar $PATHweb`;
}
if ( ($conf_only < 1) && ($db_only < 1) )
{
### BACKUP THE ASTGUICLIENT AND AGI FILES ON THE SERVER ###
if ($DBX) {print "$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$bin$wday$tar $PATHagi $PATHhome\n";}
`$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$bin$wday$tar $PATHagi $PATHhome`;
}
if ( ($conf_only < 1) && ($db_only < 1) && ($without_sounds < 1) )
{
### BACKUP THE ASTERISK SOUNDS ON THE SERVER ###
if ($DBX) {print "$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$sounds$wday$tar $PATHsounds\n";}
`$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$sounds$wday$tar $PATHsounds`;
}
if ( ($conf_only < 1) && ($db_only < 1) && ($without_voicemail < 1) )
{
### BACKUP THE ASTERISK VOICEMAIL ON THE SERVER ###
if ($DBX) {print "$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$voicemail$wday$tar /var/spool/asterisk/voicemail\n";}
`$tarbin cf $ARCHIVEpath/temp/$VARserver_ip$voicemail$wday$tar /var/spool/asterisk/voicemail`;
}
### PUT EVERYTHING TOGETHER TO BE COMPRESSED ###
if ($DBX) {print "$tarbin cf $ARCHIVEpath/$VARserver_ip$all$wday$tar $ARCHIVEpath/temp\n";}
`$tarbin cf $ARCHIVEpath/$VARserver_ip$all$wday$tar $ARCHIVEpath/temp`;
### REMOVE OLD GZ FILE
if ($DBX) {print "rm -f $ARCHIVEpath/$VARserver_ip$all$wday$tar$gz\n";}
`rm -f $ARCHIVEpath/$VARserver_ip$all$wday$tar$gz`;
### COMPRESS THE ALL FILE ###
if ($DBX) {print "$gzipbin -9 $ARCHIVEpath/$VARserver_ip$all$wday$tar\n";}
`$gzipbin -9 $ARCHIVEpath/$VARserver_ip$all$wday$tar`;
### REMOVE TEMP FILES ###
if ($DBX) {print "rm -fR $ARCHIVEpath/temp\n";}
`rm -fR $ARCHIVEpath/temp`;
#### FTP to the Backup server and upload the final file
if ($ftp_transfer > 0)
{
if ($DBX) {print "Starting FTP transfer...($VARREPORT_user at $VARREPORT_host dir: $VARREPORT_dir)\n";}
use Net::FTP;
$ftp = Net::FTP->new("$VARREPORT_host", Port => "$VARREPORT_port", Debug => "$FTPdebug");
$ftp->login("$VARREPORT_user","$VARREPORT_pass");
$ftp->cwd("$VARREPORT_dir");
$ftp->binary();
$ftp->put("$ARCHIVEpath/$VARserver_ip$all$wday$tar$gz", "$VARserver_ip$all$wday$tar$gz");
$ftp->quit;
}
### calculate time to run script ###
$secY = time();
$secZ = ($secY - $secX);
$secZm = ($secZ /60);
if (!$Q) {print "script execution time in seconds: $secZ minutes: $secZm\n";}
if ($DBX) {print "DONE, Exiting...\n";}
exit;
@@ -0,0 +1,321 @@
#!/usr/bin/perl
#
# ADMIN_bcrypt_convert.pl version 2.10
#
# Bcrypt password hashing conversion script to be used for authentication
#
# This script is to be run once to convert the plaintext passwords into bcrypt
# password hashes.
#
# IMPORTANT !!!!!!!!!!!!!
# The Crypt::Eksblowfish::Bcrypt perl module is REQUIRED for this script
#
# Copyright (C) 2014 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
#
# CHANGES
#
# 130704-2041 - First build
# 141231-0959 - Added --conffile option
#
$T=0;
$update_override=0;
$clear_plaintext_pass=0;
$DB=1;
$DBX=0;
use DBI;
use Crypt::Eksblowfish::Bcrypt qw(en_base64);
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "Bcrypt password hashing conversion script to be used for authentication\n";
print "IMPORTANT!!! RUN FIRST WITH THE --test FLAG TO MAKE SURE IT WORKS!!!\n";
print "\n";
print "allowed run time options:\n";
print " [--conffile=/path/from/root] = define configuration file path from root at runtime\n";
print " [--salt=XXX] = overide the system salt\n";
print " [--cost=XX] = overide the system cost\n";
print " [--test] = testing mode only, no database updates\n";
print " [--update-override] = override existing system settings\n";
print " [--clear-plaintext-pass] = set plaintext passwords to blank while updating users\n";
print " [--debug] = enable debugging output\n";
print " [--debugX] = enable extra debugging output\n";
print " [--help] = this help screen\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1;
if ($DB > 0) {print "\n----- DEBUGGING OUTPUT ENABLED: $DB -----\n";}
}
if ($args =~ /--debugX/i)
{
$DBX=1;
if ($DB > 0) {print "\n----- EXTRA DEBUGGING OUTPUT ENABLED: $DBX -----\n";}
}
if ($args =~ /--test/i)
{
$T=1;
open(testfile, ">/etc/vicidial_bcrypt.test") || die "can't open /etc/vicidial_bcrypt.test: $!\n";
print testfile "TEST RUN";
close(testfile);
if ($DB > 0) {print "\n----- TESTING MODE ENABLED: $T -----\n";}
}
if ($args =~ /--update-override/i)
{
$update_override=1;
if ($DB > 0) {print "\n----- UPDATE OVERRIDE ENABLED: $update_override -----\n";}
}
if ($args =~ /--clear-plaintext-pass/i)
{
$clear_plaintext_pass=1;
if ($DB > 0) {print "\n----- CLEAR PLAINTEXT PASSWORDS: $clear_plaintext_pass -----\n";}
}
if ($args =~ /--salt=/i)
{
@data_in = split(/--salt=/,$args);
$CLIsalt = $data_in[1];
$CLIsalt =~ s/ .*//gi;
if (length($CLIsalt) eq 16)
{
$newCLIsalt = en_base64($CLIsalt);
if ($DB > 0)
{print "\n----- ENCRYPTING SALT OVERRIDE: $CLIsalt -----\n";}
$CLIsalt = $newCLIsalt;
}
if (length($CLIsalt) ne 22)
{
if ($DB > 0)
{print "\n----- INVALID SALT OVERRIDE, USING DEFAULT: $CLIsalt -----\n\n";}
$CLIsalt = '';
}
else
{
if ($DB > 0)
{print "\n----- SALT OVERRIDE: $CLIsalt -----\n\n";}
}
}
if ($args =~ /--cost=/i)
{
@data_in = split(/--cost=/,$args);
$CLIcost = $data_in[1];
$CLIcost =~ s/ .*//gi;
if ($DB > 0)
{print "\n----- COST OVERRIDE: $CLIcost -----\n\n";}
}
if ($args =~ /--conffile=/i) # CLI defined conffile path
{
@CLIconffileARY = split(/--conffile=/,$args);
@CLIconffileARX = split(/ /,$CLIconffileARY[1]);
if (length($CLIconffileARX[0])>2)
{
$PATHconf = $CLIconffileARX[0];
$PATHconf =~ s/\/$| |\r|\n|\t//gi;
$CLIconffile=1;
if (!$Q) {print " CLI defined conffile path: $PATHconf\n";}
}
}
}
}
else
{
print "NO INPUT, NOTHING TO DO, EXITING...\n";
exit;
}
### end parsing run-time options ###
if ( ($T < 1) && (!-e "/etc/vicidial_bcrypt.test") )
{
print "YOU MUST RUN THIS IN TEST MODE FIRST, EXITING...\n";
exit;
}
# default path to astguiclient configuration file:
if (length($PATHconf) < 5)
{$PATHconf = '/etc/astguiclient.conf';}
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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';}
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
##### Get the settings from system_settings #####
$stmtA = "SELECT pass_hash_enabled,pass_key,pass_cost FROM system_settings;";
# print "$stmtA\n";
$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;
$pass_hash_enabled = $aryA[0];
$pass_key = $aryA[1];
$pass_cost = $aryA[2];
if (length($pass_key) eq 16)
{$newpass_key = en_base64($pass_key);}
}
$sthA->finish();
if ($DBX > 0) {print "SYSTEM SETTINGS: |$pass_hash_enabled|$pass_key|$newpass_key|$pass_cost|\n";}
if ( (length($pass_key) > 15) && ($pass_hash_enabled > 0) && ($update_override < 1) )
{
print "System already set for encryption. If you still want to run this script you must use the update override flag.\n";
exit;
}
if (length($CLIsalt) > 0)
{
if ($DBX > 0) {print "SALT OVERRIDDEN: |$pass_key|$newpass_key|$CLIsalt|\n";}
$salt = $CLIsalt;
}
else
{$salt = $newpass_key;}
if (length($CLIcost) > 0)
{
if ($DBX > 0) {print "COST OVERRIDDEN: |$pass_cost|$CLIcost|\n";}
$cost = $CLIcost;
}
else
{$cost = $pass_cost;}
while (length($cost) < 2)
{$cost = "0$cost";}
$stmtA = "SELECT user,pass,full_name from vicidial_users;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$i=0;
while ($sthArows > $i)
{
@aryA = $sthA->fetchrow_array;
$user[$i] = $aryA[0];
$pass[$i] = $aryA[1];
$full_name[$i] = $aryA[2];
$only_pass_hash[$i] = '';
$i++;
}
$sthA->finish();
if ($DB > 0) {print "$i USERS FOUND IN YOUR SYSTEM\n";}
# Set the cost to $cost and append a NUL
$settings = '$2a$'.$cost.'$'.$salt;
if ($DB > 0) {print "STARTING BCRYPT PROCESS\n";}
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl timing of less than one second
($START_s_hires, $START_usec) = gettimeofday();
$i=0;
while ($sthArows > $i)
{
# Encrypt it
$pass_hash = Crypt::Eksblowfish::Bcrypt::bcrypt($pass[$i], $settings);
$pass_hash_length = length($pass_hash);
$only_pass_hash[$i] = substr($pass_hash,29,31);
if ($DB > 0) {print "PASS HASH: |$user[$i]|$pass[$i]|$full_name[$i]|$pass_hash_length|$pass_hash|$only_pass_hash[$i]|\n";}
$i++;
}
($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("%.6f", $RUN_time);
if ($DBX > 0)
{print "TOTAL bcrypt time: |$RUN_time ($END_time - $START_time)|\n";}
if ($DB > 0) {print "STARTING USER RECORD UPDATES\n";}
$passSQL='';
if ($clear_plaintext_pass > 0)
{$passSQL=",pass=''";}
$TOTALaffected_rows=0;
$i=0;
while ($sthArows > $i)
{
$affected_rows=0;
$stmtA = "UPDATE vicidial_users set pass_hash='$only_pass_hash[$i]' $passSQL where user='$user[$i]';";
if ($T < 1)
{$affected_rows = $dbhA->do($stmtA);} # or die "Couldn't execute query:|$stmtA|\n";
$TOTALaffected_rows = ($TOTALaffected_rows + $affected_rows);
if ($DB > 0) {print "USER UPDATE: |$user[$i]|$pass[$i]|$full_name[$i]|$only_pass_hash[$i]|$affected_rows|\n";}
if ($DBX > 0) {print "SQL: |$stmtA|\n";}
$i++;
}
if ( ($T < 1) && ($TOTALaffected_rows > 0) )
{
open(keyfile, ">/etc/vicidial.key") || die "can't open /etc/vicidial.key: $!\n";
print keyfile "$salt";
close(keyfile);
$stmtA = "UPDATE system_settings set pass_hash_enabled='1';";
$affected_rows = $dbhA->do($stmtA);
if ($DB > 0) {print "BCRYPT SET TO ENABLED ON YOUR SYSTEM: |$affected_rows|$stmtA|\n";}
}
if ($DB > 0) {print "BCRYPT PROCESSES COMPLETE: $TOTALaffected_rows USERS UPDATED\n";}
exit;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,132 @@
#!/usr/bin/perl
#
# ADMIN_reset_failed_count.pl version 2.8
#
# resets the failed_login_count for a given user
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
#
# CHANGES
#
# 130909-1222 - Mikec - First build
#
$T=0;
$DB=1;
$DBX=0;
use DBI;
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "Reset a given users failed count so they can attempt to log in.\n";
print "\n";
print "allowed run time options:\n";
print " [--user=XXX] = the user to reset failed count for\n";
print " [--test] = testing mode only, no database updates\n";
print " [--debug] = enable debugging output\n";
print " [--debugX] = enable extra debugging output\n";
print " [--help] = this help screen\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1;
if ($DB > 0) {print "\n----- DEBUGGING OUTPUT ENABLED: $DB -----\n";}
}
if ($args =~ /--debugX/i)
{
$DBX=1;
$DB=1;
if ($DB > 0) {print "\n----- EXTRA DEBUGGING OUTPUT ENABLED: $DBX -----\n";}
}
if ($args =~ /--test/i)
{
$T=1;
if ($DB > 0) {print "\n----- TESTING MODE ENABLED: $T -----\n";}
}
if ($args =~ /--user=/i)
{
@data_in = split(/--user=/,$args);
$CLIuser = $data_in[1];
$CLIuser =~ s/ .*//gi;
}
}
}
else
{
print "NO INPUT, NOTHING TO DO, EXITING...\n";
exit;
}
### end parsing run-time options ###
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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';}
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
$affected_rows=0;
$stmtA = "UPDATE vicidial_users set failed_login_count=0 where user='$CLIuser';";
if ($T < 1)
{
$affected_rows = $dbhA->do($stmtA) or die "Couldn't execute query:|$stmtA|\n";
}
if ($DB > 0) {print "Failed Login Count for user $CLIuser has been reset: |$affected_rows|\n";}
if ($DBX > 0) {print "SQL: |$stmtA|\n";}
$i++;
exit;
@@ -0,0 +1,79 @@
#!/usr/bin/perl
#
# ADMIN_restart_roll_logs.pl version 2.12
#
# script to roll the Asterisk logs on machine restart
#
# have this run on the astersik server
#
# Copyright (C) 2015 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGES:
# 90311-0921 - Added /var/log/asterisk/screenlog log rolling
# 90508-0535 - Changes root screenlog to /var/log/astguiclient
# 130108-1715 - Changes for new log rolling script compatibility
# 141124-2309 - Fixed Fhour variable bug
# 151110-2005 - Added rolling of Asterisk cdr.db
#
($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";
print "rolling Asterisk messages log...\n";
if ( -e '/var/log/asterisk/messages' )
{
`mv -f /var/log/asterisk/messages /var/log/asterisk/messages.$now_date`;
}
print "rolling Asterisk event log...\n";
if ( -e '/var/log/asterisk/event_log' )
{
`mv -f /var/log/asterisk/event_log /var/log/asterisk/event_log.$now_date`;
}
print "rolling Asterisk cdr.db...\n";
if ( -e '/var/log/asterisk/cdr.db' )
{
`mv -f /var/log/asterisk/cdr.db /var/log/asterisk/cdr.db.$now_date`;
}
print "rolling Asterisk cdr logs...\n";
if ( -e '/var/log/asterisk/cdr-csv/Master.csv' )
{
`mv -f /var/log/asterisk/cdr-csv/Master.csv /var/log/asterisk/cdr-csv/Master.csv.$now_date`;
}
if ( -e '/var/log/asterisk/cdr-custom/Master.csv' )
{
`mv -f /var/log/asterisk/cdr-custom/Master.csv /var/log/asterisk/cdr-custom/Master.csv.$now_date`;
}
print "rolling Asterisk screen log...\n";
if ( -e '/var/log/astguiclient/screenlog.0' )
{
`mv -f /var/log/astguiclient/screenlog.0 /var/log/astguiclient/screenlog.0.$now_date`;
}
if ( -e '/root/screenlog.0' )
{
`mv -f /root/screenlog.0 /var/log/astguiclient/screenlog.0.root.$now_date`;
}
if ( -e '/var/log/asterisk/screenlog.0' )
{
`mv -f /var/log/asterisk/screenlog.0 /var/log/asterisk/screenlog.0.asterisk.$now_date`;
}
print "FINISHED... EXITING\n";
exit;
@@ -0,0 +1,276 @@
#!/usr/bin/perl
#
# ADMIN_timeclock_auto_logout.pl version 2.2.0 *DBI-version*
#
# DESCRIPTION:
# forces logout of all users still logged into the timeclock
#
# This script is launched by the ADMIN_keepalive_ALL.pl script with the '9' flag
# defined in astguiclient.conf
#
# Copyright (C) 2009 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 80526-0958 - First Build
# 80604-0733 - Fixed minor bug in update
# 90812-0103 - Formatting fixes
#
# constants
$DB=0; # Debug flag, set to 0 for no debug messages, On an active system this will generate lots of lines of output per minute
$US='__';
$MT[0]='';
$secT = time();
$now_date_epoch = $secT;
($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";}
$file_date = "$year-$mon-$mday";
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$VDL_date = "$year-$mon-$mday 00:00:01";
$inactive_epoch = ($secT - 60);
$HHMM = "$hour$min";
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options(must stay in this order):\n [--debug] = debug\n [--debugX] = super debug\n [-t] = test\n [--force-run] = force run even if already run for the day\n\n";
exit;
}
else
{
if ($args =~ /--force-run/i)
{
$force_run=1;
print "\n----- FORCE RUN -----\n\n";
}
if ($args =~ /--debug/i)
{
$DB=1;
print "\n----- DEBUG -----\n\n";
}
if ($args =~ /--debugX/i)
{
$DBX=1;
print "\n----- SUPER DEBUG -----\n\n";
}
if ($args =~ /-t/i)
{
$T=1; $TEST=1;
print "\n-----TESTING -----\n\n";
}
}
}
else
{
print "no command line options set\n";
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 (!$VDALOGfile) {$VDALOGfile = "$PATHlogs/timeclockautologout.$year-$mon-$mday";}
if (!$VARDB_port) {$VARDB_port='3306';}
use DBI;
$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 vd_server_logs,local_gmt FROM servers where server_ip = '$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$DBvd_server_logs = "$aryA[0]";
$DBSERVER_GMT = "$aryA[1]";
if ($DBvd_server_logs =~ /Y/) {$SYSLOG = '1';}
else {$SYSLOG = '0';}
if (length($DBSERVER_GMT)>0) {$SERVER_GMT = $DBSERVER_GMT;}
$rec_count++;
}
$sthA->finish();
### Grab system_settings values from the database
$stmtA = "SELECT timeclock_end_of_day,timeclock_last_reset_date 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;
$timeclock_end_of_day = "$aryA[0]";
$timeclock_last_reset_date = "$aryA[1]";
}
$sthA->finish();
### check to see if the script should run
$nowtest = ($HHMM+0);
$logtest = ($timeclock_end_of_day+0);
if ( ($force_run > 0) || ( ($nowtest >= $logtest) && ($timeclock_last_reset_date ne "$file_date") ) )
{
@user=@MT;
### grab users that are currently logged-in to the timeclock
$stmtA = "SELECT user,user_group,event_epoch,status,ip_address,shift_id from vicidial_timeclock_status where status IN('START','LOGIN')";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$user[$rec_count] = "$aryA[0]";
$user_group[$rec_count] = "$aryA[1]";
$event_epoch[$rec_count] = "$aryA[2]";
$status[$rec_count] = "$aryA[3]";
$ip_address[$rec_count] = "$aryA[4]";
$shift_id[$rec_count] = "$aryA[5]";
$rec_count++;
}
$sthA->finish();
if ($DB) {print "USERS TO LOG OUT OF THE TIMECLOCK: $rec_count\n";}
##### LOOP THROUGH EACH USER AND LOG THEM OUT OF THE TIMECLOCK #####
$i=0;
while($i < $rec_count)
{
if ($DBX) {print " USER: $user[$i]\n";}
$event_string = " USER: $user[$i]";
&event_logger;
$last_action_sec = ($now_date_epoch - $event_epoch[$i]);
$stmtA = "INSERT INTO vicidial_timeclock_log set event='AUTOLOGOUT', user='$user[$i]', user_group='$user_group[$i]', event_epoch='$now_date_epoch', ip_address='$VARserver_ip', login_sec='$last_action_sec', event_date='$now_date';";
$affected_rows = $dbhA->do($stmtA);
$timeclock_id = $dbhA->{'mysql_insertid'};
if ($DBX) {print "|$affected_rows|$stmtA|\n";}
$event_string = "USER VTL INSERT|$affected_rows|$timeclock_id|$stmtA|";
&event_logger;
$stmtA = "UPDATE vicidial_timeclock_log set login_sec='$last_action_sec',tcid_link='$timeclock_id' where event='LOGIN' and user='$user[$i]' order by timeclock_id desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
if ($DBX) {print "|$affected_rows|$stmtA|\n";}
$event_string = "USER VTL UPDATE|$affected_rows|$stmtA|";
&event_logger;
$stmtA = "UPDATE vicidial_timeclock_status set status='AUTOLOGOUT', user_group='$user_group[$i]', event_epoch='$now_date_epoch', ip_address='$VARserver_ip' where user='$user[$i]';";
$affected_rows = $dbhA->do($stmtA);
if ($DBX) {print "|$affected_rows|$stmtA|\n";}
$event_string = "USER VTS UPDATE|$affected_rows|$stmtA|";
&event_logger;
$stmtA = "INSERT INTO vicidial_timeclock_audit_log set timeclock_id='$timeclock_id', event='AUTOLOGOUT', user='$user[$i]', user_group='$user_group[$i]', event_epoch='$now_date_epoch', ip_address='$VARserver_ip', login_sec='$last_action_sec', event_date='$now_date';";
$affected_rows = $dbhA->do($stmtA);
if ($DBX) {print "|$affected_rows|$stmtA|\n";}
$event_string = "USER VTAL INSERT|$affected_rows|$stmtA|";
&event_logger;
$stmtA = "UPDATE vicidial_timeclock_audit_log set login_sec='$last_action_sec',tcid_link='$timeclock_id' where event='LOGIN' and user='$user[$i]' order by timeclock_id desc limit 1;";
$affected_rows = $dbhA->do($stmtA);
if ($DBX) {print "|$affected_rows|$stmtA|\n";}
$event_string = "USER VTAL UPDATE|$affected_rows|$stmtA|";
&event_logger;
$i++;
}
$stmtA = "UPDATE system_settings set timeclock_last_reset_date='$file_date';";
$affected_rows = $dbhA->do($stmtA);
if ($DBX) {print "|$affected_rows|$stmtA|\n";}
$event_string = "SYSTEM SETTINGS UPDATE|$affected_rows|$stmtA|";
&event_logger;
}
else
{
print "cannot run: |$force_run|$HHMM($nowtest)|$timeclock_end_of_day($logtest)|$timeclock_last_reset_date|$file_date|\n";
}
if($DB)
{
### calculate time to run script ###
$secY = time();
$secZ = ($secY - $secT);
if (!$q) {print "DONE. Script execution time in seconds: $secZ\n";}
}
$dbhA->disconnect();
exit;
sub event_logger
{
if ($SYSLOG)
{
### open the log file for writing ###
open(Lout, ">>$VDALOGfile")
|| die "Can't open $VDALOGfile: $!\n";
print Lout "$now_date|$event_string|\n";
close(Lout);
}
$event_string='';
}
@@ -0,0 +1,154 @@
#!/usr/bin/perl
# ADMIN_update_archive_url.pl - updates the url for the archive server
# in the recording_log table
#
# Copyright (C) 2013 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 90609-1609 - mikec - created the script
# 130902-1132 - Fix for issue #697
#
use DBI;
# function to print out the help for this script
sub print_help
{
print "$0 - updates the url in the recording_log\n";
print "command-line options:\n";
print " [--debug] = shows the sql as it is being executed.\n";
print " [--test] = activates debuging and does not actually\n";
print " execute the updates.\n";
print " [--old-server-url] = the old url used to access the recordings.\n";
print " This is a required argument.\n";
print " [--new-server-url] = the new url used to access the recordings.\n";
print " This is a required argument.\n\n";
exit;
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
# read in the conf file
open(CONFIG, "$PATHconf") || die "can't open $PATHconf: $!\n";
@config = <CONFIG>;
close(CONFIG);
$i=0;
foreach(@config) {
$line = $config[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ($line =~ /^VARserver_ip/)
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ($line =~ /^VARDB_server/)
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ($line =~ /^VARDB_database/)
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ($line =~ /^VARDB_user/)
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ($line =~ /^VARDB_pass/)
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ($line =~ /^VARDB_port/)
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
# initialize the variables
$old_url = "";
$new_url = "";
$DB = 0;
$TEST = 0;
# begin parsing run-time options
if ( length($ARGV[0]) > 1 ) {
$i=0;
while ($#ARGV >= $i) {
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i) {
&print_help;
} else {
# activate debugging
if ($args =~ /--debug/i) {
$DB=1;
}
# activate test mode
if ($args =~ /--test/i) {
$DB=1;
$TEST=1;
}
# get the old server url
if ($args =~ /--old-server-url=/i) {
@CLIoldurlARY = split(/--old-server-url=/,$args);
@CLIoldurlARX = split(/ /,$CLIoldurlARY[1]);
$old_url = $CLIoldurlARX[0];
}
# get the new server url
if ($args =~ /--new-server-url=/i) {
@CLInewurlARY = split(/--new-server-url=/,$args);
@CLInewurlARX = split(/ /,$CLInewurlARY[1]);
$new_url = $CLInewurlARX[0];
}
}
} else {
# we didnt get any arguments
&print_help;
}
# make sure they set something
if (( $new_url eq "") || ( $old_url eq "")) {
&print_help;
}
# connect to the db
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
# get all the recordings with the old_url
$stmtA = "SELECT recording_id, location from recording_log where location LIKE '$old_url%';";
if ( $DB ) {
print $stmtA . "\n";
}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
# cycle through them
while ($sthArows > $rec_count) {
@aryA = $sthA->fetchrow_array;
# get the parameters from the DB
$rec_id = "$aryA[0]";
$location = "$aryA[1]";
# change the url
$new_loc = $location;
$new_loc =~ s/$old_url/$new_url/gi;
# UPDATE THE recording_log RECORD
$stmtB = "UPDATE recording_log SET location='$new_loc' where recording_id='$rec_id';";
if ( $DB ) {
print $stmtB . "\n";
}
# execute the update if we are not in test mode
if ( $TEST == 0 ) {
$sthB = $dbhA->prepare($stmtB) or die "preparing: ",$dbhB->errstr;
$sthB->execute or die "executing: $stmtB ", $dbhB->errstr;
$sthB->finish();
}
$rec_count++;
}
print "Updated $rec_count records in the recording_log table\n";
$sthA->finish();
$dbhA->disconnect();
@@ -0,0 +1,501 @@
#!/usr/bin/perl
# ADMIN_update_server_ip.pl - updates IP address in DB and conf file
#
# This script is designed to update all database tables and the local
# astguiclient.conf file to reflect a change in IP address. The script will
# automatically default to the first eth address in the ifconfig output.
#
# Copyright (C) 2015 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 71205-2144 - Added display of extensions.conf example for call routing
# 80321-0220 - Updated for new settings
# 90211-1247 - Added asterisk version
# 90630-2256 - vicidial_process_triggers
# 100428-0943 - Added DB custom user/pass fields
# 150312-1000 - Added ExpectedDBSchema
#
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) )
{$VARold_server_ip = $line; $VARold_server_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++;
}
############################################
$CLIold_server_ip=0;
$CLIserver_ip=0;
$secX = time();
# constants
$DB=1; # Debug flag, set to 0 for no debug messages, lots of output
$US='_';
$MT[0]='';
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "ADMIN_update_server_ip.pl - updates server_ip in the $VARDB_database\n";
print "database and in the local /etc/astguiclient.conf file.\n";
print "\n";
print "command-line options:\n";
print " [--help] = this help screen\n";
print " [--debug] = verbose debug messages\n";
print " [--auto] = no prompts\n";
print "configuration options:\n";
print " [--old-server_ip=192.168.0.1] = define old server IP address at runtime\n";
print " [--server_ip=192.168.0.2] = define new server IP address at runtime\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i) # Debug flag
{
$DB=1;
}
if ($args =~ /--auto/i) # no prompts flag
{
$AUTO=1;
}
if ($args =~ /--old-server_ip=/i) # CLI defined old server IP address
{
@CLIoldserver_ipARY = split(/--old-server_ip=/,$args);
@CLIoldserver_ipARX = split(/ /,$CLIoldserver_ipARY[1]);
if (length($CLIoldserver_ipARX[0])>2)
{
$VARold_server_ip = $CLIoldserver_ipARX[0];
$VARold_server_ip =~ s/\/$| |\r|\n|\t//gi;
$CLIold_server_ip=1;
print " CLI defined old server IP: $VARold_server_ip\n";
}
}
if ($args =~ /--server_ip=/i) # CLI defined server IP address
{
@CLIserver_ipARY = split(/--server_ip=/,$args);
@CLIserver_ipARX = split(/ /,$CLIserver_ipARY[1]);
if (length($CLIserver_ipARX[0])>2)
{
$VARserver_ip = $CLIserver_ipARX[0];
$VARserver_ip =~ s/\/$| |\r|\n|\t//gi;
$CLIserver_ip=1;
print " CLI defined server IP: $VARserver_ip\n";
}
}
}
}
else
{
# print "no command line options set\n";
}
### end parsing run-time options ###
if (-e "$PATHconf")
{
print "Previous astGUIclient configuration file found at: $PATHconf\n";
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 =~ /^PATHDONEmonitor/) && ($CLIDONEmonitor < 1) )
{$PATHDONEmonitor = $line; $PATHDONEmonitor =~ 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_custom_user/) && ($CLIDB_custom_user < 1) )
{$VARDB_custom_user = $line; $VARDB_custom_user =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_custom_pass/) && ($CLIDB_custom_pass < 1) )
{$VARDB_custom_pass = $line; $VARDB_custom_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) )
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
if ( ($line =~ /^VARactive_keepalives/) && ($CLIactive_keepalives < 1) )
{$VARactive_keepalives = $line; $VARactive_keepalives =~ s/.*=//gi;}
if ( ($line =~ /^VARasterisk_version/) && ($CLIasterisk_version < 1) )
{$VARasterisk_version = $line; $VARasterisk_version =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_host/) && ($CLIFTP_host < 1) )
{$VARFTP_host = $line; $VARFTP_host =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_user/) && ($CLIFTP_user < 1) )
{$VARFTP_user = $line; $VARFTP_user =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_pass/) && ($CLIFTP_pass < 1) )
{$VARFTP_pass = $line; $VARFTP_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_port/) && ($CLIFTP_port < 1) )
{$VARFTP_port = $line; $VARFTP_port =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_dir/) && ($CLIFTP_dir < 1) )
{$VARFTP_dir = $line; $VARFTP_dir =~ s/.*=//gi;}
if ( ($line =~ /^VARHTTP_path/) && ($CLIHTTP_path < 1) )
{$VARHTTP_path = $line; $VARHTTP_path =~ s/.*=//gi;}
if ( ($line =~ /^VARREPORT_host/) && ($CLIREPORT_host < 1) )
{$VARREPORT_host = $line; $VARREPORT_host =~ s/.*=//gi;}
if ( ($line =~ /^VARREPORT_user/) && ($CLIREPORT_user < 1) )
{$VARREPORT_user = $line; $VARREPORT_user =~ s/.*=//gi;}
if ( ($line =~ /^VARREPORT_pass/) && ($CLIREPORT_pass < 1) )
{$VARREPORT_pass = $line; $VARREPORT_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARREPORT_port/) && ($CLIREPORT_port < 1) )
{$VARREPORT_port = $line; $VARREPORT_port =~ s/.*=//gi;}
if ( ($line =~ /^VARREPORT_dir/) && ($CLIREPORT_dir < 1) )
{$VARREPORT_dir = $line; $VARREPORT_dir =~ s/.*=//gi;}
if ( ($line =~ /^VARfastagi_log_min_servers/) && ($CLIVARfastagi_log_min_servers < 1) )
{$VARfastagi_log_min_servers = $line; $VARfastagi_log_min_servers =~ s/.*=//gi;}
if ( ($line =~ /^VARfastagi_log_max_servers/) && ($CLIVARfastagi_log_max_servers < 1) )
{$VARfastagi_log_max_servers = $line; $VARfastagi_log_max_servers =~ s/.*=//gi;}
if ( ($line =~ /^VARfastagi_log_min_spare_servers/) && ($CLIVARfastagi_log_min_spare_servers < 1) )
{$VARfastagi_log_min_spare_servers = $line; $VARfastagi_log_min_spare_servers =~ s/.*=//gi;}
if ( ($line =~ /^VARfastagi_log_max_spare_servers/) && ($CLIVARfastagi_log_max_spare_servers < 1) )
{$VARfastagi_log_max_spare_servers = $line; $VARfastagi_log_max_spare_servers =~ s/.*=//gi;}
if ( ($line =~ /^VARfastagi_log_max_requests/) && ($CLIVARfastagi_log_max_requests < 1) )
{$VARfastagi_log_max_requests = $line; $VARfastagi_log_max_requests =~ s/.*=//gi;}
if ( ($line =~ /^VARfastagi_log_checkfordead/) && ($CLIVARfastagi_log_checkfordead < 1) )
{$VARfastagi_log_checkfordead = $line; $VARfastagi_log_checkfordead =~ s/.*=//gi;}
if ( ($line =~ /^VARfastagi_log_checkforwait/) && ($CLIVARfastagi_log_checkforwait < 1) )
{$VARfastagi_log_checkforwait = $line; $VARfastagi_log_checkforwait =~ s/.*=//gi;}
if ($line =~ /^ExpectedDBSchema/)
{$ExpectedDBSchema = $line; $ExpectedDBSchema =~ s/.*=//gi;}
$i++;
}
}
if ($AUTO)
{
$manual='n';
if (length($VARserver_ip)<7)
{
@ip = `/sbin/ifconfig`;
$j=0;
while($#ip>=$j)
{
if ($ip[$j] =~ /inet addr/) {$VARserver_ip = $ip[$j]; $j=1000;}
$j++;
}
$VARserver_ip =~ s/.*addr:| Bcast.*|\r|\n|\t| //gi;
}
}
else
{
print("\nWould you like to use interactive mode (y/n): [y] ");
$manual = <STDIN>;
chomp($manual);
}
if ($manual =~ /n/i)
{
$manual=0;
}
else
{
$config_finished='NO';
while ($config_finished =~/NO/)
{
print "\nSTARTING SERVER IP ADDRESS CHANGE FOR VICIDIAL...\n";
##### BEGIN old_server_ip propmting and check #####
$continue='NO';
while ($continue =~/NO/)
{
print("\nOld server IP address or press enter for default: [$VARold_server_ip] ");
$PROMPTold_server_ip = <STDIN>;
chomp($PROMPTold_server_ip);
if (length($PROMPTold_server_ip)>6)
{
$PROMPTold_server_ip =~ s/ |\n|\r|\t|\/$//gi;
$VARold_server_ip=$PROMPTold_server_ip;
$continue='YES';
}
else
{
$continue='YES';
}
}
##### END old_server_ip propmting and check #####
##### BEGIN server_ip propmting and check #####
if (length($VARserver_ip)<7)
{
### get best guess of IP address from ifconfig output ###
# inet addr:10.10.11.17 Bcast:10.10.255.255 Mask:255.255.0.0
@ip = `/sbin/ifconfig`;
$j=0;
while($#ip>=$j)
{
if ($ip[$j] =~ /inet addr/) {$VARserver_ip = $ip[$j]; $j=1000;}
$j++;
}
$VARserver_ip =~ s/.*addr:| Bcast.*|\r|\n|\t| //gi;
}
$continue='NO';
while ($continue =~/NO/)
{
print("\nserver IP address or press enter for default: [$VARserver_ip] ");
$PROMPTserver_ip = <STDIN>;
chomp($PROMPTserver_ip);
if (length($PROMPTserver_ip)>6)
{
$PROMPTserver_ip =~ s/ |\n|\r|\t|\/$//gi;
$VARserver_ip=$PROMPTserver_ip;
$continue='YES';
}
else
{
$continue='YES';
}
}
##### END server_ip propmting and check #####
print "\n";
print " old server_ip: $VARold_server_ip\n";
print " new server_ip: $VARserver_ip\n";
print "\n";
print("Are these settings correct?(y/n): [y] ");
$PROMPTconfig = <STDIN>;
chomp($PROMPTconfig);
if ( (length($PROMPTconfig)<1) or ($PROMPTconfig =~ /y/i) )
{
$config_finished='YES';
}
}
}
print "Writing change to astguiclient.conf file: $PATHconf\n";
open(conf, ">$PATHconf") || die "can't open $PATHconf: $!\n";
print conf "# astguiclient.conf - configuration elements for the astguiclient package\n";
print conf "# this is the astguiclient configuration file \n";
print conf "# all comments will be lost if you run install.pl again\n";
print conf "\n";
print conf "# Paths used by astGUIclient\n";
print conf "PATHhome => $PATHhome\n";
print conf "PATHlogs => $PATHlogs\n";
print conf "PATHagi => $PATHagi\n";
print conf "PATHweb => $PATHweb\n";
print conf "PATHsounds => $PATHsounds\n";
print conf "PATHmonitor => $PATHmonitor\n";
print conf "PATHDONEmonitor => $PATHDONEmonitor\n";
print conf "\n";
print conf "# The IP address of this machine\n";
print conf "VARserver_ip => $VARserver_ip\n";
print conf "\n";
print conf "# Database connection information\n";
print conf "VARDB_server => $VARDB_server\n";
print conf "VARDB_database => $VARDB_database\n";
print conf "VARDB_user => $VARDB_user\n";
print conf "VARDB_pass => $VARDB_pass\n";
print conf "VARDB_custom_user => $VARDB_custom_user\n";
print conf "VARDB_custom_pass => $VARDB_custom_pass\n";
print conf "VARDB_port => $VARDB_port\n";
print conf "\n";
print conf "# Alpha-Numeric list of the astGUIclient processes to be kept running\n";
print conf "# (value should be listing of characters with no spaces: 123456)\n";
print conf "# X - NO KEEPALIVE PROCESSES (use only if you want none to be keepalive)\n";
print conf "# 1 - AST_update\n";
print conf "# 2 - AST_send_listen\n";
print conf "# 3 - AST_VDauto_dial\n";
print conf "# 4 - AST_VDremote_agents\n";
print conf "# 5 - AST_VDadapt (If multi-server system, this must only be on one server)\n";
print conf "# 6 - FastAGI_log\n";
print conf "# 7 - AST_VDauto_dial_FILL (only for multi-server, this must only be on one server)\n";
print conf "# 8 - ip_relay (used for blind agent monitoring)\n";
print conf "# 9 - Timeclock auto logout\n";
print conf "VARactive_keepalives => $VARactive_keepalives\n";
print conf "\n";
print conf "# Asterisk version VICIDIAL is installed for\n";
print conf "VARasterisk_version => $VARasterisk_version\n";
print conf "\n";
print conf "# FTP recording archive connection information\n";
print conf "VARFTP_host => $VARFTP_host\n";
print conf "VARFTP_user => $VARFTP_user\n";
print conf "VARFTP_pass => $VARFTP_pass\n";
print conf "VARFTP_port => $VARFTP_port\n";
print conf "VARFTP_dir => $VARFTP_dir\n";
print conf "VARHTTP_path => $VARHTTP_path\n";
print conf "\n";
print conf "# REPORT server connection information\n";
print conf "VARREPORT_host => $VARREPORT_host\n";
print conf "VARREPORT_user => $VARREPORT_user\n";
print conf "VARREPORT_pass => $VARREPORT_pass\n";
print conf "VARREPORT_port => $VARREPORT_port\n";
print conf "VARREPORT_dir => $VARREPORT_dir\n";
print conf "\n";
print conf "# Settings for FastAGI logging server\n";
print conf "VARfastagi_log_min_servers => $VARfastagi_log_min_servers\n";
print conf "VARfastagi_log_max_servers => $VARfastagi_log_max_servers\n";
print conf "VARfastagi_log_min_spare_servers => $VARfastagi_log_min_spare_servers\n";
print conf "VARfastagi_log_max_spare_servers => $VARfastagi_log_max_spare_servers\n";
print conf "VARfastagi_log_max_requests => $VARfastagi_log_max_requests\n";
print conf "VARfastagi_log_checkfordead => $VARfastagi_log_checkfordead\n";
print conf "VARfastagi_log_checkforwait => $VARfastagi_log_checkforwait\n";
print conf "\n";
print conf "# Expected DB Schema version for this install\n";
print conf "ExpectedDBSchema => $ExpectedDBSchema\n";
close(conf);
print "\nSTARTING DATABASE TABLES UPDATES PHASE...\n";
if (!$VARDB_port) {$VARDB_port='3306';}
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
print " Updating servers table...\n";
$stmtA = "UPDATE servers SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating phones table...\n";
$stmtA = "UPDATE phones SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating inbound_numbers table...\n";
$stmtA = "UPDATE inbound_numbers SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating server_updater table...\n";
$stmtA = "UPDATE server_updater SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating conferences table...\n";
$stmtA = "UPDATE conferences SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating vicidial_conferences table...\n";
$stmtA = "UPDATE vicidial_conferences SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating vicidial_stations table...\n";
$stmtA = "UPDATE vicidial_stations SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating vicidial_remote_agents table...\n";
$stmtA = "UPDATE vicidial_remote_agents SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating phone_favorites table...\n";
$stmtA = "UPDATE phone_favorites SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating vicidial_server_trunks table...\n";
$stmtA = "UPDATE vicidial_server_trunks SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating vicidial_server_carriers table...\n";
$stmtA = "UPDATE vicidial_server_carriers SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating vicidial_inbound_dids table...\n";
$stmtA = "UPDATE vicidial_inbound_dids SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Updating vicidial_process_triggers table...\n";
$stmtA = "UPDATE vicidial_process_triggers SET server_ip='$VARserver_ip' where server_ip='$VARold_server_ip';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
print " Setting servers to rebuild conf files...\n";
$stmtA="UPDATE servers SET rebuild_conf_files='Y' where generate_vicidial_conf='Y' and active_asterisk_server='Y';";
$affected_rows = $dbhA->do($stmtA);
if ($DB) {print " |$affected_rows|$stmtA|\n";}
$dbhA->disconnect();
### format the new server_ip dialstring for example to use with extensions.conf
$S='*';
if( $VARserver_ip =~ m/(\S+)\.(\S+)\.(\S+)\.(\S+)/ )
{
$a = leading_zero($1);
$b = leading_zero($2);
$c = leading_zero($3);
$d = leading_zero($4);
$VARremDIALstr = "$a$S$b$S$c$S$d";
}
print "\n";
print "SERVER IP ADDRESS CHANGE FOR VICIDIAL FINISHED!\n";
print "\n";
$secy = time(); $secz = ($secy - $secX); $minz = ($secz/60); # calculate script runtime so far
print "\n - process runtime ($secz sec) ($minz minutes)\n";
exit;
sub leading_zero($)
{
$_ = $_[0];
s/^(\d)$/0$1/;
s/^(\d\d)$/0$1/;
return $_;
} # End of the leading_zero() routine.
@@ -0,0 +1,505 @@
#!/usr/bin/perl
# ADMIN_www_languages.pl version 2.12
#
# This script is designed to traverse the vicidial and agc web directories and
# generate a list of phrases that are output from the QXZ PHP functions so that
# they can be inserted/updated in the database.
#
# NOTES: we used the following database query to set to UTF8:
# ALTER DATABASE asterisk CHARACTER SET utf8 COLLATE utf8_unicode_ci;
# you should check your table character sets:
# select TABLE_SCHEMA,TABLE_NAME,TABLE_TYPE,TABLE_COLLATION,CREATE_OPTIONS from information_schema.`TABLES`;
# and alter them if necessary:
# ALTER TABLE audio_store_details CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
#
# Copyright (C) 2015 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGES
# 141128-0024 - First build
# 141211-2123 - Added --wipe-www-phrases-table CLI option and insert_date field
# 151219-0756 - Added --chat-only option for chat_customer and --one-file-only option
#
$secX = time();
# constants
$SYSLOG=1; # log to a logfile
$DB=0; # Debug flag, set to 0 for no debug messages, lots of output
$US='_';
$MT[0]='';
$QXZlines=0;
$QXZvalues=0;
$QXZvaronly=0;
$QXZlengthonly=0;
$QXZplaceonly=0;
$secT = time();
$now_date_epoch = $secT;
($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";}
$file_date = "$year-$mon-$mday";
$now_date = "$year-$mon-$mday $hour:$min:$sec";
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "ADMIN_www_languages.pl - analyze php scripts for QXZ functions and contents\n";
print "\n";
print "options:\n";
print " [--help] = this help screen\n";
print " [--debug] = verbose debug messages\n";
print " [--debugX] = extra verbose debug messages\n";
print " [--agc-only] = only parse the agc directory\n";
print " [--chat-only] = only parse the chat_customer directory\n";
print " [--vicidial-only] = only parse the vicidial directory\n";
print " [--one-file-only=/path/from/root] = process one php file only\n";
print " [--QXZlines] = print full lines that include QXZ functions\n";
print " [--QXZvalues] = print only QXZ function values\n";
print " [--QXZvaronly] = print only QXZ function values with PHP variables in them\n";
print " [--QXZlengthonly] = print only QXZ function values that include a length spec\n";
print " [--QXZplaceonly] = print only QXZ function values with placeholder variables in them\n";
print " [--conffile=/path/from/root] = define astguiclient.conf config file to use\n";
print " [--wipe-www-phrases-table] = deletes all records in www_phrases database table\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i) # Debug flag
{$DB=1;}
if ($args =~ /--debugX/i) # Extra Debug flag
{$DBX=1;}
if ($args =~ /--agc-only/i) # agc flag
{$agc_only=1;}
if ($args =~ /--chat-only/i) # agc flag
{$chat_only=1;}
if ($args =~ /--vicidial-only/i) # vicidial flag
{$vicidial_only=1;}
if ($args =~ /--QXZlines/i) # QXZlines flag
{$QXZlines=1;}
if ($args =~ /--QXZvalues/i) # QXZvalues flag
{$QXZvalues=1;}
if ($args =~ /--QXZvaronly/i) # QXZvaronly flag
{$QXZvaronly=1;}
if ($args =~ /--QXZlengthonly/i) # QXZlengthonly flag
{$QXZlengthonly=1;}
if ($args =~ /--QXZplaceonly/i) # QXZplaceonly flag
{$QXZplaceonly=1;}
if ($args =~ /--wipe-www-phrases-table/i) # wipewwwphrasestable flag
{$wipewwwphrasestable=1;}
if ($args =~ /--one-file-only=/i) # CLI defined file path for one file only
{
@CLIonefileARY = split(/--one-file-only=/,$args);
@CLIonefileARX = split(/ /,$CLIonefileARY[1]);
if (length($CLIonefileARX[0])>2)
{
$PATHone = $CLIonefileARX[0];
$PATHone =~ s/\/$| |\r|\n|\t//gi;
print " CLI defined one-file-only path: $PATHone\n";
}
}
if ($args =~ /--conffile=/i) # CLI defined file path
{
@CLIconffileARY = split(/--conffile=/,$args);
@CLIconffileARX = split(/ /,$CLIconffileARY[1]);
if (length($CLIconffileARX[0])>2)
{
$PATHconf = $CLIconffileARX[0];
$PATHconf =~ s/\/$| |\r|\n|\t//gi;
print " CLI defined conffile path: $PATHconf\n";
}
}
}
}
else
{
print "no command line options set, exiting\n";
exit;
}
### end parsing run-time options ###
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 (!$VASLOGfile) {$VASLOGfile = "$PATHlogs/wwwlang.$year-$mon-$mday";}
if (!$VARDB_port) {$VARDB_port='3306';}
use DBI;
$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 count(*) FROM www_phrases;";
$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;
$phrase_count = $aryA[0];
}
$sthA->finish();
$event_string = "Existing phrases: $phrase_count";
if ($DB > 0) {print "$event_string\n";}
&event_logger;
if ($wipewwwphrasestable > 0)
{
$stmtA="DELETE FROM www_phrases;";
$affected_rows = $dbhA->do($stmtA);
$event_string = " $affected_rows|$stmtA|";
if ($DBX > 0) {print "$event_string\n";}
&event_logger;
}
$i=0;
$f=0;
if (length($PATHone) > 2)
{
$FILEparseDIR[$f] = "$PATHweb/temp/";
$FILEparseNAME[$f] = '';
$FILEparse[$f] = '';
if ( (length($PATHone) > 2) && (!-d "$PATHone") )
{
$FILEparse[$f] = "$PATHone";
@oneARY = split("/", $PATHone);
$FILEparseNAME[$f] = $oneARY[-1];
$event_string = "$PATHone $FILEparseNAME[$f]";
if ($DBX > 0) {print "$event_string\n";}
&event_logger;
$f++;
}
$i++;
}
else
{
$i=0;
if ( ($vicidial_only < 1) && ($chat_only < 1) )
{
opendir(FILE, "$PATHweb/agc/");
@agcFILES = readdir(FILE);
### Loop through files first to gather list
foreach(@agcFILES)
{
$FILEparseDIR[$f] = "$PATHweb/agc/";
$FILEparseNAME[$f] = '';
$FILEparse[$f] = '';
if ( (length($agcFILES[$i]) > 2) && (!-d "$PATHweb/agc/$agcFILES[$i]") )
{
$FILEparse[$f] = "$PATHweb/agc/$agcFILES[$i]";
$FILEparseNAME[$f] = $agcFILES[$i];
$event_string = "$PATHweb/agc/$agcFILES[$i] $FILEparseNAME[$f]";
if ($DBX > 0) {print "$event_string\n";}
&event_logger;
$f++;
}
$i++;
}
}
$i=0;
if ( ($agc_only < 1) && ($chat_only < 1) )
{
opendir(FILE, "$PATHweb/vicidial/");
@vicidialFILES = readdir(FILE);
### Loop through files first to gather list
foreach(@vicidialFILES)
{
$FILEparseDIR[$f] = "$PATHweb/vicidial/";
$FILEparseNAME[$f] = '';
$FILEparse[$f] = '';
if ( (length($vicidialFILES[$i]) > 2) && (!-d "$PATHweb/vicidial/$vicidialFILES[$i]") )
{
$FILEparse[$f] = "$PATHweb/vicidial/$vicidialFILES[$i]";
$FILEparseNAME[$f] = $vicidialFILES[$i];
$event_string = "$PATHweb/vicidial/$vicidialFILES[$i] $FILEparseNAME[$f]";
if ($DBX > 0) {print "$event_string\n";}
&event_logger;
$f++;
}
$i++;
}
}
$i=0;
if ( ($vicidial_only < 1) && ($agc_only < 1) )
{
opendir(FILE, "$PATHweb/chat_customer/");
@chat_customerFILES = readdir(FILE);
### Loop through files first to gather list
foreach(@chat_customerFILES)
{
$FILEparseDIR[$f] = "$PATHweb/chat_customer/";
$FILEparseNAME[$f] = '';
$FILEparse[$f] = '';
if ( (length($chat_customerFILES[$i]) > 2) && (!-d "$PATHweb/chat_customer/$chat_customerFILES[$i]") )
{
$FILEparse[$f] = "$PATHweb/chat_customer/$chat_customerFILES[$i]";
$FILEparseNAME[$f] = $chat_customerFILES[$i];
$event_string = "$PATHweb/chat_customer/$chat_customerFILES[$i] $FILEparseNAME[$f]";
if ($DBX > 0) {print "$event_string\n";}
&event_logger;
$f++;
}
$i++;
}
}
}
$event_string = "Files: $i $f";
if ($DB > 0) {print "$event_string\n";}
&event_logger;
$QXZlinecount=0;
$QXZcount=0;
$QXZcount_length=0;
$QXZcount_var=0;
$QXZcount_place=0;
$QXZcount_var_ct=0;
$QXZcount_place_ct=0;
$QXZinserts=0;
$QXZdups=0;
$f=0;
foreach(@FILEparse)
{
if (-e "$FILEparse[$f]")
{
$event_string = "file found at: $FILEparse[$f] $FILEparseNAME[$f]\n";
if ($DB > 0) {print "$event_string\n";}
&event_logger;
open(conf, "$FILEparse[$f]") || die "can't open $FILEparse[$f]: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/\n|\r|\t//gi;
if ( ($line =~ /\_QXZ\(/) && ($line !~ /function \_QXZ/) )
{
$QXZlinecount++;
$QXZ_in_line = () = $line =~ /\_QXZ\(/g;
$QXZcount = ($QXZcount + $QXZ_in_line);
@eachQXZ = split(/\_QXZ\(/,$line);
$each_ct=0;
while ($each_ct <= $#eachQXZ)
{
if ($each_ct > 0)
{
@eachQXZvalue = split(/\)/,$eachQXZ[$each_ct]);
if ( ($eachQXZvalue[0] =~ /\(/) && (length($eachQXZvalue[1])>0) )
{
$temp_QXZval_str = $eachQXZvalue[0].")".$eachQXZvalue[1];
if ( ($eachQXZvalue[1] =~ /\(/) && (length($eachQXZvalue[2])>0) )
{
$temp_QXZval_str .= ")".$eachQXZvalue[2];
if ( ($eachQXZvalue[2] =~ /\(/) && (length($eachQXZvalue[3])>0) )
{
$temp_QXZval_str .= ")".$eachQXZvalue[3];
}
}
}
else
{
$temp_QXZval_str = $eachQXZvalue[0];
}
if ( ($QXZvalues > 0) && ($QXZvaronly < 1) && ($QXZlengthonly < 1) && ($QXZplaceonly < 1) )
{
$event_string = "$temp_QXZval_str";
print "$event_string\n";
&event_logger;
}
if ($temp_QXZval_str =~ /,\d|, \d/)
{
$QXZcount_length++;
if ($QXZlengthonly > 0)
{
$event_string = "$temp_QXZval_str";
print "$event_string\n";
&event_logger;
}
}
if ($temp_QXZval_str =~ /\$/)
{
$QXZcount_var++;
$var_ct_in_line = () = $temp_QXZval_str =~ /\$/g;
$QXZcount_var_ct = ($QXZcount_var_ct + $var_ct_in_line);
if ($QXZvaronly > 0)
{
$event_string = "$temp_QXZval_str";
print "$event_string\n";
&event_logger;
}
}
if ($temp_QXZval_str =~ /%\ds/)
{
$QXZcount_place++;
$place_ct_in_line = () = $temp_QXZval_str =~ /\$/g;
$QXZcount_place_ct = ($QXZcount_place_ct + $place_ct_in_line);
if ($QXZplaceonly > 0)
{
$event_string = "$temp_QXZval_str";
print "$event_string\n";
&event_logger;
}
}
$temp_QXZval_strSQL = $temp_QXZval_str;
$temp_QXZval_strSQL =~ s/\"$|^\"|^\'|\'$//gi;
$temp_QXZval_strSQL =~ s/\",.*|\',.*//gi;
$phrase_match=0;
$stmtA = "SELECT count(*) FROM www_phrases where phrase_text='$temp_QXZval_strSQL';";
$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;
$phrase_match = $aryA[0];
}
$sthA->finish();
if ($phrase_match < 1)
{
$stmtA="INSERT INTO www_phrases SET phrase_text='$temp_QXZval_strSQL',php_filename='$FILEparseNAME[$f]',php_directory='$FILEparseDIR[$f]',source='www_languages_script',insert_date=NOW();";
$affected_rows = $dbhA->do($stmtA);
$QXZinserts++;
$event_string = " $affected_rows|$stmtA|";
if ($DBX > 0) {print "$event_string\n";}
&event_logger;
}
else
{$QXZdups++;}
}
$each_ct++;
}
if ($QXZlines > 0)
{
$event_string = "$i|$QXZlinecount|$QXZ_in_line|$line";
print "$event_string\n";
&event_logger;
}
}
$i++;
}
}
else
{
$event_string = "File does not exist: $FILEparse[$f] $FILEparseNAME[$f]";
if ($DB > 0) {print "$event_string\n";}
&event_logger;
}
$f++;
}
$event_string = "\n";
$event_string .= "FILE PARSING FINISHED!\n";
$event_string .= "Files parsed: $f\n";
$event_string .= "ConfFile: $PATHconf\n";
$event_string .= "QXZ line count: $QXZlinecount\n";
$event_string .= "QXZ count: $QXZcount\n";
$event_string .= "QXZ with length set: $QXZcount_length\n";
$event_string .= "QXZ with PHP vars: $QXZcount_var\n";
$event_string .= "QXZ with var place set: $QXZcount_place\n";
$event_string .= "QXZ with PHP vars inst: $QXZcount_var_ct\n";
$event_string .= "QXZ with var place inst: $QXZcount_place_ct\n";
$event_string .= "\n";
$event_string .= "QXZ DB inserts: $QXZinserts\n";
$event_string .= "QXZ DB dups: $QXZdups\n";
$event_string .= "\n";
if ($DB > 0) {print "$event_string\n";}
&event_logger;
$secy = time(); $secz = ($secy - $secX); $minz = ($secz/60); # calculate script runtime so far
$event_string = "\n - process runtime ($secz sec) ($minz minutes)";
if ($DB > 0) {print "$event_string\n";}
&event_logger;
exit;
sub event_logger
{
if ($SYSLOG)
{
### open the log file for writing ###
open(Lout, ">>$VASLOGfile")
|| die "Can't open $VASLOGfile: $!\n";
print Lout "$now_date|$event_string|\n";
close(Lout);
}
$event_string='';
}
@@ -0,0 +1,164 @@
#!/usr/bin/perl
#
# AST_CRON_GSM_SALE_recordings.pl version 2.0.5
#
# IMPORTANT!!! used to delete recordings!!!
#
# runs every day, goes through all recordings to compress only the SALE recordings
# and place them in a special directory
#
# put an entry into the cron of of your asterisk archive to run this script
# every day or however often you desire
#
# This program assumes that recordings are saved as .wav
# should be easy to change this code if you use .gsm instead
#
# Copyright (C) 2008 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
#
# 1112-1245 - first build
#
$save_statuses = '|SALE|UPSALE|UPSELL|XFER|A1|A2|A3|A4|';
$save_statusesSQL = "'SALE','UPSALE','UPSELL','XFER','A1','A2','A3','A4'";
$suffix = '-all.wav';
$local_DIR = '/home2/cron/RECORDINGS';
$GSM_DIR = '/home/cron/GSM';
$use_date_DIRs = 1;
$secX = time();
$TDtarget = ($secX - 36000); # 10 hours ago
($Tsec,$Tmin,$Thour,$Tmday,$Tmon,$Tyear,$Twday,$Tyday,$Tisdst) = localtime($TDtarget);
$Tyear = ($Tyear + 1900);
$Tmon++;
if ($Tmon < 10) {$Tmon = "0$Tmon";}
if ($Tmday < 10) {$Tmday = "0$Tmday";}
if ($Thour < 10) {$Thour = "0$Thour";}
if ($Tmin < 10) {$Tmin = "0$Tmin";}
if ($Tsec < 10) {$Tsec = "0$Tsec";}
$BEGINdate = "$Tyear-$Tmon-$Tmday 00:00:00";
$ENDdate = "$Tyear-$Tmon-$Tmday 23:59:59";
$BEGINdate = "2007-08-01 00:00:00";
$ENDdate = "2007-08-31 23:59:59";
$soxbin = '';
if ( -e ('/usr/bin/sox')) {$soxbin = '/usr/bin/sox';}
else
{
if ( -e ('/usr/local/bin/sox')) {$soxbin = '/usr/local/bin/sox';}
else
{
print "Can't find sox binary! Exiting...\n";
exit;
}
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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++;
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$VARDB_port) {$VARDB_port='3306';}
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### directory where in/out recordings are saved to by Asterisk
$dir1 = "$PATHmonitor";
##### Get the lead_ids of all recordings that are not DELETED or NULL #####
$stmtA = "SELECT recording_log.lead_id,recording_id,start_time,filename,location,status FROM recording_log,vicidial_log where start_time > '$BEGINdate' and start_time < '$ENDdate' and location IS NOT NULL and location NOT IN('','NOT_FOUND','NOT_FOUND_2','DELETED') and vicidial_log.status IN($save_statusesSQL) and call_date > '$BEGINdate' and call_date < '$ENDdate' and recording_log.lead_id=vicidial_log.lead_id and recording_log.user=vicidial_log.user order by recording_id LIMIT 500000;";
print "$stmtA\n";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$i=0;
while ($sthArows > $i)
{
@aryA = $sthA->fetchrow_array;
$lead_ids[$i] = "$aryA[0]";
$recording_ids[$i] = "$aryA[1]";
$start_times[$i] = "$aryA[2]";
$filenames[$i] = "$aryA[3]";
$locations[$i] = "$aryA[4]";
$status[$i] = "$aryA[5]";
$i++;
}
$sthA->finish();
##### Go through the list of sales recordings and compress all of them #####
$i=0;
$WAV='-all.wav';
$GSM='-all.gsm';
foreach(@lead_ids)
{
if ($use_date_DIRs)
{
$date_DIR = $start_times[$i];
$date_DIR =~ s/ .*//gi;
$date_DIR .= "/";
}
else {$date_DIR=''}
if ( -e ("$GSM_DIR/$date_DIR")) {$nothing=1;}
else {mkdir("$GSM_DIR/$date_DIR");}
if ( -e ("$GSM_DIR/$date_DIR$filenames[$i]$GSM"))
{print "DUPLICATE: $GSM_DIR/$date_DIR$filenames[$i]$GSM EXISTS\n";}
else
{
`$soxbin "$local_DIR/$date_DIR$filenames[$i]$WAV" "$GSM_DIR/$date_DIR$filenames[$i]$GSM"`;
print "$soxbin \"$local_DIR/$date_DIR$filenames[$i]$WAV\" \"$GSM_DIR/$date_DIR$filenames[$i]$GSM\"\n";
}
$i++;
}
print "TOTAL COMPRESSED: $i\n";
if ($v) {print "DONE... EXITING\n\n";}
$dbhA->disconnect();
exit;
@@ -0,0 +1,480 @@
#!/usr/bin/perl
#
# AST_CRON_audio_1_move_VDonly.pl
#
# This is a STEP-1 program in the audio archival process
#
# IMPORTANT!!! ONLY TO BE USED WHEN ONLY VICIDIAL RECORDINGS ARE ON THE SYSTEM!
#
# runs every 3 minutes and copies the -in recordings in the monitor to the DONE
# directory for further processing. Very important for RAM-drive usage
#
# put an entry into the cron of of your asterisk machine to run this script
# every 3 minutes or however often you desire
#
# ### recording mixing/compressing/ftping scripts
##0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_mix.pl
# 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_VDonly.pl
# 1,4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58 * * * * /usr/share/astguiclient/AST_CRON_audio_2_compress.pl --GSM
# 2,5,8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59 * * * * /usr/share/astguiclient/AST_CRON_audio_3_ftp.pl --GSM
#
# make sure that the following directories exist:
# /var/spool/asterisk/monitor # default Asterisk recording directory
# /var/spool/asterisk/monitorDONE # where the moved -in files are put
#
# This program assumes that recordings are saved by Asterisk as .wav
# should be easy to change this code if you use .gsm instead
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
#
# 80302-1958 - First Build
# 80731-2253 - Changed size comparisons for more efficiency
# 130805-1450 - Added check for length and gather length of recording for database record
# 160523-0654 - Added --HTTPS option to use https instead of http in local location
# 160731-2103 - Added --POST options to change filename with variable lookups
#
$HTTPS=0;
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [--help] = this screen\n";
print " [--quiet] = suppress output, if possible\n";
print " [--debug] = debug\n";
print " [--debugX] = super debug\n";
print " [--test] = test\n";
print " [--HTTPS] = use https instead of http in local location\n";
print " [--POST] = post call variable filename replacement, MUST define STATUS and CAMP below\n";
print " [--STATUS-POST=X] = only run post call variable filename replacement on specific status calls\n";
print " If multiple statuses, use --- delimiting, i.e.: SALE---PRESALE\n";
print " For status wildcards, use * flag, i.e.: S* to match SALE and SQUAL\n";
print " For all statuses, use ----ALL----\n";
print " \n";
print " [--CAMP-POST=X] = only run post call variable filename replacement on specific campaigns or ingroups\n";
print " If multiple campaigns or ingroups, use --- delimiting, i.e.: TESTCAMP---TEST_IN2\n";
print " For all calls, use ----ALL----\n";
print " [--CLEAR-POST-NO-MATCH] = clear POST filename variables if no match is found\n";
print "\n";
exit;
}
else
{
if ($args =~ /--quiet/)
{
$q=1;
}
if ($args =~ /--debug/i)
{
$DB=1;
print "\n----- DEBUG -----\n\n";
}
if ($args =~ /--debugX/i)
{
$DBX=1;
print "\n----- SUPER DEBUG -----\n\n";
}
if ($args =~ /--test/)
{
$T=1; $TEST=1;
if ($q < 1) {print "\n-----TESTING -----\n\n";}
}
if ($args =~ /--HTTPS/i)
{
$HTTPS=1;
if ($DB) {print "HTTPS location option enabled\n";}
}
if ($args =~ /--POST/i)
{
$POST=1;
if ($DB) {print "POST post call variable filename replacement\n";}
if ($args =~ /--STATUS-POST=/i)
{
@data_in = split(/--STATUS-POST=/,$args);
$status_post = $data_in[1];
$status_post =~ s/ .*//gi;
if ($q < 1) {print "\n----- STATUS POST SET: $status_post -----\n\n";}
}
else
{
$POST=0;
if ($q < 1) {print "\n----- POST disabled, no status set -----\n\n";}
}
if ($args =~ /--CAMP-POST=/i)
{
@data_in = split(/--CAMP-POST=/,$args);
$camp_post = $data_in[1];
$camp_post =~ s/ .*//gi;
if ($q < 1) {print "\n----- CAMP POST SET: $camp_post -----\n\n";}
}
else
{
$POST=0;
if ($q < 1) {print "\n----- POST disabled, no campaigns set -----\n\n";}
}
}
if ($args =~ /--CLEAR-POST-NO-MATCH/i)
{
$CLEAR_POST=1;
if ($DB) {print "--- CLEAR-POST-NO-MATCH ENABLED ---\n";}
}
}
if ( ($POST > 0) && ( (length($camp_post) < 1) || (length($status_post) < 1) ) )
{
$POST=0;
if ($q < 1) {print "\n----- POST disabled, status or campaign invalid: |$camp_post|$status_post| -----\n\n";}
}
}
else
{
#print "no command line options set\n";
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 =~ /^PATHDONEmonitor/) && ($CLIDONEmonitor < 1) )
{$PATHDONEmonitor = $line; $PATHDONEmonitor =~ 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;}
if ( ($line =~ /^VARFTP_host/) && ($CLIFTP_host < 1) )
{$VARFTP_host = $line; $VARFTP_host =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_user/) && ($CLIFTP_user < 1) )
{$VARFTP_user = $line; $VARFTP_user =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_pass/) && ($CLIFTP_pass < 1) )
{$VARFTP_pass = $line; $VARFTP_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_port/) && ($CLIFTP_port < 1) )
{$VARFTP_port = $line; $VARFTP_port =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_dir/) && ($CLIFTP_dir < 1) )
{$VARFTP_dir = $line; $VARFTP_dir =~ s/.*=//gi;}
if ( ($line =~ /^VARHTTP_path/) && ($CLIHTTP_path < 1) )
{$VARHTTP_path = $line; $VARHTTP_path =~ s/.*=//gi;}
$i++;
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$VARDB_port) {$VARDB_port='3306';}
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### find soxi to gather the length info if needed
$soxibin = '';
if ( -e ('/usr/bin/soxi')) {$soxibin = '/usr/bin/soxi';}
else
{
if ( -e ('/usr/local/bin/soxi')) {$soxibin = '/usr/local/bin/soxi';}
else
{
if ( -e ('/usr/sbin/soxi')) {$soxibin = '/usr/sbin/soxi';}
else
{
if ($DB) {print "Can't find soxi binary! No length calculations will be available...\n";}
}
}
}
### directory where in/out recordings are saved to by Asterisk
$dir1 = "$PATHmonitor";
$dir2 = "$PATHDONEmonitor";
opendir(FILE, "$dir1/");
@FILES = readdir(FILE);
### Loop through files first to gather filesizes
$i=0;
foreach(@FILES)
{
$FILEsize1[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir1/$FILES[$i]") )
{
$FILEsize1[$i] = (-s "$dir1/$FILES[$i]");
if ($DBX) {print "$FILES[$i] $FILEsize1[$i]\n";}
}
$i++;
}
sleep(5);
### Loop through files a second time to gather filesizes again 5 seconds later
$i=0;
foreach(@FILES)
{
$FILEsize2[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir1/$FILES[$i]") )
{
$FILEsize2[$i] = (-s "$dir1/$FILES[$i]");
if ($DBX) {print "$FILES[$i] $FILEsize2[$i]\n\n";}
if ( ($FILES[$i] !~ /out\.wav|out\.gsm|lost\+found/i) && ($FILEsize1[$i] eq $FILEsize2[$i]) && (length($FILES[$i]) > 4))
{
$INfile = $FILES[$i];
$OUTfile = $FILES[$i];
$OUTfile =~ s/-in\.wav/-out.wav/gi;
$OUTfile =~ s/-in\.gsm/-out.gsm/gi;
$ALLfile = $FILES[$i];
$ALLfile =~ s/-in\.wav/-all.wav/gi;
$ALLfile =~ s/-in\.gsm/-all.gsm/gi;
$SQLFILE = $FILES[$i];
$SQLFILE =~ s/-in\.wav|-in\.gsm//gi;
$filenameSQL='';
$length_in_sec=0;
$stmtA = "SELECT recording_id,length_in_sec,lead_id,vicidial_id from recording_log where filename='$SQLFILE' order by recording_id desc LIMIT 1;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$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;
$recording_id = $aryA[0];
$length_in_sec = $aryA[1];
$lead_id = $aryA[2];
$vicidial_id = $aryA[3];
}
$sthA->finish();
if ($DB) {print "|$recording_id|$length_in_sec|$INfile| |$ALLfile|\n";}
if (!$T)
{
`mv -f "$dir1/$INfile" "$dir2/$ALLfile"`;
`rm -f "$dir1/$OUTfile"`;
}
else
{
`cp -f "$dir1/$INfile" "$dir2/$ALLfile"`;
}
$lengthSQL='';
if ( ( ($length_in_sec < 1) || ($length_in_sec =~ /^NULL$/i) || (length($length_in_sec)<1) ) && (length($soxibin) > 3) )
{
@soxi_output = `$soxibin -D $dir2/$ALLfile`;
$soxi_sec = $soxi_output[0];
$soxi_sec =~ s/\..*|\n|\r| //gi;
$soxi_min = ($soxi_sec / 60);
$soxi_min = sprintf("%.2f", $soxi_min);
$lengthSQL = ",length_in_sec='$soxi_sec',length_in_min='$soxi_min'";
}
##### BEGIN post call variable replacement #####
if ($POST > 0)
{
if ($ALLfile =~ /POSTVLC|POSTSP|POSTADDR3|POSTSTATUS/)
{
$origALLfile = $ALLfile;
$origSQLFILE = $SQLFILE;
$vendor_lead_code=''; $security_phrase=''; $address3=''; $status='';
$status_ALL=0;
$camp_ALL=0;
$camp_status_selected=0;
if ($status_post =~ /----ALL----/)
{
$status_ALL++;
if($DBX){print "All Statuses: |$status_post|$status_ALL|\n";}
}
if ($camp_post =~ /----ALL----/)
{
$camp_ALL++;
if($DBX){print "All Campaigs and Ingroups: |$camp_post|$camp_ALL|\n";}
}
if ( ($camp_ALL < 1) || ($status_ALL < 1) )
{
$camp_postSQL='';
if ($camp_ALL < 1)
{
$camp_postSQL = $camp_post;
$camp_postSQL =~ s/---/','/gi;
$camp_postSQL = "and campaign_id IN('$camp_postSQL')";
}
if ($vicidial_id =~ /\./)
{
$log_lookupSQL = "SELECT status from vicidial_log where uniqueid='$vicidial_id' and lead_id='$lead_id' $camp_postSQL;";
}
else
{
$log_lookupSQL = "SELECT status from vicidial_closer_log where closecallid='$vicidial_id' and lead_id='$lead_id' $camp_postSQL;";
}
if($DBX){print STDERR "\n|$log_lookupSQL|\n";}
$sthA = $dbhA->prepare($log_lookupSQL) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $log_lookupSQL ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$lead_status = $aryA[0];
if ($status_ALL > 0)
{$camp_status_selected++;}
else
{
@status_vars = split(/---/,$status_post);
$fc=0;
foreach(@status_vars)
{
$status_temp = $status_vars[$fc];
if ($status_vars[$fc] =~ /\*/)
{
$status_temp =~ s/\*/.*/gi;
if ( ($lead_status =~ /^$status_temp/) && ($status_vars[$fc] =~ /\*$/) )
{$camp_status_selected++;}
if ( ($lead_status =~ /$status_temp$/) && ($status_vars[$fc] =~ /^\*/) )
{$camp_status_selected++;}
}
else
{
if ($lead_status =~ /^$status_temp$/)
{$camp_status_selected++;}
}
if ($DBX) {print " POST processing DEBUG: $fc|$status_temp|$lead_status|$lead_id|$vicidial_id|$ALLfile|\n";}
$fc++;
}
}
if ($DB) {print " POST processing SELECT: |$camp_status_selected|$sthArows|$camp_postSQL|$camp_ALL|$status_post|$status_ALL|$ALLfile|\n";}
}
else
{if ($DB) {print " POST processing ERROR: lead not found: |$lead_id|$ALLfile|\n";} }
$sthA->finish();
}
if ( ( ($camp_ALL > 0) && ($status_ALL > 0) ) || ($camp_status_selected > 0) )
{
$stmtA = "SELECT vendor_lead_code,security_phrase,address3,status from vicidial_list where lead_id='$lead_id' LIMIT 1;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$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;
$vendor_lead_code = $aryA[0];
$security_phrase = $aryA[1];
$address3 = $aryA[2];
$status = $aryA[3];
$vendor_lead_code =~ s/[^a-zA-Z0-9_-]//gi;
$security_phrase =~ s/[^a-zA-Z0-9_-]//gi;
$address3 =~ s/[^a-zA-Z0-9_-]//gi;
$status =~ s/[^a-zA-Z0-9_-]//gi;
}
else
{if ($DB) {print " POST processing ERROR: lead not found: |$lead_id|$ALLfile|\n";} }
$sthA->finish();
$ALLfile =~ s/POSTVLC/$vendor_lead_code/gi;
$ALLfile =~ s/POSTSP/$security_phrase/gi;
$ALLfile =~ s/POSTADDR3/$address3/gi;
$ALLfile =~ s/POSTSTATUS/$status/gi;
$SQLFILE =~ s/POSTVLC/$vendor_lead_code/gi;
$SQLFILE =~ s/POSTSP/$security_phrase/gi;
$SQLFILE =~ s/POSTADDR3/$address3/gi;
$SQLFILE =~ s/POSTSTATUS/$status/gi;
$filenameSQL = ",filename='$SQLFILE'";
`mv -f "$dir2/$origALLfile" "$dir2/$ALLfile"`;
if ($DB) {print " POST processing COMPLETE: old: |$origALLfile| new: |$ALLfile|\n";}
}
else
{
if ($DB) {print " POST processing SKIPPED: |$camp_ALL|$status_ALL|$camp_status_selected|$lead_id|$vicidial_id|$ALLfile|\n";}
if ($CLEAR_POST > 0)
{
$ALLfile =~ s/POSTVLC//gi;
$ALLfile =~ s/POSTSP//gi;
$ALLfile =~ s/POSTADDR3//gi;
$ALLfile =~ s/POSTSTATUS//gi;
$SQLFILE =~ s/POSTVLC//gi;
$SQLFILE =~ s/POSTSP//gi;
$SQLFILE =~ s/POSTADDR3//gi;
$SQLFILE =~ s/POSTSTATUS//gi;
$filenameSQL = ",filename='$SQLFILE'";
`mv -f "$dir2/$origALLfile" "$dir2/$ALLfile"`;
if ($DB) {print " CLEAR POST COMPLETE: old: |$origALLfile| new: |$ALLfile|\n";}
}
}
}
else
{if ($DB) {print " POST processing ERROR: No variables found: |$ALLfile|\n";} }
}
##### END post call variable replacement #####
$HTTP='http';
if ($HTTPS > 0) {$HTTP='https';}
$stmtA = "UPDATE recording_log set location='$HTTP://$server_ip/RECORDINGS/$ALLfile' $filenameSQL $lengthSQL where recording_id='$recording_id';";
if($DBX){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
### sleep for twenty hundredths of a second to not flood the server with disk activity
usleep(1*200*1000);
}
}
$i++;
}
if ($DB) {print "DONE... EXITING\n\n";}
$dbhA->disconnect();
exit;
@@ -0,0 +1,314 @@
#!/usr/bin/perl
#
# AST_CRON_audio_1_move_mix.pl
#
# This is a STEP-1 program in the audio archival process
#
# runs every 3 minutes and copies and mixes the -in and -out recordings in the
# monitor to the DONE directory for further processing. Very important for
# RAM-drive usage
#
# put an entry into the cron of of your asterisk machine to run this script
# every 3 minutes or however often you desire
#
# ### recording mixing/compressing/ftping scripts
# 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_mix.pl --MIX
##0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_VDonly.pl
# 1,4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58 * * * * /usr/share/astguiclient/AST_CRON_audio_2_compress.pl --GSM
# 2,5,8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59 * * * * /usr/share/astguiclient/AST_CRON_audio_3_ftp.pl --GSM
#
# make sure that the following directories exist:
# /var/spool/asterisk/monitor # default Asterisk recording directory
# /var/spool/asterisk/monitorDONE # where the mixed -all files are put
#
# This program assumes that recordings are saved by Asterisk as .wav
# should be easy to change this code if you use .gsm instead
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
#
# 80302-1958 - First Build
# 80731-2253 - Changed size comparisons for more efficiency
# 91105-1353 - Added --MIX option to only check the /var/spool/asterisk/monitor/MIX directory
# 130805-1450 - Added check for length and gather length of recording for database record
# 160501-1001 - Added --SPHINX options to check for SPHINX audio files
# 160523-0650 - Added --HTTPS option to use https instead of http in local location
#
$MIX=0;
$SPHINX=0;
$HTTPS=0;
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [--debug] = debug\n";
print " [--debugX] = super debug\n";
print " [-t] = test\n";
print " [--MIX] = mix audio files in MIX directory\n";
print " [--SPHINX] = mix audio files in SPHINX/RAW directory\n";
print " [--HTTPS] = use https instead of http in local location\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1;
print "\n----- DEBUG -----\n\n";
}
if ($args =~ /--debugX/i)
{
$DBX=1;
print "\n----- SUPER DEBUG -----\n\n";
}
if ($args =~ /-t/i)
{
$T=1; $TEST=1;
print "\n-----TESTING -----\n\n";
}
if ($args =~ /--MIX/i)
{
$MIX=1;
if ($DB) {print "MIX directory audio processing only\n";}
}
if ($args =~ /--SPHINX/i)
{
$SPHINX=1;
if ($DB) {print "SPHINX directory audio processing only\n";}
}
if ($args =~ /--HTTPS/i)
{
$HTTPS=1;
if ($DB) {print "HTTPS location option enabled\n";}
}
}
}
else
{
#print "no command line options set\n";
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 =~ /^PATHDONEmonitor/) && ($CLIDONEmonitor < 1) )
{$PATHDONEmonitor = $line; $PATHDONEmonitor =~ 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;}
if ( ($line =~ /^VARFTP_host/) && ($CLIFTP_host < 1) )
{$VARFTP_host = $line; $VARFTP_host =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_user/) && ($CLIFTP_user < 1) )
{$VARFTP_user = $line; $VARFTP_user =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_pass/) && ($CLIFTP_pass < 1) )
{$VARFTP_pass = $line; $VARFTP_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_port/) && ($CLIFTP_port < 1) )
{$VARFTP_port = $line; $VARFTP_port =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_dir/) && ($CLIFTP_dir < 1) )
{$VARFTP_dir = $line; $VARFTP_dir =~ s/.*=//gi;}
if ( ($line =~ /^VARHTTP_path/) && ($CLIHTTP_path < 1) )
{$VARHTTP_path = $line; $VARHTTP_path =~ s/.*=//gi;}
$i++;
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$VARDB_port) {$VARDB_port='3306';}
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### find soxmix or sox to do the mixing
$soxmixbin = '';
if ( -e ('/usr/bin/soxmix')) {$soxmixbin = '/usr/bin/soxmix';}
else
{
if ( -e ('/usr/local/bin/soxmix')) {$soxmixbin = '/usr/local/bin/soxmix';}
else
{
if ($DB) {print "Can't find soxmix binary! Trying sox...\n";}
if ( -e ('/usr/bin/sox')) {$soxmixbin = '/usr/bin/sox -m';}
else
{
if ( -e ('/usr/local/bin/sox')) {$soxmixbin = '/usr/local/bin/sox -m';}
else
{
print "Can't find sox binary! Exiting...\n";
exit;
}
}
}
}
### find soxi to gather the length info if needed
$soxibin = '';
if ( -e ('/usr/bin/soxi')) {$soxibin = '/usr/bin/soxi';}
else
{
if ( -e ('/usr/local/bin/soxi')) {$soxibin = '/usr/local/bin/soxi';}
else
{
if ( -e ('/usr/sbin/soxi')) {$soxibin = '/usr/sbin/soxi';}
else
{
if ($DB) {print "Can't find soxi binary! No length calculations will be available...\n";}
}
}
}
### directory where in/out recordings are saved to by Asterisk
$dir1 = "$PATHmonitor";
$dir2 = "$PATHDONEmonitor";
if ($MIX > 0)
{$dir1 = "$PATHmonitor/MIX";}
if ($SPHINX > 0)
{
$dir1 = "$PATHmonitor/SPHINX/RAW";
$dir2 = "$PATHDONEmonitor/SPHINX";
}
opendir(FILE, "$dir1/");
@FILES = readdir(FILE);
### Loop through files first to gather filesizes
$i=0;
foreach(@FILES)
{
$FILEsize1[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir1/$FILES[$i]") )
{
$FILEsize1[$i] = (-s "$dir1/$FILES[$i]");
if ($DBX) {print "$FILES[$i] $FILEsize1[$i]\n";}
}
$i++;
}
sleep(5);
### Loop through files a second time to gather filesizes again 5 seconds later
$i=0;
foreach(@FILES)
{
$FILEsize2[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir1/$FILES[$i]") )
{
$FILEsize2[$i] = (-s "$dir1/$FILES[$i]");
if ($DBX) {print "$FILES[$i] $FILEsize2[$i]\n\n";}
if ( ($FILES[$i] !~ /out\.wav|out\.gsm|lost\+found/i) && ($FILEsize1[$i] eq $FILEsize2[$i]) && (length($FILES[$i]) > 4))
{
$INfile = $FILES[$i];
$OUTfile = $FILES[$i];
$OUTfile =~ s/-in\.wav/-out.wav/gi;
$OUTfile =~ s/-in\.gsm/-out.gsm/gi;
$ALLfile = $FILES[$i];
$ALLfile =~ s/-in\.wav/-all.wav/gi;
$ALLfile =~ s/-in\.gsm/-all.gsm/gi;
$SQLFILE = $FILES[$i];
$SQLFILE =~ s/-in\.wav|-in\.gsm//gi;
$length_in_sec=0;
$stmtA = "select recording_id,length_in_sec from recording_log where filename='$SQLFILE' order by recording_id desc LIMIT 1;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$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;
$recording_id = $aryA[0];
$length_in_sec = $aryA[1];
}
$sthA->finish();
if ($DB) {print "|$recording_id|$length_in_sec|$INfile|$OUTfile| |$ALLfile|\n";}
`$soxmixbin "$dir1/$INfile" "$dir1/$OUTfile" "$dir2/$ALLfile"`;
$lengthSQL='';
if ( ( ($length_in_sec < 1) || ($length_in_sec =~ /^NULL$/i) || (length($length_in_sec)<1) ) && (length($soxibin) > 3) )
{
@soxi_output = `$soxibin -D $dir2/$ALLfile`;
$soxi_sec = $soxi_output[0];
$soxi_sec =~ s/\..*|\n|\r| //gi;
$soxi_min = ($soxi_sec / 60);
$soxi_min = sprintf("%.2f", $soxi_min);
$lengthSQL = ",length_in_sec='$soxi_sec',length_in_min='$soxi_min'";
}
$HTTP='http';
if ($HTTPS > 0) {$HTTP='https';}
$stmtA = "UPDATE recording_log set location='$HTTP://$server_ip/RECORDINGS/$ALLfile' $lengthSQL where recording_id='$recording_id';";
if($DBX){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
if (!$T)
{
`mv -f "$dir1/$INfile" "$dir2/ORIG/$INfile"`;
`mv -f "$dir1/$OUTfile" "$dir2/ORIG/$OUTfile"`;
}
### sleep for twenty hundredths of a second to not flood the server with disk activity
usleep(1*200*1000);
}
}
$i++;
}
if ($DB) {print "DONE... EXITING\n\n";}
$dbhA->disconnect();
exit;
@@ -0,0 +1,388 @@
#!/usr/bin/perl
#
# AST_CRON_audio_2_compress.pl
#
# This is a STEP-2 program in the audio archival process
#
# runs every 3 minutes and compresses the -all recording files to GSM format
#
# put an entry into the cron of of your asterisk machine to run this script
# every 3 minutes or however often you desire
#
# ### recording mixing/compressing/ftping scripts
##0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_mix.pl
# 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_VDonly.pl
# 1,4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58 * * * * /usr/share/astguiclient/AST_CRON_audio_2_compress.pl --GSM
# 2,5,8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59 * * * * /usr/share/astguiclient/AST_CRON_audio_3_ftp.pl --GSM
#
# FLAGS FOR COMPRESSION CODECS
# --GSM = GSM 6.10 codec
# --MP3 = MPEG Layer3 codec
# --OGG = OGG Vorbis codec
# --GSW = GSM 6.10 codec with RIFF headers (.wav extension)
#
# make sure that the following directories exist:
# /var/spool/asterisk/monitorDONE # where the mixed -all files are put
#
# This program assumes that recordings are saved by Asterisk as .wav
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
#
# 80302-1958 - First Build
# 80731-2253 - Changed size comparisons for more efficiency
# 90727-1417 - Added GSW format option
# 101207-1024 - Change to GSW option because of SoX flag changes in 14.3.0
# 110524-1059 - Added run-check concurrency check option
# 160523-0652 - Added --HTTPS option to use https instead of http in local location
#
$GSM=0; $MP3=0; $OGG=0; $GSW=0;
$HTTPS=0;
$maxfiles = 100000;
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [--help] = this screen\n";
print " [--debug] = debug\n";
print " [--debugX] = super debug\n";
print " [-t] = test\n";
print " [--GSM] = compress into GSM codec\n";
print " [--MP3] = compress into MPEG-Layer-3 codec\n";
print " [--OGG] = compress into OGG Vorbis codec\n";
print " [--GSW] = compress into GSM codec with RIFF headers and .wav extension\n";
print " [--HTTPS] = use https instead of http in local location\n";
print " [--run-check] = concurrency check, die if another instance is running\n";
print " [--max-files=x] = maximum number of files to process, default is 100000\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1;
print "\n----- DEBUG -----\n\n";
}
if ($args =~ /--debugX/i)
{
$DBX=1;
print "\n----- SUPER DEBUG -----\n\n";
}
if ($args =~ /-t/i)
{
$T=1; $TEST=1;
print "\n-----TESTING -----\n\n";
}
if ($args =~ /--run-check/i)
{
$run_check=1;
if ($DB) {print "\n----- CONCURRENCY CHECK -----\n\n";}
}
if ($args =~ /--max-files=/i)
{
@data_in = split(/--max-files=/,$args);
$maxfiles = $data_in[1];
$maxfiles =~ s/ .*$//gi;
}
if ($args =~ /--HTTPS/i)
{
$HTTPS=1;
if ($DB) {print "HTTPS location option enabled\n";}
}
if ($args =~ /--GSM/i)
{
$GSM=1;
if ($DB) {print "GSM compression\n";}
}
else
{
if ($args =~ /--MP3/i)
{
$MP3=1;
if ($DB) {print "MP3 compression\n";}
}
else
{
if ($args =~ /--OGG/i)
{
$OGG=1;
if ($DB) {print "OGG compression\n";}
}
else
{
if ($args =~ /--GSW/i)
{
$GSW=1;
if ($DB) {print "GSW compression\n";}
}
}
}
}
}
}
else
{
#print "no command line options set\n";
$GSM=1;
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 =~ /^PATHDONEmonitor/) && ($CLIDONEmonitor < 1) )
{$PATHDONEmonitor = $line; $PATHDONEmonitor =~ 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;}
if ( ($line =~ /^VARFTP_host/) && ($CLIFTP_host < 1) )
{$VARFTP_host = $line; $VARFTP_host =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_user/) && ($CLIFTP_user < 1) )
{$VARFTP_user = $line; $VARFTP_user =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_pass/) && ($CLIFTP_pass < 1) )
{$VARFTP_pass = $line; $VARFTP_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_port/) && ($CLIFTP_port < 1) )
{$VARFTP_port = $line; $VARFTP_port =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_dir/) && ($CLIFTP_dir < 1) )
{$VARFTP_dir = $line; $VARFTP_dir =~ s/.*=//gi;}
if ( ($line =~ /^VARHTTP_path/) && ($CLIHTTP_path < 1) )
{$VARHTTP_path = $line; $VARHTTP_path =~ s/.*=//gi;}
$i++;
}
### concurrency check
if ($run_check > 0)
{
my $grepout = `/bin/ps ax | grep $0 | grep -v grep | grep -v '/bin/sh'`;
my $grepnum=0;
$grepnum++ while ($grepout =~ m/\n/g);
if ($grepnum > 1)
{
if ($DB) {print "I am not alone! Another $0 is running! Exiting...\n";}
exit;
}
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$VARDB_port) {$VARDB_port='3306';}
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
if ( ($GSM > 0) || ($OGG > 0) || ($GSW > 0) )
{
### find sox binary to do the compression
$soxbin = '';
if ( -e ('/usr/bin/sox')) {$soxbin = '/usr/bin/sox';}
else
{
if ( -e ('/usr/local/bin/sox')) {$soxbin = '/usr/local/bin/sox';}
else
{
print "Can't find sox binary! Exiting...\n";
exit;
}
}
}
if ($MP3 > 0)
{
### find lame mp3 encoder binary to do the compression
$lamebin = '';
if ( -e ('/usr/bin/lame')) {$lamebin = '/usr/bin/lame';}
else
{
if ( -e ('/usr/local/bin/lame')) {$lamebin = '/usr/local/bin/lame';}
else
{
print "Can't find lame binary! Exiting...\n";
exit;
}
}
}
if ($DBX > 0)
{
print "SOX: $soxbin LAME: $lamebin\n";
}
### directory where -all recordings are
$dir2 = "$PATHDONEmonitor";
opendir(FILE, "$dir2/");
@FILES = readdir(FILE);
### Loop through files first to gather filesizes
$i=0;
foreach(@FILES)
{
$FILEsize1[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir1/$FILES[$i]") )
{
$FILEsize1[$i] = (-s "$dir1/$FILES[$i]");
if ($DBX) {print "$FILES[$i] $FILEsize1[$i]\n";}
}
$i++;
}
sleep(5);
### Loop through files a second time to gather filesizes again 5 seconds later
$i=0;
foreach(@FILES)
{
$FILEsize2[$i] = 0;
if ( ( (length($FILES[$i]) > 4) && (!-d "$dir1/$FILES[$i]") ) && ($maxfiles > $i) )
{
$FILEsize2[$i] = (-s "$dir1/$FILES[$i]");
if ($DBX) {print "$FILES[$i] $FILEsize2[$i]\n\n";}
if ( ($FILES[$i] !~ /out\.|in\.|lost\+found/i) && ($FILEsize1[$i] eq $FILEsize2[$i]) && (length($FILES[$i]) > 4))
{
$recording_id='';
$ALLfile = $FILES[$i];
$SQLFILE = $FILES[$i];
$SQLFILE =~ s/-all\.wav|-all\.gsm//gi;
$stmtA = "select recording_id from recording_log where filename='$SQLFILE' order by recording_id desc LIMIT 1;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$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;
$recording_id = "$aryA[0]";
}
$sthA->finish();
$HTTP='http';
if ($HTTPS > 0) {$HTTP='https';}
if ($GSM > 0)
{
$GSMfile = $FILES[$i];
$GSMfile =~ s/-all\.wav/-all.gsm/gi;
if ($DB) {print "|$recording_id|$ALLfile|$GSMfile| |$SQLfile|\n";}
`$soxbin "$dir2/$ALLfile" "$dir2/GSM/$GSMfile"`;
$stmtA = "UPDATE recording_log set location='$HTTP://$server_ip/RECORDINGS/GSM/$GSMfile' where recording_id='$recording_id';";
if($DBX){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
}
if ($OGG > 0)
{
$OGGfile = $FILES[$i];
$OGGfile =~ s/-all\.wav/-all.ogg/gi;
if ($DB) {print "|$recording_id|$ALLfile|$OGGfile| |$SQLfile|\n";}
`$soxbin "$dir2/$ALLfile" "$dir2/OGG/$OGGfile"`;
$stmtA = "UPDATE recording_log set location='$HTTP://$server_ip/RECORDINGS/OGG/$OGGfile' where recording_id='$recording_id';";
if($DBX){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
}
if ($MP3 > 0)
{
$MP3file = $FILES[$i];
$MP3file =~ s/-all\.wav/-all.mp3/gi;
if ($DB) {print "|$recording_id|$ALLfile|$MP3file| |$SQLfile|\n";}
`$lamebin -b 16 -m m --silent "$dir2/$ALLfile" "$dir2/MP3/$MP3file"`;
$stmtA = "UPDATE recording_log set location='$HTTP://$server_ip/RECORDINGS/MP3/$MP3file' where recording_id='$recording_id';";
if($DBX){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
}
if ($GSW > 0)
{
$GSWfile = $FILES[$i];
if ($DB) {print "|$recording_id|$ALLfile|$GSWfile| |$SQLfile|$soxbin \"$dir2/$ALLfile\" -e gsm-full-rate \"$dir2/GSW/$GSWfile\"|\n";}
# for SoX versions before 14.3.X
# `$soxbin "$dir2/$ALLfile" -g -b "$dir2/GSW/$GSWfile"`;
# for SoX versions 14.3.0 and after
`$soxbin "$dir2/$ALLfile" -e gsm-full-rate "$dir2/GSW/$GSWfile"`;
$stmtA = "UPDATE recording_log set location='$HTTP://$server_ip/RECORDINGS/GSW/$GSWfile' where recording_id='$recording_id';";
if($DBX){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
}
if (!$T)
{
`mv -f "$dir2/$ALLfile" "$dir2/ORIG/$ALLfile"`;
}
### sleep for twenty hundredths of a second to not flood the server with disk activity
usleep(1*200*1000);
}
}
$i++;
}
if ($DB) {print "DONE... EXITING\n\n";}
$dbhA->disconnect();
exit;
@@ -0,0 +1,375 @@
#!/usr/bin/perl
#
# AST_CRON_audio_2_encrypt.pl
#
# This is a STEP-2 program in the audio archival process(should happen AFTER any compression)
#
# runs every 3 minutes and encrypts the recording files to GPG format by default
#
# put an entry into the cron of of your asterisk machine to run this script
# every 3 minutes or however often you desire
#
# You MUST define the type of audio file that this process will pull from: WAV, GSM, MP3, OGG, GSW
#
# ### recording mixing/compressing/encrypting/ftping scripts
##0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_mix.pl
# 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_VDonly.pl
# 1,4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58 * * * * /usr/share/astguiclient/AST_CRON_audio_2_compress.pl --GSM
# 2,5,8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59 * * * * /usr/share/astguiclient/AST_CRON_audio_2_encrypt.pl --GPG --GSM --recipients=gpg@vicidial.com
# 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_3_ftp.pl --GPG
#
# FLAGS FOR ENCRYPTION OPTIONS
# --GPG = GnuPG encryption(assumes recipient public keys are loaded on server)
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
#
# 150911-1814 - First Build based upon 110524-1059 AST_CRON_audio_2_compress.pl
# 160523-0651 - Added --HTTPS option to use https instead of http in local location
#
$WAV=0; $GSM=0; $MP3=0; $OGG=0; $GSW=0;
$GPG=0;
$HTTPS=0;
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [--help] = this screen\n";
print " [--debug] = debug\n";
print " [--debugX] = super debug\n";
print " [-t] = test\n";
print " [--GPG] = encrypt into GPG codec\n";
print " [--WAV] = look for uncompressed WAV files\n";
print " [--GSM] = look for already compressed GSM files\n";
print " [--MP3] = look for already compressed MPEG-Layer-3 files\n";
print " [--OGG] = look for already compressed OGG Vorbis files\n";
print " [--GSW] = look for already compressed GSM codec with RIFF headers and .wav extension files\n";
print " [--HTTPS] = use https instead of http in local location\n";
print " [--run-check] = concurrency check, die if another instance is running\n";
print " [--max-files=x] = maximum number of files to process, defaults to 100000\n";
print " [--recipients=x\@y.com---z\@a.net] = encryption recipients addresses, REQUIRED\n";
print " NOTE: all recipients must be loaded into keys on local server and accessible to gpg binary\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1;
print "\n----- DEBUG -----\n\n";
}
if ($args =~ /--debugX/i)
{
$DBX=1;
print "\n----- SUPER DEBUG -----\n\n";
}
if ($args =~ /-t/i)
{
$T=1; $TEST=1;
print "\n-----TESTING -----\n\n";
}
if ($args =~ /--run-check/i)
{
$run_check=1;
if ($DB) {print "\n----- CONCURRENCY CHECK -----\n\n";}
}
if ($args =~ /--recipients=/i)
{
@data_in = split(/--recipients=/,$args);
$CLIrecipient = $data_in[1];
$CLIrecipient =~ s/ .*$//gi;
if ($DB) {print "\n----- RECIPIENTS: $CLIrecipient -----\n\n";}
if ($CLIrecipient =~ /---/)
{
$CLIrecipient =~ s/---/ --recipient /gi;
}
}
else
{print "ERROR: recipient is required, exiting..."; exit;}
if ($args =~ /--max-files=/i)
{
@data_in = split(/--max-files=/,$args);
$maxfiles = $data_in[1];
$maxfiles =~ s/ .*$//gi;
$maxfiles = ($maxfiles + 2); # account for directory lists
}
else
{$maxfiles = 100000;}
if ($DB) {print "\n----- MAX FILES: $maxfiles -----\n\n";}
if ($args =~ /--GPG/i)
{
$GPG=1;
if ($DB) {print "GPG encryption\n";}
}
else
{
$GPG=1;
if ($DB) {print "Defaulting to use GPG encryption\n";}
}
if ($args =~ /--HTTPS/i)
{
$HTTPS=1;
if ($DB) {print "HTTPS location option enabled\n";}
}
if ($args =~ /--WAV/i)
{
$WAV=1;
if ($DB) {print "WAV compression\n";}
}
else
{
if ($args =~ /--GSM/i)
{
$GSM=1;
if ($DB) {print "GSM compression\n";}
}
else
{
if ($args =~ /--MP3/i)
{
$MP3=1;
if ($DB) {print "MP3 compression\n";}
}
else
{
if ($args =~ /--OGG/i)
{
$OGG=1;
if ($DB) {print "OGG compression\n";}
}
else
{
if ($args =~ /--GSW/i)
{
$GSW=1;
if ($DB) {print "GSW compression\n";}
}
else
{
print "ERROR: no audio format defined, exiting..."; exit;
}
}
}
}
}
}
}
else
{
print "ERROR: cannot run script without any command line options, exiting..."; exit;
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 =~ /^PATHDONEmonitor/) && ($CLIDONEmonitor < 1) )
{$PATHDONEmonitor = $line; $PATHDONEmonitor =~ 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;}
if ( ($line =~ /^VARFTP_host/) && ($CLIFTP_host < 1) )
{$VARFTP_host = $line; $VARFTP_host =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_user/) && ($CLIFTP_user < 1) )
{$VARFTP_user = $line; $VARFTP_user =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_pass/) && ($CLIFTP_pass < 1) )
{$VARFTP_pass = $line; $VARFTP_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_port/) && ($CLIFTP_port < 1) )
{$VARFTP_port = $line; $VARFTP_port =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_dir/) && ($CLIFTP_dir < 1) )
{$VARFTP_dir = $line; $VARFTP_dir =~ s/.*=//gi;}
if ( ($line =~ /^VARHTTP_path/) && ($CLIHTTP_path < 1) )
{$VARHTTP_path = $line; $VARHTTP_path =~ s/.*=//gi;}
$i++;
}
### concurrency check
if ($run_check > 0)
{
my $grepout = `/bin/ps ax | grep $0 | grep -v grep | grep -v '/bin/sh'`;
my $grepnum=0;
$grepnum++ while ($grepout =~ m/\n/g);
if ($grepnum > 1)
{
if ($DB) {print "I am not alone! Another $0 is running! Exiting...\n";}
exit;
}
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$VARDB_port) {$VARDB_port='3306';}
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
if ($GPG > 0)
{
### find GnuPG encryption binary to do the encryption
$gpgbin = '';
if ( -e ('/usr/bin/gpg')) {$gpgbin = '/usr/bin/gpg';}
else
{
if ( -e ('/usr/local/bin/gpg')) {$gpgbin = '/usr/local/bin/gpg';}
else
{
print "Can't find gpg binary! Exiting...\n";
exit;
}
}
}
### directory where -all recordings are
if ($WAV > 0) {$dir2 = "$PATHDONEmonitor";}
if ($MP3 > 0) {$dir2 = "$PATHDONEmonitor/MP3";}
if ($GSM > 0) {$dir2 = "$PATHDONEmonitor/GSM";}
if ($OGG > 0) {$dir2 = "$PATHDONEmonitor/OGG";}
if ($GSW > 0) {$dir2 = "$PATHDONEmonitor/GSW";}
if ($DBX > 0)
{
print "GPG: $gpgbin DIR: $dir2\n";
}
if (!-e "$PATHDONEmonitor/GPG")
{
print "Creating directory: $PATHDONEmonitor/GPG \n";
`mkdir -p $PATHDONEmonitor/GPG`;
}
opendir(FILE, "$dir2/");
@FILES = readdir(FILE);
### Loop through files first to gather filesizes
$i=0;
foreach(@FILES)
{
$FILEsize1[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir2/$FILES[$i]") )
{
$FILEsize1[$i] = (-s "$dir2/$FILES[$i]");
if ($DBX) {print "$FILES[$i] $FILEsize1[$i]\n";}
}
$i++;
}
sleep(5);
### Loop through files a second time to gather filesizes again 5 seconds later
$i=0;
foreach(@FILES)
{
$FILEsize2[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir2/$FILES[$i]") && ($maxfiles > $i) )
{
$FILEsize2[$i] = (-s "$dir2/$FILES[$i]");
if ($DBX) {print "$FILES[$i] $FILEsize2[$i]\n\n";}
if ( ($FILES[$i] !~ /out\.|in\.|lost\+found/i) && ($FILEsize1[$i] eq $FILEsize2[$i]) && (length($FILES[$i]) > 4))
{
$recording_id='';
$ALLfile = $FILES[$i];
$SQLFILE = $FILES[$i];
$SQLFILE =~ s/-all\.wav|-all\.gsm|-all\.mp3|-all\.gsw|-all\.ogg//gi;
$stmtA = "select recording_id from recording_log where filename='$SQLFILE' order by recording_id desc LIMIT 1;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$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;
$recording_id = "$aryA[0]";
}
$sthA->finish();
$HTTP='http';
if ($HTTPS > 0) {$HTTP='https';}
if ($GPG > 0)
{
$GPGfile = $FILES[$i];
$GPGfile =~ s/-all\.wav/-all.wav.gpg/gi;
$GPGfile =~ s/-all\.gsm/-all.gsm.gpg/gi;
$GPGfile =~ s/-all\.mp3/-all.mp3.gpg/gi;
$GPGfile =~ s/-all\.gsw/-all.gsw.gpg/gi;
$GPGfile =~ s/-all\.ogg/-all.ogg.gpg/gi;
if ($DB) {print "$i|$recording_id|$ALLfile|$GPGfile| |$SQLfile|\n";}
`$gpgbin --trust-model always --output $PATHDONEmonitor/GPG/$GPGfile --encrypt --recipient $CLIrecipient $dir2/$ALLfile`;
$stmtA = "UPDATE recording_log set location='$HTTP://$server_ip/RECORDINGS/GPG/$GPGfile' where recording_id='$recording_id';";
if($DBX){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
}
if (!$T)
{
`rm -f "$dir2/$ALLfile"`;
}
### sleep for twenty hundredths of a second to not flood the server with disk activity
usleep(1*200*1000);
}
}
$i++;
}
if ($DB) {print "DONE... EXITING\n\n";}
$dbhA->disconnect();
exit;
@@ -0,0 +1,559 @@
#!/usr/bin/perl
#
# AST_CRON_audio_3_ftp.pl
#
# This is a STEP-3 program in the audio archival process
#
# runs every 3 minutes and copies the recording files to an FTP server
#
# put an entry into the cron of of your asterisk machine to run this script
# every 3 minutes or however often you desire
#
# ### recording mixing/compressing/ftping scripts
##0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_mix.pl
# 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_VDonly.pl
# 1,4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58 * * * * /usr/share/astguiclient/AST_CRON_audio_2_compress.pl --GSM
# 2,5,8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59 * * * * /usr/share/astguiclient/AST_CRON_audio_3_ftp.pl --GSM
#
# FLAGS FOR COMPRESSION FILES TO TRANSFER
# --GSM = GSM 6.10 files
# --MP3 = MPEG Layer3 files
# --OGG = OGG Vorbis files
# --WAV = WAV files
# --GSW = GSM 6.10 codec with RIFF headers (.wav extension)
# --GPG = GnuPG encrypted audio files
#
# FLAG FOR NO DATE DIRECTORY ON FTP
# --NODATEDIR
#
# FLAG FOR Y/M/D DATE DIRECTORY ON FTP
# --YMDdatedir
#
# if pinging is not working, try the 'icmp' Ping command in the code instead
#
# make sure that the following directories exist:
# /var/spool/asterisk/monitorDONE # where the mixed -all files are put
#
# This program assumes that recordings are saved by Asterisk as .wav
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
#
# 80302-1958 - First Build
# 80317-2349 - Added FTP debug if debugX
# 80731-2253 - Changed size comparisons for more efficiency
# 90727-1458 - Added GSW format option
# 90730-1454 - Fixed non-VicDial recordings date directory, added secondary icmp ping if standard ping fails
# 90818-0953 - Fixed a bug where the filesizes for all files were null
# 90818-1017 - Added a transfer limit and list limit options.
# 90827-2013 - Fixed list limit option
# 91123-0037 - Added FTP CLI options
# 110524-1049 - Added run-check concurrency check option
# 111128-1615 - Added Ftp persistence option
# 111130-1751 - Added Ftp validate option
# 130116-1536 - Added ftp port CLI flag
# 150911-2336 - Added GPG encrypted audio file compatibility
# 160406-2055 - Added YMDdatedir option
#
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
$FTPdate = "$year-$mon-$mday";
$GSM=0; $MP3=0; $OGG=0; $WAV=0; $GSW=0; $GPG=0; $NODATEDIR=0; $YMDdatedir=0;
# Default variables for FTP
$VARFTP_host = '10.0.0.4';
$VARFTP_user = 'cron';
$VARFTP_pass = 'test';
$VARFTP_port = '21';
$VARFTP_dir = 'RECORDINGS';
$VARHTTP_path = 'http://10.0.0.4';
$file_limit = 1000;
$list_limit = 1000;
$FTPpersistent=0;
$FTPvalidate=0;
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [--help] = this screen\n";
print " [--debug] = debug\n";
print " [--debugX] = super debug\n";
print " [--test] = test\n";
print " [--transfer-limit=XXX] = number of files to transfer before exiting\n";
print " [--list-limit=XXX] = number of files to list in the directory before moving on\n";
print " [--debugX] = super debug\n";
print " [--GSM] = copy GSM files\n";
print " [--MP3] = copy MPEG-Layer-3 files\n";
print " [--OGG] = copy OGG Vorbis files\n";
print " [--WAV] = copy WAV files\n";
print " [--GSW] = copy GSM with RIFF headers and .wav extension files\n";
print " [--GPG] = copy GPG encrypted files\n";
print " [--nodatedir] = do not put into dated directories\n";
print " [--YMDdatedir] = put into Year/Month/Day dated directories\n";
print " [--run-check] = concurrency check, die if another instance is running\n";
print " [--max-files=x] = maximum number of files to process, defaults to 100000\n";
print " [--ftp-server=XXX] = FTP server\n";
print " [--ftp-port=XXX] = FTP server port\n";
print " [--ftp-login=XXX] = FTP server login account\n";
print " [--ftp-pass=XXX] = FTP server password\n";
print " [--ftp-dir=XXX] = FTP server directory\n";
print " [--ftp-persistent] = Does not log out between every file transmission\n";
print " [--ftp-validate] = Checks for a file size on the file after transmission\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1;
print "\n----- DEBUG -----\n\n";
}
if ($args =~ /--debugX/i)
{
$DBX=1;
print "\n----- SUPER DEBUG -----\n\n";
}
if ($args =~ /--test/i)
{
$T=1; $TEST=1;
print "\n----- TESTING -----\n\n";
}
if ($args =~ /--nodatedir/i)
{
$NODATEDIR=1;
if ($DB) {print "\n----- NO DATE DIRECTORIES -----\n\n";}
}
if ($args =~ /--YMDdatedir/i)
{
$YMDdatedir=1;
if ($DB) {print "\n----- Y/M/D DATED DIRECTORIES -----\n\n";}
}
if ($args =~ /--run-check/i)
{
$run_check=1;
if ($DB) {print "\n----- CONCURRENCY CHECK -----\n\n";}
}
if ($args =~ /--transfer-limit=/i)
{
my @data_in = split(/--transfer-limit=/,$args);
$file_limit = $data_in[1];
$file_limit =~ s/ .*//gi;
print "\n----- FILE TRANSFER LIMIT: $file_limit -----\n\n";
}
if ($args =~ /--list-limit=/i)
{
my @data_in = split(/--list-limit=/,$args);
$list_limit = $data_in[1];
$list_limit =~ s/ .*//gi;
print "\n----- FILE LIST LIMIT: $list_limit -----\n\n";
}
if ($args =~ /--GSM/i)
{
$GSM=1;
if ($DB) {print "GSM audio files\n";}
}
else
{
if ($args =~ /--MP3/i)
{
$MP3=1;
if ($DB) {print "MP3 audio files\n";}
}
else
{
if ($args =~ /--OGG/i)
{
$OGG=1;
if ($DB) {print "OGG audio files\n";}
}
else
{
if ($args =~ /--WAV/i)
{
$WAV=1;
if ($DB) {print "WAV audio files\n";}
}
else
{
if ($args =~ /--GSW/i)
{
$GSW=1;
if ($DB) {print "GSW audio files\n";}
}
else
{
if ($args =~ /--GPG/i)
{
$GPG=1;
if ($DB) {print "GPG encrypted audio files\n";}
}
}
}
}
}
}
if ($args =~ /--ftp-server=/i)
{
my @data_in = split(/--ftp-server=/,$args);
$VARFTP_host = $data_in[1];
$VARFTP_host =~ s/ .*//gi;
$CLIFTP_host=1;
if ($DB > 0)
{print "\n----- FTP SERVER: $VARFTP_host -----\n\n";}
}
if ($args =~ /--ftp-port=/i)
{
my @data_in = split(/--ftp-port=/,$args);
$VARFTP_port = $data_in[1];
$VARFTP_port =~ s/ .*//gi;
$CLIFTP_port=1;
if ($DB > 0)
{print "\n----- FTP PORT: $VARFTP_port -----\n\n";}
}
if ($args =~ /--ftp-login=/i)
{
my @data_in = split(/--ftp-login=/,$args);
$VARFTP_user = $data_in[1];
$VARFTP_user =~ s/ .*//gi;
$CLIFTP_user=1;
if ($DB > 0)
{print "\n----- FTP LOGIN: $VARFTP_user -----\n\n";}
}
if ($args =~ /--ftp-pass=/i)
{
my @data_in = split(/--ftp-pass=/,$args);
$VARFTP_pass = $data_in[1];
$VARFTP_pass =~ s/ .*//gi;
$CLIFTP_pass=1;
if ($DB > 0)
{print "\n----- FTP PASS: $VARFTP_pass -----\n\n";}
}
if ($args =~ /--ftp-dir=/i)
{
my @data_in = split(/--ftp-dir=/,$args);
$VARFTP_dir = $data_in[1];
$VARFTP_dir =~ s/ .*//gi;
$CLIFTP_dir=1;
if ($DB > 0)
{print "\n----- FTP DIRECTORY: $VARFTP_dir -----\n\n";}
}
if ($args =~ /--ftp-persistent/i)
{
$FTPpersistent=1;
if ($DB > 0)
{print "\n----- FTP PERSISTENT: $FTPpersistent -----\n\n";}
}
if ($args =~ /--ftp-validate/i)
{
$FTPvalidate=1;
if ($DB > 0)
{print "\n----- FTP VALIDATE: $FTPvalidate -----\n\n";}
}
}
}
else
{
#print "no command line options set\n";
$WAV=1;
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 =~ /^PATHDONEmonitor/) && ($CLIDONEmonitor < 1) )
{$PATHDONEmonitor = $line; $PATHDONEmonitor =~ 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;}
if ( ($line =~ /^VARFTP_host/) && ($CLIFTP_host < 1) )
{$VARFTP_host = $line; $VARFTP_host =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_user/) && ($CLIFTP_user < 1) )
{$VARFTP_user = $line; $VARFTP_user =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_pass/) && ($CLIFTP_pass < 1) )
{$VARFTP_pass = $line; $VARFTP_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_port/) && ($CLIFTP_port < 1) )
{$VARFTP_port = $line; $VARFTP_port =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_dir/) && ($CLIFTP_dir < 1) )
{$VARFTP_dir = $line; $VARFTP_dir =~ s/.*=//gi;}
if ( ($line =~ /^VARHTTP_path/) && ($CLIHTTP_path < 1) )
{$VARHTTP_path = $line; $VARHTTP_path =~ s/.*=//gi;}
$i++;
}
### concurrency check
if ($run_check > 0)
{
my $grepout = `/bin/ps ax | grep $0 | grep -v grep | grep -v '/bin/sh'`;
my $grepnum=0;
$grepnum++ while ($grepout =~ m/\n/g);
if ($grepnum > 1)
{
if ($DB) {print "I am not alone! Another $0 is running! Exiting...\n";}
exit;
}
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$VARDB_port) {$VARDB_port='3306';}
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
use Net::Ping;
use Net::FTP;
### directory where -all recordings are
if ($WAV > 0) {$dir2 = "$PATHDONEmonitor";}
if ($MP3 > 0) {$dir2 = "$PATHDONEmonitor/MP3";}
if ($GSM > 0) {$dir2 = "$PATHDONEmonitor/GSM";}
if ($OGG > 0) {$dir2 = "$PATHDONEmonitor/OGG";}
if ($GSW > 0) {$dir2 = "$PATHDONEmonitor/GSW";}
if ($GPG > 0) {$dir2 = "$PATHDONEmonitor/GPG";}
opendir(FILE, "$dir2/");
@FILES = readdir(FILE);
### Loop through files first to gather filesizes
$i=0;
$files_that_count=0;
foreach(@FILES)
{
$FILEsize1[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir2/$FILES[$i]") )
{
$FILEsize1[$i] = (-s "$dir2/$FILES[$i]");
if ($DBX) {print "$dir2/$FILES[$i] $FILEsize1[$i]\n";}
$files_that_count++;
}
$i++;
if ($files_that_count >= $list_limit)
{
last();
}
}
sleep(5);
$transfered_files = 0;
### Loop through files a second time to gather filesizes again 5 seconds later
$i=0;
foreach(@FILES)
{
$FILEsize2[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir2/$FILES[$i]") )
{
$FILEsize2[$i] = (-s "$dir2/$FILES[$i]");
if ($DBX) {print "$dir2/$FILES[$i] $FILEsize2[$i]\n\n";}
if ($FILEsize1[$i] ne $FILEsize2[$i])
{
if ($DBX) {print "not transfering $dir2/$FILES[$i]. File size mismatch $FILEsize2[$i] != $FILEsize1[$i]\n\n";}
}
if ( ($FILES[$i] !~ /out\.|in\.|lost\+found/i) && ($FILEsize1[$i] eq $FILEsize2[$i]) && (length($FILES[$i]) > 4))
{
$recording_id='';
$ALLfile = $FILES[$i];
$SQLFILE = $FILES[$i];
$SQLFILE =~ s/\.gpg//gi;
$SQLFILE =~ s/-all\.wav|-all\.gsm|-all\.ogg|-all\.mp3//gi;
$stmtA = "select recording_id,start_time from recording_log where filename='$SQLFILE' order by recording_id desc LIMIT 1;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$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;
$recording_id = "$aryA[0]";
$start_date = "$aryA[1]";
$start_date =~ s/ .*//gi;
@filedate = split(/-/,$start_date);
$year = $filedate[0];
$mon = $filedate[1];
$mday = $filedate[2];
}
$sthA->finish();
if (length($start_date) < 6)
{$start_date = $FTPdate;}
if ($DB) {print "|$recording_id|$start_date|$ALLfile| |$SQLfile|\n";}
### BEGIN Remote file transfer
if ( ($FTPpersistent > 0) && ($ping_good > 0) )
{$ping_good=1;}
else
{
$p = Net::Ping->new();
$ping_good = $p->ping("$VARFTP_host");
}
if (!$ping_good)
{
$p = Net::Ping->new("icmp");
$ping_good = $p->ping("$VARFTP_host");
}
if ($ping_good)
{
$transfered_files++;
$start_date_PATH='';
$FTPdb=0;
if ($DBX>0) {$FTPdb=1;}
if ( ($FTPpersistent > 0) && ($transfered_files > 1) )
{
if($DBX){print STDERR "FTP PERSISTENT, skipping login\n";}
if ($NODATEDIR < 1)
{
if ($YMDdatedir > 0)
{
$ftp->cwd("../../../");
}
else
{
$ftp->cwd("../");
}
}
}
else
{
$ftp = Net::FTP->new("$VARFTP_host", Port => $VARFTP_port, Debug => $FTPdb);
$ftp->login("$VARFTP_user","$VARFTP_pass");
$ftp->cwd("$VARFTP_dir");
}
if ($NODATEDIR < 1)
{
if ($YMDdatedir > 0)
{
$ftp->mkdir("$year");
$ftp->cwd("$year");
$ftp->mkdir("$mon");
$ftp->cwd("$mon");
$ftp->mkdir("$mday");
$ftp->cwd("$mday");
$start_date_PATH = "$year/$mon/$mday/";
}
else
{
$ftp->mkdir("$start_date");
$ftp->cwd("$start_date");
$start_date_PATH = "$start_date/";
}
}
$ftp->binary();
$ftp->put("$dir2/$ALLfile", "$ALLfile");
if ($FTPvalidate > 0)
{
$FTPfilesize = $ftp->size("$ALLfile");
if($DBX){print STDERR "FTP FILESIZE: $FTPfilesize/$FILEsize1[$i] | $ALLfile\n";}
if ( ($FILEsize1[$i] > 100) && ($FTPfilesize < 100) )
{
print "ERROR! File did not transfer, exiting: $FTPfilesize/$FILEsize1[$i] | $ALLfile\n";
exit;
}
}
if ($FTPpersistent < 1)
{
$ftp->quit;
}
$stmtA = "UPDATE recording_log set location='$VARHTTP_path/$start_date_PATH$ALLfile' where recording_id='$recording_id';";
if($DB){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
if (!$T)
{
`mv -f "$dir2/$ALLfile" "$PATHDONEmonitor/FTP/$ALLfile"`;
}
if($DBX){print STDERR "Transfered $transfered_files files\n";}
if ( $transfered_files == $file_limit)
{
if($DBX){print STDERR "Transfer limit of $file_limit reached breaking out of the loop\n";}
last();
}
}
else
{
if($DB){print "ERROR: Could not ping server $VARFTP_host\n";}
}
### END Remote file transfer
### sleep for twenty hundredths of a second to not flood the server with disk activity
usleep(1*200*1000);
}
}
$i++;
}
if ($DB) {print "DONE... EXITING\n\n";}
$dbhA->disconnect();
exit;
@@ -0,0 +1,658 @@
#!/usr/bin/perl
# AST_CRON_audio_3_newftp.pl version 2.12
#
# This is a STEP-3 program in the audio archival process. Normally you can run it
# every 3 minutes and copies the recording files to an FTP server.
#
# put an entry into the cron of of your asterisk machine to run this script
# every 3 minutes or however often you desire
#
# ### recording mixing/compressing/ftping scripts
# #0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_mix.pl
# 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_VDonly.pl
# 1,4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58 * * * * /usr/share/astguiclient/AST_CRON_audio_2_compress.pl --MP3
# 2,5,8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59 * * * * /usr/share/astguiclient/AST_CRON_audio_3_newftp.pl --MP3
#
# FLAGS FOR COMPRESSION FILES TO TRANSFER
# --gsm or --GSM = GSM 6.10 files
# --mp3 or --MP3 = MPEG Layer3 files
# --ogg or --OGG = OGG Vorbis files
# --wav or --WAV = WAV files
# --gsw or --GSW = GSM 6.10 codec with RIFF headers (.wav extension)
# --gpg or --GPG = GnuPG encrypted files
#
# FLAGS FOR PING SETTINGS
# --ping-type = The type of ping to send. Options are "none", "tcp", "udp", "icmp",
# "stream", "syn", and "external". None disables pinging. Default is "icmp"
# WARNING setting --ping-type="none" can lead to files being "transfer" to no if your ftp server goes down.
# --ping-timeout = How long to wait for the ping to timeout before giving up, default is 5 seconds.
#
# FLAGS FOR FTP TRANSFER INFO
# --ftp-host = the host address to ftp into
# --ftp-port = the port of the ftp server
# --ftp-user = the user to log into the ftp server with
# --ftp-pass = the password to log into the ftp server with
# --ftp-dir = the directory to put the files into on the ftp server
# --url-path = the url where the recordings can be accessed after the move
#
# FLAGS THAT EFFECT THE ACTUAL TRANSFER
# --stay-connected = remain connected to the ftp server. Without this the script will disconnect and reconnect for each file.
# --transfer-limit = the number of files to transfer before giving up. Default is 1000
# --list-limit = number of files to list in the directory before moving on
# --no-date-dir = does not create a date directory on the server for the files.
# --campaign_id = which OUTBOUND campaigns to transfer files for in a '-' delimited list
# (this only works for outbound calls, not inbound or transfers)
# --ingroup_id = which ingroups to transfer files for in a '-' delimited list
# WARNING you can only set --campaign_id or --ingroup_id, not both.
#
# The following example will transfer 50 mp3s for the campaigns TESTCAMP1 and TESTCAMP2 to the ftp server.
# It will not create dated directories on the ftp server. It will send icmp pings to the server
# and wait at most 3 seconds for a response:
# /usr/share/astguiclient/AST_CRON_audio_3_newftp.pl --no-date-dir --mp3 --ping-type="icmp" --ping-timeout=3 \
# --ftp-host="10.10.10.15" --ftp-port=21 --ftp-user="username" --ftp-pass="password" --ftp-dir="RECORDINGS" \
# --url-path="http://10.10.10.15/RECORDINGS" --transfer-limit=50 --list-limit=200 --campaign_id="TESTCAMP1-TESTCAMP2"
#
# Copyright (C) 2015 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG:
# 90930-1405 - mikec - first build
# 110524-1054 - Added run-check concurrency check option
# 150912-0837 - Added GPG encrypted audio file compatibility
#
use 5.008;
use strict;
use warnings;
# OTHER USE FLAGS
use DBI;
use Net::Ping;
use Net::FTP;
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command for less than one second
# Vars
my $debug = 0;
my $debugX = 0;
my $test = 0;
my $run_check = 0;
my $pingtype = "tcp";
my $pingtimeout = 5;
my $datedir = 1;
my $camp_check = 0;
my $campaigns = "";
my @camp_array;
my $ingrp_check = 0;
my $ingroups = "";
my @ingrp_array;
my $list_limit = 1000;
my $trans_limit = 1000;
my $trans_type = "wav";
my $PATHhome = '';
my $PATHlogs = '';
my $PATHagi = '';
my $PATHweb = '';
my $PATHsounds = '';
my $PATHmonitor = '';
my $PATHDONEmonitor = '';
my $VARserver_ip = '';
my $VARDB_server = '';
my $VARDB_database = '';
my $VARDB_user = '';
my $VARDB_pass = '';
my $VARDB_port = '';
my $ftp_host = '10.0.0.4';
my $ftp_user = 'cron';
my $ftp_pass = 'test';
my $ftp_port = '21';
my $ftp_dir = 'RECORDINGS';
my $url_path = 'http://10.0.0.4';
# default path to astguiclient configuration file:
my $PATHconf = '/etc/astguiclient.conf';
# load the config file settings
open(CONF, "$PATHconf") || die "can't open $PATHconf: $!\n";
my @conf = <CONF>;
close(CONF);
my $i=0;
my $line='';
foreach(@conf) {
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ($line =~ /^PATHhome/)
{$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ($line =~ /^PATHlogs/)
{$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ($line =~ /^PATHagi/)
{$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ($line =~ /^PATHweb/)
{$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ($line =~ /^PATHsounds/)
{$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ($line =~ /^PATHmonitor/)
{$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ($line =~ /^PATHDONEmonitor/)
{$PATHDONEmonitor = $line; $PATHDONEmonitor =~ s/.*=//gi;}
if ($line =~ /^VARserver_ip/)
{$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ($line =~ /^VARDB_server/)
{$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ($line =~ /^VARDB_database/)
{$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ($line =~ /^VARDB_user/)
{$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ($line =~ /^VARDB_pass/)
{$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ($line =~ /^VARDB_port/)
{$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
if ($line =~ /^VARFTP_host/)
{$ftp_host = $line; $ftp_host =~ s/.*=//gi;}
if ($line =~ /^VARFTP_user/)
{$ftp_user = $line; $ftp_user =~ s/.*=//gi;}
if ($line =~ /^VARFTP_pass/)
{$ftp_pass = $line; $ftp_pass =~ s/.*=//gi;}
if ($line =~ /^VARFTP_port/)
{$ftp_port = $line; $ftp_port =~ s/.*=//gi;}
if ($line =~ /^VARFTP_dir/)
{$ftp_dir = $line; $ftp_dir =~ s/.*=//gi;}
if ($line =~ /^VARHTTP_path/)
{$url_path = $line; $url_path =~ s/.*=//gi;}
$i++;
}
# parse run-time options
my $args = '';
if (length($ARGV[0])>1) {
$i=0;
while ($#ARGV >= $i) {
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i) {
print "allowed run time options:\n";
print " [--help] = this screen\n";
print " [--test] = don't move the file\n";
print " [--debug] = debug\n";
print " [--debugX] = super debug\n";
print " [--gsm or --GSM] = copy GSM 6.10 files\n";
print " [--mp3 or --MP3] = copy MPEG Layer3 files\n";
print " [--ogg or --OGG] = copy OGG Vorbis files\n";
print " [--wav or --WAV] = copy WAV files\n";
print " [--gsw or --GSW] = copy GSM 6.10 codec with RIFF headers (.wav extension)\n";
print " [--gpg or --GPG] = copy GPG encrypted files\n";
print " [--ping-type] = The type of ping to send. Options are \"none\", \"tcp\", \"udp\", \"icmp\", \n";
print " \"stream\", \"syn\", and \"external\". None disables pinging. Default is \"icmp\"\n";
print " WARNING setting --ping-type=\"none\" can lead to files being \"transfer\"\n";
print " to no where if your ftp server goes down.\n";
print " [--ping-timeout] = How long to wait for the ping to timeout before giving up, default is 5 seconds.\n";
print " [--ftp-host] = the host address to ftp into\n";
print " [--ftp-port] = the port of the ftp server \n";
print " [--ftp-user] = the user to log into the ftp server with\n";
print " [--ftp-pass] = the password to log into the ftp server with\n";
print " [--ftp-dir] = the directory to put the files into on the ftp server\n";
print " [--url-path] = the url where the recordings can be accessed after the move\n";
print " [--transfer-limit=XXX] = the number of files to transfer before giving up. Default is 1000\n";
print " [--list-limit=XXX] = number of files to list in the directory before moving on\n";
print " [--no-date-dir] = does not put the files in a dated directory.\n";
print " [--run-check] = concurrency check, die if another instance is running\n";
print " [--campaign_id] = which OUTBOUND campaigns to transfer files for in a '-' delimited list \n";
print " (this only works for outbound calls, not inbound or transfers)\n";
print " [--ingroup_id] = which ingroups to transfer files for in a '-' delimited list\n";
print " WARNING you can only set --campaign_id or --ingroup_id, not both.\n";
print "\n";
exit;
} else {
if ($args =~ /--debug/i) {
$debug=1;
print "\n----- DEBUG -----\n\n";
}
if ($args =~ /--debugX/i) {
$debugX=1;
$debug=1;
print "\n----- SUPER DEBUG -----\n\n";
}
if ($args =~ /--test/i) {
$test=1;
print "\n----- TESTING -----\n\n";
}
if (($args =~ /--nodatedir/i) || ($args =~ /--no-date-dir/i)) {
$datedir=0;
if ($debug) {
print "\n----- NO DATE DIRECTORIES -----\n\n";
}
}
if ($args =~ /--run-check/i)
{
$run_check=1;
if ($debug) {print "\n----- CONCURRENCY CHECK -----\n\n";}
}
if ($args =~ /--ping-type=/i) {
my @data_in = split(/--ping-type=/,$args);
$pingtype = $data_in[1];
$pingtype =~ s/ .*//gi;
if ($debug) {
print "\n----- FILE TRANSFER LIMIT: $trans_limit -----\n\n";
}
}
if ($args =~ /--ping-timeout=/i) {
my @data_in = split(/--ping-timeout=/,$args);
$pingtimeout = $data_in[1];
$pingtimeout =~ s/ .*//gi;
if ($debug) {
print "\n----- PING TIMEOUT: $pingtimeout -----\n\n";
}
}
if ($args =~ /--ftp-host=/i) {
my @data_in = split(/--ftp-host=/,$args);
$ftp_host = $data_in[1];
$ftp_host =~ s/ .*//gi;
if ($debug) {
print "\n----- FTP HOST: $ftp_host -----\n\n";
}
}
if ($args =~ /--ftp-port=/i) {
my @data_in = split(/--ftp-port=/,$args);
$ftp_port = $data_in[1];
$ftp_port =~ s/ .*//gi;
if ($debug) {
print "\n----- FTP PORT: $ftp_port -----\n\n";
}
}
if ($args =~ /--ftp-user=/i) {
my @data_in = split(/--ftp-user=/,$args);
$ftp_user = $data_in[1];
$ftp_user =~ s/ .*//gi;
if ($debug) {
print "\n----- FTP USER: $ftp_user -----\n\n";
}
}
if ($args =~ /--ftp-pass=/i) {
my @data_in = split(/--ftp-pass=/,$args);
$ftp_pass = $data_in[1];
$ftp_pass =~ s/ .*//gi;
if ($debug) {
print "\n----- FTP PASSWORD: $ftp_pass -----\n\n";
}
}
if ($args =~ /--ftp-dir=/i) {
my @data_in = split(/--ftp-dir=/,$args);
$ftp_dir = $data_in[1];
$ftp_dir =~ s/ .*//gi;
if ($debug) {
print "\n----- FTP DIRECTORY: $ftp_dir -----\n\n";
}
}
if ($args =~ /--url-path=/i) {
my @data_in = split(/--url-path=/,$args);
$url_path = $data_in[1];
$url_path =~ s/ .*//gi;
if ($debug) {
print "\n----- URL PATH: $url_path -----\n\n";
}
}
if ($args =~ /--campaign_id=/i) {
my @data_in = split(/--campaign_id=/,$args);
$campaigns = $data_in[1];
$campaigns =~ s/ .*//gi;
$campaigns = uc($campaigns);
$camp_check=1;
if ($debug) {
print "\n----- CAMPAIGNS: $campaigns -----\n\n";
}
}
if ($args =~ /--ingroup_id=/i) {
my @data_in = split(/--ingroup_id=/,$args);
$ingroups = $data_in[1];
$ingroups =~ s/ .*//gi;
$ingrp_check=1;
if ($debug) {
print "\n----- INGROUPS: $ingroups -----\n\n";
}
}
if ($args =~ /--transfer-limit=/i) {
my @data_in = split(/--transfer-limit=/,$args);
$trans_limit = $data_in[1];
$trans_limit =~ s/ .*//gi;
if ($debug) {
print "\n----- FILE TRANSFER LIMIT: $trans_limit -----\n\n";
}
}
if ($args =~ /--list-limit=/i) {
my @data_in = split(/--list-limit=/,$args);
$list_limit = $data_in[1];
$list_limit =~ s/ .*//gi;
if ($debug) {
print "\n----- FILE LIST LIMIT: $list_limit -----\n\n";
}
}
if ( ( $args =~ /--GSM/i ) || ( $args =~ /--gsm/i ) ){
$trans_type="gsm";
if ($debug) {
print "GSM audio files\n";
}
} else {
if ( ($args =~ /--MP3/i) || ($args =~ /--mp3/i) ) {
$trans_type="mp3";
if ($debug) {
print "MP3 audio files\n";
}
} else {
if ( ( $args =~ /--OGG/i) || ($args =~ /--ogg/i) ) {
$trans_type="ogg";
if ($debug) {
print "OGG audio files\n";
}
} else {
if ( ( $args =~ /--WAV/i ) || ( $args =~ /--wav/i ) ) {
$trans_type="wav";
if ($debug) {
print "WAV audio files\n";
}
} else {
if ( ($args =~ /--GSW/i) || ($args =~ /--gsw/i) ) {
$trans_type="gsw";
if ($debug) {
print "GSW audio files\n";
}
} else {
if ( ($args =~ /--GPG/i) || ($args =~ /--gpg/i) ) {
$trans_type="gpg";
if ($debug) {
print "GPG compressed files\n";
}
}
}
}
}
}
}
}
}
#### make sure they are not trying to do something we cannot do ####
if (($camp_check) && ($ingrp_check)) {
print "ERROR. You cannot specify ingroups and campaigns in the same instance of this script.\n";
exit();
}
#### get the list of campaigns ####
if ($camp_check) {
@camp_array = split(/-/,$campaigns);
}
#### get the list of ingroups ####
if ($ingrp_check) {
@ingrp_array = split(/-/,$ingroups);
}
### concurrency check
if ($run_check > 0)
{
my $grepout = `/bin/ps ax | grep $0 | grep -v grep | grep -v '/bin/sh'`;
my $grepnum=0;
$grepnum++ while ($grepout =~ m/\n/g);
if ($grepnum > 1)
{
if ($debug) {print "I am not alone! Another $0 is running! Exiting...\n";}
exit;
}
}
#### connect to the db ####
my $dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
#### prepare the sql queries ahead of time so they run quicker ####
# get the info for the recording
my $rec_log_stmt = "SELECT recording_id, start_time, vicidial_id, lead_id FROM recording_log WHERE filename=? ORDER BY recording_id DESC LIMIT 1;";
my $rec_log_sth = $dbhA->prepare($rec_log_stmt) or die "preparing: ",$dbhA->errstr;
# find the campaign_id for the call.
my $vici_log_stmt = "SELECT campaign_id FROM vicidial_log WHERE uniqueid=? AND lead_id=? ORDER BY campaign_id DESC LIMIT 1;";
my $vici_log_sth = $dbhA->prepare($vici_log_stmt) or die "preparing: ",$dbhA->errstr;
# find the ingroup_id for the call.
# why did matt name the ingroup field in the closer log campaign_id?
my $clsr_log_stmt = "SELECT campaign_id FROM vicidial_closer_log WHERE closecallid=? AND lead_id=? ORDER BY campaign_id DESC LIMIT 1;";
my $clsr_log_sth = $dbhA->prepare($clsr_log_stmt) or die "preparing: ",$dbhA->errstr;
# update the recording log
my $update_log_stmt = "UPDATE recording_log SET location=? WHERE recording_id=?;";
my $update_log_sth = $dbhA->prepare($update_log_stmt) or die "preparing: ",$dbhA->errstr;
#### directory where -all recordings are
my $directory = '';
if ($trans_type eq "wav") {$directory = "$PATHDONEmonitor";}
if ($trans_type eq "gsw") {$directory = "$PATHDONEmonitor/GSW";}
if ($trans_type eq "gsm") {$directory = "$PATHDONEmonitor/GSM";}
if ($trans_type eq "ogg") {$directory = "$PATHDONEmonitor/OGG";}
if ($trans_type eq "mp3") {$directory = "$PATHDONEmonitor/MP3";}
if ($trans_type eq "gpg") {$directory = "$PATHDONEmonitor/GPG";}
opendir(FILE, "$directory/");
my @files = readdir(FILE);
### Loop through files first to gather filesizes
my $file_loop_count=0;
my $files_that_count=0;
my @FILEsize1;
foreach(@files) {
$FILEsize1[$file_loop_count] = 0;
if ( (length($files[$file_loop_count]) > 4) && (!-d "$directory/$files[$file_loop_count]") ) {
$FILEsize1[$file_loop_count] = (-s "$directory/$files[$file_loop_count]");
if ($debugX) {
print "$directory/$files[$file_loop_count] $FILEsize1[$file_loop_count]\n";
}
$files_that_count++;
}
$file_loop_count++;
if ($files_that_count >= $list_limit) {
last();
}
}
### sleep 5 seconds
sleep(5);
my $transfered_files = 0;
my @FILEsize2;
my $recording_id = '';
my $start_date = '';
my $ALLfile = '';
my $SQLFILE = '';
my $transfer_file=0;
my $ping = Net::Ping->new($pingtype, $pingtimeout);
if ($pingtype eq "none") {
$ping = 0;
}
### Loop through files a second time to gather filesizes again 5 seconds later
$file_loop_count=0;
$files_that_count=0;
foreach(@files) {
if ($debug) {print "\n\n\n--------NEW-FILE-------------------------------------------------------------------------------------------\n";}
$transfer_file=0;
$FILEsize2[$file_loop_count] = 0;
if ( (length($files[$file_loop_count]) > 4) && (!-d "$directory/$files[$file_loop_count]") ) {
$FILEsize2[$file_loop_count] = (-s "$directory/$files[$file_loop_count]");
if ($debug) {
print "$directory/$files[$file_loop_count] $FILEsize2[$file_loop_count]\n";
}
if ($FILEsize1[$file_loop_count] ne $FILEsize2[$file_loop_count]) {
if ($debugX) {print "not transfering $directory/$files[$file_loop_count]. File size mismatch $FILEsize2[$file_loop_count] != $FILEsize1[$file_loop_count]\n";}
}
if ( ($files[$file_loop_count] !~ /out\.|in\.|lost\+found/i) && ($FILEsize1[$file_loop_count] eq $FILEsize2[$file_loop_count]) && (length($files[$file_loop_count]) > 4)) {
my $recording_id = '';
my $start_date = '';
my $lead_id = '';
my $vicidial_id = '';
my $ALLfile = $files[$file_loop_count];
my $SQLFILE = $files[$file_loop_count];
$SQLFILE =~ s/\.gpg//gi;
$SQLFILE =~ s/-all\.wav|-all\.gsm|-all\.ogg|-all\.mp3//gi;
my $rec_log_db_stmt = "select recording_id, start_time, vicidial_id, lead_id from recording_log where filename=$SQLFILE order by recording_id desc LIMIT 1;";
$rec_log_sth->execute($SQLFILE) or die "executing: $rec_log_db_stmt ", $dbhA->errstr;
my $sthArows=$rec_log_sth->rows;
if ($sthArows > 0) {
my @aryA = $rec_log_sth->fetchrow_array;
$recording_id = "$aryA[0]";
$start_date = "$aryA[1]";
$vicidial_id = "$aryA[2]";
$lead_id = "$aryA[3]";
$start_date =~ s/ .*//gi;
}
$rec_log_sth->finish();
if ($debug) {
print "|$camp_check|$recording_id|$start_date|$ALLfile|$SQLFILE|\n";
}
### are we doing a campaign check
if ($camp_check) {
my $vici_log_db_stmt = "select campaign_id from vicidial_log where uniqueid=$vicidial_id and lead_id=$lead_id;";
$vici_log_sth->execute($vicidial_id, $lead_id) or die "executing: $rec_log_db_stmt ", $dbhA->errstr;
my $sthArows=$vici_log_sth->rows;
if ($sthArows > 0) {
my @aryA = $vici_log_sth->fetchrow_array;
my $campaign_id = "$aryA[0]";
if($debug){print STDERR "\n|$ALLfile is in the $campaign_id campaign.|\n";}
# loop through the campaigns they want to transfer
foreach( @camp_array ) {
# see if the campaign is in there
if ( $_ eq $campaign_id ) {
$transfer_file = 1;
if($debug){print STDERR "\n|$_ is in the list of campaigns.|\n";}
}
}
if(($debug) && ($transfer_file == 0)) {print STDERR "\n|$campaign_id is not in the list of campaigns.|\n";}
}
$vici_log_sth->finish();
} else {
### are we doing an ingroup check
if ($ingrp_check) {
my $clsr_log_db_stmt = "select campaign_id from vicidial_closer_log where closecallid=$vicidial_id and lead_id=$lead_id;";
$clsr_log_sth->execute($vicidial_id, $lead_id) or die "executing: $rec_log_db_stmt ", $dbhA->errstr;
my $sthArows=$clsr_log_sth->rows;
if ($sthArows > 0) {
my @aryA = $clsr_log_sth->fetchrow_array;
my $ingroup_id = "$aryA[0]";
if($debug){print STDERR "\n|$ALLfile is in the $ingroup_id ingroup.|\n";}
# loop through the ingroups they want to transfer
foreach( @ingrp_array ) {
# see if the ingroup is in there
if ( $_ eq $ingroup_id ) {
$transfer_file = 1;
if($debug){print STDERR "\n|$_ is in the list of ingroups.|\n";}
}
}
if(($debug) && ($transfer_file == 0)) {print STDERR "\n|$ingroup_id is not in the list of ingroups.|\n";}
}
$clsr_log_sth->finish();
} else {
### doing neither so always transfer the file.
$transfer_file = 1;
}
}
### BEGIN Remote file transfer
if ($transfer_file) {
# ping the host to make sure it is alive
my $ping_good = 0;
if ($pingtype ne "none") {
$ping_good = $ping->ping("$ftp_host");
if($debug){print "Ping result: $ping_good\n";}
}
### if the ping came back okay or if we are not pinging the server
if (($ping_good) || ($pingtype eq "none")) {
if($debug) {
print STDERR "Transfering the file\n";
}
$transfered_files++;
my $start_date_PATH='';
my $ftp = Net::FTP->new("$ftp_host", Port => $ftp_port, Debug => $debugX);
$ftp->login("$ftp_user","$ftp_pass");
$ftp->mkdir("$ftp_dir");
$ftp->cwd("$ftp_dir");
if ($datedir) {
$ftp->mkdir("$start_date");
$ftp->cwd("$start_date");
$start_date_PATH = "$start_date/";
}
$ftp->binary();
$ftp->put("$directory/$ALLfile", "$ALLfile");
$ftp->quit;
my $update_log_db_stmt = "UPDATE recording_log set location='$url_path/$start_date_PATH$ALLfile' where recording_id='$recording_id';";
if($debug){print STDERR "\n|$update_log_db_stmt|\n";}
my $affected_rows = $update_log_sth->execute("$url_path/$start_date_PATH$ALLfile",$recording_id)
or die "executing: $rec_log_db_stmt ", $dbhA->errstr;
if (!$test) {
if($debugX) {
print STDERR "Moving file from $directory/$ALLfile to $PATHDONEmonitor/FTP/$ALLfile\n";
}
`mv -f "$directory/$ALLfile" "$PATHDONEmonitor/FTP/$ALLfile"`;
}
if($debugX){
print STDERR "Transfered $transfered_files files\n";
}
if ( $transfered_files == $trans_limit) {
if($debug) {
print STDERR "Transfer limit of $trans_limit reached breaking out of the loop\n";
}
last();
}
} else {
if($debug){
print "ERROR: Could not ping server $ftp_host\n";
}
}
}
### END Remote file transfer
### sleep for twenty hundredths of a second to not flood the server with disk activity
usleep(200*1000);
}
# keep track of the files that we actually care about listing.
$files_that_count++;
} else {
if($debug) {
print STDERR "$files[$file_loop_count]'s file name is to short or it is a directory.\n";
}
}
$file_loop_count++;
# break out of here if we have reached the list_limit
if ($files_that_count >= $list_limit) {
last();
}
}
if ($debug) {print "DONE... EXITING\n\n";}
$dbhA->disconnect();
exit;
@@ -0,0 +1,452 @@
#!/usr/bin/perl
#
# AST_CRON_audio_4_ftp2.pl
#
# This is a STEP-4 program in the audio archival process
#
# runs every 3 minutes and copies the recording files to an FTP server
#
# put an entry into the cron of of your asterisk machine to run this script
# every 3 minutes or however often you desire
#
# ### recording mixing/compressing/ftping scripts
##0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_mix.pl
# 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_VDonly.pl
# 1,4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58 * * * * /usr/share/astguiclient/AST_CRON_audio_2_compress.pl --GSM
# 2,5,8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59 * * * * /usr/share/astguiclient/AST_CRON_audio_3_ftp.pl --GSM
# 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_4_ftp2.pl
#
# FLAG FOR NO DATE DIRECTORY ON FTP
# --NODATEDIR
#
# if pinging is not working, try the 'icmp' Ping command in the code instead
#
# make sure that the following directories exist:
# /var/spool/asterisk/monitorDONE # where the mixed -all files are put
#
# This program assumes that recordings are saved by Asterisk as .wav
#
# Copyright (C) 2015 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGES:
# 91123-0005 - First Build
# 110524-1052 - Added run-check concurrency check option
# 111128-1617 - Added Ftp persistence option
# 111130-1801 - Added Ftp validate option
# 130116-1536 - Added ftp port CLI flag
#
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
$FTPdate = "$year-$mon-$mday";
$GSM=0; $MP3=0; $OGG=0; $WAV=0; $GSW=0; $NODATEDIR=0;
# Default variables for FTP
$VARFTP_host = '10.0.0.4';
$VARFTP_user = 'cron';
$VARFTP_pass = 'test';
$VARFTP_port = '21';
$VARFTP_dir = 'RECORDINGS';
$VARHTTP_path = 'http://10.0.0.4';
$file_limit = 1000;
$list_limit = 1000;
$FTPpersistent=0;
$FTPvalidate=0;
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [--help] = this screen\n";
print " [--debug] = debug\n";
print " [--debugX] = super debug\n";
print " [--test] = test\n";
print " [--run-check] = concurrency check, die if another instance is running\n";
print " [--transfer-limit=XXX] = number of files to transfer before exiting\n";
print " [--list-limit=XXX] = number of files to list in the directory before moving on\n";
print " [--debugX] = super debug\n";
print " [--nodatedir] = do not put into dated directories\n\n";
print " [--ftp-server=XXX] = FTP server\n";
print " [--ftp-port=XXX] = FTP server port\n";
print " [--ftp-login=XXX] = FTP server login account\n";
print " [--ftp-pass=XXX] = FTP server password\n";
print " [--ftp-dir=XXX] = FTP server directory\n";
print " [--ftp-persistent] = Does not log out between every file transmission\n";
print " [--ftp-validate] = Checks for a file size on the file after transmission\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1;
print "\n----- DEBUG -----\n\n";
}
if ($args =~ /--debugX/i)
{
$DBX=1;
print "\n----- SUPER DEBUG -----\n\n";
}
if ($args =~ /--test/i)
{
$T=1; $TEST=1;
print "\n----- TESTING -----\n\n";
}
if ($args =~ /--nodatedir/i)
{
$NODATEDIR=1;
if ($DB) {print "\n----- NO DATE DIRECTORIES -----\n\n";}
}
if ($args =~ /--run-check/i)
{
$run_check=1;
if ($DB) {print "\n----- CONCURRENCY CHECK -----\n\n";}
}
if ($args =~ /--transfer-limit=/i)
{
my @data_in = split(/--transfer-limit=/,$args);
$file_limit = $data_in[1];
$file_limit =~ s/ .*//gi;
print "\n----- FILE TRANSFER LIMIT: $file_limit -----\n\n";
}
if ($args =~ /--list-limit=/i)
{
my @data_in = split(/--list-limit=/,$args);
$list_limit = $data_in[1];
$list_limit =~ s/ .*//gi;
print "\n----- FILE LIST LIMIT: $list_limit -----\n\n";
}
if ($args =~ /--ftp-server=/i)
{
my @data_in = split(/--ftp-server=/,$args);
$VARFTP_host = $data_in[1];
$VARFTP_host =~ s/ .*//gi;
$CLIFTP_host=1;
if ($DB > 0)
{print "\n----- FTP SERVER: $VARFTP_host -----\n\n";}
}
if ($args =~ /--ftp-port=/i)
{
my @data_in = split(/--ftp-port=/,$args);
$VARFTP_port = $data_in[1];
$VARFTP_port =~ s/ .*//gi;
$CLIFTP_port=1;
if ($DB > 0)
{print "\n----- FTP PORT: $VARFTP_port -----\n\n";}
}
if ($args =~ /--ftp-login=/i)
{
my @data_in = split(/--ftp-login=/,$args);
$VARFTP_user = $data_in[1];
$VARFTP_user =~ s/ .*//gi;
$CLIFTP_user=1;
if ($DB > 0)
{print "\n----- FTP LOGIN: $VARFTP_user -----\n\n";}
}
if ($args =~ /--ftp-pass=/i)
{
my @data_in = split(/--ftp-pass=/,$args);
$VARFTP_pass = $data_in[1];
$VARFTP_pass =~ s/ .*//gi;
$CLIFTP_pass=1;
if ($DB > 0)
{print "\n----- FTP PASS: $VARFTP_pass -----\n\n";}
}
if ($args =~ /--ftp-dir=/i)
{
my @data_in = split(/--ftp-dir=/,$args);
$VARFTP_dir = $data_in[1];
$VARFTP_dir =~ s/ .*//gi;
$CLIFTP_dir=1;
if ($DB > 0)
{print "\n----- FTP DIRECTORY: $VARFTP_dir -----\n\n";}
}
if ($args =~ /--ftp-persistent/i)
{
$FTPpersistent=1;
if ($DB > 0)
{print "\n----- FTP PERSISTENT: $FTPpersistent -----\n\n";}
}
if ($args =~ /--ftp-validate/i)
{
$FTPvalidate=1;
if ($DB > 0)
{print "\n----- FTP VALIDATE: $FTPvalidate -----\n\n";}
}
}
}
else
{
#print "no command line options set\n";
$WAV=1;
}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 =~ /^PATHDONEmonitor/) && ($CLIDONEmonitor < 1) )
{$PATHDONEmonitor = $line; $PATHDONEmonitor =~ 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;}
if ( ($line =~ /^VARFTP_host/) && ($CLIFTP_host < 1) )
{$VARFTP_host = $line; $VARFTP_host =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_user/) && ($CLIFTP_user < 1) )
{$VARFTP_user = $line; $VARFTP_user =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_pass/) && ($CLIFTP_pass < 1) )
{$VARFTP_pass = $line; $VARFTP_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_port/) && ($CLIFTP_port < 1) )
{$VARFTP_port = $line; $VARFTP_port =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_dir/) && ($CLIFTP_dir < 1) )
{$VARFTP_dir = $line; $VARFTP_dir =~ s/.*=//gi;}
if ( ($line =~ /^VARHTTP_path/) && ($CLIHTTP_path < 1) )
{$VARHTTP_path = $line; $VARHTTP_path =~ s/.*=//gi;}
$i++;
}
### concurrency check
if ($run_check > 0)
{
my $grepout = `/bin/ps ax | grep $0 | grep -v grep | grep -v '/bin/sh'`;
my $grepnum=0;
$grepnum++ while ($grepout =~ m/\n/g);
if ($grepnum > 1)
{
if ($DB) {print "I am not alone! Another $0 is running! Exiting...\n";}
exit;
}
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$VARDB_port) {$VARDB_port='3306';}
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
use Net::Ping;
use Net::FTP;
### directory where -all recordings are
$dir2 = "$PATHDONEmonitor/FTP";
opendir(FILE, "$dir2/");
@FILES = readdir(FILE);
### Loop through files first to gather filesizes
$i=0;
$files_that_count=0;
foreach(@FILES)
{
$FILEsize1[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir2/$FILES[$i]") )
{
$FILEsize1[$i] = (-s "$dir2/$FILES[$i]");
if ($DBX) {print "$dir2/$FILES[$i] $FILEsize1[$i]\n";}
$files_that_count++;
}
$i++;
if ($files_that_count >= $list_limit)
{
last();
}
}
sleep(5);
$transfered_files = 0;
### Loop through files a second time to gather filesizes again 5 seconds later
$i=0;
foreach(@FILES)
{
$FILEsize2[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir2/$FILES[$i]") )
{
$FILEsize2[$i] = (-s "$dir2/$FILES[$i]");
if ($DBX) {print "$dir2/$FILES[$i] $FILEsize2[$i]\n\n";}
if ($FILEsize1[$i] ne $FILEsize2[$i])
{
if ($DBX) {print "not transfering $dir2/$FILES[$i]. File size mismatch $FILEsize2[$i] != $FILEsize1[$i]\n\n";}
}
if ( ($FILES[$i] !~ /out\.|in\.|lost\+found/i) && ($FILEsize1[$i] eq $FILEsize2[$i]) && (length($FILES[$i]) > 4))
{
$recording_id='';
$ALLfile = $FILES[$i];
$SQLFILE = $FILES[$i];
$SQLFILE =~ s/\.gpg//gi;
$SQLFILE =~ s/-all\.wav|-all\.gsm|-all\.ogg|-all\.mp3//gi;
$stmtA = "select recording_id,start_time from recording_log where filename='$SQLFILE' order by recording_id desc LIMIT 1;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$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;
$recording_id = "$aryA[0]";
$start_date = "$aryA[1]";
$start_date =~ s/ .*//gi;
}
$sthA->finish();
if (length($start_date) < 6)
{$start_date = $FTPdate;}
if ($DB) {print "|$recording_id|$start_date|$ALLfile| |$SQLfile|\n";}
### BEGIN Remote file transfer
if ( ($FTPpersistent > 0) && ($ping_good > 0) )
{$ping_good=1;}
else
{
$p = Net::Ping->new();
$ping_good = $p->ping("$VARFTP_host");
}
if (!$ping_good)
{
$p = Net::Ping->new("icmp");
$ping_good = $p->ping("$VARFTP_host");
}
if ($ping_good)
{
$transfered_files++;
$start_date_PATH='';
$FTPdb=0;
if ($DBX>0) {$FTPdb=1;}
if ( ($FTPpersistent > 0) && ($transfered_files > 1) )
{
if($DBX){print STDERR "FTP PERSISTENT, skipping login\n";}
if ($NODATEDIR < 1)
{
$ftp->cwd("../");
}
}
else
{
$ftp = Net::FTP->new("$VARFTP_host", Port => $VARFTP_port, Debug => $FTPdb);
$ftp->login("$VARFTP_user","$VARFTP_pass");
$ftp->cwd("$VARFTP_dir");
}
if ($NODATEDIR < 1)
{
$ftp->mkdir("$start_date");
$ftp->cwd("$start_date");
$start_date_PATH = "$start_date/";
}
$ftp->binary();
$ftp->put("$dir2/$ALLfile", "$ALLfile");
if ($FTPvalidate > 0)
{
$FTPfilesize = $ftp->size("$ALLfile");
if($DBX){print STDERR "FTP FILESIZE: $FTPfilesize/$FILEsize1[$i] | $ALLfile\n";}
if ( ($FILEsize1[$i] > 100) && ($FTPfilesize < 100) )
{
print "ERROR! File did not transfer, exiting: $FTPfilesize/$FILEsize1[$i] | $ALLfile\n";
exit;
}
}
if ($FTPpersistent < 1)
{
$ftp->quit;
}
# FTP2 scripts do not alter the URL of the recording
# $stmtA = "UPDATE recording_log set location='$VARHTTP_path/$start_date_PATH$ALLfile' where recording_id='$recording_id';";
# if($DB){print STDERR "\n|$stmtA|\n";}
# $affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
if (!$T)
{
`mv -f "$dir2/$ALLfile" "$PATHDONEmonitor/FTP2/$ALLfile"`;
}
if($DBX){print STDERR "Transfered $transfered_files files\n";}
if ( $transfered_files == $file_limit)
{
if($DBX){print STDERR "Transfer limit of $file_limit reached breaking out of the loop\n";}
last();
}
}
else
{
if($DB){print "ERROR: Could not ping server $VARFTP_host\n";}
}
### END Remote file transfer
### sleep for twenty hundredths of a second to not flood the server with disk activity
usleep(1*200*1000);
}
}
$i++;
}
if ($DB) {print "DONE... EXITING\n\n";}
$dbhA->disconnect();
exit;
@@ -0,0 +1,474 @@
#!/usr/bin/perl
#
# AST_CRON_audio_4_ftp2_FTPSSL.pl
#
# This is a STEP-4 program in the audio archival process
#
# runs every 3 minutes and copies the recording files to an FTPSSL server
#
# ************* IMPORTANT!!!!!!!!!!!!!!!!!!!! ***************************
# THIS SCRIPT REQUIRES THE Net::FTPSSL PERL MODULE TO RUN!!!
# $ cpan
# cpan> install ExtUtils::MakeMaker
# cpan> install IO::Socket::SSL
# cpan> install Net::SSLeay::Handle
# cpan> install Net::FTPSSL
# cpan> quit
#
# MAKE SURE YOU TEST THAT THIS IS WORKING MANUALLY BEFORE PUTTING INTO THE CRONTAB!!!
#
# ************* IMPORTANT!!!!!!!!!!!!!!!!!!!! ***************************
#
# put an entry into the cron of of your asterisk machine to run this script
# every 3 minutes or however often you desire
#
# ### recording mixing/compressing/ftping scripts
##0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_mix.pl
# 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_1_move_VDonly.pl
# 1,4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58 * * * * /usr/share/astguiclient/AST_CRON_audio_2_compress.pl --GSM
# 2,5,8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59 * * * * /usr/share/astguiclient/AST_CRON_audio_3_ftp.pl --GSM
# 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /usr/share/astguiclient/AST_CRON_audio_4_ftp2_FTPSSL.pl
#
# FLAG FOR NO DATE DIRECTORY ON FTP
# --NODATEDIR
#
# if pinging is not working, try the 'icmp' Ping command in the code instead
#
# make sure that the following directories exist:
# /var/spool/asterisk/monitorDONE # where the mixed -all files are put
#
# This program assumes that recordings are saved by Asterisk as .wav
#
# Copyright (C) 2015 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGES:
# 130730-1849 - First Build based upon AST_CRON_audio_4_ftp2.pl script
#
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
$FTPdate = "$year-$mon-$mday";
$GSM=0; $MP3=0; $OGG=0; $WAV=0; $GSW=0; $NODATEDIR=0;
# Default variables for FTP
$VARFTP_host = '10.0.0.4';
$VARFTP_user = 'cron';
$VARFTP_pass = 'test';
$VARFTP_port = '21';
$VARFTP_dir = 'RECORDINGS';
$VARHTTP_path = 'http://10.0.0.4';
$file_limit = 1000;
$list_limit = 1000;
$FTPpersistent=0;
$FTPvalidate=0;
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [--help] = this screen\n";
print " [--debug] = debug\n";
print " [--debugX] = super debug\n";
print " [--test] = test\n";
print " [--run-check] = concurrency check, die if another instance is running\n";
print " [--transfer-limit=XXX] = number of files to transfer before exiting\n";
print " [--list-limit=XXX] = number of files to list in the directory before moving on\n";
print " [--debugX] = super debug\n";
print " [--nodatedir] = do not put into dated directories\n";
print " [--ftp-server=XXX] = FTPSSL server\n";
print " [--ftp-port=XXX] = FTPSSL server port\n";
print " [--ftp-login=XXX] = FTPSSL server login account\n";
print " [--ftp-pass=XXX] = FTPSSL server password\n";
print " [--ftp-dir=XXX] = FTPSSL server directory\n";
print " [--ftp-encrypt=X] = FTPSSL encryption type, E=Explicit, I=Implicit, default=E\n";
print " [--ftp-persistent] = Does not log out between every file transmission\n";
# print " [--ftp-validate] = Checks for a file size on the file after transmission\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1;
print "\n----- DEBUG -----\n\n";
}
if ($args =~ /--debugX/i)
{
$DBX=1;
print "\n----- SUPER DEBUG -----\n\n";
}
if ($args =~ /--test/i)
{
$T=1; $TEST=1;
print "\n----- TESTING -----\n\n";
}
if ($args =~ /--nodatedir/i)
{
$NODATEDIR=1;
if ($DB) {print "\n----- NO DATE DIRECTORIES -----\n\n";}
}
if ($args =~ /--run-check/i)
{
$run_check=1;
if ($DB) {print "\n----- CONCURRENCY CHECK -----\n\n";}
}
if ($args =~ /--transfer-limit=/i)
{
my @data_in = split(/--transfer-limit=/,$args);
$file_limit = $data_in[1];
$file_limit =~ s/ .*//gi;
print "\n----- FILE TRANSFER LIMIT: $file_limit -----\n\n";
}
if ($args =~ /--list-limit=/i)
{
my @data_in = split(/--list-limit=/,$args);
$list_limit = $data_in[1];
$list_limit =~ s/ .*//gi;
print "\n----- FILE LIST LIMIT: $list_limit -----\n\n";
}
if ($args =~ /--ftp-server=/i)
{
my @data_in = split(/--ftp-server=/,$args);
$VARFTP_host = $data_in[1];
$VARFTP_host =~ s/ .*//gi;
$CLIFTP_host=1;
if ($DB > 0)
{print "\n----- FTPSSL SERVER: $VARFTP_host -----\n\n";}
}
if ($args =~ /--ftp-port=/i)
{
my @data_in = split(/--ftp-port=/,$args);
$VARFTP_port = $data_in[1];
$VARFTP_port =~ s/ .*//gi;
$CLIFTP_port=1;
if ($DB > 0)
{print "\n----- FTPSSL PORT: $VARFTP_port -----\n\n";}
}
if ($args =~ /--ftp-login=/i)
{
my @data_in = split(/--ftp-login=/,$args);
$VARFTP_user = $data_in[1];
$VARFTP_user =~ s/ .*//gi;
$CLIFTP_user=1;
if ($DB > 0)
{print "\n----- FTPSSL LOGIN: $VARFTP_user -----\n\n";}
}
if ($args =~ /--ftp-pass=/i)
{
my @data_in = split(/--ftp-pass=/,$args);
$VARFTP_pass = $data_in[1];
$VARFTP_pass =~ s/ .*//gi;
$CLIFTP_pass=1;
if ($DB > 0)
{print "\n----- FTPSSL PASS: $VARFTP_pass -----\n\n";}
}
if ($args =~ /--ftp-dir=/i)
{
my @data_in = split(/--ftp-dir=/,$args);
$VARFTP_dir = $data_in[1];
$VARFTP_dir =~ s/ .*//gi;
$CLIFTP_dir=1;
if ($DB > 0)
{print "\n----- FTPSSL DIRECTORY: $VARFTP_dir -----\n\n";}
}
if ($args =~ /--ftp-encrypt=/i)
{
my @data_in = split(/--ftp-encrypt=/,$args);
$VARFTP_encrypt = $data_in[1];
$VARFTP_encrypt =~ s/ .*//gi;
if ($VARFTP_encrypt =~ /E/) {$VARFTP_encrypt = 'EXP_CRYPT';}
if ($VARFTP_encrypt =~ /I/) {$VARFTP_encrypt = 'IMP_CRYPT';}
if (length($VARFTP_encrypt)<5) {$VARFTP_encrypt = 'EXP_CRYPT';}
$CLIFTP_encrypt=1;
if ($DB > 0)
{print "\n----- FTPSSL ENCRYPTION: $VARFTP_encrypt -----\n\n";}
}
if ($args =~ /--ftp-persistent/i)
{
$FTPpersistent=1;
if ($DB > 0)
{print "\n----- FTPSSL PERSISTENT: $FTPpersistent -----\n\n";}
}
# if ($args =~ /--ftp-validate/i)
# {
# $FTPvalidate=1;
# if ($DB > 0)
# {print "\n----- FTPSSL VALIDATE: $FTPvalidate -----\n\n";}
# }
}
}
else
{
#print "no command line options set\n";
$WAV=1;
}
if (length($VARFTP_encrypt)<5) {$VARFTP_encrypt = 'EXP_CRYPT';}
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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 =~ /^PATHDONEmonitor/) && ($CLIDONEmonitor < 1) )
{$PATHDONEmonitor = $line; $PATHDONEmonitor =~ 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;}
if ( ($line =~ /^VARFTP_host/) && ($CLIFTP_host < 1) )
{$VARFTP_host = $line; $VARFTP_host =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_user/) && ($CLIFTP_user < 1) )
{$VARFTP_user = $line; $VARFTP_user =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_pass/) && ($CLIFTP_pass < 1) )
{$VARFTP_pass = $line; $VARFTP_pass =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_port/) && ($CLIFTP_port < 1) )
{$VARFTP_port = $line; $VARFTP_port =~ s/.*=//gi;}
if ( ($line =~ /^VARFTP_dir/) && ($CLIFTP_dir < 1) )
{$VARFTP_dir = $line; $VARFTP_dir =~ s/.*=//gi;}
if ( ($line =~ /^VARHTTP_path/) && ($CLIHTTP_path < 1) )
{$VARHTTP_path = $line; $VARHTTP_path =~ s/.*=//gi;}
$i++;
}
### concurrency check
if ($run_check > 0)
{
my $grepout = `/bin/ps ax | grep $0 | grep -v grep | grep -v '/bin/sh'`;
my $grepnum=0;
$grepnum++ while ($grepout =~ m/\n/g);
if ($grepnum > 1)
{
if ($DB) {print "I am not alone! Another $0 is running! Exiting...\n";}
exit;
}
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$VARDB_port) {$VARDB_port='3306';}
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
use Net::Ping;
use Net::FTPSSL;
### directory where -all recordings are
$dir2 = "$PATHDONEmonitor/FTP";
opendir(FILE, "$dir2/");
@FILES = readdir(FILE);
### Loop through files first to gather filesizes
$i=0;
$files_that_count=0;
foreach(@FILES)
{
$FILEsize1[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir2/$FILES[$i]") )
{
$FILEsize1[$i] = (-s "$dir2/$FILES[$i]");
if ($DBX) {print "$dir2/$FILES[$i] $FILEsize1[$i]\n";}
$files_that_count++;
}
$i++;
if ($files_that_count >= $list_limit)
{
last();
}
}
sleep(5);
$transfered_files = 0;
### Loop through files a second time to gather filesizes again 5 seconds later
$i=0;
foreach(@FILES)
{
$FILEsize2[$i] = 0;
if ( (length($FILES[$i]) > 4) && (!-d "$dir2/$FILES[$i]") )
{
$FILEsize2[$i] = (-s "$dir2/$FILES[$i]");
if ($DBX) {print "$dir2/$FILES[$i] $FILEsize2[$i]\n\n";}
if ($FILEsize1[$i] ne $FILEsize2[$i])
{
if ($DBX) {print "not transfering $dir2/$FILES[$i]. File size mismatch $FILEsize2[$i] != $FILEsize1[$i]\n\n";}
}
if ( ($FILES[$i] !~ /out\.|in\.|lost\+found/i) && ($FILEsize1[$i] eq $FILEsize2[$i]) && (length($FILES[$i]) > 4))
{
$recording_id='';
$ALLfile = $FILES[$i];
$SQLFILE = $FILES[$i];
$SQLFILE =~ s/\.gpg//gi;
$SQLFILE =~ s/-all\.wav|-all\.gsm|-all\.ogg|-all\.mp3//gi;
$stmtA = "select recording_id,start_time from recording_log where filename='$SQLFILE' order by recording_id desc LIMIT 1;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$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;
$recording_id = $aryA[0];
$start_date = $aryA[1];
$start_date =~ s/ .*//gi;
}
$sthA->finish();
if (length($start_date) < 6)
{$start_date = $FTPdate;}
if ($DB) {print "|$recording_id|$start_date|$ALLfile| |$SQLfile|\n";}
### BEGIN Remote file transfer
if ( ($FTPpersistent > 0) && ($ping_good > 0) )
{$ping_good=1;}
else
{
$p = Net::Ping->new();
$ping_good = $p->ping("$VARFTP_host");
}
if (!$ping_good)
{
$p = Net::Ping->new("icmp");
$ping_good = $p->ping("$VARFTP_host");
}
if ($ping_good)
{
$transfered_files++;
$start_date_PATH='';
$FTPdb=0;
if ($DBX>0) {$FTPdb=1;}
if ( ($FTPpersistent > 0) && ($transfered_files > 1) )
{
if($DBX){print STDERR "FTPSSL PERSISTENT, skipping login\n";}
if ($NODATEDIR < 1)
{
$ftps->cwd("../");
}
}
else
{
# Some versions of the FTPSSL perl module require you to hard code the encryption value: IMP_CRYPT or EXP_CRYPT
$ftps = Net::FTPSSL->new("$VARFTP_host", Port => $VARFTP_port, Encryption => $VARFTP_encrypt, Debug => $FTPdb);
$ftps->login("$VARFTP_user","$VARFTP_pass");
$ftps->cwd("$VARFTP_dir");
}
if ($NODATEDIR < 1)
{
$ftps->Net::FTPSSL::mkdir("$start_date");
$ftps->cwd("$start_date");
$start_date_PATH = "$start_date/";
}
$ftps->binary();
$ftps->put("$dir2/$ALLfile", "$ALLfile");
# if ($FTPvalidate > 0)
# {
# $FTPfilesize = $ftps->size("$ALLfile");
# if($DBX){print STDERR "FTP FILESIZE: $FTPfilesize/$FILEsize1[$i] | $ALLfile\n";}
# if ( ($FILEsize1[$i] > 100) && ($FTPfilesize < 100) )
# {
# print "ERROR! File did not transfer, exiting: $FTPfilesize/$FILEsize1[$i] | $ALLfile\n";
# exit;
# }
# }
if ($FTPpersistent < 1)
{
$ftps->quit;
}
# FTP2 scripts do not alter the URL of the recording
# $stmtA = "UPDATE recording_log set location='$VARHTTP_path/$start_date_PATH$ALLfile' where recording_id='$recording_id';";
# if($DB){print STDERR "\n|$stmtA|\n";}
# $affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
if (!$T)
{
`mv -f "$dir2/$ALLfile" "$PATHDONEmonitor/FTP2/$ALLfile"`;
}
if($DBX){print STDERR "Transfered $transfered_files files\n";}
if ( $transfered_files == $file_limit)
{
if($DBX){print STDERR "Transfer limit of $file_limit reached breaking out of the loop\n";}
last();
}
}
else
{
if($DB){print "ERROR: Could not ping server $VARFTP_host\n";}
}
### END Remote file transfer
### sleep for twenty hundredths of a second to not flood the server with disk activity
usleep(1*200*1000);
}
}
$i++;
}
if ($DB) {print "DONE... EXITING\n\n";}
$dbhA->disconnect();
exit;
@@ -0,0 +1,193 @@
#!/usr/bin/perl
#
# AST_CRON_purge_recordings.pl version 2.0.5
#
# IMPORTANT!!! used to delete recordings!!!
#
# runs every day, goes through recordings older than a certain number of days
# and deletes those recordings that are not of a certain status
# default is 30 days old to remove non-sales
#
# put an entry into the cron of of your asterisk machine to run this script
# every day or however often you desire
#
# This program assumes that recordings are saved as .wav
# should be easy to change this code if you use .gsm instead
#
# Copyright (C) 2008 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
#
# 70917-1339 - first build
#
$save_statuses = '|SALE|UPSALE|UPSELL|XFER|DNC|DROP|A1|A2|A3|A4|A5|A6|A7|A8|A9|';
$suffix = '-all.wav';
$local_DIR = '/home2/cron/RECORDINGS';
$use_date_DIRs = 1;
# Customize variables for FTP
$FTP_host = '10.0.0.4';
$FTP_user = 'cron';
$FTP_pass = 'test';
$FTP_dir = 'RECORDINGS';
$HTTP_path = 'http://10.0.0.4';
$secX = time();
$TDtarget = ($secX - 2592000); # thirty days
($Tsec,$Tmin,$Thour,$Tmday,$Tmon,$Tyear,$Twday,$Tyday,$Tisdst) = localtime($TDtarget);
$Tyear = ($Tyear + 1900);
$Tmon++;
if ($Tmon < 10) {$Tmon = "0$Tmon";}
if ($Tmday < 10) {$Tmday = "0$Tmday";}
if ($Thour < 10) {$Thour = "0$Thour";}
if ($Tmin < 10) {$Tmin = "0$Tmin";}
if ($Tsec < 10) {$Tsec = "0$Tsec";}
$TDSQLdate = "$Tyear-$Tmon-$Tmday $Thour:$Tmin:$Tsec";
$FDtarget = ($secX - 3456000); # forty-five days
($Fsec,$Fmin,$Fhour,$Fmday,$Fmon,$Fyear,$Fwday,$Fyday,$Fisdst) = localtime($FDtarget);
$Fyear = ($Fyear + 1900);
$Fmon++;
if ($Fmon < 10) {$Fmon = "0$Fmon";}
if ($Fmday < 10) {$Fmday = "0$Fmday";}
if ($Fhour < 10) {$Fhour = "0$Fhour";}
if ($Fmin < 10) {$Fmin = "0$Fmin";}
if ($Fsec < 10) {$Fsec = "0$Fsec";}
$FDSQLdate = "$Fyear-$Fmon-$Fmday $Fhour:$Fmin:$Fsec";
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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++;
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$VARDB_port) {$VARDB_port='3306';}
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### directory where in/out recordings are saved to by Asterisk
$dir1 = "$PATHmonitor";
##### Get the lead_ids of all recordings that are not DELETED or NULL #####
$stmtA = "SELECT lead_id,recording_id,start_time,filename,location FROM recording_log where start_time < '$TDSQLdate' and start_time > '$FDSQLdate' and location IS NOT NULL and location NOT IN('','NOT_FOUND','NOT_FOUND_2','DELETED') LIMIT 5000;";
print "$stmtA\n";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$i=0;
while ($sthArows > $i)
{
@aryA = $sthA->fetchrow_array;
$lead_ids[$i] = "$aryA[0]";
$recording_ids[$i] = "$aryA[1]";
$start_times[$i] = "$aryA[2]";
$filenames[$i] = "$aryA[3]";
$locations[$i] = "$aryA[4]";
$i++;
}
$sthA->finish();
##### Go through list of leads and find all of their statuses #####
$i=0;
foreach(@lead_ids)
{
### Grab status of the lead in the vicidial_list table
$stmtA = "SELECT status FROM vicidial_list where lead_id='$lead_ids[$i]';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$h=0;
while ($sthArows > $h)
{
@aryA = $sthA->fetchrow_array;
$statuses[$i] = "$aryA[0]";
$h++;
}
$sthA->finish();
$i++;
}
##### Go through list of leads and delete all recordings with no-save statuses #####
$i=0;
$KEEP=0;
$DELETE=0;
foreach(@lead_ids)
{
if ( ($save_statuses !~ /\|$statuses[$i]\|/) && (length($statuses[$i])>0) )
{
if ($use_date_DIRs)
{
$date_DIR = $start_times[$i];
$date_DIR =~ s/ .*//gi;
$date_DIR .= "/";
}
else {$date_DIR=''}
`rm -f $local_DIR/$date_DIR$filenames[$i]$suffix`;
print "rm -f $local_DIR/$date_DIR$filenames[$i]$suffix |$statuses[$i]|$lead_ids[$i]|\n";
$stmtA = "UPDATE recording_log set location='DELETED' where recording_id='$recording_ids[$i]';";
$affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
$DELETE++;
}
else
{
print "KEEP- $filenames[$i]$suffix |$statuses[$i]|$lead_ids[$i]|\n";
$KEEP++;
}
$i++;
}
print "KEEP: $KEEP\n";
print "DELETED: $DELETE\n";
print "--------------------\n";
print "TOTAL: $i\n";
if ($v) {print "DONE... EXITING\n\n";}
$dbhA->disconnect();
exit;
@@ -0,0 +1,323 @@
#!/usr/bin/perl
#
# AST_DB_DNC_filter.pl version 2.12
#
# DESCRIPTION:
# OPTIONAL!!!
# - runs several filters on numbers in the DNC lists and reports results with an
# option to delete filtered numbers, like few digits, too many digits,
# invalid phone numbers, etc...
#
# It is recommended that you run this program on the local Asterisk machine
#
# Copyright (C) 2015 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGES
# 151004-0826 - first build
# 151004-2225 - Added --remove-nondigits and --protect-areacodes options
#
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [--without-campaign-dnc] = will skip analyzing the campaign dnc lists\n";
print " [--campaign-dnc-only=X] = will only run on one campaign DNC list\n";
print " [--remove-x-or-less=X] = remove phone numbers in the dnc list that are X digits or less <=\n";
print " [--remove-x-or-more=X] = remove phone numbers in the dnc list that are X digits or more >=\n";
print " [--remove-nondigits] = remove phone numbers that have non-digits in them\n";
print " [--protect-areacodes] = protect areacode entries with wildcards from being deleted\n";
print " [--test] = test\n";
print " [--quiet] = quiet\n";
print " [--debug] = verbose debug messages\n";
print " [--debugX] = extra verbose debug messages\n\n";
exit;
}
else
{
if ($args =~ /--quiet/i)
{
$Q=1;
}
if ($args =~ /--without-campaign-dnc/i)
{
$without_campaign_dnc=1;
}
if ($args =~ /--campaign-dnc-only=/i)
{
# print "\n|$ARGS|\n\n";
@data_in = split(/--campaign-dnc-only=/,$args);
$CLIcampaign = $data_in[1];
$CLIcampaign =~ s/ .*$//gi;
if ($CLIcampaign =~ /---/)
{
$CLIcampaign =~ s/---/','/gi;
}
if ($DB > 0) {print "\n-----CAMPAIGN DNC ONLY: $CLIcampaign -----\n\n";}
}
else
{$CLIcampaign = '';}
if ($args =~ /--remove-x-or-less=/i)
{
# print "\n|$ARGS|\n\n";
@data_in = split(/--remove-x-or-less=/,$args);
$CLIremoveless = $data_in[1];
$CLIremoveless =~ s/ .*$//gi;
$CLIremoveless =~ s/\D//gi;
if ($DB > 0) {print "\n-----REMOVE X DIGITS OR LESS: $CLIremoveless -----\n\n";}
}
else
{$CLIremoveless = '';}
if ($args =~ /--remove-x-or-more=/i)
{
# print "\n|$ARGS|\n\n";
@data_in = split(/--remove-x-or-more=/,$args);
$CLIremovemore = $data_in[1];
$CLIremovemore =~ s/ .*$//gi;
$CLIremovemore =~ s/\D//gi;
if ($DB > 0) {print "\n-----REMOVE X DIGITS OR MORE: $CLIremovemore -----\n\n";}
}
else
{$CLIremovemore = '';}
if ($args =~ /--remove-nondigits/i)
{
$remove_nondigits=1;
}
if ($args =~ /--protect-areacodes/i)
{
$protect_areacodes=1;
}
if ($args =~ /--debug/i)
{
$DB=1; # Debug flag, set to 0 for no debug messages, On an active system this will generate hundreds of lines of output per minute
}
if ($args =~ /--debugX/i)
{
$DBX=1; # Debug flag, set to 0 for no debug messages, On an active system this will generate hundreds of lines of output per minute
}
if ($args =~ /--test/i)
{
$TEST=1;
$T=1;
}
}
}
else
{
print "no command line options set, exiting...\n";
exit;
}
### end parsing run-time options ###
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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++;
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$VARDB_port) {$VARDB_port='3306';}
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$deleted=0;
$MT[0]='';
### find stats on dnc lists
$stmtA = "SELECT count(*) from vicidial_dnc;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsDNC=$sthA->rows;
if ($sthArowsDNC > 0)
{
@aryA = $sthA->fetchrow_array;
$DNCcount = $aryA[0];
}
$sthA->finish();
if($DB){print "\nTotal System Internal DNC entries: |$DNCcount|\n";}
if($DB){print "\n";}
if($DB){print "Total Campaign DNC entries:\n";}
$stmtA = "SELECT count(*),campaign_id from vicidial_campaign_dnc group by campaign_id order by campaign_id;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsCDNC=$sthA->rows;
$rec_count=0;
while ($sthArowsCDNC > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$aryA[0] = sprintf("%10s", $aryA[0]);
$aryA[1] = sprintf("%10s", $aryA[1]);
if($DB){print "$aryA[1]: $aryA[0]\n";}
$rec_count++;
}
$sthA->finish();
if ( (length($CLIremoveless)>0) or (length($CLIremovemore)>0) or ($remove_nondigits > 0) )
{
$removelessSQL='';
$removemoreSQL='';
$remove_nondigitsSQL='';
$protect_areacodesSQL='';
if (length($CLIremoveless)>0)
{$removelessSQL="(char_length(phone_number) <= $CLIremoveless)";}
if (length($CLIremovemore)>0)
{
if (length($removelessSQL) > 1)
{$removemoreSQL = 'or ';}
$removemoreSQL .= "(char_length(phone_number) >= $CLIremovemore)";
}
if ($remove_nondigits > 0)
{
if ( (length($removelessSQL) > 1) or (length($removemoreSQL) > 1) )
{$remove_nondigitsSQL = 'or ';}
$remove_nondigitsSQL .= "( (phone_number LIKE \"% %\") or (phone_number LIKE \"%*%\") or (phone_number LIKE \"%#%\") or (phone_number LIKE \"%a%\") or (phone_number LIKE \"%b%\") or (phone_number LIKE \"%c%\") or (phone_number LIKE \"%d%\") or (phone_number LIKE \"%e%\") or (phone_number LIKE \"%f%\") or (phone_number LIKE \"%g%\") or (phone_number LIKE \"%h%\") or (phone_number LIKE \"%i%\") or (phone_number LIKE \"%j%\") or (phone_number LIKE \"%k%\") or (phone_number LIKE \"%l%\") or (phone_number LIKE \"%m%\") or (phone_number LIKE \"%n%\") or (phone_number LIKE \"%o%\") or (phone_number LIKE \"%p%\") or (phone_number LIKE \"%q%\") or (phone_number LIKE \"%r%\") or (phone_number LIKE \"%s%\") or (phone_number LIKE \"%t%\") or (phone_number LIKE \"%u%\") or (phone_number LIKE \"%v%\") or (phone_number LIKE \"%q%\") or (phone_number LIKE \"%x%\") or (phone_number LIKE \"%y%\") or (phone_number LIKE \"%z%\") or (phone_number LIKE \"%.%\") or (phone_number LIKE \"%,%\") )";
}
if ($protect_areacodes > 0)
{
if ( (length($removelessSQL) > 1) or (length($removemoreSQL) > 1) or (length($remove_nondigitsSQL) > 1) )
{$protect_areacodesSQL = "and (phone_number NOT LIKE \"%XXXXXXX\")";}
}
if (length($CLIcampaign)<1)
{
##### BEGIN system internal DNC filter #####
$stmtA = "SELECT phone_number from vicidial_dnc where $removelessSQL $removemoreSQL $remove_nondigitsSQL $protect_areacodesSQL limit 100000000;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsCT=$sthA->rows;
if($DB){print "|$sthArowsCT|$stmtA|\n";}
$rec_count=0;
while ($sthArowsCT > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$phone_numbers[$rec_count] = $aryA[0];
$rec_count++;
}
$sthA->finish();
$rec_count=0;
while ($sthArowsCT > $rec_count)
{
$affected_rows=0;
$affected_rowsA=0;
$stmtA = "DELETE from vicidial_dnc where phone_number='$phone_numbers[$rec_count]';";
if (!$T) {$affected_rows = $dbhA->do($stmtA);}
if($DBX){print STDERR "\n|$affected_rows deleted| |$stmtA|\n";}
$deleted++;
if ($affected_rows > 0)
{
$stmtA="INSERT INTO vicidial_dnc_log SET phone_number='$phone_numbers[$rec_count]', campaign_id='-SYSINT-', action='delete', action_date=NOW(), user='CLIFLTR';";
if (!$T) {$affected_rowsA = $dbhA->do($stmtA);}
if($DBX){print STDERR "\n|$affected_rowsA log| |$stmtA|\n";}
}
$rec_count++;
}
##### END system internal DNC filter #####
}
if ( (length($CLIcampaign) > 0) or ($without_campaign_dnc < 1) )
{
$CLIcampaignSQL='';
if (length($CLIcampaign) > 0)
{$CLIcampaignSQL = "and campaign_id IN('$CLIcampaign')";}
##### BEGIN campaign DNC filter #####
$stmtA = "SELECT phone_number,campaign_id from vicidial_campaign_dnc where $removelessSQL $removemoreSQL $remove_nondigitsSQL $protect_areacodesSQL $CLIcampaignSQL limit 100000000;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsCT=$sthA->rows;
if($DB){print "|$sthArowsCT|$stmtA|\n";}
$rec_count=0;
while ($sthArowsCT > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$Cphone_numbers[$rec_count] = $aryA[0];
$Ccampaigns[$rec_count] = $aryA[1];
$rec_count++;
}
$sthA->finish();
$rec_count=0;
while ($sthArowsCT > $rec_count)
{
$affected_rows=0;
$affected_rowsA=0;
$stmtA = "DELETE from vicidial_campaign_dnc where phone_number='$Cphone_numbers[$rec_count]' and campaign_id='$Ccampaigns[$rec_count]';";
if (!$T) {$affected_rows = $dbhA->do($stmtA);}
if($DBX){print STDERR "\n|$affected_rows deleted| |$stmtA|\n";}
$deleted++;
if ($affected_rows > 0)
{
$stmtA="INSERT INTO vicidial_dnc_log SET phone_number='$Cphone_numbers[$rec_count]', campaign_id='$Ccampaigns[$rec_count]', action='delete', action_date=NOW(), user='CLIFLTR';";
if (!$T) {$affected_rowsA = $dbhA->do($stmtA);}
if($DBX){print STDERR "\n|$affected_rowsA log| |$stmtA|\n";}
}
$rec_count++;
}
##### END campaign DNC filter #####
}
}
else
{
if($DB>0){print "\n no dnc filter set: |$CLIremoveless|$CLIremovemore|\n\n";}
}
exit;
@@ -0,0 +1,196 @@
#!/usr/bin/perl
#
# AST_DB_action.pl version 2.10
#
# DESCRIPTION:
# OPTIONAL!!! CUSTOMIZE THIS SCRIPT FIRST!!!
# - executes an SQL query
# - writes to the vicidial_admin_log with number of affected records
#
#
# Copyright (C) 2014 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGES
# 140729 - first build
#
$start_time=time();
$DB=0;
$T=0;
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [--test] = test\n";
print " [--debug] = verbose debug messages\n";
print " [--debugX] = extra verbose debug messages\n";
print " [--list-id=XXX] = list that you can use in SQL, double-dash-delimited if more than one: 111--222\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1; # Debug flag
}
if ($args =~ /--debugX/i)
{
$DBX=1; # Extra Debug flag
}
if ($args =~ /--test/i)
{
$TEST=1;
$T=1;
}
if ($args =~ /--list-id=/i)
{
@data_in = split(/--list-id=/,$args);
$list_id = $data_in[1];
$list_id =~ s/ .*//gi;
if ($list_id =~ /---ALL---/)
{
$list_idSQL = '';
$list_idSQLand = '';
$list_idIN = '';
}
else
{
if ($list_id =~ /--/)
{
$list_idTEMP = $list_id;
$list_idTEMP =~ s/--/','/gi;
$list_idIN = "$list_idTEMP";
$list_idSQL = "where list_id IN('$list_idTEMP')";
$list_idSQLand = "where list_id IN('$list_idTEMP') and";
}
else
{
$list_idIN = "$list_id";
$list_idSQL = "where list_id='$list_id'";
$list_idSQLand = "where list_id='$list_id' and";
}
}
if ($DB > 0) {print "\n----- LIST ID: $list_id ($list_idSQL) -----\n\n";}
}
}
}
else
{
# print "no command line options set\n";
}
### end parsing run-time options ###
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <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++;
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
if (!$VARDB_port) {$VARDB_port='3306';}
$secX = time();
$XDtarget = ($secX - 2678400);
($Xsec,$Xmin,$Xhour,$Xmday,$Xmon,$Xyear,$Xwday,$Xyday,$Xisdst) = localtime($XDtarget);
$Xyear = ($Xyear + 1900);
$Xmon++;
if ($Xmon < 10) {$Xmon = "0$Xmon";}
if ($Xmday < 10) {$Xmday = "0$Xmday";}
if ($Xhour < 10) {$Xhour = "0$Xhour";}
if ($Xmin < 10) {$Xmin = "0$Xmin";}
if ($Xsec < 10) {$Xsec = "0$Xsec";}
$XDSQLdate = "$Xyear-$Xmon-$Xmday $Xhour:$Xmin:$Xsec";
$TDtarget = ($secX - 5356800);
($Tsec,$Tmin,$Thour,$Tmday,$Tmon,$Tyear,$Twday,$Tyday,$Tisdst) = localtime($TDtarget);
$Tyear = ($Tyear + 1900);
$Tmon++;
if ($Tmon < 10) {$Tmon = "0$Tmon";}
if ($Tmday < 10) {$Tmday = "0$Tmday";}
if ($Thour < 10) {$Thour = "0$Thour";}
if ($Tmin < 10) {$Tmin = "0$Tmin";}
if ($Tsec < 10) {$Tsec = "0$Tsec";}
$TDSQLdate = "$Tyear-$Tmon-$Tmday $Thour:$Tmin:$Tsec";
use DBI;
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$affected_rows=0;
$stmtA = "UPDATE vicidial_list set called_since_last_reset='N',rank=90 where list_id IN('$list_idIN') and called_count < 1;";
if($DB){print STDERR "\n|$stmtA|\n";}
if ($T < 1)
{
$affected_rows = $dbhA->do($stmtA);
if($DB){print STDERR "\n|$affected_rows records changed|\n";}
}
else
{$affected_rows='TEST';}
$end_time=time();
$SQLlog = $stmtA;
$SQLlog =~ s/\'|\"|\\|\///gi;
$stmtA="INSERT INTO vicidial_admin_log set event_date=NOW(), user='VDAD', ip_address='1.1.1.1', event_section='SERVERS', event_type='OTHER', record_id='$server_ip', event_code='DB_ACTION', event_sql='$SQLlog', event_notes='Affected rows: $affected_rows TOTAL Elapsed time: ".($end_time-$start_time)." sec |$args|';";
$Iaffected_rows = $dbhA->do($stmtA);
if ($DBX) {print "Admin logged: |$Iaffected_rows|$stmtA|\n";}
if ($DB) {print "TOTAL Elapsed time: ".($end_time-$start_time)." sec\n\n";}
$dbhA->disconnect();
exit;

Some files were not shown because too many files have changed in this diff Show More