# -*- coding: utf-8 -*-
"""
AppImage instructions:
mkdir -p ~/Downloads/Cursor
cd ~/Downloads/Cursor
cd Cursor && ./Cursor-1.0.5-x86_64.AppImage --appimage-extract
mkdir -p ~/.local
rsync -rt ~/Downloads/Cursor/squashfs-root/usr/ ~/.local
# ^ copy the subfolders not usr itself, so the resulting executable should be ~/.local/bin/cursor
"""
import subprocess
import os

SCRIPTS_DIR = os.path.dirname(os.path.abspath(__file__))
# repo_dir = os.path.dirname(SCRIPTS_DIR)
repo_dir = SCRIPTS_DIR
locales_dir = os.path.join(repo_dir, 'locales')
t_domain = "cursor_id_modifier"

def compile_messages():
    global _
    languages = ['en_US', 'zh_CN']
    for lang in languages:
        lang_dir = os.path.join(locales_dir, lang, 'LC_MESSAGES')
        if os.path.isdir(lang_dir):
            # Change the directory to the LC_MESSAGES folder
            os.chdir(lang_dir)
            # Run msgfmt command
            out_name = 'cursor_id_modifier.mo'
            subprocess.run(['msgfmt', '-o', out_name, 'cursor_id_modifier.po'], check=True)
            print(os.path.abspath(out_name))
        else:
            print(f"Directory not found: {lang_dir}")

import sys
import subprocess
import datetime
import tempfile
import shutil
import uuid
import hashlib
import re
import getpass
import time
import select
import tty
import termios
import signal
import json
from pathlib import Path
import glob
import pwd

import gettext
import random

# 尝试导入netifaces，如果不可用则使用系统命令
# Try to import netifaces, use system commands if not available
try:
    import netifaces
    NETIFACES_AVAILABLE = True
except ImportError:
    NETIFACES_AVAILABLE = False
    log_warn = lambda x: print(f"[WARN] {x}")  # 临时日志函数
    log_warn("netifaces library not found, will use system commands for network operations")

# 设置语言环境
# Set language environment

# lang = 'zh' if '--en' not in sys.argv else 'en'
lang = 'en'

assert os.path.isdir(locales_dir)
# gettext.bindtextdomain(t_domain, localedir=locales_dir)
if lang == 'zh':
    translation = gettext.translation(
        t_domain,
        localedir=locales_dir,
        languages=['en_US', 'zh_CN'],
    )
else:
    translation = gettext.NullTranslations()
translation.install()
_ = translation.gettext

# 设置错误处理
# Set error handling
def set_error_handling():
    global _
    # 在 Python 中，我们使用 try/except 来处理错误，而不是 bash 的 set -e
    # In Python, we use try/except to handle errors instead of bash's set -e
    pass

set_error_handling()

# 定义日志文件路径
# Define log file path
LOG_FILE = "/tmp/cursor_linux_id_modifier.log"

# 初始化日志文件
# Initialize log file
def initialize_log():
    with open(LOG_FILE, 'w') as f:
        f.write(_("========== Cursor ID modification tool log start {} ==========").format(datetime.datetime.now()) + "\n")
    os.chmod(LOG_FILE, 0o644)

# 颜色定义
# Color definitions
RED = '\033[0;31m'
GREEN = '\033[0;32m'
YELLOW = '\033[1;33m'
BLUE = '\033[0;34m'
NC = '\033[0m'  # No Color

# 日志函数 - 同时输出到终端和日志文件
# Log functions - output to terminal and log file simultaneously
def log_info(message):
    global _
    print(f"{GREEN}[INFO]{NC} {_(message)}")
    with open(LOG_FILE, 'a') as f:
        f.write(_("[INFO] {} {}").format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), _(message)) + "\n")

def log_warn(message):
    global _
    print(f"{YELLOW}[WARN]{NC} {_(message)}")
    with open(LOG_FILE, 'a') as f:
        f.write(_("[WARN] {} {}").format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), _(message)) + "\n")

def log_error(message):
    global _
    print(f"{RED}[ERROR]{NC} {_(message)}")
    with open(LOG_FILE, 'a') as f:
        f.write(_("[ERROR] {} {}").format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), _(message)) + "\n")

def log_debug(message):
    global _
    print(f"{BLUE}[DEBUG]{NC} {_(message)}")
    with open(LOG_FILE, 'a') as f:
        f.write(_("[DEBUG] {} {}").format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), _(message)) + "\n")

# 记录命令输出到日志文件
# Log command output to log file
def log_cmd_output(cmd, msg):
    global _
    with open(LOG_FILE, 'a') as f:
        f.write(_("[CMD] {} Executing command: {}").format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), cmd) + "\n")
        f.write(_("[CMD] {}:").format(_(msg)) + "\n")
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
    with open(LOG_FILE, 'a') as f:
        for line in process.stdout:
            print(line, end='')
            f.write(line)
    process.wait()
    with open(LOG_FILE, 'a') as f:
        f.write("\n")

# 获取当前用户
# Get current user
def get_current_user():
    global _
    if os.geteuid() == 0:
        return os.environ.get('SUDO_USER', '')
    return getpass.getuser()

CURRENT_USER = get_current_user()
if not CURRENT_USER:
    log_error(_("Unable to get username"))
    sys.exit(1)

# 定义Linux下的Cursor路径
# Define Cursor paths on Linux
CURSOR_CONFIG_DIR = os.path.expanduser("~/.config/Cursor")
STORAGE_FILE = os.path.join(CURSOR_CONFIG_DIR, "User/globalStorage/storage.json")
BACKUP_DIR = os.path.join(CURSOR_CONFIG_DIR, "User/globalStorage/backups")

# 可能的Cursor二进制路径
# Possible Cursor binary paths
CURSOR_BIN_PATHS = [
    "/usr/bin/cursor",
    "/usr/local/bin/cursor",
    os.path.expanduser("~/.local/bin/cursor"),
    "/opt/cursor/cursor",
    "/snap/bin/cursor",
]

# 找到Cursor安装路径
# Find Cursor installation path
def find_cursor_path():
    global _
    log_info(_("Finding Cursor installation path..."))

    for path in CURSOR_BIN_PATHS:
        if os.path.isfile(path):
            log_info(_("Found Cursor installation path: {}").format(path))
            os.environ['CURSOR_PATH'] = path
            return True

    # 尝试通过which命令定位
    # Try locating via which command
    try:
        result = subprocess.run(['which', 'cursor'], capture_output=True, text=True)
        if result.returncode == 0:
            os.environ['CURSOR_PATH'] = result.stdout.strip()
            log_info(_("Found Cursor via which: {}").format(os.environ['CURSOR_PATH']))
            return True
    except subprocess.CalledProcessError:
        pass

    # 尝试查找可能的安装路径
    # Try finding possible installation paths
    search_dirs = ['/usr', '/opt', os.path.expanduser('~/.local')]
    for dir in search_dirs:
        try:
            for root, _1, files in os.walk(dir):
                if 'cursor' in files:
                    path = os.path.join(root, 'cursor')
                    if os.access(path, os.X_OK):
                        os.environ['CURSOR_PATH'] = path
                        log_info(_("Found Cursor via search: {}").format(os.environ['CURSOR_PATH']))
                        return True
        except PermissionError:
            continue
    log_warn(_("Cursor executable not found, will try using config directory"))
    return False

# 查找并定位Cursor资源文件目录
# Find and locate Cursor resource directory
def find_cursor_resources():
    global _
    log_info(_("Finding Cursor resource directory..."))

    # 可能的资源目录路径
    # Possible resource directory paths
    resource_paths = [
        "/usr/lib/cursor",
        "/usr/share/cursor",
        "/opt/cursor",
        os.path.expanduser("~/.local/share/cursor"),
    ]

    for path in resource_paths:
        if os.path.isdir(path):
            log_info(_("Found Cursor resource directory: {}").format(path))
            os.environ['CURSOR_RESOURCES'] = path
            return True

    # 如果有CURSOR_PATH，尝试从它推断
    # If CURSOR_PATH exists, try to infer from it
    if os.environ.get('CURSOR_PATH'):
        base_dir = os.path.dirname(os.environ['CURSOR_PATH'])
        resource_dir = os.path.join(base_dir, 'resources')
        if os.path.isdir(resource_dir):
            os.environ['CURSOR_RESOURCES'] = resource_dir
            log_info(_("Found resource directory via binary path: {}").format(os.environ['CURSOR_RESOURCES']))
            return True

    log_warn(_("Cursor resource directory not found"))
    return False

# 检查权限
# Check permissions
def check_permissions():
    global _
    if os.geteuid() != 0:
        log_error(_("Please run this script with sudo"))
        print(_("Example: sudo {}").format(sys.argv[0]))
        sys.exit(1)

# 检查并关闭 Cursor 进程
# Check and kill Cursor processes
def check_and_kill_cursor():
    global _
    log_info(_("Checking Cursor processes..."))

    attempt = 1
    max_attempts = 5

    # 函数：获取进程详细信息
    # Function: Get process details
    def get_process_details(process_name):
        log_debug(_("Getting process details for {}:").format(process_name))
        try:
            result = subprocess.run(
                'ps aux | grep -i "cursor" | grep -v grep | grep -v "cursor_id_modifier.py"',
                shell=True, capture_output=True, text=True
            )
            print(result.stdout)
        except subprocess.CalledProcessError:
            pass

    while attempt <= max_attempts:
        # 使用更精确的匹配来获取 Cursor 进程，排除当前脚本和grep进程
        # Use more precise matching to get Cursor processes, excluding current script and grep
        try:
            result = subprocess.run(
                'ps aux | grep -i "cursor" | grep -v "grep" | grep -v "cursor_id_modifier.py" | awk \'{print $2}\'',
                shell=True, capture_output=True, text=True
            )
            CURSOR_PIDS = result.stdout.strip().split('\n')
            CURSOR_PIDS = [pid for pid in CURSOR_PIDS if pid]
        except subprocess.CalledProcessError:
            CURSOR_PIDS = []

        if not CURSOR_PIDS:
            log_info(_("No running Cursor processes found"))
            return True

        log_warn(_("Found running Cursor processes"))
        get_process_details("cursor")

        log_warn(_("Attempting to terminate Cursor processes..."))

        for pid in CURSOR_PIDS:
            try:
                if attempt == max_attempts:
                    log_warn(_("Attempting to forcefully terminate processes..."))
                    os.kill(int(pid), signal.SIGKILL)
                else:
                    os.kill(int(pid), signal.SIGTERM)
            except (OSError, ValueError):
                continue

        time.sleep(1)

        # 再次检查进程是否还在运行
        # Check again if processes are still running
        try:
            result = subprocess.run(
                'ps aux | grep -i "cursor" | grep -v "grep" | grep -v "cursor_id_modifier.py"',
                shell=True, capture_output=True, text=True
            )
            if not result.stdout.strip():
                log_info(_("Cursor processes successfully terminated"))
                return True
        except subprocess.CalledProcessError:
            log_info(_("Cursor processes successfully terminated"))
            return True

        log_warn(_("Waiting for processes to terminate, attempt {}/{}...").format(attempt, max_attempts))
        attempt += 1

    log_error(_("Unable to terminate Cursor processes after {} attempts").format(max_attempts))
    get_process_details("cursor")
    log_error(_("Please manually terminate the processes and try again"))
    sys.exit(1)

# 备份配置文件
# Backup configuration file
def backup_config():
    global _
    if not os.path.isfile(STORAGE_FILE):
        log_warn(_("Configuration file does not exist, skipping backup"))
        return True

    os.makedirs(BACKUP_DIR, exist_ok=True)
    backup_file = os.path.join(BACKUP_DIR, "storage.json.backup_{}".format(datetime.datetime.now().strftime('%Y%m%d_%H%M%S')))

    try:
        shutil.copy(STORAGE_FILE, backup_file)
        os.chmod(backup_file, 0o644)
        os.chown(backup_file, pwd.getpwnam(CURRENT_USER).pw_uid, -1)
        log_info(_("Configuration backed up to: {}").format(backup_file))
    except (OSError, shutil.Error):
        log_error(_("Backup failed"))
        sys.exit(1)

# 生成随机 ID
# Generate random ID
def generate_random_id():
    global _
    # 生成32字节(64个十六进制字符)的随机数
    # Generate 32 bytes (64 hexadecimal characters) of random data
    return hashlib.sha256(os.urandom(32)).hexdigest()

# 生成随机 UUID
# Generate random UUID
def generate_uuid():
    global _
    # 在Linux上使用uuid模块生成UUID
    # Use uuid module to generate UUID on Linux
    try:
        return str(uuid.uuid1()).lower()
    except Exception:
        # 备选方案：生成类似UUID的字符串
        # Fallback: Generate UUID-like string
        rand_bytes = os.urandom(16)
        rand_hex = rand_bytes.hex()
        return f"{rand_hex[:8]}-{rand_hex[8:12]}-{rand_hex[12:16]}-{rand_hex[16:20]}-{rand_hex[20:]}"

# 修改现有文件
# Modify or add to configuration file
def modify_or_add_config(key, value, file):
    global _
    if not os.path.isfile(file):
        log_error(_("File does not exist: {}").format(file))
        return False

    # 确保文件可写
    # Ensure file is writable
    try:
        os.chmod(file, 0o644)
    except OSError:
        log_error(_("Unable to modify file permissions: {}").format(file))
        return False

    # 创建临时文件
    # Create temporary file
    with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp_file:
        temp_path = temp_file.name

    # 读取原始文件
    # Read original file
    with open(file, 'r') as f:
        content = f.read()

    # 检查key是否存在
    # Check if key exists
    if f'"{key}":' in content:
        # key存在，执行替换
        # Key exists, perform replacement
        pattern = f'"{key}":\\s*"[^"]*"'
        replacement = f'"{key}": "{value}"'
        new_content = re.sub(pattern, replacement, content)
    else:
        # key不存在，添加新的key-value对
        # Key does not exist, add new key-value pair
        new_content = content.rstrip('}\n') + f',\n    "{key}": "{value}"\n}}'

    # 写入临时文件
    # Write to temporary file
    with open(temp_path, 'w') as f:
        f.write(new_content)

    # 检查临时文件是否为空
    # Check if temporary file is empty
    if os.path.getsize(temp_path) == 0:
        log_error(_("Generated temporary file is empty"))
        os.unlink(temp_path)
        return False

    # 替换原文件
    # Replace original file
    try:
        shutil.move(temp_path, file)
    except OSError:
        log_error(_("Unable to write to file: {}").format(file))
        os.unlink(temp_path)
        return False

    # 恢复文件权限
    # Restore file permissions
    os.chmod(file, 0o444)
    return True

# 生成新的配置
# Generate new configuration
def generate_new_config():
    global _
    print()
    log_warn(_("Machine code reset options"))

    # 使用菜单选择函数询问用户是否重置机器码
    # Use menu selection function to ask user whether to reset machine code
    reset_choice = select_menu_option(
        _("Do you need to reset the machine code? (Usually, modifying JS files is sufficient):"),
        [_("Don't reset - only modify JS files"), _("Reset - modify both config file and machine code")],
        0
    )

    # 记录日志以便调试
    # Log for debugging
    with open(LOG_FILE, 'a') as f:
        f.write(_("[INPUT_DEBUG] Machine code reset option selected: {}").format(reset_choice) + "\n")

    # 处理用户选择
    # Handle user selection
    if reset_choice == 1:
        log_info(_("You chose to reset the machine code"))

        # 确保配置文件目录存在
        # Ensure configuration file directory exists
        if os.path.isfile(STORAGE_FILE):
            log_info(_("Found existing configuration file: {}").format(STORAGE_FILE))

            # 备份现有配置
            # Backup existing configuration
            backup_config()

            # 生成并设置新的设备ID
            # Generate and set new device ID
            new_device_id = generate_uuid()
            new_machine_id = "auth0|user_{}".format(hashlib.sha256(os.urandom(16)).hexdigest()[:32])

            log_info(_("Setting new device and machine IDs..."))
            log_debug(_("New device ID: {}").format(new_device_id))
            log_debug(_("New machine ID: {}").format(new_machine_id))

            # 修改配置文件
            # Modify configuration file
            if (modify_or_add_config("deviceId", new_device_id, STORAGE_FILE) and
                modify_or_add_config("machineId", new_machine_id, STORAGE_FILE)):
                log_info(_("Configuration file modified successfully"))
            else:
                log_error(_("Configuration file modification failed"))
        else:
            log_warn(_("Configuration file not found, this is normal, skipping ID modification"))
    else:
        log_info(_("You chose not to reset the machine code, will only modify JS files"))

        # 确保配置文件目录存在
        # Ensure configuration file directory exists
        if os.path.isfile(STORAGE_FILE):
            log_info(_("Found existing configuration file: {}").format(STORAGE_FILE))

            # 备份现有配置
            # Backup existing configuration
            backup_config()
        else:
            log_warn(_("Configuration file not found, this is normal, skipping ID modification"))

    print()
    log_info(_("Configuration processing completed"))

# 查找Cursor的JS文件
# Find Cursor's JS files
def find_cursor_js_files():
    global _
    log_info(_("Finding Cursor's JS files..."))

    js_files = []
    found = False

    # 如果找到了资源目录，在资源目录中搜索
    # If resource directory is found, search in it
    if os.environ.get('CURSOR_RESOURCES'):
        log_debug(_("Searching for JS files in resource directory: {}").format(os.environ['CURSOR_RESOURCES']))

        # 在资源目录中递归搜索特定JS文件
        # Recursively search for specific JS files in resource directory
        js_patterns = [
            "*/extensionHostProcess.js",
            "*/main.js",
            "*/cliProcessMain.js",
            "*/app/out/vs/workbench/api/node/extensionHostProcess.js",
            "*/app/out/main.js",
            "*/app/out/vs/code/node/cliProcessMain.js",
        ]

        for pattern in js_patterns:
            try:
                files = glob.glob(os.path.join(os.environ['CURSOR_RESOURCES'], pattern), recursive=True)
                for file in files:
                    log_info(_("Found JS file: {}").format(file))
                    js_files.append(file)
                    found = True
            except Exception:
                continue

    # 如果还没找到，尝试在/usr和$HOME目录下搜索
    # If not found, try searching in /usr and $HOME directories
    if not found:
        log_warn(_("No JS files found in resource directory, trying other directories..."))

        search_dirs = [
            "/usr/lib/cursor",
            "/usr/share/cursor",
            "/opt/cursor",
            os.path.expanduser("~/.config/Cursor"),
            os.path.expanduser("~/.local/share/cursor"),
        ]

        for dir in search_dirs:
            if os.path.isdir(dir):
                log_debug(_("Searching directory: {}").format(dir))
                try:
                    for root, _1, files in os.walk(dir):
                        for file in files:
                            if file.endswith('.js'):
                                file_path = os.path.join(root, file)
                                with open(file_path, 'r', errors='ignore') as f:
                                    content = f.read()
                                    if "IOPlatformUUID" in content or "x-cursor-checksum" in content:
                                        log_info(_("Found JS file: {}").format(file_path))
                                        js_files.append(file_path)
                                        found = True
                except Exception:
                    continue

    if not found:
        log_error(_("No modifiable JS files found"))
        return False, []

    # 保存找到的文件列表到环境变量
    # Save found files to environment variable
    os.environ['CURSOR_JS_FILES'] = json.dumps(js_files)
    log_info(_("Found {} JS files to modify").format(len(js_files)))
    return True, js_files

# 修改Cursor的JS文件
# Modify Cursor's JS files
def modify_cursor_js_files():
    global _
    log_info(_("Starting to modify Cursor's JS files..."))

    # 先查找需要修改的JS文件
    # First find JS files to modify
    success, js_files = find_cursor_js_files()
    if not success:
        log_error(_("Unable to find modifiable JS files"))
        return False

    modified_count = 0

    for file in js_files:
        log_info(_("Processing file: {}").format(file))

        # 创建文件备份
        # Create file backup
        backup_file = f"{file}.backup_{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}"
        try:
            shutil.copy(file, backup_file)
        except OSError:
            log_error(_("Unable to create backup for file: {}").format(file))
            continue

        # 确保文件可写
        # Ensure file is writable
        try:
            os.chmod(file, 0o644)
        except OSError:
            log_error(_("Unable to modify file permissions: {}").format(file))
            continue

        # 读取文件内容
        # Read file content
        with open(file, 'r', errors='ignore') as f:
            content = f.read()

        # 检查文件内容并进行相应修改
        # Check file content and make appropriate modifications
        if 'i.header.set("x-cursor-checksum' in content:
            log_debug(_("Found x-cursor-checksum setting code"))
            new_content = content.replace(
                'i.header.set("x-cursor-checksum",e===void 0?`${p}${t}`:`${p}${t}/${e}`)',
                'i.header.set("x-cursor-checksum",e===void 0?`${p}${t}`:`${p}${t}/${p}`)'
            )
            if new_content != content:
                with open(file, 'w') as f:
                    f.write(new_content)
                log_info(_("Successfully modified x-cursor-checksum setting code"))
                modified_count += 1
            else:
                log_error(_("Failed to modify x-cursor-checksum setting code"))
                shutil.copy(backup_file, file)
        elif "IOPlatformUUID" in content:
            log_debug(_("Found IOPlatformUUID keyword"))
            if "function a$" in content and "return crypto.randomUUID()" not in content:
                new_content = content.replace(
                    "function a$(t){switch",
                    "function a$(t){return crypto.randomUUID(); switch"
                )
                if new_content != content:
                    with open(file, 'w') as f:
                        f.write(new_content)
                    log_debug(_("Successfully injected randomUUID call into a$ function"))
                    modified_count += 1
                else:
                    log_error(_("Failed to modify a$ function"))
                    shutil.copy(backup_file, file)
            elif "async function v5" in content and "return crypto.randomUUID()" not in content:
                new_content = content.replace(
                    "async function v5(t){let e=",
                    "async function v5(t){return crypto.randomUUID(); let e="
                )
                if new_content != content:
                    with open(file, 'w') as f:
                        f.write(new_content)
                    log_debug(_("Successfully injected randomUUID call into v5 function"))
                    modified_count += 1
                else:
                    log_error(_("Failed to modify v5 function"))
                    shutil.copy(backup_file, file)
            else:
                # 通用注入方法
                # Universal injection method
                if "// Cursor ID 修改工具注入" not in content:
                    timestamp = datetime.datetime.now().strftime('%s')
                    datetime_s = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
                    inject_code = f"""
// Cursor ID 修改工具注入 - {datetime_s}
// 随机设备ID生成器注入 - {timestamp}
const randomDeviceId_{timestamp} = () => {{
    try {{
        return require('crypto').randomUUID();
    }} catch (e) {{
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {{
            const r = Math.random() * 16 | 0;
            return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
        }});
    }}
}};
"""
                    # NOTE: double {{ or }} is literal, so code matches:
                    old_bash_inject_code = """
// Cursor ID 修改工具注入 - $(date +%Y%m%d%H%M%S)
// 随机设备ID生成器注入 - $(date +%s)
const randomDeviceId_$(date +%s) = () => {
    try {
        return require('crypto').randomUUID();
    } catch (e) {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
            const r = Math.random() * 16 | 0;
            return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
        });
    }
};
"""
                    new_content = inject_code + content
                    new_content = new_content.replace(f"await v5(!1)", f"randomDeviceId_{timestamp}()")
                    new_content = new_content.replace(f"a$(t)", f"randomDeviceId_{timestamp}()")
                    with open(file, 'w') as f:
                        f.write(new_content)
                    log_debug(_("Completed universal modification"))
                    modified_count += 1
                else:
                    log_info(_("File already contains custom injection code, skipping modification"))
        else:
            # 未找到关键字，尝试通用方法
            # No keywords found, try universal method
            if "return crypto.randomUUID()" not in content and "// Cursor ID 修改工具注入" not in content:
                if "function t$()" in content or "async function y5" in content:
                    new_content = content
                    if "function t$()" in new_content:
                        new_content = new_content.replace(
                            "function t$(){",
                            'function t$(){return "00:00:00:00:00:00";'
                        )
                    if "async function y5" in new_content:
                        new_content = new_content.replace(
                            "async function y5(t){",
                            "async function y5(t){return crypto.randomUUID();"
                        )
                    if new_content != content:
                        with open(file, 'w') as f:
                            f.write(new_content)
                        modified_count += 1
                else:
                    # 最通用的注入方法
                    # Most universal injection method
                    new_uuid = generate_uuid()
                    machine_id = f"auth0|user_{hashlib.sha256(os.urandom(16)).hexdigest()[:32]}"
                    device_id = generate_uuid()
                    mac_machine_id = hashlib.sha256(os.urandom(32)).hexdigest()
                    timestamp = datetime.datetime.now().strftime('%s')
                    datetime_s = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
                    inject_universal_code = f"""
// Cursor ID 修改工具注入 - {datetime_s}
// 全局拦截设备标识符 - {timestamp}
const originalRequire_{timestamp} = require;
require = function(module) {{
    const result = originalRequire_{timestamp}(module);
    if (module === 'crypto' && result.randomUUID) {{
        const originalRandomUUID_{timestamp} = result.randomUUID;
        result.randomUUID = function() {{
            return '{new_uuid}';
        }};
    }}
    return result;
}};

// 覆盖所有可能的系统ID获取函数
global.getMachineId = function() {{ return '{machine_id}'; }};
global.getDeviceId = function() {{ return '{device_id}'; }};
global.macMachineId = '{mac_machine_id}';
"""
                    # NOTE: Double {{ or }} is literal, so matches:
                    old_bash_inject_code = """
// Cursor ID 修改工具注入 - $(date +%Y%m%d%H%M%S)
// 全局拦截设备标识符 - $(date +%s)
const originalRequire_$(date +%s) = require;
require = function(module) {
    const result = originalRequire_$(date +%s)(module);
    if (module === 'crypto' && result.randomUUID) {
        const originalRandomUUID_$(date +%s) = result.randomUUID;
        result.randomUUID = function() {
            return '$new_uuid';
        };
    }
    return result;
};

// 覆盖所有可能的系统ID获取函数
global.getMachineId = function() { return '$machine_id'; };
global.getDeviceId = function() { return '$device_id'; };
global.macMachineId = '$mac_machine_id';
"""
                    new_content = inject_universal_code + content
                    with open(file, 'w') as f:
                        f.write(new_content)
                    log_debug(_("Completed most universal injection"))
                    modified_count += 1
            else:
                log_info(_("File has already been modified, skipping modification"))

        # 恢复文件权限
        # Restore file permissions
        os.chmod(file, 0o444)

    if modified_count == 0:
        log_error(_("Failed to modify any JS files"))
        return False

    log_info(_("Successfully modified {} JS files").format(modified_count))
    return True

# 获取网络接口列表
# Get network interface list
def get_network_interfaces():
    global _
    if NETIFACES_AVAILABLE:
        try:
            # 使用netifaces库
            # Use netifaces library
            interfaces = netifaces.interfaces()
            # 过滤掉回环接口
            # Filter out loopback interfaces
            return [iface for iface in interfaces if not iface.startswith('lo')]
        except Exception:
            pass

    # 如果netifaces不可用或失败，使用系统命令
    # If netifaces is not available or failed, use system commands
    try:
        result = subprocess.run(['ip', 'link', 'show'], capture_output=True, text=True)
        interfaces = []
        for line in result.stdout.split('\n'):
            if ': ' in line and 'state' in line.lower():
                iface_name = line.split(': ')[1].split('@')[0]
                if not iface_name.startswith('lo'):
                    interfaces.append(iface_name)
        return interfaces
    except subprocess.CalledProcessError:
        # 最后的备选方案
        # Last fallback option
        try:
            result = subprocess.run(['ls', '/sys/class/net/'], capture_output=True, text=True)
            interfaces = result.stdout.strip().split('\n')
            return [iface for iface in interfaces if not iface.startswith('lo')]
        except subprocess.CalledProcessError:
            log_error(_("Unable to get network interface list"))
            return []

# 生成随机MAC地址
# Generate random MAC address
def generate_random_mac():
    global _
    # 生成随机MAC地址，确保第一个字节的最低位为0（单播地址）
    # Generate random MAC address, ensure the lowest bit of first byte is 0 (unicast address)
    mac = [0x00, 0x16, 0x3e,
           random.randint(0x00, 0x7f),
           random.randint(0x00, 0xff),
           random.randint(0x00, 0xff)]
    return ':'.join(map(lambda x: "%02x" % x, mac))

# 获取当前MAC地址
# Get current MAC address
def get_current_mac(interface):
    global _
    if NETIFACES_AVAILABLE:
        try:
            # 使用netifaces库
            # Use netifaces library
            addrs = netifaces.ifaddresses(interface)
            if netifaces.AF_LINK in addrs:
                return addrs[netifaces.AF_LINK][0]['addr']
        except Exception:
            pass

    # 使用系统命令获取MAC地址
    # Use system command to get MAC address
    try:
        result = subprocess.run(['cat', f'/sys/class/net/{interface}/address'],
                              capture_output=True, text=True)
        if result.returncode == 0:
            return result.stdout.strip()
    except subprocess.CalledProcessError:
        pass

    # 备选方案：使用ip命令
    # Fallback: use ip command
    try:
        result = subprocess.run(['ip', 'link', 'show', interface],
                              capture_output=True, text=True)
        for line in result.stdout.split('\n'):
            if 'link/ether' in line:
                return line.split()[1]
    except subprocess.CalledProcessError:
        pass

    return None

# 修改MAC地址
# Modify MAC address
def modify_mac_address():
    global _
    log_info(_("Starting MAC address modification..."))

    # 获取网络接口列表
    # Get network interface list
    interfaces = get_network_interfaces()
    if not interfaces:
        log_error(_("No network interfaces found"))
        return False

    log_info(_("Found network interfaces: {}").format(', '.join(interfaces)))

    # 选择要修改的接口（通常选择第一个非回环接口）
    # Select interface to modify (usually the first non-loopback interface)
    target_interface = None
    for iface in interfaces:
        # 优先选择以太网接口
        # Prefer ethernet interfaces
        if any(prefix in iface.lower() for prefix in ['eth', 'enp', 'ens', 'enx']):
            target_interface = iface
            break

    # 如果没有找到以太网接口，选择第一个可用接口
    # If no ethernet interface found, select first available interface
    if not target_interface and interfaces:
        target_interface = interfaces[0]

    if not target_interface:
        log_error(_("No suitable network interface found"))
        return False

    log_info(_("Selected network interface: {}").format(target_interface))

    # 获取当前MAC地址
    # Get current MAC address
    current_mac = get_current_mac(target_interface)
    if current_mac:
        log_info(_("Current MAC address: {}").format(current_mac))

        # 备份当前MAC地址
        # Backup current MAC address
        backup_file = os.path.join(BACKUP_DIR, f"original_mac_{target_interface}.txt")
        try:
            os.makedirs(BACKUP_DIR, exist_ok=True)
            with open(backup_file, 'w') as f:
                f.write(f"{target_interface}:{current_mac}\n")
            log_info(_("Original MAC address backed up to: {}").format(backup_file))
        except OSError:
            log_warn(_("Failed to backup original MAC address"))
    else:
        log_warn(_("Unable to get current MAC address"))

    # 生成新的MAC地址
    # Generate new MAC address
    new_mac = generate_random_mac()
    log_info(_("Generated new MAC address: {}").format(new_mac))

    # 修改MAC地址
    # Modify MAC address
    success = False

    # 方法1：使用ip命令
    # Method 1: Use ip command
    try:
        log_debug(_("Attempting to modify MAC address using ip command..."))

        # 先关闭接口
        # First bring down the interface
        subprocess.run(['ip', 'link', 'set', 'dev', target_interface, 'down'],
                      check=True, capture_output=True)

        # 修改MAC地址
        # Modify MAC address
        subprocess.run(['ip', 'link', 'set', 'dev', target_interface, 'address', new_mac],
                      check=True, capture_output=True)

        # 重新启用接口
        # Bring up the interface
        subprocess.run(['ip', 'link', 'set', 'dev', target_interface, 'up'],
                      check=True, capture_output=True)

        success = True
        log_info(_("Successfully modified MAC address using ip command"))

    except subprocess.CalledProcessError as e:
        log_warn(_("Failed to modify MAC address using ip command: {}").format(str(e)))

    # 方法2：使用ifconfig命令（备选方案）
    # Method 2: Use ifconfig command (fallback)
    if not success:
        try:
            log_debug(_("Attempting to modify MAC address using ifconfig command..."))

            # 先关闭接口
            # First bring down the interface
            subprocess.run(['ifconfig', target_interface, 'down'],
                          check=True, capture_output=True)

            # 修改MAC地址
            # Modify MAC address
            subprocess.run(['ifconfig', target_interface, 'hw', 'ether', new_mac],
                          check=True, capture_output=True)

            # 重新启用接口
            # Bring up the interface
            subprocess.run(['ifconfig', target_interface, 'up'],
                          check=True, capture_output=True)

            success = True
            log_info(_("Successfully modified MAC address using ifconfig command"))

        except subprocess.CalledProcessError as e:
            log_warn(_("Failed to modify MAC address using ifconfig command: {}").format(str(e)))

    # 验证MAC地址修改
    # Verify MAC address modification
    if success:
        time.sleep(2)  # 等待网络接口稳定
        # Wait for network interface to stabilize

        new_current_mac = get_current_mac(target_interface)
        if new_current_mac and new_current_mac.lower() == new_mac.lower():
            log_info(_("MAC address modification verified successfully"))
            log_info(_("New MAC address: {}").format(new_current_mac))

            # 保存新MAC地址信息
            # Save new MAC address information
            new_mac_file = os.path.join(BACKUP_DIR, f"new_mac_{target_interface}.txt")
            try:
                with open(new_mac_file, 'w') as f:
                    f.write(f"{target_interface}:{new_current_mac}\n")
                    f.write(f"Modified at: {datetime.datetime.now()}\n")
                log_info(_("New MAC address information saved to: {}").format(new_mac_file))
            except OSError:
                log_warn(_("Failed to save new MAC address information"))

            return True
        else:
            log_error(_("MAC address modification verification failed"))
            log_error(_("Expected: {}, Actual: {}").format(new_mac, new_current_mac))
            return False
    else:
        log_error(_("All MAC address modification methods failed"))
        log_error(_("Please check if you have sufficient permissions or try running with sudo"))
        return False

# 禁用自动更新
# Disable auto-update
def disable_auto_update():
    global _
    log_info(_("Disabling Cursor auto-update..."))

    # 查找可能的更新配置文件
    # Find possible update configuration files
    update_configs = [
        os.path.join(CURSOR_CONFIG_DIR, "update-config.json"),
        os.path.expanduser("~/.local/share/cursor/update-config.json"),
        "/opt/cursor/resources/app-update.yml",
    ]

    disabled = False

    for config in update_configs:
        if os.path.isfile(config):
            log_info(_("Found update configuration file: {}").format(config))
            try:
                shutil.copy(config, f"{config}.bak")
                with open(config, 'w') as f:
                    json.dump({"autoCheck": False, "autoDownload": False}, f)
                os.chmod(config, 0o444)
                log_info(_("Disabled update configuration file: {}").format(config))
                disabled = True
            except (OSError, shutil.Error):
                continue

    # 尝试查找updater可执行文件并禁用
    # Try to find and disable updater executable
    updater_paths = [
        os.path.join(CURSOR_CONFIG_DIR, "updater"),
        "/opt/cursor/updater",
        "/usr/lib/cursor/updater",
    ]

    for updater in updater_paths:
        if os.path.exists(updater):
            log_info(_("Found updater: {}").format(updater))
            try:
                if os.path.isfile(updater):
                    shutil.move(updater, f"{updater}.bak")
                else:
                    Path(f"{updater}.disabled").touch()
                log_info(_("Disabled updater: {}").format(updater))
                disabled = True
            except (OSError, shutil.Error):
                continue

    if not disabled:
        log_warn(_("No update configuration files or updaters found"))
    else:
        log_info(_("Successfully disabled auto-update"))

# 新增：通用菜单选择函数
# New: Universal menu selection function
def select_menu_option(prompt, options, default_index=0):
    global _
    # 保存终端设置
    # Save terminal settings
    old_settings = termios.tcgetattr(sys.stdin)
    selected_index = default_index

    try:
        # 设置终端为非缓冲模式
        # Set terminal to non-buffered mode
        tty.setcbreak(sys.stdin.fileno())

        # 显示提示信息
        # Display prompt
        print(_(prompt))

        # 第一次显示菜单
        # Display menu initially
        for i, option in enumerate(options):
            if i == selected_index:
                print(f" {GREEN}►{NC} {_(option)}")
            else:
                print(f"   {_(option)}")

        while True:
            # 读取键盘输入
            # Read keyboard input
            rlist, _1, _2 = select.select([sys.stdin], [], [], 0.1)
            if rlist:
                key = sys.stdin.read(1)
                # 上箭头键
                # Up arrow key
                if key == '\033':
                    next_char = sys.stdin.read(2)
                    if next_char == '[A' and selected_index > 0:
                        selected_index -= 1
                    # 下箭头键
                    # Down arrow key
                    elif next_char == '[B' and selected_index < len(options) - 1:
                        selected_index += 1
                # Enter键
                # Enter key
                elif key == '\n':
                    print()
                    log_info(_("You selected: {}").format(options[selected_index]))
                    return selected_index

                # 清除当前菜单
                # Clear current menu
                sys.stdout.write('\033[{}A\033[J'.format(len(options) + 1))
                sys.stdout.flush()

                # 重新显示提示和菜单
                # Redisplay prompt and menu
                print(_(prompt))
                for i, option in enumerate(options):
                    if i == selected_index:
                        print(f" {GREEN}►{NC} {_(option)}")
                    else:
                        print(f"   {_(option)}")
                sys.stdout.flush()

    finally:
        # 恢复终端设置
        # Restore terminal settings
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)

# 主函数
# Main function
def main():
    global _
    # 检查系统环境
    # Check system environment
    if sys.platform != "linux":
        log_error(_("This script only supports Linux systems"))
        sys.exit(1)

    # 初始化日志文件
    # Initialize log file
    initialize_log()
    log_info(_("Script started..."))

    # 记录系统信息
    # Log system information
    log_info(_("System information: {}").format(subprocess.getoutput("uname -a")))
    log_info(_("Current user: {}").format(CURRENT_USER))
    log_cmd_output(
        "lsb_release -a 2>/dev/null || cat /etc/*release 2>/dev/null || cat /etc/issue",
        _("System version information")
    )

    # 清除终端
    # Clear terminal
    os.system('clear')

    # 显示 Logo
    # Display Logo
    print("""
    ██████╗██╗   ██╗██████╗ ███████╗ ██████╗ ██████╗
   ██╔════╝██║   ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗
   ██║     ██║   ██║██████╔╝███████╗██║   ██║██████╔╝
   ██║     ██║   ██║██╔══██╗╚════██║██║   ██║██╔══██╗
   ╚██████╗╚██████╔╝██║  ██║███████║╚██████╔╝██║  ██║
    ╚═════╝ ╚═════╝ ╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝  ╚═╝
    """)
    print(f"{BLUE}================================{NC}")
    print(f"{GREEN}   {_('Cursor Linux startup tool')}     {NC}")
    print(f"{BLUE}================================{NC}")
    print()
    print(f"{YELLOW}[{_('Important notice')}] {NC} {_('This tool prioritizes modifying JS files, which is safer and more reliable')}")
    print()

    # 执行主要功能
    # Execute main functions
    check_permissions()
    find_cursor_path()
    find_cursor_resources()
    check_and_kill_cursor()
    backup_config()
    generate_new_config()

    # 修改JS文件
    # Modify JS files
    log_info(_("Modifying Cursor JS files..."))
    js_success = modify_cursor_js_files()
    if js_success:
        log_info(_("JS files modified successfully!"))
    else:
        log_warn(_("JS file modification failed, but configuration file modification may have succeeded"))
        log_warn(_("If Cursor still indicates the device is disabled after restarting, please rerun this script"))

    # 修改MAC地址
    # Modify MAC address
    log_info(_("Modifying system MAC address..."))
    mac_success = modify_mac_address()
    if mac_success:
        log_info(_("MAC address modified successfully!"))
    else:
        log_warn(_("MAC address modification failed"))
        log_warn(_("This may affect the effectiveness of device identification bypass"))

    # 禁用自动更新
    # Disable auto-update
    disable_auto_update()

    # 显示修改结果总结
    # Display modification result summary
    print()
    print(f"{GREEN}================================{NC}")
    print(f"{BLUE}   {_('Modification Results Summary')}     {NC}")
    print(f"{GREEN}================================{NC}")

    if js_success:
        print(f"{GREEN}✓{NC} {_('JS files modification: SUCCESS')}")
    else:
        print(f"{RED}✗{NC} {_('JS files modification: FAILED')}")

    if mac_success:
        print(f"{GREEN}✓{NC} {_('MAC address modification: SUCCESS')}")
    else:
        print(f"{RED}✗{NC} {_('MAC address modification: FAILED')}")

    print(f"{GREEN}================================{NC}")
    print()

    log_info(_("Please restart Cursor to apply the new configuration"))

    # 显示最后的提示信息
    # Display final prompt
    print()
    print(f"{GREEN}================================{NC}")
    print(f"{YELLOW} {_('Follow the WeChat public account [Pancake AI] to discuss more Cursor tips and AI knowledge (script is free, join the group via the public account for more tips and experts)')} {NC}")
    print("WeChat account: [煎饼果子卷AI]")
    print(f"{GREEN}================================{NC}")
    print()

    # 记录脚本完成信息
    # Log script completion information
    log_info(_("Script execution completed"))
    with open(LOG_FILE, 'a') as f:
        f.write(_("========== Cursor ID modification tool log end {} ==========").format(datetime.datetime.now()) + "\n")

    # 显示日志文件位置
    # Display log file location
    print()
    log_info(_("Detailed log saved to: {}").format(LOG_FILE))
    print(_("If you encounter issues, please provide this log file to the developer for troubleshooting"))
    print()

if __name__ == "__main__":
    main()