From 7c00875818b0b2ce8c497a88e9d4a97ac7a415ff Mon Sep 17 00:00:00 2001 From: mattf Date: Thu, 21 Sep 2017 12:28:02 +0000 Subject: [PATCH] Added option for Auto-inactive of expired lists Fixed issue with using CALLID at beginning of recording filename Added partial experimantal Asterisk 13 compatibility git-svn-id: svn://192.168.202.10@2817 3d104415-ff17-0410-8863-d5cf3c621b8a --- UPGRADE | 6 + agi/agi-VDAD_ALL_inbound.agi | 10 +- agi/agi-VDAD_local_optimize.agi | 240 +++ bin/ADMIN_keepalive_ALL.pl | 335 ++-- bin/AST_VDauto_dial.pl | 56 +- bin/AST_VDauto_dial_FILL.pl | 81 +- bin/AST_conf_update.pl | 148 +- bin/AST_manager_listen.pl | 13 +- bin/AST_manager_listenBUFFER.pl | 9 +- bin/AST_manager_listen_AMI2.pl | 1007 +++++++++++ bin/AST_manager_send.pl | 9 +- bin/AST_update_AMI2.pl | 1652 ++++++++++++++++++ bin/FastAGI_log.pl | 144 +- docs/AGENT_MONITOR.txt | 5 +- docs/ASTERISK_13.txt | 115 ++ docs/REQUIRED_APPS_INSTALL.txt | 36 + docs/conf_examples/extensions.conf.sample-13 | 684 ++++++++ docs/conf_examples/manager.conf.sample-13 | 38 + extras/MySQL_AST_CREATE_tables.sql | 5 +- extras/upgrade_2.14.sql | 4 + install.pl | 27 +- www/agc/images/folder_closed.png | Bin 0 -> 1846 bytes www/agc/images/folder_open.png | Bin 0 -> 2589 bytes www/agc/images/lastnode.png | Bin 0 -> 144 bytes www/agc/images/node.png | Bin 0 -> 145 bytes www/agc/images/vline.png | Bin 0 -> 123 bytes www/agc/simpletreemenu.js | 133 ++ www/vicidial/admin.php | 49 +- www/vicidial/help.php | 6 + 29 files changed, 4545 insertions(+), 267 deletions(-) create mode 100644 agi/agi-VDAD_local_optimize.agi create mode 100644 bin/AST_manager_listen_AMI2.pl create mode 100644 bin/AST_update_AMI2.pl create mode 100644 docs/ASTERISK_13.txt create mode 100644 docs/conf_examples/extensions.conf.sample-13 create mode 100644 docs/conf_examples/manager.conf.sample-13 create mode 100644 www/agc/images/folder_closed.png create mode 100644 www/agc/images/folder_open.png create mode 100644 www/agc/images/lastnode.png create mode 100644 www/agc/images/node.png create mode 100644 www/agc/images/vline.png create mode 100644 www/agc/simpletreemenu.js diff --git a/UPGRADE b/UPGRADE index 5789da66..3d0f2612 100644 --- a/UPGRADE +++ b/UPGRADE @@ -194,6 +194,12 @@ OTHER CHANGES: 46. Added Agent Inbound Status Summary Report +47. Added experimental support for Asterisk 13. See the ASTERISK_13.txt doc + for notes on changes needed to get it to work. + +48. Added System Settings option to set lists to inactive once they pass their + expiration date + diff --git a/agi/agi-VDAD_ALL_inbound.agi b/agi/agi-VDAD_ALL_inbound.agi index dfa19b56..ca04095c 100644 --- a/agi/agi-VDAD_ALL_inbound.agi +++ b/agi/agi-VDAD_ALL_inbound.agi @@ -214,6 +214,7 @@ # 170621-2031 - Added missing list_id in log inserts # 170816-2245 - Added ask survey options # 170903-0929 - Added additional xfer_log details +# 170914-1634 - Added Asterisk 13 compatibility # $script = 'agi-VDAD_ALL_inbound.agi'; @@ -708,7 +709,7 @@ if ($channel =~ /Local/i) ### 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';"; +$stmtA = "SELECT voicemail_dump_exten,ext_context,answer_transfer_agent,local_gmt,asterisk_version,max_vicidial_trunks,voicemail_dump_exten_no_inst,routing_prefix 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; @@ -723,6 +724,7 @@ while ($sthArows > $cbc) $asterisk_version = $aryA[4]; $DBmax_vicidial_trunks = $aryA[5]; $voicemail_dump_exten_no_inst = $aryA[6]; + $routing_prefix = $aryA[7]; 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;} @@ -3223,7 +3225,11 @@ while ( ($drop_timer <= $DROP_TIME) && ($wait_in_queue > 0) && ($MCdrop_override $RAFaffected_rows = $dbhA->do($stmtA); $dbhP=$dbhA; $mysql_count='02167'; $MEL_aff_rows=$RAFaffected_rows; &mysql_error_logging; - $RINGALLexten = "8331*$auto_call_id*$callerid*$ARuser[$ragp]*$ARdialplan_number[$ragp]"; + %ast_ver_str = parse_asterisk_version($asterisk_version); + if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) + { $RINGALLexten = "8331*$auto_call_id*$callerid*$ARuser[$ragp]*$ARdialplan_number[$ragp]"; } + else + { $RINGALLexten = "$routing_prefix" . "8331*$auto_call_id*$callerid*$ARuser[$ragp]*$ARdialplan_number[$ragp]"; } $PADauto_call_id = sprintf("%011s", $auto_call_id); while (length($PADauto_call_id) > 11) {chop($PADauto_call_id);} $RINGALLqueryCID = "RINGAGENT$PADauto_call_id"; diff --git a/agi/agi-VDAD_local_optimize.agi b/agi/agi-VDAD_local_optimize.agi new file mode 100644 index 00000000..84b0b915 --- /dev/null +++ b/agi/agi-VDAD_local_optimize.agi @@ -0,0 +1,240 @@ +#!/usr/bin/perl +# +# agi_VDAD_local_optimize.agi +# +# This script looks up the Local channel in the cid_channels_recent table +# and redirects the actual channel to the current extension with the first +# two digits stripped off. IE 138368 -> 8368. This is to overcome the change +# to Local channels in Asterisk 12 and later. +# +# Copyright (C) 2017 Matt Florell LICENSE: AGPLv2 +# +# CHANGELOG +# 170104-1700 - First build +# 170420-1100 - Indexed call_date and added it to the channel lookup +# + +use strict; + +my $script = 'agi_VDAD_local_optimize.agi'; + +# constants and globals +my ($servConf, $SYSLOG); +my %conf; +$conf{PATHconf} = '/etc/astguiclient.conf'; # default path to astguiclient configuration file: + +# Begin Parsing astguiclient config file. +open(CONF, $conf{PATHconf}) || die "can't open " . $conf{PATHconf} . ": " . $! . "\n"; +while (my $line = ) + { + $line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi; + foreach my $key (qw( PATHhome PATHlogs PATHagi PATHweb PATHsounds PATHmontior + VARserver_ip VARDB_server VARDB_database VARDB_user VARDB_pass VARDB_port)) + { + if ($line =~ /^$key/) + { + $conf{$key} = $line; + $conf{$key} =~ s/.*=//gi; + } + } + } +$conf{VARDB_port} = '3306' unless ($conf{VARDB_port}); + +my ($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";} +my $SQLdate = "$year-$mon-$mday $hour:$min:$sec"; + +my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time - 120); +$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";} +my $SQL2mindate = "$year-$mon-$mday $hour:$min:$sec"; + +use DBI; +use Asterisk::AGI; +use Time::HiRes ('gettimeofday','usleep','sleep'); + +my ($seconds, $microseconds) = gettimeofday; + +print STDERR "$seconds.$microseconds\n"; + +my $AGI = new Asterisk::AGI; + +my $dbhA = DBI->connect("DBI:mysql:" . $conf{VARDB_database} . ":" . $conf{VARDB_server} . ":" . $conf{VARDB_port}, + $conf{VARDB_user}, $conf{VARDB_pass}) or die "Couldn't connect to database: " . DBI->errstr; + + +my %agi_vars = $AGI->ReadParse(); + +my $channel = $agi_vars{'channel'}; +my $cid_name = $agi_vars{'calleridname'}; +my $connected_line_name = $agi_vars{'arg_1'}; +my $extension = $agi_vars{'extension'}; +my $context = $agi_vars{'context'}; +my $uniqueid = $agi_vars{'uniqueid'}; +my $dest_channel = ""; + +my $new_extension = substr( $extension, 2 ); + +# find the local channel's real channel +my $stmtA = "SELECT dest_channel FROM cid_channels_recent where (caller_id_name = '$cid_name' or connected_line_name = '$connected_line_name' or caller_id_name = '$connected_line_name' or connected_line_name = '$cid_name') and ( linkedid = '$uniqueid' or dest_uniqueid = '$uniqueid' or uniqueid = '$uniqueid') and call_date > '$SQL2mindate'"; +my $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + +print STDERR "$stmtA\n"; + +$sthA->execute or die "executing: $stmtA ", $dbhA->errstr; +my $sthArows=$sthA->rows; +if ($sthArows > 0) + { + my @aryA = $sthA->fetchrow_array; + $dest_channel = $aryA[0]; + } +$sthA->finish(); + +if ( $dest_channel ne "" ) + { + print STDERR "$sthArows|$dest_channel\n"; + + ### insert a NEW record to the vicidial_manager table to be processed + $stmtA = "INSERT INTO vicidial_manager values('','','$SQLdate','SENT','N','$conf{VARserver_ip}','','Redirect','$cid_name','Channel: $dest_channel','Context: $context','Exten: $new_extension','Priority: 1','','','','','','')"; + + print STDERR "$stmtA\n"; + + my $affected_rows = $dbhA->do($stmtA); + my $man_id = $dbhA->{'mysql_insertid'}; + + ### Grab Server values from the database + $servConf = getServerConfig($dbhA, $conf{VARserver_ip}); + $SYSLOG = 1 if ($servConf->{vd_server_logs} =~ /Y/); + my $event_string='LOGGED INTO MYSQL SERVER ON 1 CONNECTION|'; + eventLogger($conf{PATHlogs}, 'process', $event_string); + + my $cPATHlogs = $conf{PATHlogs}; + + my $launch = $conf{PATHhome} . "/AST_send_action_child.pl"; + $launch .= " --SYSLOG"; + $launch .= " --PATHlogs=" . $cPATHlogs; + $launch .= " --telnet_host=" . $servConf->{telnet_host}; + $launch .= " --telnet_port=" . $servConf->{telnet_port}; + $launch .= " --ASTmgrUSERNAME=" . $servConf->{ASTmgrUSERNAME}; + $launch .= " --ASTmgrSECRET=" . $servConf->{ASTmgrSECRET}; + $launch .= " --ASTmgrUSERNAMEsend=" . $servConf->{ASTmgrUSERNAMEsend}; + $launch .= " --man_id=" . $man_id; + $launch .= " --action=Redirect"; + $launch .= " --cmd_line_b='Channel: $dest_channel'"; + $launch .= " --cmd_line_c='Context: $context'"; + $launch .= " --cmd_line_d='Exten: $new_extension'"; + $launch .= " --cmd_line_e='Priority: 1'"; + + eventLogger($conf{'PATHlogs'}, 'launch', $launch . " " . + $cid_name . " " . $uniqueid . " " . $dest_channel); + + $launch .= " >> " . $conf{PATHlogs} . "/action_send." . logDate() if ($SYSLOG); + system($launch . ' &'); + + print STDERR "$launch\n"; + + usleep(1*10*1000); + } +else + { + print STDERR "NO DestChannel for callid $cid_name|$agi_vars{'channel'}!!!\n"; + } + + + + +$dbhA->disconnect(); + +exit; + +# getServerConfig usage: +# getServerConfig($dbh, $serverIP); +# Requires: +# $dbh : Database handle to current open DB. +# $serverIP : IP of server to get config for. +# Returns: +# hashref with conents of table entry. +sub getServerConfig + { + my ($dbhA, $serverip) = @_; + my $stmtA = "SELECT server_id,server_description,server_ip,active,asterisk_version,max_vicidial_trunks,telnet_host,telnet_port,ASTmgrUSERNAME,ASTmgrSECRET,ASTmgrUSERNAMEupdate,ASTmgrUSERNAMElisten,ASTmgrUSERNAMEsend,local_gmt,voicemail_dump_exten,answer_transfer_agent,ext_context,sys_perf_log,vd_server_logs,agi_output,vicidial_balance_active,balance_trunks_offlimits,recording_web_link,alt_server_ip,active_asterisk_server,generate_vicidial_conf,rebuild_conf_files,outbound_calls_per_second,sysload,channels_total,cpu_idle_percent,disk_usage,sounds_update,vicidial_recording_limit,carrier_logging_active,vicidial_balance_rank,rebuild_music_on_hold,active_agent_login_server,conf_secret FROM servers where server_ip = '" . $serverip ."';"; + my $sthA = $dbhA->prepare($stmtA) or die "preparing: " . $dbhA->errstr; + $sthA->execute or die "executing: $stmtA " . $dbhA->errstr; + my $servConf = $sthA->fetchrow_hashref; + $SYSLOG = 1 if ($servConf->{vd_server_logs} =~ /Y/); + $sthA->finish(); + return $servConf; + } + +# eventLogger usage: +# eventLgger($LogFileDir, $LogType, $EventString); +# Requires: +# $LogFilePath : Directory where log files are. +# $LogType : Type of log, ie process, send, launch, full +# $EventString : String to record in log. +sub eventLogger + { + my ($path,$type,$string) = @_; + open(LOG, ">>" . $path . "/action_" . $type . "." . logDate()) + || die "Can't open " . $path . "/action_" . $type . "." . + logDate() . ": " . $! . "\n"; + print LOG nowDate() . "|" . $string . "|\n"; + close(LOG); + } + +# logDate usage: +# logDate($SecondsSinceEpoch); +# Options: +# $SecondsSinceEpoch : Request time in seconds, defaults to current date/time. +# Returns: +# scalar date string ie "2007-01-01" +sub logDate + { + my ($tms) = @_; + my($sec,$min,$hour,$mday,$mon,$year) = getTime($tms); + return $year . '-' . $mon . '-' . $mday; + } + +# nowDate usage: +# nowDate($SecondsSinceEpoch); +# Options: +# $SecondsSinceEpoch : Request time in seconds, defaults to current date/time. +# Returns: +# scalar date/time string (MySQL formatted) ie "2007-01-01 00:00:00" +sub nowDate + { + my ($tms) = @_; + my($sec,$min,$hour,$mday,$mon,$year) = getTime($tms); + return $year.'-'.$mon.'-'.$mday.' '.$hour.':'.$min.':'.$sec; + } + +# getTime usage: +# getTime($SecondsSinceEpoch); +# Options: +# $SecondsSinceEpoch : Request time in seconds, defaults to current date/time. +# Returns: +# ($sec, $min, $hour. $day, $mon, $year) +sub getTime + { + my ($tms) = @_; + $tms = time unless ($tms); + my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($tms); + $year += 1900; + $mon++; + $mon = "0" . $mon if ($mon < 10); + $mday = "0" . $mday if ($mday < 10); + $min = "0" . $min if ($min < 10); + $sec = "0" . $sec if ($sec < 10); + return ($sec,$min,$hour,$mday,$mon,$year); + } diff --git a/bin/ADMIN_keepalive_ALL.pl b/bin/ADMIN_keepalive_ALL.pl index a50276f5..0198914e 100644 --- a/bin/ADMIN_keepalive_ALL.pl +++ b/bin/ADMIN_keepalive_ALL.pl @@ -122,9 +122,11 @@ # 170711-0824 - Fixed help documentation for delay seconds, issue #1025 # 170725-0017 - Added vicidial_campaign_hour_counts and vicidial_carrier_hour_counts rolling # 170816-2323 - Added In-Group Ask-Post-Call Survey AGI dialplan entries +# 170916-1009 - Added Asterisk 13 'h' exten for dialplan generation and triggering of AMI2 scripts +# 170920-2214 - Added expired_lists_inactive option, checks once per hour # -$build = '170816-2323'; +$build = '170920-2214'; $DB=0; # Debug flag $teodDB=0; # flag to log Timeclock End of Day processes to log file @@ -150,6 +152,7 @@ if ($min < 10) {$min = "0$min";} if ($sec < 10) {$sec = "0$sec";} $now_date = "$year-$mon-$mday $hour:$min:$sec"; $today_start = "$year-$mon-$mday 00:00:00"; +$today_date = "$year-$mon-$mday"; $reset_test = "$hour$min"; ### calculate the date and time for slightly less than 24 hours ago @@ -322,7 +325,6 @@ else } ### end parsing run-time options ### - # default path to astguiclient configuration file: $PATHconf = '/etc/astguiclient.conf'; @@ -338,8 +340,26 @@ foreach(@conf) {$PATHhome = $line; $PATHhome =~ s/.*=//gi;} if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) ) {$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;} + if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) ) + {$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;} if ( ($line =~ /^VARactive_keepalives/) && ($CLIactive_keepalives < 1) ) {$VARactive_keepalives = $line; $VARactive_keepalives =~ 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;} $i++; } @@ -357,6 +377,73 @@ foreach(@conf) # E - Email parser script # - Other setting are set by configuring them in the database +# Customized Variables +$server_ip = $VARserver_ip; # Asterisk server IP +$THISserver_voicemail=0; +$voicemail_server_id=''; +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; + + +##### Get the settings from system_settings ##### +$stmtA = "SELECT sounds_central_control_active,active_voicemail_server,custom_dialplan_entry,default_codecs,generate_cross_server_exten,voicemail_timezones,default_voicemail_timezone,call_menu_qualify_enabled,allow_voicemail_greeting,reload_timestamp,meetme_enter_login_filename,meetme_enter_leave3way_filename,allow_chats,enable_auto_reports,enable_drop_lists,expired_lists_inactive 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; + $sounds_central_control_active = $aryA[0]; + $active_voicemail_server = $aryA[1]; + $SScustom_dialplan_entry = $aryA[2]; + $SSdefault_codecs = $aryA[3]; + $SSgenerate_cross_server_exten = $aryA[4]; + $SSvoicemail_timezones = $aryA[5]; + $SSdefault_voicemail_timezone = $aryA[6]; + $SScall_menu_qualify_enabled = $aryA[7]; + $SSallow_voicemail_greeting = $aryA[8]; + $SSreload_timestamp = $aryA[9]; + $meetme_enter_login_filename = $aryA[10]; + $meetme_enter_leave3way_filename = $aryA[11]; + $SSallow_chats = $aryA[12]; + $SSenable_auto_reports = $aryA[13]; + $SSenable_drop_lists = $aryA[14]; + $SSexpired_lists_inactive = $aryA[15]; + } +$sthA->finish(); +if ($DBXXX > 0) {print "SYSTEM SETTINGS: $sounds_central_control_active|$active_voicemail_server|$SScustom_dialplan_entry|$SSdefault_codecs\n";} + +##### Get the settings for this server's server_ip ##### +$stmtA = "SELECT active_asterisk_server,generate_vicidial_conf,rebuild_conf_files,asterisk_version,sounds_update,conf_secret,custom_dialplan_entry,auto_restart_asterisk,asterisk_temp_no_restart,gather_asterisk_output,conf_qualify FROM servers where server_ip='$server_ip';"; +# 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; + $active_asterisk_server = $aryA[0]; + $generate_vicidial_conf = $aryA[1]; + $rebuild_conf_files = $aryA[2]; + $asterisk_version = $aryA[3]; + $sounds_update = $aryA[4]; + $self_conf_secret = $aryA[5]; + $SERVERcustom_dialplan_entry = $aryA[6]; + $auto_restart_asterisk = $aryA[7]; + $asterisk_temp_no_restart = $aryA[8]; + $gather_asterisk_output = $aryA[9]; + $conf_qualify = $aryA[10]; + } +$sthA->finish(); + +%ast_ver_str = parse_asterisk_version($asterisk_version); +if ($DBX) {print "Asterisk version: $ast_ver_str{major} $ast_ver_str{minor}\n";} + if ($VARactive_keepalives =~ /X/) { if ($DB) {print "X in active_keepalives, skipping this section...\n";} @@ -473,7 +560,7 @@ else $runningASTERISK++; if ($DB) {print "asterisk RUNNING: |$psoutput[$i]|\n";} } - if ($psline[1] =~ /$REGhome\/AST_update\.pl/) + if ($psline[1] =~ /$REGhome\/AST_update/) { $runningAST_update++; if ($DB) {print "AST_update RUNNING: |$psline[1]|\n";} @@ -630,7 +717,7 @@ else $runningASTERISK++; if ($DB) {print "asterisk RUNNING: |$psoutput2[$i]|\n";} } - if ($psline[1] =~ /$REGhome\/AST_update\.pl/) + if ($psline[1] =~ /$REGhome\/AST_update/) { $runningAST_update++; if ($DB) {print "AST_update RUNNING: |$psline[1]|\n";} @@ -693,7 +780,10 @@ else { if ($DB) {print "starting AST_update...\n";} # add a '-L' to the command below to activate logging - `/usr/bin/screen -d -m -S ASTupdate $PATHhome/AST_update.pl`; + if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} >= 12)) + {`/usr/bin/screen -d -m -S ASTupdate $PATHhome/AST_update_AMI2.pl`;} + else + {`/usr/bin/screen -d -m -S ASTupdate $PATHhome/AST_update.pl`;} } if ( ($AST_send_listen > 0) && ($runningAST_send < 1) ) { @@ -705,10 +795,15 @@ else { if ($DB) {print "starting AST_manager_listen...\n";} # add a '-L' to the command below to activate logging - if ($lstn_buffer > 0) - {`/usr/bin/screen -d -m -S ASTlisten $PATHhome/AST_manager_listenBUFFER.pl`;} + if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} >= 12)) + {`/usr/bin/screen -d -m -S ASTlisten $PATHhome/AST_manager_listen_AMI2.pl`;} else - {`/usr/bin/screen -d -m -S ASTlisten $PATHhome/AST_manager_listen.pl`;} + { + if ($lstn_buffer > 0) + {`/usr/bin/screen -d -m -S ASTlisten $PATHhome/AST_manager_listenBUFFER.pl`;} + else + {`/usr/bin/screen -d -m -S ASTlisten $PATHhome/AST_manager_listen.pl`;} + } } if ( ($AST_VDauto_dial > 0) && ($runningAST_VDauto_dial < 1) ) { @@ -785,80 +880,6 @@ if ($timeclock_auto_logout > 0) ##### tally tables at Timeclock end-of-day ################################################################################ -# default path to astguiclient configuration file: -$PATHconf = '/etc/astguiclient.conf'; - -open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n"; -@conf = ; -close(conf); -$i=0; -foreach(@conf) - { - $line = $conf[$i]; - $line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi; - if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) ) - {$PATHlogs = $line; $PATHlogs =~ 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_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;} - $i++; - } - -# Customized Variables -$server_ip = $VARserver_ip; # Asterisk server IP -$THISserver_voicemail=0; -$voicemail_server_id=''; -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; - - -##### Get the settings from system_settings ##### -$stmtA = "SELECT sounds_central_control_active,active_voicemail_server,custom_dialplan_entry,default_codecs,generate_cross_server_exten,voicemail_timezones,default_voicemail_timezone,call_menu_qualify_enabled,allow_voicemail_greeting,reload_timestamp,meetme_enter_login_filename,meetme_enter_leave3way_filename,allow_chats,enable_auto_reports,enable_drop_lists 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; - $sounds_central_control_active = $aryA[0]; - $active_voicemail_server = $aryA[1]; - $SScustom_dialplan_entry = $aryA[2]; - $SSdefault_codecs = $aryA[3]; - $SSgenerate_cross_server_exten = $aryA[4]; - $SSvoicemail_timezones = $aryA[5]; - $SSdefault_voicemail_timezone = $aryA[6]; - $SScall_menu_qualify_enabled = $aryA[7]; - $SSallow_voicemail_greeting = $aryA[8]; - $SSreload_timestamp = $aryA[9]; - $meetme_enter_login_filename = $aryA[10]; - $meetme_enter_leave3way_filename = $aryA[11]; - $SSallow_chats = $aryA[12]; - $SSenable_auto_reports = $aryA[13]; - $SSenable_drop_lists = $aryA[14]; - } -$sthA->finish(); -if ($DBXXX > 0) {print "SYSTEM SETTINGS: $sounds_central_control_active|$active_voicemail_server|$SScustom_dialplan_entry|$SSdefault_codecs\n";} - $timeclock_end_of_day_NOW=0; ### determine if it is the timeclock end of day right now $stmtA = "SELECT count(*) from system_settings where timeclock_end_of_day LIKE \"%$reset_test%\";"; @@ -873,29 +894,6 @@ if ($sthArows > 0) } $sthA->finish(); -##### Get the settings for this server's server_ip ##### -$stmtA = "SELECT active_asterisk_server,generate_vicidial_conf,rebuild_conf_files,asterisk_version,sounds_update,conf_secret,custom_dialplan_entry,auto_restart_asterisk,asterisk_temp_no_restart,gather_asterisk_output,conf_qualify FROM servers where server_ip='$server_ip';"; -# 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; - $active_asterisk_server = $aryA[0]; - $generate_vicidial_conf = $aryA[1]; - $rebuild_conf_files = $aryA[2]; - $asterisk_version = $aryA[3]; - $sounds_update = $aryA[4]; - $self_conf_secret = $aryA[5]; - $SERVERcustom_dialplan_entry = $aryA[6]; - $auto_restart_asterisk = $aryA[7]; - $asterisk_temp_no_restart = $aryA[8]; - $gather_asterisk_output = $aryA[9]; - $conf_qualify = $aryA[10]; - } -$sthA->finish(); - if ($timeclock_end_of_day_NOW > 0) { @@ -1914,6 +1912,19 @@ if ( ($active_asterisk_server =~ /Y/) && ($generate_vicidial_conf =~ /Y/) && ($r { if ($DB) {print "generating new auto-gen conf files\n";} + $hangup_exten_line = 'exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; + %ast_ver_str = parse_asterisk_version($asterisk_version); + if ($DBX) {print "Asterisk version: $ast_ver_str{major} $ast_ver_str{minor}\n";} + + if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) + { + $hangup_exten_line = 'exten => h,1,DeadAGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; + } + if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} >= 12)) + { + $hangup_exten_line = 'exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME}-----${HANGUPCAUSE(${HANGUPCAUSE_KEYS()},tech)}))'; + } + $stmtA="UPDATE servers SET rebuild_conf_files='N' where server_ip='$server_ip';"; $affected_rows = $dbhA->do($stmtA); @@ -1921,9 +1932,9 @@ if ( ($active_asterisk_server =~ /Y/) && ($generate_vicidial_conf =~ /Y/) && ($r $S='*'; if( $VARserver_ip =~ m/(\S+)\.(\S+)\.(\S+)\.(\S+)/ ) { - $a = leading_zero($1); - $b = leading_zero($2); - $c = leading_zero($3); + $a = leading_zero($1); + $b = leading_zero($2); + $c = leading_zero($3); $d = leading_zero($4); $VARremDIALstr = "$a$S$b$S$c$S$d"; } @@ -2709,14 +2720,14 @@ if ( ($active_asterisk_server =~ /Y/) && ($generate_vicidial_conf =~ /Y/) && ($r $meetme_custom_ext .= "exten => _8600XXX,1,Meetme(\${EXTEN},FG($meetme_enter_login_filename))\n"; $meetme_custom_ext .= "exten => _8600XXX,n,Hangup()\n"; $meetme_custom_ext .= "\n"; - $meetme_custom_ext .= 'exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; + $meetme_custom_ext .= $hangup_exten_line; $meetme_custom_ext .= "\n\n"; $meetme_custom_ext .= '[meetme-enter-leave3way]'; $meetme_custom_ext .= "\n; meetme entry for Vicidial agent leaving 3way call, Asterisk 1.8+ compatible only\n"; $meetme_custom_ext .= "exten => _8600XXX,1,Meetme(\${EXTEN},FG($meetme_enter_leave3way_filename))\n"; $meetme_custom_ext .= "exten => _8600XXX,n,Hangup()\n"; $meetme_custom_ext .= "\n"; - $meetme_custom_ext .= 'exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; + $meetme_custom_ext .= $hangup_exten_line; $meetme_custom_ext .= "\n\n"; if ($DBX>0) {print "Custom Meetme login and leave3way entries generated: |$meetme_enter_login_filename|$meetme_enter_leave3way_filename|\n";} @@ -3193,15 +3204,7 @@ if ( ($active_asterisk_server =~ /Y/) && ($generate_vicidial_conf =~ /Y/) && ($r $call_menu_ext .= "$call_menu_invalid_ext"; } $call_menu_ext .= "; hangup\n"; - - %ast_ver_str = parse_asterisk_version($asterisk_version); - if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) - { - $call_menu_ext .= 'exten => h,1,DeadAGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } else { - $call_menu_ext .= 'exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } - + $call_menu_ext .= $hangup_exten_line; if (length($custom_dialplan_entry[$i]) > 4) { @@ -3432,70 +3435,35 @@ if ( ($active_asterisk_server =~ /Y/) && ($generate_vicidial_conf =~ /Y/) && ($r if (length($SScustom_dialplan_entry)>5) { print ext "[vicidial-auto-system-setting-custom]\n"; - %ast_ver_str = parse_asterisk_version($asterisk_version); - if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) - { - print ext 'exten => h,1,DeadAGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } else { - print ext 'exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } + print ext $hangup_exten_line; print ext "\n"; print ext "; System Setting Custom Dialplan\n$SScustom_dialplan_entry\n\n"; } if (length($SERVERcustom_dialplan_entry)>5) { print ext "[vicidial-auto-server-custom]\n"; - %ast_ver_str = parse_asterisk_version($asterisk_version); - if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) - { - print ext 'exten => h,1,DeadAGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } else { - print ext 'exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } + print ext $hangup_exten_line; print ext "\n"; print ext "; Server Custom Dialplan\n$SERVERcustom_dialplan_entry\n\n"; } print ext "[vicidial-auto-external]\n"; - %ast_ver_str = parse_asterisk_version($asterisk_version); - if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) - { - print ext 'exten => h,1,DeadAGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } else { - print ext 'exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } + print ext $hangup_exten_line; print ext "\n"; print ext "$Lext\n"; print ext "[vicidial-auto-internal]\n"; - %ast_ver_str = parse_asterisk_version($asterisk_version); - if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) - { - print ext 'exten => h,1,DeadAGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } else { - print ext 'exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } + print ext $hangup_exten_line; print ext "\n"; print ext "$Vext\n"; print ext "[vicidial-auto-phones]\n"; - %ast_ver_str = parse_asterisk_version($asterisk_version); - if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) - { - print ext 'exten => h,1,DeadAGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } else { - print ext 'exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } + print ext $hangup_exten_line; print ext "\n"; print ext "$Pext\n"; print ext "[vicidial-auto]\n"; - %ast_ver_str = parse_asterisk_version($asterisk_version); - if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) - { - print ext 'exten => h,1,DeadAGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } else { - print ext 'exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME})'; - } + + print ext $hangup_exten_line; print ext "\n"; print ext "\n"; print ext "include => vicidial-auto-internal\n"; @@ -4123,10 +4091,11 @@ if ($SSenable_drop_lists > 0) ################################################################################ -##### BEGIN reset lists +##### BEGIN reset lists, and expired lists to inactive check ################################################################################ if ($AST_VDadapt > 0) { + ### reset lists if reset time matches $stmtA = "SELECT list_id FROM vicidial_lists where reset_time LIKE \"%$reset_test%\";"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; @@ -4160,9 +4129,49 @@ if ($AST_VDadapt > 0) $i++; } + + ### set expired lists to inactive, only run at 12 minutes past the hour + if ( ($SSexpired_lists_inactive > 0) && ($min =~ /12/) ) + { + if ($DB) {print "STARTING EXPIRED LIST TO INACTIVE CHECK: |$SSexpired_lists_inactive|$min";} + + $stmtA = "SELECT list_id FROM vicidial_lists where active='Y' and expiration_date < \"$today_date\";"; + $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; + $sthCrows=$sthA->rows; + $i=0; + while ($sthCrows > $i) + { + @aryA = $sthA->fetchrow_array; + $expired_list_id[$i] = "$aryA[0]"; + $i++; + } + $sthA->finish(); + + if ($DBX) {print "EXPIRED LIST CHECK: $i|$sthCrows|$min";} + + $i=0; + while ($sthCrows > $i) + { + $stmtA="UPDATE vicidial_lists set active='N' where list_id='$expired_list_id[$i]';"; + $affected_rows = $dbhA->do($stmtA); + + $SQL_log = "$stmtA|"; + $SQL_log =~ s/;|\\|\'|\"//gi; + + if ($DB) {print "DONE\n";} + if ($DB) {print "$trigger_results\n";} + + $stmtA="INSERT INTO vicidial_admin_log set event_date='$now_date', user='VDAD', ip_address='1.1.1.1', event_section='LISTS', event_type='MODIFY', record_id='$expired_list_id[$i]', event_code='ADMIN EXPIRED LIST INACTIVE', event_sql=\"$SQL_log\", event_notes='$affected_rows list expired';"; + $Iaffected_rows = $dbhA->do($stmtA); + if ($DB) {print "FINISHED: $affected_rows|$Iaffected_rows|$stmtA";} + + $i++; + } + } } ################################################################################ -##### END reset lists +##### END reset lists, and expired lists to inactive check ################################################################################ diff --git a/bin/AST_VDauto_dial.pl b/bin/AST_VDauto_dial.pl index c4c9a029..c820b5ae 100644 --- a/bin/AST_VDauto_dial.pl +++ b/bin/AST_VDauto_dial.pl @@ -124,6 +124,7 @@ # 170313-1041 - Added CHAT option to inbound_queue_no_dial # 170325-1106 - Added optional vicidial_drop_log logging # 170527-2347 - Fix for rare inbound logging issue #1017 +# 170915-1817 - Added support for per server routing prefix needed for Asterisk 13+ # ### begin parsing run-time options ### @@ -243,7 +244,7 @@ $dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VA or die "Couldn't connect to database: " . DBI->errstr; ### Grab Server values from the database -$stmtA = "SELECT telnet_host,telnet_port,ASTmgrUSERNAME,ASTmgrSECRET,ASTmgrUSERNAMEupdate,ASTmgrUSERNAMElisten,ASTmgrUSERNAMEsend,max_vicidial_trunks,answer_transfer_agent,local_gmt,ext_context,vd_server_logs,vicidial_recording_limit FROM servers where server_ip = '$server_ip';"; +$stmtA = "SELECT telnet_host,telnet_port,ASTmgrUSERNAME,ASTmgrSECRET,ASTmgrUSERNAMEupdate,ASTmgrUSERNAMElisten,ASTmgrUSERNAMEsend,max_vicidial_trunks,answer_transfer_agent,local_gmt,ext_context,vd_server_logs,vicidial_recording_limit,asterisk_version,routing_prefix FROM servers where server_ip = '$server_ip';"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; $sthArows=$sthA->rows; @@ -263,6 +264,8 @@ if ($sthArows > 0) $DBext_context = $aryA[10]; $DBvd_server_logs = $aryA[11]; $DBvicidial_recording_limit = $aryA[12]; + $asterisk_version = $aryA[13]; + $routing_prefix = $aryA[14]; if ($DBtelnet_host) {$telnet_host = $DBtelnet_host;} if ($DBtelnet_port) {$telnet_port = $DBtelnet_port;} if ($DBASTmgrUSERNAME) {$ASTmgrUSERNAME = $DBASTmgrUSERNAME;} @@ -276,6 +279,7 @@ if ($sthArows > 0) if ($DBext_context) {$ext_context = $DBext_context;} if ($DBvd_server_logs =~ /Y/) {$SYSLOG = '1';} else {$SYSLOG = '0';} + %ast_ver_str = parse_asterisk_version($asterisk_version); } $sthA->finish(); @@ -1214,6 +1218,12 @@ while($one_day_interval > 0) if (length($DBIPvdadexten[$user_CIPct]) > 0) {$VDAD_dial_exten = "$DBIPvdadexten[$user_CIPct]";} else {$VDAD_dial_exten = "$answer_transfer_agent";} + # add the routing prefix if using Asterisk 13 + if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} > 11)) + { + $VDAD_dial_exten = $routing_prefix . $VDAD_dial_exten; + } + if (length($DBIPcampaigncid[$user_CIPct]) > 6) {$CCID = "$DBIPcampaigncid[$user_CIPct]"; $CCID_on++;} if (length($campaign_cid_override) > 6) {$CCID = "$campaign_cid_override"; $CCID_on++;} if ($DBIPuse_custom_cid[$user_CIPct] =~ /Y/) @@ -3532,3 +3542,47 @@ sub jam_event_logger } $jam_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 ); +} diff --git a/bin/AST_VDauto_dial_FILL.pl b/bin/AST_VDauto_dial_FILL.pl index 71b70464..832937ee 100644 --- a/bin/AST_VDauto_dial_FILL.pl +++ b/bin/AST_VDauto_dial_FILL.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# AST_VDauto_dial_FILL.pl version 2.12 +# AST_VDauto_dial_FILL.pl version 2.14 # # DESCRIPTION: # Places auto_dial calls on the VICIDIAL dialer system across all servers only @@ -12,7 +12,7 @@ # # Should only be run on one server in a multi-server Asterisk/VICIDIAL cluster # -# Copyright (C) 2015 Matt Florell LICENSE: AGPLv2 +# Copyright (C) 2017 Matt Florell LICENSE: AGPLv2 # # CHANGELOG: # 61115-1246 - First build, framework setup, non-functional @@ -38,6 +38,7 @@ # 131016-0658 - Fix for disable_auto_dial system option # 131122-1237 - Formatting fixes and missing sthA->finish # 151006-0937 - Changed campaign_cid_areacodes to operate with 2-5 digit areacodes +# 170915-1915 - Added support for per server routing prefix needed for Asterisk 13+ # ### begin parsing run-time options ### @@ -446,7 +447,7 @@ while($one_day_interval > 0) @DB_camp_server_available=@MT; @DB_camp_server_trunks_to_dial=@MT; ##### Get the trunk settings for the campaign across all servers - $stmtA = "SELECT server_ip,max_vicidial_trunks,balance_trunks_offlimits,vicidial_balance_rank FROM servers where vicidial_balance_active = 'Y' and server_ip NOT IN($full_serversSQL) order by vicidial_balance_rank desc, server_ip;"; + $stmtA = "SELECT server_ip,max_vicidial_trunks,balance_trunks_offlimits,vicidial_balance_rank,asterisk_version,routing_prefix FROM servers where vicidial_balance_active = 'Y' and server_ip NOT IN($full_serversSQL) order by vicidial_balance_rank desc, server_ip;"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; $sthArows=$sthA->rows; @@ -457,6 +458,8 @@ while($one_day_interval > 0) $DB_camp_server_server_ip[$DB_camp_servers] = $aryA[0]; $DB_camp_server_max_vicidial_trunks[$DB_camp_servers] = $aryA[1]; $DB_camp_server_balance_trunks_offlimits[$DB_camp_servers] = $aryA[2]; + $DB_camp_server_asterisk_version[$DB_camp_servers] = $aryA[4]; + $DB_camp_server_routing_prefix[$DB_camp_servers] = $aryA[5]; $DB_camp_servers++; $rec_count++; } @@ -835,11 +838,19 @@ while($one_day_interval > 0) if ($staggered < 1) { + %ast_ver_str = parse_asterisk_version($DB_camp_server_asterisk_version[$server_CIPct]); + if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} > 11)) + { + $VDAD_dial_exten = "$DB_camp_server_routing_prefix[$server_CIPct]$VDAD_dial_exten"; + $event_string = "|VDAD_dial_exten = $VDAD_dial_exten|"; + &event_logger; + } + ### insert a NEW record to the vicidial_manager table to be processed $stmtA = "INSERT INTO vicidial_manager values('','','$SQLdate','NEW','N','$DB_camp_server_server_ip[$server_CIPct]','','Originate','$VqueryCID','Exten: $VDAD_dial_exten','Context: $ext_context','Channel: $local_DEF$Ndialstring$local_AMP$ext_context','Priority: 1','Callerid: $CIDstring','Timeout: $Local_dial_timeout','','','','VDACnote: $DBfill_campaign[$camp_CIPct]|$lead_id|$phone_code|$phone_number|OUTBALANCE|$alt_dial|$DBIPqueue_priority[$camp_CIPct]')"; $affected_rows = $dbhA->do($stmtA); - $event_string = "| number call dialed|$DBfill_campaign[$camp_CIPct]|$VqueryCID|$stmtA|$gmt_offset_now|$alt_dial|"; + $event_string = "| number call dialed|$DBfill_campaign[$camp_CIPct]|$VqueryCID|$stmtA|$gmt_offset_now|$alt_dial|$DB_camp_server_server_ip[$server_CIPct]|$DB_camp_server_asterisk_version[$server_CIPct]"; &event_logger; ### insert a SENT record to the vicidial_auto_calls table @@ -919,7 +930,7 @@ while($one_day_interval > 0) $staggered_rank_ct=0; while ( ($st_ct > $staggered_rank_ct) && ($staggered_ct > $staggered_fill) ) { - $stmtA = "SELECT server_ip FROM servers where vicidial_balance_rank='$ST_rank[$staggered_rank_ct]' and vicidial_balance_active = 'Y' order by server_ip LIMIT $ST_count[$staggered_rank_ct];"; + $stmtA = "SELECT server_ip,asterisk_version,routing_prefix FROM servers where vicidial_balance_rank='$ST_rank[$staggered_rank_ct]' and vicidial_balance_active = 'Y' order by server_ip LIMIT $ST_count[$staggered_rank_ct];"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; $sthArowsSIPS=$sthA->rows; @@ -928,7 +939,9 @@ while($one_day_interval > 0) while ($sthArowsSIPS > $st_si_ct) { @aryA = $sthA->fetchrow_array; - $ST_server_ip[$st_si_ct] = $aryA[0]; + $ST_server_ip[$st_si_ct] = $aryA[0]; + $ST_asterisk_version[$st_si_ct] = $aryA[1]; + $ST_routing_prefix[$st_si_ct] = $aryA[2]; $io=0; foreach(@DB_camp_server_server_ip) @@ -950,6 +963,8 @@ while($one_day_interval > 0) $RANK_calls_placed=0; $st_si_loop=0; $TEMP_server_ip = ''; + $TEMP_asterisk_version = ''; + $TEMP_routing_prefix = ''; $TEMP_vm_insert = ''; $TEMP_vac_insert = ''; $TEMP_vl_update = ''; @@ -962,6 +977,8 @@ while($one_day_interval > 0) while ( ($TOTAL_available > $RANK_calls_placed) && ($failsafe_ct < 99999) && ($staggered_fill <= $staggered_ct) ) { $TEMP_server_ip = $ST_server_ip[$st_si_loop]; + $TEMP_asterisk_version = $ST_asterisk_version[$st_si_loop]; + $TEMP_routing_prefix = $ST_routing_prefix[$st_si_loop]; $TEMP_vm_insert = $vm_inserts[$staggered_fill]; $TEMP_vac_insert = $vac_inserts[$staggered_fill]; @@ -973,6 +990,11 @@ while($one_day_interval > 0) $TEMP_vac_insert =~ s/XXXXXXXXXXXXXXX/$TEMP_server_ip/gi; $TEMP_vddl_inserts =~ s/XXXXXXXXXXXXXXX/$TEMP_server_ip/gi; + # add the routing prefix for Asterisk 13+ systems + %ast_ver_str = parse_asterisk_version($TEMP_asterisk_version); + if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} > 11)) + { $TEMP_vm_insert =~ s/Exten: /Exten: $TEMP_routing_prefix/gi; } + if (length($TEMP_vm_insert) > 20) { $affected_rows_vl = $dbhA->do($TEMP_vl_update); @@ -981,7 +1003,7 @@ while($one_day_interval > 0) $affected_rows_vddl = $dbhA->do($TEMP_vddl_inserts); } - $event_string = "| number call stagger dialed|$TEMP_server_ip|$staggered_fill|$staggered_ct|$affected_rows_vm|$affected_rows_vac|$affected_rows_vl|$affected_rows_vddl $TEMP_st_logged"; + $event_string = "| number call stagger dialed|$TEMP_vm_insert|$TEMP_server_ip|$staggered_fill|$staggered_ct|$affected_rows_vm|$affected_rows_vac|$affected_rows_vl|$affected_rows_vddl $TEMP_st_logged"; &event_logger; ### sleep for 2.5 hundredths of a second to not flood the server with new calls @@ -1244,3 +1266,48 @@ sub event_logger } $event_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 ); +} diff --git a/bin/AST_conf_update.pl b/bin/AST_conf_update.pl index c41c7d2b..bc1eb8fe 100644 --- a/bin/AST_conf_update.pl +++ b/bin/AST_conf_update.pl @@ -1,10 +1,10 @@ #!/usr/bin/perl # -# AST_conf_update.pl version 2.12 +# AST_conf_update.pl version 2.14 # # This script checks if there are channels in reserved conferences # -# Copyright (C) 2015 Matt Florell LICENSE: AGPLv2 +# Copyright (C) 2017 Matt Florell LICENSE: AGPLv2 # # 50810-1532 - Added database server variable definitions lookup # 50823-1456 - Added commandline arguments for debug at runtime @@ -18,6 +18,7 @@ # 100928-1506 - Changed from hard-coded 60 minute limit to servers.vicidial_recording_limit # 130108-1712 - Changes for Asterisk 1.8 compatibility # 150610-1200 - Added support for AMI version 1.3 +# 170916-0947 - Added support for AMI version 2+ # # constants @@ -248,19 +249,32 @@ if ($no_vc_3way_check < 1) if (!$telnet_port) {$telnet_port = '5038';} + $max_buffer = 4*1024*1024; # 4 meg buffer + ### connect to asterisk manager through telnet - $t = new Net::Telnet (Port => $telnet_port, - Prompt => '/.*[\$%#>] $/', - Output_record_separator => '',); - #$fh = $t->dump_log("$telnetlog"); # uncomment for telnet log - if (length($ASTmgrUSERNAMEsend) > 3) {$telnet_login = $ASTmgrUSERNAMEsend;} - else {$telnet_login = $ASTmgrUSERNAME;} + $t = new Net::Telnet ( + Port => $telnet_port, + Prompt => '/\r\n/', + Output_record_separator => "\n\n", + Max_buffer_length => $max_buffer, + Telnetmode => 0, + ); + $LItelnetlog = "$PATHlogs/listen_telnet_log.txt"; # uncomment for telnet log + #$fh = $t->dump_log("$LItelnetlog"); # uncomment for telnet log + if (length($ASTmgrUSERNAMEsend) > 3) {$telnet_login = $ASTmgrUSERNAMEsend;} + else {$telnet_login = $ASTmgrUSERNAME;} + $t->open("$telnet_host"); + $t->waitfor('/Asterisk Call Manager\//'); - $t->open("$telnet_host"); - $t->waitfor('/[0123]\n$/'); # print login - $t->print("Action: Login\nUsername: $telnet_login\nSecret: $ASTmgrSECRET\n\n"); - $t->waitfor('/Authentication accepted/'); # waitfor auth accepted + # get the AMI version number + $ami_version = $t->getline(Errmode => Return, Timeout => 1,); + $ami_version =~ s/\n//gi; + if ($DB) {print "----- AMI Version $ami_version -----\n";} + $t->print("Action: Login\nUsername: $telnet_login\nSecret: $ASTmgrSECRET"); + $t->waitfor('/Authentication accepted/'); # waitfor auth accepted + + $t->buffer_empty; $i=0; if ( !( ( @PTextensions == 1 ) && ( $PTextensions[0] eq '') ) ) @@ -269,16 +283,38 @@ if ($no_vc_3way_check < 1) { @list_channels=@MT; $t->buffer_empty; - $COMMAND = "Action: Command\nCommand: Meetme list $PT_conf_extens[$i]\n\nAction: Ping\n\n"; - if ($DB) {print "|$PTextensions[$i]|$PT_conf_extens[$i]|$COMMAND|\n";} - %ast_ver_str = parse_asterisk_version($asterisk_version); - if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) + + if ($ami_version =~ /^1\./i) { - @list_channels = $t->cmd(String => "$COMMAND", Prompt => '/Response: Pong.*/'); + $COMMAND = "Action: Command\nCommand: Meetme list $PT_conf_extens[$i]\n\nAction: Ping\n\n"; + if ($DB) {print "|$PTextensions[$i]|$PT_conf_extens[$i]|$COMMAND|\n";} + %ast_ver_str = parse_asterisk_version($asterisk_version); + if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) + { + @list_channels = $t->cmd(String => "$COMMAND", Prompt => '/Response: Pong.*/'); + } + else + { + @list_channels = $t->cmd(String => "$COMMAND", Prompt => '/Response: Success\nPing: Pong.*/'); + } } - else + elsif ($ami_version =~ /^2\./i) { - @list_channels = $t->cmd(String => "$COMMAND", Prompt => '/Response: Success\nPing: Pong.*/'); + # get the current time + ( $now_sec, $now_micro_sec ) = gettimeofday(); + + # figure out how many micro seconds since epoch + $now_micro_epoch = $now_sec * 1000000; + $now_micro_epoch = $now_micro_epoch + $now_micro_sec; + + $begin_micro_epoch = $now_micro_epoch; + + # create a new action id + $action_id = "$now_sec.$now_micro_sec"; + + $COMMAND = "Action: Command\nActionID:$action_id\nCommand: Meetme list $PT_conf_extens[$i]"; + if ($DB) {print "\n\n|$PTextensions[$i]|$PT_conf_extens[$i]|$COMMAND|\n";} + @list_channels = $t->cmd(String => "$COMMAND", Prompt => '/--END COMMAND--\n\n/'); } $j=0; @@ -336,7 +372,7 @@ if ($no_vc_3way_check < 1) $i++; ### sleep for 10 hundredths of a second - usleep(1*100*1000); + usleep(10*100*100); } } @@ -377,19 +413,32 @@ $sthA->finish(); if (!$telnet_port) {$telnet_port = '5038';} +$max_buffer = 4*1024*1024; # 4 meg buffer + ### connect to asterisk manager through telnet -$t = new Net::Telnet (Port => $telnet_port, - Prompt => '/.*[\$%#>] $/', - Output_record_separator => '',); -#$fh = $t->dump_log("$telnetlog"); # uncomment for telnet log +$t = new Net::Telnet ( + Port => $telnet_port, + Prompt => '/\r\n/', + Output_record_separator => "\n\n", + Max_buffer_length => $max_buffer, + Telnetmode => 0, +); +$LItelnetlog = "$PATHlogs/listen_telnet_log.txt"; # uncomment for telnet log +#$fh = $t->dump_log("$LItelnetlog"); # uncomment for telnet log if (length($ASTmgrUSERNAMEsend) > 3) {$telnet_login = $ASTmgrUSERNAMEsend;} else {$telnet_login = $ASTmgrUSERNAME;} +$t->open("$telnet_host"); +$t->waitfor('/Asterisk Call Manager\//'); -$t->open("$telnet_host"); -$t->waitfor('/[0123]\n$/'); # print login -$t->print("Action: Login\nUsername: $telnet_login\nSecret: $ASTmgrSECRET\n\n"); -$t->waitfor('/Authentication accepted/'); # waitfor auth accepted +# get the AMI version number +$ami_version = $t->getline(Errmode => Return, Timeout => 1,); +$ami_version =~ s/\n//gi; +if ($DB) {print "----- AMI Version $ami_version -----\n";} +$t->print("Action: Login\nUsername: $telnet_login\nSecret: $ASTmgrSECRET"); +$t->waitfor('/Authentication accepted/'); # waitfor auth accepted + +$t->buffer_empty; $i=0; if ( !( ( @PTextensions == 1 ) && ( $PTextensions[0] eq '') ) ) @@ -400,18 +449,39 @@ if ( !( ( @PTextensions == 1 ) && ( $PTextensions[0] eq '') ) ) { @list_channels=@MT; $t->buffer_empty; - $COMMAND = "Action: Command\nCommand: Meetme list $PT_conf_extens[$i]\n\nAction: Ping\n\n"; - if ($DB) {print "|$PT_conf_extens[$i]|$COMMAND|\n";} - %ast_ver_str = parse_asterisk_version($asterisk_version); - if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) - { - @list_channels = $t->cmd(String => "$COMMAND", Prompt => '/Response: Pong.*/'); - } - else - { - @list_channels = $t->cmd(String => "$COMMAND", Prompt => '/Response: Success\nPing: Pong.*/'); - } + if ($ami_version =~ /^1\./i) + { + $COMMAND = "Action: Command\nCommand: Meetme list $PT_conf_extens[$i]\n\nAction: Ping\n\n"; + if ($DB) {print "|$PT_conf_extens[$i]|$COMMAND|\n";} + %ast_ver_str = parse_asterisk_version($asterisk_version); + if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 6)) + { + @list_channels = $t->cmd(String => "$COMMAND", Prompt => '/Response: Pong.*/'); + } + else + { + @list_channels = $t->cmd(String => "$COMMAND", Prompt => '/Response: Success\nPing: Pong.*/'); + } + } + elsif ($ami_version =~ /^2\./i) + { + # get the current time + ( $now_sec, $now_micro_sec ) = gettimeofday(); + + # figure out how many micro seconds since epoch + $now_micro_epoch = $now_sec * 1000000; + $now_micro_epoch = $now_micro_epoch + $now_micro_sec; + + $begin_micro_epoch = $now_micro_epoch; + + # create a new action id + $action_id = "$now_sec.$now_micro_sec"; + + $COMMAND = "Action: Command\nActionID: $action_id\nCommand: Meetme list $PT_conf_extens[$i]"; + if ($DB) {print "|$PTextensions[$i]|$PT_conf_extens[$i]|$COMMAND|\n";} + @list_channels = $t->cmd(String => "$COMMAND", Prompt => '/--END COMMAND--/'); + } $j=0; $conf_empty[$i]=0; diff --git a/bin/AST_manager_listen.pl b/bin/AST_manager_listen.pl index 641e0712..fd6b0b3e 100644 --- a/bin/AST_manager_listen.pl +++ b/bin/AST_manager_listen.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# AST_manager_listen.pl version 2.12 +# AST_manager_listen.pl version 2.14 # # Part of the Asterisk Central Queue System (ACQS) # @@ -17,7 +17,7 @@ # the ADMIN_keepalive_ALL.pl script, which makes sure it is always running in a # screen, provided that the astguiclient.conf keepalive setting "2" is set. # -# Copyright (C) 2015 Matt Florell LICENSE: AGPLv2 +# Copyright (C) 2017 Matt Florell LICENSE: AGPLv2 # # CHANGES # 50322-1300 - changed callerid parsing to remove quotes and number @@ -47,6 +47,7 @@ # 150610-1200 - Added support for AMI version 1.3 # 150709-1506 - Added DTMF logging for Asterisk 1.8 and higher # 151031-0918 - Added better capture of errors in telnet connection, other small fixes +# 170920-1416 - Fix for issue with recordings beginning with CALLID variable # # constants @@ -411,7 +412,7 @@ while($one_day_interval > 0) $channel =~ s/Channel: |\s*$//gi; $uniqueid = $command_line[3]; $uniqueid =~ s/Uniqueid: |\s*$//gi; - $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\";"; + $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\" and cmd_line_d!='Exten: 8309' and cmd_line_d!='Exten: 8310';"; if ( ($channel !~ /local/i) && ($channel !~ /CXFER/i) ) { @@ -432,7 +433,7 @@ while($one_day_interval > 0) $channel =~ s/Channel: |\s*$//gi; $uniqueid = $command_line[4]; $uniqueid =~ s/Uniqueid: |\s*$//gi; - $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\";"; + $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\" and cmd_line_d!='Exten: 8309' and cmd_line_d!='Exten: 8310';"; print STDERR "|$stmtA|\n"; my $affected_rows = $dbhA->do($stmtA); @@ -444,7 +445,7 @@ while($one_day_interval > 0) $channel =~ s/Channel: |\s*$//gi; $uniqueid = $command_line[2]; $uniqueid =~ s/Uniqueid: |\s*$//gi; - $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\";"; + $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\" and cmd_line_d!='Exten: 8309' and cmd_line_d!='Exten: 8310';"; print STDERR "|$stmtA|\n"; my $affected_rows = $dbhA->do($stmtA); @@ -1053,7 +1054,7 @@ while($one_day_interval > 0) $channel =~ s/Channel: |\s*$//gi; $uniqueid = $command_line[3]; $uniqueid =~ s/Uniqueid: |\s*$//gi; - $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\";"; + $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\" and cmd_line_d!='Exten: 8309' and cmd_line_d!='Exten: 8310';"; if ( ($channel !~ /local/i) && ($channel !~ /CXFER/i) ) { print STDERR "|$stmtA|\n"; diff --git a/bin/AST_manager_listenBUFFER.pl b/bin/AST_manager_listenBUFFER.pl index 42024dd4..041cb81a 100644 --- a/bin/AST_manager_listenBUFFER.pl +++ b/bin/AST_manager_listenBUFFER.pl @@ -47,6 +47,7 @@ # 150610-1200 - Added support for AMI version 1.3 # 150709-1506 - Added DTMF logging for Asterisk 1.8 and higher # 151031-0651 - Added perl telnet buffer options, requires newer versions of Net::Telnet CPAN module +# 170920-1417 - Fix for issue with recordings beginning with CALLID variable # # constants @@ -412,7 +413,7 @@ while($one_day_interval > 0) $channel =~ s/Channel: |\s*$//gi; $uniqueid = $command_line[3]; $uniqueid =~ s/Uniqueid: |\s*$//gi; - $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\";"; + $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\" and cmd_line_d!='Exten: 8309' and cmd_line_d!='Exten: 8310';"; if ( ($channel !~ /local/i) && ($channel !~ /CXFER/i) ) { @@ -433,7 +434,7 @@ while($one_day_interval > 0) $channel =~ s/Channel: |\s*$//gi; $uniqueid = $command_line[4]; $uniqueid =~ s/Uniqueid: |\s*$//gi; - $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\";"; + $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\" and cmd_line_d!='Exten: 8309' and cmd_line_d!='Exten: 8310';"; print STDERR "|$stmtA|\n"; my $affected_rows = $dbhA->do($stmtA); @@ -445,7 +446,7 @@ while($one_day_interval > 0) $channel =~ s/Channel: |\s*$//gi; $uniqueid = $command_line[2]; $uniqueid =~ s/Uniqueid: |\s*$//gi; - $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\";"; + $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\" and cmd_line_d!='Exten: 8309' and cmd_line_d!='Exten: 8310';"; print STDERR "|$stmtA|\n"; my $affected_rows = $dbhA->do($stmtA); @@ -1054,7 +1055,7 @@ while($one_day_interval > 0) $channel =~ s/Channel: |\s*$//gi; $uniqueid = $command_line[3]; $uniqueid =~ s/Uniqueid: |\s*$//gi; - $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\";"; + $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$channel' where server_ip = '$server_ip' and uniqueid = '$uniqueid' and callerid NOT LIKE \"DCagcW%\" and cmd_line_d!='Exten: 8309' and cmd_line_d!='Exten: 8310';"; if ( ($channel !~ /local/i) && ($channel !~ /CXFER/i) ) { print STDERR "|$stmtA|\n"; diff --git a/bin/AST_manager_listen_AMI2.pl b/bin/AST_manager_listen_AMI2.pl new file mode 100644 index 00000000..de9f7e18 --- /dev/null +++ b/bin/AST_manager_listen_AMI2.pl @@ -0,0 +1,1007 @@ +#!/usr/bin/perl +# +# AST_manager_listen_AMI2.pl version 2.14 +# +# Part of the Asterisk Central Queue System (ACQS) +# +# DESCRIPTION: +# connects to the Asterisk Manager Interface version 2 and updates records in the +# vicidial_manager table of the asterisk database in MySQL based upon the +# events that it receives +# +# SUMMARY: +# This program was designed as the listen-only part of the ACQS. It's job is to +# look for certain events and based upon either the uniqueid or the callerid of +# the call update the status and information of an action record in the +# vicidial_manager table of the asterisk MySQL database. This program is run by +# the ADMIN_keepalive_ALL.pl script, which makes sure it is always running in a +# screen, provided that the astguiclient.conf keepalive setting "2" is set. +# +# Copyright (C) 2017 Matt Florell LICENSE: AGPLv2 +# +# CHANGES +# 170915-2106 - Initial version based off the orginal AST_manager_listen.pl script +# 170920-1418 - Fix for issue with recordings beginning with CALLID variable +# + +# constants +$DB=0; # Debug flag, set to 0 for no debug messages, lots of output +$DBX=0; +$run_check=1; # concurrency check +$last_keepalive_epoch = time(); +$keepalive_skips=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 " [--help] = this screen\n"; + print "\n"; + exit; + } + else + { + if ($args =~ /--debug/i) + { + $DB=1; # Debug flag + print "\n----- DEBUGGING ENABLED -----\n\n"; + } + if ($args =~ /--debugX/i) + { + $DBX=1; + print "\n----- SUPER-DUPER DEBUGGING -----\n\n"; + } + if ($args =~ /--test/i) + { + $TEST=1; + $T=1; + } + } + } +### 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 = ; +close(conf); +$i=0; +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 =~ /^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++; + } + +# Customized Variables +$server_ip = $VARserver_ip; # Asterisk server IP + +if (!$VARDB_port) {$VARDB_port='3306';} + +&get_time_now; + +#use lib './lib', '../lib'; +use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second +use DBI; +use Net::Telnet (); +use Switch; +#use String::Escape qw( backslash unbackslash ); + +$module = 'String::Escape qw( backslash unbackslash )'; +$bs_loaded=0; +if (try_load($module)) + { + $bs_loaded=1; + } + +$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 telnet_host,telnet_port,ASTmgrUSERNAME,ASTmgrSECRET,ASTmgrUSERNAMEupdate,ASTmgrUSERNAMElisten,ASTmgrUSERNAMEsend,max_vicidial_trunks,answer_transfer_agent,local_gmt,ext_context,vd_server_logs,asterisk_version FROM servers where server_ip = '$server_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; + $DBtelnet_host = $aryA[0]; + $DBtelnet_port = $aryA[1]; + $DBASTmgrUSERNAME = $aryA[2]; + $DBASTmgrSECRET = $aryA[3]; + $DBASTmgrUSERNAMEupdate = $aryA[4]; + $DBASTmgrUSERNAMElisten = $aryA[5]; + $DBASTmgrUSERNAMEsend = $aryA[6]; + $DBmax_vicidial_trunks = $aryA[7]; + $DBanswer_transfer_agent= $aryA[8]; + $DBSERVER_GMT = $aryA[9]; + $DBext_context = $aryA[10]; + $DBvd_server_logs = $aryA[11]; + $asterisk_version = $aryA[12]; + if ($DBtelnet_host) {$telnet_host = $DBtelnet_host;} + if ($DBtelnet_port) {$telnet_port = $DBtelnet_port;} + if ($DBASTmgrUSERNAME) {$ASTmgrUSERNAME = $DBASTmgrUSERNAME;} + if ($DBASTmgrSECRET) {$ASTmgrSECRET = $DBASTmgrSECRET;} + if ($DBASTmgrUSERNAMEupdate) {$ASTmgrUSERNAMEupdate = $DBASTmgrUSERNAMEupdate;} + if ($DBASTmgrUSERNAMElisten) {$ASTmgrUSERNAMElisten = $DBASTmgrUSERNAMElisten;} + if ($DBASTmgrUSERNAMEsend) {$ASTmgrUSERNAMEsend = $DBASTmgrUSERNAMEsend;} + if ($DBmax_vicidial_trunks) {$max_vicidial_trunks = $DBmax_vicidial_trunks;} + if ($DBanswer_transfer_agent) {$answer_transfer_agent = $DBanswer_transfer_agent;} + if ($DBSERVER_GMT) {$SERVER_GMT = $DBSERVER_GMT;} + if ($DBext_context) {$ext_context = $DBext_context;} + if ($DBvd_server_logs =~ /Y/) {$SYSLOG = '1';} + else {$SYSLOG = '0';} + } +$sthA->finish(); + +if (!$telnet_port) {$telnet_port = '5038';} + +$event_string='LOGGED INTO MYSQL SERVER ON 1 CONNECTION|'; +&event_logger; + +### concurrency check (SCREEN uses script path, so check for more than 2 entries) +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 > 2) + { + if ($DB) {print "I am not alone! Another $0 is running! Exiting...\n";} + $event_string = "I am not alone! Another $0 is running! Exiting..."; + &event_logger; + exit; + } + } + + +$event_string="STARTING NEW MANAGER TELNET CONNECTION||ATTEMPT|ONE DAY INTERVAL:$one_day_interval|"; +&event_logger; + +$max_buffer = 4*1024*1024; # 4 meg buffer + +### connect to asterisk manager through telnet +$tn = new Net::Telnet ( + Port => $telnet_port, + Prompt => '/\r\n/', + Output_record_separator => "\n\n", + Max_buffer_length => $max_buffer, + Telnetmode => 0, +); + +$LItelnetlog = "$PATHlogs/listen_telnet_log.txt"; # uncomment for telnet log +$fh = $tn->dump_log("$LItelnetlog"); # uncomment for telnet log +if (length($ASTmgrUSERNAMElisten) > 3) {$telnet_login = $ASTmgrUSERNAMElisten;} +else {$telnet_login = $ASTmgrUSERNAME;} +$tn->open("$telnet_host"); +$tn->waitfor('/Asterisk Call Manager\//'); + +# get the AMI version number +$ami_version = $tn->getline(Errmode => Return, Timeout => 1,); +$ami_version =~ s/\n//gi; +print "----- AMI Version $ami_version -----\n"; + +# Login +$tn->print("Action: Login\nUsername: $telnet_login\nSecret: $ASTmgrSECRET"); +$tn->waitfor('/Authentication accepted/'); # waitfor auth accepted + +$tn->buffer_empty; + +$event_string="STARTING NEW MANAGER TELNET CONNECTION|$telnet_login|CONFIRMED CONNECTION|AMI Version $ami_version|ONE DAY INTERVAL:$one_day_interval|"; +&event_logger; + +# initalizing timing variables; +$loop_time = 1*100*1000; # each loop show take 10 hundredths of a second +$sleep_micro_sec = 0; # time to actually sleep in micro seconds +$begin_sec = 0; # the seconds at the beginning of the loop +$begin_micro_sec = 0; # the microseconds at the beginning of the loop +$end_sec = 0; # the seconds at the end of the loop +$end_micro_sec = 0; # the microseconds at the end of the loop +$sleep_diff = 0; # how off the sleep actually was + +$last_keep_alive_epoch = time(); +$last_partial_keep_alive_epoch = $last_keep_alive_epoch; +$last_event_epoch = $last_keep_alive_epoch; +$keep_alive_sec = 30; +$keep_alive_skips = 0; +$keep_alive_response = 1; +$keep_alive_no_responses = 0; + +%ast_ver_str = parse_asterisk_version($asterisk_version); +if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 13)) + { + print "Asterisk version too low for this script. Exiting.\n\n\n"; + $event_string = "Asterisk version too low for this script. Exiting."; + &event_logger; + exit; + } +else + { + ### BEGIN manager event handling for asterisk version >= 13 + $endless_loop = 1; + while($endless_loop > 0) + { + $breakout = 1; + $record_line = ''; + %event_hash = (); + + # get an entire record + ( $read_input_buf, $match ) = $tn->waitfor(Errmode => Return, Timeout => 1, Match => "/\n\n/" ); + + chomp( $read_input_buf ); + + if (($DBX) && ($bs_loaded) && (length($read_input_buf) > 0)) { print "|read|" . backslash( $read_input_buf ) . "|\n"; } + + if (($DBX) && ($bs_loaded) && (length($read_input_buf) > 0)) { print "|match|" . backslash( $match ) . "|\n"; } + + # check if there were any errors + $msg=''; + $msg = $tn->errmsg; + if ( ( $msg ne '' ) && ( $msg !~ /pattern match timed-out/i ) ) + { + if ($msg =~ /filehandle isn\'t open/i) + { + # we have lost connection + $endless_loop=0; + $one_day_interval=0; + print "ERRMSG: |$msg|\n"; + print "\nAsterisk server shutting down, PROCESS KILLED... EXITING\n\n"; + $event_string="Asterisk server shutting down, PROCESS KILLED... EXITING|ONE DAY INTERVAL:$one_day_interval|$msg|"; + &event_logger; + } + else + { + # something happened + print "ERRMSG: |$msg|\n"; + } + } + else + { + @lines = split( /\n/, $read_input_buf ); + foreach my $line ( @lines ) + { + # add the line to the hash + ($key,$value) = split( /: /, $line ); + if ($key ne "") + { + $value =~ s/\n//gi; # remove new lines + $value =~ s/^ +//gi; # remove leading white space + $value =~ s/ +$//gi; # remove trailing white space + $event_hash{"$key"} = $value; + } + } + } + + + $keep_alive_epoch = time(); + + # take certain actions every second + if ( $keep_alive_epoch - $last_partial_keep_alive_epoch >= 1 ) + { + $last_partial_keep_alive_epoch = $keep_alive_epoch; + + ### check if we are getting close to filling the buffer + if ( $buf_len > ($max_buffer * 0.9) ) + { + if ($DB) { print "WARNING: BUFFER 90% full!!!! Purging it so we keep running.";} + $manager_string="WARNING: BUFFER 90% full!!!! Purging it so we keep running."; + &manager_output_logger; + + # purge the buffer + $tn->buffer_empty; + } + + ### Grab Server values from the database + ### Also keeps DB connection alive + $stmtA = "SELECT vd_server_logs FROM servers where server_ip = '$server_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; + $DBvd_server_logs = $aryA[0]; + if ($DBvd_server_logs =~ /Y/) {$SYSLOG = '1';} + else {$SYSLOG = '0';} + } + $sthA->finish(); + + ### putting a blank file called "listenmgr.kill" in a directory will automatically safely kill this program + if ( -e "$PATHhome/listenmgr.kill" ) + { + unlink("$PATHhome/listenmgr.kill"); + $endless_loop=0; + $one_day_interval=0; + print "\nPROCESS KILLED MANUALLY... EXITING\n\n"; + } + + ### no response to our last keep alive + if ( $keep_alive_response == 0 ) + { + $response_wait = $keep_alive_epoch - $last_keep_alive_epoch; + if($DB) { print "No response to keep alive in $response_wait seconds.\n"; } + } + + if ( $keep_alive_no_responses > 10 ) + { + if($DB) { print "$keep_alive_no_responses failed to get a response. Exiting!!!" } + $endless_loop=0; + $one_day_interval=0; + } + + ### check if it has been 40 seconds sense the last keep alive + &get_time_now; + if ( $keep_alive_epoch - $last_event_epoch >= $keep_alive_sec ) + { + if ( $keep_alive_epoch - $last_keep_alive_epoch >= $keep_alive_sec ) + { + ### if so send an AMI command to keep the connection alive + $keep_alive_skips = 0; + + if ( $keep_alive_response == 0 ) { $keep_alive_no_responses++; } + + $keep_alive_response = 0; + + $keep_alive_string = "Action: Ping"; + + $tn->print($keep_alive_string); + + $msg = $tn->errmsg; + + $buf_ref = $tn->buffer; + $buf_len = length( $$buf_ref ); + $output_size = @keep_alive_output; + + if($DB) { print "++++++++++++++++sending keepalive |$keep_alive_type|em:$msg|$output_size|$endless_loop|$now_date|$buf_len|$keep_alive_no_responses\n"; } + if($DBX) { print "---@keep_alive_output---\n"; } + + $manager_string="PROCESS: keepalive length: $output_size|$now_date"; + &manager_output_logger; + + $last_keep_alive_epoch = time(); + } + else + { + ### otherwise + $keep_alive_skips++; + + $buf_ref = $tn->buffer; + $buf_len = length( $$buf_ref ); + if($DB){print "----------------no keepalive transmit necessary ($keep_alive_skips in a row) $endless_loop|$now_date|$buf_len|$keep_alive_no_responses\n";} + + $manager_string="PROCESS: keepalive skip ($keep_alive_skips in a row)|$now_date"; + &manager_output_logger; + } + } + else + { + if($DB){ print "Event recieved within the last $keep_alive_sec seconds. No keep alive needed.\n"; } + } + } + + $event_hash{'AMIVersion'} = $ami_version; + $event_hash{'ServerIP'} = $server_ip; + + if ( ($DB) && ( keys %event_hash > 2 ) ) + { + &get_time_now; + print "\n\n$now_date|EVENT HASH:\n"; + foreach $key ( sort keys %event_hash ) + { + $value = $event_hash{"$key"}; + print " $key -> $value\n"; + } + print "\n"; + } + + $retcode = 1; + # make sure this is an event not a response + if (exists($event_hash{"Event"})) + { + # handle the event + $retcode = handle_event( %event_hash ); + $last_event_epoch = time(); + } + elsif ( ( exists($event_hash{"Response"}) ) && ( exists($event_hash{"Ping"}) ) ) + { + $keep_alive_response = 1; + $keep_alive_no_responses = 0; + } + + + # handle a shutdown + if ( $retcode == 0 ) + { + $endless_loop=0; + $one_day_interval=0; + print "\nAsterisk server shutting down, PROCESS KILLED... EXITING\n\n"; + $event_string="Asterisk server shutting down, PROCESS KILLED... EXITING|ONE DAY INTERVAL:$one_day_interval|"; + &event_logger; + } + } + + usleep(1*100*1000); + } + + + +if($DB){print "DONE... Exiting... Goodbye... See you later... Not really, initiating next loop...$one_day_interval left\n";} + +$event_string='HANGING UP|'; +&event_logger; + +@hangup = $tn->cmd(String => "Action: Logoff\n\n", Prompt => "/.*/", Errmode => Return, Timeout => 1); + +$tn->buffer_empty; +$tn->waitfor(Match => '/Message:.*\n\n/', Timeout => 10); +$ok = $tn->close; + + +$event_string='CLOSING DB CONNECTION|'; +&event_logger; + + +$dbhA->disconnect(); + + +if($DB){print "DONE... Exiting... Goodbye... See you later... Really I mean it this time\n";} + + +exit; + +# function to validate whether a CID Name is a Vicidial Call ID that we care about +sub validate_cid_name + { + my ($cid_name) = @_; + + # check if it is a valid CID Name + if ( + ( $cid_name =~ /DC\d\d\d\d\d\dW\d\d\d\d\d\d\d\d\d\dW/ ) || # 3way transfers + ( $cid_name =~ /M\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) || # Manual Dials + ( $cid_name =~ /V\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) || # Auto Dials + ( $cid_name =~ /Y\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) # Inbound Calls + ) + { + return 1; # if so return 1 for true + } + else + { + return 0; # if not return 0 for false + } + + } + +# function to return the valid callid +sub get_valid_callid + { + my ( $CallerIDName, $ConnectedLineName ) = @_; + + # remove everything after the space for Orex + if ( $CallerIDName =~ /\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S/) {$CallerIDName =~ s/ .*//gi;} + if ( $ConnectedLineName =~ /\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S/) {$ConnectedLineName =~ s/ .*//gi;} + + # if the CallerIDName variable does not have a valid Vicidial Call ID + # but the ConnectedLineName does use the ConnectedLineName + if ( !(validate_cid_name($CallerIDName)) && (validate_cid_name($ConnectedLineName)) ) + { + return $ConnectedLineName; + } + else + { + return $CallerIDName; + } + } + +# function to handle the AMI events +sub handle_event + { + my %event_hash = @_; + + switch ($event_hash{'Event'}) + { + # Asterisk is shutting down so should we + case "Shutdown" { return 0; } + + # DTMF event + case "DTMFBegin" { return handle_dtmf_begin_event( %event_hash ); } + case "DTMFEnd" { return handle_dtmf_end_event( %event_hash ); } + + # CPD-Result event + case "CPD-Result" { return handle_cpd_event( %event_hash ); } + + # SIP-Hangup-Cause event + case "SIP-Hangup-Cause" { return handle_sip_event( %event_hash ); } + + # NewCallerid event + case "NewCallerid" { return handle_newcid_event( %event_hash ); } + + # Newstate event + case "Newstate" { return handle_newstate_event( %event_hash ); } + + # Hangup event + case "Hangup" { return handle_hangup_event( %event_hash ); } + + #case "" { return handle__event( %event_hash ); } + + else { return 2; } + } + + } + +sub handle_hangup_event + { + my %event_hash = @_; + + if ( + ( exists $event_hash{'Channel'} ) && + ( exists $event_hash{'Uniqueid'} ) && + ( exists $event_hash{'CallerIDName'} ) && + ( exists $event_hash{'ConnectedLineName'} ) + ) + { + + # get the valid Vicidial Call ID + $call_id = get_valid_callid( $event_hash{'CallerIDName'}, $event_hash{'ConnectedLineName'} ); + + # Check if we are not a local channel for a consultative transfer + if ( ( $event_hash{'Channel'} !~ /local/i) && ( $event_hash{'Channel'} !~ /cxfer/i) ) + { + $stmtA = "UPDATE vicidial_manager set status='DEAD', channel='$event_hash{'Channel'}' where server_ip = '$server_ip' and uniqueid = '$event_hash{'Uniqueid'}' and cmd_line_d!='Exten: 8309' and cmd_line_d!='Exten: 8310';"; + if($DB){print STDERR "|$stmtA|\n";} + my $affected_rows = $dbhA->do($stmtA); + if($DB){print "|$affected_rows HANGUPS updated|\n";} + return 1; + } + else + { + if($DB){print STDERR "Ignoring CXFER Local Hangup: |$event_hash{'Channel'}|$server_ip|$event_hash{'Uniqueid'}|$callid|\n";} + return 1; + } + } + else + { + print STDERR "Hangup event does not have a Channel, Uniqueid, or CallerIDName ?!!!\n"; + return 3; + } + } + +sub handle_newstate_event + { + my %event_hash = @_; + + if ( + ( exists $event_hash{'Channel'} ) && + ( exists $event_hash{'Uniqueid'} ) && + ( exists $event_hash{'CallerIDName'} ) && + ( exists $event_hash{'ChannelStateDesc'} ) && + ( exists $event_hash{'ConnectedLineName'} ) + ) + { + + # get the valid Vicidial Call ID + $call_id = get_valid_callid( $event_hash{'CallerIDName'}, $event_hash{'ConnectedLineName'} ); + + ### ChannelStateDesc = Dialing + if ($event_hash{'ChannelStateDesc'} =~ /Dialing/) + { + $stmtA = "UPDATE vicidial_manager set status='SENT', channel='$event_hash{'Channel'}', uniqueid = '$event_hash{'Uniqueid'}' where server_ip = '$event_hash{'ServerIP'}' and callerid = '$call_id'"; + if($DB){print STDERR "|$stmtA|\n";} + my $affected_rows = $dbhA->do($stmtA); + if($DB){print "|$affected_rows DIALINGs updated|\n";} + } + + ### ChannelStateDesc = Ringing or Up + elsif ($event_hash{'ChannelStateDesc'} =~ /Ringing|Up/) + { + $stmtA = "UPDATE vicidial_manager set status='UPDATED', channel='$event_hash{'Channel'}', uniqueid = '$event_hash{'Uniqueid'}' where server_ip = '$event_hash{'ServerIP'}' and callerid = '$call_id' and status != 'NEW'"; + if($DB){print STDERR "|$stmtA|\n";} + if ($event_hash{'Channel'} !~ /local/i) + { + if($DB){print STDERR "|$event_hash{'Channel'}|NON LOCAL CHANNEL >>>> EXECUTING ABOVE STATMENT|\n";} + my $affected_rows = $dbhA->do($stmtA); + if($DB){print "|$affected_rows RINGINGs updated|\n";} + } + else + { + if($DB){print STDERR "|$event_hash{'Channel'}|LOCAL CHANNEL >>>> ABOVE STATMENT IGNORED|\n";} + } + } + else + { + if ( $DBX ) { print "Channel State $event_hash{'ChannelStateDesc'} not Dialing, Ringing, or Up. Ignoring."; } + } + + + return 1; + } + else + { + print STDERR "Newstate event does not have a Channel, Uniqueid, ChannelStateDesc, ConnectedLineName, or CallerIDName ?!!!\n"; + return 3; + } + } + +sub handle_newcid_event + { + my %event_hash = @_; + + if ( + ( exists $event_hash{'Channel'} ) && + ( exists $event_hash{'Uniqueid'} ) && + ( exists $event_hash{'CallerIDName'} ) && + ( exists $event_hash{'ConnectedLineName'} ) + ) + { + + # get the valid Vicidial Call ID + $call_id = get_valid_callid( $event_hash{'CallerIDName'}, $event_hash{'ConnectedLineName'} ); + + $stmtA = "UPDATE vicidial_manager set status='UPDATED', channel='$event_hash{'Channel'}', uniqueid = '$event_hash{'Uniqueid'}' where server_ip = '$event_hash{'ServerIP'}' and callerid = '$call_id'"; + if ($event_hash{'Channel'} =~ /local/i) + { + if($DB){print STDERR "|$stmtA|\n";} + my $affected_rows = $dbhA->do($stmtA); + if($DB){print "|$affected_rows RINGINGs updated|\n";} + } + + return 1; + } + else + { + print STDERR "NewCallerid event does not have a Channel, Uniqueid, ConnectedLineName, or CallerIDName ?!!!\n"; + return 3; + } + } + +sub handle_dtmf_begin_event + { + my %event_hash = @_; + + if ( + ( exists $event_hash{'Channel'} ) && + ( exists $event_hash{'Uniqueid'} ) && + ( exists $event_hash{'Direction'} ) && + ( exists $event_hash{'Digit'} ) && + ( exists $event_hash{'CallerIDName'} ) && + ( exists $event_hash{'ConnectedLineName'} ) + ) + { + + # get the valid Vicidial Call ID + $call_id = get_valid_callid( $event_hash{'CallerIDName'}, $event_hash{'ConnectedLineName'} ); + + # log the DTMF to the DB + $stmtA = "INSERT INTO vicidial_dtmf_log SET dtmf_time=NOW(),channel='$event_hash{'Channel'}',server_ip='$event_hash{'ServerIP'}',uniqueid='$event_hash{'Uniqueid'}',digit='$event_hash{'Digit'}',direction='$event_hash{'Direction'}',state='Begin'"; + if($DB){print STDERR "|$stmtA|\n";} + my $affected_rows = $dbhA->do($stmtA); + + # log the DTMF to the log file + ($s_hires, $usec) = gettimeofday(); # get seconds and microseconds since the epoch + $usec = sprintf("%06s", $usec); + $HRmsec = substr($usec, -6); + ($HRsec,$HRmin,$HRhour,$HRmday,$HRmon,$HRyear,$HRwday,$HRyday,$HRisdst) = localtime($s_hires); + $HRyear = ($HRyear + 1900); + $HRmon++; + if ($HRmon < 10) {$HRmon = "0$HRmon";} + if ($HRmday < 10) {$HRmday = "0$HRmday";} + if ($HRhour < 10) {$HRFhour = "0$HRhour";} + if ($HRmin < 10) {$HRmin = "0$HRmin";} + if ($HRsec < 10) {$HRsec = "0$HRsec";} + $HRnow_date = "$HRyear-$HRmon-$HRmday $HRhour:$HRmin:$HRsec.$HRmsec"; + if($DB){print "|$affected_rows vicidial_dtmf inserted|$HRnow_date|$s_hires|$usec|\n";} + + $dtmf_string = "$HRnow_date|$s_hires|$usec|$event_hash{'Channel'}|$event_hash{'Uniqueid'}|$event_hash{'Digit'}|$event_hash{'Direction'}|Begin|$event_hash{'CallerIDName'}"; + &dtmf_logger; + + return 1; + } + else + { + print STDERR "DTMFBegin event does not have a Channel, Uniqueid, Direction, Digit, ConnectedLineName, or CallerIDName ?!!!\n"; + return 3; + } + } + +sub handle_dtmf_end_event + { + my %event_hash = @_; + + if ( + ( exists $event_hash{'Channel'} ) && + ( exists $event_hash{'Uniqueid'} ) && + ( exists $event_hash{'Direction'} ) && + ( exists $event_hash{'Digit'} ) && + ( exists $event_hash{'CallerIDName'} ) && + ( exists $event_hash{'ConnectedLineName'} ) + ) + { + + # get the valid Vicidial Call ID + $call_id = get_valid_callid( $event_hash{'CallerIDName'}, $event_hash{'ConnectedLineName'} ); + + # log the DTMF to the DB + $stmtA = "INSERT INTO vicidial_dtmf_log SET dtmf_time=NOW(),channel='$event_hash{'Channel'}',server_ip='$event_hash{'ServerIP'}',uniqueid='$event_hash{'Uniqueid'}',digit='$event_hash{'Digit'}',direction='$event_hash{'Direction'}',state='End'"; + if($DB){print STDERR "|$stmtA|\n";} + my $affected_rows = $dbhA->do($stmtA); + + # log the DTMF to the log file + ($s_hires, $usec) = gettimeofday(); # get seconds and microseconds since the epoch + $usec = sprintf("%06s", $usec); + $HRmsec = substr($usec, -6); + ($HRsec,$HRmin,$HRhour,$HRmday,$HRmon,$HRyear,$HRwday,$HRyday,$HRisdst) = localtime($s_hires); + $HRyear = ($HRyear + 1900); + $HRmon++; + if ($HRmon < 10) {$HRmon = "0$HRmon";} + if ($HRmday < 10) {$HRmday = "0$HRmday";} + if ($HRhour < 10) {$HRFhour = "0$HRhour";} + if ($HRmin < 10) {$HRmin = "0$HRmin";} + if ($HRsec < 10) {$HRsec = "0$HRsec";} + $HRnow_date = "$HRyear-$HRmon-$HRmday $HRhour:$HRmin:$HRsec.$HRmsec"; + if($DB){print "|$affected_rows vicidial_dtmf inserted|$HRnow_date|$s_hires|$usec|\n";} + + $dtmf_string = "$HRnow_date|$s_hires|$usec|$event_hash{'Channel'}|$event_hash{'Uniqueid'}|$event_hash{'Digit'}|$event_hash{'Direction'}|End|$event_hash{'CallerIDName'}"; + &dtmf_logger; + + return 1; + } + else + { + print STDERR "DTMFEnd event does not have a Channel, Uniqueid, Direction, Digit, ConnectedLineName, or CallerIDName ?!!!\n"; + return 3; + } + } + + +sub handle_cpd_event + { + my %event_hash = @_; + + if ( + ( exists $event_hash{'Channel'} ) && + ( exists $event_hash{'Uniqueid'} ) && + ( exists $event_hash{'CallerIDName'} ) && + ( exists $event_hash{'ConnectedLineName'} ) && + ( exists $event_hash{'CPDResult'} ) + ) + { + + # get the valid Vicidial Call ID + $call_id = get_valid_callid( $event_hash{'CallerIDName'}, $event_hash{'ConnectedLineName'} ); + + &get_time_now; + + if($DB){print STDERR "|cpd_result = $event_hash{'CPDResult'}|cpd_detailed_result = $event_hash{'CPDDetailedResult'}|cpd_call_id = $event_hash{'CPDCallID'}|cpd_ref_id = $event_hash{'CPDReferenceID'}|cpd_camp_name = $event_hash{'CPDCampaignName'}|\n";} + + if (length($event_hash{'CPDResult'})>0) + { + $lead_id = substr($call_id, 10, 10); + $lead_id = ($lead_id + 0); + + # TODO change the cpd log and this insert to include the new SIP Headers for 2.0 CPD + $stmtA = "INSERT INTO vicidial_cpd_log set channel='$event_hash{'Channel'}', uniqueid='$event_hash{'Uniqueid'}', callerid='$call_id', server_ip='$event_hash{'ServerIP'}', lead_id='$lead_id', event_date='$now_date', result='$event_hash{'CPDResult'}';"; + if($DB){print STDERR "|$stmtA|\n";} + my $affected_rows = $dbhA->do($stmtA); + if($DB){print "|$affected_rows CPD_log inserted|$now_date|\n";} + } + + return 1; + } + else + { + print STDERR "CPD-Result event does not have a Channel, Uniqueid, CPDResult, ConnectedLineName, or CallerIDName ?!!!\n"; + return 3; + } + } + + +sub handle_sip_event + { + my %event_hash = @_; + + if ( + ( exists $event_hash{'Channel'} ) && + ( exists $event_hash{'Uniqueid'} ) && + ( exists $event_hash{'CallerIDName'} ) && + ( exists $event_hash{'ConnectedLineName'} ) && + ( exists $event_hash{'Result'} ) + ) + { + + # get the valid Vicidial Call ID + $call_id = get_valid_callid( $event_hash{'CallerIDName'}, $event_hash{'ConnectedLineName'} ); + + &get_time_now; + + @result_details=split(/\|/, $event_hash{'Result'}); + + if ( (length($event_hash{'Result'})>0) && ($result_details[0] !~ /^407/) ) + { + $lead_id = substr($call_id, 10, 10); + $lead_id = ($lead_id + 0); + $beginUNIQUEID = $event_hash{'Uniqueid'}; + $beginUNIQUEID =~ s/\..*//gi; + $stmtA = "UPDATE vicidial_dial_log SET sip_hangup_cause='$result_details[0]',sip_hangup_reason='$result_details[1]',uniqueid='$event_hash{'Uniqueid'}' where caller_code='$call_id' and server_ip='$event_hash{'ServerIP'}' and lead_id='$lead_id';"; + if($DB){print STDERR "|$stmtA|\n";} + my $affected_rows = $dbhA->do($stmtA); + if($DB){print "|$affected_rows dial_log updated|$call_id|$event_hash{'ServerIP'}|$event_hash{'Result'}|\n";} + $vddl_update = ($vddl_update + $affected_rows); + + $preCtarget = ($beginUNIQUEID - 180); # 180 seconds before call start + ($preCsec,$preCmin,$preChour,$preCmday,$preCmon,$preCyear,$preCwday,$preCyday,$preCisdst) = localtime($preCtarget); + $preCyear = ($preCyear + 1900); + $preCmon++; + if ($preCmon < 10) {$preCmon = "0$preCmon";} + if ($preCmday < 10) {$preCmday = "0$preCmday";} + if ($preChour < 10) {$preChour = "0$preChour";} + if ($preCmin < 10) {$preCmin = "0$preCmin";} + if ($preCsec < 10) {$preCsec = "0$preCsec";} + $preCSQLdate = "$preCyear-$preCmon-$preCmday $preChour:$preCmin:$preCsec"; + + $postCtarget = ($beginUNIQUEID + 10); # 10 seconds after call start + ($postCsec,$postCmin,$postChour,$postCmday,$postCmon,$postCyear,$postCwday,$postCyday,$postCisdst) = localtime($postCtarget); + $postCyear = ($postCyear + 1900); + $postCmon++; + if ($postCmon < 10) {$postCmon = "0$postCmon";} + if ($postCmday < 10) {$postCmday = "0$postCmday";} + if ($postChour < 10) {$postChour = "0$postChour";} + if ($postCmin < 10) {$postCmin = "0$postCmin";} + if ($postCsec < 10) {$postCsec = "0$postCsec";} + $postCSQLdate = "$postCyear-$postCmon-$postCmday $postChour:$postCmin:$postCsec"; + + $stmtA = "UPDATE vicidial_carrier_log SET sip_hangup_cause='$result_details[0]',sip_hangup_reason='$result_details[1]' where server_ip='$event_hash{'ServerIP'}' and caller_code='$call_id' and lead_id='$lead_id' and call_date > \"$preCSQLdate\" and call_date < \"$postCSQLdate\" order by call_date desc limit 1;"; + if($DB){print STDERR "|$stmtA|\n";} + my $affected_rows = $dbhA->do($stmtA); + if($DB){print "|$affected_rows carrier_log updated|$call_id|$event_hash{'ServerIP'}|$event_hash{'Uniqueid'}|$result_details[0]|$result_details[1]|\n";} + } + + return 1; + } + else + { + print STDERR "SIP-Hangup-Cause event does not have a Channel, Uniqueid, Result, ConnectedLineName, or CallerIDName ?!!!\n"; + return 3; + } + } + + + +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"; + $action_log_date = "$year-$mon-$mday"; + } + + + +sub event_logger + { + if ($SYSLOG) + { + ### open the log file for writing ### + open(Lout, ">>$PATHlogs/listen_process.$action_log_date") + || die "Can't open $PATHlogs/listen_process.$action_log_date: $!\n"; + print Lout "$now_date|$event_string|\n"; + close(Lout); + } + $event_string=''; + } + + + +sub manager_output_logger + { + if ($SYSLOG) + { + open(MOout, ">>$PATHlogs/listen.$action_log_date") + || die "Can't open $PATHlogs/listen.$action_log_date: $!\n"; + print MOout "$now_date|$manager_string|\n"; + close(MOout); + } + } + +sub dtmf_logger + { + if ($SYSLOG) + { + open(Dout, ">>$PATHlogs/dtmf.$action_log_date") + || die "Can't open $PATHlogs/dttmf.$action_log_date: $!\n"; + print Dout "|$dtmf_string|\n"; + close(Dout); + } + } + +# 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 ); + } + +# try to load a module +sub try_load + { + my $mod = shift; + + eval("use $mod"); + + if ($@) + { + #print "\$@ = $@\n"; + return(0); + } + else + { + return(1); + } + } diff --git a/bin/AST_manager_send.pl b/bin/AST_manager_send.pl index 3b85bbec..d3388852 100644 --- a/bin/AST_manager_send.pl +++ b/bin/AST_manager_send.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# AST_manager_send.pl version 2.10 +# AST_manager_send.pl version 2.14 # # Part of the Asterisk Central Queue System (ACQS) # @@ -16,7 +16,7 @@ # scalability over just using a single process. Also, this means that a single # action execution lock cannot bring the entire system down. # -# Copyright (C) 2014 Matt Florell LICENSE: AGPLv2 +# Copyright (C) 2017 Matt Florell LICENSE: AGPLv2 # # CHANGES # 50823-1514 - Added commandline debug options with debug printouts @@ -30,6 +30,7 @@ # 80418-0901 - reduced time between Actions being sent, raised endless loop timer # 91129-2146 - removed SELECT STAR and formatting fixes # 141113-1356 - Added more logging, check for number of running instances, processing of QUEUE but not SENT commands +# 170920-1419 - Fix for issue with recordings beginning with CALLID variable # $|++; @@ -192,7 +193,7 @@ while ($one_day_interval > 0) $originate_command .= "\n"; my $SENDNOW=1; - if ($originate_command =~ /Action: Hangup|Action: Redirect/) + if ( ($originate_command =~ /Action: Hangup|Action: Redirect/) && ($originate_command !~ /Exten: 8309\n|Exten: 8310\n/) ) { $SENDNOW=0; print STDERR "\n|checking for dead call before executing|" . $vdm->{callerid} . "|" . $vdm->{uniqueid} . "|\n" if ($DB); @@ -269,7 +270,7 @@ while ($one_day_interval > 0) } else { - $stmtA = "UPDATE vicidial_manager set status='DEAD' where man_id='" . $vdm->{man_id} . "'"; + $stmtA = "UPDATE vicidial_manager set status='DEAD' where man_id='" . $vdm->{man_id} . "' and cmd_line_d!='Exten: 8309' and cmd_line_d!='Exten: 8310';"; print STDERR "\n|$stmtA|\n" if ($DB); $affected_rows = $dbhA->do($stmtA); $event_string="COMMAND NOT SENT, SQL_QUERY|$stmtA|"; diff --git a/bin/AST_update_AMI2.pl b/bin/AST_update_AMI2.pl new file mode 100644 index 00000000..eed1da46 --- /dev/null +++ b/bin/AST_update_AMI2.pl @@ -0,0 +1,1652 @@ +#!/usr/bin/perl +# +# AST_update_AMI2.pl version 2.14 +# +# This script uses the Asterisk Manager interface to update the live_channels +# tables and verify the parked_channels table in the asterisk MySQL database +# +# Copyright (C) 2017 Matt Florell LICENSE: AGPLv2 +# +# CHANGES +# 170915-2110 - Initial version for Asterisk 13, based upon AST_update.pl +# + +# constants +$DB=0; # Debug flag, set to 0 for no debug messages, lots of output +$DBX=0; +$run_check=1; # concurrency check + +# loop time in seconds +$loop_time = 0.4; + +# how often settings should be reloaded from the DB in seconds +$settings_reload_interval = 10; + +# how often the server stats are updated +$server_stats_update_interval = 30; + +# how often performance logging is triggered +$performance_logging_interval = 5; + +### 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 " [--help] = this screen\n"; + print "\n"; + exit; + } + else + { + if ($args =~ /--debug/i) + { + $DB=1; # Debug flag + print "\n----- DEBUGGING ENABLED -----\n\n"; + } + if ($args =~ /--debugX/i) + { + $DBX=1; + print "\n----- SUPER-DUPER DEBUGGING -----\n\n"; + } + if ($args =~ /--test/i) + { + $TEST=1; + $T=1; + } + } + } +### 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 = ; +close(conf); +$i=0; +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 =~ /^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++; + } + +# Customized Variables +$server_ip = $VARserver_ip; # Asterisk server IP + + +### find df binary (partition usage) +$dfbin = ''; +if ( -e ('/bin/df')) {$dfbin = '/bin/df';} +else + { + if ( -e ('/usr/bin/df')) {$dfbin = '/usr/bin/df';} + else + { + if ( -e ('/usr/local/bin/df')) {$dfbin = '/usr/local/bin/df';} + else + { + print "Can't find df binary! Exiting...\n"; + exit; + } + } + } + + +if (!$VARDB_port) {$VARDB_port='3306';} + +&get_time_now; + +#use lib './lib', '../lib'; +use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second +use DBI; +use Net::Telnet (); +use Switch; +use POSIX; +use Scalar::Util qw(looks_like_number); +use Term::ANSIColor qw(:constants); + + +$module = 'String::Escape qw( backslash unbackslash )'; +$bs_loaded=0; +if (try_load($module)) + { + $bs_loaded=1; + } + +$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 telnet_host,telnet_port,ASTmgrUSERNAME,ASTmgrSECRET,ASTmgrUSERNAMEupdate,ASTmgrUSERNAMElisten,ASTmgrUSERNAMEsend,max_vicidial_trunks,answer_transfer_agent,local_gmt,ext_context,vd_server_logs,asterisk_version FROM servers where server_ip = '$server_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; + $DBtelnet_host = $aryA[0]; + $DBtelnet_port = $aryA[1]; + $DBASTmgrUSERNAME = $aryA[2]; + $DBASTmgrSECRET = $aryA[3]; + $DBASTmgrUSERNAMEupdate = $aryA[4]; + $DBASTmgrUSERNAMElisten = $aryA[5]; + $DBASTmgrUSERNAMEsend = $aryA[6]; + $DBmax_vicidial_trunks = $aryA[7]; + $DBanswer_transfer_agent= $aryA[8]; + $DBSERVER_GMT = $aryA[9]; + $DBext_context = $aryA[10]; + $DBvd_server_logs = $aryA[11]; + $asterisk_version = $aryA[12]; + if ($DBtelnet_host) {$telnet_host = $DBtelnet_host;} + if ($DBtelnet_port) {$telnet_port = $DBtelnet_port;} + if ($DBASTmgrUSERNAME) {$ASTmgrUSERNAME = $DBASTmgrUSERNAME;} + if ($DBASTmgrSECRET) {$ASTmgrSECRET = $DBASTmgrSECRET;} + if ($DBASTmgrUSERNAMEupdate) {$ASTmgrUSERNAMEupdate = $DBASTmgrUSERNAMEupdate;} + if ($DBASTmgrUSERNAMEupdate) {$ASTmgrUSERNAMEupdate = $DBASTmgrUSERNAMEupdate;} + if ($DBASTmgrUSERNAMEsend) {$ASTmgrUSERNAMEsend = $DBASTmgrUSERNAMEsend;} + if ($DBmax_vicidial_trunks) {$max_vicidial_trunks = $DBmax_vicidial_trunks;} + if ($DBanswer_transfer_agent) {$answer_transfer_agent = $DBanswer_transfer_agent;} + if ($DBSERVER_GMT) {$SERVER_GMT = $DBSERVER_GMT;} + if ($DBext_context) {$ext_context = $DBext_context;} + if ($DBvd_server_logs =~ /Y/) {$SYSLOG = '1';} + else {$SYSLOG = '0';} + } + +if (!$telnet_port) {$telnet_port = '5038';} + + +##### Check for a server_updater record, and if not present, insert one +$SUrec=0; +$stmtA = "SELECT count(*) FROM server_updater where server_ip='$server_ip';"; +$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; +$sthA->execute or die "executing: $stmtA ", $dbhA->errstr; +@aryA = $sthA->fetchrow_array; +$SUrec = $aryA[0]; +if($DB){print STDERR "\n|$SUrec|$stmtA|\n";} + +if ($SUrec < 1) + { + &get_time_now; + + $stmtU = "INSERT INTO server_updater set server_ip='$server_ip', last_update=NOW();"; + if($DB){print STDERR "\n$stmtU\n";} + $affected_rows = $dbhA->do($stmtU); + } + +$event_string='LOGGED INTO MYSQL SERVER ON 1 CONNECTION|'; +event_logger($SYSLOG,$event_string); + +### concurrency check (SCREEN uses script path, so check for more than 2 entries) +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 > 2) + { + if ($DB) {print "I am not alone! Another $0 is running! Exiting...\n";} + $event_string = "I am not alone! Another $0 is running! Exiting..."; + &event_logger; + exit; + } + } + + +$event_string="STARTING NEW MANAGER TELNET CONNECTION||ATTEMPT|ONE DAY INTERVAL:$one_day_interval|"; +event_logger($SYSLOG,$event_string); + +$max_buffer = 4*1024*1024; # 4 meg buffer + +### connect to asterisk manager through telnet +$tn = new Net::Telnet ( + Port => $telnet_port, + Prompt => '/\r\n/', + Output_record_separator => "\n\n", + Max_buffer_length => $max_buffer, + Telnetmode => 0, +); + +$UPtelnetlog = "$PATHlogs/update_telnet_log.txt"; # uncomment for telnet log +$fh = $tn->dump_log("$UPtelnetlog"); # uncomment for telnet log + +if (length($ASTmgrUSERNAMEupdate) > 3) {$telnet_login = $ASTmgrUSERNAMEupdate;} +else {$telnet_login = $ASTmgrUSERNAME;} +$tn->open("$telnet_host"); +$tn->waitfor('/Asterisk Call Manager\//'); + +# get the AMI version number +$ami_version = $tn->getline(Errmode => Return, Timeout => 1,); +$ami_version =~ s/\n//gi; +print "----- AMI Version $ami_version -----\n"; + +# Login +$tn->print("Action: Login\nUsername: $telnet_login\nSecret: $ASTmgrSECRET"); +$tn->waitfor('/Authentication accepted/'); # waitfor auth accepted + +$tn->buffer_empty; + +$event_string="STARTING NEW MANAGER TELNET CONNECTION|$telnet_login|CONFIRMED CONNECTION|AMI Version $ami_version|ONE DAY INTERVAL:$one_day_interval|"; +event_logger($SYSLOG,$event_string); + +%ast_ver_str = parse_asterisk_version($asterisk_version); +if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 13)) + { + print "Asterisk version too low for this script. Exiting.\n\n\n"; + $event_string = "Asterisk version too low for this script. Exiting."; + &event_logger; + exit; + } +else + { + ### BEGIN manager event handling for asterisk version >= 13 + $endless_loop = 1; + + # get the number of microseconds the loop is supposed to take + $loop_time_usec = $loop_time * 1000000; + $loop_time_usec = ceil($loop_time_usec); # take care of any floating point math + + # total of the number of bad channel grabs from Asterisk + $total_bad_grabs = 0; + + # the last time our settings were loaded from the DB + $last_config_reload = 0; + + # the last time the server stats were updated + $last_stats_update = 0; + + # the last time the performance data was logged + $last_perf_log = 0; + + # the various channel counts from the last loop + $counts->{'psuedo'} = 0; + $counts->{'total'} = 0; + $counts->{'trunks'} = 0; + $counts->{'clients'} = 0; + $counts->{'sip'} = 0; + $counts->{'iax'} = 0; + $counts->{'dahdi'} = 0; + $counts->{'local'} = 0; + $counts->{'other'} = 0; + + %parked_channels_hash = {}; + $parked_channels = \%parked_channels_hash; + + while($endless_loop) + { + # make a copy of our counts + %old_counts_hash = %{ $counts }; + $old_counts = \%old_counts_hash; + + # get the current time + ( $now_sec, $now_micro_sec ) = gettimeofday(); + + # figure out how many micro seconds since epoch + $now_micro_epoch = $now_sec * 1000000; + $now_micro_epoch = $now_micro_epoch + $now_micro_sec; + + $begin_micro_epoch = $now_micro_epoch; + + # create a new action id + $action_id = "$now_sec.$now_micro_sec"; + + # ask the AMI for the channels + $action_string = "Action: CoreShowChannels\nActionID: $action_id"; + $tn->print($action_string); + + # wait till we get the response + $tn->waitfor('/Message: Channels will follow\n\n/'); + + # initialize the channal array + @chan_array = (); + + # prepare to loop + $get_channels = 1; + + # total number of channels pulled + $total_channels = 0; + + # whether this channel pull was bad + $bad_grab = 0; + + &get_time_now; + if ($DB) { print "\n\n$now_date\n|Channel List:\n"; } + + # Loop to get all of the channels + $event_ref = {}; + + $match_string = '/Event: CoreShowChannelsComplete\nActionID: ' . $action_id . '\nEventList: Complete\nListItems: \d+/'; + + # get an entire record + ( $read_input_buf, $match ) = $tn->waitfor(Errmode => Return, Timeout => 1, Match => "$match_string" ); + + chomp( $read_input_buf ); + + if (($DBX) && ($bs_loaded) && (length($read_input_buf) > 0)) { print "|read|" . backslash( $read_input_buf ) . "|\n"; } + + if (($DBX) && ($bs_loaded) && (length($read_input_buf) > 0)) { print "|match|" . backslash( $match ) . "|\n"; } + + + ( $junk, $list_items) = split( /ListItems: /, $match ); + + if ($DBX) { print "|total_channels|$list_items\n"; } + + # check if there were any errors + $msg=''; + $msg = $tn->errmsg; + if ( ( $msg ne '' ) && ( $msg !~ /read timed-out/i ) ) + { + if ($msg =~ /filehandle isn\'t open/i) + { + # we have lost connection + $endless_loop=0; + $one_day_interval=0; + print "ERRMSG: |$msg|\n"; + print "\nAsterisk server shutting down, PROCESS KILLED... EXITING\n\n"; + $event_string="Asterisk server shutting down, PROCESS KILLED... EXITING|ONE DAY INTERVAL:$one_day_interval|$msg|"; + event_logger($SYSLOG,$event_string); + } + else + { + # something happened + print "ERRMSG: |$msg|\n"; + } + } + else + { + @records = split( /\n\n/, $read_input_buf ); + foreach my $record ( @records ) + { + # Loop to get all of the channels + $event_ref = {}; + + # break the record into lines + @lines = split( /\n/, $record ); + foreach my $line ( @lines) + { + # add the line to the hash + ($key,$value) = split( /: /, $line ); + if ($key ne "") + { + $value =~ s/\n//gi; # remove new lines + $value =~ s/^ +//gi; # remove leading white space + $value =~ s/ +$//gi; # remove trailing white space + + # change certain strings to conform with Asterisk 1.0 behavior + $value =~ s/Congestion\s+\(Empty\)/ SIP\/CONGEST/gi; + $value =~ s/\(Outgoing Line\)|\(None\)/SIP\/ring/gi; + $value =~ s/\(Empty\)/SIP\/internal/gi; + $event_ref->{"$key"} = $value; + } + } + + $hash_size = keys(%$event_ref); + + if ( ($DB) && ( $hash_size > 2 ) ) + { + if ( $event_ref->{'Event'} eq "CoreShowChannel" ) + { + if ( $total_channels == 0 ) + { + print "|Channel|ChannelState|ChannelStateDesc|Exten|Priority|Context|CallerIDName|CallerIDNum|ConnectedLineName|ConnectedLineNum|Uniqueid|Linkedid|Application|ApplicationData|BridgeId|AccountCode|Language|Duration|\n"; + } + + print "|$event_ref->{'Channel'}"; + print "|$event_ref->{'ChannelState'}"; + print "|$event_ref->{'ChannelStateDesc'}"; + print "|$event_ref->{'Exten'}"; + print "|$event_ref->{'Priority'}"; + print "|$event_ref->{'Context'}"; + print "|$event_ref->{'CallerIDName'}"; + print "|$event_ref->{'CallerIDNum'}"; + print "|$event_ref->{'ConnectedLineName'}"; + print "|$event_ref->{'ConnectedLineNum'}"; + print "|$event_ref->{'Uniqueid'}"; + print "|$event_ref->{'Linkedid'}"; + print "|$event_ref->{'Application'}"; + print "|$event_ref->{'ApplicationData'}"; + print "|$event_ref->{'BridgeId'}"; + print "|$event_ref->{'AccountCode'}"; + print "|$event_ref->{'Language'}"; + print "|$event_ref->{'Duration'}|"; + print "\n"; + } + } + + $event_ref->{'AMIVersion'} = $ami_version; + $event_ref->{'ServerIP'} = $server_ip; + + + $retcode = 1; + # make sure this is an event not a response + if (exists($event_ref->{"Event"})) + { + if ( $event_ref->{"Event"} eq "CoreShowChannel" ) + { + $total_channels++; + # We got a channel + if ( $event_ref->{"ActionID"} eq $action_id ) + { + push( @chan_array, $event_ref ); + } + else + { + if ($DB) { print STDERR "We got the wrong Action ID!!!!\n"; } + } + } + else + { + # We got something else??? + } + } + elsif ( exists($event_ref->{"Response"}) ) + { + # we got the response. Channels should follow. + } + } + } + + if ( $total_channels != $list_items ) + { + # something is wrong. we did not process the + # same number of channels as were reported. + $bad_grab = 1; + $total_bad_grabs++; + } + + if ($DB) { print STDERR "$total_channels channels recieved out of $list_items reported.|$bad_grab|\n"; } + + $chan_array_ref = \@chan_array; + + # reload the settings from the DB at a fixed interval + $epoch = time(); + if ( $epoch - $last_config_reload >= $settings_reload_interval ) + { + # reload the server settings + $settings_ref = get_server_settings($dbhA,$server_ip); + %settings = %$settings_ref; + + # reload the phone settings + $phones_ref = get_phones_settings($dbhA,$server_ip); + %phones = %$phones_ref; + + $last_config_reload = time(); + } + + + # update our time in the DB + $stmtA = "UPDATE server_updater set last_update=NOW() where server_ip='$server_ip'"; + if($DB){print STDERR "\n$stmtA\n";} + $dbhA->do($stmtA); + + # get the channels currently in the db + my ($db_trunks_ref, $db_clients_ref) = get_db_channels($dbhA,$server_ip); + + # gather the various stats specific to the server stats + if ( $epoch - $last_stats_update >= $server_stats_update_interval ) + { + $disk_usage = get_disk_space(); + } + + # gather the various stats specific to the performance log + if (( $settings_ref->{'sys_perf_log'} ) && ( $epoch - $last_perf_log >= $performance_logging_interval )) + { + ( $mem_total, $mem_used, $mem_free ) = get_mem_usage(); + $num_processes = get_num_processes(); + ( $reads, $writes ) = get_disk_rw(); + } + + # gather stats common to the performance log and server stats + if ( ( $epoch - $last_stats_update >= $server_stats_update_interval ) || + (( $settings_ref->{'sys_perf_log'} ) && ( $epoch - $last_perf_log >= $performance_logging_interval )) ) + { + $server_load = get_cpu_load(); + + ( + $cpu_user_percent, + $cpu_idle_percent, + $cpu_sys_percent, + $cpu_vm_percent, + $user_diff, + $nice_diff, + $system_diff, + $idle_diff, + $iowait_diff, + $irq_diff, + $softirq_diff, + $steal_diff, + $guest_diff, + $guest_nice_diff + ) = get_cpu_percent(); + + } + + + # check if there was something wrong with our channel grab + if ( $bad_grab ) + { + if($DB){print STDERR "BAD GRAB!!!\n";} + + # check if it is time to update the server stats + # if so use the old counts as the new ones are off + if ( $epoch - $last_stats_update >= $server_stats_update_interval ) + { + server_stats_update( $dbhA, $server_ip, $old_counts, $server_load, $cpu_idle_percent, $disk_usage ); + $last_stats_update = time(); + } + + # check if it is time to log the performance stats + # if so use the old counts as the new ones are off + if (( $settings_ref->{'sys_perf_log'} ) && ( $epoch - $last_perf_log >= $performance_logging_interval )) + { + server_perf_log( $dbhA, $server_ip, $old_counts, $server_load, $mem_free, $mem_used, $num_processes, $cpu_user_percent, $cpu_sys_percent, $cpu_idle_percent, $reads, $writes ); + $last_perf_log = time(); + } + + usleep(10000); # sleep a hundreth of a second and try again + } + else + { + + # Process the channel list + $counts = process_channels($dbhA,$chan_array_ref,$phones_ref,$db_trunks_ref,$db_clients_ref,$server_ip,$old_counts); + + # make sure all the parked calls are valid + $parked_channels = validate_parked_channels( $dbhA, $parked_channels, $chan_array_ref, $server_ip ); + + # check if it is time to update the server stats + if ( $epoch - $last_stats_update >= $server_stats_update_interval ) + { + server_stats_update( $dbhA, $server_ip, $counts, $server_load, $cpu_idle_percent, $disk_usage ); + $last_stats_update = time(); + } + + # check if it is time to log the performance stats + if (( $settings_ref->{'sys_perf_log'} ) && ( $epoch - $last_perf_log >= $performance_logging_interval )) + { + server_perf_log( $dbhA, $server_ip, $counts, $server_load, $mem_free, $mem_used, $num_processes, $cpu_user_percent, $cpu_sys_percent, $cpu_idle_percent, $reads, $writes ); + $last_perf_log = time(); + } + + # figure out how long that loop took. + # get the current time + ( $now_sec, $now_micro_sec ) = gettimeofday(); + + # figure out how many micro seconds since epoch + $now_micro_epoch = $now_sec * 1000000; + $now_micro_epoch = $now_micro_epoch + $now_micro_sec; + + $end_micro_epoch = $now_micro_epoch; + + # subtract the current time in usec from time at the beginning of the loop + $loop_usec = $end_micro_epoch - $begin_micro_epoch; + + # figure out how long to sleep + $sleep_usec = $loop_time_usec - $loop_usec; + + # cannot sleep negative time + if ( $sleep_usec > 0 ) + { + if ($DB) { print STDERR "loop took $loop_usec microseconds. sleeping for $sleep_usec microseconds to compensate\n"; } + + # sleep it + usleep($sleep_usec); + + } + } + } + } + + + +if($DB){print "DONE... Exiting... Goodbye... See you later... Not really, initiating next loop...$one_day_interval left\n";} + +$event_string='HANGING UP|'; +event_logger($SYSLOG,$event_string); + +@hangup = $tn->cmd(String => "Action: Logoff\n\n", Prompt => "/.*/", Errmode => Return, Timeout => 1); + +$tn->buffer_empty; +$tn->waitfor(Match => '/Message:.*\n\n/', Timeout => 10); +$ok = $tn->close; + + +$event_string='CLOSING DB CONNECTION|'; +event_logger($SYSLOG,$event_string); + + +$dbhA->disconnect(); + + +if($DB){print "DONE... Exiting... Goodbye... See you later... Really I mean it this time\n";} + + +exit; + + +sub process_channels + { + my ($dbhA,$chan_array_ref,$phones_ref,$db_trunks_ref,$db_clients_ref,$server_ip,$old_counts) = @_; + + $client_insert_sql = ""; + $client_insert_count = 0; + $client_delete_sql = ""; + $client_delete_count = 0; + $trunk_insert_sql = ""; + $trunk_insert_count = 0; + $trunk_delete_sql = ""; + $trunk_delete_count = 0; + + $counts->{'psuedo'} = 0; + $counts->{'total'} = 0; + $counts->{'trunks'} = 0; + $counts->{'clients'} = 0; + $counts->{'sip'} = 0; + $counts->{'iax'} = 0; + $counts->{'dahdi'} = 0; + $counts->{'local'} = 0; + $counts->{'other'} = 0; + + %cid_chan_hash = {}; + + foreach $channel_ref (@$chan_array_ref) + { + $call_id = get_valid_callid($channel_ref->{'CallerIDName'},$channel_ref->{'ConnectedLineName'}); + + # only need to match local channels to real channels on VDAD calls + if ( ( $call_id =~ /^V\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d$/ ) && ( $channel_ref->{'ConnectedLineName'} ne "" )) + { + if ( $channel_ref->{'Channel'} =~ /^Local/ ) + { + $cid_chan_hash{"$call_id"}->{'channel'} = $channel_ref->{'Channel'}; + $cid_chan_hash{"$call_id"}->{'uniqueid'} = $channel_ref->{'Uniqueid'}; + $cid_chan_hash{"$call_id"}->{'linkedid'} = $channel_ref->{'Linkedid'}; + $cid_chan_hash{"$call_id"}->{'calleridname'} = $channel_ref->{'CallerIDName'}; + $cid_chan_hash{"$call_id"}->{'connectedlinename'} = $channel_ref->{'ConnectedLineName'}; + } + else + { + $cid_chan_hash{"$call_id"}->{'dest_channel'} = $channel_ref->{'Channel'}; + $cid_chan_hash{"$call_id"}->{'dest_uniqueid'} = $channel_ref->{'Uniqueid'}; + $cid_chan_hash{"$call_id"}->{'linkedid'} = $channel_ref->{'Linkedid'}; + $cid_chan_hash{"$call_id"}->{'calleridname'} = $channel_ref->{'CallerIDName'}; + $cid_chan_hash{"$call_id"}->{'connectedlinename'} = $channel_ref->{'ConnectedLineName'}; + } + } + + + $extension = $channel_ref->{'ApplicationData'}; + $extension =~ s/^SIP\///gi; # remove "SIP/" from the beginning + $extension =~ s/-\S+$//gi; # remove everything after a - + $extension =~ s/\|.*//gi; # remove everything after the | + $extension =~ s/,.*//gi; # remove everything after the , + + # make sure the channel is a channel type we care about + if ( $channel_ref->{'Channel'} =~ /^IAX2|^SIP|^Local|^DAHDI/) + { + # assume all channels are trunks then check if they are not + $line_type = 'TRUNK'; + + $channel_match = $channel_ref->{'Channel'}; + + + # Local channels are not considered trunks + if ( $channel_match =~ /^Local/) + { + $line_type = 'CLIENT'; + $counts->{'local'}++; + $counts->{'clients'}++; + } + elsif ( $channel_match =~ /^IAX2/) + { + # clean up the channel to get the extension + $channel_match =~ s/\/\d+$|-\d+$//gi; + $channel_match =~ s/^IAX2\///gi; + $channel_match =~ s/\*/\\\*/gi; + + # if the channels extension is in phones + # and it is and IAX phone then it is a client + if ( ( exists ( $phones_ref->{ $channel_match } ) ) && ( $phones_ref->{ $channel_match }->{'protocol'} eq 'IAX2' ) ) + { + $line_type = 'CLIENT'; + $counts->{'iax'}++; + $counts->{'clients'}++; + } + } + elsif ($channel_ref->{'Channel'} =~ /^SIP/) + { + # clean up the channel to get the extension + $channel_match =~ s/-\S+$//gi; + $channel_match =~ s/^SIP\///gi; + $channel_match =~ s/\*/\\\*/gi; + + # if the channels extension is in phones + # and it is and SIP phone then it is a client + if ( ( exists ( $phones_ref->{ $channel_match } ) ) && ( $phones_ref->{ $channel_match }->{'protocol'} eq 'SIP' ) ) + { + $line_type = 'CLIENT'; + $counts->{'sip'}++; + $counts->{'clients'}++; + } + } + # no point logging pseudo channels, just increment the psuedo count + elsif ( $channel_ref->{'Channel'} =~ /^DAHDI\/pseudo/ ) + { + $line_type = 'PSEUDO'; + $counts->{'psuedo'}++; + } + + elsif ($channel_ref->{'Channel'} =~ /^DAHDI/) + { + # clean up the channel to get the extension + $channel_match =~ s/^DAHDI\///gi; + $channel_match =~ s/\*/\\\*/gi; + + # if the channels extension is in phones + # and it is and DAHDI/ZAP phone then it is a client + if ( ( exists ( $phones_ref->{ $channel_match } ) ) && ( $phones_ref->{$channel_match}->{'protocol'} =~ /^ZAP|^DAHDI/) ) + { + $line_type = 'CLIENT'; + $counts->{'dahdi'}++; + $counts->{'clients'}++; + } + } + + # count what is left of the trunks + if ( $line_type eq 'TRUNK' ) { $counts->{'trunks'}++; } + + } + else + { + $counts->{'other'}++; + } + + # count the total we have processed + $counts->{'total'}++; + + # process the CLIENTs first + if ( $line_type eq 'CLIENT' ) + { + # check if the channel is in the DB already + $in_db = 0; + foreach $db_client ( @$db_clients_ref ) + { + if ( ( $db_client->{'channel'} eq $channel_ref->{'Channel'} ) && ( $db_client->{'extension'} eq $extension ) ) + { + if ($DBX) { print STDERR "marking $db_client->{'channel'} active in db_clients\n"; } + $in_db = 1; # not that the channel is in the DB + $db_client->{'active'} = 1; # mark that this channel is still active + last; # break out of this foreach loop + } + } + + if ( $in_db ) + { + # channel already exists in the DB + } + else + { + # Add this channel to the client insert + if ( $client_insert_count > 0 ) { $client_insert_sql .= ", \n\t" } + $client_insert_sql .= "('$channel_ref->{'Channel'}','$server_ip','$extension','$channel_ref->{'ApplicationData'}')"; + $client_insert_count++; + } + } + + # if not a client it must be a TRUNK + elsif ( $line_type eq 'TRUNK' ) + { + # check if the channel is in the DB already + $in_db = 0; + foreach $db_trunk ( @$db_trunks_ref ) + { + if ( ( $db_trunk->{'channel'} eq $channel_ref->{'Channel'} ) && ( $db_trunk->{'extension'} eq $extension) ) + { + if ($DBX) { print STDERR "marking $db_trunk->{'channel'} active in db_trunks\n"; } + $in_db = 1; # not that the channel is in the DB + $db_trunk->{'active'} = 1; # mark that this channel is still active + last; # break out of this foreach loop + } + } + + if ( $in_db ) + { + # channel already exists in the DB + } + else + { + # Add this channel to the trunk insert + if ( $trunk_insert_count > 0 ) { $trunk_insert_sql .= ", \n\t"; } + $trunk_insert_sql .= "('$channel_ref->{'Channel'}','$server_ip','$extension','$channel_ref->{'ApplicationData'}')"; + $trunk_insert_count++; + } + } + } + + if ( bad_grab_check( $counts, $old_counts ) ) + { + if($DB){print STDERR "BAD GRAB!!!\n";} + + usleep(10000); # sleep a hundreth of a second and try again + + return $old_counts; + } + else + { + if ( $client_insert_count > 0 ) + { + # insert all the new clients + my $stmtA = "INSERT INTO live_sip_channels (channel,server_ip,extension,channel_data) values \n\t" . $client_insert_sql; + if ($DB) { print STDERR "$stmtA\n"; } + $stmtA =~ s/\n|\t//gi; + $dbhA->do($stmtA); + } + elsif ($DB) { print STDERR "|no client channels to insert|\n"; } + + if ( $trunk_insert_count > 0 ) + { + # insert all the new trunks + my $stmtA = "INSERT INTO live_channels (channel,server_ip,extension,channel_data) values \n\t" . $trunk_insert_sql; + if ($DB) { print STDERR "$stmtA\n"; } + $stmtA =~ s/\n|\t//gi; + $dbhA->do($stmtA); + } + elsif ($DB) { print STDERR "|no trunk channels to insert|\n"; } + + # find any clients that have hung up + foreach $db_client ( @$db_clients_ref ) + { + # if DB client not in current channel list add it to the client delete + if ( ( !(exists( $db_client->{'active'} ) ) ) || ($db_client->{'active'} == 0 ) ) + { + if ( $client_delete_count > 0 ) { $client_delete_sql .= " or \n\t"; } + $client_delete_sql .= "(server_ip='$server_ip' and channel='$db_client->{'channel'}' and extension='$db_client->{'extension'}')"; + $client_delete_count++; + } + } + + # find any trunks that have hung up + foreach $db_trunk ( @$db_trunks_ref ) + { + # if DB trunk not in current channel list add it to the trunk delte + if ( ( !(exists( $db_trunk->{'active'} ) ) ) || ( $db_trunk->{'active'} == 0 ) ) + { + if ( $trunk_delete_count > 0 ) { $trunk_delete_sql .= " or \n\t"; } + $trunk_delete_sql .= "(server_ip='$server_ip' and channel='$db_trunk->{'channel'}' and extension='$db_trunk->{'extension'}')"; + $trunk_delete_count++; + } + } + + # delete all the hung up clients + if ( $client_delete_count > 0 ) + { + my $stmtA = "DELETE FROM live_sip_channels where \n\t(" . $client_delete_sql . " )"; + if ($DB) { print STDERR "$stmtA\n"; } + $stmtA =~ s/\n|\t//gi; + $affected_rows = $dbhA->do($stmtA); + } + elsif ($DB) { print STDERR "|no client channels to delete|\n"; } + + # delete all the hung up trunks + if ( $trunk_delete_count > 0 ) + { + my $stmtA = "DELETE FROM live_channels where \n\t(" . $trunk_delete_sql . " )"; + if ($DB) { print STDERR "$stmtA\n"; } + $stmtA =~ s/\n|\t//gi; + $affected_rows = $dbhA->do($stmtA); + } + elsif ($DB) { print STDERR "|no trunk channels to delete|\n"; } + + # build the cid_channels_recent insert + $cid_chan_sql = ''; + $cid_chan_count = 0; + foreach $call_id (keys %cid_chan_hash) + { + if ( ( $cid_chan_hash{"$call_id"}->{'channel'} ne "" ) && ( $cid_chan_hash{"$call_id"}->{'dest_channel'} ne "" ) ) + { + if ( $cid_chan_count > 0 ) { $cid_chan_sql .= ",\n\t"; } + $cid_chan_sql .= "( "; + $cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'calleridname'} . "', "; + $cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'connectedlinename'} . "', "; + $cid_chan_sql .= "'$server_ip', "; + $cid_chan_sql .= "NOW(), "; + $cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'channel'} . "', "; + $cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'dest_channel'} . "', "; + $cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'linkedid'} . "', "; + $cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'uniqueid'} . "', "; + $cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'dest_uniqueid'} . "'"; + $cid_chan_sql .= " )"; + $cid_chan_count++; + } + } + + if ( $cid_chan_count > 0 ) + { + $stmtA = "INSERT IGNORE INTO cid_channels_recent (caller_id_name, connected_line_name, server_ip, call_date, channel, dest_channel, linkedid, dest_uniqueid, uniqueid) values \n\t"; + $stmtA .= $cid_chan_sql; + if ($DB) { print STDERR "$stmtA\n"; } + $stmtA =~ s/\n|\t//gi; + $dbhA->do($stmtA); + } + + return $counts; + } + } + +sub validate_parked_channels + { + ( $dbhA, $parked_channels, $chan_array_ref, $server_ip ) = @_; + + my $park_delete_sql = ""; + my $park_delete_count = 0; + my $auto_delete_sql = "("; + + # remove the duplicates caused by agents quickly parking, unparking, and parking again calls + $stmtA = "DELETE pc1 FROM parked_channels pc1, parked_channels pc2 WHERE pc1.parked_time < pc2.parked_time AND pc1.parked_time <> pc2.parked_time AND pc1.channel = pc2.channel AND pc1.server_ip='$server_ip' and pc2.server_ip='$server_ip'"; + $deleted_rows = $dbhA->do($stmtA); + if ($DB) { print STDERR "Park Dup Del|$stmtA|$deleted_rows\n"; } + + # get the channels currently parked + $stmtA = "SELECT channel,extension,parked_time,UNIX_TIMESTAMP(parked_time),channel_group FROM parked_channels where server_ip = '$server_ip' order by channel desc, parked_time desc;"; + $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; + $sthArows=$sthA->rows; + $ref = $sthA->fetchall_arrayref; + + # loop through the parked channels + foreach my $row ( @{ $ref } ) + { + $channel = $row->[0]; + $extension = $row->[1]; + $parked_time = $row->[2]; + $unix_parked_time = $row->[3]; + $channel_group = $row->[4]; + + # check if we already saw the parked channel before + if ( exists( $parked_channels->{"$channel"} ) ) + { + # if we have look for it in the current active channels + $channel_found = 0; + foreach $channel_ref (@$chan_array_ref) + { + # if we found it note that it there + if ( $channel_ref->{'Channel'} eq $channel ) { $channel_found = 1; } + } + + # if it was found set its count back to 0 + if ($channel_found) { $parked_channels->{"$channel"} = 0; } + # otherwise increment its count + else { $parked_channels->{"$channel"}++; } + } + else + { + # if not add it to our list and set the count to 0 + $parked_channels->{"$channel"} = 0; + } + + # if a channel has been gone for more than 10 seconds (25 calls to this function) + if ( $parked_channels->{"$channel"} >= 25 ) + { + # build the SQL for deleting stale values + if ( $park_delete_count > 0 ) + { + $park_delete_sql .= " or "; + $auto_delete_sql .= ", "; + } + $park_delete_sql .= "(channel='$channel' and extension='$extension')"; + $auto_delete_sql .= "'$channel_group'"; + $park_delete_count++; + } + } + + $auto_delete_sql .= " )"; + + # if we have records to delete + if ( $park_delete_count > 0 ) + { + # delete the records from parked_channels + $stmtA = "DELETE FROM parked_channels WHERE (" . $park_delete_sql . ") and server_ip='$server_ip'"; + $deleted_rows = $dbhA->do($stmtA); + if ($DB) { print STDERR "Park Del|$stmtA|$deleted_rows\n"; } + + # delete the records from vicidial_auto_calls + $stmtA = "DELETE FROM vicidial_auto_calls WHERE callerid IN " . $auto_delete_sql; + $deleted_rows = $dbhA->do($stmtA); + if ($DB) { print STDERR "Auto Calls Del|$stmtA|$deleted_rows\n"; } + } + + return $parked_channels; + } + +sub bad_grab_check + { + my ($counts,$old_counts) = @_; + my $bad_grab = 0; + + # calculate the percentage of the total number of channels that changed + if ( (!$old_counts->{'total'}) or ($counts->{'total'} < 2) ) + {$percent_total_static = 0;} + else + { + $percent_total_static = ( ($counts->{'total'} / $old_counts->{'total'}) * 100); + $percent_total_static = sprintf("%6.2f", $percent_total_static); + } + + # calculate the percentage of DAHDI client channels that changed including pseudo channels + $current_dahdi = $counts->{'dahdi'} + $counts->{'pseudo'}; + $old_dahdi = $old_counts->{'dahdi'} + $_oldcounts->{'pseudo'}; + if ( (!$current_dahdi) or ($old_dahdi < 2) ) + {$percent_dahdi_client_static = 0;} + else + { + $percent_dahdi_client_static = ( ($current_dahdi / $old_dahdi) * 100); + $percent_dahdi_client_static = sprintf("%6.2f", $percent_dahdi_client_static); + } + + # calculate the percentage of IAX client channels that changed + if ( (!$counts->{'iax'}) or ($old_counts->{'iax'} < 2) ) + {$percent_iax_client_static = 0;} + else + { + $percent_iax_client_static = ( ($counts->{'iax'} / $old_counts->{'iax'}) * 100); + $percent_iax_client_static = sprintf("%6.2f", $percent_iax_client_static); + } + + # calculate the percentage of Local client channels that changed + if ( (!$counts->{'local'}) or ($old_counts->{'local'} < 2) ) + {$percent_local_client_static = 0;} + else + { + $percent_local_client_static = ( ($counts->{'local'} / $old_counts->{'local'}) * 100); + $percent_local_client_static = sprintf("%6.2f", $percent_local_client_static); + } + + # calculate the percentage of SIP client channels that changed + if ( (!$counts->{'sip'}) or ($old_counts->{'sip'} < 2) ) + {$percent_sip_client_static = 0;} + else + { + $percent_sip_client_static = ( ($counts->{'sip'} / $old_counts->{'sip'}) * 100); + $percent_sip_client_static = sprintf("%6.2f", $percent_sip_client_static); + } + + if ($DB) { print "BG_check_stats [$percent_total_static|$counts->{'total'}:$old_counts->{'total'}\t$percent_dahdi_client_static|$counts->{'dahdi'}:$old_counts->{'dahdi'}\t$percent_iax_client_static|$counts->{'iax'}:$old_counts->{'iax'}\t$percent_local_client_static|$counts->{'local'}:$old_counts->{'local'}\t$percent_sip_client_static|$counts->{'sip'}:$old_counts->{'sip'}]\n"; } + + # MASSIVE IF STATEMENT FOR CHECKING IF IT WAS A BAD GRAB + if ( + # if we had > 3 trunks or > 4 clients and we now have less than 10% of those remaining + ( ($percent_total_static < 10) && ( ($old_counts->{'trunk'} > 3) or ($old_counts->{'client'} > 4) ) ) or + + # or if we had > 10 trunks or > 10 clients and we now have less than 20% of those remaining + ( ($percent_total_static < 20) && ( ($old_counts->{'trunk'} > 10) or ($old_counts->{'client'} > 10) ) ) or + + # or if we had > 20 trunks or > 20 clients and we now have less than 30% of those remaining + ( ($percent_total_static < 30) && ( ($old_counts->{'trunk'} > 20) or ($old_counts->{'client'} > 20) ) ) or + + # or if we had > 30 trunks or > 30 clients and we now have less than 40% of those remaining + ( ($percent_total_static < 40) && ( ($old_counts->{'trunk'} > 30) or ($old_counts->{'client'} > 30) ) ) or + + # or if we had > 40 trunks or > 40 clients and we now have less than 50% of those remaining + ( ($percent_total_static < 50) && ( ($old_counts->{'trunk'} > 40) or ($old_counts->{'client'} > 40) ) ) or + + # or if we had > 3 dahdi clients and we now have less than 20% of those remaining + ( ($percent_dahdi_client_static < 20) && ( $old_counts->{'dahdi'} > 3 ) ) or + + # or if we had > 9 dahdi clients and we now have less than 40% of those remaining + ( ($percent_dahdi_client_static < 40) && ( $old_counts->{'dahdi'} > 9 ) ) or + + # or if we had > 3 iax clients and we now have less than 20% of those remaining + ( ($percent_iax_client_static < 20) && ( $old_counts->{'iax'} > 3 ) ) or + + # or if we had > 9 iax clients and we now have less than 40% of those remaining + ( ($percent_iax_client_static < 40) && ( $old_counts->{'iax'} > 9 ) ) or + + # or if we had > 3 sip clients and we now have less than 20% of those remaining + ( ($percent_sip_client_static < 20) && ( $old_counts->{'sip'} > 3 ) ) or + + # or if we had > 9 sip clients and we now have less than 40% of those remaining + ( ($percent_sip_client_static < 40) && ( $old_counts->{'sip'} > 9 ) ) + ) + { + $bad_grab = 1; + $event_string="------ UPDATER BAD GRAB!!!\n$percent_total_static|$counts->{'total'}:$old_counts->{'total'}\t$percent_dahdi_client_static|$counts->{'dahdi'}:$old_counts->{'dahdi'}\t$percent_iax_client_static|$counts->{'iax'}:$old_counts->{'iax'}\t$percent_local_client_static|$counts->{'local'}:$old_counts->{'local'}\t$percent_sip_client_static|$counts->{'sip'}:$old_counts->{'sip'}\n"; + &event_logger; + } + + return $bad_grab; + } + + + +sub server_stats_update + { + ( $dbhA, $server_ip, $channel_counts, $server_load, $cpu_idle_percent, $disk_usage ) = @_; + + $stmt = "UPDATE servers SET sysload='$server_load', channels_total='$channel_counts->{'total'}', cpu_idle_percent='$cpu_idle_percent', disk_usage='$disk_usage' where server_ip='$server_ip';"; + $rows = $dbhA->do($stmt); + + if ($DB) + { + print STDERR BRIGHT_RED BOLD, "\nServer Stats Updated", RESET; + print STDERR "|$stmt|$rows\n"; + } + } + +sub server_perf_log + { + ( $dbhA, $server_ip, $channel_counts, $server_load, $mem_free, $mem_used, $num_processes, $cpu_user_percent, $cpu_sys_percent, $cpu_idle_percent, $reads, $writes ) = @_; + + $stmt = "INSERT INTO server_performance (start_time, server_ip, sysload, freeram, usedram, processes, channels_total, trunks_total, clients_total, clients_zap, clients_iax, clients_local, clients_sip, live_recordings, cpu_user_percent, cpu_system_percent, cpu_idle_percent, disk_reads, disk_writes) values( NOW(), '$server_ip', '$server_load', '$mem_free', '$mem_used', '$num_processes', '$channel_counts->{'total'}', '$channel_counts->{'trunks'}', '$channel_counts->{'clients'}', '$channel_counts->{'dahdi'}', '$channel_counts->{'iax'}', '$channel_counts->{'local'}', '$channel_counts->{'sip'}', '0', '$cpu_user_percent', '$cpu_sys_percent', '$cpu_idle_percent', '$reads', '$writes')"; + $dbhA->do($stmt); + if ($DB) + { + print STDERR BRIGHT_BLUE BOLD, "\nPerformance Log Record Inserted", RESET; + print STDERR "|$stmt\n\n"; + } + } + + +sub get_server_settings + { + my ($dbhA,$server_ip) = @_; + + ### Grab Server values from the database + $stmtA = "SELECT sys_perf_log,vd_server_logs FROM servers where server_ip='$server_ip';"; + $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; + $sthArows=$sthA->rows; + $settings_ref = $sthA->fetchrow_hashref; + + if ( $settings_ref->{'sys_perf_log'} eq 'Y' ) { $settings_ref->{'sys_perf_log'} = 1;} + else { $settings_ref->{'sys_perf_log'} = 0;} + if ( $settings_ref->{'vd_server_logs'} eq 'Y' ) { $settings_ref->{'vd_server_logs'} = 1;} + else { $settings_ref->{'vd_server_logs'} = 0;} + + return $settings_ref; + } + +sub get_phones_settings + { + my ($dbhA,$server_ip) = @_; + + $stmtA = "SELECT extension, protocol FROM phones where server_ip='$server_ip' and phone_type NOT LIKE \"%trunk%\""; + if($DB){print STDERR "|$stmtA|\n";} + $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; + $phones_ref = $sthA->fetchall_hashref('extension'); + + $zap_phones = 0; + $sip_phones = 0; + $iax_phones = 0; + + $zap_phone_list = "|"; + $sip_phone_list = "|"; + $iax_phone_list = "|"; + foreach $key ( sort (keys %$phones_ref) ) + { + if ($DB) { print STDERR "$key|$phones_ref->{$key}->{'protocol'}\n"; } + + if ( $phones_ref->{$key}->{'protocol'} eq 'ZAP' ) + { + $zap_phones++; + $zap_phone_list .= "$key|"; + } + elsif ( $phones_ref->{$key}->{'protocol'} eq 'SIP' ) + { + $sip_phones++; + $sip_phone_list .= "$key|"; + } + elsif ( $phones_ref->{$key}->{'protocol'} eq 'IAX' ) + { + $iax_phones++; + $iax_phone_list .= "$keys|"; + } + } + + $phones_ref->{'zap_phones'} = $zap_phones; + $phones_ref->{'sip_phones'} = $sip_phones; + $phones_ref->{'iax_phones'} = $iax_phones; + $phones_ref->{'zap_phone_list'} = $zap_phone_list; + $phones_ref->{'sip_phone_list'} = $sip_phone_list; + $phones_ref->{'iax_phone_list'} = $iax_phone_list; + + return $phones_ref; + } + +sub get_db_channels + { + my ($dbhA,$server_ip) = @_; + + my @db_trunks; + my @db_clients; + + my $stmtA = "SELECT channel,extension FROM live_channels where server_ip='$server_ip';"; + $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; + + while ( $hash_ref = $sthA->fetchrow_hashref ) + { + push( @db_trunks, $hash_ref ); + } + + my $stmtA = "SELECT channel,extension FROM live_sip_channels where server_ip='$server_ip';"; + $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; + + while ( $hash_ref = $sthA->fetchrow_hashref ) + { + push( @db_clients, $hash_ref ); + } + + return (\@db_trunks, \@db_clients); + } + + +# function to validate whether a CID Name is a Vicidial Call ID that we care about +sub validate_cid_name + { + my ($cid_name) = @_; + + # check if it is a valid CID Name + if ( + ( $cid_name =~ /DC\d\d\d\d\d\dW\d\d\d\d\d\d\d\d\d\dW/ ) || # 3way transfers + ( $cid_name =~ /M\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) || # Manual Dials + ( $cid_name =~ /V\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) || # Auto Dials + ( $cid_name =~ /Y\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) # Inbound Calls + ) + { + return 1; # if so return 1 for true + } + else + { + return 0; # if not return 0 for false + } + + } + +# function to return the valid callid +sub get_valid_callid + { + my ( $CallerIDName, $ConnectedLineName ) = @_; + + # remove everything after the space for Orex + if ( $CallerIDName =~ /\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S/) {$CallerIDName =~ s/ .*//gi;} + if ( $ConnectedLineName =~ /\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S/) {$ConnectedLineName =~ s/ .*//gi;} + + # if the CallerIDName variable does not have a valid Vicidial Call ID + # but the ConnectedLineName does use the ConnectedLineName + if ( !(validate_cid_name($CallerIDName)) && (validate_cid_name($ConnectedLineName)) ) + { + return $ConnectedLineName; + } + else + { + return $CallerIDName; + } + } + + +sub event_logger + { + my ($SYSLOG,$event_string) = @_; + if ($SYSLOG) + { + ### open the log file for writing ### + open(Lout, ">>$PATHlogs/update.$action_log_date") + || die "Can't open $PATHlogs/update.$action_log_date: $!\n"; + print Lout "$now_date|$event_string|\n"; + close(Lout); + } + $event_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 ); + } + +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"; + $action_log_date = "$year-$mon-$mday"; + } + + +# try to load a module +sub try_load + { + my $mod = shift; + + eval("use $mod"); + + if ($@) + { + #print "\$@ = $@\n"; + return(0); + } + else + { + return(1); + } + } + + +sub print_now + { + my $string = shift; + + # get the current time in microseconds + my ( $now_sec, $now_micro_sec ) = gettimeofday(); + + # figure out how many micro seconds since epoch + my $now_micro_epoch = $now_sec * 1000000; + $now_micro_epoch = $now_micro_epoch + $now_micro_sec; + + print "\n$string|$now_micro_epoch\n\n"; + } + +sub get_cpu_percent + { + # stat file in proc + $stat = '/proc/stat'; + + # read it + open( FH , "<$stat" ); + @lines = ; + close( FH ); + + # get the various times spent doing stuff ( $cpu is useless ) + ($cpu, $user, $nice, $system, $idle, $iowait, $irq, $softirq, $steal, $guest, $guest_nice ) = split( ' ', $lines[0] ); + + # total the different catagories of time + $cpu_user = $user + $nice; + $cpu_idle = $idle + $iowait; + $cpu_sys = $system + $irq + $softirq; + $cpu_vm = $steal + $guest + $guest_nice; + + # check if we have previous values + if ( defined ( $prev_user ) ) + { + # get the differential from last time + $cpu_user_diff = $cpu_user - $prev_cpu_user; + $cpu_idle_diff = $cpu_idle - $prev_cpu_idle; + $cpu_sys_diff = $cpu_sys - $prev_cpu_sys; + $cpu_vm_diff = $cpu_vm - $prev_cpu_vm; + + $user_diff = $user - $prev_user; + $nice_diff = $nice - $prev_nice; + $system_diff = $system - $prev_system; + $idle_diff = $idle - $prev_idle; + $iowait_diff = $iowait - $prev_iowait; + $irq_diff = $irq - $prev_irq; + $softirq_diff = $softirq - $prev_softirq; + $steal_diff = $steal - $prev_steal; + $guest_diff = $guest - $prev_guest; + $guest_nice_diff = $guest_nice - $prev_guest_nice; + + # total the differentials + $cpu_total_diff = $cpu_user_diff + $cpu_idle_diff + $cpu_sys_diff + $cpu_vm_diff; + + $cpu_user_percent = sprintf("%.0f", (( $cpu_user_diff / $cpu_total_diff ) * 100 )); + $cpu_idle_percent = sprintf("%.0f", (( $cpu_idle_diff / $cpu_total_diff ) * 100 )); + $cpu_sys_percent = sprintf("%.0f", (( $cpu_sys_diff / $cpu_total_diff ) * 100 )); + $cpu_vm_percent = sprintf("%.0f", (( $cpu_vm_diff / $cpu_total_diff ) * 100 )); + } + else + { + # first time runnings so there are no previous values. + # all we can do is base it off the system totals since boot. + $cpu_total = $cpu_user + $cpu_idle + $cpu_sys + $cpu_vm; + + $cpu_user_percent = sprintf("%.0f", (( $cpu_user / $cpu_total ) * 100 )); + $cpu_idle_percent = sprintf("%.0f", (( $cpu_idle / $cpu_total ) * 100 )); + $cpu_sys_percent = sprintf("%.0f", (( $cpu_sys / $cpu_total ) * 100 )); + $cpu_vm_percent = sprintf("%.0f", (( $cpu_vm / $cpu_total ) * 100 )); + } + + # store the values for the next call + $prev_user = $user; + $prev_nice = $nice; + $prev_system = $system; + $prev_idle = $idle; + $prev_iowait = $iowait; + $prev_irq = $irq; + $prev_softirq = $softirq; + $prev_steal = $steal; + $prev_guest = $guest; + $prev_guest_nice = $guest_nice; + $prev_cpu_user = $cpu_user; + $prev_cpu_idle = $cpu_idle; + $prev_cpu_sys = $cpu_sys; + $prev_cpu_vm = $cpu_vm; + + + return ( + $cpu_user_percent, + $cpu_idle_percent, + $cpu_sys_percent, + $cpu_vm_percent, + $user_diff, + $nice_diff, + $system_diff, + $idle_diff, + $iowait_diff, + $irq_diff, + $softirq_diff, + $steal_diff, + $guest_diff, + $guest_nice_diff + ); + } + +sub get_cpu_load + { + $lavg = '/proc/loadavg'; + + open( FH , "<$lavg" ); + @lines = ; + close( FH ); + + $server_load = $lines[0]; + $server_load =~ s/ .*//gi; + $server_load =~ s/\D//gi; + + return $server_load; + } + +sub get_mem_usage + { + $meminfo = '/proc/meminfo'; + + open( FH , "<$meminfo" ); + @lines = ; + close( FH ); + + $mem_total = $lines[0]; + $mem_total =~ s/MemTotal: *//g; + + $mem_free = $lines[1]; + $mem_free =~ s/MemFree: *//g; + + $mem_used = $mem_total - $mem_free; + + $mem_used = floor( $mem_used / 1024 ); + $mem_total = floor( $mem_total / 1024 ); + $mem_free = floor( $mem_free / 1023 ); + + return ( $mem_total, $mem_used, $mem_free ); + + } + +sub get_disk_space + { + @serverDISK = `$dfbin -B 1048576 -x nfs -x cifs -x sshfs -x ftpfs`; + $ct=0; + $ct_PCT=0; + $disk_usage = ''; + foreach(@serverDISK) + { + if ($serverDISK[$ct] =~ /(\d+\%)/) + { + $ct_PCT++; + $usage = $1; + $usage =~ s/\%//gi; + $disk_usage .= "$ct_PCT $usage|"; + } + $ct++; + } + + return $disk_usage; + } + +sub get_num_processes + { + $num_processes = 0; + + opendir( DH, '/proc'); + while ( readdir( DH ) ) + { + if ( looks_like_number( $_ ) ) { $num_processes++; } + } + closedir( DH ); + + return ($num_processes); + } + + +sub get_disk_rw + { + $total_reads = 0; + $total_writes = 0; + + $diskstats = "/proc/diskstats"; + + open( FH , "<$diskstats" ); + @lines = ; + close( FH ); + + foreach $line ( @lines ) + { + # remove excess white space + $line =~ s/\h+/ /g; + $line =~ s/^\s+|\s+$//g; + + # split the line + ( + $major, + $minor, + $device, + $reads_completed, + $reads_merged, + $sectors_read, + $time_reading, + $writes_completed, + $writes_merged, + $sectors_written, + $time_writing, + $current_ios, + $ios_time, + $weighted_ios_time + ) = split( ' ', $line ); + + # check if device is a drive or partition or raid + if ( $device !~ /\d/ ) + { + $total_reads += $sectors_read; + $total_writes += $sectors_written; + } + } + + # check if we previously got the total reads + if ( defined ( $prev_total_reads ) ) + { + $reads = $total_reads - $prev_total_reads; + $writes = $total_writes - $prev_total_writes; + } + else + { + # cannot figure out the difference + # if we don't know what it was before + $reads = 0; + $writes = 0; + } + + $prev_total_reads = $total_reads; + $prev_total_writes = $total_writes; + + return ( $reads, $writes ); + } diff --git a/bin/FastAGI_log.pl b/bin/FastAGI_log.pl index 043a21b9..f04d6eef 100644 --- a/bin/FastAGI_log.pl +++ b/bin/FastAGI_log.pl @@ -79,6 +79,7 @@ # 170427-1125 - Fix for drop call logging of answered calls hung up by customer first # 170508-1148 - Added blind monitor call end logging # 170527-2340 - Fix for rare inbound logging issue #1017 +# 170915-1753 - Asterisk 13 compatibility # # defaults for PreFork @@ -151,14 +152,15 @@ $dbhB = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VA or die "Couldn't connect to database: " . DBI->errstr; ### Grab Server values from the database -$stmtB = "SELECT vd_server_logs FROM servers where server_ip = '$VARserver_ip';"; +$stmtB = "SELECT vd_server_logs,asterisk_version FROM servers where server_ip = '$VARserver_ip';"; $sthB = $dbhB->prepare($stmtB) or die "preparing: ",$dbhB->errstr; $sthB->execute or die "executing: $stmtB ", $dbhB->errstr; $sthBrows=$sthB->rows; if ($sthBrows > 0) { @aryB = $sthB->fetchrow_array; - $SERVERLOG = $aryB[0]; + $SERVERLOG = $aryB[0]; + $asterisk_version = $aryB[1]; } $sthB->finish(); $dbhB->disconnect(); @@ -250,7 +252,7 @@ sub process_request 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';"; + $stmtA = "SELECT agi_output,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; @@ -259,16 +261,21 @@ sub process_request $AGILOG = '0'; @aryA = $sthA->fetchrow_array; $DBagi_output = $aryA[0]; + $asterisk_version = $aryA[1]; if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';} if ($DBagi_output =~ /FILE/) {$AGILOG = '2';} if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';} } $sthA->finish(); + $h_exten_reason=0; + %ast_ver_str = parse_asterisk_version($asterisk_version); + if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} >= 12)) + {$h_exten_reason=1;} if ($AGILOG) { - $agi_string = "+++++++++++++++++ FastAGI Start ++++++++++++++++++++++++++++++++++++++++"; + $agi_string = "+++++++++++++++++ FastAGI Start ++++ Asterisk version: $ast_ver_str{major} $ast_ver_str{minor} ++++++ hER: $h_exten_reason ++++++"; &agi_output; } @@ -334,15 +341,16 @@ sub process_request $PRI = $ARGV_vars[0]; $PRI =~ s/.*--HVcauses--//gi; $DEBUG = $ARGV_vars[1]; - $hangup_cause = $ARGV_vars[2]; - $dialstatus = $ARGV_vars[3]; - $dial_time = $ARGV_vars[4]; - $answered_time = $ARGV_vars[5]; + $hangup_cause = $ARGV_vars[2]; + $dialstatus = $ARGV_vars[3]; + $dial_time = $ARGV_vars[4]; + $answered_time = $ARGV_vars[5]; + $tech_hangup_cause = $ARGV_vars[6]; if( $dial_time > $answered_time ) {$ring_time = $dial_time - $answered_time;} else {$ring_time = 0;} - $agi_string = "URL HVcauses: |$PRI|$DEBUG|$hangup_cause|$dialstatus|$dial_time|$ring_time|"; + $agi_string = "URL HVcauses: |$PRI|$DEBUG|$hangup_cause|$dialstatus|$dial_time|$ring_time|$tech_hangup_cause|"; &agi_output; } if (!$fullCID) # if no fullCID sent @@ -601,16 +609,17 @@ sub process_request @ARGV_vars = split(/-----/, $request); $PRI = $ARGV_vars[0]; $PRI =~ s/.*--HVcauses--//gi; - $DEBUG = $ARGV_vars[1]; - $hangup_cause = $ARGV_vars[2]; - $dialstatus = $ARGV_vars[3]; - $dial_time = $ARGV_vars[4]; - $answered_time = $ARGV_vars[5]; + $DEBUG = $ARGV_vars[1]; + $hangup_cause = $ARGV_vars[2]; + $dialstatus = $ARGV_vars[3]; + $dial_time = $ARGV_vars[4]; + $answered_time = $ARGV_vars[5]; + $tech_hangup_cause = $ARGV_vars[6]; if( $dial_time > $answered_time ) {$ring_time = $dial_time - $answered_time;} else {$ring_time = 0;} - $agi_string = "URL HVcauses: |$PRI|$DEBUG|$hangup_cause|$dialstatus|$dial_time|$ring_time|"; + $agi_string = "URL HVcauses: |$PRI|$DEBUG|$hangup_cause|$dialstatus|$dial_time|$ring_time|$tech_hangup_cause|"; &agi_output; if ( (length($dialstatus) > 0) && ($callerid =~ /^V|^M/) ) @@ -649,21 +658,61 @@ sub process_request } $sthA->finish(); } - $sip_hangup_cause=0; - $sip_hangup_reason=''; - $stmtA = "SELECT sip_hangup_cause,sip_hangup_reason FROM vicidial_dial_log where lead_id='$CIDlead_id' and server_ip='$VARserver_ip' and caller_code='$callerid' 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) + ### if using Asterisk 11 and older method for hangup reasons, check vicidial_dial_log + if ($h_exten_reason < 1) { - @aryA = $sthA->fetchrow_array; - $sip_hangup_cause = $aryA[0]; - $sip_hangup_reason = $aryA[1]; + $sip_hangup_cause=0; + $sip_hangup_reason=''; + + $stmtA = "SELECT sip_hangup_cause,sip_hangup_reason FROM vicidial_dial_log where lead_id='$CIDlead_id' and server_ip='$VARserver_ip' and caller_code='$callerid' 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; + $sip_hangup_cause = $aryA[0]; + $sip_hangup_reason = $aryA[1]; + } + $sthA->finish(); + if ($AGILOG) {$agi_string = "$sthArows|$stmtA|$sip_hangup_cause|$sip_hangup_reason|"; &agi_output;} } - $sthA->finish(); + + ### if using Asterisk 12 and newer method for hangup reasons, check variables + else + { + if ( $tech_hangup_cause =~ /SIP/ ) + { + # we got the tech hangup cause from Asterisk (available in asterisk 13+) + ( $tech, $sip_hangup_cause, @error ) = split( / /, $tech_hangup_cause ); + $sip_hangup_reason = join( ' ', @error ); + + # the vicidial_dial_log does not have the sip hangup data so populate it + $stmtA = "UPDATE vicidial_dial_log SET sip_hangup_cause='$sip_hangup_cause',sip_hangup_reason='$sip_hangup_reason',uniqueid='$uniqueid' where caller_code='$callerid' and server_ip='$VARserver_ip' and lead_id='$CIDlead_id';"; + $dbhA->do($stmtA); + } + else + { + # tech hangup cause was unavailable + $sip_hangup_cause=0; + $sip_hangup_reason=''; + + $stmtA = "SELECT sip_hangup_cause,sip_hangup_reason FROM vicidial_dial_log where lead_id='$CIDlead_id' and server_ip='$VARserver_ip' and caller_code='$callerid' 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; + $sip_hangup_cause = $aryA[0]; + $sip_hangup_reason = $aryA[1]; + } + $sthA->finish(); + } + if ($AGILOG) {$agi_string = "$sthArows|$stmtA|$sip_hangup_cause|$sip_hangup_reason|"; &agi_output;} + } $stmtA = "INSERT IGNORE INTO vicidial_carrier_log set uniqueid='$uniqueid',call_date='$now_date',server_ip='$VARserver_ip',lead_id='$CIDlead_id',hangup_cause='$hangup_cause',dialstatus='$dialstatus',channel='$channel',dial_time='$dial_time',answered_time='$answered_time',sip_hangup_cause='$sip_hangup_cause',sip_hangup_reason='$sip_hangup_reason',caller_code='$callerid';"; if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} @@ -1962,3 +2011,46 @@ sub agi_output } $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 ); + } diff --git a/docs/AGENT_MONITOR.txt b/docs/AGENT_MONITOR.txt index 79eccad8..aa6c9625 100644 --- a/docs/AGENT_MONITOR.txt +++ b/docs/AGENT_MONITOR.txt @@ -1,4 +1,4 @@ -AGENT MONITOR DOC Started: 2013-07-16 Updated: 2013-07-16 +AGENT MONITOR DOC Started: 2013-07-16 Updated: 2017-09-15 Requirements: @@ -40,6 +40,9 @@ and the dialplan entries below should replace the older dialplan entries used. ### ADD THE LINES BELOW TO THE SYSTEM SETTINGS CUSTOM DIALPLAN ######################################################################### +NOTE: For Asteirsk 13 only, you should use the following 'h' line instead of the ones included in the below example: +exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME}-----${HANGUPCAUSE(${HANGUPCAUSE_KEYS()},tech)})) + ; quiet entry, listen-only, exit-on-dtmf conferences for VICIDIAL (listen) diff --git a/docs/ASTERISK_13.txt b/docs/ASTERISK_13.txt new file mode 100644 index 00000000..cb48ccb5 --- /dev/null +++ b/docs/ASTERISK_13.txt @@ -0,0 +1,115 @@ +ASTERISK 13 COMPATIBILITY START: 2017-09-16 UPDATE: 2017-09-16 + + + +Adding support for Asterisk 13 was much more involved and complex than adding support for previous versions, mostly because several core asterisk functions were removed or made unstable since Asterisk 11. This caused us to have to find other ways of performing the same tasks, which lead to some new processes having to be written. Although, there were also some new features that helped VICIdial to run more efficiently, so hopefully all of the changes taken together will yield the same or better overall running efficiency. + +VERY IMPORTANT: Make sure you set the "Asterisk Version" properly in the Modify Server page, then force a rebuild of the conf files on that server if you have upgraded from a previous version. + +These changes in Asterisk have necessitated some changes in the default Asterisk configurations for VICIdial: +NOTE: These are installed by the install.pl script if you select Asterisk version 13 and choose to copy sample conf files + + +In extensions.conf (from extensions.conf.sample-13): + +The 'h' extension now needs to looks like this(changed in several places): + + +exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME}-----${HANGUPCAUSE(${HANGUPCAUSE_KEYS()},tech)})) + + +The following is needed in the default context: + + +; Local channel resolution fix for Asterisk 13 +exten => _1383XX,1,AGI(agi-VDAD_local_optimize.agi,${CONNECTEDLINE(name)}) +exten => _1383XX,n,Wait(2) +exten => _1383XX,n,Hangup() + +exten => _138331*.,1,AGI(agi-VDAD_local_optimize.agi,${CONNECTEDLINE(name)}) +exten => _138331*.,n,Wait(2) +exten => _138331*.,n,Hangup() + + +In manager.conf (from manager.conf.sample-13): + +The updatecron user needs new permissions added: + + +[updatecron] +secret = 1234 +read = command,call,system +write = command,call,system + + + + + +For Asterisk 13 support, a stock asterisk build with meetme enabled should work with VICIdial, but we do recommend using the vicidial enter/leave sounds for a more optimized call handling process. See the example compilation instructions below. + + + + +#### Compiling Asterisk 13 (pre-patched and tested VICIdial build) +# NOTE: The below instructions assume that you already have all prerequisite compilation tools and libraries installed on your system + +wget http://download.vicidial.com/beta-apps/dahdi-linux-complete-2.11.1.tar.gz +tar xvfz dahdi-linux-complete-2.11.1.tar.gz +cd dahdi-linux-complete-2.11.1+2.11.1/ +make +make install +cd tools +./configure +make +make install +cd ../../ + +wget http://download.vicidial.com/beta-apps/asterisk-13.17.1-vici.tar.gz +tar xvfz asterisk-13.17.1-vici.tar.gz +cd asterisk-13.17.1-vici/ +./configure --with-dahdi=/usr/src/asterisk/dahdi-linux-complete-2.11.1+2.11.1/ --with-gsm=internal --with-ogg=/usr/lib64/ +make menuselect +make +make install +asterisk -vvvvvvvvvvvvvvvvvvgc + + + + + + + + + + + +### Stock Asterisk from Digium example install + +#### Asterisk 13 +# NOTE: The below instructions assume that you already have all prerequisite compilation tools and libraries installed on your system + +wget http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/dahdi-linux-complete-current.tar.gz +tar xvfz dahdi-linux-complete-current.tar.gz +cd dahdi-linux-complete-2.11.1+2.11.1/ +make +make install +cd tools +./configure +make +make install +cd ../../ + +wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-13-current.tar.gz +tar xvfz asterisk-13-current.tar.gz +cd asterisk-13.17.1/ +wget http://download.vicidial.com/asterisk-patches/leave.h +wget http://download.vicidial.com/asterisk-patches/enter.h +mv -f enter.h apps/enter.h +mv -f leave.h apps/leave.h +./configure --with-dahdi=/usr/src/asterisk/dahdi-linux-complete-2.11.1+2.11.1/ --with-gsm=internal --with-ogg=/usr/lib64/ +make menuselect +make +make install +asterisk -vvvvvvvvvvvvvvvvvvgc + + diff --git a/docs/REQUIRED_APPS_INSTALL.txt b/docs/REQUIRED_APPS_INSTALL.txt index 9f4379cb..dafc918a 100644 --- a/docs/REQUIRED_APPS_INSTALL.txt +++ b/docs/REQUIRED_APPS_INSTALL.txt @@ -625,6 +625,42 @@ asterisk -vvvvvvvvvvvvvvvvvvgc +#### Asterisk 13 +# NOTE: The below instructions assume that you already have all prerequisite compilation tools and libraries installed on your system + +wget http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/dahdi-linux-complete-current.tar.gz +tar xvfz dahdi-linux-complete-current.tar.gz +cd dahdi-linux-complete-2.11.1+2.11.1/ +make +make install +cd tools +./configure +make +make install +cd ../../ + +wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-13-current.tar.gz +tar xvfz asterisk-13-current.tar.gz +cd asterisk-13.17.1/ +wget http://download.vicidial.com/asterisk-patches/leave.h +wget http://download.vicidial.com/asterisk-patches/enter.h +mv -f enter.h apps/enter.h +mv -f leave.h apps/leave.h +./configure --with-dahdi=/usr/src/asterisk/dahdi-linux-complete-2.11.1+2.11.1/ --with-gsm=internal --with-ogg=/usr/lib64/ +make menuselect +make +make install +asterisk -vvvvvvvvvvvvvvvvvvgc + + + + + + + + + + #### pureftpd FTP server installation instructions #### diff --git a/docs/conf_examples/extensions.conf.sample-13 b/docs/conf_examples/extensions.conf.sample-13 new file mode 100644 index 00000000..49772910 --- /dev/null +++ b/docs/conf_examples/extensions.conf.sample-13 @@ -0,0 +1,684 @@ +[general] +static=yes +writeprotect=no + +[globals] +CONSOLE=Console/dsp ; Console interface for demo +TRUNK=DAHDI/r1 ; Trunk interface +TRUNKX=DAHDI/r2 ; 2nd trunk interface +TRUNKIAX=IAX2/ASTtest1:test@10.10.10.16:4569 ; IAX trunk interface +TRUNKIAX1=IAX2/ASTtest1:test@10.10.10.16:4569 ; IAX trunk interface +TRUNKBINFONE=IAX2/1112223333:PASSWORD@iax.binfone.com ; IAX trunk interface +SIPtrunk=SIP/1234:PASSWORD@sip.provider.net ; SIP trunk + +#include extensions-vicidial.conf + +[trunkinbound] +; DID call routing process +; exten => _XXXXXXXXXX,1,AGI(agi-DID_route.agi) ; use this one instead of the one below if you are having delay issues, and match to number of received digits +exten => _X.,1,AGI(agi-DID_route.agi) +exten => _X.,n,Hangup() +; If you have DIDs that arrive with a plus sign at the beginning then uncomment +;exten => _+X.,1,AGI(agi-DID_route.agi) +;exten => _+X.,n,Hangup() +; If you have DIDs that arrive with a plus and 1 at the beginning that you want to filter out, then uncomment +;exten => _+1X.,1,Goto(trunkinbound,${EXTEN:2},1) + +; FastAGI for VICIDIAL/astGUIclient call logging +exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME}-----${HANGUPCAUSE(${HANGUPCAUSE_KEYS()},tech)})) + +[loopback-no-log] +; This context is to accept calls that have already been logged in another context in Vicidial +; and has been sent through one of the loopbacks. This is why this context is missing the h extension. +; Do not put any extensions in this context unless you specifically understand what this means. + +;exten => _91NXXNXXXXXX,1,Dial(${TRUNKX}/${EXTEN:1},,To) +;exten => _91NXXNXXXXXX,n,Hangup() + +; special Canadian PRI callerIDname settings FOR USE IN LOOPBACK CONTEXT ONLY +;exten => _91NXXNXXXXXX,1,Set(CALLERID(name)="ACME Widgets") +;exten => _91NXXNXXXXXX,n,AGI(agi-CANADA_PRI_CIDname.agi) +;exten => _91NXXNXXXXXX,n,Dial(${TRUNKX}/${EXTEN:1},,To) +;exten => _91NXXNXXXXXX,n,Hangup() + +exten => _999XX11112,1,Wait(2) +exten => _999XX11112,n,Answer() +exten => _999XX11112,n,Playback(ss-noservice) +exten => _999XX11112,n,Playback(vm-goodbye) +exten => _999XX11112,n,Hangup() + +[default] +include => vicidial-auto + +; Local agent alert extensions +exten => _8600XXX*.,1,AGI(agi-VDADfixCXFER.agi) +exten => _8600XXX*.,n,Hangup() +exten => _78600XXX*.,1,AGI(agi-VDADfixCXFER.agi) +exten => _78600XXX*.,n,Hangup() + +; Local blind monitoring +exten => _08600XXX,1,Dial(${TRUNKblind}/6${EXTEN:1},55,To) +exten => _08600XXX,n,Hangup() + + +; playback of recorded prompts +exten => _851XXXXX,1,Answer() +exten => _851XXXXX,n,Playback(${EXTEN}) +exten => _851XXXXX,n,Hangup() + +; this is used for playing a message to an answering machine forwarded from AMD in VICIDIAL +exten => _6851XXXXX,1,Answer() +exten => _6851XXXXX,n,WaitForSilence(2000,1,90) +exten => _6851XXXXX,n,Playback(sip-silence) +exten => _6851XXXXX,n,Playback(${EXTEN:1}) +exten => _6851XXXXX,n,Hangup() +exten => _7851XXXXX,1,WaitForSilence(2000,2) ; AMD got machine. leave message after recording +exten => _7851XXXXX,n,Playback(${EXTEN:1}) +exten => _7851XXXXX,n,AGI(VD_amd_post.agi,${EXTEN:1}) +exten => _7851XXXXX,n,Hangup() + + +; FastAGI for VICIDIAL/astGUIclient call logging +exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME}-----${HANGUPCAUSE(${HANGUPCAUSE_KEYS()},tech)})) + +; Example phone extensions +; 100-350 phone extensions now auto-generated, so no need to uncommend them +; extensions for other SIP and IAX call center phones +; cc100-cc150 SIP Phones +;exten => _1[0-5]X,1,Dial(sip/cc${EXTEN},20,to) +;exten => _1[0-5]X,n,Hangup() +; cc300-cc350 IAX Phones +;exten => _3[0-5]X,1,Dial(IAX2/cc${EXTEN},20,to) +;exten => _3[0-5]X,n,Hangup() +; extensions if using a T1 channelbank +;exten => _19XX,1,Dial(Zap/${EXTEN:2},30,o) +;exten => _19XX,n,Hangup() +; Extension 4001 rings Zap phone (this example for FXS on Zap port 1) +;exten => 4001,1,Dial(Zap/1,30,o) ; ring Zap device 1 +;exten => 4001,n,Voicemail(u4001) ; Send to voicemail... +;exten => 4001,n,Hangup() + + +; # timeout invalid rules +exten => #,1,Playback(invalid) ; "Thanks for trying the demo" +exten => #,2,Hangup() ; Hang them up. +exten => t,1,Goto(#,1) ; If they take too long, give up +exten => t,n,Hangup() +exten => i,1,Playback(invalid) ; "That's not valid, try again" +exten => i,n,Hangup() + + +; Extensions for performance testing +;exten => _91999NXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => _91999NXXXXXX,n,Dial(${TRUNKloop}/${EXTEN:2},,tTo) +;exten => _91999NXXXXXX,n,Hangup() +;exten => 999999999999,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => 999999999999,n,Dial(${TRUNKloop}/${EXTEN:1},,tTo) +;exten => 999999999999,n,Hangup() + +; This is a loopback dialaround to allow for hearing of ringing for 3way calls +exten => _881NXXNXXXXXX,1,Answer() +exten => _881NXXNXXXXXX,n,Dial(${TRUNKloop}/9${EXTEN:2},,To) +exten => _881NXXNXXXXXX,n,Hangup() + +; Vtiger fax and email log extensions +exten => _9118XXXXXXXX,1,Dial(${TRUNKblind}/9998818112,55,to) +exten => _9118XXXXXXXX,n,Hangup() +exten => _9119XXXXXXXX,1,Dial(${TRUNKblind}/9998819112,55,to) +exten => _9119XXXXXXXX,n,Hangup() + + +; CARRIER DIALING EXTENSIONS, USE THE ADMIN INTERFACE TO PROGRAM THESE +; dial an 800 outbound number +;exten => _91800NXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => _91800NXXXXXX,n,Dial(${TRUNK}/${EXTEN:1},,To) +;exten => _91800NXXXXXX,n,Hangup() +;exten => _91888NXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => _91888NXXXXXX,n,Dial(${TRUNK}/${EXTEN:1},,To) +;exten => _91888NXXXXXX,n,Hangup() +;exten => _91877NXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => _91877NXXXXXX,n,Dial(${TRUNK}/${EXTEN:1},,To) +;exten => _91877NXXXXXX,n,Hangup() +;exten => _91866NXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => _91866NXXXXXX,n,Dial(${TRUNK}/${EXTEN:1},,To) +;exten => _91866NXXXXXX,n,Hangup() +;exten => _91855NXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => _91855NXXXXXX,n,Dial(${TRUNK}/${EXTEN:1},,To) +;exten => _91855NXXXXXX,n,Hangup() + +; dial a long distance outbound number +; This 'o' Dial flag is VERY important for VICIDIAL on outbound calls +;exten => _91NXXNXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => _91NXXNXXXXXX,n,Dial(${TRUNKX}/${EXTEN:1},,To) +;exten => _91NXXNXXXXXX,n,Hangup() + +; dial a local outbound number (modified because of only LD T1) +;exten => _9NXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => _9NXXXXXX,n,Dial(${TRUNK}/1727${EXTEN:1},,To) +;exten => _9NXXXXXX,n,Hangup() + +; dial a local 727 outbound number with area code +;exten => _9727NXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => _9727NXXXXXX,n,Dial(${TRUNK}/1${EXTEN:1},,To) +;exten => _9727NXXXXXX,n,Hangup() + +; dial a long distance outbound number to the UK +; This 'o' Dial flag is VERY important for VICIDIAL on outbound calls, +;exten => _901144XXXXXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => _901144XXXXXXXXXX,n,Dial(${TRUNKX}/${EXTEN:1},55,To) +;exten => _901144XXXXXXXXXX,n,Hangup() + +; dial a long distance outbound number to Australia +; This 'o' Dial flag is VERY important for VICIDIAL on outbound calls, +;exten => _901161XXXXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +;exten => _901161XXXXXXXXX,n,Dial(${TRUNKX}/${EXTEN:1},,To) +;exten => _901161XXXXXXXXX,n,Hangup() + +; dial a long distance outbound number through BINFONE +; exten => _91NXXNXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91NXXNXXXXXX,n,Dial(${TRUNKIAX}/${EXTEN:1},55,To) +; exten => _91NXXNXXXXXX,n,Hangup() +; dial a long distance outbound number through a SIP provider +; exten => _91NXXNXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91NXXNXXXXXX,n,Dial(sip/${EXTEN:1}@SIPtrunk,55,o) +; exten => _91NXXNXXXXXX,n,Hangup() +; special extensions for North America to catch invalid phone numbers +; exten => _91XXX[0-1]XXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91XXX[0-1]XXXXXX,n,Dial(${TRUNKloop}/8889990011112,,to) +; exten => _91XXX[0-1]XXXXXX,n,Hangup() +; exten => _91[0-1]XXXXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91[0-1]XXXXXXXXX,n,Dial(${TRUNKloop}/8889990011112,,to) +; exten => _91[0-1]XXXXXXXXX,n,Hangup() +; exten => _91XXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91XXXXXX,n,Dial(${TRUNKloop}/8889990011112,,to) +; exten => _91XXXXXX,n,Hangup() +; exten => _91XXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91XXXXXXX,n,Dial(${TRUNKloop}/8889990011112,,to) +; exten => _91XXXXXXX,n,Hangup() +; exten => _91XXXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91XXXXXXXX,n,Dial(${TRUNKloop}/8889990011112,,to) +; exten => _91XXXXXXXX,n,Hangup() +; exten => _91XXXXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91XXXXXXXXX,n,Dial(${TRUNKloop}/8889990011112,,to) +; exten => _91XXXXXXXXX,n,Hangup() +; exten => _91XXXXXXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91XXXXXXXXXXX,n,Dial(${TRUNKloop}/8889990011112,,to) +; exten => _91XXXXXXXXXXX,n,Hangup() +; exten => _91XXXXXXXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91XXXXXXXXXXXX,n,Dial(${TRUNKloop}/8889990011112,,to) +; exten => _91XXXXXXXXXXXX,n,Hangup() +; exten => _91XXXXXXXXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91XXXXXXXXXXXXX,n,Dial(${TRUNKloop}/8889990011112,,to) +; exten => _91XXXXXXXXXXXXX,n,Hangup() +; block calls to 555 numbers +; exten => _91NXX555NXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91NXX555NXXX,n,Dial(${TRUNKloop}/8889990011112,,to) +; exten => _91NXX555NXXX,n,Hangup() +; dial a USA long distance outbound number through the loopback-no-log context +; exten => _91NXXNXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => _91NXXNXXXXXX,n,Dial(${TRUNKloop}/888${EXTEN:2},55,o) +; exten => _91NXXNXXXXXX,n,Hangup() +;exten => _888NXXNXXXXXX,1,Goto(loopback-no-log,91${EXTEN:3},1) +;exten => _888NXXNXXXXXX,n,Hanguo() + +exten => 8889990011112,1,Goto(loopback-no-log,9990011112,1) +exten => 8889990011112,n,Hanguo() + + +; Inbound call from BINFONE +; exten => 1112223333,1,AGI(agi://127.0.0.1:4577/call_log) +; exten => 1112223333,n,Dial(sip/gs102,55,o) +; exten => 1112223333,n,Hangup() + +; Extension 7275551212 - Inbound local number from PRI with 10 digit delivery +;exten => 7275551212,1,Ringing() +;exten => 7275551212,n,Wait(1) +;exten => 7275551212,n,AGI(agi://127.0.0.1:4577/call_log--fullCID--${EXTEN}-----${CALLERID(all)}-----${CALLERID(num)}-----${CALLERID(name)}) +;exten => 7275551212,n,Answer() +;exten => 7275551212,n,Dial(sip/spa2000&sip/spa2001,30,To) +;exten => 7275551212,n,Voicemail(u2000) +;exten => 7275551212,n,Hangup() + +; 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 +; This is not part of VICIDIAL, it is for astGUIclient agent use only + +; Extension 3429 - Inbound 800 number (1-800-555-3429) example of RBS T1 +; with 10 digit ANI and 4 digit DNIS star separated +;exten => _**3429,1,Ringing +;exten => _**3429,n,AGI(agi://127.0.0.1:4577/call_log) +;exten => _**3429,n,AGI(call_inbound.agi,spa2000-----8005553429-----Inbound 800-----x-----y-----z-----w) +;exten => _**3429,n,Answer() +;exten => _**3429,n,Dial(sip/spa2000&sip/spa2001,30,to) +;exten => _**3429,n,Voicemail(u2000) +;exten => _**3429,n,Hangup() +; Extension 3429 - with ANI [callerID] +;exten => _*NXXNXXXXXX*3429,1,Ringing +;exten => _*NXXNXXXXXX*3429,n,AGI(agi://127.0.0.1:4577/call_log) +;exten => _*NXXNXXXXXX*3429,n,AGI(call_inbound.agi,spa2000-----8005553429-----Inbound 800-----x-----y-----z-----w) +;exten => _*NXXNXXXXXX*3429,n,Answer() +;exten => _*NXXNXXXXXX*3429,n,Dial(sip/spa2000&sip/spa2001,30,to) +;exten => _*NXXNXXXXXX*3429,n,Voicemail(u2000) +;exten => _*NXXNXXXXXX*3429,n,Hangup() + + +; parameters for agi-VDAD_ALL_inbound.agi (upto 12 fields separated by five dashes "-----"): +; Below are the parameters needed for the script to be run properly +; 1. the method of call handling for the script: +; - CID - CID received, add record with phone number +; - CIDLOOKUP - Lookup CID to find record in whole system +; - CIDLOOKUPRL - Restrict lookup to one list +; - CIDLOOKUPRC - Restrict lookup to one campaign's lists +; - CLOSER - Closer calls from VICIDIAL fronters +; - ANI - ANI received, add record with phone number (based on RBS T1s) +; - ANILOOKUP - Lookup ANI to find record in whole system +; - ANILOOKUPRL - Restrict lookup to one list +; - ANILOOKUPRC - Restrict lookup to one campaign's lists +; - VID - Add record with Vendor Lead Code received as argument 12 +; - VIDLOOKUP - Lookup Vendor Lead Code received as argument 12 to find record in whole system +; - VIDLOOKUPRL - Restrict lookup to one list (argument 12) +; - VIDLOOKUPRC - Restrict lookup to one campaign's lists (argument 12) +; - VIDPROMPT - Prompt Vendor Lead Code to User with IVR to add record with Vendor Lead Code +; - VIDPROMPTLOOKUP - Prompt Vendor Lead Code to User with IVR to find record in whole system +; - VIDPROMPTLOOKUPRL - Restrict lookup to one list +; - VIDPROMPTLOOKUPRC - Restrict lookup to one campaign's lists +; - 3DIGITID - Enter 3 digit code to go to agent +; - 4DIGITID - Enter 4 digit code to go to agent +; - XDIGITID - Enter X digit code to go to agent(variable, i.e. 9DIGITID, 12DIGITID, etc...) +; 2. the method of searching for an available agent: +; - LO - Load Balance Overflow only (priority to home server) +; - LB - Load Balance total system +; - SO - Home server only +; 3. the full name of the IN GROUP to be used in vicidial for the inbound call +; 4. the phone number that was called, for the log entry +; 5. the callerID or lead_id of the person that called(usually overridden) +; 6. the park extension audio file name if used +; 7. the status of the call initially(usually not used) +; 8. the list_id to insert the new lead under if it is new (and CID/ANI available) +; 9. the phone dialing code to insert with the new lead if new (and CID/ANI available) +; 10. the campaign_id to search within lists if CIDLOOKUPRC +; 11. the user to queue the call to for AGENTDIRECT in-group calls +; 12. vendor_lead_code if external mechanism like custom IVR is used to prompt user for ID +; +; inbound VICIDIAL call with CID delivery through T1 PRI +;exten => 1234,1,Answer() ; Answer the line +;exten => 1234,n,AGI(agi-VDAD_ALL_inbound.agi,CID-----LB-----CL_GALLERIA-----7274515134-----Closer-----park----------999-----1) +;exten => 1234,n,Hangup() + +; inbound VICIDIAL transfer calls [can arrive through PRI T1 crossover, IAX or SIP channel] +exten => _90009.,1,Answer() ; Answer the line +exten => _90009.,n,Dial(${TRUNKloop}/9${EXTEN},,to) +exten => _90009.,n,Hangup() +exten => _990009.,1,Answer() ; Answer the line, Sometimes needs to be removed +exten => _990009.,n,AGI(agi-VDAD_ALL_inbound.agi,CLOSER-----LB-----CL_TESTCAMP-----7275551212-----Closer-----park----------999-----1) +exten => _990009.,n,Hangup() +; DID forwarded calls +exten => _99909*.,1,Answer() +exten => _99909*.,n,AGI(agi-VDAD_ALL_inbound.agi) +exten => _99909*.,n,Hangup() + + +; barge monitoring extension +exten => 8159,1,ZapBarge() +exten => 8159,n,Hangup() + +; ZapBarge direct channel extensions +exten => _86120XX,1,ZapBarge(${EXTEN:5}) +exten => _86120XX,n,Hangup() + +; MeetMe Adjustment Extensions +exten => _X48600XXX,1,MeetMeAdmin(${EXTEN:2},T,${EXTEN:0:1}) +exten => _X48600XXX,2,Hangup() + +exten => _X38600XXX,1,MeetMeAdmin(${EXTEN:2},t,${EXTEN:0:1}) +exten => _X38600XXX,2,Hangup() + +exten => _X28600XXX,1,MeetMeAdmin(${EXTEN:2},m,${EXTEN:0:1}) +exten => _X28600XXX,2,Hangup() + +exten => _X18600XXX,1,MeetMeAdmin(${EXTEN:2},M,${EXTEN:0:1}) +exten => _X18600XXX,2,Hangup() + +exten => _55558600XXX,1,MeetMeAdmin(${EXTEN:4},K) +exten => _55558600XXX,2,Hangup() + +; immediate hangup extension +exten => 8300,1,Hangup() + +; astGUIclient conferences +exten => _86000[0-4]X,1,Meetme(${EXTEN},q) +exten => _86000[0-4]X,n,Hangup() + +; VICIDIAL conferences +exten => _86000[5-9]X,1,Meetme(${EXTEN},F) +exten => _86000[5-9]X,n,Hangup() +exten => _8600[1-2]XX,1,Meetme(${EXTEN},F) +exten => _8600[1-2]XX,n,Hangup() + +; quiet entry and leaving conferences for VICIDIAL (inbound announce, SendDTMF and ring-agent) +exten => _78600XXX,1,Meetme(${EXTEN:1},Fq) +exten => _78600XXX,n,Hangup() + +; quiet monitor-only extensions for meetme rooms (for room managers) +exten => _68600XXX,1,Meetme(${EXTEN:1},Fmq) +exten => _68600XXX,n,Hangup() + +; Asterisk 1.8 workaround +exten => _58600XXX,1,Meetme(${EXTEN:1},Fmq) +exten => _58600XXX,n,Hangup() + +; quiet monitor-only entry and leaving conferences for VICIDIAL (recording) +exten => _558600XXX,1,Meetme(${EXTEN:2},Fmq) +exten => _558600XXX,n,Hangup() + +; voicelab exten +exten => _86009XX,1,Meetme(${EXTEN},Fmq) +; voicelab exten moderator +exten => _986009XX,1,Meetme(${EXTEN:1}) + + + +; park channel for client GUI parking, hangup after 30 minutes +; create a GSM formatted audio file named "park.gsm" that is 30 minutes long +; and put it in /var/lib/asterisk/sounds +exten => 8301,1,Answer() +exten => 8301,n,AGI(park_CID.agi) +exten => 8301,n,Playback(park) +exten => 8301,n,Hangup() +exten => 8303,1,Answer() +exten => 8303,n,AGI(park_CID.agi) +exten => 8303,n,Playback(conf) +exten => 8303,n,Hangup() + +; park channel for client GUI conferencing, hangup after 30 minutes +; create a GSM formatted audio file named "conf.gsm" that is 30 minutes long +; and put it in /var/lib/asterisk/sounds +exten => 8302,1,Answer() +exten => 8302,n,Playback(conf) +exten => 8302,n,Hangup() + +exten => 8304,1,Answer() +exten => 8304,n,Playback(ding) +exten => 8304,n,Hangup() + +; default audio for safe harbor 2-second-after-hello message then hangup +; create a GSM formatted audio file complies with safe harbor rules +; and put it in /var/lib/asterisk/sounds then change filename below +exten => 8307,1,Answer() +exten => 8307,n,Playback(vm-goodbye) +exten => 8307,n,Hangup() + +; this is used for playing a message to an answering machine forwarded from AMD in VICIDIAL +exten => 8320,1,AGI(VD_amd.agi,${EXTEN}-----YES) +exten => 8320,n,Hangup() +exten => _8320*.,1,AGI(VD_amd.agi,${EXTEN}-----YES) +exten => _8320*.,n,Hangup() + +; 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,AGI(agi-VDAD_RINGALL.agi,${EXTEN}) +exten => _8331*.,n,Hangup() + + +; use for selective CallerID hangup by area code(hard-coded) +exten => 8352,1,AGI(agi-VDADselective_CID_hangup.agi,${EXTEN}) +exten => 8352,n,Playback(safe_harbor) +exten => 8352,n,Hangup() + +; this is used for sending DTMF signals within conference calls, the client app +; sends the digits to be played in the callerID field +; sound files must be placed in /var/lib/asterisk/sounds +exten => 8500998,1,Answer() +exten => 8500998,n,Playback(silence) +exten => 8500998,n,AGI(agi-dtmf.agi) +exten => 8500998,n,Hangup() + +; multi-remote-monitor entry extensions +exten => 8162,1,Dial(${TRUNKblind}/34567890123456789,55,to) +exten => 8162,n,Hangup() + +exten => 34567890123456789,1,Answer() +exten => 34567890123456789,n,Goto(monitor,s,1) +exten => 34567890123456789,n,Hangup() + +;#### VDAD STANDARD TRANSFER ENTRIES #### +; Below are the parameters needed for the agi-VDAD_ALL_outbound.agi script to be run properly +; 1. the method of call handling for the script: +; - NORMAL - Standard outbound routing to agent +; - TEST - For performance testing only +; - BROADCAST - For no-agent broadcast dialing +; - SURVEY - For survery question then on to agent +; - REMINDER - Reminder campaign +; - REMINDX - Reminder with transfer to agent +; 2. the method of searching for an available agent: +; - LB - Load Balance total system +; - LO - Load Balance Overflow only (priority to home server) +; - SO - Home server only +; 3. the sound file to play when doing a SURVEY, REMINDER, REMINDX campaign +; 4. the acceptible dtmf digits for a SURVEY +; 5. the out-opt digit for a SURVEY (must be in the digit map) +; 6. the sound file to play for a SURVEY when transfering to an agent +; 7. the sound file to play for a SURVEY when DNCing the call +; 8. OPTIN or OPTOUT: if OPTIN call is only sent to agent with button press +; if OPTOUT call is sent to agent if no button press at all +; 9. the status that is use for a SURVEY when someone opts out +; if the status is DNC it will also add them to the internal dnc table + +; Local channel resolution fix for Asterisk 13 +exten => _1383XX,1,AGI(agi-VDAD_local_optimize.agi,${CONNECTEDLINE(name)}) +exten => _1383XX,n,Wait(2) +exten => _1383XX,n,Hangup() + +exten => _138331*.,1,AGI(agi-VDAD_local_optimize.agi,${CONNECTEDLINE(name)}) +exten => _138331*.,n,Wait(2) +exten => _138331*.,n,Hangup() + +; VICIDIAL_auto_dialer transfer script for no-agent campaigns: +exten => 8364,1,Playback(sip-silence) +exten => 8364,n,AGI(agi://127.0.0.1:4577/call_log) +exten => 8364,n,AGI(agi-VDAD_ALL_outbound.agi,NORMAL-----LB) +exten => 8364,n,AGI(agi-VDAD_ALL_outbound.agi,NORMAL-----LB) +exten => 8364,n,Hangup() + +; VICIDIAL_auto_dialer transfer script: +exten => 8365,1,Playback(sip-silence) +exten => 8365,n,AGI(agi://127.0.0.1:4577/call_log) +exten => 8365,n,AGI(agi-VDAD_ALL_outbound.agi,NORMAL-----SO) +exten => 8365,n,AGI(agi-VDAD_ALL_outbound.agi,NORMAL-----SO) +exten => 8365,n,Hangup() + +; VICIDIAL_auto_dialer transfer script SURVEY at beginning: +exten => 8366,1,Playback(sip-silence) +exten => 8366,n,AGI(agi://127.0.0.1:4577/call_log) +exten => 8366,n,AGI(agi-VDAD_ALL_outbound.agi,SURVEYCAMP-----LB) +exten => 8366,n,AGI(agi-VDAD_ALL_outbound.agi,SURVEYCAMP-----LB) +exten => 8366,n,Hangup() + +; VICIDIAL_auto_dialer transfer script Load Balance Overflow: +exten => 8367,1,Playback(sip-silence) +exten => 8367,n,AGI(agi://127.0.0.1:4577/call_log) +exten => 8367,n,AGI(agi-VDAD_ALL_outbound.agi,NORMAL-----LO) +exten => 8367,n,AGI(agi-VDAD_ALL_outbound.agi,NORMAL-----LO) +exten => 8367,n,Hangup() + +; VICIDIAL_auto_dialer transfer script Load Balanced: +exten => 8368,1,Playback(sip-silence) +exten => 8368,n,AGI(agi://127.0.0.1:4577/call_log) +exten => 8368,n,AGI(agi-VDAD_ALL_outbound.agi,NORMAL-----LB) +exten => 8368,n,AGI(agi-VDAD_ALL_outbound.agi,NORMAL-----LB) +exten => 8368,n,Hangup() + +; VICIDIAL_auto_dialer transfer script AMD with Load Balanced: +exten => 8369,1,Playback(sip-silence) +exten => 8369,n,AGI(agi://127.0.0.1:4577/call_log) +exten => 8369,n,AMD(2000,2000,1000,5000,120,50,4,256) +exten => 8369,n,AGI(VD_amd.agi,${EXTEN}) +exten => 8369,n,AGI(agi-VDAD_ALL_outbound.agi,NORMAL-----LB) +exten => 8369,n,AGI(agi-VDAD_ALL_outbound.agi,NORMAL-----LB) +exten => 8369,n,Hangup() + +; VICIDIAL auto-dial reminder script +exten => 8372,1,Playback(sip-silence) +exten => 8372,n,AGI(agi://127.0.0.1:4577/call_log) +exten => 8372,n,AGI(agi-VDADautoREMINDER.agi,${EXTEN}) +exten => 8372,n,AGI(agi-VDADautoREMINDER.agi,${EXTEN}) +exten => 8372,n,Hangup() + +; VICIDIAL SURVEY transfer script AMD with Load Balanced: +exten => 8373,1,Playback(sip-silence) +exten => 8373,n,AGI(agi://127.0.0.1:4577/call_log) +exten => 8373,n,AMD(2000,2000,1000,5000,120,50,4,256) +exten => 8373,n,AGI(VD_amd.agi,${EXTEN}) +exten => 8373,n,AGI(agi-VDAD_ALL_outbound.agi,SURVEYCAMP-----LB) +exten => 8373,n,AGI(agi-VDAD_ALL_outbound.agi,SURVEYCAMP-----LB) +exten => 8373,n,Hangup() + +; VICIDIAL SURVEY transfer script with Cepstral names: +exten => 8374,1,Playback(sip-silence) +exten => 8374,n,AGI(agi://127.0.0.1:4577/call_log) +exten => 8374,n,AGI(agi-VDAD_ALL_outbound.agi,SURVEYCAMPCEP-----LB) +exten => 8374,n,AGI(agi-VDAD_ALL_outbound.agi,SURVEYCAMPCEP-----LB) +exten => 8374,n,Hangup() + +; VICIDIAL SURVEY transfer script AMD with Cepstral variables: +exten => 8375,1,Playback(sip-silence) +exten => 8375,n,AGI(agi://127.0.0.1:4577/call_log) +exten => 8375,n,AMD(2000,2000,1000,5000,120,50,4,256) +exten => 8375,n,AGI(VD_amd.agi,${EXTEN}) +exten => 8375,n,AGI(agi-VDAD_ALL_outbound.agi,SURVEYCAMPCEP-----LB) +exten => 8375,n,AGI(agi-VDAD_ALL_outbound.agi,SURVEYCAMPCEP-----LB) +exten => 8375,n,Hangup() + +; BETA VICIDIAL_auto_dialer transfer script Load Balanced: +exten => 8377,1,Playback(sip-silence) +exten => 8377,n,AGI(agi://127.0.0.1:4577/call_log) +exten => 8377,n,Set(LRct=1) +exten => 8377,n,While($[${LRct} < 100]) +exten => 8377,n,AGI(agi-VDAD_ALL_outboundBETA.agi,NORMAL-----LB) +exten => 8377,n,Set(LRct=$[${LRct} + 1]) +exten => 8377,n,EndWhile() +exten => 8377,n,AGI(agi-VDAD_ALL_outboundBETA.agi,NORMAL-----LB) +exten => 8377,n,Hangup() + + +; PERFORMANCE TESTING +exten => _999XXXXXX1,1,Answer() +exten => _999XXXXXX1,n,Wait(2) +exten => _999XXXXXX1,n,Playback(vicidial-welcome) +exten => _999XXXXXX1,n,Hangup() + +exten => _999XX11112,1,Wait(2) +exten => _999XX11112,n,Answer() +exten => _999XX11112,n,Playback(ss-noservice) +exten => _999XX11112,n,Playback(vm-goodbye) +exten => _999XX11112,n,Hangup() + +exten => _999XX18112,1,Wait(2) +exten => _999XX18112,n,Answer() +exten => _999XX18112,n,Playback(vtiger-fax) +exten => _999XX18112,n,Playback(vtiger-fax) +exten => _999XX18112,n,Hangup() + +exten => _999XX19112,1,Wait(2) +exten => _999XX19112,n,Answer() +exten => _999XX19112,n,Playback(vtiger-email) +exten => _999XX19112,n,Playback(vtiger-email) +exten => _999XX19112,n,Hangup() + +exten => _999XXXX112,1,Wait(5) +exten => _999XXXX112,n,Answer() +exten => _999XXXX112,n,Playback(demo-instruct) +exten => _999XXXX112,n,Playback(demo-instruct) +exten => _999XXXX112,n,Hangup() + +exten => _999XXXXXX2,1,Wait(8) +exten => _999XXXXXX2,n,Answer() +exten => _999XXXXXX2,n,Playback(demo-instruct) +exten => _999XXXXXX2,n,Hangup() + +exten => _999XXXXXX3,1,Set(PRI_CAUSE=1) +exten => _999XXXXXX3,n,Hangup() + +exten => _999XXXXXX4,1,Set(PRI_CAUSE=27) +exten => _999XXXXXX4,n,Hangup() + +exten => _999XXXXXX5,1,Ringing +exten => _999XXXXXX5,n,Wait(120) +exten => _999XXXXXX5,n,Hangup() + +exten => _999XXXXXX6,1,Wait(10) +exten => _999XXXXXX6,n,Answer() +exten => _999XXXXXX6,n,Playback(demo-instruct) +exten => _999XXXXXX6,n,Hangup() + +exten => _999XXXXXX7,1,Wait(12) +exten => _999XXXXXX7,n,Answer() +exten => _999XXXXXX7,n,Playback(demo-enterkeywords) +exten => _999XXXXXX7,n,Hangup() + +exten => _999XXXXXX8,1,Set(PRI_CAUSE=17) +exten => _999XXXXXX8,n,Hangup() + +exten => _999XXXXXX9,1,Wait(6) +exten => _999XXXXXX9,n,Answer() +exten => _999XXXXXX9,n,Playback(demo-abouttotry) +exten => _999XXXXXX9,n,Hangup() + +exten => _999XXXXXX0,1,Wait(5) +exten => _999XXXXXX0,n,Answer() +exten => _999XXXXXX0,n,Playback(vm-goodbye) +exten => _999XXXXXX0,n,Hangup() + +;exten => 99999999999,1,Answer() +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Playback(conf) +;exten => 99999999999,n,Hangup() + + +[monitor] +exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME}-----${HANGUPCAUSE(${HANGUPCAUSE_KEYS()},tech)})) +exten => s,1,Set(TIMEOUT(digit)=10) +exten => s,n,Set(TIMEOUT(response)=10) +exten => s,n,Set(MEETME_EXIT_CONTEXT=monitor_exit) +exten => s,n,Background(vm-extension) ; need audio prompt. +exten => s,n,WaitExten(10) +exten => s,n,Hangup() + +exten => i,1,Goto(monitor_exit,s,1) +exten => i,n,Hangup() +exten => #,1,Goto(monitor_exit,s,1) +exten => #,n,Hangup() +exten => t,1,Goto(monitor_exit,s,1) +exten => t,n,Hangup() + +exten => _8[0-2]XX,1,Meetme(8600${EXTEN:1},mqX) ; Listen +exten => _8[0-2]XX,n,Hangup() +exten => _99[0-2]XX,1,Meetme(8600${EXTEN:2},X) ; Barge +exten => _99[0-2]XX,n,Hangup() + +[monitor_exit] +exten => h,1,AGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME}-----${HANGUPCAUSE(${HANGUPCAUSE_KEYS()},tech)})) +exten => _X,1,Goto(monitor,s,1) +exten => _X,n,Hangup() + +exten => i,1,Goto(monitor,s,1) +exten => i,n,Hangup() +exten => #,1,Goto(monitor,s,1) +exten => #,n,Hangup() +exten => t,1,Goto(monitor,s,1) +exten => t,n,Hangup() diff --git a/docs/conf_examples/manager.conf.sample-13 b/docs/conf_examples/manager.conf.sample-13 new file mode 100644 index 00000000..c7aad88b --- /dev/null +++ b/docs/conf_examples/manager.conf.sample-13 @@ -0,0 +1,38 @@ +[general] +enabled = yes +port = 5038 +bindaddr = 0.0.0.0 + +[cron] +secret = 1234 +read = system,call,log,verbose,command,agent,user,originate +write = system,call,log,verbose,command,agent,user,originate + +[updatecron] +secret = 1234 +read = command,reporting +write = command,reporting + +eventfilter=Event: CoreShowChannel + + +[listencron] +secret = 1234 +read = system,call,log,verbose,command,agent,user,dtmf +write = command + +eventfilter=Event: Shutdown +eventfilter=Event: DTMFBegin +eventfilter=Event: DTMFEnd +eventfilter=Event: CPD-Result +eventfilter=Event: SIP-Hangup-Cause +eventfilter=Event: NewCallerid +eventfilter=Event: Newstate +eventfilter=Event: Hangup +eventfilter=!Event: HangupRequest + + +[sendcron] +secret = 1234 +read = command +write = system,call,log,verbose,command,agent,user,originate diff --git a/extras/MySQL_AST_CREATE_tables.sql b/extras/MySQL_AST_CREATE_tables.sql index 9a366c7c..5cf4badf 100644 --- a/extras/MySQL_AST_CREATE_tables.sql +++ b/extras/MySQL_AST_CREATE_tables.sql @@ -1723,7 +1723,8 @@ system_ip_blacklist VARCHAR(30) default '', agent_push_events ENUM('0','1') default '0', agent_push_url TEXT, hide_inactive_lists ENUM('0','1') default '0', -allow_manage_active_lists ENUM('0','1') default '0' +allow_manage_active_lists ENUM('0','1') default '0', +expired_lists_inactive ENUM('0','1') default '0' ) ENGINE=MyISAM; CREATE TABLE vicidial_campaigns_list_mix ( @@ -4071,4 +4072,4 @@ UPDATE vicidial_configuration set value='1766' where name='qc_database_version'; UPDATE system_settings set vdc_agent_api_active='1'; -UPDATE system_settings SET db_schema_version='1515',db_schema_update_date=NOW(),reload_timestamp=NOW(); +UPDATE system_settings SET db_schema_version='1516',db_schema_update_date=NOW(),reload_timestamp=NOW(); diff --git a/extras/upgrade_2.14.sql b/extras/upgrade_2.14.sql index 9e965c02..3dcff9c1 100644 --- a/extras/upgrade_2.14.sql +++ b/extras/upgrade_2.14.sql @@ -370,3 +370,7 @@ CREATE TABLE vicidial_xfer_log_archive LIKE vicidial_xfer_log; ALTER TABLE vicidial_xfer_log_archive MODIFY xfercallid INT(9) UNSIGNED NOT NULL; UPDATE system_settings SET db_schema_version='1515',db_schema_update_date=NOW() where db_schema_version < 1515; + +ALTER TABLE system_settings ADD expired_lists_inactive ENUM('0','1') default '0'; + +UPDATE system_settings SET db_schema_version='1516',db_schema_update_date=NOW() where db_schema_version < 1516; diff --git a/install.pl b/install.pl index df122524..93a839d2 100644 --- a/install.pl +++ b/install.pl @@ -1,8 +1,8 @@ #!/usr/bin/perl -# install.pl version 2.12 +# install.pl version 2.14 # -# Copyright (C) 2016 Matt Florell LICENSE: AGPLv2 +# Copyright (C) 2017 Matt Florell LICENSE: AGPLv2 # # CHANGES @@ -42,6 +42,7 @@ # 151029-0650 - Added Asterisk 11 as listed option, added new sample voicemail.conf for 1.8 and higher # 151212-0840 - Added chat_customer web directory, removed static language build actions # 160101-0907 - Changed ip_relay code to look for installed package +# 170915-1458 - Added Asterisk 13 compability pieces # ############################################ @@ -1845,6 +1846,7 @@ else print " 1.4\n"; print " 1.8\n"; print " 11.X\n"; + print " 13.X\n"; print "Enter asterisk version or press enter for default: [$VARasterisk_version] "; $PROMPTasterisk_version = ; chomp($PROMPTasterisk_version); @@ -2649,11 +2651,22 @@ if ( ($PROMPTcopy_conf_files =~ /y/i) || ($CLIcopy_conf_files =~ /y/i) ) } else { - `cp -f ./docs/conf_examples/extensions.conf.sample-1.4 /etc/asterisk/extensions.conf`; - `cp -f ./docs/conf_examples/iax.conf.sample-1.4 /etc/asterisk/iax.conf`; - `cp -f ./docs/conf_examples/sip.conf.sample-1.4 /etc/asterisk/sip.conf`; - `cp -f ./docs/conf_examples/manager.conf.sample /etc/asterisk/manager.conf`; - `cp -f ./docs/conf_examples/voicemail.conf.sample /etc/asterisk/voicemail.conf`; + if ($VARasterisk_version =~ /^13/) + { + `cp -f ./docs/conf_examples/extensions.conf.sample-13 /etc/asterisk/extensions.conf`; + `cp -f ./docs/conf_examples/iax.conf.sample-1.4 /etc/asterisk/iax.conf`; + `cp -f ./docs/conf_examples/sip.conf.sample-1.4 /etc/asterisk/sip.conf`; + `cp -f ./docs/conf_examples/manager.conf.sample-13 /etc/asterisk/manager.conf`; + `cp -f ./docs/conf_examples/voicemail.conf.sample-1.8 /etc/asterisk/voicemail.conf`; + } + else + { + `cp -f ./docs/conf_examples/extensions.conf.sample-1.4 /etc/asterisk/extensions.conf`; + `cp -f ./docs/conf_examples/iax.conf.sample-1.4 /etc/asterisk/iax.conf`; + `cp -f ./docs/conf_examples/sip.conf.sample-1.4 /etc/asterisk/sip.conf`; + `cp -f ./docs/conf_examples/manager.conf.sample /etc/asterisk/manager.conf`; + `cp -f ./docs/conf_examples/voicemail.conf.sample /etc/asterisk/voicemail.conf`; + } } } `cp -f ./docs/conf_examples/meetme.conf.sample /etc/asterisk/meetme.conf`; diff --git a/www/agc/images/folder_closed.png b/www/agc/images/folder_closed.png new file mode 100644 index 0000000000000000000000000000000000000000..d5c46db2aa17334d0bc270269236e284a85c7084 GIT binary patch literal 1846 zcmZ9NcTf`s6vh(*NkAe*wv|Yj3Pb{B$Vd$~NWun#3?YOeq7r16Aw-6SiXaH65lNyf z^$1G@fd&}`DrgD?nF0Z1SXP)}1snft@4esq?!LSC$GiLP-fvD0)-Z|V5&!@IM!@4- zgc=~k3knv_$34<{LIL~PTH^rUz88~SmMe6`L-8IF005%nJ3x!PeoLVVi6q!tL8ipz zfItNqVmkq6NsJj?F7ye${7I>WI`3uvoAQ`?n60>d!4pH|H9{_UQ2sdchJt5p zmOc~zA}H?y6ltujDOW0fEb=AqQBqzQj>O32%c#L#NTm#eWQo z?WYgIrib}Ut)&53-jj=FhOA~rBxxloWJQq3Pn>bzvJrh1=A(H=kLIQST0WnLiAWmeEeaEwK6 zKl?R5cw(Siz^4?y(hlwWR#MWCl}Cx#8TVH|_I_#8^$}w6g){mjY3j6X{O#Em38uDM zA0S%OY8)I4IT)cftmtHxyH^(nXpIR%6|DCi)<##Qa_mZLeyN1eA#9Ylo8n&h#09Tx zQ8aWjMH!VOJq}(17y~krY_L~T6;<*^eoEV}gVs+pHWs_Nxw;bg6=(ML4tu74xj(x{ z__;JeMp3X%g3oHuOz-zI`Jnxl!*V<_?nsrwuxMVBX$F>=yfW@xTW@8PcxQ3QWNkt1 zvXa>kMenHS$-mlYb=kv!axsB_m1AQ$G7iQ&QT37H_+eGg#BrtJ^77tx;H~EM2R`{O zcRTan5Z%NS6%{p)D>r*}|Ey7^S?Dn^*`j_zqK`y2;ROw1%T+QnhcxLsoM-{B0`;m? z^XyHxxvjXMYZXP$p2;)bJ#B66qg7YGjZ(t*VSnTqKTb?LPt@U!d#HuDE@V+|W>n2I zXIdN%53!o+DldN0Sa6loO+;ki1H_eYR2DV7=FhUF#*7vHoowI|yB_T8N+?v1yX;Z#2RgNsg1$aN)^_1^(Bx?j zU0E%^##uWdHUv^!V#87^k~x@ubkhKX(OO}*D3cjsE(7f&25nO+{MCgoIV0~e*F}Q0Rq_$!dC^;$I|ut1>`ukhQ5fgWX{~bRtf6)enmgPSY6O?;xNQ#yc0b*& znZxm4Wl!q*G`qWAx}>|KF4%=qkT|JbaT1!cjWIUfw8N zR({xt+>@l}6XqBSxvKB`d z-SP9C@`;=6g^}fy>~wSW8b9%ZCc5u+?WwoKv#*eHa#ublUe;lm4A|y*_fE)9aahXp z{qBP)WI2?&?0R*OGkPfLj>y2L*@MuR>m3tedbUV|yGYsfrp6rQBl>u_-mm0dYTt}> ztgOu_ta&HN*Q?Fl?DNr2;o`I$G^tJhUMe;fs*3wR(nwX@e@TYIk^cji4u$_0E;haJ znon>Q?0qq6!(XoTgWdY`JNJNUuT3Oj9SdJEmb#h|5^s?R#+(%Oz`PD~)pJ}lb`JEX zk+2c!v*_JhkpK&^1H&N~YHaC+K0e@_8hiMm zljkAmGi*CPB+i2h+$Jo|-BC!Q&W_QpDgko=TR(j*(HYhFRbytpo9v9>oDXl+!@~000McNliru;RzK10R>m#LfCq9$rGB`E#CPs~t>@i8pxF%Wm_jaixLtXh?dn8OG%IXOjd-w2bF)B2$<6L<+^8&Ix* zTv=Hl9@HD3{E?k!p4!KT^_g=5a?v|YWmPMmepVXKz#>aWN|A zArQ}kxCFRxdoF)?>nXNwy^ZALM3R!Oe63iXOy1_T*lh&_f)TJ)2%{P3*Hp@3Xo zc_4lU!uqvI^1~RG8*-Hda1S|nMfN`_BtfjzKAQxB` zZngrr1;l+IY%_m3EiHw6_iVko7n#-RJpbH-w6ylo*wi}{N)qsE-~o^>pc9y0#5$V> z`hhxN=vurO+Ce-6JP4!#7F`h*{Rf_SyqI_X^c+b^iC6uA@Ba03e)Zb^C<8r!lz?31 zMl1m@Py_M<;N4h0!Mgw^q#Ea2f(o6{P@o}tOyOJM2S;8+~d6av0Z;Ab% zEd+(z*Hcuqk(<(&apA&6E=*j+?+;uLP?iEg-~iw^a10TD0rB)q%l-Sdap#T=ELjqo z3nVT{AUit)t2Kw)H)LV4SQe!U`uay`YU-h*bBOcjCkY0Fi!*pg=qUxwpsT<<#i`%E~n!YB{hX7Uf&! z>dq`ekdd(hvnwvnLQ>L_Xr9JmG!Uh0AO%DLQBpt@5G4iV22uQC-puFoFpEc`RJVPqgbz=^%bjC<=Tz zO#_`ED}euSnXIRwKx%4F^TCIu{OjM93=UmSLBUu{2;lBH{_@kn0g!(LT#E+e<4?+Y z`<>6Iscqxye3nu;Li{kW4CD(yi{XR%$Dfq*#+x5eQ`@dUTwZ&D#|-Zwwa43d`<>6| z=r|MUALA{grKZej1XK|cD2bB3GxN|O8cZRfk+DPr3l zxtGHCW>S0m5WjrwJ$*yXGPH-Zp6cho!7n3VJpb$iy!`X;u_ikMvnnpmLLd+^F(Cf=1S}Zy!_I`riKA&=6}VZ(s9T=fhL zp3~TN7HwklrZuJq;&i#`A2_EsA0^64m6!mTn7D|;<<<=57K^}cx00BcU}_j1j~Az_ z9&Pwb20$Jr%I>h30I93*r20$k_;l;7E3p;lo4$86G0By z8r$w&TUei)X?h?IXFbDb&+E-)`jAP?fSfxwfy1eFR|yGml-R7q$H$o(#`w4gr_Pmw z^n)xVw81s@Kx&V-ak8#MW6NE4iyYU zwJS{zq|{N**qA3`LP}_FOYDIRof(Vhl1rB+P*PH`Xv<2kSB;EZz*W|ucUM#4*;T+0 zAl22UXlU%#*fwpQ?IAU3zmfSJ%hjNV;R%OIq#;0#9&O^( z>3)sPYRzHCjt!=FSH~(_Xm07%o87>%D}8oBKmvgPrH*>0rnKSwJ$5UrR;HR7Mlcw} z>D1Sal;L-eGll@^>KdlJLhG(lQcNIm^-p4R`O#W8J!2Ob?{gSr;vD?jp*{L_^-xA(S`YV=qv7^KlPOS41Mp zH(TD^5FqPwSF?Lpp6Po>?eR8FoSa|Y+z=qP;w`3MvkReRKI7w)5tA;UYtev&^5$Dj zpEn;qJB~9lZ|=QP-aO_&@;0xb=q{Bvuc~Ur9X)S;WT9m)2#C#=ukz+n;wp1TIh<2E z2%TEGI6#&yOQgi6BD?(qqv6?=2F3)TM3h`KAO+UjxO2ztrUz14*+NTe!~zmGPHAgIh>jDnN;y$yj`FsN`ug^4Ou1@3To6}5pG=`KgHtwOP z=d3P8d#QK43A`SQd(GBEszUQ>vFt0uz~C4IgJURZ^mpLTu_|n~*m*CAwIB*rok#6A zLEwFmzh!}e#Q6g81E&f7&yf7t59K$T1EVE;0NGoih8sK0Wi&_!egI-0u$j64*UlS? z0--(SZ6M2mgFwA%oJvYcN=iyfN=iyfH-i2TA110>iEve@00000NkvXXu0mjfQ>5XG literal 0 HcmV?d00001 diff --git a/www/agc/images/lastnode.png b/www/agc/images/lastnode.png new file mode 100644 index 0000000000000000000000000000000000000000..f8809f80226b5b355de607adab481e0d2a98833f GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^96&6>$P6UAuD;U%QfvV}A+8L}3>_UEvNtA_0Yw-~ zg8YIR9G=}s19CVEJR*x37`TN&n2}-D90{Nxdx@v7EBiGLHW3abX}iYrKp_E77sn8e j>&Y1j4(gTe~DWM4fSK1-d literal 0 HcmV?d00001 diff --git a/www/agc/images/node.png b/www/agc/images/node.png new file mode 100644 index 0000000000000000000000000000000000000000..29f6c446045ada93d886de10a85dcbf7c686cc48 GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^96&6>$P6UAuD;U%QfvV}A+8L}3>_UEvNtA_0Yw-~ zg8YIR9G=}s19CVEJR*x37`TN&n2}-D90{Nxdx@v7EBiGLHW3ch)+mu2ppc-ai(?4K k_2i5MhxY%H21lhBE=}fY@LT011C(U&boFyt=akR{0Bd3)YXATM literal 0 HcmV?d00001 diff --git a/www/agc/images/vline.png b/www/agc/images/vline.png new file mode 100644 index 0000000000000000000000000000000000000000..4c9bc6d749a5c5d6b34202e17dd06f1d790d024c GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrA$P6U?WtMRQDdqs55Z8{5j)>H}%|I?^fk$L9 z0|U1(2s1Lwnj--eWH0gbb!ETC!6qy$$>y{53s8vL)5S4_<9c$!0Tu=Z5eCMmZ5zCR O!VI3SelF{r5}E))DH%rq literal 0 HcmV?d00001 diff --git a/www/agc/simpletreemenu.js b/www/agc/simpletreemenu.js new file mode 100644 index 00000000..0fe47d68 --- /dev/null +++ b/www/agc/simpletreemenu.js @@ -0,0 +1,133 @@ +var persisteduls=new Object() +var ddtreemenu=new Object() + +ddtreemenu.closefolder="images/folder_closed.png" //set image path to "closed" folder image +ddtreemenu.openfolder="images/folder_open.png" //set image path to "open" folder image + +//////////No need to edit beyond here/////////////////////////// + +ddtreemenu.createTree=function(treeid, enablepersist, persistdays){ +var ultags=document.getElementById(treeid).getElementsByTagName("ul") +if (typeof persisteduls[treeid]=="undefined") +persisteduls[treeid]=(enablepersist==true && ddtreemenu.getCookie(treeid)!="")? ddtreemenu.getCookie(treeid).split(",") : "" +for (var i=0; i 0) ############################################# ##### START SYSTEM_SETTINGS LOOKUP ##### -$stmt = "SELECT use_non_latin,enable_queuemetrics_logging,enable_vtiger_integration,qc_features_active,outbound_autodial_active,sounds_central_control_active,enable_second_webform,user_territories_active,custom_fields_enabled,admin_web_directory,webphone_url,first_login_trigger,hosted_settings,default_phone_registration_password,default_phone_login_password,default_server_password,test_campaign_calls,active_voicemail_server,voicemail_timezones,default_voicemail_timezone,default_local_gmt,campaign_cid_areacodes_enabled,pllb_grouping_limit,did_ra_extensions_enabled,expanded_list_stats,contacts_enabled,alt_log_server_ip,alt_log_dbname,alt_log_login,alt_log_pass,tables_use_alt_log_db,call_menu_qualify_enabled,admin_list_counts,allow_voicemail_greeting,svn_revision,allow_emails,level_8_disable_add,pass_key,pass_hash_enabled,disable_auto_dial,country_code_list_stats,frozen_server_call_clear,active_modules,allow_chats,enable_languages,language_method,meetme_enter_login_filename,meetme_enter_leave3way_filename,enable_did_entry_list_id,enable_third_webform,default_language,user_hide_realtime_enabled,log_recording_access,alt_ivr_logging,admin_row_click,admin_screen_colors,ofcom_uk_drop_calc,agent_screen_colors,script_remove_js,manual_auto_next,user_new_lead_limit,agent_xfer_park_3way,agent_soundboards,web_loader_phone_length,agent_script,enable_auto_reports,enable_pause_code_limits,enable_drop_lists,allow_ip_lists,system_ip_blacklist,hide_inactive_lists,allow_manage_active_lists FROM system_settings;"; +$stmt = "SELECT use_non_latin,enable_queuemetrics_logging,enable_vtiger_integration,qc_features_active,outbound_autodial_active,sounds_central_control_active,enable_second_webform,user_territories_active,custom_fields_enabled,admin_web_directory,webphone_url,first_login_trigger,hosted_settings,default_phone_registration_password,default_phone_login_password,default_server_password,test_campaign_calls,active_voicemail_server,voicemail_timezones,default_voicemail_timezone,default_local_gmt,campaign_cid_areacodes_enabled,pllb_grouping_limit,did_ra_extensions_enabled,expanded_list_stats,contacts_enabled,alt_log_server_ip,alt_log_dbname,alt_log_login,alt_log_pass,tables_use_alt_log_db,call_menu_qualify_enabled,admin_list_counts,allow_voicemail_greeting,svn_revision,allow_emails,level_8_disable_add,pass_key,pass_hash_enabled,disable_auto_dial,country_code_list_stats,frozen_server_call_clear,active_modules,allow_chats,enable_languages,language_method,meetme_enter_login_filename,meetme_enter_leave3way_filename,enable_did_entry_list_id,enable_third_webform,default_language,user_hide_realtime_enabled,log_recording_access,alt_ivr_logging,admin_row_click,admin_screen_colors,ofcom_uk_drop_calc,agent_screen_colors,script_remove_js,manual_auto_next,user_new_lead_limit,agent_xfer_park_3way,agent_soundboards,web_loader_phone_length,agent_script,enable_auto_reports,enable_pause_code_limits,enable_drop_lists,allow_ip_lists,system_ip_blacklist,hide_inactive_lists,allow_manage_active_lists,expired_lists_inactive FROM system_settings;"; $rslt=mysql_to_mysqli($stmt, $link); if ($DB) {echo "$stmt\n";} $qm_conf_ct = mysqli_num_rows($rslt); @@ -2358,6 +2360,7 @@ if ($qm_conf_ct > 0) $SSsystem_ip_blacklist = $row[69]; $SShide_inactive_lists = $row[70]; $SSallow_manage_active_lists = $row[71]; + $SSexpired_lists_inactive = $row[72]; } ##### END SETTINGS LOOKUP ##### ########################################### @@ -2681,6 +2684,7 @@ if ($non_latin < 1) $hide_inactive_lists = preg_replace('/[^0-9]/','',$hide_inactive_lists); $inbound_survey_accept_digit = preg_replace('/[^0-9]/','',$inbound_survey_accept_digit); $allow_manage_active_lists = preg_replace('/[^0-9]/','',$allow_manage_active_lists); + $expired_lists_inactive = preg_replace('/[^0-9]/','',$expired_lists_inactive); $user_new_lead_limit = preg_replace('/[^-0-9]/','',$user_new_lead_limit); $drop_call_seconds = preg_replace('/[^-0-9]/','',$drop_call_seconds); @@ -4171,12 +4175,13 @@ else # 170825-1708 - Added filename_override option for Automated Reports, added more space for report_times # 170828-2105 - Added Inbound DID Summary Report # 170913-0908 - Added Agent Inbound Status Summary Report +# 170920-2153 - Added expired_lists_inactive system setting and functions # # make sure you have added a user to the vicidial_users MySQL table with at least user_level 9 to access this page the first time -$admin_version = '2.14-628a'; -$build = '170913-0908'; +$admin_version = '2.14-629a'; +$build = '170920-2153'; $STARTtime = date("U"); $SQLdate = date("Y-m-d H:i:s"); @@ -16863,7 +16868,7 @@ if ($ADD==411111111111111) } } - $stmt="UPDATE system_settings set use_non_latin='$use_non_latin',webroot_writable='$webroot_writable',enable_queuemetrics_logging='$enable_queuemetrics_logging',queuemetrics_server_ip='$queuemetrics_server_ip',queuemetrics_dbname='$queuemetrics_dbname',queuemetrics_login='$queuemetrics_login',queuemetrics_pass='$queuemetrics_pass',queuemetrics_url='$queuemetrics_url',queuemetrics_log_id='$queuemetrics_log_id',queuemetrics_eq_prepend='$queuemetrics_eq_prepend',vicidial_agent_disable='$vicidial_agent_disable',allow_sipsak_messages='$allow_sipsak_messages',admin_home_url='$admin_home_url',enable_agc_xfer_log='$enable_agc_xfer_log',timeclock_end_of_day='$timeclock_end_of_day',vdc_header_date_format='$vdc_header_date_format',vdc_customer_date_format='$vdc_customer_date_format',vdc_header_phone_format='$vdc_header_phone_format',vdc_agent_api_active='$vdc_agent_api_active',enable_vtiger_integration='$enable_vtiger_integration',vtiger_server_ip='$vtiger_server_ip',vtiger_dbname='$vtiger_dbname',vtiger_login='$vtiger_login',vtiger_pass='$vtiger_pass',vtiger_url='$vtiger_url',qc_features_active='$qc_features_active',outbound_autodial_active='$outbound_autodial_active',outbound_calls_per_second='$outbound_calls_per_second',enable_tts_integration='$enable_tts_integration',agentonly_callback_campaign_lock='$agentonly_callback_campaign_lock',sounds_central_control_active='$sounds_central_control_active',sounds_web_server='$sounds_web_server',sounds_web_directory='$sounds_web_directory',active_voicemail_server='$active_voicemail_server',auto_dial_limit='$auto_dial_limit',user_territories_active='$user_territories_active',allow_custom_dialplan='$allow_custom_dialplan',enable_second_webform='$enable_second_webform',default_webphone='$default_webphone',default_external_server_ip='$default_external_server_ip',webphone_url='" . mysqli_real_escape_string($link, $webphone_url) . "',enable_agc_dispo_log='$enable_agc_dispo_log',queuemetrics_loginout='$queuemetrics_loginout',callcard_enabled='$callcard_enabled',queuemetrics_callstatus='$queuemetrics_callstatus',default_codecs='$default_codecs',admin_web_directory='$admin_web_directory',label_title='$label_title',label_first_name='$label_first_name',label_middle_initial='$label_middle_initial',label_last_name='$label_last_name',label_address1='$label_address1',label_address2='$label_address2',label_address3='$label_address3',label_city='$label_city',label_state='$label_state',label_province='$label_province',label_postal_code='$label_postal_code',label_vendor_lead_code='$label_vendor_lead_code',label_gender='$label_gender',label_phone_number='$label_phone_number',label_phone_code='$label_phone_code',label_alt_phone='$label_alt_phone',label_security_phrase='$label_security_phrase',label_email='$label_email',label_comments='$label_comments',custom_fields_enabled='$custom_fields_enabled',slave_db_server='$slave_db_server',reports_use_slave_db='$reports_use_slave_db'$custom_reports_slave_SQL,webphone_systemkey='$webphone_systemkey',first_login_trigger='$first_login_trigger',default_phone_registration_password='$default_phone_registration_password',default_phone_login_password='$default_phone_login_password',default_server_password='$default_server_password',admin_modify_refresh='$admin_modify_refresh',nocache_admin='$nocache_admin',generate_cross_server_exten='$generate_cross_server_exten',queuemetrics_addmember_enabled='$queuemetrics_addmember_enabled',queuemetrics_dispo_pause='$queuemetrics_dispo_pause',label_hide_field_logs='$label_hide_field_logs',queuemetrics_pe_phone_append='$queuemetrics_pe_phone_append',test_campaign_calls='$test_campaign_calls',agents_calls_reset='$agents_calls_reset',default_voicemail_timezone='$default_voicemail_timezone',default_local_gmt='$default_local_gmt',noanswer_log='$noanswer_log',alt_log_server_ip='$alt_log_server_ip',alt_log_dbname='$alt_log_dbname',alt_log_login='$alt_log_login',alt_log_pass='$alt_log_pass',tables_use_alt_log_db='$tables_use_alt_log_db',did_agent_log='$did_agent_log',campaign_cid_areacodes_enabled='$campaign_cid_areacodes_enabled',pllb_grouping_limit='$pllb_grouping_limit',did_ra_extensions_enabled='$did_ra_extensions_enabled',expanded_list_stats='$expanded_list_stats',contacts_enabled='$contacts_enabled',call_menu_qualify_enabled='$call_menu_qualify_enabled',admin_list_counts='$admin_list_counts',allow_voicemail_greeting='$allow_voicemail_greeting',queuemetrics_socket='$queuemetrics_socket',queuemetrics_socket_url='$queuemetrics_socket_url',enhanced_disconnect_logging='$enhanced_disconnect_logging',allow_emails='$allow_emails',level_8_disable_add='$level_8_disable_add',queuemetrics_record_hold='$queuemetrics_record_hold',country_code_list_stats='$country_code_list_stats',queuemetrics_pause_type='$queuemetrics_pause_type',frozen_server_call_clear='$frozen_server_call_clear',callback_time_24hour='$callback_time_24hour',enable_languages='$enable_languages',language_method='$language_method',meetme_enter_login_filename='$meetme_enter_login_filename',meetme_enter_leave3way_filename='$meetme_enter_leave3way_filename',enable_did_entry_list_id='$enable_did_entry_list_id',enable_third_webform='$enable_third_webform',allow_chats='$allow_chats',chat_url='$chat_url',chat_timeout='$chat_timeout',agent_debug_logging='$agent_debug_logging',default_language='$default_language',agent_whisper_enabled='$agent_whisper_enabled',user_hide_realtime_enabled='$user_hide_realtime_enabled',usacan_phone_dialcode_fix='$usacan_phone_dialcode_fix',cache_carrier_stats_realtime='$cache_carrier_stats_realtime',log_recording_access='$log_recording_access',report_default_format='$report_default_format',alt_ivr_logging='$alt_ivr_logging',default_phone_code='$default_phone_code',admin_row_click='$admin_row_click',admin_screen_colors='$admin_screen_colors',ofcom_uk_drop_calc='$ofcom_uk_drop_calc',agent_screen_colors='$agent_screen_colors',script_remove_js='$script_remove_js',manual_auto_next='$manual_auto_next',user_new_lead_limit='$user_new_lead_limit',agent_xfer_park_3way='$agent_xfer_park_3way',agent_soundboards='$agent_soundboards',web_loader_phone_length='$web_loader_phone_length',agent_script='$agent_script',agent_chat_screen_colors='$agent_chat_screen_colors',enable_auto_reports='$enable_auto_reports',enable_pause_code_limits='$enable_pause_code_limits',enable_drop_lists='$enable_drop_lists',allow_ip_lists='$allow_ip_lists',system_ip_blacklist='$system_ip_blacklist',agent_push_events='$agent_push_events',agent_push_url='$agent_push_url',hide_inactive_lists='$hide_inactive_lists',allow_manage_active_lists='$allow_manage_active_lists'$custom_dialplanSQL;"; + $stmt="UPDATE system_settings set use_non_latin='$use_non_latin',webroot_writable='$webroot_writable',enable_queuemetrics_logging='$enable_queuemetrics_logging',queuemetrics_server_ip='$queuemetrics_server_ip',queuemetrics_dbname='$queuemetrics_dbname',queuemetrics_login='$queuemetrics_login',queuemetrics_pass='$queuemetrics_pass',queuemetrics_url='$queuemetrics_url',queuemetrics_log_id='$queuemetrics_log_id',queuemetrics_eq_prepend='$queuemetrics_eq_prepend',vicidial_agent_disable='$vicidial_agent_disable',allow_sipsak_messages='$allow_sipsak_messages',admin_home_url='$admin_home_url',enable_agc_xfer_log='$enable_agc_xfer_log',timeclock_end_of_day='$timeclock_end_of_day',vdc_header_date_format='$vdc_header_date_format',vdc_customer_date_format='$vdc_customer_date_format',vdc_header_phone_format='$vdc_header_phone_format',vdc_agent_api_active='$vdc_agent_api_active',enable_vtiger_integration='$enable_vtiger_integration',vtiger_server_ip='$vtiger_server_ip',vtiger_dbname='$vtiger_dbname',vtiger_login='$vtiger_login',vtiger_pass='$vtiger_pass',vtiger_url='$vtiger_url',qc_features_active='$qc_features_active',outbound_autodial_active='$outbound_autodial_active',outbound_calls_per_second='$outbound_calls_per_second',enable_tts_integration='$enable_tts_integration',agentonly_callback_campaign_lock='$agentonly_callback_campaign_lock',sounds_central_control_active='$sounds_central_control_active',sounds_web_server='$sounds_web_server',sounds_web_directory='$sounds_web_directory',active_voicemail_server='$active_voicemail_server',auto_dial_limit='$auto_dial_limit',user_territories_active='$user_territories_active',allow_custom_dialplan='$allow_custom_dialplan',enable_second_webform='$enable_second_webform',default_webphone='$default_webphone',default_external_server_ip='$default_external_server_ip',webphone_url='" . mysqli_real_escape_string($link, $webphone_url) . "',enable_agc_dispo_log='$enable_agc_dispo_log',queuemetrics_loginout='$queuemetrics_loginout',callcard_enabled='$callcard_enabled',queuemetrics_callstatus='$queuemetrics_callstatus',default_codecs='$default_codecs',admin_web_directory='$admin_web_directory',label_title='$label_title',label_first_name='$label_first_name',label_middle_initial='$label_middle_initial',label_last_name='$label_last_name',label_address1='$label_address1',label_address2='$label_address2',label_address3='$label_address3',label_city='$label_city',label_state='$label_state',label_province='$label_province',label_postal_code='$label_postal_code',label_vendor_lead_code='$label_vendor_lead_code',label_gender='$label_gender',label_phone_number='$label_phone_number',label_phone_code='$label_phone_code',label_alt_phone='$label_alt_phone',label_security_phrase='$label_security_phrase',label_email='$label_email',label_comments='$label_comments',custom_fields_enabled='$custom_fields_enabled',slave_db_server='$slave_db_server',reports_use_slave_db='$reports_use_slave_db'$custom_reports_slave_SQL,webphone_systemkey='$webphone_systemkey',first_login_trigger='$first_login_trigger',default_phone_registration_password='$default_phone_registration_password',default_phone_login_password='$default_phone_login_password',default_server_password='$default_server_password',admin_modify_refresh='$admin_modify_refresh',nocache_admin='$nocache_admin',generate_cross_server_exten='$generate_cross_server_exten',queuemetrics_addmember_enabled='$queuemetrics_addmember_enabled',queuemetrics_dispo_pause='$queuemetrics_dispo_pause',label_hide_field_logs='$label_hide_field_logs',queuemetrics_pe_phone_append='$queuemetrics_pe_phone_append',test_campaign_calls='$test_campaign_calls',agents_calls_reset='$agents_calls_reset',default_voicemail_timezone='$default_voicemail_timezone',default_local_gmt='$default_local_gmt',noanswer_log='$noanswer_log',alt_log_server_ip='$alt_log_server_ip',alt_log_dbname='$alt_log_dbname',alt_log_login='$alt_log_login',alt_log_pass='$alt_log_pass',tables_use_alt_log_db='$tables_use_alt_log_db',did_agent_log='$did_agent_log',campaign_cid_areacodes_enabled='$campaign_cid_areacodes_enabled',pllb_grouping_limit='$pllb_grouping_limit',did_ra_extensions_enabled='$did_ra_extensions_enabled',expanded_list_stats='$expanded_list_stats',contacts_enabled='$contacts_enabled',call_menu_qualify_enabled='$call_menu_qualify_enabled',admin_list_counts='$admin_list_counts',allow_voicemail_greeting='$allow_voicemail_greeting',queuemetrics_socket='$queuemetrics_socket',queuemetrics_socket_url='$queuemetrics_socket_url',enhanced_disconnect_logging='$enhanced_disconnect_logging',allow_emails='$allow_emails',level_8_disable_add='$level_8_disable_add',queuemetrics_record_hold='$queuemetrics_record_hold',country_code_list_stats='$country_code_list_stats',queuemetrics_pause_type='$queuemetrics_pause_type',frozen_server_call_clear='$frozen_server_call_clear',callback_time_24hour='$callback_time_24hour',enable_languages='$enable_languages',language_method='$language_method',meetme_enter_login_filename='$meetme_enter_login_filename',meetme_enter_leave3way_filename='$meetme_enter_leave3way_filename',enable_did_entry_list_id='$enable_did_entry_list_id',enable_third_webform='$enable_third_webform',allow_chats='$allow_chats',chat_url='$chat_url',chat_timeout='$chat_timeout',agent_debug_logging='$agent_debug_logging',default_language='$default_language',agent_whisper_enabled='$agent_whisper_enabled',user_hide_realtime_enabled='$user_hide_realtime_enabled',usacan_phone_dialcode_fix='$usacan_phone_dialcode_fix',cache_carrier_stats_realtime='$cache_carrier_stats_realtime',log_recording_access='$log_recording_access',report_default_format='$report_default_format',alt_ivr_logging='$alt_ivr_logging',default_phone_code='$default_phone_code',admin_row_click='$admin_row_click',admin_screen_colors='$admin_screen_colors',ofcom_uk_drop_calc='$ofcom_uk_drop_calc',agent_screen_colors='$agent_screen_colors',script_remove_js='$script_remove_js',manual_auto_next='$manual_auto_next',user_new_lead_limit='$user_new_lead_limit',agent_xfer_park_3way='$agent_xfer_park_3way',agent_soundboards='$agent_soundboards',web_loader_phone_length='$web_loader_phone_length',agent_script='$agent_script',agent_chat_screen_colors='$agent_chat_screen_colors',enable_auto_reports='$enable_auto_reports',enable_pause_code_limits='$enable_pause_code_limits',enable_drop_lists='$enable_drop_lists',allow_ip_lists='$allow_ip_lists',system_ip_blacklist='$system_ip_blacklist',agent_push_events='$agent_push_events',agent_push_url='$agent_push_url',hide_inactive_lists='$hide_inactive_lists',allow_manage_active_lists='$allow_manage_active_lists',expired_lists_inactive='$expired_lists_inactive'$custom_dialplanSQL;"; $rslt=mysql_to_mysqli($stmt, $link); if ( ($meetme_enter_login_filename != $SSmeetme_enter_login_filename) or ($meetme_enter_leave3way_filename != $SSmeetme_enter_leave3way_filename) ) @@ -25173,6 +25178,37 @@ if ($ADD==311) echo "\n"; + echo "\n"; + echo "\n"; echo "\n"; diff --git a/www/vicidial/help.php b/www/vicidial/help.php index 76026087..0d178e6c 100644 --- a/www/vicidial/help.php +++ b/www/vicidial/help.php @@ -133,6 +133,7 @@ # 170816-1057 - Added inbound after call entries # 170819-0951 - Added allow_manage_active_lists entry # 170825-1129 - Added auto_reports-filename_override entry +# 170920-2156 - Added expired_lists_inactive entry # @@ -5380,6 +5381,11 @@ FR_SPAC 00 00 00 00 00 - - +
+ +
+ - +

\n"; echo ""; + if ($SSexpired_lists_inactive > 0) + { + $expired_check=0; + $stmt="SELECT count(*) from vicidial_lists where list_id='$list_id' and expiration_date < \"$REPORTdate\";"; + $rslt=mysql_to_mysqli($stmt, $link); + $Cexp_to_print = mysqli_num_rows($rslt); + if ($Cexp_to_print > 0) + { + $rowx=mysqli_fetch_row($rslt); + $expired_check = "$rowx[0]"; + } + if ($DB) {echo "$expired_check|$stmt|\n";} + if ($expired_check > 0) + { + $stmt = "UPDATE vicidial_lists SET active='N' where list_id='$list_id';"; + $rslt=mysql_to_mysqli($stmt, $link); + $ELaffected_rows = mysqli_affected_rows($link); + if ($DB) {echo "|$stmt|\n";} + + ### LOG INSERTION Admin Log Table ### + $SQL_log = "$stmt|"; + $SQL_log = preg_replace('/;/', '', $SQL_log); + $SQL_log = addslashes($SQL_log); + $stmt="INSERT INTO vicidial_admin_log set event_date='$SQLdate', user='$PHP_AUTH_USER', ip_address='$ip', event_section='LISTS', event_type='MODIFY', record_id='$list_id', event_code='ADMIN AUTO EXPIRE LIST', event_sql=\"$SQL_log\", event_notes='LIST: $list_id CHANGED: $ELaffected_rows';"; + if ($DB) {echo "|$stmt|\n";} + $rslt=mysql_to_mysqli($stmt, $link); + + echo "
"._QXZ("NOTICE: expired list set to inactive")."\n"; + } + } + $stmt="SELECT vicidial_lists.list_id,list_name,campaign_id,active,list_description,list_changedate,list_lastcalldate,reset_time,agent_script_override,campaign_cid_override,am_message_exten_override,drop_inbound_group_override,xferconf_a_number,xferconf_b_number,xferconf_c_number,xferconf_d_number,xferconf_e_number,web_form_address,web_form_address_two,time_zone_setting,inventory_report,IFNULL(audit_comments,0),expiration_date,DATE_FORMAT(expiration_date,'%Y%m%d'),na_call_url,local_call_time,web_form_address_three,status_group_id,user_new_lead_limit from vicidial_lists left outer join vicidial_lists_custom on vicidial_lists.list_id=vicidial_lists_custom.list_id where vicidial_lists.list_id='$list_id' $LOGallowed_campaignsSQL;"; $rslt=mysql_to_mysqli($stmt, $link); @@ -34779,7 +34815,7 @@ if ($ADD==311111111111111) $ALLagent_count = $rowx[2]; } - $stmt="SELECT version,install_date,use_non_latin,webroot_writable,enable_queuemetrics_logging,queuemetrics_server_ip,queuemetrics_dbname,queuemetrics_login,queuemetrics_pass,queuemetrics_url,queuemetrics_log_id,queuemetrics_eq_prepend,vicidial_agent_disable,allow_sipsak_messages,admin_home_url,enable_agc_xfer_log,db_schema_version,auto_user_add_value,timeclock_end_of_day,timeclock_last_reset_date,vdc_header_date_format,vdc_customer_date_format,vdc_header_phone_format,vdc_agent_api_active,qc_last_pull_time,enable_vtiger_integration,vtiger_server_ip,vtiger_dbname,vtiger_login,vtiger_pass,vtiger_url,qc_features_active,outbound_autodial_active,outbound_calls_per_second,enable_tts_integration,agentonly_callback_campaign_lock,sounds_central_control_active,sounds_web_server,sounds_web_directory,active_voicemail_server,auto_dial_limit,user_territories_active,allow_custom_dialplan,db_schema_update_date,enable_second_webform,default_webphone,default_external_server_ip,webphone_url,enable_agc_dispo_log,custom_dialplan_entry,queuemetrics_loginout,callcard_enabled,queuemetrics_callstatus,default_codecs,admin_web_directory,label_title,label_first_name,label_middle_initial,label_last_name,label_address1,label_address2,label_address3,label_city,label_state,label_province,label_postal_code,label_vendor_lead_code,label_gender,label_phone_number,label_phone_code,label_alt_phone,label_security_phrase,label_email,label_comments,custom_fields_enabled,slave_db_server,reports_use_slave_db,webphone_systemkey,first_login_trigger,default_phone_registration_password,default_phone_login_password,default_server_password,admin_modify_refresh,nocache_admin,generate_cross_server_exten,queuemetrics_addmember_enabled,queuemetrics_dispo_pause,label_hide_field_logs,queuemetrics_pe_phone_append,test_campaign_calls,agents_calls_reset,default_voicemail_timezone,default_local_gmt,noanswer_log,alt_log_server_ip,alt_log_dbname,alt_log_login,alt_log_pass,tables_use_alt_log_db,did_agent_log,campaign_cid_areacodes_enabled,pllb_grouping_limit,did_ra_extensions_enabled,expanded_list_stats,contacts_enabled,call_menu_qualify_enabled,admin_list_counts,allow_voicemail_greeting,svn_revision,queuemetrics_socket,queuemetrics_socket_url,enhanced_disconnect_logging,allow_emails,level_8_disable_add,pass_hash_enabled,pass_key,pass_cost,disable_auto_dial,queuemetrics_record_hold,country_code_list_stats,reload_timestamp,queuemetrics_pause_type,frozen_server_call_clear,callback_time_24hour,allow_chats,chat_url,chat_timeout,enable_languages,language_method,meetme_enter_login_filename,meetme_enter_leave3way_filename,enable_did_entry_list_id,enable_third_webform,agent_debug_logging,default_language,agent_whisper_enabled,user_hide_realtime_enabled,usacan_phone_dialcode_fix,cache_carrier_stats_realtime,oldest_logs_date,log_recording_access,report_default_format,alt_ivr_logging,default_phone_code,admin_row_click,admin_screen_colors,ofcom_uk_drop_calc,agent_screen_colors,script_remove_js,manual_auto_next,user_new_lead_limit,agent_xfer_park_3way,rec_prompt_count,agent_soundboards,web_loader_phone_length,agent_script,agent_chat_screen_colors,enable_auto_reports,enable_pause_code_limits,enable_drop_lists,allow_ip_lists,system_ip_blacklist,agent_push_events,agent_push_url,hide_inactive_lists,allow_manage_active_lists from system_settings;"; + $stmt="SELECT version,install_date,use_non_latin,webroot_writable,enable_queuemetrics_logging,queuemetrics_server_ip,queuemetrics_dbname,queuemetrics_login,queuemetrics_pass,queuemetrics_url,queuemetrics_log_id,queuemetrics_eq_prepend,vicidial_agent_disable,allow_sipsak_messages,admin_home_url,enable_agc_xfer_log,db_schema_version,auto_user_add_value,timeclock_end_of_day,timeclock_last_reset_date,vdc_header_date_format,vdc_customer_date_format,vdc_header_phone_format,vdc_agent_api_active,qc_last_pull_time,enable_vtiger_integration,vtiger_server_ip,vtiger_dbname,vtiger_login,vtiger_pass,vtiger_url,qc_features_active,outbound_autodial_active,outbound_calls_per_second,enable_tts_integration,agentonly_callback_campaign_lock,sounds_central_control_active,sounds_web_server,sounds_web_directory,active_voicemail_server,auto_dial_limit,user_territories_active,allow_custom_dialplan,db_schema_update_date,enable_second_webform,default_webphone,default_external_server_ip,webphone_url,enable_agc_dispo_log,custom_dialplan_entry,queuemetrics_loginout,callcard_enabled,queuemetrics_callstatus,default_codecs,admin_web_directory,label_title,label_first_name,label_middle_initial,label_last_name,label_address1,label_address2,label_address3,label_city,label_state,label_province,label_postal_code,label_vendor_lead_code,label_gender,label_phone_number,label_phone_code,label_alt_phone,label_security_phrase,label_email,label_comments,custom_fields_enabled,slave_db_server,reports_use_slave_db,webphone_systemkey,first_login_trigger,default_phone_registration_password,default_phone_login_password,default_server_password,admin_modify_refresh,nocache_admin,generate_cross_server_exten,queuemetrics_addmember_enabled,queuemetrics_dispo_pause,label_hide_field_logs,queuemetrics_pe_phone_append,test_campaign_calls,agents_calls_reset,default_voicemail_timezone,default_local_gmt,noanswer_log,alt_log_server_ip,alt_log_dbname,alt_log_login,alt_log_pass,tables_use_alt_log_db,did_agent_log,campaign_cid_areacodes_enabled,pllb_grouping_limit,did_ra_extensions_enabled,expanded_list_stats,contacts_enabled,call_menu_qualify_enabled,admin_list_counts,allow_voicemail_greeting,svn_revision,queuemetrics_socket,queuemetrics_socket_url,enhanced_disconnect_logging,allow_emails,level_8_disable_add,pass_hash_enabled,pass_key,pass_cost,disable_auto_dial,queuemetrics_record_hold,country_code_list_stats,reload_timestamp,queuemetrics_pause_type,frozen_server_call_clear,callback_time_24hour,allow_chats,chat_url,chat_timeout,enable_languages,language_method,meetme_enter_login_filename,meetme_enter_leave3way_filename,enable_did_entry_list_id,enable_third_webform,agent_debug_logging,default_language,agent_whisper_enabled,user_hide_realtime_enabled,usacan_phone_dialcode_fix,cache_carrier_stats_realtime,oldest_logs_date,log_recording_access,report_default_format,alt_ivr_logging,default_phone_code,admin_row_click,admin_screen_colors,ofcom_uk_drop_calc,agent_screen_colors,script_remove_js,manual_auto_next,user_new_lead_limit,agent_xfer_park_3way,rec_prompt_count,agent_soundboards,web_loader_phone_length,agent_script,agent_chat_screen_colors,enable_auto_reports,enable_pause_code_limits,enable_drop_lists,allow_ip_lists,system_ip_blacklist,agent_push_events,agent_push_url,hide_inactive_lists,allow_manage_active_lists,expired_lists_inactive from system_settings;"; $rslt=mysql_to_mysqli($stmt, $link); $row=mysqli_fetch_row($rslt); $version = $row[0]; @@ -34948,6 +34984,7 @@ if ($ADD==311111111111111) $agent_push_url = $row[163]; $hide_inactive_lists = $row[164]; $allow_manage_active_lists = $row[165]; + $expired_lists_inactive = $row[166]; if ($pass_hash_enabled > 0) {$pass_hash_enabled = 'ENABLED';} else {$pass_hash_enabled = 'DISABLED';} @@ -35208,6 +35245,8 @@ if ($ADD==311111111111111) echo "
"._QXZ("Lead Manager Active Lists").": $NWB#settings-allow_manage_active_lists$NWE
"._QXZ("Expired Lists Auto Inactive").": $NWB#settings-expired_lists_inactive$NWE
"._QXZ("Enable Drop Lists").": $NWB#settings-enable_drop_lists$NWE
"._QXZ("Agent Screen Debug Logging").": $NWB#settings-agent_debug_logging$NWE