mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-04-24 08:25:23 +00:00
feat: Enhance Multilingual Support and System Language Detection
- Add automatic system language detection for Windows and Unix-like systems - Update localization files with new translation keys - Improve language handling in various modules - Translate more UI messages to English - Add GitHub link to logo display - Bump version to 1.4.04
This commit is contained in:
parent
4c91525082
commit
d852bcff50
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,3 +1,8 @@
|
|||||||
cursor_accounts.txt
|
cursor_accounts.txt
|
||||||
/venv
|
/venv
|
||||||
/__pycache__
|
/__pycache__
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
install.bat
|
||||||
|
run.bat
|
||||||
|
temp_account_info.txt
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## v1.4.04
|
||||||
|
|
||||||
|
1. Change Some Language Info to English | 更改一些語言信息為英文
|
||||||
|
2. Add Auto Detect System Language | 增加自動檢測系統語言
|
||||||
|
3. Fixed Some Issues | 修復一些問題
|
||||||
|
|
||||||
|
|
||||||
## v1.4.03
|
## v1.4.03
|
||||||
|
|
||||||
1. Switch to API-based Registration System | 改用API註冊系統替代瀏覽器操作
|
1. Switch to API-based Registration System | 改用API註冊系統替代瀏覽器操作
|
||||||
|
30
build.bat
30
build.bat
@ -2,28 +2,28 @@
|
|||||||
chcp 65001 > nul
|
chcp 65001 > nul
|
||||||
cls
|
cls
|
||||||
|
|
||||||
:: 檢查是否以管理員權限運行
|
:: Check if running with administrator privileges
|
||||||
net session >nul 2>&1
|
net session >nul 2>&1
|
||||||
if %errorLevel% == 0 (
|
if %errorLevel% == 0 (
|
||||||
:: 如果是管理員權限,只創建虛擬環境後就降權運行
|
:: If running with administrator privileges, create virtual environment and then run with normal user privileges
|
||||||
if not exist venv (
|
if not exist venv (
|
||||||
echo ℹ️ 正在創建虛擬環境...
|
echo ℹ️ 正在創建虛擬環境...
|
||||||
python -m venv venv
|
python -m venv venv
|
||||||
)
|
)
|
||||||
|
|
||||||
:: 降權運行剩餘的步驟
|
:: Run remaining steps with normal user privileges
|
||||||
echo ℹ️ 以普通用戶權限繼續...
|
echo ℹ️ 以普通用戶權限繼續...
|
||||||
powershell -Command "Start-Process -FilePath '%comspec%' -ArgumentList '/c cd /d %cd% && %~f0 run' -Verb RunAs:NO"
|
powershell -Command "Start-Process -FilePath '%comspec%' -ArgumentList '/c cd /d %cd% && %~f0 run' -Verb RunAs:NO"
|
||||||
exit /b
|
exit /b
|
||||||
) else (
|
) else (
|
||||||
:: 檢查是否是第二階段運行
|
:: Check if running in second stage
|
||||||
if "%1"=="run" (
|
if "%1"=="run" (
|
||||||
goto RUN_BUILD
|
goto RUN_BUILD
|
||||||
) else (
|
) else (
|
||||||
:: 如果是普通權限且需要創建虛擬環境,請求管理員權限
|
:: If running with normal privileges and creating virtual environment is required, request administrator privileges
|
||||||
if not exist venv (
|
if not exist venv (
|
||||||
echo ⚠️ 需要管理員權限來創建虛擬環境
|
echo ⚠️ Requires administrator privileges to create virtual environment
|
||||||
echo ℹ️ 正在請求管理員權限...
|
echo ℹ️ Requesting administrator privileges...
|
||||||
powershell -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c cd /d %cd% && %~f0'"
|
powershell -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c cd /d %cd% && %~f0'"
|
||||||
exit /b
|
exit /b
|
||||||
) else (
|
) else (
|
||||||
@ -33,30 +33,30 @@ if %errorLevel% == 0 (
|
|||||||
)
|
)
|
||||||
|
|
||||||
:RUN_BUILD
|
:RUN_BUILD
|
||||||
echo ℹ️ 啟動虛擬環境...
|
echo ℹ️ Starting virtual environment...
|
||||||
call venv\Scripts\activate.bat
|
call venv\Scripts\activate.bat
|
||||||
if errorlevel 1 (
|
if errorlevel 1 (
|
||||||
echo ❌ 啟動虛擬環境失敗
|
echo ❌ Failed to start virtual environment
|
||||||
pause
|
pause
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
:: 檢查並安裝缺失的依賴
|
:: Check and install missing dependencies
|
||||||
echo ℹ️ 檢查依賴...
|
echo ℹ️ Checking dependencies...
|
||||||
for /f "tokens=1" %%i in (requirements.txt) do (
|
for /f "tokens=1" %%i in (requirements.txt) do (
|
||||||
pip show %%i >nul 2>&1 || (
|
pip show %%i >nul 2>&1 || (
|
||||||
echo ℹ️ 安裝 %%i...
|
echo ℹ️ Installing %%i...
|
||||||
pip install %%i
|
pip install %%i
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
echo ℹ️ 開始構建...
|
echo ℹ️ Starting build...
|
||||||
python build.py
|
python build.py
|
||||||
if errorlevel 1 (
|
if errorlevel 1 (
|
||||||
echo ❌ 構建失敗
|
echo ❌ Build failed
|
||||||
pause
|
pause
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
echo ✅ 完成!
|
echo ✅ Completed!
|
||||||
pause
|
pause
|
26
build.py
26
build.py
@ -8,7 +8,7 @@ import shutil
|
|||||||
from logo import print_logo
|
from logo import print_logo
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
# 忽略特定警告
|
# Ignore specific warnings
|
||||||
warnings.filterwarnings("ignore", category=SyntaxWarning)
|
warnings.filterwarnings("ignore", category=SyntaxWarning)
|
||||||
|
|
||||||
class LoadingAnimation:
|
class LoadingAnimation:
|
||||||
@ -50,21 +50,21 @@ def simulate_progress(message, duration=1.0, steps=20):
|
|||||||
progress_bar(i, steps, prefix="Progress:", length=40)
|
progress_bar(i, steps, prefix="Progress:", length=40)
|
||||||
|
|
||||||
def build():
|
def build():
|
||||||
# 清理屏幕
|
# Clean screen
|
||||||
os.system("cls" if platform.system().lower() == "windows" else "clear")
|
os.system("cls" if platform.system().lower() == "windows" else "clear")
|
||||||
|
|
||||||
# 顯示 logo
|
# Display logo
|
||||||
print_logo()
|
print_logo()
|
||||||
|
|
||||||
# 清理 PyInstaller 緩存
|
# Clean PyInstaller cache
|
||||||
print("\033[93m🧹 清理構建緩存...\033[0m")
|
print("\033[93m🧹 Cleaning build cache...\033[0m")
|
||||||
if os.path.exists('build'):
|
if os.path.exists('build'):
|
||||||
shutil.rmtree('build')
|
shutil.rmtree('build')
|
||||||
|
|
||||||
# 重新加載環境變量以確保獲取最新版本
|
# Reload environment variables to ensure getting the latest version
|
||||||
load_dotenv(override=True)
|
load_dotenv(override=True)
|
||||||
version = os.getenv('VERSION', '1.0.0')
|
version = os.getenv('VERSION', '1.0.0')
|
||||||
print(f"\033[93m📦 正在構建版本: v{version}\033[0m")
|
print(f"\033[93m📦 Building version: v{version}\033[0m")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
simulate_progress("Preparing build environment...", 0.5)
|
simulate_progress("Preparing build environment...", 0.5)
|
||||||
@ -72,7 +72,7 @@ def build():
|
|||||||
loading = LoadingAnimation()
|
loading = LoadingAnimation()
|
||||||
loading.start("Building in progress")
|
loading.start("Building in progress")
|
||||||
|
|
||||||
# 根据系统类型设置输出名称
|
# Set output name based on system type
|
||||||
system = platform.system().lower()
|
system = platform.system().lower()
|
||||||
if system == "windows":
|
if system == "windows":
|
||||||
os_type = "windows"
|
os_type = "windows"
|
||||||
@ -86,7 +86,7 @@ def build():
|
|||||||
|
|
||||||
output_name = f"CursorFreeVIP_{version}_{os_type}"
|
output_name = f"CursorFreeVIP_{version}_{os_type}"
|
||||||
|
|
||||||
# 构建命令
|
# Build command
|
||||||
build_command = f'pyinstaller --clean --noconfirm build.spec'
|
build_command = f'pyinstaller --clean --noconfirm build.spec'
|
||||||
output_path = os.path.join('dist', f'{output_name}{ext}')
|
output_path = os.path.join('dist', f'{output_name}{ext}')
|
||||||
|
|
||||||
@ -95,16 +95,16 @@ def build():
|
|||||||
loading.stop()
|
loading.stop()
|
||||||
|
|
||||||
if os.path.exists(output_path):
|
if os.path.exists(output_path):
|
||||||
print(f"\n\033[92m✅ 構建完成!")
|
print(f"\n\033[92m✅ Build completed!")
|
||||||
print(f"📦 可執行文件位於: {output_path}\033[0m")
|
print(f"📦 Executable file located: {output_path}\033[0m")
|
||||||
else:
|
else:
|
||||||
print("\n\033[91m❌ 構建失敗:未找到輸出文件\033[0m")
|
print("\n\033[91m❌ Build failed: Output file not found\033[0m")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if loading:
|
if loading:
|
||||||
loading.stop()
|
loading.stop()
|
||||||
print(f"\n\033[91m❌ 構建過程出錯: {str(e)}\033[0m")
|
print(f"\n\033[91m❌ Build process error: {str(e)}\033[0m")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
20
build.sh
20
build.sh
@ -8,7 +8,7 @@ NC='\033[0m' # No Color
|
|||||||
|
|
||||||
# 检查并安装必要的依赖
|
# 检查并安装必要的依赖
|
||||||
check_dependencies() {
|
check_dependencies() {
|
||||||
echo -e "${YELLOW}检查系统依赖...${NC}"
|
echo -e "${YELLOW}Checking system dependencies...${NC}"
|
||||||
|
|
||||||
# 检查是否为 Ubuntu/Debian
|
# 检查是否为 Ubuntu/Debian
|
||||||
if [ -f /etc/debian_version ]; then
|
if [ -f /etc/debian_version ]; then
|
||||||
@ -16,42 +16,42 @@ check_dependencies() {
|
|||||||
PACKAGES="python3 python3-pip python3-venv"
|
PACKAGES="python3 python3-pip python3-venv"
|
||||||
for pkg in $PACKAGES; do
|
for pkg in $PACKAGES; do
|
||||||
if ! dpkg -l | grep -q "^ii $pkg "; then
|
if ! dpkg -l | grep -q "^ii $pkg "; then
|
||||||
echo -e "${YELLOW}安装 $pkg...${NC}"
|
echo -e "${YELLOW}Installing $pkg...${NC}"
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y $pkg
|
sudo apt-get install -y $pkg
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
echo -e "${RED}不支持的系统,请手动安装 python3, pip3 和 python3-venv${NC}"
|
echo -e "${RED}Unsupported system, please install python3, pip3 and python3-venv manually${NC}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# 创建并激活虚拟环境
|
# 创建并激活虚拟环境
|
||||||
setup_venv() {
|
setup_venv() {
|
||||||
echo -e "${GREEN}正在创建虚拟环境...${NC}"
|
echo -e "${GREEN}Creating virtual environment...${NC}"
|
||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
|
|
||||||
echo -e "${GREEN}启动虚拟环境...${NC}"
|
echo -e "${GREEN}Starting virtual environment...${NC}"
|
||||||
. ./venv/bin/activate || source ./venv/bin/activate
|
. ./venv/bin/activate || source ./venv/bin/activate
|
||||||
}
|
}
|
||||||
|
|
||||||
# 安装依赖
|
# 安装依赖
|
||||||
install_dependencies() {
|
install_dependencies() {
|
||||||
echo -e "${GREEN}安装依赖...${NC}"
|
echo -e "${GREEN}Installing dependencies...${NC}"
|
||||||
python3 -m pip install --upgrade pip
|
python3 -m pip install --upgrade pip
|
||||||
pip3 install -r requirements.txt
|
pip3 install -r requirements.txt
|
||||||
}
|
}
|
||||||
|
|
||||||
# 构建程序
|
# 构建程序
|
||||||
build_program() {
|
build_program() {
|
||||||
echo -e "${GREEN}开始构建...${NC}"
|
echo -e "${GREEN}Starting build...${NC}"
|
||||||
python3 build.py
|
python3 build.py
|
||||||
}
|
}
|
||||||
|
|
||||||
# 清理
|
# 清理
|
||||||
cleanup() {
|
cleanup() {
|
||||||
echo -e "${GREEN}清理虚拟环境...${NC}"
|
echo -e "${GREEN}Cleaning virtual environment...${NC}"
|
||||||
deactivate 2>/dev/null || true
|
deactivate 2>/dev/null || true
|
||||||
rm -rf venv
|
rm -rf venv
|
||||||
}
|
}
|
||||||
@ -73,8 +73,8 @@ main() {
|
|||||||
# 清理
|
# 清理
|
||||||
cleanup
|
cleanup
|
||||||
|
|
||||||
echo -e "${GREEN}完成!${NC}"
|
echo -e "${GREEN}Completed!${NC}"
|
||||||
echo "按任意键退出..."
|
echo "Press any key to exit..."
|
||||||
# 使用兼容的方式读取输入
|
# 使用兼容的方式读取输入
|
||||||
if [ "$(uname)" = "Linux" ]; then
|
if [ "$(uname)" = "Linux" ]; then
|
||||||
read dummy
|
read dummy
|
||||||
|
@ -10,10 +10,10 @@ from reset_machine_manual import MachineIDResetter
|
|||||||
os.environ["PYTHONVERBOSE"] = "0"
|
os.environ["PYTHONVERBOSE"] = "0"
|
||||||
os.environ["PYINSTALLER_VERBOSE"] = "0"
|
os.environ["PYINSTALLER_VERBOSE"] = "0"
|
||||||
|
|
||||||
# 初始化colorama
|
# Initialize colorama
|
||||||
init()
|
init()
|
||||||
|
|
||||||
# 定义emoji常量
|
# Define emoji constants
|
||||||
EMOJI = {
|
EMOJI = {
|
||||||
'START': '🚀',
|
'START': '🚀',
|
||||||
'FORM': '📝',
|
'FORM': '📝',
|
||||||
@ -33,7 +33,7 @@ EMOJI = {
|
|||||||
class CursorRegistration:
|
class CursorRegistration:
|
||||||
def __init__(self, translator=None):
|
def __init__(self, translator=None):
|
||||||
self.translator = translator
|
self.translator = translator
|
||||||
# 设置为显示模式
|
# Set to display mode
|
||||||
os.environ['BROWSER_HEADLESS'] = 'False'
|
os.environ['BROWSER_HEADLESS'] = 'False'
|
||||||
self.browser_manager = BrowserManager()
|
self.browser_manager = BrowserManager()
|
||||||
self.browser = None
|
self.browser = None
|
||||||
@ -44,7 +44,7 @@ class CursorRegistration:
|
|||||||
self.signup_tab = None
|
self.signup_tab = None
|
||||||
self.email_tab = None
|
self.email_tab = None
|
||||||
|
|
||||||
# 账号信息
|
# Account information
|
||||||
self.password = self._generate_password()
|
self.password = self._generate_password()
|
||||||
self.first_name = self._generate_name()
|
self.first_name = self._generate_name()
|
||||||
self.last_name = self._generate_name()
|
self.last_name = self._generate_name()
|
||||||
@ -61,9 +61,9 @@ class CursorRegistration:
|
|||||||
return first_letter + rest_letters
|
return first_letter + rest_letters
|
||||||
|
|
||||||
def setup_email(self):
|
def setup_email(self):
|
||||||
"""设置邮箱"""
|
"""Setup Email"""
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.manual_email_input') if self.translator else '请输入邮箱地址:'}")
|
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.manual_email_input') if self.translator else 'Please enter your email address:'}")
|
||||||
self.email_address = input().strip()
|
self.email_address = input().strip()
|
||||||
|
|
||||||
if '@' not in self.email_address:
|
if '@' not in self.email_address:
|
||||||
@ -77,9 +77,9 @@ class CursorRegistration:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def get_verification_code(self):
|
def get_verification_code(self):
|
||||||
"""手动获取验证码"""
|
"""Manually Get Verification Code"""
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['CODE']} {self.translator.get('register.manual_code_input') if self.translator else '请输入验证码:'}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['CODE']} {self.translator.get('register.manual_code_input') if self.translator else 'Please enter the verification code:'}")
|
||||||
code = input().strip()
|
code = input().strip()
|
||||||
|
|
||||||
if not code.isdigit() or len(code) != 6:
|
if not code.isdigit() or len(code) != 6:
|
||||||
@ -93,31 +93,31 @@ class CursorRegistration:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def register_cursor(self):
|
def register_cursor(self):
|
||||||
"""注册 Cursor"""
|
"""Register Cursor"""
|
||||||
browser_tab = None
|
browser_tab = None
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.register_start')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.register_start')}...{Style.RESET_ALL}")
|
||||||
|
|
||||||
# 直接使用 new_signup.py 进行注册
|
# Use new_signup.py directly for registration
|
||||||
from new_signup import main as new_signup_main
|
from new_signup import main as new_signup_main
|
||||||
|
|
||||||
# 执行新的注册流程,传入 translator
|
# Execute new registration process, passing translator
|
||||||
result, browser_tab = new_signup_main(
|
result, browser_tab = new_signup_main(
|
||||||
email=self.email_address,
|
email=self.email_address,
|
||||||
password=self.password,
|
password=self.password,
|
||||||
first_name=self.first_name,
|
first_name=self.first_name,
|
||||||
last_name=self.last_name,
|
last_name=self.last_name,
|
||||||
email_tab=None, # 不需要邮箱标签页
|
email_tab=None, # No email tab needed
|
||||||
controller=self, # 传入 self 而不是 self.controller
|
controller=self, # Pass self instead of self.controller
|
||||||
translator=self.translator
|
translator=self.translator
|
||||||
)
|
)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
# 使用返回的浏览器实例获取账户信息
|
# Use the returned browser instance to get account information
|
||||||
self.signup_tab = browser_tab # 保存浏览器实例
|
self.signup_tab = browser_tab # Save browser instance
|
||||||
success = self._get_account_info()
|
success = self._get_account_info()
|
||||||
|
|
||||||
# 获取信息后关闭浏览器
|
# Close browser after getting information
|
||||||
if browser_tab:
|
if browser_tab:
|
||||||
try:
|
try:
|
||||||
browser_tab.quit()
|
browser_tab.quit()
|
||||||
@ -132,7 +132,7 @@ class CursorRegistration:
|
|||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.register_process_error', error=str(e))}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.register_process_error', error=str(e))}{Style.RESET_ALL}")
|
||||||
return False
|
return False
|
||||||
finally:
|
finally:
|
||||||
# 确保在任何情况下都关闭浏览器
|
# Ensure browser is closed in any case
|
||||||
if browser_tab:
|
if browser_tab:
|
||||||
try:
|
try:
|
||||||
browser_tab.quit()
|
browser_tab.quit()
|
||||||
@ -140,7 +140,7 @@ class CursorRegistration:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def _get_account_info(self):
|
def _get_account_info(self):
|
||||||
"""获取账户信息和 Token"""
|
"""Get Account Information and Token"""
|
||||||
try:
|
try:
|
||||||
self.signup_tab.get(self.settings_url)
|
self.signup_tab.get(self.settings_url)
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
@ -191,22 +191,22 @@ class CursorRegistration:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def _save_account_info(self, token, total_usage):
|
def _save_account_info(self, token, total_usage):
|
||||||
"""保存账户信息到文件"""
|
"""Save Account Information to File"""
|
||||||
try:
|
try:
|
||||||
# 先更新认证信息
|
# Update authentication information first
|
||||||
print(f"{Fore.CYAN}{EMOJI['KEY']} {self.translator.get('register.update_cursor_auth_info')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['KEY']} {self.translator.get('register.update_cursor_auth_info')}...{Style.RESET_ALL}")
|
||||||
if self.update_cursor_auth(email=self.email_address, access_token=token, refresh_token=token):
|
if self.update_cursor_auth(email=self.email_address, access_token=token, refresh_token=token):
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.cursor_auth_info_updated')}...{Style.RESET_ALL}")
|
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.cursor_auth_info_updated')}...{Style.RESET_ALL}")
|
||||||
else:
|
else:
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.cursor_auth_info_update_failed')}...{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.cursor_auth_info_update_failed')}...{Style.RESET_ALL}")
|
||||||
|
|
||||||
# 重置机器ID
|
# Reset machine ID
|
||||||
print(f"{Fore.CYAN}{EMOJI['UPDATE']} {self.translator.get('register.reset_machine_id')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['UPDATE']} {self.translator.get('register.reset_machine_id')}...{Style.RESET_ALL}")
|
||||||
resetter = MachineIDResetter(self.translator) # 创建实例时传入translator
|
resetter = MachineIDResetter(self.translator) # Create instance with translator
|
||||||
if not resetter.reset_machine_ids(): # 直接调用reset_machine_ids方法
|
if not resetter.reset_machine_ids(): # Call reset_machine_ids method directly
|
||||||
raise Exception("Failed to reset machine ID")
|
raise Exception("Failed to reset machine ID")
|
||||||
|
|
||||||
# 保存账户信息到文件
|
# Save account information to file
|
||||||
with open('cursor_accounts.txt', 'a', encoding='utf-8') as f:
|
with open('cursor_accounts.txt', 'a', encoding='utf-8') as f:
|
||||||
f.write(f"\n{'='*50}\n")
|
f.write(f"\n{'='*50}\n")
|
||||||
f.write(f"Email: {self.email_address}\n")
|
f.write(f"Email: {self.email_address}\n")
|
||||||
@ -223,7 +223,7 @@ class CursorRegistration:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""启动注册流程"""
|
"""Start Registration Process"""
|
||||||
try:
|
try:
|
||||||
if self.setup_email():
|
if self.setup_email():
|
||||||
if self.register_cursor():
|
if self.register_cursor():
|
||||||
@ -231,7 +231,7 @@ class CursorRegistration:
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
finally:
|
finally:
|
||||||
# 关闭邮箱标签页
|
# Close email tab
|
||||||
if hasattr(self, 'temp_email'):
|
if hasattr(self, 'temp_email'):
|
||||||
try:
|
try:
|
||||||
self.temp_email.close()
|
self.temp_email.close()
|
||||||
@ -239,7 +239,7 @@ class CursorRegistration:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def update_cursor_auth(self, email=None, access_token=None, refresh_token=None):
|
def update_cursor_auth(self, email=None, access_token=None, refresh_token=None):
|
||||||
"""更新Cursor的认证信息的便捷函数"""
|
"""Convenient function to update Cursor authentication information"""
|
||||||
auth_manager = CursorAuth(translator=self.translator)
|
auth_manager = CursorAuth(translator=self.translator)
|
||||||
return auth_manager.update_auth(email, access_token, refresh_token)
|
return auth_manager.update_auth(email, access_token, refresh_token)
|
||||||
|
|
||||||
|
@ -5,10 +5,10 @@ import shutil
|
|||||||
from colorama import Fore, Style, init
|
from colorama import Fore, Style, init
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
# 初始化 colorama
|
# Initialize colorama
|
||||||
init()
|
init()
|
||||||
|
|
||||||
# 定义 emoji 常量
|
# Define emoji constants
|
||||||
EMOJI = {
|
EMOJI = {
|
||||||
"PROCESS": "🔄",
|
"PROCESS": "🔄",
|
||||||
"SUCCESS": "✅",
|
"SUCCESS": "✅",
|
||||||
@ -31,7 +31,7 @@ class AutoUpdateDisabler:
|
|||||||
}
|
}
|
||||||
|
|
||||||
def _kill_cursor_processes(self):
|
def _kill_cursor_processes(self):
|
||||||
"""结束所有 Cursor 进程"""
|
"""End all Cursor processes"""
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['PROCESS']} {self.translator.get('update.killing_processes') if self.translator else '正在结束 Cursor 进程...'}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['PROCESS']} {self.translator.get('update.killing_processes') if self.translator else '正在结束 Cursor 进程...'}{Style.RESET_ALL}")
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ class AutoUpdateDisabler:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def _remove_updater_directory(self):
|
def _remove_updater_directory(self):
|
||||||
"""删除更新程序目录"""
|
"""Delete updater directory"""
|
||||||
try:
|
try:
|
||||||
updater_path = self.updater_paths.get(self.system)
|
updater_path = self.updater_paths.get(self.system)
|
||||||
if not updater_path:
|
if not updater_path:
|
||||||
@ -70,7 +70,7 @@ class AutoUpdateDisabler:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def _create_blocking_file(self):
|
def _create_blocking_file(self):
|
||||||
"""创建阻止文件"""
|
"""Create blocking file"""
|
||||||
try:
|
try:
|
||||||
updater_path = self.updater_paths.get(self.system)
|
updater_path = self.updater_paths.get(self.system)
|
||||||
if not updater_path:
|
if not updater_path:
|
||||||
@ -78,14 +78,14 @@ class AutoUpdateDisabler:
|
|||||||
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('update.creating_block_file') if self.translator else '正在创建阻止文件...'}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('update.creating_block_file') if self.translator else '正在创建阻止文件...'}{Style.RESET_ALL}")
|
||||||
|
|
||||||
# 创建空文件
|
# Create empty file
|
||||||
open(updater_path, 'w').close()
|
open(updater_path, 'w').close()
|
||||||
|
|
||||||
# 设置只读属性
|
# Set read-only attribute
|
||||||
if self.system == "Windows":
|
if self.system == "Windows":
|
||||||
os.system(f'attrib +r "{updater_path}"')
|
os.system(f'attrib +r "{updater_path}"')
|
||||||
else:
|
else:
|
||||||
os.chmod(updater_path, 0o444) # 设置为只读
|
os.chmod(updater_path, 0o444) # Set to read-only
|
||||||
|
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('update.block_file_created') if self.translator else '阻止文件已创建'}{Style.RESET_ALL}")
|
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('update.block_file_created') if self.translator else '阻止文件已创建'}{Style.RESET_ALL}")
|
||||||
return True
|
return True
|
||||||
@ -95,19 +95,19 @@ class AutoUpdateDisabler:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def disable_auto_update(self):
|
def disable_auto_update(self):
|
||||||
"""禁用自动更新"""
|
"""Disable auto update"""
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('update.start_disable') if self.translator else '开始禁用自动更新...'}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('update.start_disable') if self.translator else '开始禁用自动更新...'}{Style.RESET_ALL}")
|
||||||
|
|
||||||
# 1. 结束进程
|
# 1. End processes
|
||||||
if not self._kill_cursor_processes():
|
if not self._kill_cursor_processes():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 2. 删除目录
|
# 2. Delete directory
|
||||||
if not self._remove_updater_directory():
|
if not self._remove_updater_directory():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 3. 创建阻止文件
|
# 3. Create blocking file
|
||||||
if not self._create_blocking_file():
|
if not self._create_blocking_file():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -119,16 +119,16 @@ class AutoUpdateDisabler:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def run(translator=None):
|
def run(translator=None):
|
||||||
"""便捷函数,用于直接调用禁用功能"""
|
"""Convenient function for directly calling the disable function"""
|
||||||
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||||
print(f"{Fore.CYAN}{EMOJI['STOP']} {translator.get('update.title') if translator else '禁用 Cursor 自动更新'}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['STOP']} {translator.get('update.title') if translator else 'Disable Cursor Auto Update'}{Style.RESET_ALL}")
|
||||||
print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||||
|
|
||||||
disabler = AutoUpdateDisabler(translator)
|
disabler = AutoUpdateDisabler(translator)
|
||||||
disabler.disable_auto_update()
|
disabler.disable_auto_update()
|
||||||
|
|
||||||
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||||
input(f"{EMOJI['INFO']} {translator.get('update.press_enter') if translator else '按回车键继续...'}")
|
input(f"{EMOJI['INFO']} {translator.get('update.press_enter') if translator else 'Press Enter to Continue...'}")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from main import translator as main_translator
|
from main import translator as main_translator
|
||||||
|
@ -64,7 +64,11 @@
|
|||||||
"patch_completed": "Patching getMachineId Completed",
|
"patch_completed": "Patching getMachineId Completed",
|
||||||
"patch_failed": "Patching getMachineId Failed: {error}",
|
"patch_failed": "Patching getMachineId Failed: {error}",
|
||||||
"version_check_passed": "Cursor Version Check Passed",
|
"version_check_passed": "Cursor Version Check Passed",
|
||||||
"file_modified": "File Modified"
|
"file_modified": "File Modified",
|
||||||
|
"version_less_than_0_45": "Cursor Version < 0.45.0, Skip Patching getMachineId",
|
||||||
|
"detecting_version": "Detecting Cursor Version",
|
||||||
|
"patching_getmachineid": "Patching getMachineId",
|
||||||
|
"version_greater_than_0_45": "Cursor Version >= 0.45.0, Patching getMachineId"
|
||||||
},
|
},
|
||||||
"register": {
|
"register": {
|
||||||
"title": "Cursor Registration Tool",
|
"title": "Cursor Registration Tool",
|
||||||
|
@ -64,7 +64,11 @@
|
|||||||
"patch_completed": "getMachineId修补完成",
|
"patch_completed": "getMachineId修补完成",
|
||||||
"patch_failed": "getMachineId修补失败: {error}",
|
"patch_failed": "getMachineId修补失败: {error}",
|
||||||
"version_check_passed": "Cursor版本检查通过",
|
"version_check_passed": "Cursor版本检查通过",
|
||||||
"file_modified": "文件已修改"
|
"file_modified": "文件已修改",
|
||||||
|
"version_less_than_0_45": "Cursor版本 < 0.45.0,跳过getMachineId修补",
|
||||||
|
"detecting_version": "检测Cursor版本",
|
||||||
|
"patching_getmachineid": "修补getMachineId",
|
||||||
|
"version_greater_than_0_45": "Cursor版本 >= 0.45.0,修补getMachineId"
|
||||||
},
|
},
|
||||||
"register": {
|
"register": {
|
||||||
"title": "Cursor 注册工具",
|
"title": "Cursor 注册工具",
|
||||||
|
@ -64,7 +64,11 @@
|
|||||||
"patch_completed": "getMachineId修補完成",
|
"patch_completed": "getMachineId修補完成",
|
||||||
"patch_failed": "getMachineId修補失敗: {error}",
|
"patch_failed": "getMachineId修補失敗: {error}",
|
||||||
"version_check_passed": "Cursor版本檢查通過",
|
"version_check_passed": "Cursor版本檢查通過",
|
||||||
"file_modified": "文件已修改"
|
"file_modified": "文件已修改",
|
||||||
|
"version_less_than_0_45": "Cursor版本 < 0.45.0,跳过getMachineId修补",
|
||||||
|
"detecting_version": "檢測Cursor版本",
|
||||||
|
"patching_getmachineid": "修補getMachineId",
|
||||||
|
"version_greater_than_0_45": "Cursor版本 >= 0.45.0,修補getMachineId"
|
||||||
},
|
},
|
||||||
"register": {
|
"register": {
|
||||||
"title": "Cursor 註冊工具",
|
"title": "Cursor 註冊工具",
|
||||||
@ -92,7 +96,6 @@
|
|||||||
"no_turnstile": "未檢測到 Turnstile 驗證",
|
"no_turnstile": "未檢測到 Turnstile 驗證",
|
||||||
"turnstile_passed": "驗證通過",
|
"turnstile_passed": "驗證通過",
|
||||||
"verification_start": "開始獲取驗證碼",
|
"verification_start": "開始獲取驗證碼",
|
||||||
"waiting_for_verification_code": "等待驗證碼",
|
|
||||||
"verification_code_filled": "驗證碼填寫完成",
|
"verification_code_filled": "驗證碼填寫完成",
|
||||||
"login_success_and_jump_to_settings_page": "成功登錄並跳轉到設置頁面",
|
"login_success_and_jump_to_settings_page": "成功登錄並跳轉到設置頁面",
|
||||||
"detect_login_page": "檢測到登錄頁面,開始登錄...",
|
"detect_login_page": "檢測到登錄頁面,開始登錄...",
|
||||||
|
12
logo.py
12
logo.py
@ -2,17 +2,17 @@ from colorama import Fore, Style, init
|
|||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# 獲取當前腳本所在目錄
|
# Get the current script directory
|
||||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
# 構建.env文件的完整路徑
|
# Build the full path to the .env file
|
||||||
env_path = os.path.join(current_dir, '.env')
|
env_path = os.path.join(current_dir, '.env')
|
||||||
|
|
||||||
# 加載環境變量,指定.env文件路徑
|
# Load environment variables, specifying the .env file path
|
||||||
load_dotenv(env_path)
|
load_dotenv(env_path)
|
||||||
# 獲取版本號,如果未找到則使用默認值
|
# Get the version number, using the default value if not found
|
||||||
version = os.getenv('VERSION', '1.0.0')
|
version = os.getenv('VERSION', '1.0.0')
|
||||||
|
|
||||||
# 初始化 colorama
|
# Initialize colorama
|
||||||
init()
|
init()
|
||||||
|
|
||||||
CURSOR_LOGO = f"""
|
CURSOR_LOGO = f"""
|
||||||
@ -27,6 +27,8 @@ CURSOR_LOGO = f"""
|
|||||||
Pro Version Activator v{version}
|
Pro Version Activator v{version}
|
||||||
{Fore.GREEN}
|
{Fore.GREEN}
|
||||||
Author: Pin Studios | yeongpin
|
Author: Pin Studios | yeongpin
|
||||||
|
|
||||||
|
Github: https://github.com/yeongpin/cursor-free-vip
|
||||||
{Fore.RED}
|
{Fore.RED}
|
||||||
Press 5 to change language | 按下 5 键切换语言
|
Press 5 to change language | 按下 5 键切换语言
|
||||||
{Style.RESET_ALL}
|
{Style.RESET_ALL}
|
||||||
|
69
main.py
69
main.py
@ -5,6 +5,10 @@ import sys
|
|||||||
import json
|
import json
|
||||||
from logo import print_logo
|
from logo import print_logo
|
||||||
from colorama import Fore, Style, init
|
from colorama import Fore, Style, init
|
||||||
|
import ctypes
|
||||||
|
from ctypes import windll
|
||||||
|
import locale
|
||||||
|
import platform
|
||||||
|
|
||||||
# 初始化colorama
|
# 初始化colorama
|
||||||
init()
|
init()
|
||||||
@ -25,11 +29,74 @@ EMOJI = {
|
|||||||
|
|
||||||
class Translator:
|
class Translator:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.current_language = 'en' # Default language
|
self.current_language = self.detect_system_language() # Changed to use system language
|
||||||
self.translations = {}
|
self.translations = {}
|
||||||
self.fallback_language = 'en' # Fallback language if translation is missing
|
self.fallback_language = 'en' # Fallback language if translation is missing
|
||||||
self.load_translations()
|
self.load_translations()
|
||||||
|
|
||||||
|
def detect_system_language(self):
|
||||||
|
"""Detect system language and return corresponding language code"""
|
||||||
|
try:
|
||||||
|
system = platform.system()
|
||||||
|
|
||||||
|
if system == 'Windows':
|
||||||
|
return self._detect_windows_language()
|
||||||
|
else:
|
||||||
|
return self._detect_unix_language()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"{Fore.YELLOW}{EMOJI['INFO']} Failed to detect system language: {e}{Style.RESET_ALL}")
|
||||||
|
return 'en'
|
||||||
|
|
||||||
|
def _detect_windows_language(self):
|
||||||
|
"""Detect language on Windows systems"""
|
||||||
|
try:
|
||||||
|
# Get the keyboard layout
|
||||||
|
user32 = ctypes.WinDLL('user32', use_last_error=True)
|
||||||
|
hwnd = user32.GetForegroundWindow()
|
||||||
|
threadid = user32.GetWindowThreadProcessId(hwnd, 0)
|
||||||
|
layout_id = user32.GetKeyboardLayout(threadid) & 0xFFFF
|
||||||
|
|
||||||
|
# Map language ID to our language codes
|
||||||
|
language_map = {
|
||||||
|
0x0409: 'en', # English
|
||||||
|
0x0404: 'zh_tw', # Traditional Chinese
|
||||||
|
0x0804: 'zh_cn', # Simplified Chinese
|
||||||
|
}
|
||||||
|
|
||||||
|
return language_map.get(layout_id, 'en')
|
||||||
|
except:
|
||||||
|
return self._detect_unix_language()
|
||||||
|
|
||||||
|
def _detect_unix_language(self):
|
||||||
|
"""Detect language on Unix-like systems (Linux, macOS)"""
|
||||||
|
try:
|
||||||
|
# Get the system locale
|
||||||
|
system_locale = locale.getdefaultlocale()[0]
|
||||||
|
if not system_locale:
|
||||||
|
return 'en'
|
||||||
|
|
||||||
|
system_locale = system_locale.lower()
|
||||||
|
|
||||||
|
# Map locale to our language codes
|
||||||
|
if system_locale.startswith('zh_tw') or system_locale.startswith('zh_hk'):
|
||||||
|
return 'zh_tw'
|
||||||
|
elif system_locale.startswith('zh_cn'):
|
||||||
|
return 'zh_cn'
|
||||||
|
elif system_locale.startswith('en'):
|
||||||
|
return 'en'
|
||||||
|
|
||||||
|
# Try to get language from LANG environment variable as fallback
|
||||||
|
env_lang = os.getenv('LANG', '').lower()
|
||||||
|
if 'tw' in env_lang or 'hk' in env_lang:
|
||||||
|
return 'zh_tw'
|
||||||
|
elif 'cn' in env_lang:
|
||||||
|
return 'zh_cn'
|
||||||
|
|
||||||
|
return 'en'
|
||||||
|
except:
|
||||||
|
return 'en'
|
||||||
|
|
||||||
def load_translations(self):
|
def load_translations(self):
|
||||||
"""Load all available translations"""
|
"""Load all available translations"""
|
||||||
try:
|
try:
|
||||||
|
@ -243,7 +243,7 @@ def fill_password(page, password, translator=None):
|
|||||||
if translator:
|
if translator:
|
||||||
print(f"{Fore.CYAN}🔑 {translator.get('register.setting_password')}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}🔑 {translator.get('register.setting_password')}{Style.RESET_ALL}")
|
||||||
else:
|
else:
|
||||||
print("\n正在设置密码...")
|
print(f"\n{translator.get('register.setting_password')}")
|
||||||
password_input = page.ele("@name=password")
|
password_input = page.ele("@name=password")
|
||||||
if password_input:
|
if password_input:
|
||||||
password_input.input(password)
|
password_input.input(password)
|
||||||
@ -257,14 +257,14 @@ def fill_password(page, password, translator=None):
|
|||||||
if translator:
|
if translator:
|
||||||
print(f"{Fore.GREEN}✅ {translator.get('register.password_success')}{Style.RESET_ALL}")
|
print(f"{Fore.GREEN}✅ {translator.get('register.password_success')}{Style.RESET_ALL}")
|
||||||
else:
|
else:
|
||||||
print(f"密码设置完成: {password}")
|
print(f"{translator.get('register.password_success')}: {password}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if translator:
|
if translator:
|
||||||
print(f"{Fore.RED}❌ {translator.get('register.password_error', error=str(e))}{Style.RESET_ALL}")
|
print(f"{Fore.RED}❌ {translator.get('register.password_error', error=str(e))}{Style.RESET_ALL}")
|
||||||
else:
|
else:
|
||||||
print(f"设置密码时出错: {e}")
|
print(f"{translator.get('register.password_error')}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def handle_verification_code(browser_tab, email_tab, controller, email, password, translator=None):
|
def handle_verification_code(browser_tab, email_tab, controller, email, password, translator=None):
|
||||||
@ -273,7 +273,7 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password
|
|||||||
if translator:
|
if translator:
|
||||||
print(f"\n{Fore.CYAN}{translator.get('register.waiting_for_verification_code')}{Style.RESET_ALL}")
|
print(f"\n{Fore.CYAN}{translator.get('register.waiting_for_verification_code')}{Style.RESET_ALL}")
|
||||||
else:
|
else:
|
||||||
print("\n等待并获取验证码...")
|
print(f"\n{translator.get('register.waiting_for_verification_code')}")
|
||||||
|
|
||||||
# 检查是否使用手动输入验证码
|
# 检查是否使用手动输入验证码
|
||||||
if hasattr(controller, 'get_verification_code') and email_tab is None: # 手动模式
|
if hasattr(controller, 'get_verification_code') and email_tab is None: # 手动模式
|
||||||
@ -284,7 +284,7 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password
|
|||||||
browser_tab.ele(f"@data-index={i}").input(digit)
|
browser_tab.ele(f"@data-index={i}").input(digit)
|
||||||
time.sleep(random.uniform(0.1, 0.3))
|
time.sleep(random.uniform(0.1, 0.3))
|
||||||
|
|
||||||
print("验证码填写完成")
|
print(f"{translator.get('register.verification_success')}")
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
|
|
||||||
# 处理最后一次 Turnstile 验证
|
# 处理最后一次 Turnstile 验证
|
||||||
@ -292,11 +292,11 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password
|
|||||||
if translator:
|
if translator:
|
||||||
print(f"{translator.get('register.verification_success')}")
|
print(f"{translator.get('register.verification_success')}")
|
||||||
else:
|
else:
|
||||||
print("最后一次验证通过!")
|
print(f"{translator.get('register.verification_success')}")
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
# 访问设置页面
|
# 访问设置页面
|
||||||
print("访问设置页面...")
|
print(f"{translator.get('register.visiting_url')}: https://www.cursor.com/settings")
|
||||||
browser_tab.get("https://www.cursor.com/settings")
|
browser_tab.get("https://www.cursor.com/settings")
|
||||||
time.sleep(3) # 等待页面加载
|
time.sleep(3) # 等待页面加载
|
||||||
return True, browser_tab
|
return True, browser_tab
|
||||||
@ -305,7 +305,7 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password
|
|||||||
|
|
||||||
# 自动获取验证码逻辑
|
# 自动获取验证码逻辑
|
||||||
elif email_tab:
|
elif email_tab:
|
||||||
print("等待验证码邮件...")
|
print(f"{translator.get('register.waiting_for_verification_code')}")
|
||||||
time.sleep(5) # 等待验证码邮件
|
time.sleep(5) # 等待验证码邮件
|
||||||
|
|
||||||
# 使用已有的 email_tab 刷新邮箱
|
# 使用已有的 email_tab 刷新邮箱
|
||||||
|
@ -41,11 +41,11 @@ class NewTempEmail:
|
|||||||
# 获取可用域名列表
|
# 获取可用域名列表
|
||||||
domains_response = requests.get(f"{self.api_url}/domains")
|
domains_response = requests.get(f"{self.api_url}/domains")
|
||||||
if domains_response.status_code != 200:
|
if domains_response.status_code != 200:
|
||||||
raise Exception("Failed to get available domains")
|
raise Exception(f"{self.translator.get('email.failed_to_get_available_domains')}")
|
||||||
|
|
||||||
domains = domains_response.json()["hydra:member"]
|
domains = domains_response.json()["hydra:member"]
|
||||||
if not domains:
|
if not domains:
|
||||||
raise Exception("No available domains")
|
raise Exception(f"{self.translator.get('email.no_available_domains')}")
|
||||||
|
|
||||||
# 生成随机用户名和密码
|
# 生成随机用户名和密码
|
||||||
username, password = self._generate_credentials()
|
username, password = self._generate_credentials()
|
||||||
@ -60,7 +60,7 @@ class NewTempEmail:
|
|||||||
|
|
||||||
create_response = requests.post(f"{self.api_url}/accounts", json=account_data)
|
create_response = requests.post(f"{self.api_url}/accounts", json=account_data)
|
||||||
if create_response.status_code != 201:
|
if create_response.status_code != 201:
|
||||||
raise Exception("Failed to create account")
|
raise Exception(f"{self.translator.get('email.failed_to_create_account')}")
|
||||||
|
|
||||||
# 获取访问令牌
|
# 获取访问令牌
|
||||||
token_data = {
|
token_data = {
|
||||||
@ -70,7 +70,7 @@ class NewTempEmail:
|
|||||||
|
|
||||||
token_response = requests.post(f"{self.api_url}/token", json=token_data)
|
token_response = requests.post(f"{self.api_url}/token", json=token_data)
|
||||||
if token_response.status_code != 200:
|
if token_response.status_code != 200:
|
||||||
raise Exception("Failed to get access token")
|
raise Exception(f"{self.translator.get('email.failed_to_get_access_token')}")
|
||||||
|
|
||||||
self.token = token_response.json()["token"]
|
self.token = token_response.json()["token"]
|
||||||
self.email = email
|
self.email = email
|
||||||
|
@ -4,10 +4,10 @@ from colorama import Fore, Style, init
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# 初始化colorama
|
# Initialize colorama
|
||||||
init()
|
init()
|
||||||
|
|
||||||
# 定义emoji常量
|
# Define emoji constants
|
||||||
EMOJI = {
|
EMOJI = {
|
||||||
"PROCESS": "⚙️",
|
"PROCESS": "⚙️",
|
||||||
"SUCCESS": "✅",
|
"SUCCESS": "✅",
|
||||||
@ -19,15 +19,15 @@ EMOJI = {
|
|||||||
class CursorQuitter:
|
class CursorQuitter:
|
||||||
def __init__(self, timeout=5, translator=None):
|
def __init__(self, timeout=5, translator=None):
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.translator = translator # 使用传入的翻译器
|
self.translator = translator # Use the passed translator
|
||||||
|
|
||||||
def quit_cursor(self):
|
def quit_cursor(self):
|
||||||
"""温和地关闭 Cursor 进程"""
|
"""Gently close Cursor processes"""
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['PROCESS']} {self.translator.get('quit_cursor.start')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['PROCESS']} {self.translator.get('quit_cursor.start')}...{Style.RESET_ALL}")
|
||||||
cursor_processes = []
|
cursor_processes = []
|
||||||
|
|
||||||
# 收集所有 Cursor 进程
|
# Collect all Cursor processes
|
||||||
for proc in psutil.process_iter(['pid', 'name']):
|
for proc in psutil.process_iter(['pid', 'name']):
|
||||||
try:
|
try:
|
||||||
if proc.info['name'].lower() in ['cursor.exe', 'cursor']:
|
if proc.info['name'].lower() in ['cursor.exe', 'cursor']:
|
||||||
@ -39,7 +39,7 @@ class CursorQuitter:
|
|||||||
print(f"{Fore.GREEN}{EMOJI['INFO']} {self.translator.get('quit_cursor.no_process')}{Style.RESET_ALL}")
|
print(f"{Fore.GREEN}{EMOJI['INFO']} {self.translator.get('quit_cursor.no_process')}{Style.RESET_ALL}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# 温和地请求进程终止
|
# Gently request processes to terminate
|
||||||
for proc in cursor_processes:
|
for proc in cursor_processes:
|
||||||
try:
|
try:
|
||||||
if proc.is_running():
|
if proc.is_running():
|
||||||
@ -48,7 +48,7 @@ class CursorQuitter:
|
|||||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 等待进程自然终止
|
# Wait for processes to terminate naturally
|
||||||
print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('quit_cursor.waiting')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('quit_cursor.waiting')}...{Style.RESET_ALL}")
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while time.time() - start_time < self.timeout:
|
while time.time() - start_time < self.timeout:
|
||||||
@ -66,7 +66,7 @@ class CursorQuitter:
|
|||||||
|
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
# 如果超时后仍有进程在运行
|
# If processes are still running after timeout
|
||||||
if still_running:
|
if still_running:
|
||||||
process_list = ", ".join([str(p.pid) for p in still_running])
|
process_list = ", ".join([str(p.pid) for p in still_running])
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('quit_cursor.timeout', pids=process_list)}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('quit_cursor.timeout', pids=process_list)}{Style.RESET_ALL}")
|
||||||
@ -79,11 +79,11 @@ class CursorQuitter:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def quit_cursor(translator=None, timeout=5):
|
def quit_cursor(translator=None, timeout=5):
|
||||||
"""便捷函数,用于直接调用退出功能"""
|
"""Convenient function for directly calling the quit function"""
|
||||||
quitter = CursorQuitter(timeout, translator)
|
quitter = CursorQuitter(timeout, translator)
|
||||||
return quitter.quit_cursor()
|
return quitter.quit_cursor()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# 如果直接运行,使用默认翻译器
|
# If run directly, use the default translator
|
||||||
from main import translator as main_translator
|
from main import translator as main_translator
|
||||||
quit_cursor(main_translator)
|
quit_cursor(main_translator)
|
@ -11,10 +11,10 @@ import tempfile
|
|||||||
from colorama import Fore, Style, init
|
from colorama import Fore, Style, init
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
# 初始化colorama
|
# Initialize colorama
|
||||||
init()
|
init()
|
||||||
|
|
||||||
# 定义emoji常量
|
# Define emoji constants
|
||||||
EMOJI = {
|
EMOJI = {
|
||||||
"FILE": "📄",
|
"FILE": "📄",
|
||||||
"BACKUP": "💾",
|
"BACKUP": "💾",
|
||||||
@ -25,7 +25,7 @@ EMOJI = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def get_cursor_paths(translator=None) -> Tuple[str, str]:
|
def get_cursor_paths(translator=None) -> Tuple[str, str]:
|
||||||
"""根据不同操作系统获取 Cursor 相关路径"""
|
""" Get Cursor related paths"""
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
|
|
||||||
paths_map = {
|
paths_map = {
|
||||||
@ -65,7 +65,7 @@ def get_cursor_paths(translator=None) -> Tuple[str, str]:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def version_check(version: str, min_version: str = "", max_version: str = "", translator=None) -> bool:
|
def version_check(version: str, min_version: str = "", max_version: str = "", translator=None) -> bool:
|
||||||
"""版本号检查"""
|
"""Version number check"""
|
||||||
version_pattern = r"^\d+\.\d+\.\d+$"
|
version_pattern = r"^\d+\.\d+\.\d+$"
|
||||||
try:
|
try:
|
||||||
if not re.match(version_pattern, version):
|
if not re.match(version_pattern, version):
|
||||||
@ -92,7 +92,7 @@ def version_check(version: str, min_version: str = "", max_version: str = "", tr
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def check_cursor_version(translator) -> bool:
|
def check_cursor_version(translator) -> bool:
|
||||||
"""检查 Cursor 版本"""
|
"""Check Cursor version"""
|
||||||
try:
|
try:
|
||||||
pkg_path, _ = get_cursor_paths(translator)
|
pkg_path, _ = get_cursor_paths(translator)
|
||||||
with open(pkg_path, "r", encoding="utf-8") as f:
|
with open(pkg_path, "r", encoding="utf-8") as f:
|
||||||
@ -103,7 +103,7 @@ def check_cursor_version(translator) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def modify_main_js(main_path: str, translator) -> bool:
|
def modify_main_js(main_path: str, translator) -> bool:
|
||||||
"""修改 main.js 文件"""
|
"""Modify main.js file"""
|
||||||
try:
|
try:
|
||||||
original_stat = os.stat(main_path)
|
original_stat = os.stat(main_path)
|
||||||
original_mode = original_stat.st_mode
|
original_mode = original_stat.st_mode
|
||||||
@ -142,14 +142,14 @@ def modify_main_js(main_path: str, translator) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def patch_cursor_get_machine_id(translator) -> bool:
|
def patch_cursor_get_machine_id(translator) -> bool:
|
||||||
"""修补 Cursor getMachineId 函数"""
|
"""Patch Cursor getMachineId function"""
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.start_patching')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.start_patching')}...{Style.RESET_ALL}")
|
||||||
|
|
||||||
# 获取路径
|
# Get paths
|
||||||
pkg_path, main_path = get_cursor_paths(translator)
|
pkg_path, main_path = get_cursor_paths(translator)
|
||||||
|
|
||||||
# 检查文件权限
|
# Check file permissions
|
||||||
for file_path in [pkg_path, main_path]:
|
for file_path in [pkg_path, main_path]:
|
||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.file_not_found', path=file_path)}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.file_not_found', path=file_path)}{Style.RESET_ALL}")
|
||||||
@ -158,7 +158,7 @@ def patch_cursor_get_machine_id(translator) -> bool:
|
|||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.no_write_permission', path=file_path)}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.no_write_permission', path=file_path)}{Style.RESET_ALL}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 获取版本号
|
# Get version number
|
||||||
try:
|
try:
|
||||||
with open(pkg_path, "r", encoding="utf-8") as f:
|
with open(pkg_path, "r", encoding="utf-8") as f:
|
||||||
version = json.load(f)["version"]
|
version = json.load(f)["version"]
|
||||||
@ -167,20 +167,20 @@ def patch_cursor_get_machine_id(translator) -> bool:
|
|||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.read_version_failed', error=str(e))}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.read_version_failed', error=str(e))}{Style.RESET_ALL}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 检查版本
|
# Check version
|
||||||
if not version_check(version, min_version="0.45.0", translator=translator):
|
if not version_check(version, min_version="0.45.0", translator=translator):
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.version_not_supported')}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.version_not_supported')}{Style.RESET_ALL}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.version_check_passed')}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.version_check_passed')}{Style.RESET_ALL}")
|
||||||
|
|
||||||
# 备份文件
|
# Backup file
|
||||||
backup_path = main_path + ".bak"
|
backup_path = main_path + ".bak"
|
||||||
if not os.path.exists(backup_path):
|
if not os.path.exists(backup_path):
|
||||||
shutil.copy2(main_path, backup_path)
|
shutil.copy2(main_path, backup_path)
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.backup_created', path=backup_path)}{Style.RESET_ALL}")
|
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.backup_created', path=backup_path)}{Style.RESET_ALL}")
|
||||||
|
|
||||||
# 修改文件
|
# Modify file
|
||||||
if not modify_main_js(main_path, translator):
|
if not modify_main_js(main_path, translator):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -195,7 +195,7 @@ class MachineIDResetter:
|
|||||||
def __init__(self, translator=None):
|
def __init__(self, translator=None):
|
||||||
self.translator = translator
|
self.translator = translator
|
||||||
|
|
||||||
# 判断操作系统
|
# Check operating system
|
||||||
if sys.platform == "win32": # Windows
|
if sys.platform == "win32": # Windows
|
||||||
appdata = os.getenv("APPDATA")
|
appdata = os.getenv("APPDATA")
|
||||||
if appdata is None:
|
if appdata is None:
|
||||||
@ -224,17 +224,17 @@ class MachineIDResetter:
|
|||||||
raise NotImplementedError(f"Not Supported OS: {sys.platform}")
|
raise NotImplementedError(f"Not Supported OS: {sys.platform}")
|
||||||
|
|
||||||
def generate_new_ids(self):
|
def generate_new_ids(self):
|
||||||
"""生成新的机器ID"""
|
"""Generate new machine ID"""
|
||||||
# 生成新的UUID
|
# Generate new UUID
|
||||||
dev_device_id = str(uuid.uuid4())
|
dev_device_id = str(uuid.uuid4())
|
||||||
|
|
||||||
# 生成新的machineId (64个字符的十六进制)
|
# Generate new machineId (64 characters of hexadecimal)
|
||||||
machine_id = hashlib.sha256(os.urandom(32)).hexdigest()
|
machine_id = hashlib.sha256(os.urandom(32)).hexdigest()
|
||||||
|
|
||||||
# 生成新的macMachineId (128个字符的十六进制)
|
# Generate new macMachineId (128 characters of hexadecimal)
|
||||||
mac_machine_id = hashlib.sha512(os.urandom(64)).hexdigest()
|
mac_machine_id = hashlib.sha512(os.urandom(64)).hexdigest()
|
||||||
|
|
||||||
# 生成新的sqmId
|
# Generate new sqmId
|
||||||
sqm_id = "{" + str(uuid.uuid4()).upper() + "}"
|
sqm_id = "{" + str(uuid.uuid4()).upper() + "}"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -242,11 +242,11 @@ class MachineIDResetter:
|
|||||||
"telemetry.macMachineId": mac_machine_id,
|
"telemetry.macMachineId": mac_machine_id,
|
||||||
"telemetry.machineId": machine_id,
|
"telemetry.machineId": machine_id,
|
||||||
"telemetry.sqmId": sqm_id,
|
"telemetry.sqmId": sqm_id,
|
||||||
"storage.serviceMachineId": dev_device_id, # 添加 storage.serviceMachineId
|
"storage.serviceMachineId": dev_device_id, # Add storage.serviceMachineId
|
||||||
}
|
}
|
||||||
|
|
||||||
def update_sqlite_db(self, new_ids):
|
def update_sqlite_db(self, new_ids):
|
||||||
"""更新 SQLite 数据库中的机器ID"""
|
"""Update machine ID in SQLite database"""
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.updating_sqlite')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.updating_sqlite')}...{Style.RESET_ALL}")
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ class MachineIDResetter:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def update_system_ids(self, new_ids):
|
def update_system_ids(self, new_ids):
|
||||||
"""更新系统级别的ID"""
|
"""Update system-level IDs"""
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.updating_system_ids')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.updating_system_ids')}...{Style.RESET_ALL}")
|
||||||
|
|
||||||
@ -297,7 +297,7 @@ class MachineIDResetter:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def _update_windows_machine_guid(self):
|
def _update_windows_machine_guid(self):
|
||||||
"""更新Windows MachineGuid"""
|
"""Update Windows MachineGuid"""
|
||||||
try:
|
try:
|
||||||
import winreg
|
import winreg
|
||||||
key = winreg.OpenKey(
|
key = winreg.OpenKey(
|
||||||
@ -318,11 +318,11 @@ class MachineIDResetter:
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def _update_macos_platform_uuid(self, new_ids):
|
def _update_macos_platform_uuid(self, new_ids):
|
||||||
"""更新macOS Platform UUID"""
|
"""Update macOS Platform UUID"""
|
||||||
try:
|
try:
|
||||||
uuid_file = "/var/root/Library/Preferences/SystemConfiguration/com.apple.platform.uuid.plist"
|
uuid_file = "/var/root/Library/Preferences/SystemConfiguration/com.apple.platform.uuid.plist"
|
||||||
if os.path.exists(uuid_file):
|
if os.path.exists(uuid_file):
|
||||||
# 使用sudo来执行plutil命令
|
# Use sudo to execute plutil command
|
||||||
cmd = f'sudo plutil -replace "UUID" -string "{new_ids["telemetry.macMachineId"]}" "{uuid_file}"'
|
cmd = f'sudo plutil -replace "UUID" -string "{new_ids["telemetry.macMachineId"]}" "{uuid_file}"'
|
||||||
result = os.system(cmd)
|
result = os.system(cmd)
|
||||||
if result == 0:
|
if result == 0:
|
||||||
@ -334,7 +334,7 @@ class MachineIDResetter:
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def reset_machine_ids(self):
|
def reset_machine_ids(self):
|
||||||
"""重置机器ID并备份原文件"""
|
"""Reset machine ID and backup original file"""
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.checking')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.checking')}...{Style.RESET_ALL}")
|
||||||
|
|
||||||
@ -360,26 +360,26 @@ class MachineIDResetter:
|
|||||||
print(f"{Fore.CYAN}{EMOJI['RESET']} {self.translator.get('reset.generating')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['RESET']} {self.translator.get('reset.generating')}...{Style.RESET_ALL}")
|
||||||
new_ids = self.generate_new_ids()
|
new_ids = self.generate_new_ids()
|
||||||
|
|
||||||
# 更新配置文件
|
# Update configuration file
|
||||||
config.update(new_ids)
|
config.update(new_ids)
|
||||||
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('reset.saving_json')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('reset.saving_json')}...{Style.RESET_ALL}")
|
||||||
with open(self.db_path, "w", encoding="utf-8") as f:
|
with open(self.db_path, "w", encoding="utf-8") as f:
|
||||||
json.dump(config, f, indent=4)
|
json.dump(config, f, indent=4)
|
||||||
|
|
||||||
# 更新SQLite数据库
|
# Update SQLite database
|
||||||
self.update_sqlite_db(new_ids)
|
self.update_sqlite_db(new_ids)
|
||||||
|
|
||||||
# 更新系统ID
|
# Update system IDs
|
||||||
self.update_system_ids(new_ids)
|
self.update_system_ids(new_ids)
|
||||||
|
|
||||||
# 检查 Cursor 版本并执行相应的操作
|
# Check Cursor version and perform corresponding actions
|
||||||
greater_than_0_45 = check_cursor_version(self.translator)
|
greater_than_0_45 = check_cursor_version(self.translator)
|
||||||
if greater_than_0_45:
|
if greater_than_0_45:
|
||||||
print(f"{Fore.CYAN}{EMOJI['INFO']} 检测到 Cursor 版本 >= 0.45.0,正在修补 getMachineId...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.detecting_version')} >= 0.45.0,{self.translator.get('reset.patching_getmachineid')}{Style.RESET_ALL}")
|
||||||
patch_cursor_get_machine_id(self.translator)
|
patch_cursor_get_machine_id(self.translator)
|
||||||
else:
|
else:
|
||||||
print(f"{Fore.YELLOW}{EMOJI['INFO']} Cursor 版本 < 0.45.0,跳过 getMachineId 修补{Style.RESET_ALL}")
|
print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.version_less_than_0_45')}{Style.RESET_ALL}")
|
||||||
|
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.success')}{Style.RESET_ALL}")
|
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.success')}{Style.RESET_ALL}")
|
||||||
print(f"\n{Fore.CYAN}{self.translator.get('reset.new_id')}:{Style.RESET_ALL}")
|
print(f"\n{Fore.CYAN}{self.translator.get('reset.new_id')}:{Style.RESET_ALL}")
|
||||||
@ -397,12 +397,12 @@ class MachineIDResetter:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def run(translator=None):
|
def run(translator=None):
|
||||||
"""便捷函数,用于直接调用重置功能"""
|
"""Convenient function for directly calling the reset function"""
|
||||||
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||||
print(f"{Fore.CYAN}{EMOJI['RESET']} {translator.get('reset.title')}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['RESET']} {translator.get('reset.title')}{Style.RESET_ALL}")
|
||||||
print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||||
|
|
||||||
resetter = MachineIDResetter(translator) # 正確傳遞 translator
|
resetter = MachineIDResetter(translator) # Correctly pass translator
|
||||||
resetter.reset_machine_ids()
|
resetter.reset_machine_ids()
|
||||||
|
|
||||||
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user