#!/bin/bash

# 超级网站探测脚本
# 支持并发探测、灵活频率配置（60秒到1秒，甚至1秒内1-100次并发）

# 默认配置
DEFAULT_URL="https://zrp233.top"
DEFAULT_INITIAL_FREQ="5s"      # 支持格式: 5s, 0.5s, 100ms, 1s:10 (1秒内10次并发)
DEFAULT_SWITCH_FREQ="10s"
DEFAULT_SWITCH_TIME=3600
DEFAULT_MODE="normal"
DEFAULT_MAX_CONCURRENT=10

# 全局变量
PROBE_URL="${1:-$DEFAULT_URL}"
INITIAL_FREQ="${2:-$DEFAULT_INITIAL_FREQ}"
SWITCH_FREQ="${3:-$DEFAULT_SWITCH_FREQ}"
SWITCH_TIME="${4:-$DEFAULT_SWITCH_TIME}"
PROBE_MODE="${5:-$DEFAULT_MODE}"
CURRENT_FREQ=$INITIAL_FREQ
LOG_FILE=""
STATS_FILE=""
START_TIME=$(date +%s)
PROBE_COUNT=0
SUCCESS_COUNT=0
ERROR_COUNT=0
LAST_STATUS=""
CONCURRENT_PIDS=()

# User-Agent 池
USER_AGENTS=(
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0"
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.0"
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edge/91.0.864.59"
    "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"
    "Mozilla/5.0 (Android 11; Mobile; rv:89.0) Gecko/89.0 Firefox/89.0"
)

# 解析频率配置
parse_frequency() {
    local freq_str=$1
    
    # 检查是否是并发格式 (例如: 1s:10 表示1秒内10次)
    if [[ "$freq_str" =~ ^([0-9]*\.?[0-9]+)(s|ms):([0-9]+)$ ]]; then
        local time_value="${BASH_REMATCH[1]}"
        local time_unit="${BASH_REMATCH[2]}"
        local concurrent_count="${BASH_REMATCH[3]}"
        
        if [ "$time_unit" = "ms" ]; then
            time_value=$(echo "scale=3; $time_value / 1000" | bc -l)
        fi
        
        echo "concurrent:${time_value}:${concurrent_count}"
    # 检查是否是毫秒格式
    elif [[ "$freq_str" =~ ^([0-9]*\.?[0-9]+)ms$ ]]; then
        local ms_value="${BASH_REMATCH[1]}"
        local sec_value=$(echo "scale=3; $ms_value / 1000" | bc -l)
        echo "interval:${sec_value}"
    # 检查是否是秒格式
    elif [[ "$freq_str" =~ ^([0-9]*\.?[0-9]+)s?$ ]]; then
        local sec_value="${BASH_REMATCH[1]}"
        echo "interval:${sec_value}"
    else
        echo "interval:5"  # 默认5秒
    fi
}

# 生成文件名
generate_filenames() {
    local timestamp=$(date +"%Y%m%d_%H%M%S")
    local random_num=$(printf "%04d" $((RANDOM % 10000)))
    LOG_FILE="super_probe_${timestamp}_${random_num}.log"
    STATS_FILE="super_stats_${timestamp}_${random_num}.log"
    echo "日志文件: $LOG_FILE"
    echo "统计文件: $STATS_FILE"
}

# 获取随机User-Agent
get_random_user_agent() {
    local index=$((RANDOM % ${#USER_AGENTS[@]}))
    echo "${USER_AGENTS[$index]}"
}

# 记录日志（线程安全）
log_result() {
    local status_code=$1
    local response_time=$2
    local user_agent_index=$3
    local is_system_event=${4:-false}
    local thread_id=${5:-0}
    local current_time=$(date +"%Y/%m/%d/%H/%M/%S.%3N")
    local log_entry="[$current_time] 状态码: $status_code | 响应时间: ${response_time}ms | 探测频率: $CURRENT_FREQ | UA: $user_agent_index | 模式: $PROBE_MODE | 线程: $thread_id"
    
    # 使用文件锁确保日志写入的原子性
    (
        flock -x 200
        echo "$log_entry" | tee -a "$LOG_FILE"
    ) 200>>"$LOG_FILE.lock"
    
    # 更新统计 - 只有真实的探测结果才计入统计
    if [ "$is_system_event" = "false" ]; then
        (
            flock -x 201
            PROBE_COUNT=$((PROBE_COUNT + 1))
            if [ "$status_code" = "200" ]; then
                SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
            else
                ERROR_COUNT=$((ERROR_COUNT + 1))
            fi
            LAST_STATUS="$status_code"
            # 更新统计文件中的计数器
            echo "$PROBE_COUNT" > /tmp/probe_count.tmp
            echo "$SUCCESS_COUNT" > /tmp/success_count.tmp
            echo "$ERROR_COUNT" > /tmp/error_count.tmp
            echo "$LAST_STATUS" > /tmp/last_status.tmp
        ) 201>>/tmp/probe_stats.lock
    fi
}

# 单次探测函数
single_probe() {
    local thread_id=$1
    local user_agent=$(get_random_user_agent)
    local ua_index=0
    for i in "${!USER_AGENTS[@]}"; do
        if [ "${USER_AGENTS[$i]}" = "$user_agent" ]; then
            ua_index=$i
            break
        fi
    done
    
    local timeout_connect=10
    local timeout_max=30
    
    case "$PROBE_MODE" in
        "fast")
            timeout_connect=5
            timeout_max=15
            ;;
        "stealth")
            timeout_connect=15
            timeout_max=45
            # 隐蔽模式添加随机延迟
            sleep $(echo "scale=2; $RANDOM % 200 / 100" | bc -l)
            ;;
    esac
    
    local start_time=$(date +%s%3N)
    local response=$(curl -s -o /dev/null -w "%{http_code}" \
        -H "User-Agent: $user_agent" \
        -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" \
        -H "Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7" \
        -H "Accept-Encoding: gzip, deflate, br" \
        -H "Connection: keep-alive" \
        -H "Upgrade-Insecure-Requests: 1" \
        -H "Cache-Control: max-age=0" \
        --connect-timeout $timeout_connect \
        --max-time $timeout_max \
        -L "$PROBE_URL" 2>/dev/null)
    local end_time=$(date +%s%3N)
    local response_time=$((end_time - start_time))
    
    if [ -z "$response" ]; then
        response="000"
        response_time=0
    fi
    
    log_result "$response" "$response_time" "$ua_index" "false" "$thread_id"
}

# 并发探测函数
concurrent_probe() {
    local interval=$1
    local count=$2
    
    echo "$(date +"%Y/%m/%d/%H/%M/%S") - 启动并发探测: ${count}次 / ${interval}秒"
    
    # 启动并发探测
    for ((i=1; i<=count; i++)); do
        single_probe $i &
        CONCURRENT_PIDS+=($!)
        
        # 在间隔内均匀分布请求
        if [ $i -lt $count ]; then
            local sub_interval=$(echo "scale=3; $interval / $count" | bc -l)
            sleep $sub_interval
        fi
    done
    
    # 等待所有并发任务完成
    for pid in "${CONCURRENT_PIDS[@]}"; do
        wait $pid 2>/dev/null
    done
    
    # 清空PID数组
    CONCURRENT_PIDS=()
    
    # 如果还有剩余时间，等待
    local remaining_time=$(echo "scale=3; $interval - ($interval / $count * ($count - 1))" | bc -l)
    if (( $(echo "$remaining_time > 0" | bc -l) )); then
        sleep $remaining_time
    fi
}

# 执行探测
execute_probe() {
    local freq_config=$(parse_frequency "$CURRENT_FREQ")
    
    if [[ "$freq_config" =~ ^concurrent:([0-9]*\.?[0-9]+):([0-9]+)$ ]]; then
        local interval="${BASH_REMATCH[1]}"
        local count="${BASH_REMATCH[2]}"
        concurrent_probe "$interval" "$count"
    else
        # 普通间隔探测
        local interval=$(echo "$freq_config" | cut -d: -f2)
        single_probe 1
        sleep "$interval"
    fi
}

# 检查频率切换
check_frequency_switch() {
    local current_time=$(date +%s)
    local elapsed_time=$((current_time - START_TIME))
    
    if [ $elapsed_time -ge $SWITCH_TIME ] && [ "$CURRENT_FREQ" = "$INITIAL_FREQ" ]; then
        CURRENT_FREQ=$SWITCH_FREQ
        echo "$(date +"%Y/%m/%d/%H/%M/%S") - 切换探测频率到 $CURRENT_FREQ"
        log_result "FREQ_SWITCH_TO_${CURRENT_FREQ}" "0" "0" "true" "0"
    fi
}

# 更新统计信息
update_stats() {
    # 从临时文件读取最新统计
    if [ -f /tmp/probe_count.tmp ]; then
        PROBE_COUNT=$(cat /tmp/probe_count.tmp 2>/dev/null || echo "0")
        SUCCESS_COUNT=$(cat /tmp/success_count.tmp 2>/dev/null || echo "0")
        ERROR_COUNT=$(cat /tmp/error_count.tmp 2>/dev/null || echo "0")
        LAST_STATUS=$(cat /tmp/last_status.tmp 2>/dev/null || echo "")
    fi
    
    local current_time=$(date +"%Y/%m/%d/%H/%M/%S")
    local success_rate=0
    if [ $PROBE_COUNT -gt 0 ]; then
        success_rate=$((SUCCESS_COUNT * 100 / PROBE_COUNT))
    fi
    
    cat > "$STATS_FILE" << EOF
========================================
超级网站探测统计信息
========================================
更新时间: $current_time
目标URL: $PROBE_URL
探测模式: $PROBE_MODE
当前频率: $CURRENT_FREQ
========================================
总探测次数: $PROBE_COUNT
成功次数: $SUCCESS_COUNT
失败次数: $ERROR_COUNT
成功率: ${success_rate}%
最后状态码: $LAST_STATUS
========================================
运行时间: $(($(date +%s) - START_TIME))秒
========================================
EOF
}

# 显示实时统计
show_stats() {
    update_stats
    local success_rate=0
    if [ $PROBE_COUNT -gt 0 ]; then
        success_rate=$((SUCCESS_COUNT * 100 / PROBE_COUNT))
    fi
    
    echo "统计: 总计${PROBE_COUNT} | 成功${SUCCESS_COUNT} | 失败${ERROR_COUNT} | 成功率${success_rate}% | 最后状态:${LAST_STATUS}"
}

# 显示使用说明
show_usage() {
    echo "超级网站探测脚本 - 支持并发和灵活频率配置"
    echo "使用方法: $0 [URL] [初始频率] [切换频率] [切换时间] [模式]"
    echo ""
    echo "参数说明:"
    echo "  URL        - 要探测的网站URL (默认: $DEFAULT_URL)"
    echo "  初始频率   - 初始探测频率 (默认: $DEFAULT_INITIAL_FREQ)"
    echo "  切换频率   - 切换后探测频率 (默认: $DEFAULT_SWITCH_FREQ)"
    echo "  切换时间   - 多少秒后切换频率 (默认: $DEFAULT_SWITCH_TIME)"
    echo "  模式       - 探测模式: normal/fast/stealth (默认: $DEFAULT_MODE)"
    echo ""
    echo "频率格式说明:"
    echo "  60s        - 每60秒探测1次"
    echo "  5s         - 每5秒探测1次"
    echo "  1s         - 每1秒探测1次"
    echo "  500ms      - 每500毫秒探测1次"
    echo "  1s:10      - 每1秒内并发探测10次"
    echo "  1s:50      - 每1秒内并发探测50次"
    echo "  1s:100     - 每1秒内并发探测100次"
    echo "  0.5s:20    - 每0.5秒内并发探测20次"
    echo ""
    echo "探测模式说明:"
    echo "  normal   - 普通模式，标准请求头和超时设置"
    echo "  fast     - 快速模式，较短的超时时间"
    echo "  stealth  - 隐蔽模式，更多请求头和随机延迟"
    echo ""
    echo "示例:"
    echo "  $0                                           # 默认参数"
    echo "  $0 https://zrp233.top 1s 5s 1800 stealth   # 1秒频率，隐蔽模式"
    echo "  $0 https://zrp233.top 1s:50 1s:10 3600     # 高并发探测"
    echo "  $0 https://zrp233.top 500ms 2s 600 fast    # 毫秒级探测"
    echo ""
    echo "按 Ctrl+C 停止探测"
}

# 信号处理
cleanup() {
    echo ""
    echo "$(date +"%Y/%m/%d/%H/%M/%S") - 正在停止探测..."
    
    # 终止所有并发进程
    for pid in "${CONCURRENT_PIDS[@]}"; do
        kill $pid 2>/dev/null
    done
    
    # 等待进程结束
    sleep 1
    
    log_result "PROBE_STOPPED" "0" "0" "true" "0"
    update_stats
    echo "日志已保存到: $LOG_FILE"
    echo "统计已保存到: $STATS_FILE"
    show_stats
    
    # 清理临时文件
    rm -f /tmp/probe_count.tmp /tmp/success_count.tmp /tmp/error_count.tmp /tmp/last_status.tmp /tmp/probe_stats.lock "$LOG_FILE.lock" 2>/dev/null
    
    exit 0
}

# 主函数
main() {
    # 检查依赖
    if ! command -v bc &> /dev/null; then
        echo "错误: 需要安装 bc 计算器"
        echo "Ubuntu/Debian: sudo apt-get install bc"
        echo "CentOS/RHEL: sudo yum install bc"
        exit 1
    fi
    
    # 检查参数
    if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
        show_usage
        exit 0
    fi
    
    # 设置信号处理
    trap cleanup SIGINT SIGTERM
    
    # 初始化统计文件
    echo "0" > /tmp/probe_count.tmp
    echo "0" > /tmp/success_count.tmp
    echo "0" > /tmp/error_count.tmp
    echo "" > /tmp/last_status.tmp
    
    # 生成文件名
    generate_filenames
    
    # 显示配置信息
    echo "=========================================="
    echo "超级网站探测脚本启动"
    echo "=========================================="
    echo "目标URL: $PROBE_URL"
    echo "探测模式: $PROBE_MODE"
    echo "初始探测频率: $INITIAL_FREQ"
    echo "切换探测频率: $SWITCH_FREQ"
    echo "切换时间: ${SWITCH_TIME}秒"
    echo "日志文件: $LOG_FILE"
    echo "统计文件: $STATS_FILE"
    echo "启动时间: $(date +"%Y/%m/%d/%H/%M/%S")"
    echo "User-Agent池: ${#USER_AGENTS[@]} 个"
    
    # 解析并显示频率配置
    local initial_config=$(parse_frequency "$INITIAL_FREQ")
    local switch_config=$(parse_frequency "$SWITCH_FREQ")
    
    if [[ "$initial_config" =~ ^concurrent ]]; then
        echo "初始模式: 并发探测"
    else
        echo "初始模式: 间隔探测"
    fi
    
    echo "=========================================="
    
    # 记录启动日志
    log_result "PROBE_STARTED" "0" "0" "true" "0"
    
    # 主探测循环
    while true; do
        # 检查是否需要切换频率
        check_frequency_switch
        
        # 执行探测
        execute_probe
        
        # 显示实时统计（每50次探测显示一次）
        if [ $((PROBE_COUNT % 50)) -eq 0 ] && [ $PROBE_COUNT -gt 0 ]; then
            show_stats
        fi
    done
}

# 运行主函数
main "$@"
