#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 遥辉APK报毒处理系统自动化部署脚本 (Python版)
# 作者：消失的阿力【B站&闲鱼同名】
# 优化版本：2025.08.28

import os
import sys
import re
import subprocess
import shutil
import time
import socket
import pwd
import pymysql
import random
from getpass import getpass
import configparser
import logging
from logging.handlers import RotatingFileHandler
import argparse  # 添加argparse用于处理命令行参数

# ==================== 全局定义区 ====================
# 颜色定义
COLOR_RESET = '\033[0m'
COLOR_ERROR = '\033[0;31m'
COLOR_SUCCESS = '\033[0;32m'
COLOR_WARNING = '\033[1;33m'
COLOR_INFO = '\033[1;34m'
COLOR_STEP = '\033[1;36m'
COLOR_INPUT = '\033[1;35m'
COLOR_HEADER = '\033[1;37m'
COLOR_DIVIDER = '\033[1;34m'

# 默认路径定义（可通过命令行参数覆盖）
DEFAULT_TARGET_DIR = "/www/wwwroot/AliPack/DPB"

# 解析命令行参数
def parse_arguments():
    parser = argparse.ArgumentParser(description='遥辉APK报毒处理系统自动化部署脚本')
    parser.add_argument('--target-dir', type=str, default=DEFAULT_TARGET_DIR,
                       help=f'指定部署目录路径，默认为: {DEFAULT_TARGET_DIR}')
    return parser.parse_args()

# 获取命令行参数
args = parse_arguments()
TARGET_DIR = args.target_dir

# 其他路径定义（基于动态传入的TARGET_DIR）
CONFIG_FILE = os.path.join(TARGET_DIR, "config", "application.yml")
SRC_DIR = os.path.join(TARGET_DIR, "rt", "dxtool")
DEST_DIR = os.path.join(TARGET_DIR, "jiagu")
DEPLOYMENT_MARKER = os.path.join(TARGET_DIR, ".xali_deployed")
LOG_FILE = os.path.join(TARGET_DIR, "遥辉正版.md")
PID_FILE = os.path.join(TARGET_DIR, "AliPack.jar.pid")
SQL_FILE = os.path.join(TARGET_DIR, "AliDPB.sql")

# 数据库配置
DB_NAME = "apkdpb"
DB_USER = "apkdpb"
DB_PASS = "alidpb"

# 服务配置
DEFAULT_PORT_RANGE = (5000, 9999)
MAX_PORT_ATTEMPTS = 10
INIT_WAIT_TIME = 30

# 清理配置
CLEAN_DIRS = [
    os.path.join(TARGET_DIR, "storage", "1", "apk"),
    os.path.join(TARGET_DIR, "storage", "1", "ios"),
    os.path.join(TARGET_DIR, "storage", "1", "mixed"),
    os.path.join(TARGET_DIR, "storage", "1", "certificate")
]
KEEP_DAYS = 3

# 状态变量
server_ip = ""
rand_port = 0
app_pid = 0

# ==================== 日志配置 ====================
def setup_logging():
    """配置日志系统"""
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    
    # 控制台日志
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    
    # 文件日志
    file_handler = RotatingFileHandler(
        LOG_FILE, 
        maxBytes=10*1024*1024, 
        backupCount=5,
        encoding='utf-8'
    )
    file_handler.setLevel(logging.INFO)
    
    # 日志格式
    formatter = logging.Formatter(
        '%(asctime)s [%(levelname)s] %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S'
    )
    console_handler.setFormatter(formatter)
    file_handler.setFormatter(formatter)
    
    logger.addHandler(console_handler)
    logger.addHandler(file_handler)
    
    # 记录脚本开始
    logging.info("========== 脚本开始运行 ==========")
    logging.info(f"Python 版本: {sys.version}")
    logging.info(f"当前用户: {os.getlogin()}")
    logging.info(f"工作目录: {os.getcwd()}")
    logging.info(f"目标部署目录: {TARGET_DIR}")
    logging.info("=================================")

# ==================== 辅助函数 ====================
def log_message(message, status="INFO"):
    """记录日志消息"""
    clean_message = re.sub(r'\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]', '', message)
    logging.log(
        logging.INFO if status == "INFO" else 
        logging.WARNING if status == "WARNING" else 
        logging.ERROR if status == "ERROR" else 
        logging.INFO,
        clean_message
    )

def show_step(step_num, step_desc):
    """显示步骤标题"""
    print(f"\n{COLOR_STEP}➤ 步骤{step_num}/10：{step_desc}{COLOR_RESET}")
    log_message(f"步骤{step_num}/10：{step_desc}", "INFO")
    # 步骤间缓冲时间
    time.sleep(2)

def show_divider():
    """显示分隔线"""
    print(f"{COLOR_DIVIDER}========================================{COLOR_RESET}")
    # 分隔线后缓冲时间
    time.sleep(1)

def run_command(cmd, capture_output=False, check=False):
    """运行系统命令并处理输出"""
    try:
        # 使用universal_newlines替代text以兼容Python 3.6
        result = subprocess.run(
            cmd, 
            shell=True, 
            check=check,
            stdout=subprocess.PIPE if capture_output else None,
            stderr=subprocess.PIPE if capture_output else None,
            universal_newlines=True
        )
        # 命令执行后缓冲时间
        time.sleep(1)
        if capture_output:
            return result.stdout.strip(), result.stderr.strip(), result.returncode
        return result.returncode == 0
    except subprocess.CalledProcessError as e:
        log_message(f"命令执行失败: {cmd} | 错误: {str(e)}", "ERROR")
        return None, str(e), e.returncode
    except Exception as e:
        log_message(f"命令执行异常: {cmd} | 错误: {str(e)}", "ERROR")
        return None, str(e), -1

def is_first_deployment():
    """检查是否首次部署"""
    return not os.path.exists(DEPLOYMENT_MARKER)

def mark_deployment_complete():
    """标记部署完成"""
    try:
        with open(DEPLOYMENT_MARKER, 'w') as f:
            f.write(f"部署完成时间: {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
        print(f"{COLOR_SUCCESS}✅ 系统已标记为已部署状态{COLOR_RESET}")
        log_message("系统已标记为已部署状态", "SUCCESS")
        # 操作完成缓冲时间
        time.sleep(1)
        return True
    except Exception as e:
        print(f"{COLOR_ERROR}❌ 标记部署状态失败: {str(e)}{COLOR_RESET}")
        log_message(f"标记部署状态失败: {str(e)}", "ERROR")
        return False


# ==================== 数据库操作 ====================
def change_mysql_root_password():
    """重置MySQL root密码"""
    show_step(1, "重置MySQL root密码")
    show_divider()
    
    # 获取新密码
    while True:
        new_password = getpass(f"{COLOR_INPUT}请输入新的MySQL root密码: {COLOR_RESET}")
        confirm_password = getpass(f"{COLOR_INPUT}请确认新密码: {COLOR_RESET}")
        
        if new_password != confirm_password:
            print(f"{COLOR_ERROR}❌ 错误：两次输入的密码不匹配！{COLOR_RESET}")
            log_message("错误：两次输入的MySQL root密码不匹配", "ERROR")
            # 错误提示后缓冲时间
            time.sleep(1)
        else:
            break
    
    print(f"{COLOR_INFO}🔄 正在停止MySQL服务...{COLOR_RESET}")
    log_message("正在停止MySQL服务", "INFO")
    
    # 尝试多种停止MySQL的方式
    stop_commands = [
        "/etc/init.d/mysqld stop",
        "systemctl stop mysqld",
        "service mysqld stop"
    ]
    
    stopped = False
    for cmd in stop_commands:
        if run_command(cmd):
            print(f"{COLOR_SUCCESS}✅ MySQL服务已停止{COLOR_RESET}")
            log_message("MySQL服务已停止", "SUCCESS")
            stopped = True
            break
    
    if not stopped:
        print(f"{COLOR_WARNING}⚠️ 无法停止MySQL，尝试强制停止{COLOR_RESET}")
        log_message("无法停止MySQL，尝试强制停止", "WARNING")
        # 使用更可靠的停止方法
        run_command("killall -9 mysqld_safe")
        run_command("killall -9 mysqld")
    
    # 确保MySQL完全停止
    time.sleep(3)
    
    print(f"{COLOR_INFO}🔄 以跳过权限模式启动MySQL...{COLOR_RESET}")
    log_message("以跳过权限模式启动MySQL", "INFO")
    
    # 启动MySQL并跳过权限检查 - 添加日志输出以便调试
    run_command("nohup mysqld_safe --skip-grant-tables > /tmp/mysql_safe.log 2>&1 &")
    time.sleep(8)  # 增加等待时间确保MySQL完全启动
    
    # 检查MySQL进程是否运行
    mysql_running = run_command("pgrep mysqld", capture_output=True)[0] is not None
    if not mysql_running:
        print(f"{COLOR_ERROR}❌ MySQL未能以跳过权限模式启动{COLOR_RESET}")
        log_message("MySQL未能以跳过权限模式启动", "ERROR")
        # 显示日志以帮助诊断
        run_command("cat /tmp/mysql_safe.log")
        sys.exit(1)
    
    print(f"{COLOR_INFO}🔄 正在重置root密码...{COLOR_RESET}")
    log_message("正在重置root密码", "INFO")
    
    # 修复SQL命令 - 使用更可靠的密码设置方法
    sql_commands = [
        "USE mysql;",
        f"UPDATE user SET authentication_string=PASSWORD('{new_password}') WHERE User='root';",
        "FLUSH PRIVILEGES;"
    ]
    
    # 构建完整SQL命令
    full_sql = " ".join(sql_commands)
    
    # 执行SQL命令 - 添加重试机制
    sql_success = False
    for attempt in range(1, 4):
        print(f"{COLOR_INFO}➔ 尝试执行SQL命令 (第{attempt}次){COLOR_RESET}")
        sql_cmd = f"mysql -u root -e \"{full_sql}\""
        if run_command(sql_cmd):
            print(f"{COLOR_SUCCESS}✅ 密码重置SQL执行成功{COLOR_RESET}")
            log_message("密码重置SQL执行成功", "SUCCESS")
            sql_success = True
            break
        time.sleep(2)  # 等待后重试
    
    if not sql_success:
        print(f"{COLOR_ERROR}❌ 密码重置失败，请检查MySQL状态{COLOR_RESET}")
        log_message("密码重置失败", "ERROR")
        sys.exit(1)
    
    print(f"{COLOR_INFO}🔄 停止跳过权限模式的MySQL...{COLOR_RESET}")
    log_message("停止跳过权限模式的MySQL", "INFO")
    run_command("pkill -9 mysqld_safe")
    run_command("pkill -9 mysqld")
    time.sleep(3)  # 确保MySQL完全停止
    
    print(f"{COLOR_INFO}🔄 正常启动MySQL服务...{COLOR_RESET}")
    log_message("正常启动MySQL服务", "INFO")
    
    # 尝试多种启动MySQL的方式 - 添加重试机制
    start_commands = [
        "/etc/init.d/mysqld start",
        "systemctl start mysqld",
        "service mysqld start"
    ]
    
    started = False
    for cmd in start_commands:
        if run_command(cmd):
            print(f"{COLOR_SUCCESS}✅ MySQL服务启动命令执行成功{COLOR_RESET}")
            log_message("MySQL服务启动命令执行成功", "SUCCESS")
            
            # 等待MySQL完全启动
            print(f"{COLOR_INFO}🔄 等待MySQL服务初始化...{COLOR_RESET}")
            for i in range(1, 16):  # 最多等待15秒
                if run_command("pgrep mysqld", capture_output=True)[0] is not None:
                    started = True
                    print(f"{COLOR_SUCCESS}✅ MySQL服务已启动{COLOR_RESET}")
                    log_message("MySQL服务已启动", "SUCCESS")
                    break
                print(f"{COLOR_INFO}➔ 等待中... ({i}/15 秒){COLOR_RESET}")
                time.sleep(1)
            if started:
                break
    
    if not started:
        print(f"{COLOR_ERROR}❌ MySQL启动失败，请手动检查{COLOR_RESET}")
        log_message("MySQL启动失败", "ERROR")
        # 显示MySQL错误日志
        mysql_error_log = "/var/log/mysqld.log"  # 常见错误日志路径
        if os.path.exists(mysql_error_log):
            print(f"{COLOR_ERROR}=== MySQL错误日志 ==={COLOR_RESET}")
            run_command(f"tail -n 20 {mysql_error_log}")
        sys.exit(1)
    
    # 验证新密码 - 添加重试机制
    print(f"{COLOR_INFO}🔄 验证新密码...{COLOR_RESET}")
    for attempt in range(1, 6):
        try:
            connection = pymysql.connect(
                host='localhost',
                user='root',
                password=new_password,
                charset='utf8mb4',
                connect_timeout=3
            )
            connection.close()
            print(f"{COLOR_SUCCESS}✅ 新密码验证成功！{COLOR_RESET}")
            log_message("新密码验证成功", "SUCCESS")
            # 成功验证后缓冲时间
            time.sleep(1)
            return new_password
        except pymysql.Error as e:
            if attempt < 5:
                print(f"{COLOR_WARNING}⚠️ 新密码验证失败，等待重试... ({str(e)}){COLOR_RESET}")
                time.sleep(3)
            else:
                print(f"{COLOR_ERROR}❌ 新密码验证失败: {str(e)}{COLOR_RESET}")
                log_message(f"新密码验证失败: {str(e)}", "ERROR")
                sys.exit(1)
        
def setup_database(mysql_root_password):
    """配置数据库"""
    show_step(3, "配置数据库")
    show_divider()
    
    # 检查数据库是否已存在
    try:
        connection = pymysql.connect(
            host='localhost',
            user='root',
            password=mysql_root_password,
            charset='utf8mb4'
        )
        
        with connection.cursor() as cursor:
            cursor.execute(f"SHOW DATABASES LIKE '{DB_NAME}'")
            result = cursor.fetchone()
            
            if result:
                print(f"{COLOR_SUCCESS}✅ 检测到数据库 '{DB_NAME}' 已存在，跳过数据库配置{COLOR_RESET}")
                log_message(f"检测到数据库 '{DB_NAME}' 已存在，跳过数据库配置", "INFO")
                # 跳过操作后缓冲时间
                time.sleep(1)
                return True
            
            # 创建数据库
            cursor.execute(f"CREATE DATABASE `{DB_NAME}` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci")
            
            # 创建用户
            cursor.execute(f"CREATE USER '{DB_USER}'@'localhost' IDENTIFIED BY '{DB_PASS}'")
            
            # 授权
            cursor.execute(f"GRANT ALL PRIVILEGES ON `{DB_NAME}`.* TO '{DB_USER}'@'localhost'")
            cursor.execute("FLUSH PRIVILEGES")
            
            print(f"{COLOR_SUCCESS}✅ 数据库和用户创建成功！{COLOR_RESET}")
            log_message("数据库和用户创建成功", "SUCCESS")
            # 成功操作后缓冲时间
            time.sleep(1)
        
        connection.close()
    except pymysql.Error as e:
        print(f"{COLOR_ERROR}❌ 数据库配置失败: {str(e)}{COLOR_RESET}")
        log_message(f"数据库配置失败: {str(e)}", "ERROR")
        return False
    
    # 导入SQL文件
    if not os.path.exists(SQL_FILE):
        print(f"{COLOR_ERROR}❌ 错误：未找到SQL导入文件 {SQL_FILE}{COLOR_RESET}")
        log_message(f"错误：未找到SQL导入文件 {SQL_FILE}", "ERROR")
        return False
    
    print(f"{COLOR_INFO}🔄 正在导入数据库结构...{COLOR_RESET}")
    log_message("正在导入数据库结构...", "INFO")
    
    try:
        connection = pymysql.connect(
            host='localhost',
            user='root',
            password=mysql_root_password,
            database=DB_NAME,
            charset='utf8mb4'
        )
        
        # 读取SQL文件内容
        with open(SQL_FILE, 'r', encoding='utf-8') as sql_file:
            sql_content = sql_file.read()
        
        # 分割SQL语句
        sql_commands = [cmd.strip() for cmd in sql_content.split(';') if cmd.strip()]
        
        with connection.cursor() as cursor:
            for command in sql_commands:
                if command:  # 确保不是空命令
                    cursor.execute(command)
        
        connection.commit()
        connection.close()
        
        print(f"{COLOR_SUCCESS}✅ 数据库导入成功！{COLOR_RESET}")
        log_message("数据库导入成功", "SUCCESS")
        # 成功操作后缓冲时间
        time.sleep(1)
        return True
    except pymysql.Error as e:
        print(f"{COLOR_ERROR}❌ 数据库导入失败: {str(e)}{COLOR_RESET}")
        log_message(f"数据库导入失败: {str(e)}", "ERROR")
        return False
    except Exception as e:
        print(f"{COLOR_ERROR}❌ SQL文件处理失败: {str(e)}{COLOR_RESET}")
        log_message(f"SQL文件处理失败: {str(e)}", "ERROR")
        return False
        
# ==================== Java环境管理 ====================
def install_java_environment():
    """安装和配置Java环境"""
    show_step(2, "安装和配置Java环境")
    show_divider()
    
    # 检查是否已安装完整JDK (兼容Python 3.6)
    java_exists = run_command("command -v java", capture_output=True)[0] is not None
    javac_exists = run_command("command -v javac", capture_output=True)[0] is not None
    
    if not java_exists or not javac_exists:
        print(f"{COLOR_INFO}🔄 正在安装完整Java开发环境(JDK)...{COLOR_RESET}")
        log_message("正在安装完整Java开发环境(JDK)...", "INFO")
        
        # 安装JDK
        if run_command("yum -y install java-1.8.0-openjdk-devel"):
            print(f"{COLOR_SUCCESS}✅ JDK环境安装成功！{COLOR_RESET}")
            log_message("JDK环境安装成功", "SUCCESS")
            # 成功安装后缓冲时间
            time.sleep(1)
        else:
            print(f"{COLOR_ERROR}❌ JDK安装失败！请检查yum配置{COLOR_RESET}")
            log_message("JDK安装失败", "ERROR")
            sys.exit(1)
    else:
        print(f"{COLOR_INFO}ℹ️ 检测到已安装完整JDK环境，跳过安装{COLOR_RESET}")
        log_message("检测到已安装完整JDK环境，跳过安装", "INFO")
        # 跳过操作后缓冲时间
        time.sleep(1)
    
    # 配置Java环境变量
    print(f"{COLOR_INFO}🔄 正在配置Java环境...{COLOR_RESET}")
    log_message("正在配置Java环境...", "INFO")
    
    # 查找JDK路径
    jdk_path = ""
    possible_paths = [
        "/usr/lib/jvm/java-1.8.0-openjdk",
        "/usr/lib/jvm/java-1.8.0",
        "/usr/lib/jvm/jre-1.8.0",
        "/usr/lib/jvm/java-8-openjdk-amd64"
    ]
    
    # 通过javac查找路径
    javac_path, _, _ = run_command("readlink -f $(command -v javac)", capture_output=True)
    if javac_path:
        jdk_dir = os.path.dirname(os.path.dirname(javac_path))
        if os.path.isdir(jdk_dir):
            possible_paths.insert(0, jdk_dir)
    
    # 尝试可能的路径
    for path in possible_paths:
        if os.path.isdir(path):
            jdk_path = path
            break
    
    if not jdk_path:
        # 尝试通过环境变量查找
        java_home = run_command("echo $JAVA_HOME", capture_output=True)[0]
        if java_home and os.path.isdir(java_home):
            jdk_path = java_home
        else:
            print(f"{COLOR_ERROR}❌ 错误：无法自动检测JDK安装路径！{COLOR_RESET}")
            log_message("错误：无法自动检测JDK安装路径", "ERROR")
            sys.exit(1)
    
    print(f"{COLOR_SUCCESS}✅ 检测到JDK路径: {jdk_path}{COLOR_RESET}")
    log_message(f"检测到JDK路径: {jdk_path}", "INFO")
    # 检测成功后缓冲时间
    time.sleep(1)
    
    # 创建Java环境配置文件
    print(f"{COLOR_INFO}🔄 创建/更新Java环境配置文件...{COLOR_RESET}")
    java_conf = f"""#!/bin/bash
# Java环境自动配置
export JAVA_HOME="{jdk_path}"
export PATH="$JAVA_HOME/bin:$PATH"
export CLASSPATH=".:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tool.jar"
"""
    
    try:
        with open("/etc/profile.d/java.sh", "w") as f:
            f.write(java_conf)
        os.chmod("/etc/profile.d/java.sh", 0o644)
        run_command("source /etc/profile.d/java.sh")
        log_message("Java环境配置文件已创建: /etc/profile.d/java.sh", "INFO")
    except Exception as e:
        print(f"{COLOR_ERROR}❌ 创建Java环境配置文件失败: {str(e)}{COLOR_RESET}")
        log_message(f"创建Java环境配置文件失败: {str(e)}", "ERROR")
        sys.exit(1)
    
    # 验证Java环境
    print(f"{COLOR_INFO}==================== 验证结果 ===================={COLOR_RESET}")
    print(f"{COLOR_INFO}➔ Java版本信息:{COLOR_RESET}")
    run_command("java -version 2>&1")
    
    print(f"\n{COLOR_INFO}➔ 环境变量检查:{COLOR_RESET}")
    java_home, _, _ = run_command("echo $JAVA_HOME", capture_output=True)
    path, _, _ = run_command("echo $PATH", capture_output=True)
    print(f"JAVA_HOME = {java_home}")
    print(f"PATH = {path}")
    
    # 检查javac是否存在
    javac_exists = run_command("command -v javac", capture_output=True)[0] is not None
    if javac_exists:
        print(f"{COLOR_SUCCESS}✅ JDK完整（检测到javac编译器）{COLOR_RESET}")
        log_message("JDK完整（检测到javac编译器）", "SUCCESS")
    elif os.path.exists(os.path.join(jdk_path, "bin", "javac")):
        print(f"{COLOR_WARNING}⚠️ 警告：javac存在但未加入PATH，已修复{COLOR_RESET}")
        log_message("警告：javac存在但未加入PATH", "WARNING")
        java_conf += f'\nexport PATH="{os.path.join(jdk_path, "bin")}:$PATH"'
        with open("/etc/profile.d/java.sh", "w") as f:
            f.write(java_conf)
        run_command("source /etc/profile.d/java.sh")
    else:
        print(f"{COLOR_ERROR}❌ 错误：未找到javac！JDK可能未正确安装{COLOR_RESET}")
        log_message("错误：未找到javac！JDK可能未正确安装", "ERROR")
        sys.exit(1)
    
    print(f"{COLOR_SUCCESS}\n✅ Java环境配置完成！{COLOR_RESET}")
    log_message("Java环境配置完成", "SUCCESS")
    # 配置完成后缓冲时间
    time.sleep(2)
    show_divider()

# ==================== 文件系统操作 ====================
def set_directory_permissions():
    """设置目录权限"""
    show_step(4, "检查目录权限")
    show_divider()
    
    if not os.path.isdir(TARGET_DIR):
        print(f"{COLOR_ERROR}❌ 错误：目录 {TARGET_DIR} 不存在！{COLOR_RESET}")
        log_message(f"错误：目录 {TARGET_DIR} 不存在！", "ERROR")
        sys.exit(1)
    
    # 获取当前权限和所有者
    stat_info = os.stat(TARGET_DIR)
    current_perm = oct(stat_info.st_mode & 0o777)
    try:
        current_owner = pwd.getpwuid(stat_info.st_uid).pw_name
    except:
        current_owner = "unknown"
    
    if current_perm == '0o777' and current_owner == 'root':
        print(f"{COLOR_INFO}ℹ️ 检测到目录已是777权限且属于root用户，跳过权限设置{COLOR_RESET}")
        log_message("检测到目录已是777权限且属于root用户，跳过权限设置", "INFO")
        show_divider()
        # 跳过操作后缓冲时间
        time.sleep(1)
        return
    
    print(f"{COLOR_INFO}🔄 正在设置DPB目录权限...{COLOR_RESET}")
    log_message("正在设置DPB目录权限...", "INFO")
    
    try:
        # 排除 .user.ini 文件
        run_command(f"find {TARGET_DIR} -path {TARGET_DIR}/.user.ini -prune -o -exec chmod 777 {{}} \\;")
        run_command(f"chown -R root:root {TARGET_DIR}")
        print(f"{COLOR_SUCCESS}✅ 目录权限设置完成！{COLOR_RESET}")
        log_message("目录权限设置完成", "SUCCESS")
        # 权限设置后缓冲时间
        time.sleep(1)
    except Exception as e:
        print(f"{COLOR_ERROR}❌ 目录权限设置失败: {str(e)}{COLOR_RESET}")
        log_message(f"目录权限设置失败: {str(e)}", "ERROR")
    
    show_divider()

def copy_required_files():
    """复制所需文件"""
    show_step(5, "检查所需文件目录")
    show_divider()
    
    validation_dir = os.path.join(DEST_DIR, "dxtool")
    if os.path.isdir(validation_dir):
        print(f"{COLOR_SUCCESS}ℹ️ 检测到dxtool目录已存在，跳过文件夹复制{COLOR_RESET}")
        log_message("检测到dxtool目录已存在，跳过文件夹复制", "INFO")
        # 跳过操作后缓冲时间
        time.sleep(1)
        return
    
    print(f"{COLOR_INFO}🔄 正在复制 {SRC_DIR} 到 {DEST_DIR}...{COLOR_RESET}")
    log_message(f"正在复制 {SRC_DIR} 到 {DEST_DIR}...", "INFO")
    
    if not os.path.isdir(SRC_DIR):
        print(f"{COLOR_ERROR}❌ 错误：源目录不存在！{COLOR_RESET}")
        log_message("错误：源目录不存在！", "ERROR")
        sys.exit(1)
    
    try:
        shutil.copytree(SRC_DIR, validation_dir, dirs_exist_ok=True)
        if os.path.isdir(validation_dir):
            print(f"{COLOR_SUCCESS}✅ 文件夹复制完成并验证成功{COLOR_RESET}")
            log_message("文件夹复制完成并验证成功", "SUCCESS")
            # 复制完成后缓冲时间
            time.sleep(1)
        else:
            print(f"{COLOR_ERROR}❌ 错误：文件夹复制后验证失败{COLOR_RESET}")
            log_message("错误：文件夹复制后验证失败", "ERROR")
            sys.exit(1)
    except Exception as e:
        print(f"{COLOR_ERROR}❌ 错误：文件夹复制失败: {str(e)}{COLOR_RESET}")
        log_message(f"错误：文件夹复制失败: {str(e)}", "ERROR")
        sys.exit(1)
    
    show_divider()

def check_config_file():
    """验证配置文件"""
    show_step(6, "验证配置文件")
    show_divider()
    
    if not os.path.isfile(CONFIG_FILE):
        print(f"{COLOR_ERROR}❌ 错误：配置文件 {CONFIG_FILE} 不存在{COLOR_RESET}")
        log_message(f"错误：配置文件 {CONFIG_FILE} 不存在", "ERROR")
        sys.exit(1)
    
    print(f"{COLOR_SUCCESS}✅ 配置文件验证通过：{CONFIG_FILE}{COLOR_RESET}")
    log_message(f"配置文件验证通过：{CONFIG_FILE}", "SUCCESS")
    # 验证通过后缓冲时间
    time.sleep(1)
    show_divider()

def clean_cache_directories():
    """清理缓存目录"""
    print(f"{COLOR_HEADER}========== 清理缓存目录 =========={COLOR_RESET}")
    print(f"{COLOR_INFO}🔄 正在清理缓存目录...{COLOR_RESET}")
    log_message("正在清理缓存目录...", "INFO")
    
    print(f"{COLOR_INPUT}即将清理以下目录：{COLOR_RESET}")
    for dir_path in CLEAN_DIRS:
        print(f" • {dir_path}")
    print(f"{COLOR_INPUT}保留策略: 保留最近{KEEP_DAYS}天内的文件{COLOR_RESET}")
    log_message(f"保留策略: 保留最近{KEEP_DAYS}天内的文件", "INFO")
    
    confirm = input(f"{COLOR_ERROR}⚠️ 警告：此操作不可恢复！确认清理？[y/N] {COLOR_RESET}").strip().lower()
    if confirm != 'y':
        print(f"{COLOR_WARNING}⚠️ 已取消清理操作{COLOR_RESET}")
        log_message("用户取消清理操作", "INFO")
        return
    
    for target_dir in CLEAN_DIRS:
        if not target_dir or target_dir == "/":
            print(f"{COLOR_ERROR}❌ 危险操作：禁止清理空目录或根目录！{COLOR_RESET}")
            log_message("危险操作：禁止清理空目录或根目录！", "ERROR")
            sys.exit(1)
        
        print(f"{COLOR_INFO}--------------------------------------{COLOR_RESET}")
        print(f"{COLOR_INFO}处理目录: {target_dir}{COLOR_RESET}")
        log_message(f"处理目录: {target_dir}", "INFO")
        
        if not os.path.isdir(target_dir):
            print(f"{COLOR_WARNING}⚠️ 警告：目录不存在，跳过处理{COLOR_RESET}")
            log_message(f"警告：目录 {target_dir} 不存在，跳过处理", "WARNING")
            continue
        
        # 获取清理前大小
        pre_clean_size = run_command(f"du -sh {target_dir} 2>/dev/null | awk '{{print $1}}'", capture_output=True)[0] or "0B"
        
        # 清理旧文件
        run_command(f"find {target_dir} -mindepth 1 -mtime +{KEEP_DAYS} -delete 2>/dev/null")
        
        # 获取清理后大小
        post_clean_size = run_command(f"du -sh {target_dir} 2>/dev/null | awk '{{print $1}}'", capture_output=True)[0] or "0B"
        
        print(f"{COLOR_SUCCESS}✅ 清理完成！{COLOR_RESET}")
        print(f"{COLOR_INFO}释放空间: {pre_clean_size} → {post_clean_size}{COLOR_RESET}")
        log_message(f"清理完成: {target_dir}, 释放空间: {pre_clean_size} → {post_clean_size}", "SUCCESS")
        
        # 计算剩余项目数
        remaining_count = run_command(f"find {target_dir} -mindepth 1 2>/dev/null | wc -l", capture_output=True)[0] or "0"
        print(f"{COLOR_INFO}剩余项目: {remaining_count} 个{COLOR_RESET}")
        log_message(f"剩余项目: {remaining_count} 个", "INFO")
        # 每个目录清理后缓冲时间
        time.sleep(1)
    
    print(f"{COLOR_SUCCESS}✅ 所有目录清理完成！{COLOR_RESET}")
    log_message("所有目录清理完成", "SUCCESS")
    show_divider()

# ==================== 服务器配置 ====================
def get_server_ip():
    """获取服务器IP地址"""
    try:
        # 尝试通过公网API获取
        try:
            import requests
            ip = requests.get('https://icanhazip.com', timeout=5).text
            if ip:
                return ip
        except:
            pass
        
        # 通过socket获取
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            s.connect(("8.8.8.8", 80))
            ip = s.getsockname()[0]
            return ip
        finally:
            s.close()
        
        # 通过hostname获取
        return socket.gethostbyname(socket.gethostname())
    except Exception as e:
        log_message(f"获取服务器IP失败: {str(e)}", "WARNING")
        return ""

def is_port_available(port):
    """检查端口是否可用"""
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        return s.connect_ex(('localhost', port)) != 0

def generate_random_port():
    """生成随机可用端口"""
    min_port, max_port = DEFAULT_PORT_RANGE
    attempts = 0
    
    while attempts < MAX_PORT_ATTEMPTS:
        port = random.randint(min_port, max_port)
        if is_port_available(port):
            return port
        attempts += 1
        time.sleep(0.5)
    
    print(f"{COLOR_ERROR}❌ 错误：无法找到可用端口，请手动指定{COLOR_RESET}")
    log_message("错误：无法找到可用端口", "ERROR")
    sys.exit(1)

def add_firewall_port(port):
    """添加防火墙端口"""
    success = False
    
    # 尝试使用firewalld
    if run_command("command -v firewall-cmd", capture_output=True)[0]:
        if run_command(f"firewall-cmd --permanent --add-port={port}/tcp") and run_command("firewall-cmd --reload"):
            print(f"{COLOR_SUCCESS}✅ [firewalld] 端口 {port} 已添加到防火墙{COLOR_RESET}")
            success = True
    
    # 尝试使用ufw
    elif run_command("command -v ufw", capture_output=True)[0]:
        if run_command(f"ufw allow {port}/tcp") and run_command("ufw reload"):
            print(f"{COLOR_SUCCESS}✅ [ufw] 端口 {port} 已添加到防火墙{COLOR_RESET}")
            success = True
    
    if success:
        log_message(f"端口 {port} 已成功添加到防火墙", "SUCCESS")
        # 添加防火墙后缓冲时间
        time.sleep(1)
    else:
        print(f"{COLOR_ERROR}❌ 添加防火墙规则失败，请手动添加端口 {port}{COLOR_RESET}")
        log_message(f"添加防火墙规则失败，请手动添加端口 {port}", "ERROR")

# ==================== 应用程序管理 ====================
def start_application():
    """启动应用程序"""
    print(f"{COLOR_INFO}🔄 正在启动应用程序...{COLOR_RESET}")
    log_message("正在启动应用程序...", "INFO")
    
    # 切换到目标目录
    os.chdir(TARGET_DIR)
    
    # 启动应用程序 - 使用nohup后台运行
    process = subprocess.Popen(
        "nohup sh start.sh > start.log 2>&1 &",
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True
    )
    
    # 等待进程启动
    time.sleep(5)
    
    # 检查PID文件
    pid_file_found = False
    for _ in range(10):  # 最多尝试10次
        if os.path.exists(PID_FILE):
            pid_file_found = True
            break
        time.sleep(2)
    
    if not pid_file_found:
        print(f"{COLOR_ERROR}❌ 应用启动失败，未找到 PID 文件{COLOR_RESET}")
        log_message("应用启动失败，未找到 PID 文件", "ERROR")
        return False
    
    # 读取PID
    global app_pid
    try:
        with open(PID_FILE, 'r') as f:
            app_pid = int(f.read().strip())
        print(f"{COLOR_SUCCESS}✅ 已获取Java进程PID: {app_pid}{COLOR_RESET}")
        log_message(f"已获取Java进程PID: {app_pid}", "SUCCESS")
        # 获取PID后缓冲时间
        time.sleep(1)
    except Exception as e:
        print(f"{COLOR_ERROR}❌ 读取PID文件失败: {str(e)}{COLOR_RESET}")
        log_message(f"读取PID文件失败: {str(e)}", "ERROR")
        return False
    
    # 等待应用初始化
    print(f"{COLOR_INFO}🔄 等待程序初始化完成 (约{INIT_WAIT_TIME}秒)...{COLOR_RESET}")
    log_message(f"等待程序初始化完成 (约{INIT_WAIT_TIME}秒)...", "INFO")
    
    for i in range(1, INIT_WAIT_TIME + 1):
        print(f"{COLOR_INFO}➔ 等待中... {i}/{INIT_WAIT_TIME} 秒{COLOR_RESET}", end='\r')
        time.sleep(1)
    
    print(f"\n{COLOR_SUCCESS}✅ 程序初始化完成{COLOR_RESET}")
    log_message("程序初始化完成", "SUCCESS")
    # 初始化完成后缓冲时间
    time.sleep(1)
    return True

def stop_application():
    """停止应用程序"""
    print(f"{COLOR_INFO}🔄 正在关闭应用程序...{COLOR_RESET}")
    log_message("正在关闭应用程序...", "INFO")
    
    if not os.path.exists(PID_FILE):
        print(f"{COLOR_WARNING}⚠️ 未找到PID文件，应用程序可能未运行{COLOR_RESET}")
        log_message("未找到PID文件，应用程序可能未运行", "WARNING")
        return True
    
    try:
        with open(PID_FILE, 'r') as f:
            pid = int(f.read().strip())
        
        # 尝试正常终止
        run_command(f"kill {pid}")
        
        # 检查进程是否仍在运行
        time.sleep(3)
        if run_command(f"ps -p {pid} > /dev/null"):
            # 强制终止
            run_command(f"kill -9 {pid}")
        
        # 删除PID文件
        if os.path.exists(PID_FILE):
            os.remove(PID_FILE)
        
        print(f"{COLOR_SUCCESS}✅ 应用程序关闭成功！{COLOR_RESET}")
        log_message("应用程序关闭成功", "SUCCESS")
        # 停止应用后缓冲时间
        time.sleep(1)
        return True
    except Exception as e:
        print(f"{COLOR_ERROR}❌ 关闭应用程序失败: {str(e)}{COLOR_RESET}")
        log_message(f"关闭应用程序失败: {str(e)}", "ERROR")
        return False

def check_application_status():
    """检查应用程序状态"""
    # 从配置文件中读取端口
    try:
        with open(CONFIG_FILE, 'r') as f:
            content = f.read()
            match = re.search(r'port:\s*(\d+)', content)
            if match:
                config_port = int(match.group(1))
            else:
                print(f"{COLOR_ERROR}❌ 无法从配置文件中获取端口号{COLOR_RESET}")
                return False
    except Exception as e:
        print(f"{COLOR_ERROR}❌ 读取配置文件失败: {str(e)}{COLOR_RESET}")
        return False
    
    # 检查端口是否被占用
    if not is_port_available(config_port):
        print(f"{COLOR_SUCCESS}✅ 端口 {config_port} 正在被使用{COLOR_RESET}")
        
        # 获取占用端口的进程
        output = run_command(f"lsof -i :{config_port}", capture_output=True)[0]
        if output:
            print(f"{COLOR_INFO}占用进程信息:\n{output}{COLOR_RESET}")
        
        # 检查PID文件
        if os.path.exists(PID_FILE):
            try:
                with open(PID_FILE, 'r') as f:
                    pid = f.read().strip()
                print(f"{COLOR_INFO}应用PID文件存在: PID={pid}{COLOR_RESET}")
                return True
            except:
                pass
        
        print(f"{COLOR_WARNING}⚠️ 端口 {config_port} 被占用，但未找到有效的PID文件{COLOR_RESET}")
        return False
    
    print(f"{COLOR_WARNING}⚠️ 端口 {config_port} 未被占用，应用可能未运行{COLOR_RESET}")
    return False

# ==================== 工具管理函数 ====================
def manage_tools(tool_type):
    """管理各种工具"""
    if tool_type == "apk":
        # 清屏
        if os.name == 'posix':
            os.system('clear')
        
        print(f"{COLOR_HEADER}========== APK去签工具 =========={COLOR_RESET}")
        print(f"{COLOR_INFO}🔄 正在运行APK去签工具...{COLOR_RESET}")
        log_message("正在运行APK去签工具...", "INFO")
        
        nkstool_dir = os.path.join(TARGET_DIR, "nkstool")
        if os.path.isdir(nkstool_dir):
            os.chdir(nkstool_dir)
            run_command("sh run.sh")
            log_message("运行APK去签工具成功", "SUCCESS")
            # 运行工具后缓冲时间
            time.sleep(2)
        else:
            print(f"{COLOR_ERROR}❌ 错误：未找到APK去签工具目录{COLOR_RESET}")
            log_message("错误：未找到APK去签工具目录", "ERROR")
            # 错误提示后缓冲时间
            time.sleep(1)
        
        show_divider()
        input("按任意键返回主菜单...")
        
    elif tool_type == "jiagu":
        # 清屏
        if os.name == 'posix':
            os.system('clear')
        
        print(f"{COLOR_HEADER}========== APK普通加固工具 =========={COLOR_RESET}")
        print(f"{COLOR_INFO}🔄 正在运行APK普通加固工具...{COLOR_RESET}")
        log_message("正在运行APK普通加固工具...", "INFO")
        
        jiagu_dir = os.path.join(TARGET_DIR, "jiagu")
        if os.path.isdir(jiagu_dir):
            os.chdir(jiagu_dir)
            run_command("sh jg.sh")
            log_message("运行APK普通加固工具成功", "SUCCESS")
            # 运行工具后缓冲时间
            time.sleep(2)
        else:
            print(f"{COLOR_ERROR}❌ 错误：未找到加固工具目录{COLOR_RESET}")
            log_message("错误：未找到加固工具目录", "ERROR")
            # 错误提示后缓冲时间
            time.sleep(1)
        
        show_divider()
        input("按任意键返回主菜单...")
        
    elif tool_type == "jiaguhx":
        # 清屏
        if os.name == 'posix':
            os.system('clear')
        
        print(f"{COLOR_HEADER}========== APK超级混淆360加固工具 =========={COLOR_RESET}")
        print(f"{COLOR_INFO}🔄 正在运行超级混淆360加固工具...{COLOR_RESET}")
        log_message("正在运行APK超级混淆360加固工具...", "INFO")
        
        jiagu_dir = os.path.join(TARGET_DIR, "jiagu")
        if os.path.isdir(jiagu_dir):
            os.chdir(jiagu_dir)
            run_command("sh alihx.sh")
            log_message("运行APK超级混淆360加固工具成功", "SUCCESS")
            # 运行工具后缓冲时间
            time.sleep(2)
        else:
            print(f"{COLOR_ERROR}❌ 错误：未找到加固工具目录{COLOR_RESET}")
            log_message("错误：未找到加固工具目录", "ERROR")
            # 错误提示后缓冲时间
            time.sleep(1)
        
        show_divider()
        input("按任意键返回主菜单...")
        
    elif tool_type == "alitc":
        # 清屏
        if os.name == 'posix':
            os.system('clear')
        
        print(f"{COLOR_HEADER}========== APK注入弹窗式注册机注入工具 =========={COLOR_RESET}")
        print(f"{COLOR_INFO}🔄 正在运行APK弹窗式注册机注入工具...{COLOR_RESET}")
        log_message("正在运行APK注入弹窗式注册机注入工具...", "INFO")
        
        alitc_dir = os.path.join(TARGET_DIR, "Alitc")
        if os.path.isdir(alitc_dir):
            os.chdir(alitc_dir)
            run_command("sh ali.sh")
            log_message("运行APK注入弹窗式注册机注入工具成功", "SUCCESS")
            # 运行工具后缓冲时间
            time.sleep(2)
        else:
            print(f"{COLOR_ERROR}❌ 错误：未找到注册机注入工具目录{COLOR_RESET}")
            log_message("错误：未找到注册机注入工具目录", "ERROR")
            # 错误提示后缓冲时间
            time.sleep(1)
        
        show_divider()
        input("按任意键返回主菜单...")

# ==================== 主部署流程 ====================
def verify_application_access():
    """验证网站访问"""
    show_step(10, "验证网站访问")
    show_divider()
    
    access_url = f"http://{server_ip}:{rand_port}"
    print(f"{COLOR_INFO}🔄 正在测试访问: {access_url}{COLOR_RESET}")
    log_message(f"正在测试访问: {access_url}", "INFO")
    
    try:
        import requests
        response = requests.get(access_url, timeout=10)
        if response.status_code == 200:
            print(f"{COLOR_SUCCESS}✅ 网站访问成功！{COLOR_RESET}")
            log_message("网站访问成功", "SUCCESS")
            
            print(f"{COLOR_INFO}========================================{COLOR_RESET}")
            print(f"{COLOR_SUCCESS}请使用以下地址访问系统：{COLOR_RESET}")
            print(f"{COLOR_HEADER}{access_url}{COLOR_RESET}")
            print(f"{COLOR_INFO}========================================{COLOR_RESET}")
            # 访问成功后缓冲时间
            time.sleep(2)
            return True
    except:
        pass
    
    print(f"{COLOR_WARNING}⚠️ 网站访问测试失败，但服务可能仍在启动中{COLOR_RESET}")
    log_message("网站访问测试失败，但服务可能仍在启动中", "WARNING")
    print(f"{COLOR_WARNING}请稍后手动检查: {access_url}{COLOR_RESET}")
    # 访问失败后缓冲时间
    time.sleep(2)
    return False

def show_deployment_result():
    """显示部署结果"""
    print(f"{COLOR_HEADER}========== 部署结果 =========={COLOR_RESET}")
    
    # 标记部署完成
    mark_deployment_complete()
    
    print(f"• {COLOR_STEP}后台访问地址{COLOR_RESET}: {COLOR_SUCCESS}http://{server_ip}:{rand_port}{COLOR_RESET}")
    print(f"• {COLOR_STEP}管理员账号{COLOR_RESET}: {COLOR_SUCCESS}admin{COLOR_RESET}")
    print(f"• {COLOR_STEP}管理员密码{COLOR_RESET}: {COLOR_SUCCESS}123456{COLOR_RESET}")
    print(f"• {COLOR_STEP}使用端口{COLOR_RESET}: {COLOR_SUCCESS}{rand_port}{COLOR_RESET}")
    print(f"• {COLOR_STEP}服务器IP{COLOR_RESET}: {COLOR_SUCCESS}{server_ip}{COLOR_RESET}")
    print(f"• {COLOR_STEP}应用PID{COLOR_RESET}: {COLOR_SUCCESS}{app_pid}{COLOR_RESET}")
    print(f"• {COLOR_STEP}输出日志{COLOR_RESET}: {COLOR_SUCCESS}{LOG_FILE}{COLOR_RESET}")
    print(f"• {COLOR_STEP}标记文件{COLOR_RESET}: {COLOR_SUCCESS}{DEPLOYMENT_MARKER}{COLOR_RESET}")
    
    show_divider()
    print(f"{COLOR_WARNING}重要提示：{COLOR_RESET}")
    print("1. 首次启动需要等待30秒以上初始化时间")
    print("2. 检查CPU负载情况，正常启动会有波动")
    print(f"3. 确保防火墙已开放端口 {COLOR_SUCCESS}{rand_port}{COLOR_RESET}")
    print("4. 如无法访问，请检查端口配置并重启程序")
    print("5. 如数据库未显示，请点击『同步数据库』->『从服务器同步』恢复显示")
    print("6. 如仍有问题，再次点击『同步数据库』->『从面板同步』再修改密码为alidpb")
    
    show_divider()
    print(f"{COLOR_STEP}技术支持：消失的阿力【闲鱼&B站同号】{COLOR_RESET}")
    print(f"{COLOR_STEP}联系方式：QQ：1728031575 | 微信：Ali01021123{COLOR_RESET}")
    log_message(f"部署完成，访问地址: http://{server_ip}:{rand_port}", "SUCCESS")
    show_divider()

def deploy_application():
    """主部署流程"""
    # 检查部署锁
    if os.path.exists(DEPLOYMENT_MARKER):
        print(f"{COLOR_ERROR}❌ 错误：系统已部署，非必要情况禁止重复操作！{COLOR_RESET}")
        print(f"{COLOR_WARNING}⚠️ 如需重新部署，请先执行: {COLOR_RESET}")
        print("  1. 主菜单选择『重置部署状态』")
        print("  2. 手动删除数据库")
        print("  3. 重启服务器")
        print("  4. 如只是想重启程序请移步菜单选项2")
        show_divider()
        log_message("拒绝部署：系统已部署且未重置", "ERROR")
        # 错误提示后缓冲时间
        time.sleep(2)
        return
    
    # 修改MySQL root密码
    new_root_pass = change_mysql_root_password()
    # 步骤间缓冲时间
    time.sleep(2)
    
    # 安装Java环境
    install_java_environment()
    # 步骤间缓冲时间
    time.sleep(2)
    
    # 配置数据库
    if not setup_database(new_root_pass):
        sys.exit(1)
    # 步骤间缓冲时间
    time.sleep(2)
    
    # 设置目录权限
    set_directory_permissions()
    # 步骤间缓冲时间
    time.sleep(2)
    
    # 复制文件
    copy_required_files()
    # 步骤间缓冲时间
    time.sleep(2)
    
    # 检查配置文件
    check_config_file()
    # 步骤间缓冲时间
    time.sleep(2)
    
    # 更新服务器配置
    global server_ip, rand_port
    server_ip = get_server_ip()
    if not server_ip:
        server_ip = input(f"{COLOR_INPUT}请输入服务器IP地址: {COLOR_RESET}").strip()
    
    rand_port = generate_random_port()
    print(f"{COLOR_INFO}ℹ️ 已生成可用端口：{rand_port}{COLOR_RESET}")
    # 获取端口后缓冲时间
    time.sleep(1)
    
    # 更新配置文件
    print(f"{COLOR_INFO}🔄 正在更新配置文件...{COLOR_RESET}")
    try:
        with open(CONFIG_FILE, 'r') as f:
            content = f.read()
        
        content = re.sub(r'ipAddress:\s*\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', f'ipAddress: {server_ip}', content)
        content = re.sub(r'port:\s*\d+', f'port: {rand_port}', content)
        
        with open(CONFIG_FILE, 'w') as f:
            f.write(content)
        
        print(f"{COLOR_SUCCESS}✅ 配置文件更新成功！{COLOR_RESET}")
        log_message("配置文件更新成功", "SUCCESS")
        # 更新配置后缓冲时间
        time.sleep(2)
    except Exception as e:
        print(f"{COLOR_ERROR}❌ 更新配置文件失败: {str(e)}{COLOR_RESET}")
        log_message(f"更新配置文件失败: {str(e)}", "ERROR")
        sys.exit(1)
    
    # 启动应用程序
    if not start_application():
        sys.exit(1)
    # 启动应用后缓冲时间
    time.sleep(2)
    
    # 配置防火墙
    print(f"{COLOR_INFO}🔄 正在配置防火墙...{COLOR_RESET}")
    add_firewall_port(rand_port)
    # 配置防火墙后缓冲时间
    time.sleep(2)
    
    # 验证访问
    verify_application_access()
    # 验证访问后缓冲时间
    time.sleep(2)
    
    # 显示部署结果
    show_deployment_result()

# ==================== 菜单系统 ====================
def deployment_menu():
    """部署菜单"""
    while True:
        # 清屏
        if os.name == 'posix':
            os.system('clear')
        
        print(f"{COLOR_HEADER}============ 系统部署选项 ============{COLOR_RESET}")
        print(f"{COLOR_INFO}1. 执行完整部署")
        print(f"2. 重置部署状态")
        print(f"0. 返回主菜单{COLOR_RESET}")
        
        choice = input(f"{COLOR_INPUT}请输入选项 [0-2]: {COLOR_RESET}").strip()
        log_message(f"用户选择部署菜单选项: {choice}", "INFO")
        
        if choice == '1':
            print(f"{COLOR_WARNING}⚠️ 即将开始部署应用程序，是否继续？ [y/N] {COLOR_RESET}", end='')
            confirm = input().strip().lower()
            if confirm == 'y':
                deploy_application()
            else:
                print(f"{COLOR_INFO}❕ 已取消部署操作{COLOR_RESET}")
                # 取消操作后缓冲时间
                time.sleep(1)
        elif choice == '2':
            print(f"{COLOR_WARNING}⚠️ 即将重置部署状态，是否继续？ [y/N] {COLOR_RESET}", end='')
            confirm = input().strip().lower()
            if confirm == 'y':
                if os.path.exists(DEPLOYMENT_MARKER):
                    os.remove(DEPLOYMENT_MARKER)
                    print(f"{COLOR_SUCCESS}✅ 部署状态已重置！{COLOR_RESET}")
                    log_message("部署状态已重置", "SUCCESS")
                    print(f"{COLOR_WARNING}❕ 重要提示：必须重启服务器使重置生效！{COLOR_RESET}")
                    # 重置状态后缓冲时间
                    time.sleep(2)
                else:
                    print(f"{COLOR_INFO}ℹ️ 当前已是首次部署状态，无需重置{COLOR_RESET}")
                    # 无需操作后缓冲时间
                    time.sleep(1)
            else:
                print(f"{COLOR_INFO}❕ 已取消重置操作{COLOR_RESET}")
                # 取消操作后缓冲时间
                time.sleep(1)
        elif choice == '0':
            return
        else:
            print(f"{COLOR_ERROR}❌ 无效选择，请重新输入{COLOR_RESET}")
            # 无效输入后缓冲时间
            time.sleep(1)
        
        input("按任意键继续...")

def program_management_menu():
    """程序管理菜单"""
    while True:
        # 清屏
        if os.name == 'posix':
            os.system('clear')
        
        print(f"{COLOR_HEADER}============ 程序管理选项 ============{COLOR_RESET}")
        print(f"{COLOR_INFO}1. 启动/重启应用程序")
        print(f"2. 停止应用程序")
        print(f"3. 查看程序状态")
        print(f"0. 返回主菜单{COLOR_RESET}")
        
        choice = input(f"{COLOR_INPUT}请输入选项 [0-3]: {COLOR_RESET}").strip()
        log_message(f"用户选择程序管理选项: {choice}", "INFO")
        
        if choice == '1':
            print(f"{COLOR_WARNING}⚠️ 即将启动/重启应用程序，是否继续？ [y/N] {COLOR_RESET}", end='')
            confirm = input().strip().lower()
            if confirm == 'y':
                if start_application():
                    print(f"{COLOR_SUCCESS}✅ 应用程序启动成功！{COLOR_RESET}")
                else:
                    print(f"{COLOR_ERROR}❌ 应用程序启动失败{COLOR_RESET}")
                # 操作完成后缓冲时间
                time.sleep(2)
            else:
                print(f"{COLOR_INFO}❕ 已取消启动操作{COLOR_RESET}")
                # 取消操作后缓冲时间
                time.sleep(1)
        elif choice == '2':
            print(f"{COLOR_WARNING}⚠️ 即将关闭应用程序，是否继续？ [y/N] {COLOR_RESET}", end='')
            confirm = input().strip().lower()
            if confirm == 'y':
                if stop_application():
                    print(f"{COLOR_SUCCESS}✅ 应用程序已停止！{COLOR_RESET}")
                else:
                    print(f"{COLOR_ERROR}❌ 停止应用程序失败{COLOR_RESET}")
                # 操作完成后缓冲时间
                time.sleep(2)
            else:
                print(f"{COLOR_INFO}❕ 已取消关闭操作{COLOR_RESET}")
                # 取消操作后缓冲时间
                time.sleep(1)
        elif choice == '3':
            if check_application_status():
                print(f"{COLOR_SUCCESS}✅ 应用程序正在运行{COLOR_RESET}")
            else:
                print(f"{COLOR_WARNING}⚠️ 应用程序未运行{COLOR_RESET}")
            # 查看状态后缓冲时间
            time.sleep(2)
        elif choice == '0':
            return
        else:
            print(f"{COLOR_ERROR}❌ 无效选择，请重新输入{COLOR_RESET}")
            # 无效输入后缓冲时间
            time.sleep(1)
        
        input("按任意键继续...")

def utilities_menu():
    """实用工具菜单"""
    while True:
        # 清屏
        if os.name == 'posix':
            os.system('clear')
        
        print(f"{COLOR_HEADER}============ 实用工具选项 ============{COLOR_RESET}")
        print(f"{COLOR_INFO}1. 签名校验破解工具")
        print(f"2. 独立普通加固工具")
        print(f"3. 超级混淆360加固工具")
        print(f"4. 弹窗式注册机注入工具")
        print(f"5. 清理程序缓存目录")
        print(f"0. 返回主菜单{COLOR_RESET}")
        
        choice = input(f"{COLOR_INPUT}请输入选项 [0-5]: {COLOR_RESET}").strip()
        log_message(f"用户选择实用工具选项: {choice}", "INFO")
        
        if choice == '1':
            manage_tools("apk")
        elif choice == '2':
            manage_tools("jiagu")
        elif choice == '3':
            manage_tools("jiaguhx")
        elif choice == '4':
            manage_tools("alitc")
        elif choice == '5':
            clean_cache_directories()
        elif choice == '0':
            return
        else:
            print(f"{COLOR_ERROR}❌ 无效选择，请重新输入{COLOR_RESET}")
            # 无效输入后缓冲时间
            time.sleep(1)
        
        input("按任意键继续...")

def show_log_content(filename, title):
    """显示日志内容"""
    # 清屏
    if os.name == 'posix':
        os.system('clear')
    
    filepath = os.path.join(TARGET_DIR, filename)
    
    print(f"{COLOR_HEADER}========== {title} =========={COLOR_RESET}")
    print(f"{COLOR_INFO}文件路径: {filepath}{COLOR_RESET}")
    
    if not os.path.exists(filepath):
        print(f"{COLOR_ERROR}❌ 错误：日志文件不存在！{COLOR_RESET}")
        log_message(f"错误：日志文件 {filepath} 不存在", "ERROR")
        # 错误提示后缓冲时间
        time.sleep(1)
        return
    
    try:
        # 显示文件内容
        with open(filepath, 'r', encoding='utf-8') as f:
            content = f.read()
        
        print(f"{COLOR_INFO}--------------------------------------{COLOR_RESET}")
        print(content)
        print(f"{COLOR_INFO}--------------------------------------{COLOR_RESET}")
        print(f"{COLOR_SUCCESS}✅ 日志显示完成{COLOR_RESET}")
        # 显示日志后缓冲时间
        time.sleep(2)
    except Exception as e:
        print(f"{COLOR_ERROR}❌ 读取日志文件失败: {str(e)}{COLOR_RESET}")
        log_message(f"读取日志文件失败: {str(e)}", "ERROR")
        # 错误提示后缓冲时间
        time.sleep(1)

def log_management_menu():
    """日志管理菜单"""
    while True:
        # 清屏
        if os.name == 'posix':
            os.system('clear')
        
        print(f"{COLOR_HEADER}============ 日志管理选项 ============{COLOR_RESET}")
        print(f"{COLOR_INFO}1. 查看脚本更新日志")
        print(f"2. 查看程序更新日志")
        print(f"3. 查看脚本运行日志")
        print(f"0. 返回主菜单{COLOR_RESET}")
        
        choice = input(f"{COLOR_INPUT}请输入选项 [0-3]: {COLOR_RESET}").strip()
        log_message(f"用户选择日志管理选项: {choice}", "INFO")
        
        if choice == '1':
            show_log_content("脚本更新日志.md", "脚本更新日志")
        elif choice == '2':
            show_log_content("程序更新日志.md", "程序更新日志")
        elif choice == '3':
            show_log_content("遥辉正版.md", "脚本运行日志")
        elif choice == '0':
            return
        else:
            print(f"{COLOR_ERROR}❌ 无效选择，请重新输入{COLOR_RESET}")
            # 无效输入后缓冲时间
            time.sleep(1)
        
        input("按任意键继续...")

def system_management_menu():
    """系统管理菜单"""
    while True:
        # 清屏
        if os.name == 'posix':
            os.system('clear')
        
        print(f"{COLOR_HEADER}============ 系统管理选项 ============{COLOR_RESET}")
        print(f"{COLOR_INFO}1. 修改MySQL root密码")
        print(f"2. 重新配置Java环境")
        print(f"3. 修复目录权限")
        print(f"0. 返回主菜单{COLOR_RESET}")
        
        choice = input(f"{COLOR_INPUT}请输入选项 [0-3]: {COLOR_RESET}").strip()
        log_message(f"用户选择系统管理选项: {choice}", "INFO")
        
        if choice == '1':
            change_mysql_root_password()
            # 修改密码后缓冲时间
            time.sleep(2)
        elif choice == '2':
            install_java_environment()
            # 配置环境后缓冲时间
            time.sleep(2)
        elif choice == '3':
            set_directory_permissions()
            # 设置权限后缓冲时间
            time.sleep(2)
        elif choice == '0':
            return
        else:
            print(f"{COLOR_ERROR}❌ 无效选择，请重新输入{COLOR_RESET}")
            # 无效输入后缓冲时间
            time.sleep(1)
        
        input("按任意键继续...")

def main_menu():
    """显示主菜单"""
    while True:
        print(f"{COLOR_HEADER}============ 遥辉APK报毒处理系统智能部署脚本 ============{COLOR_RESET}\n")
        
        print(f"{COLOR_INFO}======================= 特别说明 ========================{COLOR_RESET}")
        print(f"{COLOR_STEP}1. 通过宝塔面板上传部署包到 {TARGET_DIR}")
        print(f"2. 创建网站并设置目录为 {TARGET_DIR}")
        print("3. 目前支持自动创建数据库但是不完美又不会影响运行")
        print("4. 建议还是手动添加不介意不显示数据库的就直接脚本部署即可")
        print(f"5. 创建数据库: 用户名={DB_USER}, 密码={DB_PASS}")
        print(f"6. 导入数据库文件 AliDPB.sql")
        print(f"{COLOR_INFO}========================================================={COLOR_RESET}")
        print(f"{COLOR_SUCCESS}✅ 脚本作者：消失的阿力{COLOR_RESET}")
        print(f"{COLOR_SUCCESS}✅ 联系企鹅：1728031575{COLOR_RESET}")
        print(f"{COLOR_SUCCESS}✅ 联系微信：Ali01021123{COLOR_RESET}")
        print(f"{COLOR_SUCCESS}✅ 闲鱼搜索：阿力_遥辉网络{COLOR_RESET}")
        print(f"{COLOR_SUCCESS}✅ 脚本版本：5.0 最终优化版{COLOR_RESET}")
        print(f"{COLOR_INFO}========================================================={COLOR_RESET}")
        
        # 显示部署状态
        if is_first_deployment():
            print(f"{COLOR_WARNING}⚠️ 当前部署状态：首次部署{COLOR_RESET}")
        else:
            print(f"{COLOR_SUCCESS}✅ 当前部署状态：已部署{COLOR_RESET}")
        
        # 显示程序当前状态
        print(f"{COLOR_INFO}当前程序状态: ", end="")
        if check_application_status():
            print(f"{COLOR_SUCCESS}运行中{COLOR_RESET}")
        else:
            print(f"{COLOR_WARNING}未运行{COLOR_RESET}")
        
        print(f"{COLOR_INFO}========================================================={COLOR_RESET}")
        print(f"{COLOR_SUCCESS}1. 一键部署{COLOR_RESET}")
        print(f"{COLOR_SUCCESS}2. 程序管理{COLOR_RESET}")
        print(f"{COLOR_SUCCESS}3. 实用工具{COLOR_RESET}")
        print(f"{COLOR_SUCCESS}4. 日志管理{COLOR_RESET}")
        print(f"{COLOR_SUCCESS}5. 系统管理{COLOR_RESET}")
        print(f"{COLOR_SUCCESS}0. 退出脚本{COLOR_RESET}")
        print(f"{COLOR_HEADER}================================={COLOR_RESET}")
        
        choice = input(f"{COLOR_INPUT}请输入选项 [0-5]: {COLOR_RESET}").strip()
        log_message(f"用户选择主菜单选项: {choice}", "INFO")
        
        if choice == '1':
            deployment_menu()
        elif choice == '2':
            program_management_menu()
        elif choice == '3':
            utilities_menu()
        elif choice == '4':
            log_management_menu()
        elif choice == '5':
            system_management_menu()
        elif choice == '0':
            print(f"{COLOR_SUCCESS}✅ 感谢使用遥辉部署脚本！{COLOR_RESET}")
            sys.exit(0)
        else:
            print(f"{COLOR_ERROR}❌ 无效选择，请重新输入{COLOR_RESET}")
            # 无效输入后缓冲时间
            time.sleep(1)

# ==================== 脚本入口 ====================
if __name__ == "__main__":
    # 检查root权限
    if os.geteuid() != 0:
        print(f"{COLOR_ERROR}❌ 错误：该脚本需要root权限执行！{COLOR_RESET}")
        sys.exit(1)
    
    # 初始化日志
    setup_logging()
    
    # 启动主菜单
    main_menu()