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.04
VERSION=1.4.03 VERSION=1.4.04

5
.gitignore vendored
View File

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

View File

@ -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註冊系統替代瀏覽器操作

View File

@ -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啟動虛擬環境失敗 echoFailed 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構建失敗 echoBuild failed
pause pause
exit /b 1 exit /b 1
) )
echo完成! echoCompleted!
pause pause

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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",

View File

@ -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 注册工具",

View File

@ -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
View File

@ -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
View File

@ -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:

View File

@ -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 刷新邮箱

View File

@ -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

View File

@ -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)

View File

@ -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}")