#!/usr/bin/perl
#/* ========================================
# * ███╗   ███╗██████╗ ██╗ █████╗ ██╗
# * ████╗ ████║██╔══██╗██║██╔══██╗██║
# * ██╔████╔██║██║  ██║██║███████║██║
# * ██║╚██╔╝██║██║  ██║██║██╔══██║██║
# * ██║ ╚═╝ ██║██████╔╝██║██║  ██║███████╗
# * ╚═╝     ╚═╝╚═════╝ ╚═╝╚═╝  ╚═╝╚══════╝
# * ========================================
# * mDial - Omni-Channel Contact Centre Suite.
# * Initially Written by Martin McCarthy.
# * Contributions welcome.
# * Active: 2020 - 2023.
# *
# * This software is licensed under AGPLv2.
# * You can find more information here;
# * https://www.gnu.org/licenses/agpl-3.0.en.html
# * A copy of the license is also shipped with this build.
# *
# * Important note: this software is provided to you free of charge.
# * If you paid for this software, you were ripped off.
# *
# * This project is a fork of the awesome FOSS project, ViCiDial.
# * ViCiDial is copyrighted by Matt Florell and the ViCiDial Group
# * under the AGPLv2 license.
# *
# * You can find out more about ViCiDial;
# * Web: https://www.vicidial.com/
# * Email: Matt Florell <vicidial@gmail.com>
# * IRC: Libera.Chat - ##vicidial
# *
# * Bug reports, feature requests and patches welcome!
# * ======================================== */
$build                      = '230430-0800';
$MT[0]                      = '';
$minimum_gap                = 10;
$CLIminimum_gap             = '';
$check_user_sessions        = 0;
$vicidial_agent_latency_log = 'vicidial_agent_latency_log';
$gaps_found                 = 0;
$email_gaps_notice          = 0;
$email_message              = '';
$day_end_report             = 0;
$day_end_hours              = 18;
$day_end_groups             = '';
$group_groups[0]            = '';
$group_email[0]             = '';
$group_email_message[0]     = '';
$group_group_count          = 0;
$group_group_list           = '|';
use Time::Local;

if ( length( $ARGV[0] ) > 1 ) {
    $i = 0;
    while ( $#ARGV >= $i ) {
        $args = "$args $ARGV[$i]";
        $i++;
    }
    if ( $args =~ /--version/i ) {
        print "build: $build\n";
        exit;
    }
    if ( $args =~ /--help/i ) {
        print "allowed run time options:\n";
        print "  [-q] = quiet\n";
        print "  [-t] = test\n";
        print "  [--version] = show version of this script\n";
        print "  [--help] = this screen\n";
        print "  [--debug] = debugging messages\n";
        print "  [--debugX] = Extra debugging messages\n";
        print
"  [--container=XXX] = REQUIRED, the specifications to run these checks with\n";
        print
"  [--live] = check current logged-in agents only for the last 2 minutes\n";
        print "  [--fresh] = check agent records for 30-150 seconds ago\n";
        print "  [--recent] = check agent records for 1-63 minutes ago\n";
        print
"  [--24-hours] = check agent records for the last 24 hours(until last timeclock-end-of-day)\n";
        print
"  [--date=XXX] = check agent records for this specific date YYYY-MM-DD\n";
        print
"  [--minimum-gap=XXX] = override settings container with this gap seconds\n";
        print
"  [--check-user-sessions] = check by all user sessions (recommended only for --date=X or --24-hours runs)\n";
        print
"  [--email-gaps-notice] = if gaps are found, send email using container settings\n";
        print "  [--day-end-report] = only run day-end report, now\n";
        print "\n";
        exit;
    }
    else {
        if ( $args =~ /-q/i ) {
            $q = 1;
            $Q = 1;
        }
        if ( $args =~ /--debug/i ) {
            $DB = 1;
            print "\n----- DEBUGGING -----\n\n";
        }
        if ( $args =~ /--debugX/i ) {
            $DBX = 1;
            print "\n----- EXTRA DEBUGGING -----\n\n";
        }
        if ( $args =~ /-t|--test/i ) {
            $T    = 1;
            $TEST = 1;
            print "\n----- TESTING -----\n\n";
        }
        if ( $args =~ /--container=/i ) {
            @data_in   = split( /--container=/, $args );
            $container = $data_in[1];
            $container =~ s/ .*$//gi;
            if ( $Q < 1 ) {
                print "\n----- SETTINGS CONTAINER: $container -----\n\n";
            }
        }
        if ( length($container) < 1 ) {
            print
              "ERROR! Invalid Settings Container: $container     Exiting...\n";
            exit;
        }
        if ( $args =~ /--date=/i ) {
            @data_in = split( /--date=/, $args );
            $date    = $data_in[1];
            $date =~ s/ .*$//gi;
            if ( $Q < 1 ) { print "\n----- DATE SET: $date -----\n\n"; }
        }
        if ( $args =~ /--minimum-gap=/i ) {
            @data_in        = split( /--minimum-gap=/, $args );
            $CLIminimum_gap = $data_in[1];
            $CLIminimum_gap =~ s/ .*$//gi;
            $CLIminimum_gap =~ s/\D//gi;
            if ( $Q < 1 ) {
                print
                  "\n----- MINIMUM GAP OVERRIDE SET: $CLIminimum_gap -----\n\n";
            }
        }
        if ( $args =~ /--live/i ) {
            $check_live = 1;
            if ( $Q < 1 ) { print "\n----- LIVE CHECK -----\n\n"; }
        }
        if ( $args =~ /--fresh/i ) {
            $check_fresh = 1;
            if ( $Q < 1 ) { print "\n----- FRESH CHECK -----\n\n"; }
        }
        if ( $args =~ /--recent/i ) {
            $check_recent = 1;
            if ( $Q < 1 ) { print "\n----- RECENT CHECK -----\n\n"; }
        }
        if ( $args =~ /--24-hours/i ) {
            $check_oneday = 1;
            if ( $Q < 1 ) { print "\n----- 24-HOUR CHECK -----\n\n"; }
        }
        if ( $args =~ /--check-user-sessions/i ) {
            $check_user_sessions = 1;
            if ( $Q < 1 ) {
                print
"\n----- CHECK BY USER SESSIONS: $check_user_sessions -----\n\n";
            }
        }
        if ( $args =~ /--email-gaps-notice/i ) {
            $email_gaps_notice = 1;
            if ( $Q < 1 ) {
                print "\n----- EMAIL GAPS NOTICE: $email_gaps_notice -----\n\n";
            }
        }
        if ( $args =~ /--day-end-report/i ) {
            $day_end_report = 1;
            if ( $Q < 1 ) {
                print "\n----- DAY END REPORT: $day_end_report -----\n\n";
            }
        }
    }
}
else {
    print "no command line options set   Exiting...\n";
}
$secX = time();
( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
  localtime(time);
$year = ( $year + 1900 );
$yy   = $year;
$yy =~ s/^..//gi;
$mon++;
if ( $mon < 10 )  { $mon  = "0$mon"; }
if ( $mday < 10 ) { $mday = "0$mday"; }
if ( $hour < 10 ) { $hour = "0$hour"; }
if ( $min < 10 )  { $min  = "0$min"; }
if ( $sec < 10 )  { $sec  = "0$sec"; }
$SQLdate_NOW      = "$year-$mon-$mday $hour:$min:$sec";
$SQLdate_MIDNIGHT = "$year-$mon-$mday 00:00:00";
$VDL_one          = ( $secX - ( 60 * 1440 ) );
( $Dsec, $Dmin, $Dhour, $Dmday, $Dmon, $Dyear, $Dwday, $Dyday, $Disdst ) =
  localtime($VDL_one);
$Dyear = ( $Dyear + 1900 );
$Dmon++;
if ( $Dmon < 10 )  { $Dmon  = "0$Dmon"; }
if ( $Dmday < 10 ) { $Dmday = "0$Dmday"; }
if ( $Dhour < 10 ) { $Dhour = "0$Dhour"; }
if ( $Dmin < 10 )  { $Dmin  = "0$Dmin"; }
if ( $Dsec < 10 )  { $Dsec  = "0$Dsec"; }
$VDL_day = "$Dyear-$Dmon-$Dmday $Dhour:$Dmin:$Dsec";

if ( $check_live > 0 ) {
    $VDL_secBEGIN       = ( $secX - 0 );
    $VDL_secEND         = ( $secX - 120 );
    $query_length_check = ( $VDL_secBEGIN - $VDL_secEND );
}
if ( $check_fresh > 0 ) {
    $VDL_secBEGIN       = ( $secX - 30 );
    $VDL_secEND         = ( $secX - 150 );
    $query_length_check = ( $VDL_secBEGIN - $VDL_secEND );
}
if ( $check_recent > 0 ) {
    $VDL_secBEGIN       = ( $secX - ( 60 * 1 ) );
    $VDL_secEND         = ( $secX - ( 60 * 63 ) );
    $query_length_check = ( $VDL_secBEGIN - $VDL_secEND );
}
if ( $check_oneday > 0 ) {
    $VDL_secBEGIN       = ( $secX - ( 60 * 1 ) );
    $VDL_secEND         = ( $secX - ( 60 * 1441 ) );
    $query_length_check = ( $VDL_secBEGIN - $VDL_secEND );
}
if ( length($date) > 9 ) {
    $vicidial_agent_latency_log = 'vicidial_agent_latency_log_archive';
    $query_length_check         = 86400;
    $VDL_hourEND                = "$date 00:00:00";
    @cli_dateB                  = split( "-", $date );
    $cli_dateB[1]               = ( $cli_dateB[1] - 1 );
    $VDL_secEND =
      timelocal( 0, 0, 0, $cli_dateB[2], $cli_dateB[1], $cli_dateB[0] );
    $XDL_hourBEGIN = "$date 23:59:59";
    $VDL_secBEGIN =
      timelocal( 59, 59, 23, $cli_dateB[2], $cli_dateB[1], $cli_dateB[0] );
    $VDL_day = $VDL_hourEND;
}
( $Vsec, $Vmin, $Vhour, $Vmday, $Vmon, $Vyear, $Vwday, $Vyday, $Visdst ) =
  localtime($VDL_secBEGIN);
$Vyear = ( $Vyear + 1900 );
$Vmon++;
if ( $Vmon < 10 )  { $Vmon  = "0$Vmon"; }
if ( $Vmday < 10 ) { $Vmday = "0$Vmday"; }
if ( $Vhour < 10 ) { $Vhour = "0$Vhour"; }
if ( $Vmin < 10 )  { $Vmin  = "0$Vmin"; }
if ( $Vsec < 10 )  { $Vsec  = "0$Vsec"; }
$VDL_hourBEGIN = "$Vyear-$Vmon-$Vmday $Vhour:$Vmin:$Vsec";
( $Xsec, $Xmin, $Xhour, $Xmday, $Xmon, $Xyear, $Xwday, $Xyday, $Xisdst ) =
  localtime($VDL_secEND);
$Xyear = ( $Xyear + 1900 );
$Xmon++;
if ( $Xmon < 10 )  { $Xmon  = "0$Xmon"; }
if ( $Xmday < 10 ) { $Xmday = "0$Xmday"; }
if ( $Xhour < 10 ) { $Xhour = "0$Xhour"; }
if ( $Xmin < 10 )  { $Xmin  = "0$Xmin"; }
if ( $Xsec < 10 )  { $Xsec  = "0$Xsec"; }
$XDL_hourEND = "$Xyear-$Xmon-$Xmday $Xhour:$Xmin:$Xsec";
if ( !$Q ) { print "TEST\n\n"; }
if ( !$Q ) { print "NOW DATETIME:         $SQLdate_NOW\n"; }
if ( !$Q ) { print "ANALYSIS DATE RANGE:  $VDL_hourBEGIN - $XDL_hourEND\n"; }
$PATHconf = '/etc/astguiclient.conf';
open( conf, "$PATHconf" ) || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i = 0;

foreach (@conf) {
    $line = $conf[$i];
    $line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
    if ( ( $line =~ /^PATHhome/ ) && ( $CLIhome < 1 ) ) {
        $PATHhome = $line;
        $PATHhome =~ s/.*=//gi;
    }
    if ( ( $line =~ /^PATHlogs/ ) && ( $CLIlogs < 1 ) ) {
        $PATHlogs = $line;
        $PATHlogs =~ s/.*=//gi;
    }
    if ( ( $line =~ /^PATHagi/ ) && ( $CLIagi < 1 ) ) {
        $PATHagi = $line;
        $PATHagi =~ s/.*=//gi;
    }
    if ( ( $line =~ /^PATHweb/ ) && ( $CLIweb < 1 ) ) {
        $PATHweb = $line;
        $PATHweb =~ s/.*=//gi;
    }
    if ( ( $line =~ /^PATHsounds/ ) && ( $CLIsounds < 1 ) ) {
        $PATHsounds = $line;
        $PATHsounds =~ s/.*=//gi;
    }
    if ( ( $line =~ /^PATHmonitor/ ) && ( $CLImonitor < 1 ) ) {
        $PATHmonitor = $line;
        $PATHmonitor =~ s/.*=//gi;
    }
    if ( ( $line =~ /^VARserver_ip/ ) && ( $CLIserver_ip < 1 ) ) {
        $VARserver_ip = $line;
        $VARserver_ip =~ s/.*=//gi;
    }
    if ( ( $line =~ /^VARDB_server/ ) && ( $CLIDB_server < 1 ) ) {
        $VARDB_server = $line;
        $VARDB_server =~ s/.*=//gi;
    }
    if ( ( $line =~ /^VARDB_database/ ) && ( $CLIDB_database < 1 ) ) {
        $VARDB_database = $line;
        $VARDB_database =~ s/.*=//gi;
    }
    if ( ( $line =~ /^VARDB_user/ ) && ( $CLIDB_user < 1 ) ) {
        $VARDB_user = $line;
        $VARDB_user =~ s/.*=//gi;
    }
    if ( ( $line =~ /^VARDB_pass/ ) && ( $CLIDB_pass < 1 ) ) {
        $VARDB_pass = $line;
        $VARDB_pass =~ s/.*=//gi;
    }
    if ( ( $line =~ /^VARDB_port/ ) && ( $CLIDB_port < 1 ) ) {
        $VARDB_port = $line;
        $VARDB_port =~ s/.*=//gi;
    }
    $i++;
}
$server_ip = $VARserver_ip;    # Asterisk server IP
if ( !$VARDB_port ) { $VARDB_port = '3306'; }
use DBI;
$dbhA = DBI->connect( "DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port",
    "$VARDB_user", "$VARDB_pass", { PrintError => 0, RaiseError => 0 } )
  or die "Couldn't connect to database: " . DBI->errstr;
$container_sql = '';
$stmtA =
"SELECT container_entry FROM vicidial_settings_containers where container_id = '$container';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",        $dbhA->errstr;
$sthA->execute                 or die "executing: $stmtA ", $dbhA->errstr;
$sthArows = $sthA->rows;

if ( $sthArows > 0 ) {
    @aryA          = $sthA->fetchrow_array;
    $container_sql = $aryA[0];
}
$sthA->finish();
if ( length($container_sql) > 5 ) {
    @container_lines = split( /\n/, $container_sql );
    $i               = 0;
    foreach (@container_lines) {
        $container_lines[$i] =~ s/;.*//gi;
        if ( length( $container_lines[$i] ) > 5 ) {
            if ( $container_lines[$i] =~ /^minimum_gap/i ) {
                $minimum_gap = $container_lines[$i];
                $minimum_gap =~ s/minimum_gap=>|minimum_gap => //gi;
                $minimum_gap =~ s/\D//gi;
                if ($DBX) { print "Minimum Gap set: $minimum_gap \n"; }
            }
            if ( $container_lines[$i] =~ /^email_sender/i ) {
                $email_sender = $container_lines[$i];
                $email_sender =~ s/email_sender=>|email_sender => //gi;
                $email_sender =~ s/\n|\r|\t//gi;
                if ($DBX) { print "Email Sender set: $email_sender \n"; }
            }
            if ( $container_lines[$i] =~ /^email_list/i ) {
                $email_list = $container_lines[$i];
                $email_list =~ s/email_list=>|email_list => //gi;
                $email_list =~ s/\n|\r|\t//gi;
                if ($DBX) { print "Email List set: $email_list \n"; }
            }
            if ( $container_lines[$i] =~ /^email_subject/i ) {
                $email_subject = $container_lines[$i];
                $email_subject =~ s/email_subject=>|email_subject => //gi;
                $email_subject =~ s/\n|\r|\t//gi;
                if ($DBX) { print "Email Subject set: $email_subject \n"; }
            }
            if (   ( $container_lines[$i] =~ /^day_end_minimum_gap/i )
                && ( $day_end_report > 0 ) )
            {
                $minimum_gap = $container_lines[$i];
                $minimum_gap =~
                  s/day_end_minimum_gap=>|day_end_minimum_gap => //gi;
                $minimum_gap =~ s/\D//gi;
                if ($DBX) { print "Day End Minimum Gap set: $minimum_gap \n"; }
            }
            if (   ( $container_lines[$i] =~ /^day_end_email_list/i )
                && ( $day_end_report > 0 ) )
            {
                $email_list = $container_lines[$i];
                $email_list =~
                  s/day_end_email_list=>|day_end_email_list => //gi;
                $email_list =~ s/\n|\r|\t//gi;
                if ($DBX) { print "Day End Email List set: $email_list \n"; }
            }
            if (   ( $container_lines[$i] =~ /^day_end_email_subject/i )
                && ( $day_end_report > 0 ) )
            {
                $email_subject = $container_lines[$i];
                $email_subject =~
                  s/day_end_email_subject=>|day_end_email_subject => //gi;
                $email_subject =~ s/\n|\r|\t//gi;
                if ($DBX) {
                    print "Day End Email Subject set: $email_subject \n";
                }
            }
            if (   ( $container_lines[$i] =~ /^day_end_hours/i )
                && ( $day_end_report > 0 ) )
            {
                $day_end_hours = $container_lines[$i];
                $day_end_hours =~ s/day_end_hours=>|day_end_hours => //gi;
                $day_end_hours =~ s/\n|\r|\t//gi;
                if ($DBX) { print "Day End Hours set: $day_end_hours \n"; }
            }
            if (   ( $container_lines[$i] =~ /^day_end_groups/i )
                && ( $day_end_report > 0 ) )
            {
                $day_end_groups = $container_lines[$i];
                $day_end_groups =~ s/day_end_groups=>|day_end_groups => //gi;
                $day_end_groups =~ s/\n|\r|\t//gi;
                if ($DBX) {
                    print "Day End User Groups set: $day_end_groups \n";
                }
            }
            if ( $container_lines[$i] =~ /^group\d\d_groups/i ) {
                $temp_group_groups = $container_lines[$i];
                $temp_group_groups =~
                  s/^group\d\d_groups=>|^group\d\d_groups => //gi;
                $temp_group_groups =~ s/\n|\r|\t//gi;
                $temp_group_groups_num = $container_lines[$i];
                $temp_group_groups_num =~ s/^group|_groups.*//gi;
                $temp_group_groups_num = ( $temp_group_groups_num - 1 );
                $group_groups[$temp_group_groups_num] = ",$temp_group_groups,";
                $group_email_message[$temp_group_groups_num] = '';

                if ( $group_group_list !~ /\|$temp_group_groups\|/ ) {
                    $group_group_list .= "$temp_group_groups|";
                    $group_group_count++;
                }
                if ($DBX) {
                    print
"User Group Email User Group Restriction set: $temp_group_groups_num|$group_groups[$temp_group_groups_num]|$group_group_count| \n";
                }
            }
            if ( $container_lines[$i] =~ /^group\d\d_email/i ) {
                $temp_group_email = $container_lines[$i];
                $temp_group_email =~
                  s/^group\d\d_email=>|^group\d\d_email => //gi;
                $temp_group_email =~ s/\n|\r|\t//gi;
                $temp_group_email_num = $container_lines[$i];
                $temp_group_email_num =~ s/^group|_email.*//gi;
                $temp_group_email_num = ( $temp_group_email_num - 1 );
                $group_email[$temp_group_email_num] = $temp_group_email;
                if ($DBX) {
                    print
"User Group Email Group set: $temp_group_email_num|$group_email[$temp_group_email_num]| \n";
                }
            }
        }
        $i++;
    }
}
else {
    if ( $Q < 1 ) {
        print "ERROR: SETTINGS CONTAINER EMPTY: $container $container_sql\n";
    }
}
if ( length($CLIminimum_gap) > 0 ) { $minimum_gap = $CLIminimum_gap; }
$query_length_check_net = ( $query_length_check - $minimum_gap );
if ($DB) {
    print
"Net check seconds:  $query_length_check_net = ($query_length_check - $minimum_gap)\n";
}
$VDL_secBEGIN_master  = $VDL_secBEGIN;
$VDL_hourBEGIN_master = $VDL_hourBEGIN;
$VDL_secEND_master    = $VDL_secEND;
$XDL_hourEND_master   = $XDL_hourEND;
if ( $day_end_report > 0 ) {
    $DE_sec = ( $secX - ( 60 * 60 * $day_end_hours ) );
    ( $Dsec, $Dmin, $Dhour, $Dmday, $Dmon, $Dyear, $Dwday, $Dyday, $Disdst ) =
      localtime($DE_sec);
    $Dyear = ( $Dyear + 1900 );
    $Dmon++;
    if ( $Dmon < 10 )  { $Dmon  = "0$Dmon"; }
    if ( $Dmday < 10 ) { $Dmday = "0$Dmday"; }
    if ( $Dhour < 10 ) { $Dhour = "0$Dhour"; }
    if ( $Dmin < 10 )  { $Dmin  = "0$Dmin"; }
    if ( $Dsec < 10 )  { $Dsec  = "0$Dsec"; }
    $DE_date           = "$Dyear-$Dmon-$Dmday $Dhour:$Dmin:$Dsec";
    $day_end_groupsSQL = '';

    if ( length($day_end_groups) > 0 ) {
        $day_end_groupsSQL = $day_end_groups;
        $day_end_groupsSQL =~ s/,|\|/','/gi;
        $day_end_groupsSQL = "and user_group IN('$day_end_groupsSQL')";
    }
    if ($DB) {
        print
"Running the day-end report, for $day_end_hours hours ($day_end_groupsSQL) \n";
    }
    $stmtA =
"SELECT user,user_ip,gap_date,gap_length FROM vicidial_latency_gaps where gap_date > \"$DE_date\" and (gap_length >= $minimum_gap) order by gap_date limit 1000;";
    $sthA = $dbhA->prepare($stmtA) or die "preparing: ",        $dbhA->errstr;
    $sthA->execute                 or die "executing: $stmtA ", $dbhA->errstr;
    $sthArows = $sthA->rows;
    if ($DB) { print "|$sthArows|$stmtA|\n"; }
    $ug = 0;
    while ( $sthArows > $ug ) {
        @aryA              = $sthA->fetchrow_array;
        $DEuser[$ug]       = $aryA[0];
        $DEuser_ip[$ug]    = $aryA[1];
        $DEgap_date[$ug]   = $aryA[2];
        $DEgap_length[$ug] = $aryA[3];
        $ug++;
    }
    $sthA->finish();
    if ($DB) { print "Gaps found:  $ug |$usersSQL|\n"; }
    if ( $ug > 0 ) {
        $ug = 0;
        while ( $sthArows > $ug ) {
            $temp_ug       = ( $ug + 1 );
            $user_fullname = '';
            $stmtA =
"SELECT full_name,user_group FROM vicidial_users where user='$DEuser[$ug]' $day_end_groupsSQL limit 1;";
            $sthA = $dbhA->prepare($stmtA) or die "preparing: ", $dbhA->errstr;
            $sthA->execute or die "executing: $stmtA ",          $dbhA->errstr;
            $sthArowsU = $sthA->rows;
            if ($DBX) { print "|$sthArowsU|$stmtA|\n"; }
            if ( $sthArowsU > 0 ) {
                @aryA          = $sthA->fetchrow_array;
                $user_fullname = " - $aryA[0]";
                $email_message .=
"\nGap Detected: $temp_ug \nUser:$DEuser[$ug]$user_fullname \nWeb IP: $DEuser_ip[$ug] \nGap Start: $DEgap_date[$ug] \nGap Length: $DEgap_length[$ug] \n";
                if ($DBX) {
                    print
"LG Gap Debug:  $DEuser[$ug]$user_fullname|$DEuser_ip[$ug]|$DEgap_date[$ug]|$DEgap_length[$ug]|\n";
                }
            }
            else {
                if ($DBX) {
                    print
"LG Gap Debug Excluded:  $DEuser[$ug]$user_fullname|$DEuser_ip[$ug]|$DEgap_date[$ug]|$DEgap_length[$ug]|\n";
                }
            }
            $sthA->finish();
            $ug++;
        }
        $sthA->finish();
    }
    if (   ( $ug > 0 )
        && ( length($email_message) > 5 )
        && ( length($email_list) > 3 )
        && ( length($email_sender) > 3 )
        && ( length($email_subject) > 3 ) )
    {
        if ( !$Q ) { print "Sending email: $email_list\n"; }
        use MIME::QuotedPrint;
        use MIME::Base64;
        use Mail::Sendmail;
        %mail = (
            To      => "$email_list",
            From    => "$email_sender",
            Subject => "$email_subject",
        );
        $boundary             = "====" . time() . "====";
        $mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\"";
        $message              = encode_qp($email_message);
        $boundary             = '--' . $boundary;
        $mail{body} .= "$boundary\n";
        $mail{body} .= "Content-Type: text/plain; charset=\"iso-8859-1\"\n";
        $mail{body} .= "Content-Transfer-Encoding: quoted-printable\n\n";
        $mail{body} .= "$message\n";
        $mail{body} .= "$boundary\n";
        $mail{body} .= "--\n";
        sendmail(%mail) or die $mail::Sendmail::error;

        if ( !$Q ) {
            print "ok. log says:\n", $mail::sendmail::log;
        }    ### print mail log for status
    }
    exit;
}
if ( $check_live > 0 ) {
    $VDL_secBEGIN_master  = $VDL_secBEGIN;
    $VDL_hourBEGIN_master = $VDL_hourBEGIN;
    $VDL_secEND_master    = $VDL_secEND;
    $XDL_hourEND_master   = $XDL_hourEND;
    $stmtA =
      "SELECT user FROM vicidial_live_agents where ra_user='' order by user;";
    $active_users       = '';
    $active_users_count = 0;
    $sthA = $dbhA->prepare($stmtA) or die "preparing: ", $dbhA->errstr;
    $sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
    $sthArows = $sthA->rows;
    if ($DB) { print "|$sthArows|$stmtA|\n"; }

    while ( $sthArows > $active_users_count ) {
        @aryA                         = $sthA->fetchrow_array;
        $users[$active_users_count]   = "$aryA[0]";
        $hourEND[$active_users_count] = $XDL_hourEND;
        $secEND[$active_users_count]  = $VDL_secEND;
        $usersSQL .= "'$aryA[0]',";
        $active_users_count++;
    }
    $sthA->finish();
    if ( length($usersSQL) > 3 ) { $usersSQL =~ s/,$//gi; }
    if ($DB) { print "Active Users:  $active_users_count |$usersSQL|\n"; }
    $i = 0;
    while ( $active_users_count > $i ) {
        $VDL_secBEGIN  = $VDL_secBEGIN_master;
        $VDL_hourBEGIN = $VDL_hourBEGIN_master;
        $VDL_secEND    = $secEND[$i];
        $XDL_hourEND   = $hourEND[$i];
        if ($DB) {
            print
"\nAnalyzing user activity:  $users[$i] ($i)    starting at $XDL_hourEND ($VDL_secEND)\n";
        }
        $ping_count = 0;
        $stmtA =
"SELECT count(*) FROM $vicidial_agent_latency_log where user='$users[$i]' and log_date <= \"$VDL_hourBEGIN\" and log_date > \"$XDL_hourEND\";";
        $sthA = $dbhA->prepare($stmtA) or die "preparing: ", $dbhA->errstr;
        $sthA->execute or die "executing: $stmtA ",          $dbhA->errstr;
        $sthArows = $sthA->rows;
        if ($DBX) { print "|$sthArows|$stmtA|\n"; }
        if ( $sthArows > 0 ) {
            @aryA       = $sthA->fetchrow_array;
            $ping_count = $aryA[0];
        }
        $sthA->finish();
        if ( $ping_count < $query_length_check_net ) {
            $last_login_date        = $XDL_hourEND;
            $last_login_date_epoch  = $VDL_secEND;
            $last_logout_date       = $VDL_hourBEGIN;
            $last_logout_date_epoch = $VDL_secBEGIN;
            $last_login_date_epoch  = 0;
            $stmtA =
"SELECT event_date,UNIX_TIMESTAMP(event_date) FROM vicidial_user_log where user='$users[$i]' and event='LOGIN' and event_date <= \"$VDL_hourBEGIN\" and event_date > \"$VDL_day\" order by event_date desc limit 1;";
            $sthA = $dbhA->prepare($stmtA) or die "preparing: ", $dbhA->errstr;
            $sthA->execute or die "executing: $stmtA ",          $dbhA->errstr;
            $sthArowsU = $sthA->rows;
            if ($DBX) { print "|$sthArowsU|$stmtA|\n"; }

            if ( $sthArowsU > 0 ) {
                @aryA                  = $sthA->fetchrow_array;
                $last_login_date       = $aryA[0];
                $last_login_date_epoch = $aryA[1];
            }
            $sthA->finish();
            $stmtA =
"SELECT event_date,UNIX_TIMESTAMP(event_date) FROM vicidial_user_log where user='$users[$i]' and event IN('LOGOUT','TIMEOUTLOGOUT') and event_date <= \"$VDL_hourBEGIN\" and event_date > \"$last_login_date\" and event_date > \"$XDL_hourEND\" order by event_date limit 1;";
            $sthA = $dbhA->prepare($stmtA) or die "preparing: ", $dbhA->errstr;
            $sthA->execute or die "executing: $stmtA ",          $dbhA->errstr;
            $sthArowsU = $sthA->rows;
            if ($DBX) { print "|$sthArowsU|$stmtA|\n"; }
            if ( $sthArowsU > 0 ) {
                @aryA                   = $sthA->fetchrow_array;
                $last_logout_date       = $aryA[0];
                $last_logout_date_epoch = $aryA[1];
                if ($DB) {
                    print
"Last Logout within check range, overriding check begin: |$users[$i]|$last_logout_date|   |$VDL_hourBEGIN|$XDL_hourEND|\n";
                }
                $VDL_secBEGIN  = $last_logout_date_epoch;
                $VDL_hourBEGIN = $last_logout_date;
            }
            $sthA->finish();
            if ($DBX) {
                print
"Last Login check: |$users[$i]|$last_login_date|   |($last_login_date_epoch >= $VDL_secEND) && ($last_login_date_epoch <= $VDL_secBEGIN)|\n";
            }
            if (   ( $last_login_date_epoch >= $VDL_secEND )
                && ( $last_login_date_epoch <= $VDL_secBEGIN ) )
            {
                if ($DB) {
                    print
"Last Login within check range, overriding check end: |$users[$i]|$last_login_date|   |$VDL_hourBEGIN|$XDL_hourEND|\n";
                }
                $VDL_secEND  = $last_login_date_epoch;
                $XDL_hourEND = $last_login_date;
            }
            $last_ping_date       = '1970-01-01 00:00:00';
            $last_ping_date_epoch = 0;
            $last_ping_web_ip     = '';
            $last_ping_record     = 0;
            $temp_ping_gap_test   = 0;
            $stmtA =
"SELECT log_date,UNIX_TIMESTAMP(log_date),web_ip FROM $vicidial_agent_latency_log where user='$users[$i]' and log_date <= \"$VDL_hourBEGIN\" and log_date > \"$XDL_hourEND\";";
            $sthA = $dbhA->prepare($stmtA) or die "preparing: ", $dbhA->errstr;
            $sthA->execute or die "executing: $stmtA ",          $dbhA->errstr;
            $sthArows = $sthA->rows;
            if ($DBX) { print "|$sthArows|$stmtA|\n"; }
            $p = 0;

            while ( $sthArows > $p ) {
                @aryA = $sthA->fetchrow_array;
                if ( $last_ping_record != $aryA[1] ) {
                    if ( $last_ping_date_epoch < 1 ) {
                        $last_ping_date       = $aryA[0];
                        $last_ping_date_epoch = $aryA[1];
                        $last_ping_web_ip     = $aryA[2];
                        $temp_ping_gap_test =
                          ( $last_ping_date_epoch + $minimum_gap );
                        $last_ping_record = $aryA[1];
                    }
                    else {
                        if (   ( $aryA[1] >= $temp_ping_gap_test )
                            && ( length($last_ping_web_ip) > 3 ) )
                        {
                            $gaps_found++;
                            if ($DB) {
                                print
"Ping gap found! |$aryA[1]|$temp_ping_gap_test|\n";
                            }
                            $temp_gap_sec =
                              ( $aryA[1] - $last_ping_date_epoch );
                            $stmtA =
"INSERT IGNORE INTO vicidial_latency_gaps SET user='$users[$i]',user_ip='$last_ping_web_ip',gap_date='$last_ping_date',gap_length='$temp_gap_sec',last_login_date='$last_login_date',check_date='$SQLdate_NOW' ON DUPLICATE KEY UPDATE gap_length='$temp_gap_sec',last_login_date='$last_login_date',check_date='$SQLdate_NOW';";
                            $affected_rows = $dbhA->do($stmtA);
                            if ($DBX) {
                                print "LC DEBUG:  $affected_rows|$stmtA|\n";
                            }
                            if ( $affected_rows eq '1' ) {
                                $user_fullname   = '';
                                $user_user_group = '';
                                $stmtA =
"SELECT full_name,user_group FROM vicidial_users where user='$users[$i]' limit 1;";
                                $sthA = $dbhA->prepare($stmtA)
                                  or die "preparing: ", $dbhA->errstr;
                                $sthA->execute
                                  or die "executing: $stmtA ", $dbhA->errstr;
                                $sthArowsU = $sthA->rows;
                                if ($DBX) { print "|$sthArowsU|$stmtA|\n"; }
                                if ( $sthArowsU > 0 ) {
                                    @aryA            = $sthA->fetchrow_array;
                                    $user_fullname   = " - $aryA[0]";
                                    $user_user_group = $aryA[1];
                                }
                                $sthA->finish();
                                if ( length( $group_groups[0] ) > 0 ) {
                                    $ggc = 0;
                                    while ( $ggc < $group_group_count ) {
                                        if ( $group_groups[$ggc] =~
                                            /,$user_user_group,/ )
                                        {
                                            $group_email_message[$ggc] .=
"\nGap Detected: $gaps_found \nUser:$users[$i]$user_fullname \nWeb IP: $last_ping_web_ip \nGap Start: $last_ping_date \nGap Length: $temp_gap_sec \n";
                                        }
                                        $ggc++;
                                    }
                                }
                                else {
                                    $email_message .=
"\nGap Detected: $gaps_found \nUser:$users[$i]$user_fullname \nWeb IP: $last_ping_web_ip \nGap Start: $last_ping_date \nGap Length: $temp_gap_sec \n";
                                }
                            }
                            $last_ping_date       = $aryA[0];
                            $last_ping_date_epoch = $aryA[1];
                            $last_ping_web_ip     = $aryA[2];
                            $temp_ping_gap_test =
                              ( $last_ping_date_epoch + $minimum_gap );
                            $last_ping_record = $aryA[1];
                        }
                        else {
                            $last_ping_date       = $aryA[0];
                            $last_ping_date_epoch = $aryA[1];
                            $last_ping_web_ip     = $aryA[2];
                            $temp_ping_gap_test =
                              ( $last_ping_date_epoch + $minimum_gap );
                            $last_ping_record = $aryA[1];
                        }
                    }
                }
                $p++;
            }
            $sthA->finish();
            if (   ( $VDL_secBEGIN >= $temp_ping_gap_test )
                && ( $p > 0 )
                && ( length($last_ping_web_ip) > 3 ) )
            {
                $gaps_found++;
                if ($DB) {
                    print
                      "Ping gap found! |$VDL_secBEGIN|$temp_ping_gap_test|\n";
                }
                $temp_gap_sec = ( $VDL_secBEGIN - $last_ping_date_epoch );
                $stmtA =
"INSERT IGNORE INTO vicidial_latency_gaps SET user='$users[$i]',user_ip='$last_ping_web_ip',gap_date='$last_ping_date',gap_length='$temp_gap_sec',last_login_date='$last_login_date',check_date='$SQLdate_NOW' ON DUPLICATE KEY UPDATE gap_length='$temp_gap_sec',last_login_date='$last_login_date',check_date='$SQLdate_NOW';";
                $affected_rows = $dbhA->do($stmtA);
                if ($DBX) { print "LC DEBUG:  $affected_rows|$stmtA|\n"; }
                if ( $affected_rows eq '1' ) {
                    $user_fullname   = '';
                    $user_user_group = '';
                    $stmtA =
"SELECT full_name,user_group FROM vicidial_users where user='$users[$i]' limit 1;";
                    $sthA = $dbhA->prepare($stmtA)
                      or die "preparing: ", $dbhA->errstr;
                    $sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
                    $sthArowsU = $sthA->rows;
                    if ($DBX) { print "|$sthArowsU|$stmtA|\n"; }
                    if ( $sthArowsU > 0 ) {
                        @aryA            = $sthA->fetchrow_array;
                        $user_fullname   = " - $aryA[0]";
                        $user_user_group = $aryA[1];
                    }
                    $sthA->finish();
                    if ( length( $group_groups[0] ) > 0 ) {
                        $ggc = 0;
                        while ( $ggc < $group_group_count ) {
                            if ( $group_groups[$ggc] =~ /,$user_user_group,/ ) {
                                $group_email_message[$ggc] .=
"\nGap Detected: $gaps_found \nUser:$users[$i]$user_fullname \nWeb IP: $last_ping_web_ip \nGap Start: $last_ping_date \nGap Length: $temp_gap_sec \n";
                            }
                            $ggc++;
                        }
                    }
                    else {
                        $email_message .=
"\nGap Detected: $gaps_found \nUser:$users[$i]$user_fullname \nWeb IP: $last_ping_web_ip \nGap Start: $last_ping_date \nGap Length: $temp_gap_sec \n";
                    }
                }
            }
        }
        else {
            if ($DBX) {
                print
"LC DEBUG: normal ping count for user: $users[$i] {$ping_count >= $query_length_check_net}\n";
            }
        }
        $i++;
    }
}
if (   ( $check_fresh > 0 )
    || ( $check_recent > 0 )
    || ( $check_oneday > 0 )
    || ( length($date) > 9 ) )
{
    $VDL_secBEGIN_master  = $VDL_secBEGIN;
    $VDL_hourBEGIN_master = $VDL_hourBEGIN;
    $VDL_secEND_master    = $VDL_secEND;
    $XDL_hourEND_master   = $XDL_hourEND;
    if ( $check_user_sessions > 0 ) {
        $stmtA =
"SELECT user,event_date,UNIX_TIMESTAMP(event_date) FROM vicidial_user_log where event='LOGIN' and event_date <= \"$VDL_hourBEGIN\" and event_date > \"$XDL_hourEND\" order by user,event_date limit 1000000;";
        $active_users       = '';
        $active_users_count = 0;
        $sthA = $dbhA->prepare($stmtA) or die "preparing: ", $dbhA->errstr;
        $sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
        $sthArows = $sthA->rows;
        if ($DB) { print "|$sthArows|$stmtA|\n"; }
        while ( $sthArows > $active_users_count ) {
            @aryA                         = $sthA->fetchrow_array;
            $users[$active_users_count]   = "$aryA[0]";
            $hourEND[$active_users_count] = "$aryA[1]";
            $secEND[$active_users_count]  = "$aryA[2]";
            $usersSQL .= "'$aryA[0]',";
            $active_users_count++;
        }
        $sthA->finish();
        if ( length($usersSQL) > 3 ) { $usersSQL =~ s/,$//gi; }
        if ($DB) {
            print "Active User Sessions:  $active_users_count |$usersSQL|\n";
        }
    }
    else {
        $stmtA =
"SELECT distinct user FROM $vicidial_agent_latency_log where log_date <= \"$VDL_hourBEGIN\" and log_date > \"$XDL_hourEND\" order by user;";
        $active_users       = '';
        $active_users_count = 0;
        $sthA = $dbhA->prepare($stmtA) or die "preparing: ", $dbhA->errstr;
        $sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
        $sthArows = $sthA->rows;
        if ($DB) { print "|$sthArows|$stmtA|\n"; }
        while ( $sthArows > $active_users_count ) {
            @aryA                         = $sthA->fetchrow_array;
            $users[$active_users_count]   = "$aryA[0]";
            $hourEND[$active_users_count] = $XDL_hourEND;
            $secEND[$active_users_count]  = $VDL_secEND;
            $usersSQL .= "'$aryA[0]',";
            $active_users_count++;
        }
        $sthA->finish();
        if ( length($usersSQL) > 3 ) { $usersSQL =~ s/,$//gi; }
        if ($DB) { print "Active Users:  $active_users_count |$usersSQL|\n"; }
    }
    $i = 0;
    while ( $active_users_count > $i ) {
        $VDL_secBEGIN  = $VDL_secBEGIN_master;
        $VDL_hourBEGIN = $VDL_hourBEGIN_master;
        $VDL_secEND    = $secEND[$i];
        $XDL_hourEND   = $hourEND[$i];
        if ($DB) {
            print
"\nAnalyzing user activity:  $users[$i] ($i)    starting at $XDL_hourEND ($VDL_secEND)\n";
        }
        $ping_count = 0;
        $stmtA =
"SELECT count(*) FROM $vicidial_agent_latency_log where user='$users[$i]' and log_date <= \"$VDL_hourBEGIN\" and log_date > \"$XDL_hourEND\";";
        $sthA = $dbhA->prepare($stmtA) or die "preparing: ", $dbhA->errstr;
        $sthA->execute or die "executing: $stmtA ",          $dbhA->errstr;
        $sthArows = $sthA->rows;
        if ($DBX) { print "|$sthArows|$stmtA|\n"; }
        if ( $sthArows > 0 ) {
            @aryA       = $sthA->fetchrow_array;
            $ping_count = $aryA[0];
        }
        $sthA->finish();
        if ( $ping_count < $query_length_check_net ) {
            $last_login_date        = $XDL_hourEND;
            $last_login_date_epoch  = $VDL_secEND;
            $last_logout_date       = $VDL_hourBEGIN;
            $last_logout_date_epoch = $VDL_secBEGIN;
            if ( $check_user_sessions < 1 ) {
                $last_login_date_epoch = 0;
                $stmtA =
"SELECT event_date,UNIX_TIMESTAMP(event_date) FROM vicidial_user_log where user='$users[$i]' and event='LOGIN' and event_date <= \"$VDL_hourBEGIN\" and event_date > \"$VDL_day\" order by event_date desc limit 1;";
                $sthA = $dbhA->prepare($stmtA)
                  or die "preparing: ", $dbhA->errstr;
                $sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
                $sthArowsU = $sthA->rows;
                if ($DBX) { print "|$sthArowsU|$stmtA|\n"; }
                if ( $sthArowsU > 0 ) {
                    @aryA                  = $sthA->fetchrow_array;
                    $last_login_date       = $aryA[0];
                    $last_login_date_epoch = $aryA[1];
                }
                $sthA->finish();
            }
            $stmtA =
"SELECT event_date,UNIX_TIMESTAMP(event_date) FROM vicidial_user_log where user='$users[$i]' and event IN('LOGOUT','TIMEOUTLOGOUT') and event_date <= \"$VDL_hourBEGIN\" and event_date > \"$last_login_date\" and event_date > \"$XDL_hourEND\" order by event_date limit 1;";
            $sthA = $dbhA->prepare($stmtA) or die "preparing: ", $dbhA->errstr;
            $sthA->execute or die "executing: $stmtA ",          $dbhA->errstr;
            $sthArowsU = $sthA->rows;
            if ($DBX) { print "|$sthArowsU|$stmtA|\n"; }
            if ( $sthArowsU > 0 ) {
                @aryA                   = $sthA->fetchrow_array;
                $last_logout_date       = $aryA[0];
                $last_logout_date_epoch = $aryA[1];
                if ($DB) {
                    print
"Last Logout within check range, overriding check begin: |$users[$i]|$last_logout_date|   |$VDL_hourBEGIN|$XDL_hourEND|\n";
                }
                $VDL_secBEGIN  = $last_logout_date_epoch;
                $VDL_hourBEGIN = $last_logout_date;
            }
            $sthA->finish();
            if ($DBX) {
                print
"Last Login check: |$users[$i]|$last_login_date|   |($last_login_date_epoch >= $VDL_secEND) && ($last_login_date_epoch <= $VDL_secBEGIN)|\n";
            }
            if (   ( $last_login_date_epoch >= $VDL_secEND )
                && ( $last_login_date_epoch <= $VDL_secBEGIN ) )
            {
                if ($DB) {
                    print
"Last Login within check range, overriding check end: |$users[$i]|$last_login_date|   |$VDL_hourBEGIN|$XDL_hourEND|\n";
                }
                $VDL_secEND  = $last_login_date_epoch;
                $XDL_hourEND = $last_login_date;
            }
            $last_ping_date       = '1970-01-01 00:00:00';
            $last_ping_date_epoch = 0;
            $last_ping_web_ip     = '';
            $last_ping_record     = 0;
            $temp_ping_gap_test   = 0;
            $stmtA =
"SELECT log_date,UNIX_TIMESTAMP(log_date),web_ip FROM $vicidial_agent_latency_log where user='$users[$i]' and log_date <= \"$VDL_hourBEGIN\" and log_date > \"$XDL_hourEND\";";
            $sthA = $dbhA->prepare($stmtA) or die "preparing: ", $dbhA->errstr;
            $sthA->execute or die "executing: $stmtA ",          $dbhA->errstr;
            $sthArows = $sthA->rows;
            if ($DBX) { print "|$sthArows|$stmtA|\n"; }
            $p = 0;

            while ( $sthArows > $p ) {
                @aryA = $sthA->fetchrow_array;
                if ( $last_ping_record != $aryA[1] ) {
                    if ( $last_ping_date_epoch < 1 ) {
                        $last_ping_date       = $aryA[0];
                        $last_ping_date_epoch = $aryA[1];
                        $last_ping_web_ip     = $aryA[2];
                        $temp_ping_gap_test =
                          ( $last_ping_date_epoch + $minimum_gap );
                        $last_ping_record = $aryA[1];
                    }
                    else {
                        if (   ( $aryA[1] >= $temp_ping_gap_test )
                            && ( length($last_ping_web_ip) > 3 ) )
                        {
                            $gaps_found++;
                            if ($DB) {
                                print
"Ping gap found! |$aryA[1]|$temp_ping_gap_test|\n";
                            }
                            $temp_gap_sec =
                              ( $aryA[1] - $last_ping_date_epoch );
                            $stmtA =
"INSERT IGNORE INTO vicidial_latency_gaps SET user='$users[$i]',user_ip='$last_ping_web_ip',gap_date='$last_ping_date',gap_length='$temp_gap_sec',last_login_date='$last_login_date',check_date='$SQLdate_NOW' ON DUPLICATE KEY UPDATE gap_length='$temp_gap_sec',last_login_date='$last_login_date',check_date='$SQLdate_NOW';";
                            $affected_rows = $dbhA->do($stmtA);
                            if ($DBX) {
                                print "LC DEBUG:  $affected_rows|$stmtA|\n";
                            }
                            if ( $affected_rows eq '1' ) {
                                $user_fullname   = '';
                                $user_user_group = '';
                                $stmtA =
"SELECT full_name,user_group FROM vicidial_users where user='$users[$i]' limit 1;";
                                $sthA = $dbhA->prepare($stmtA)
                                  or die "preparing: ", $dbhA->errstr;
                                $sthA->execute
                                  or die "executing: $stmtA ", $dbhA->errstr;
                                $sthArowsU = $sthA->rows;
                                if ($DBX) { print "|$sthArowsU|$stmtA|\n"; }
                                if ( $sthArowsU > 0 ) {
                                    @aryA            = $sthA->fetchrow_array;
                                    $user_fullname   = " - $aryA[0]";
                                    $user_user_group = $aryA[1];
                                }
                                $sthA->finish();
                                if ( length( $group_groups[0] ) > 0 ) {
                                    $ggc = 0;
                                    while ( $ggc < $group_group_count ) {
                                        if ( $group_groups[$ggc] =~
                                            /,$user_user_group,/ )
                                        {
                                            $group_email_message[$ggc] .=
"\nGap Detected: $gaps_found \nUser:$users[$i]$user_fullname \nWeb IP: $last_ping_web_ip \nGap Start: $last_ping_date \nGap Length: $temp_gap_sec \n";
                                        }
                                        $ggc++;
                                    }
                                }
                                else {
                                    $email_message .=
"\nGap Detected: $gaps_found \nUser:$users[$i]$user_fullname \nWeb IP: $last_ping_web_ip \nGap Start: $last_ping_date \nGap Length: $temp_gap_sec \n";
                                }
                            }
                            $last_ping_date       = $aryA[0];
                            $last_ping_date_epoch = $aryA[1];
                            $last_ping_web_ip     = $aryA[2];
                            $temp_ping_gap_test =
                              ( $last_ping_date_epoch + $minimum_gap );
                            $last_ping_record = $aryA[1];
                        }
                        else {
                            $last_ping_date       = $aryA[0];
                            $last_ping_date_epoch = $aryA[1];
                            $last_ping_web_ip     = $aryA[2];
                            $temp_ping_gap_test =
                              ( $last_ping_date_epoch + $minimum_gap );
                            $last_ping_record = $aryA[1];
                        }
                    }
                }
                $p++;
            }
            $sthA->finish();
            if (   ( $VDL_secBEGIN >= $temp_ping_gap_test )
                && ( $p > 0 )
                && ( length($last_ping_web_ip) > 3 ) )
            {
                $gaps_found++;
                if ($DB) {
                    print
                      "Ping gap found! |$VDL_secBEGIN|$temp_ping_gap_test|\n";
                }
                $temp_gap_sec = ( $VDL_secBEGIN - $last_ping_date_epoch );
                $stmtA =
"INSERT IGNORE INTO vicidial_latency_gaps SET user='$users[$i]',user_ip='$last_ping_web_ip',gap_date='$last_ping_date',gap_length='$temp_gap_sec',last_login_date='$last_login_date',check_date='$SQLdate_NOW' ON DUPLICATE KEY UPDATE gap_length='$temp_gap_sec',last_login_date='$last_login_date',check_date='$SQLdate_NOW';";
                $affected_rows = $dbhA->do($stmtA);
                if ($DBX) { print "LC DEBUG:  $affected_rows|$stmtA|\n"; }
                if ( $affected_rows eq '1' ) {
                    $user_fullname   = '';
                    $user_user_group = '';
                    $stmtA =
"SELECT full_name,user_group FROM vicidial_users where user='$users[$i]' limit 1;";
                    $sthA = $dbhA->prepare($stmtA)
                      or die "preparing: ", $dbhA->errstr;
                    $sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
                    $sthArowsU = $sthA->rows;
                    if ($DBX) { print "|$sthArowsU|$stmtA|\n"; }
                    if ( $sthArowsU > 0 ) {
                        @aryA            = $sthA->fetchrow_array;
                        $user_fullname   = " - $aryA[0]";
                        $user_user_group = $aryA[1];
                    }
                    $sthA->finish();
                    if ( length( $group_groups[0] ) > 0 ) {
                        $ggc = 0;
                        while ( $ggc < $group_group_count ) {
                            if ( $group_groups[$ggc] =~ /,$user_user_group,/ ) {
                                $group_email_message[$ggc] .=
"\nGap Detected: $gaps_found \nUser:$users[$i]$user_fullname \nWeb IP: $last_ping_web_ip \nGap Start: $last_ping_date \nGap Length: $temp_gap_sec \n";
                            }
                            $ggc++;
                        }
                    }
                    else {
                        $email_message .=
"\nGap Detected: $gaps_found \nUser:$users[$i]$user_fullname \nWeb IP: $last_ping_web_ip \nGap Start: $last_ping_date \nGap Length: $temp_gap_sec \n";
                    }
                }
            }
        }
        else {
            if ($DBX) {
                print
"LC DEBUG: normal ping count for user: $users[$i] {$ping_count >= $query_length_check_net}\n";
            }
        }
        $i++;
    }
}
$dbhA->disconnect();
if (   ( $gaps_found > 0 )
    && ( $email_gaps_notice > 0 )
    && ( length($email_message) > 5 )
    && ( length($email_list) > 3 )
    && ( length($email_sender) > 3 )
    && ( length($email_subject) > 3 ) )
{
    if ( !$Q ) { print "Sending email: $email_list\n"; }
    use MIME::QuotedPrint;
    use MIME::Base64;
    use Mail::Sendmail;
    %mail = (
        To      => "$email_list",
        From    => "$email_sender",
        Subject => "$email_subject",
    );
    $boundary             = "====" . time() . "====";
    $mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\"";
    $message              = encode_qp($email_message);
    $boundary             = '--' . $boundary;
    $mail{body} .= "$boundary\n";
    $mail{body} .= "Content-Type: text/plain; charset=\"iso-8859-1\"\n";
    $mail{body} .= "Content-Transfer-Encoding: quoted-printable\n\n";
    $mail{body} .= "$message\n";
    $mail{body} .= "$boundary\n";
    $mail{body} .= "--\n";
    sendmail(%mail) or die $mail::Sendmail::error;

    if ( !$Q ) {
        print "ok. log says:\n", $mail::sendmail::log;
    }    ### print mail log for status
}
if ( ( $gaps_found > 0 ) && ( $group_group_count > 0 ) ) {
    $ggc = 0;
    while ( $ggc < $group_group_count ) {
        if (   ( length( $group_email_message[$ggc] ) > 10 )
            && ( length( $group_email[$ggc] ) > 5 )
            && ( length($email_sender) > 5 )
            && ( length($email_subject) > 1 ) )
        {
            if ( !$Q ) {
                print
"Sending group group email: $group_email[$ggc]|$group_groups[$ggc]|\n";
            }
            use MIME::QuotedPrint;
            use MIME::Base64;
            use Mail::Sendmail;
            %mail = (
                To      => "$group_email[$ggc]",
                From    => "$email_sender",
                Subject => "$email_subject",
            );
            $boundary             = "====" . time() . "====";
            $mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\"";
            $message              = encode_qp( $group_email_message[$ggc] );
            $boundary             = '--' . $boundary;
            $mail{body} .= "$boundary\n";
            $mail{body} .= "Content-Type: text/plain; charset=\"iso-8859-1\"\n";
            $mail{body} .= "Content-Transfer-Encoding: quoted-printable\n\n";
            $mail{body} .= "$message\n";
            $mail{body} .= "$boundary\n";
            $mail{body} .= "--\n";
            sendmail(%mail) or die $mail::Sendmail::error;

            if ( !$Q ) {
                print "ok. log says:\n", $mail::sendmail::log;
            }    ### print mail log for status
        }
        $ggc++;
    }
}
$secY = time();
$secZ = ( $secY - $secX );
if ( !$q ) {
    print
"\nDONE. Gaps found: $gaps_found   Script execution time in seconds: $secZ\n";
}
if ( !$Q ) { print "Script exiting...\n"; }
exit;
