if ! command -v "$dep" &> /dev/null; then error_exit "依赖 $dep 安装失败,请手动安装" fi }
# 检查并安装依赖 check_deps() { local missing=0 local deps=()
if ! command -v curl &> /dev/null; then echo"缺少依赖:curl" >&2 deps+=("curl") missing=1 fi if ! command -v jq &> /dev/null; then echo"缺少依赖:jq" >&2 deps+=("jq") missing=1 fi # 检查IPv6 ping工具 local ping6_available=0 ifcommand -v ping6 &> /dev/null; then ping6_available=1 elif ping -6 -c 1 -W 1 ::1 &> /dev/null; then ping6_available=1 fi if [ $ping6_available -eq 0 ]; then echo"缺少依赖:IPv6 ping工具" >&2 # 根据不同系统添加对应的iputils包 ifcommand -v apt-get &> /dev/null; then deps+=("iputils-ping") elifcommand -v yum &> /dev/null || command -v dnf &> /dev/null; then deps+=("iputils") elifcommand -v pacman &> /dev/null; then deps+=("iputils") fi missing=1 fi
if [ $missing -eq 1 ]; then log_info "开始安装缺失的依赖..." for dep in"${deps[@]}"; do install_dependency "$dep" done log_info "所有依赖安装完成" fi }
# 验证响应是否为JSON(修复HTML响应问题) is_valid_json() { local input="$1" # 检查是否包含HTML标签(常见错误情况) ifecho"$input" | grep -qi '<html>\|<body>\|<doctype'; then return 1 fi # 使用jq验证JSON格式 echo"$input" | jq . >/dev/null 2>&1 return $? }
# IPv6网络连通性验证 verify_ipv6_connectivity() { log_info "正在验证IPv6网络连通性..." local ping_success=0 local ping_cmd="ping6" if ! command -v ping6 &> /dev/null; then ping_cmd="ping -6" fi
for node in"${IPV6_PING_NODES[@]}"; do log_info "正在ping IPv6节点:$node..." if$ping_cmd -c 1 -W 3 "$node" &> /dev/null; then log_info "✅ IPv6节点[$node] ping通" ping_success=1 break fi done
if [ "$ping_success" -eq 0 ]; then error_exit "❌ 所有IPv6节点均无法连通,取消IPv6操作" fi }
# 获取IPv6(带错误处理) IPV6=$(curl -6 -s --max-time 5 --retry 2 api64.ipify.org) if [ -z "$IPV6" ]; then IPV6=$(curl -6 -s --max-time 5 --retry 2 ipv6.ip.sb) fi
# 验证并输出结果 if [ -n "$IPV6" ]; then verify_ipv6_connectivity log_info "✅ 检测到IPv6:$IPV6" fi if [ -n "$IPV4" ]; then log_info "✅ 检测到IPv4:$IPV4" fi if [ -z "$IPV4" ] && [ -z "$IPV6" ]; then error_exit "❌ 未检测到任何公网IP" fi }
# 调用Cloudflare API(增强版) call_api() { local method="$1" local endpoint="$2" local data="${3:-}"
http_code=$(echo"$response" | tail -n1) response_body=$(echo"$response" | head -n -1)
# 检查HTTP状态码 if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then # 检查是否为有效JSON if is_valid_json "$response_body"; then # 检查API成功状态 ifecho"$response_body" | jq -e '.success' > /dev/null; then echo"$response_body" return 0 fi fi fi
# 重试提示 if [ $attempt -lt 3 ]; then log_warn "API请求尝试$attempt失败,正在重试..." sleep 2 fi done
# -------------------------- 主逻辑函数 -------------------------- manage_ipv4() { local has_a_record=0 local a_record_id="" local a_old_ip=""
# 检查现有A记录 for ((i=0; i<${#EXISTING_TYPES[@]}; i++)); do if [ "${EXISTING_TYPES[$i]}" = "A" ]; then has_a_record=1 a_record_id="${EXISTING_IDS[$i]}" a_old_ip="${EXISTING_CONTENTS[$i]}" break fi done
# 处理A记录 if [ "$has_a_record" -eq 1 ]; then if [ "$a_old_ip" = "$IPV4" ]; then log_info "ℹ️ A记录已为最新:$IPV4" else update_record "$a_record_id""A""$a_old_ip""$IPV4" fi else add_record "A""$IPV4" fi
# 清理残留IPv6记录 if [ -z "$IPV6" ] && [ "$OPERATION" -ne 6 ]; then for ((i=0; i<${#EXISTING_TYPES[@]}; i++)); do if [ "${EXISTING_TYPES[$i]}" = "AAAA" ]; then delete_record "${EXISTING_IDS[$i]}""AAAA""${EXISTING_CONTENTS[$i]}" fi done fi }
local has_aaaa_record=0 local aaaa_record_id="" local aaaa_old_ip=""
# 检查现有AAAA记录 for ((i=0; i<${#EXISTING_TYPES[@]}; i++)); do if [ "${EXISTING_TYPES[$i]}" = "AAAA" ]; then has_aaaa_record=1 aaaa_record_id="${EXISTING_IDS[$i]}" aaaa_old_ip="${EXISTING_CONTENTS[$i]}" break fi done
# 处理AAAA记录 if [ "$has_aaaa_record" -eq 1 ]; then if [ "$aaaa_old_ip" = "$IPV6" ]; then log_info "ℹ️ AAAA记录已为最新:$IPV6" else update_record "$aaaa_record_id""AAAA""$aaaa_old_ip""$IPV6" fi else add_record "AAAA""$IPV6" fi
# 清理残留IPv4记录 if [ -z "$IPV4" ] && [ "$OPERATION" -ne 4 ]; then for ((i=0; i<${#EXISTING_TYPES[@]}; i++)); do if [ "${EXISTING_TYPES[$i]}" = "A" ]; then delete_record "${EXISTING_IDS[$i]}""A""${EXISTING_CONTENTS[$i]}" fi done fi }
delete_all_records() { if [ ${#EXISTING_TYPES[@]} -eq 0 ]; then log_info "ℹ️ 没有记录可删除" return fi
log_info "正在删除所有记录(共${#EXISTING_TYPES[@]}条)..." for ((i=0; i<${#EXISTING_TYPES[@]}; i++)); do delete_record "${EXISTING_IDS[$i]}""${EXISTING_TYPES[$i]}""${EXISTING_CONTENTS[$i]}" done }
# -------------------------- 主流程 -------------------------- main() { # 参数检查 if [ -z "$RECORD_NAME" ]; then error_exit "请指定域名!使用方法: 自动适配:$0 域名 单独操作:$0 域名 [4/6/1]" fi