#!/bin/bash
#!/bin/bash
#============================================================================================================
# Name                : domains-checker.sh
# Description         : Grabs all domains under a cpanel account and retrieves the PHP version.
# Author              : Nelson A.
# Created             : 11.11.2024
# Updated             :
# Usage               :
# Version             : 0.5
#============================================================================================================

# Set alert to 'False'
alert=0

# Add colors
red=$(tput setaf 1)
green=$(tput setaf 2)
yellow=$(tput setaf 3)
blue=$(tput setaf 4)
reset=$(tput sgr0)
bold='\033[1m'

username=$1

# Parse command line arguments
SUMMARY_ONLY=false
MAILBOXES=false
NO_INODES=false
NO_HTTP=false

while [[ $# -gt 0 ]]; do
    case $1 in
        --summary)
            SUMMARY_ONLY=true
            shift
            ;;
        --mailboxes)
            MAILBOXES=true
            shift
            ;;
        --no-inodes)
            NO_INODES=true
            shift
            ;;
        --no-inode)
            NO_INODES=true
            shift
            ;;
        --no-http)
            NO_HTTP=true
            shift
            ;;
        *)
            shift
            ;;
    esac
done

#-----------------------------------------------------------
# Validate input
#-----------------------------------------------------------
if [ -z "$username" ]; then
    echo "${red}Usage:${reset} $0 <cpanel-username>"
    exit 1
fi

echo $MAILBOXES

# Check if cPanel user exists
if [ ! -f /var/cpanel/users/"$username" ]; then
    echo "$red Account $reset $username $red is NOT found on the server!$reset"
    exit 1
fi

#-----------------------------------------------------------
# BASIC FUNCTIONS
#-----------------------------------------------------------

# Basic info
get_basic_info() {
    accountip=$(grep ^IP /var/cpanel/users/"$username" | cut -d= -f2)
    maindomain=$(grep ^DNS= /var/cpanel/users/"$username" | cut -d= -f2)
    validusername=$username
    hostname=$(hostname)
}

#Let's get the PHP Version for the mainsite:
php_ver=$(uapi --output=jsonpretty --user=$username LangPHP php_get_vhost_versions type='vhost' | grep -B11 -F "\"vhost\" : \"$maindomain\"" | grep '"version" :' | awk -F'"' '{print $4}')
echo "PHP Version for $maindomain is: $php_ver"
# Nameservers (using WHM API)
get_nameservers() {
    NS1=""; NS2=""
    if command -v whmapi1 >/dev/null 2>&1; then
        mapfile -t NSLIST < <(whmapi1 --output=jsonpretty get_nameserver_config 2>/dev/null | awk -F'"' '/nameservers/ {getline; print $2; getline; print $2; exit}')
        NS1="${NSLIST[0]:-}"
        NS2="${NSLIST[1]:-}"
    fi
}

# Disk usage
get_disk_usage() {
    DISK=$(uapi --user="$username" Quota get_quota_info 2>/dev/null | grep megabytes_used | cut -d: -f2 | tr -d "' ")
    formatedDisk="${DISK:-0} MB"
}

# Email usage
get_email_usage() {
    EMAILUSAGE=$(du -sh /home/"$username"/mail 2>/dev/null | awk '{print $1}')
    EMAILUSAGE=${EMAILUSAGE:-"N/A"}
}

# Inodes
check_inodes() {
    inodes_count=$(find /home/"$username" -xdev 2>/dev/null | wc -l)
    if [ "$inodes_count" -gt 295001  ]; then
        inode_status="${red}${inodes_count} !!! WARNING: High inode usage${reset}"
    elif [ "$inodes_count" -ge 280000 ] && [ "$inodes_count" -le 295000 ]; then
        inode_status="${yellow}${inodes_count} - Inode usage a bit high${reset}"
    else
        inode_status="${green}${inodes_count}${reset}"
    fi
}

# Database sizes
get_db_sizes() {
    total_db_human=$(du -shc /var/lib/mysql/${username}_* 2>/dev/null | tail -n1 | awk '{print $1}')
    total_db_human=${total_db_human:-"N/A"}
}

#-----------------------------------------------------------
# PRINT HEADER
#-----------------------------------------------------------
echo -e "\n${bold}+===================================+"
echo -e "| cPanel Account Summary            |"
echo -e "+===================================+${reset}"

#-----------------------------------------------------------
# RUN EACH SECTION AND PRINT IMMEDIATELY
#-----------------------------------------------------------

#------------Print Basic Account Information---------------------------------------------

get_basic_info
echo -e "| Domain: $maindomain"
echo -e "| IP: $accountip"
echo -e "| Username: $validusername"
echo -e "| Hostname: $hostname"

#------------Print Nameservers---------------------------------------------

get_nameservers
echo -e "| NameServer1: $NS1"
echo -e "| NameServer2: $NS2"


#------------Print Disk Usage---------------------------------------------

get_disk_usage
echo -e "| Disk Usage: $formatedDisk"

#------------Print Email Usage---------------------------------------------

get_email_usage
echo -e "| Email Usage: $EMAILUSAGE"

#------------Print Databases---------------------------------------------
get_db_sizes
echo -e "| Database Disk Use: $total_db_human"

#------------Print Inodes---------------------------------------------

if [[ "$NO_INODES" == false ]]; then
    check_inodes
    echo -e "| Inodes: $inode_status"
fi

echo "+===================================+"


# Exit if --summary flag was used
if [ "$SUMMARY_ONLY" = true ]; then
    exit 0
fi



#-----------------------------------------------------------
# STAGE 2: DOMAIN CHECKS
#-----------------------------------------------------------

echo
echo "$yellow STAGE #2 ----- Getting Domains Information $reset"

domains=$(grep "$username" /etc/userdatadomains | grep -E "(main|addon|parked)" | cut -d: -f1)

if [[ -z "$domains" ]]; then
    echo "No domains found for user $username"
    exit 0
fi

count=$(echo "$domains" | wc -l)
echo -e " == Found $count domains for $username cPanel account ==\n"
echo "$domains"
echo


# Loop through each domain

check_domains_dns() {
    using_this_ns=()
    not_using_this_ns=()
    declare -A domain_details

    for domain in $domains; do
        output=""
        output+="\n${bold}=== Checking DNS for $domain ===${reset}\n\n"

        # --- NS Lookup ---
        output+="Nameservers for $domain:\n"
        if command -v dig >/dev/null 2>&1; then
            ns_records=$(dig +short NS "$domain")
        elif command -v host >/dev/null 2>&1; then
            ns_records=$(host -t NS "$domain" | awk '{print $NF}')
        elif command -v nslookup >/dev/null 2>&1; then
            ns_records=$(nslookup -type=NS "$domain" | grep -i 'nameserver' | awk '{print $NF}')
        else
            output+="${red}No DNS lookup tool (dig/host/nslookup) found!${reset}\n"
            continue
        fi

        domain_uses_this_ns=false

        if [[ -z "$ns_records" ]]; then
            output+="${red}No NS records found!${reset}\n"
        else
            while read -r ns; do
                [[ -z "$ns" ]] && continue
                ns_clean="${ns%.}"
                if [[ "$ns_clean" == "$NS1" || "$ns_clean" == "$NS2" ]]; then
                    output+=" NS: ${green}$ns${reset}\n"
                    domain_uses_this_ns=true
                else
                    output+=" NS: ${red}$ns${reset}\n"
                fi
            done <<< "$ns_records"
        fi

        # --- Registrar Lookup (WHOIS) ---
        output+="\nRegistrar Information:\n"

        if command -v whois >/dev/null 2>&1; then
            registrar_raw=$(whois "$domain" 2>/dev/null)

            registrar_name=$(echo "$registrar_raw" | grep -iE '^Registrar:' | head -n1 | sed 's/Registrar:[ ]*//I')
            registrar_url=$(echo "$registrar_raw" | grep -iE '^Registrar URL:' | head -n1 | sed 's/Registrar URL:[ ]*//I')

            [[ -z "$registrar_name" ]] && registrar_name="Unknown"
            [[ -z "$registrar_url" ]] && registrar_url="Not listed"

            output+=" Registrar: $registrar_name\n"
            output+=" Registrar URL: $registrar_url\n"

        else
            output+="${red}WHOIS command not available, skipping registrar info${reset}\n"
        fi

        # --- A Record Lookup ---
        output+="\nResolving A record(s) for $domain...\n"
        a_records=$(dig +short "$domain" A | egrep '^([0-9]{1,3}\.){3}[0-9]{1,3}$')

        if [[ -z "$a_records" ]]; then
            output+=" A Record: ${red}MISSING!${reset}\n"
        else
            while read -r ip; do
                [[ -z "$ip" ]] && continue
                if [[ "$ip" == "$accountip" ]]; then
                    output+=" A Record: ${green}$ip Matches cPanel IP${reset}\n"
                else
                    output+=" A Record: ${red}$ip Not Pointed to this cPanel${reset}\n"
                fi
            done <<< "$a_records"
        fi

        output+="------------------------------------\n"

        domain_details["$domain"]="$output"

        if [[ "$domain_uses_this_ns" == true ]]; then
            using_this_ns+=("$domain")
        else
            not_using_this_ns+=("$domain")
        fi
    done

    # --- Output Phase ---

    echo
    echo "-- Domains using this server nameservers (${#using_this_ns[@]})"
    for d in "${using_this_ns[@]}"; do
        echo "$d"
    done
    echo

    for d in "${using_this_ns[@]}"; do
        echo -e "${domain_details[$d]}"
    done

    echo
    echo "-- Domains not using this server nameservers (${#not_using_this_ns[@]})"
    for d in "${not_using_this_ns[@]}"; do
        echo "$d"
    done
    echo

    for d in "${not_using_this_ns[@]}"; do
        echo -e "${domain_details[$d]}"
    done

    echo
}

# Run
check_domains_dns



#-----------------------------------------------------------
# STAGE 3: CuRL CHECKS
#-----------------------------------------------------------
curl_check() {
    local domain="$1"

    # Check if the domain resolves to an IP address
    if ! host "$domain" >/dev/null 2>&1; then
        echo "$domain $red HTTP Status: 000 (Inactive/Missing A record) $reset"
        return
    fi

    # Proceed with CURL check if the domain resolves
    local status
    status=$(curl -o /dev/null -L -s -w "%{http_code}" "http://$domain")

    if [[ "$status" =~ ^(200|301|302)$ ]]; then
        echo "$domain $green HTTP Status: $status $reset"
    else
        echo "$domain $red HTTP Status: $status $reset"
        alert=1
    fi
}

echo -e "\n$yellow STAGE #3 ----- Testing websites with CURL $reset"

# HTTP check block
if [ "$NO_HTTP" = true ]; then
    echo "Skipping HTTP checks as per --no-http flag."
else
    for domain in $domains; do
        curl_check "$domain"
    done
fi


local_curl_check() {
    local domain="$1"

    # Force CURL to use the account IP instead of DNS
    local status
    status=$(curl -o /dev/null -L -s \
        --resolve "$domain:80:$accountip" \
        -w "%{http_code}" \
        "http://$domain")

    # Evaluate result
    if [[ "$status" =~ ^(200|301|302)$ ]]; then
        echo "$domain (LOCAL) $green HTTP Status: $status $reset"
    else
        echo "$domain (LOCAL) $red HTTP Status: $status $reset"
        alert=1
    fi
}



if [ "$NO_HTTP" = true ]; then
    echo "Skipping LOCAL HTTP checks as per --no-http flag."
else
    echo -e "\n$yellow STAGE #3b ----- Testing LOCAL websites via $accountip $reset"
    for domain in $domains; do
        local_curl_check "$domain"
    done
fi

#-----------------------------------------------------------
# STAGE 4: ADDITIONAL CHECKS
#-----------------------------------------------------------

detailed_email_usage() {
    echo -e "\n${bold}=== Individual email usage =======================${reset}\n"
    uapi --output=json --user="$username" Email list_pops_with_disk 2>/dev/null \
        | jq -r '.result.data[] | [._diskused, .email] | @tsv' \
        | numfmt --to=iec | sort -rh | column -t | head -n 20
}

echo "MAILBOXES is set to: $MAILBOXES"

if [ "$MAILBOXES" = true ]; then
    detailed_email_usage
fi

#-----------------------------------------------------------
# STAGE 3: ADDITIONAL CHECKS
#-----------------------------------------------------------