0
0
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:
yeongpin 2025-02-25 10:46:36 +08:00
parent 4c91525082
commit d852bcff50
17 changed files with 240 additions and 148 deletions

4
.env
View File

@ -1,2 +1,2 @@
version=1.4.03
VERSION=1.4.03
version=1.4.04
VERSION=1.4.04

5
.gitignore vendored
View File

@ -1,3 +1,8 @@
cursor_accounts.txt
/venv
/__pycache__
dist
build
install.bat
run.bat
temp_account_info.txt

View File

@ -1,5 +1,12 @@
# 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
1. Switch to API-based Registration System | 改用API註冊系統替代瀏覽器操作

View File

@ -2,28 +2,28 @@
chcp 65001 > nul
cls
:: 檢查是否以管理員權限運行
:: Check if running with administrator privileges
net session >nul 2>&1
if %errorLevel% == 0 (
:: 如果是管理員權限,只創建虛擬環境後就降權運行
:: If running with administrator privileges, create virtual environment and then run with normal user privileges
if not exist venv (
echo 正在創建虛擬環境...
python -m venv venv
)
:: 降權運行剩餘的步驟
:: Run remaining steps with normal user privileges
echo 以普通用戶權限繼續...
powershell -Command "Start-Process -FilePath '%comspec%' -ArgumentList '/c cd /d %cd% && %~f0 run' -Verb RunAs:NO"
exit /b
) else (
:: 檢查是否是第二階段運行
:: Check if running in second stage
if "%1"=="run" (
goto RUN_BUILD
) else (
:: 如果是普通權限且需要創建虛擬環境,請求管理員權限
:: If running with normal privileges and creating virtual environment is required, request administrator privileges
if not exist venv (
echo ⚠️ 需要管理員權限來創建虛擬環境
echo 正在請求管理員權限...
echo ⚠️ Requires administrator privileges to create virtual environment
echo Requesting administrator privileges...
powershell -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c cd /d %cd% && %~f0'"
exit /b
) else (
@ -33,30 +33,30 @@ if %errorLevel% == 0 (
)
:RUN_BUILD
echo 啟動虛擬環境...
echo Starting virtual environment...
call venv\Scripts\activate.bat
if errorlevel 1 (
echo啟動虛擬環境失敗
echoFailed to start virtual environment
pause
exit /b 1
)
:: 檢查並安裝缺失的依賴
echo 檢查依賴...
:: Check and install missing dependencies
echo Checking dependencies...
for /f "tokens=1" %%i in (requirements.txt) do (
pip show %%i >nul 2>&1 || (
echo 安裝 %%i...
echo Installing %%i...
pip install %%i
)
)
echo 開始構建...
echo Starting build...
python build.py
if errorlevel 1 (
echo構建失敗
echoBuild failed
pause
exit /b 1
)
echo完成!
echoCompleted!
pause

View File

@ -8,7 +8,7 @@ import shutil
from logo import print_logo
from dotenv import load_dotenv
# 忽略特定警告
# Ignore specific warnings
warnings.filterwarnings("ignore", category=SyntaxWarning)
class LoadingAnimation:
@ -50,21 +50,21 @@ def simulate_progress(message, duration=1.0, steps=20):
progress_bar(i, steps, prefix="Progress:", length=40)
def build():
# 清理屏幕
# Clean screen
os.system("cls" if platform.system().lower() == "windows" else "clear")
# 顯示 logo
# Display logo
print_logo()
# 清理 PyInstaller 緩存
print("\033[93m🧹 清理構建緩存...\033[0m")
# Clean PyInstaller cache
print("\033[93m🧹 Cleaning build cache...\033[0m")
if os.path.exists('build'):
shutil.rmtree('build')
# 重新加載環境變量以確保獲取最新版本
# Reload environment variables to ensure getting the latest version
load_dotenv(override=True)
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:
simulate_progress("Preparing build environment...", 0.5)
@ -72,7 +72,7 @@ def build():
loading = LoadingAnimation()
loading.start("Building in progress")
# 根据系统类型设置输出名称
# Set output name based on system type
system = platform.system().lower()
if system == "windows":
os_type = "windows"
@ -86,7 +86,7 @@ def build():
output_name = f"CursorFreeVIP_{version}_{os_type}"
# 构建命令
# Build command
build_command = f'pyinstaller --clean --noconfirm build.spec'
output_path = os.path.join('dist', f'{output_name}{ext}')
@ -95,16 +95,16 @@ def build():
loading.stop()
if os.path.exists(output_path):
print(f"\n\033[92m✅ 構建完成!")
print(f"📦 可執行文件位於: {output_path}\033[0m")
print(f"\n\033[92m✅ Build completed!")
print(f"📦 Executable file located: {output_path}\033[0m")
else:
print("\n\033[91m❌ 構建失敗:未找到輸出文件\033[0m")
print("\n\033[91m❌ Build failed: Output file not found\033[0m")
return False
except Exception as e:
if loading:
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 True

View File

@ -8,7 +8,7 @@ NC='\033[0m' # No Color
# 检查并安装必要的依赖
check_dependencies() {
echo -e "${YELLOW}检查系统依赖...${NC}"
echo -e "${YELLOW}Checking system dependencies...${NC}"
# 检查是否为 Ubuntu/Debian
if [ -f /etc/debian_version ]; then
@ -16,42 +16,42 @@ check_dependencies() {
PACKAGES="python3 python3-pip python3-venv"
for pkg in $PACKAGES; do
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 install -y $pkg
fi
done
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
fi
}
# 创建并激活虚拟环境
setup_venv() {
echo -e "${GREEN}正在创建虚拟环境...${NC}"
echo -e "${GREEN}Creating virtual environment...${NC}"
python3 -m venv venv
echo -e "${GREEN}启动虚拟环境...${NC}"
echo -e "${GREEN}Starting virtual environment...${NC}"
. ./venv/bin/activate || source ./venv/bin/activate
}
# 安装依赖
install_dependencies() {
echo -e "${GREEN}安装依赖...${NC}"
echo -e "${GREEN}Installing dependencies...${NC}"
python3 -m pip install --upgrade pip
pip3 install -r requirements.txt
}
# 构建程序
build_program() {
echo -e "${GREEN}开始构建...${NC}"
echo -e "${GREEN}Starting build...${NC}"
python3 build.py
}
# 清理
cleanup() {
echo -e "${GREEN}清理虚拟环境...${NC}"
echo -e "${GREEN}Cleaning virtual environment...${NC}"
deactivate 2>/dev/null || true
rm -rf venv
}
@ -73,8 +73,8 @@ main() {
# 清理
cleanup
echo -e "${GREEN}完成!${NC}"
echo "按任意键退出..."
echo -e "${GREEN}Completed!${NC}"
echo "Press any key to exit..."
# 使用兼容的方式读取输入
if [ "$(uname)" = "Linux" ]; then
read dummy

View File

@ -10,10 +10,10 @@ from reset_machine_manual import MachineIDResetter
os.environ["PYTHONVERBOSE"] = "0"
os.environ["PYINSTALLER_VERBOSE"] = "0"
# 初始化colorama
# Initialize colorama
init()
# 定义emoji常量
# Define emoji constants
EMOJI = {
'START': '🚀',
'FORM': '📝',
@ -33,7 +33,7 @@ EMOJI = {
class CursorRegistration:
def __init__(self, translator=None):
self.translator = translator
# 设置为显示模式
# Set to display mode
os.environ['BROWSER_HEADLESS'] = 'False'
self.browser_manager = BrowserManager()
self.browser = None
@ -44,7 +44,7 @@ class CursorRegistration:
self.signup_tab = None
self.email_tab = None
# 账号信息
# Account information
self.password = self._generate_password()
self.first_name = self._generate_name()
self.last_name = self._generate_name()
@ -61,9 +61,9 @@ class CursorRegistration:
return first_letter + rest_letters
def setup_email(self):
"""设置邮箱"""
"""Setup Email"""
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()
if '@' not in self.email_address:
@ -77,9 +77,9 @@ class CursorRegistration:
return False
def get_verification_code(self):
"""手动获取验证码"""
"""Manually Get Verification Code"""
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()
if not code.isdigit() or len(code) != 6:
@ -93,31 +93,31 @@ class CursorRegistration:
return None
def register_cursor(self):
"""注册 Cursor"""
"""Register Cursor"""
browser_tab = None
try:
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
# 执行新的注册流程,传入 translator
# Execute new registration process, passing translator
result, browser_tab = new_signup_main(
email=self.email_address,
password=self.password,
first_name=self.first_name,
last_name=self.last_name,
email_tab=None, # 不需要邮箱标签页
controller=self, # 传入 self 而不是 self.controller
email_tab=None, # No email tab needed
controller=self, # Pass self instead of self.controller
translator=self.translator
)
if result:
# 使用返回的浏览器实例获取账户信息
self.signup_tab = browser_tab # 保存浏览器实例
# Use the returned browser instance to get account information
self.signup_tab = browser_tab # Save browser instance
success = self._get_account_info()
# 获取信息后关闭浏览器
# Close browser after getting information
if browser_tab:
try:
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}")
return False
finally:
# 确保在任何情况下都关闭浏览器
# Ensure browser is closed in any case
if browser_tab:
try:
browser_tab.quit()
@ -140,7 +140,7 @@ class CursorRegistration:
pass
def _get_account_info(self):
"""获取账户信息和 Token"""
"""Get Account Information and Token"""
try:
self.signup_tab.get(self.settings_url)
time.sleep(2)
@ -191,22 +191,22 @@ class CursorRegistration:
return False
def _save_account_info(self, token, total_usage):
"""保存账户信息到文件"""
"""Save Account Information to File"""
try:
# 先更新认证信息
# Update authentication information first
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):
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.cursor_auth_info_updated')}...{Style.RESET_ALL}")
else:
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}")
resetter = MachineIDResetter(self.translator) # 创建实例时传入translator
if not resetter.reset_machine_ids(): # 直接调用reset_machine_ids方法
resetter = MachineIDResetter(self.translator) # Create instance with translator
if not resetter.reset_machine_ids(): # Call reset_machine_ids method directly
raise Exception("Failed to reset machine ID")
# 保存账户信息到文件
# Save account information to file
with open('cursor_accounts.txt', 'a', encoding='utf-8') as f:
f.write(f"\n{'='*50}\n")
f.write(f"Email: {self.email_address}\n")
@ -223,7 +223,7 @@ class CursorRegistration:
return False
def start(self):
"""启动注册流程"""
"""Start Registration Process"""
try:
if self.setup_email():
if self.register_cursor():
@ -231,7 +231,7 @@ class CursorRegistration:
return True
return False
finally:
# 关闭邮箱标签页
# Close email tab
if hasattr(self, 'temp_email'):
try:
self.temp_email.close()
@ -239,7 +239,7 @@ class CursorRegistration:
pass
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)
return auth_manager.update_auth(email, access_token, refresh_token)

View File

@ -5,10 +5,10 @@ import shutil
from colorama import Fore, Style, init
import subprocess
# 初始化 colorama
# Initialize colorama
init()
# 定义 emoji 常量
# Define emoji constants
EMOJI = {
"PROCESS": "🔄",
"SUCCESS": "",
@ -31,7 +31,7 @@ class AutoUpdateDisabler:
}
def _kill_cursor_processes(self):
"""结束所有 Cursor 进程"""
"""End all Cursor processes"""
try:
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
def _remove_updater_directory(self):
"""删除更新程序目录"""
"""Delete updater directory"""
try:
updater_path = self.updater_paths.get(self.system)
if not updater_path:
@ -70,7 +70,7 @@ class AutoUpdateDisabler:
return False
def _create_blocking_file(self):
"""创建阻止文件"""
"""Create blocking file"""
try:
updater_path = self.updater_paths.get(self.system)
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}")
# 创建空文件
# Create empty file
open(updater_path, 'w').close()
# 设置只读属性
# Set read-only attribute
if self.system == "Windows":
os.system(f'attrib +r "{updater_path}"')
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}")
return True
@ -95,19 +95,19 @@ class AutoUpdateDisabler:
return False
def disable_auto_update(self):
"""禁用自动更新"""
"""Disable auto update"""
try:
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():
return False
# 2. 删除目录
# 2. Delete directory
if not self._remove_updater_directory():
return False
# 3. 创建阻止文件
# 3. Create blocking file
if not self._create_blocking_file():
return False
@ -119,16 +119,16 @@ class AutoUpdateDisabler:
return False
def run(translator=None):
"""便捷函数,用于直接调用禁用功能"""
"""Convenient function for directly calling the disable function"""
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}")
disabler = AutoUpdateDisabler(translator)
disabler.disable_auto_update()
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__":
from main import translator as main_translator

View File

@ -64,7 +64,11 @@
"patch_completed": "Patching getMachineId Completed",
"patch_failed": "Patching getMachineId Failed: {error}",
"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": {
"title": "Cursor Registration Tool",

View File

@ -64,7 +64,11 @@
"patch_completed": "getMachineId修补完成",
"patch_failed": "getMachineId修补失败: {error}",
"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": {
"title": "Cursor 注册工具",

View File

@ -64,7 +64,11 @@
"patch_completed": "getMachineId修補完成",
"patch_failed": "getMachineId修補失敗: {error}",
"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": {
"title": "Cursor 註冊工具",
@ -92,7 +96,6 @@
"no_turnstile": "未檢測到 Turnstile 驗證",
"turnstile_passed": "驗證通過",
"verification_start": "開始獲取驗證碼",
"waiting_for_verification_code": "等待驗證碼",
"verification_code_filled": "驗證碼填寫完成",
"login_success_and_jump_to_settings_page": "成功登錄並跳轉到設置頁面",
"detect_login_page": "檢測到登錄頁面,開始登錄...",

12
logo.py
View File

@ -2,17 +2,17 @@ from colorama import Fore, Style, init
from dotenv import load_dotenv
import os
# 獲取當前腳本所在目錄
# Get the current script directory
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文件路徑
# Load environment variables, specifying the .env file path
load_dotenv(env_path)
# 獲取版本號,如果未找到則使用默認值
# Get the version number, using the default value if not found
version = os.getenv('VERSION', '1.0.0')
# 初始化 colorama
# Initialize colorama
init()
CURSOR_LOGO = f"""
@ -27,6 +27,8 @@ CURSOR_LOGO = f"""
Pro Version Activator v{version}
{Fore.GREEN}
Author: Pin Studios | yeongpin
Github: https://github.com/yeongpin/cursor-free-vip
{Fore.RED}
Press 5 to change language | 按下 5 键切换语言
{Style.RESET_ALL}

69
main.py
View File

@ -5,6 +5,10 @@ import sys
import json
from logo import print_logo
from colorama import Fore, Style, init
import ctypes
from ctypes import windll
import locale
import platform
# 初始化colorama
init()
@ -25,11 +29,74 @@ EMOJI = {
class Translator:
def __init__(self):
self.current_language = 'en' # Default language
self.current_language = self.detect_system_language() # Changed to use system language
self.translations = {}
self.fallback_language = 'en' # Fallback language if translation is missing
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):
"""Load all available translations"""
try:

View File

@ -243,7 +243,7 @@ def fill_password(page, password, translator=None):
if translator:
print(f"{Fore.CYAN}🔑 {translator.get('register.setting_password')}{Style.RESET_ALL}")
else:
print("\n正在设置密码...")
print(f"\n{translator.get('register.setting_password')}")
password_input = page.ele("@name=password")
if password_input:
password_input.input(password)
@ -257,14 +257,14 @@ def fill_password(page, password, translator=None):
if translator:
print(f"{Fore.GREEN}{translator.get('register.password_success')}{Style.RESET_ALL}")
else:
print(f"密码设置完成: {password}")
print(f"{translator.get('register.password_success')}: {password}")
return True
except Exception as e:
if translator:
print(f"{Fore.RED}{translator.get('register.password_error', error=str(e))}{Style.RESET_ALL}")
else:
print(f"设置密码时出错: {e}")
print(f"{translator.get('register.password_error')}: {e}")
return False
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:
print(f"\n{Fore.CYAN}{translator.get('register.waiting_for_verification_code')}{Style.RESET_ALL}")
else:
print("\n等待并获取验证码...")
print(f"\n{translator.get('register.waiting_for_verification_code')}")
# 检查是否使用手动输入验证码
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)
time.sleep(random.uniform(0.1, 0.3))
print("验证码填写完成")
print(f"{translator.get('register.verification_success')}")
time.sleep(3)
# 处理最后一次 Turnstile 验证
@ -292,11 +292,11 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password
if translator:
print(f"{translator.get('register.verification_success')}")
else:
print("最后一次验证通过!")
print(f"{translator.get('register.verification_success')}")
time.sleep(2)
# 访问设置页面
print("访问设置页面...")
print(f"{translator.get('register.visiting_url')}: https://www.cursor.com/settings")
browser_tab.get("https://www.cursor.com/settings")
time.sleep(3) # 等待页面加载
return True, browser_tab
@ -305,7 +305,7 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password
# 自动获取验证码逻辑
elif email_tab:
print("等待验证码邮件...")
print(f"{translator.get('register.waiting_for_verification_code')}")
time.sleep(5) # 等待验证码邮件
# 使用已有的 email_tab 刷新邮箱

View File

@ -41,11 +41,11 @@ class NewTempEmail:
# 获取可用域名列表
domains_response = requests.get(f"{self.api_url}/domains")
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"]
if not domains:
raise Exception("No available domains")
raise Exception(f"{self.translator.get('email.no_available_domains')}")
# 生成随机用户名和密码
username, password = self._generate_credentials()
@ -60,7 +60,7 @@ class NewTempEmail:
create_response = requests.post(f"{self.api_url}/accounts", json=account_data)
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 = {
@ -70,7 +70,7 @@ class NewTempEmail:
token_response = requests.post(f"{self.api_url}/token", json=token_data)
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.email = email

View File

@ -4,10 +4,10 @@ from colorama import Fore, Style, init
import sys
import os
# 初始化colorama
# Initialize colorama
init()
# 定义emoji常量
# Define emoji constants
EMOJI = {
"PROCESS": "⚙️",
"SUCCESS": "",
@ -19,15 +19,15 @@ EMOJI = {
class CursorQuitter:
def __init__(self, timeout=5, translator=None):
self.timeout = timeout
self.translator = translator # 使用传入的翻译器
self.translator = translator # Use the passed translator
def quit_cursor(self):
"""温和地关闭 Cursor 进程"""
"""Gently close Cursor processes"""
try:
print(f"{Fore.CYAN}{EMOJI['PROCESS']} {self.translator.get('quit_cursor.start')}...{Style.RESET_ALL}")
cursor_processes = []
# 收集所有 Cursor 进程
# Collect all Cursor processes
for proc in psutil.process_iter(['pid', 'name']):
try:
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}")
return True
# 温和地请求进程终止
# Gently request processes to terminate
for proc in cursor_processes:
try:
if proc.is_running():
@ -48,7 +48,7 @@ class CursorQuitter:
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
# 等待进程自然终止
# Wait for processes to terminate naturally
print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('quit_cursor.waiting')}...{Style.RESET_ALL}")
start_time = time.time()
while time.time() - start_time < self.timeout:
@ -66,7 +66,7 @@ class CursorQuitter:
time.sleep(0.5)
# 如果超时后仍有进程在运行
# If processes are still running after timeout
if 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}")
@ -79,11 +79,11 @@ class CursorQuitter:
return False
def quit_cursor(translator=None, timeout=5):
"""便捷函数,用于直接调用退出功能"""
"""Convenient function for directly calling the quit function"""
quitter = CursorQuitter(timeout, translator)
return quitter.quit_cursor()
if __name__ == "__main__":
# 如果直接运行,使用默认翻译器
# If run directly, use the default translator
from main import translator as main_translator
quit_cursor(main_translator)

View File

@ -11,10 +11,10 @@ import tempfile
from colorama import Fore, Style, init
from typing import Tuple
# 初始化colorama
# Initialize colorama
init()
# 定义emoji常量
# Define emoji constants
EMOJI = {
"FILE": "📄",
"BACKUP": "💾",
@ -25,7 +25,7 @@ EMOJI = {
}
def get_cursor_paths(translator=None) -> Tuple[str, str]:
"""根据不同操作系统获取 Cursor 相关路径"""
""" Get Cursor related paths"""
system = platform.system()
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:
"""版本号检查"""
"""Version number check"""
version_pattern = r"^\d+\.\d+\.\d+$"
try:
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
def check_cursor_version(translator) -> bool:
"""检查 Cursor 版本"""
"""Check Cursor version"""
try:
pkg_path, _ = get_cursor_paths(translator)
with open(pkg_path, "r", encoding="utf-8") as f:
@ -103,7 +103,7 @@ def check_cursor_version(translator) -> bool:
return False
def modify_main_js(main_path: str, translator) -> bool:
"""修改 main.js 文件"""
"""Modify main.js file"""
try:
original_stat = os.stat(main_path)
original_mode = original_stat.st_mode
@ -142,14 +142,14 @@ def modify_main_js(main_path: str, translator) -> bool:
return False
def patch_cursor_get_machine_id(translator) -> bool:
"""修补 Cursor getMachineId 函数"""
"""Patch Cursor getMachineId function"""
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.start_patching')}...{Style.RESET_ALL}")
# 获取路径
# Get paths
pkg_path, main_path = get_cursor_paths(translator)
# 检查文件权限
# Check file permissions
for file_path in [pkg_path, main_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}")
@ -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}")
return False
# 获取版本号
# Get version number
try:
with open(pkg_path, "r", encoding="utf-8") as f:
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}")
return False
# 检查版本
# Check version
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}")
return False
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.version_check_passed')}{Style.RESET_ALL}")
# 备份文件
# Backup file
backup_path = main_path + ".bak"
if not os.path.exists(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}")
# 修改文件
# Modify file
if not modify_main_js(main_path, translator):
return False
@ -195,7 +195,7 @@ class MachineIDResetter:
def __init__(self, translator=None):
self.translator = translator
# 判断操作系统
# Check operating system
if sys.platform == "win32": # Windows
appdata = os.getenv("APPDATA")
if appdata is None:
@ -224,17 +224,17 @@ class MachineIDResetter:
raise NotImplementedError(f"Not Supported OS: {sys.platform}")
def generate_new_ids(self):
"""生成新的机器ID"""
# 生成新的UUID
"""Generate new machine ID"""
# Generate new UUID
dev_device_id = str(uuid.uuid4())
# 生成新的machineId (64个字符的十六进制)
# Generate new machineId (64 characters of hexadecimal)
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()
# 生成新的sqmId
# Generate new sqmId
sqm_id = "{" + str(uuid.uuid4()).upper() + "}"
return {
@ -242,11 +242,11 @@ class MachineIDResetter:
"telemetry.macMachineId": mac_machine_id,
"telemetry.machineId": machine_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):
"""更新 SQLite 数据库中的机器ID"""
"""Update machine ID in SQLite database"""
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.updating_sqlite')}...{Style.RESET_ALL}")
@ -281,7 +281,7 @@ class MachineIDResetter:
return False
def update_system_ids(self, new_ids):
"""更新系统级别的ID"""
"""Update system-level IDs"""
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.updating_system_ids')}...{Style.RESET_ALL}")
@ -297,7 +297,7 @@ class MachineIDResetter:
return False
def _update_windows_machine_guid(self):
"""更新Windows MachineGuid"""
"""Update Windows MachineGuid"""
try:
import winreg
key = winreg.OpenKey(
@ -318,11 +318,11 @@ class MachineIDResetter:
raise
def _update_macos_platform_uuid(self, new_ids):
"""更新macOS Platform UUID"""
"""Update macOS Platform UUID"""
try:
uuid_file = "/var/root/Library/Preferences/SystemConfiguration/com.apple.platform.uuid.plist"
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}"'
result = os.system(cmd)
if result == 0:
@ -334,7 +334,7 @@ class MachineIDResetter:
raise
def reset_machine_ids(self):
"""重置机器ID并备份原文件"""
"""Reset machine ID and backup original file"""
try:
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}")
new_ids = self.generate_new_ids()
# 更新配置文件
# Update configuration file
config.update(new_ids)
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:
json.dump(config, f, indent=4)
# 更新SQLite数据库
# Update SQLite database
self.update_sqlite_db(new_ids)
# 更新系统ID
# Update system IDs
self.update_system_ids(new_ids)
# 检查 Cursor 版本并执行相应的操作
# Check Cursor version and perform corresponding actions
greater_than_0_45 = check_cursor_version(self.translator)
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)
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"\n{Fore.CYAN}{self.translator.get('reset.new_id')}:{Style.RESET_ALL}")
@ -397,12 +397,12 @@ class MachineIDResetter:
return False
def run(translator=None):
"""便捷函数,用于直接调用重置功能"""
"""Convenient function for directly calling the reset function"""
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}{'='*50}{Style.RESET_ALL}")
resetter = MachineIDResetter(translator) # 正確傳遞 translator
resetter = MachineIDResetter(translator) # Correctly pass translator
resetter.reset_machine_ids()
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")