Added backstop for muted recordings on some systems that won't record silence of muted recordings

git-svn-id: svn://192.168.202.10@3073 3d104415-ff17-0410-8863-d5cf3c621b8a
This commit is contained in:
mattf
2019-03-11 06:03:14 +00:00
parent e3f7ea0b7f
commit 40057e8b22
2 changed files with 229 additions and 155 deletions
+226 -152
View File
@@ -25,7 +25,7 @@
# This program assumes that recordings are saved by Asterisk as .wav
# should be easy to change this code if you use .gsm instead
#
# Copyright (C) 2016 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
# Copyright (C) 2019 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
#
# 80302-1958 - First Build
@@ -33,6 +33,7 @@
# 130805-1450 - Added check for length and gather length of recording for database record
# 160523-0654 - Added --HTTPS option to use https instead of http in local location
# 160731-2103 - Added --POST options to change filename with variable lookups
# 190311-0105 - Added code to check for agent-muted recordings
#
$HTTPS=0;
@@ -207,6 +208,18 @@ 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 #####
$SSmute_recordings=0;
$stmtA = "SELECT mute_recordings FROM system_settings;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$SSmute_recordings = $aryA[0];
}
$sthA->finish();
### find soxi to gather the length info if needed
$soxibin = '';
@@ -274,7 +287,8 @@ foreach(@FILES)
$filenameSQL='';
$length_in_sec=0;
$stmtA = "SELECT recording_id,length_in_sec,lead_id,vicidial_id from recording_log where filename='$SQLFILE' order by recording_id desc LIMIT 1;";
$rec_ended=0;
$stmtA = "SELECT recording_id,length_in_sec,lead_id,vicidial_id,start_time,end_time,user from recording_log where filename='$SQLFILE' order by recording_id desc LIMIT 1;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
@@ -286,117 +300,42 @@ foreach(@FILES)
$length_in_sec = $aryA[1];
$lead_id = $aryA[2];
$vicidial_id = $aryA[3];
$start_time = $aryA[4];
$end_time = $aryA[5];
$user = $aryA[6];
if (length($end_time) > 15) {$rec_ended=1;}
}
$sthA->finish();
if ($DB) {print "|$recording_id|$length_in_sec|$INfile| |$ALLfile|\n";}
if (!$T)
$process_recording=1;
if ( ($SSmute_recordings > 0) && ($rec_ended < 1) )
{
`mv -f "$dir1/$INfile" "$dir2/$ALLfile"`;
`rm -f "$dir1/$OUTfile"`;
}
else
{
`cp -f "$dir1/$INfile" "$dir2/$ALLfile"`;
}
$lengthSQL='';
if ( ( ($length_in_sec < 1) || ($length_in_sec =~ /^NULL$/i) || (length($length_in_sec)<1) ) && (length($soxibin) > 3) )
{
@soxi_output = `$soxibin -D $dir2/$ALLfile`;
$soxi_sec = $soxi_output[0];
$soxi_sec =~ s/\..*|\n|\r| //gi;
$soxi_min = ($soxi_sec / 60);
$soxi_min = sprintf("%.2f", $soxi_min);
$lengthSQL = ",length_in_sec='$soxi_sec',length_in_min='$soxi_min'";
}
##### BEGIN post call variable replacement #####
if ($POST > 0)
{
if ($ALLfile =~ /POSTVLC|POSTSP|POSTADDR3|POSTSTATUS/)
### check for active muted recordings
$rec_on_ct=0; $rec_off_ct=0;
$stmtA = "SELECT count(*),stage from vicidial_agent_function_log where lead_id='$lead_id' and event_time >= \"$start_time\" and user='$user' and function='mute_rec' group by stage;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rs=0;
while ($sthArows > $rs)
{
$origALLfile = $ALLfile;
$origSQLFILE = $SQLFILE;
$vendor_lead_code=''; $security_phrase=''; $address3=''; $status='';
$status_ALL=0;
$camp_ALL=0;
$camp_status_selected=0;
@aryA = $sthA->fetchrow_array;
if ($aryA[1] =~ /on/i) {$rec_on_ct = $aryA[0];}
if ($aryA[1] =~ /off/i) {$rec_off_ct = $aryA[0];}
$rs++;
}
$sthA->finish();
if ($status_post =~ /----ALL----/)
{
$status_ALL++;
if($DBX){print "All Statuses: |$status_post|$status_ALL|\n";}
}
if ($rec_on_ct > $rec_off_ct)
{
if ($DBX > 0) {print "DEBUG: recording muting on for this call: ($rec_on_ct > $rec_off_ct) |$SQLFILE|ended: $rec_ended|\n";}
if ($camp_post =~ /----ALL----/)
$rs_recent_on=0;
if ($rec_ended < 1)
{
$camp_ALL++;
if($DBX){print "All Campaigs and Ingroups: |$camp_post|$camp_ALL|\n";}
}
if ( ($camp_ALL < 1) || ($status_ALL < 1) )
{
$camp_postSQL='';
if ($camp_ALL < 1)
{
$camp_postSQL = $camp_post;
$camp_postSQL =~ s/---/','/gi;
$camp_postSQL = "and campaign_id IN('$camp_postSQL')";
}
if ($vicidial_id =~ /\./)
{
$log_lookupSQL = "SELECT status from vicidial_log where uniqueid='$vicidial_id' and lead_id='$lead_id' $camp_postSQL;";
}
else
{
$log_lookupSQL = "SELECT status from vicidial_closer_log where closecallid='$vicidial_id' and lead_id='$lead_id' $camp_postSQL;";
}
if($DBX){print STDERR "\n|$log_lookupSQL|\n";}
$sthA = $dbhA->prepare($log_lookupSQL) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $log_lookupSQL ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$lead_status = $aryA[0];
if ($status_ALL > 0)
{$camp_status_selected++;}
else
{
@status_vars = split(/---/,$status_post);
$fc=0;
foreach(@status_vars)
{
$status_temp = $status_vars[$fc];
if ($status_vars[$fc] =~ /\*/)
{
$status_temp =~ s/\*/.*/gi;
if ( ($lead_status =~ /^$status_temp/) && ($status_vars[$fc] =~ /\*$/) )
{$camp_status_selected++;}
if ( ($lead_status =~ /$status_temp$/) && ($status_vars[$fc] =~ /^\*/) )
{$camp_status_selected++;}
}
else
{
if ($lead_status =~ /^$status_temp$/)
{$camp_status_selected++;}
}
if ($DBX) {print " POST processing DEBUG: $fc|$status_temp|$lead_status|$lead_id|$vicidial_id|$ALLfile|\n";}
$fc++;
}
}
if ($DB) {print " POST processing SELECT: |$camp_status_selected|$sthArows|$camp_postSQL|$camp_ALL|$status_post|$status_ALL|$ALLfile|\n";}
}
else
{if ($DB) {print " POST processing ERROR: lead not found: |$lead_id|$ALLfile|\n";} }
$sthA->finish();
}
if ( ( ($camp_ALL > 0) && ($status_ALL > 0) ) || ($camp_status_selected > 0) )
{
$stmtA = "SELECT vendor_lead_code,security_phrase,address3,status from vicidial_list where lead_id='$lead_id' LIMIT 1;";
### check if muting started in last 15 minutes
$stmtA = "SELECT count(*) from vicidial_agent_function_log where lead_id='$lead_id' and event_time >= \"$start_time\" and event_time > DATE_SUB(NOW(),INTERVAL 15 MINUTE) and user='$user' and function='mute_rec' and stage='on';";
if($DBX){print STDERR "\n|$stmtA|\n";}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
@@ -404,69 +343,204 @@ foreach(@FILES)
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$vendor_lead_code = $aryA[0];
$security_phrase = $aryA[1];
$address3 = $aryA[2];
$status = $aryA[3];
$vendor_lead_code =~ s/[^a-zA-Z0-9_-]//gi;
$security_phrase =~ s/[^a-zA-Z0-9_-]//gi;
$address3 =~ s/[^a-zA-Z0-9_-]//gi;
$status =~ s/[^a-zA-Z0-9_-]//gi;
$rs_recent_on = $aryA[0];
}
else
{if ($DB) {print " POST processing ERROR: lead not found: |$lead_id|$ALLfile|\n";} }
$sthA->finish();
}
$ALLfile =~ s/POSTVLC/$vendor_lead_code/gi;
$ALLfile =~ s/POSTSP/$security_phrase/gi;
$ALLfile =~ s/POSTADDR3/$address3/gi;
$ALLfile =~ s/POSTSTATUS/$status/gi;
$SQLFILE =~ s/POSTVLC/$vendor_lead_code/gi;
$SQLFILE =~ s/POSTSP/$security_phrase/gi;
$SQLFILE =~ s/POSTADDR3/$address3/gi;
$SQLFILE =~ s/POSTSTATUS/$status/gi;
$filenameSQL = ",filename='$SQLFILE'";
`mv -f "$dir2/$origALLfile" "$dir2/$ALLfile"`;
if ($DB) {print " POST processing COMPLETE: old: |$origALLfile| new: |$ALLfile|\n";}
if ($rs_recent_on > 0)
{
if ($DBX > 0) {print "DEBUG2: recording muting recently for this call, do not process: ($rs_recent_on) |$SQLFILE|ended: $rec_ended|\n";}
$process_recording=0;
}
else
{
if ($DB) {print " POST processing SKIPPED: |$camp_ALL|$status_ALL|$camp_status_selected|$lead_id|$vicidial_id|$ALLfile|\n";}
if ($DBX > 0) {print "DEBUG3: recording muting started over 15 minutes ago, OK to process: ($rs_recent_on) |$SQLFILE|ended: $rec_ended|\n";}
}
}
}
if ($CLEAR_POST > 0)
if ($process_recording > 0)
{
if ($DB) {print "|$recording_id|$length_in_sec|$INfile| |$ALLfile|\n";}
if (!$T)
{
`mv -f "$dir1/$INfile" "$dir2/$ALLfile"`;
`rm -f "$dir1/$OUTfile"`;
}
else
{
`cp -f "$dir1/$INfile" "$dir2/$ALLfile"`;
}
$lengthSQL='';
if ( ( ($length_in_sec < 1) || ($length_in_sec =~ /^NULL$/i) || (length($length_in_sec)<1) ) && (length($soxibin) > 3) )
{
@soxi_output = `$soxibin -D $dir2/$ALLfile`;
$soxi_sec = $soxi_output[0];
$soxi_sec =~ s/\..*|\n|\r| //gi;
$soxi_min = ($soxi_sec / 60);
$soxi_min = sprintf("%.2f", $soxi_min);
$lengthSQL = ",length_in_sec='$soxi_sec',length_in_min='$soxi_min'";
}
##### BEGIN post call variable replacement #####
if ($POST > 0)
{
if ($ALLfile =~ /POSTVLC|POSTSP|POSTADDR3|POSTSTATUS/)
{
$origALLfile = $ALLfile;
$origSQLFILE = $SQLFILE;
$vendor_lead_code=''; $security_phrase=''; $address3=''; $status='';
$status_ALL=0;
$camp_ALL=0;
$camp_status_selected=0;
if ($status_post =~ /----ALL----/)
{
$ALLfile =~ s/POSTVLC//gi;
$ALLfile =~ s/POSTSP//gi;
$ALLfile =~ s/POSTADDR3//gi;
$ALLfile =~ s/POSTSTATUS//gi;
$SQLFILE =~ s/POSTVLC//gi;
$SQLFILE =~ s/POSTSP//gi;
$SQLFILE =~ s/POSTADDR3//gi;
$SQLFILE =~ s/POSTSTATUS//gi;
$status_ALL++;
if($DBX){print "All Statuses: |$status_post|$status_ALL|\n";}
}
if ($camp_post =~ /----ALL----/)
{
$camp_ALL++;
if($DBX){print "All Campaigs and Ingroups: |$camp_post|$camp_ALL|\n";}
}
if ( ($camp_ALL < 1) || ($status_ALL < 1) )
{
$camp_postSQL='';
if ($camp_ALL < 1)
{
$camp_postSQL = $camp_post;
$camp_postSQL =~ s/---/','/gi;
$camp_postSQL = "and campaign_id IN('$camp_postSQL')";
}
if ($vicidial_id =~ /\./)
{
$log_lookupSQL = "SELECT status from vicidial_log where uniqueid='$vicidial_id' and lead_id='$lead_id' $camp_postSQL;";
}
else
{
$log_lookupSQL = "SELECT status from vicidial_closer_log where closecallid='$vicidial_id' and lead_id='$lead_id' $camp_postSQL;";
}
if($DBX){print STDERR "\n|$log_lookupSQL|\n";}
$sthA = $dbhA->prepare($log_lookupSQL) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $log_lookupSQL ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$lead_status = $aryA[0];
if ($status_ALL > 0)
{$camp_status_selected++;}
else
{
@status_vars = split(/---/,$status_post);
$fc=0;
foreach(@status_vars)
{
$status_temp = $status_vars[$fc];
if ($status_vars[$fc] =~ /\*/)
{
$status_temp =~ s/\*/.*/gi;
if ( ($lead_status =~ /^$status_temp/) && ($status_vars[$fc] =~ /\*$/) )
{$camp_status_selected++;}
if ( ($lead_status =~ /$status_temp$/) && ($status_vars[$fc] =~ /^\*/) )
{$camp_status_selected++;}
}
else
{
if ($lead_status =~ /^$status_temp$/)
{$camp_status_selected++;}
}
if ($DBX) {print " POST processing DEBUG: $fc|$status_temp|$lead_status|$lead_id|$vicidial_id|$ALLfile|\n";}
$fc++;
}
}
if ($DB) {print " POST processing SELECT: |$camp_status_selected|$sthArows|$camp_postSQL|$camp_ALL|$status_post|$status_ALL|$ALLfile|\n";}
}
else
{if ($DB) {print " POST processing ERROR: lead not found: |$lead_id|$ALLfile|\n";} }
$sthA->finish();
}
if ( ( ($camp_ALL > 0) && ($status_ALL > 0) ) || ($camp_status_selected > 0) )
{
$stmtA = "SELECT vendor_lead_code,security_phrase,address3,status from vicidial_list where lead_id='$lead_id' LIMIT 1;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$vendor_lead_code = $aryA[0];
$security_phrase = $aryA[1];
$address3 = $aryA[2];
$status = $aryA[3];
$vendor_lead_code =~ s/[^a-zA-Z0-9_-]//gi;
$security_phrase =~ s/[^a-zA-Z0-9_-]//gi;
$address3 =~ s/[^a-zA-Z0-9_-]//gi;
$status =~ s/[^a-zA-Z0-9_-]//gi;
}
else
{if ($DB) {print " POST processing ERROR: lead not found: |$lead_id|$ALLfile|\n";} }
$sthA->finish();
$ALLfile =~ s/POSTVLC/$vendor_lead_code/gi;
$ALLfile =~ s/POSTSP/$security_phrase/gi;
$ALLfile =~ s/POSTADDR3/$address3/gi;
$ALLfile =~ s/POSTSTATUS/$status/gi;
$SQLFILE =~ s/POSTVLC/$vendor_lead_code/gi;
$SQLFILE =~ s/POSTSP/$security_phrase/gi;
$SQLFILE =~ s/POSTADDR3/$address3/gi;
$SQLFILE =~ s/POSTSTATUS/$status/gi;
$filenameSQL = ",filename='$SQLFILE'";
`mv -f "$dir2/$origALLfile" "$dir2/$ALLfile"`;
if ($DB) {print " CLEAR POST COMPLETE: old: |$origALLfile| new: |$ALLfile|\n";}
if ($DB) {print " POST processing COMPLETE: old: |$origALLfile| new: |$ALLfile|\n";}
}
else
{
if ($DB) {print " POST processing SKIPPED: |$camp_ALL|$status_ALL|$camp_status_selected|$lead_id|$vicidial_id|$ALLfile|\n";}
if ($CLEAR_POST > 0)
{
$ALLfile =~ s/POSTVLC//gi;
$ALLfile =~ s/POSTSP//gi;
$ALLfile =~ s/POSTADDR3//gi;
$ALLfile =~ s/POSTSTATUS//gi;
$SQLFILE =~ s/POSTVLC//gi;
$SQLFILE =~ s/POSTSP//gi;
$SQLFILE =~ s/POSTADDR3//gi;
$SQLFILE =~ s/POSTSTATUS//gi;
$filenameSQL = ",filename='$SQLFILE'";
`mv -f "$dir2/$origALLfile" "$dir2/$ALLfile"`;
if ($DB) {print " CLEAR POST COMPLETE: old: |$origALLfile| new: |$ALLfile|\n";}
}
}
}
else
{if ($DB) {print " POST processing ERROR: No variables found: |$ALLfile|\n";} }
}
else
{if ($DB) {print " POST processing ERROR: No variables found: |$ALLfile|\n";} }
##### END post call variable replacement #####
$HTTP='http';
if ($HTTPS > 0) {$HTTP='https';}
$stmtA = "UPDATE recording_log set location='$HTTP://$server_ip/RECORDINGS/$ALLfile' $filenameSQL $lengthSQL where recording_id='$recording_id';";
if($DBX){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
### sleep for twenty hundredths of a second to not flood the server with disk activity
usleep(1*200*1000);
}
##### END post call variable replacement #####
$HTTP='http';
if ($HTTPS > 0) {$HTTP='https';}
$stmtA = "UPDATE recording_log set location='$HTTP://$server_ip/RECORDINGS/$ALLfile' $filenameSQL $lengthSQL where recording_id='$recording_id';";
if($DBX){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n";
### sleep for twenty hundredths of a second to not flood the server with disk activity
usleep(1*200*1000);
}
}
$i++;
@@ -1,4 +1,4 @@
# version: 20190310190601
# version: 20190311013701
users-user User ID <QXZ>This field is where you put the users ID number, can be up to 8 digits in length, Must be at least 2 characters in length.</QXZ>
users-pass Password <QXZ>This field is where you put the users password. Must be at least 2 characters in length. A medium strength user password will be at least 10 characters in length, and a strong user password will be at least 20 characters in length and have letters as well as at least one number. It is recommended that you use a longer password if possible, stringing together several unrelated words with no spaces, and a number somewhere in the string. The maximum size of a password is 100 characters.</QXZ>
users-force_change_password Force Change Password <QXZ>If this option is set to Y then the user will be prompted to change their password the next time they log in to the administration webpage. Default is N.</QXZ>
@@ -216,7 +216,7 @@ campaigns-campaign_recording Campaign Recording <QXZ>This menu allows you to cho
campaigns-campaign_rec_filename Campaign Rec Filename <QXZ>This field allows you to customize the name of the recording when Campaign recording is ONDEMAND or ALLCALLS. The allowed variables are CAMPAIGN INGROUP CUSTPHONE FULLDATE TINYDATE EPOCH AGENT VENDORLEADCODE LEADID CALLID RECID. If your dialers have --POST recording processing enabled, you can also use POSTVLC POSTSP POSTARRD3 POSTSTATUS. These POST options will alter the recording file name after the call has been finished and will replace the post variable with the value from the default fields. The default is FULLDATE_AGENT and would look like this 20051020-103108_6666. Another example is CAMPAIGN_TINYDATE_CUSTPHONE which would look like this TESTCAMP_51020103108_3125551212. The resulting filename must be less than 90 characters in length.</QXZ>
campaigns-allcalls_delay Recording Delay <QXZ>For ALLCALLS and ALLFORCE recording only. This setting will delay the starting of the recording on all calls for the number of seconds specified in this field. Default is 0.</QXZ>
campaigns-routing_initiated_recordings Routing Initiated Recording <QXZ>This option, if enabled, allows you to have the call routing script for Outbound auto-dial calls trigger the agent call recording instead of the agent screen. This option will only work if the recording option is set to ALLCALLS or ALLFORCE. This will work with agent manual dialed calls only if the recording delay is also set to 0. Default is N for disabled.</QXZ>
campaigns-mute_recordings Mute Recording Button <QXZ>This option, if enabled, will make the MUTE RECORDING button appear on the agent screen below the existing recording button. If a recording is muted, it will record silence until the MUTE RECORDING is clicked a second time. Default is N for disabled.</QXZ>
campaigns-mute_recordings Mute Recording Button <QXZ>This option, if enabled, will make the MUTE RECORDING button appear on the agent screen below the existing recording button. If a recording is muted, it will record silence or pause the recording until the MUTE RECORDING button is clicked a second time. You should not mute recordings for more than 15 minutes at a time. Default is N for disabled.</QXZ>
campaigns-per_call_notes Call Notes Per Call <QXZ>Setting this option to ENABLED will allow agents to enter in notes for every call they handle in the agent interface. The notes entry field will appear below the Comments field in the agent interface. Also, if the Agent User Group is allowed to view Call Logs then the agent will be able to view past call notes for a lead at any time. Default is DISABLED.</QXZ>
campaigns-comments_all_tabs Comments All Tabs <QXZ>Setting this option to ENABLED will display the Comments field on all tabs in the main agent screen. Default is DISABLED.</QXZ>
campaigns-comments_dispo_screen Comments Dispo Screen <QXZ>Setting this option to ENABLED will display the Comments field at the top of the agent disposition screen. If the REPLACE_CALL_NOTES option is selected, then the Comments field will replace the Call Notes field on the disposition screen if Per Call Notes is enabled. Default is DISABLED.</QXZ>
@@ -1037,7 +1037,7 @@ settings-chat_url Chat URL <QXZ>This is the location where you have placed the c
settings-agent_push_events Agent Push Events <QXZ>This setting will enable the sending of events from agent screens to the URL defined below. Default is 0 for disabled.</QXZ>
settings-agent_push_url Agent Push URL <QXZ>If Agent Push Events are enabled above, this is the URL that the events will be sent to. The variables that you can use within the URL are --A--user--B--, --A--event--B--, --A--message--B--, --A--lead_id--B--. Since this function uses AJAX, it must reference a local script on the web server. If you want to reference an external web address then you should use the get2post.php script that can be found in the extras directory.</QXZ>
settings-log_recording_access Log Recording Access <QXZ>This option if enabled allows the logging of user access to call recordings. It also requires the User setting Access Recordings to be set to 1 to allow a user to access call recordings. Default is 0 for disabled.</QXZ>
settings-mute_recordings Allow Mute Recordings <QXZ>This option if enabled allows you to enable the MUTE RECORDING button on the agent screen by campaign and-or user. This feature is only tested with systems running Asterisk 13. Default is 0 for disabled.</QXZ>
settings-mute_recordings Allow Mute Recordings <QXZ>This option if enabled allows you to enable the MUTE RECORDING button on the agent screen by campaign and-or user. This feature is only tested with systems running Asterisk 13. You should not mute recordings for more than 15 minutes at a time. Default is 0 for disabled.</QXZ>
settings-enable_auto_reports Enable Automated Reports <QXZ>This option if enabled allows you access to the Automated Reports section where you can set up reports to run at scheduled times and be delivered by email or FTP. Default is 0 for disabled.</QXZ>
settings-first_login_trigger First Login Trigger <QXZ>This setting allows for the initial configuration of the server screen to be shown to the administrator when they first log into the system.</QXZ>
settings-default_phone_registration_password Default Phone Registration Password <QXZ>This is the default registration password used when new phones are added to the system. Default is test.</QXZ>