mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-08-02 20:47:35 +08:00
Merge branch 'main' into auto-translate-missing-keys
This commit is contained in:
commit
f39435f2de
@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
|
|
||||||
[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
|
[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
|
||||||
[](https://creativecommons.org/licenses/by-nc-nd/4.0/)
|
[](https://creativecommons.org/licenses/by-nc-nd/4.0/)
|
||||||
[](https://github.com/yeongpin/cursor-free-vip/stargazers)
|
[](https://github.com/yeongpin/cursor-free-vip/stargazers)
|
||||||
[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
|
[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
|
||||||
<a href="https://buymeacoffee.com/yeongpin" target="_blank"><img alt="Buy Me a Coffee" src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-Support%20Me-FFDA33"></a>
|
<a href="https://buymeacoffee.com/yeongpin" target="_blank"><img alt="Buy Me a Coffee" src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-Support%20Me-FFDA33"></a>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
@ -249,6 +249,13 @@ def setup_config(translator=None):
|
|||||||
'product_json_path': os.path.join(cursor_dir, "resources/app/product.json") if cursor_dir else ""
|
'product_json_path': os.path.join(cursor_dir, "resources/app/product.json") if cursor_dir else ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Add tempmail_plus configuration
|
||||||
|
default_config['TempMailPlus'] = {
|
||||||
|
'enabled': 'false',
|
||||||
|
'email': '',
|
||||||
|
'epin': ''
|
||||||
|
}
|
||||||
|
|
||||||
# Read existing configuration and merge
|
# Read existing configuration and merge
|
||||||
if os.path.exists(config_file):
|
if os.path.exists(config_file):
|
||||||
config.read(config_file, encoding='utf-8')
|
config.read(config_file, encoding='utf-8')
|
||||||
|
@ -6,6 +6,7 @@ from faker import Faker
|
|||||||
from cursor_auth import CursorAuth
|
from cursor_auth import CursorAuth
|
||||||
from reset_machine_manual import MachineIDResetter
|
from reset_machine_manual import MachineIDResetter
|
||||||
from get_user_token import get_token_from_cookie
|
from get_user_token import get_token_from_cookie
|
||||||
|
from config import get_config
|
||||||
|
|
||||||
os.environ["PYTHONVERBOSE"] = "0"
|
os.environ["PYTHONVERBOSE"] = "0"
|
||||||
os.environ["PYINSTALLER_VERBOSE"] = "0"
|
os.environ["PYINSTALLER_VERBOSE"] = "0"
|
||||||
@ -102,6 +103,18 @@ class CursorRegistration:
|
|||||||
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}")
|
||||||
|
|
||||||
|
# Check if tempmail_plus is enabled
|
||||||
|
config = get_config(self.translator)
|
||||||
|
email_tab = None
|
||||||
|
if config and config.has_section('TempMailPlus'):
|
||||||
|
if config.getboolean('TempMailPlus', 'enabled'):
|
||||||
|
email = config.get('TempMailPlus', 'email')
|
||||||
|
epin = config.get('TempMailPlus', 'epin')
|
||||||
|
if email and epin:
|
||||||
|
from email_tabs.tempmail_plus_tab import TempMailPlusTab
|
||||||
|
email_tab = TempMailPlusTab(email, epin)
|
||||||
|
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('register.using_tempmail_plus')}{Style.RESET_ALL}")
|
||||||
|
|
||||||
# Use new_signup.py directly for registration
|
# 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
|
||||||
|
|
||||||
@ -111,7 +124,7 @@ class CursorRegistration:
|
|||||||
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, # No email tab needed
|
email_tab=email_tab, # Pass email_tab if tempmail_plus is enabled
|
||||||
controller=self, # Pass self instead of self.controller
|
controller=self, # Pass self instead of self.controller
|
||||||
translator=self.translator
|
translator=self.translator
|
||||||
)
|
)
|
||||||
|
27
email_tabs/email_tab_interface.py
Normal file
27
email_tabs/email_tab_interface.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
class EmailTabInterface(ABC):
|
||||||
|
"""Email tab interface for handling email verification"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def refresh_inbox(self) -> None:
|
||||||
|
"""Refresh the email inbox"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def check_for_cursor_email(self) -> bool:
|
||||||
|
"""Check if there is a verification email from Cursor
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if verification email exists, False otherwise
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_verification_code(self) -> str:
|
||||||
|
"""Get the verification code from the email
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The verification code if found, empty string otherwise
|
||||||
|
"""
|
||||||
|
pass
|
109
email_tabs/tempmail_plus_tab.py
Normal file
109
email_tabs/tempmail_plus_tab.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import requests
|
||||||
|
import re
|
||||||
|
from typing import Optional
|
||||||
|
from .email_tab_interface import EmailTabInterface
|
||||||
|
|
||||||
|
class TempMailPlusTab(EmailTabInterface):
|
||||||
|
"""Implementation of EmailTabInterface for tempmail.plus"""
|
||||||
|
|
||||||
|
def __init__(self, email: str, epin: str):
|
||||||
|
"""Initialize TempMailPlusTab
|
||||||
|
|
||||||
|
Args:
|
||||||
|
email: The email address to check
|
||||||
|
epin: The epin token for authentication
|
||||||
|
"""
|
||||||
|
self.email = email
|
||||||
|
self.epin = epin
|
||||||
|
self.base_url = "https://tempmail.plus/api"
|
||||||
|
self.headers = {
|
||||||
|
'accept': 'application/json',
|
||||||
|
'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6',
|
||||||
|
'cache-control': 'no-cache',
|
||||||
|
'pragma': 'no-cache',
|
||||||
|
'referer': 'https://tempmail.plus/zh/',
|
||||||
|
'sec-ch-ua': '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
|
||||||
|
'sec-ch-ua-mobile': '?0',
|
||||||
|
'sec-ch-ua-platform': '"macOS"',
|
||||||
|
'sec-fetch-dest': 'empty',
|
||||||
|
'sec-fetch-mode': 'cors',
|
||||||
|
'sec-fetch-site': 'same-origin',
|
||||||
|
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36',
|
||||||
|
'x-requested-with': 'XMLHttpRequest'
|
||||||
|
}
|
||||||
|
self.cookies = {'email': email}
|
||||||
|
self._cached_mail_id = None # 缓存mail_id
|
||||||
|
|
||||||
|
def refresh_inbox(self) -> None:
|
||||||
|
"""Refresh the email inbox"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def check_for_cursor_email(self) -> bool:
|
||||||
|
"""Check if there is a verification email from Cursor
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if verification email exists, False otherwise
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
params = {
|
||||||
|
'email': self.email,
|
||||||
|
'epin': self.epin
|
||||||
|
}
|
||||||
|
response = requests.get(
|
||||||
|
f"{self.base_url}/mails",
|
||||||
|
params=params,
|
||||||
|
headers=self.headers,
|
||||||
|
cookies=self.cookies
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
if data.get('result') and data.get('mail_list'):
|
||||||
|
for mail in data['mail_list']:
|
||||||
|
if 'cursor.sh' in mail.get('from_mail', '') and mail.get('is_new') == True:
|
||||||
|
self._cached_mail_id = mail.get('mail_id') # 缓存mail_id
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f"检查Cursor邮件失败: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_verification_code(self) -> str:
|
||||||
|
"""Get the verification code from the email
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The verification code if found, empty string otherwise
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 如果没有缓存的mail_id,先检查是否有新邮件
|
||||||
|
if not self._cached_mail_id:
|
||||||
|
if not self.check_for_cursor_email():
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# 使用缓存的mail_id获取邮件内容
|
||||||
|
params = {
|
||||||
|
'email': self.email,
|
||||||
|
'epin': self.epin
|
||||||
|
}
|
||||||
|
response = requests.get(
|
||||||
|
f"{self.base_url}/mails/{self._cached_mail_id}",
|
||||||
|
params=params,
|
||||||
|
headers=self.headers,
|
||||||
|
cookies=self.cookies
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
if not data.get('result'):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Extract verification code from text content using regex
|
||||||
|
text = data.get('text', '')
|
||||||
|
match = re.search(r'\n\n(\d{6})\n\n', text)
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
|
||||||
|
return ""
|
||||||
|
except Exception as e:
|
||||||
|
print(f"获取验证码失败: {str(e)}")
|
||||||
|
return ""
|
@ -211,7 +211,18 @@
|
|||||||
"try_install_browser": "Try installing the browser with your package manager",
|
"try_install_browser": "Try installing the browser with your package manager",
|
||||||
"tracking_processes": "Tracking {count} {browser} processes",
|
"tracking_processes": "Tracking {count} {browser} processes",
|
||||||
"no_new_processes_detected": "No new {browser} processes detected to track",
|
"no_new_processes_detected": "No new {browser} processes detected to track",
|
||||||
"could_not_track_processes": "Could not track {browser} processes: {error}"
|
"could_not_track_processes": "Could not track {browser} processes: {error}",
|
||||||
|
"using_tempmail_plus": "Using TempMailPlus for email verification",
|
||||||
|
"tempmail_plus_enabled": "TempMailPlus is enabled",
|
||||||
|
"tempmail_plus_disabled": "TempMailPlus is disabled",
|
||||||
|
"tempmail_plus_config_missing": "TempMailPlus configuration is missing",
|
||||||
|
"tempmail_plus_email_missing": "TempMailPlus email is not configured",
|
||||||
|
"tempmail_plus_epin_missing": "TempMailPlus epin is not configured",
|
||||||
|
"tempmail_plus_initialized": "TempMailPlus initialized successfully",
|
||||||
|
"tempmail_plus_init_failed": "Failed to initialize TempMailPlus: {error}",
|
||||||
|
"tempmail_plus_verification_started": "Starting TempMailPlus verification process",
|
||||||
|
"tempmail_plus_verification_completed": "TempMailPlus verification completed successfully",
|
||||||
|
"tempmail_plus_verification_failed": "TempMailPlus verification failed: {error}"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"title": "Cursor Auth Manager",
|
"title": "Cursor Auth Manager",
|
||||||
|
@ -211,7 +211,18 @@
|
|||||||
"no_new_processes_detected": "未检测到新的 {browser} 进程",
|
"no_new_processes_detected": "未检测到新的 {browser} 进程",
|
||||||
"could_not_track_processes": "无法跟踪 {browser} 进程: {error}",
|
"could_not_track_processes": "无法跟踪 {browser} 进程: {error}",
|
||||||
"human_verify_error": "无法验证用户是人类,正在重试...",
|
"human_verify_error": "无法验证用户是人类,正在重试...",
|
||||||
"max_retries_reached": "已达到最大重试次数,注册失败。"
|
"max_retries_reached": "已达到最大重试次数,注册失败。",
|
||||||
|
"using_tempmail_plus": "使用TempMailPlus进行邮箱验证",
|
||||||
|
"tempmail_plus_enabled": "TempMailPlus已启用",
|
||||||
|
"tempmail_plus_disabled": "TempMailPlus已禁用",
|
||||||
|
"tempmail_plus_config_missing": "TempMailPlus配置缺失",
|
||||||
|
"tempmail_plus_email_missing": "未配置TempMailPlus邮箱",
|
||||||
|
"tempmail_plus_epin_missing": "未配置TempMailPlus epin",
|
||||||
|
"tempmail_plus_initialized": "TempMailPlus初始化成功",
|
||||||
|
"tempmail_plus_init_failed": "TempMailPlus初始化失败:{error}",
|
||||||
|
"tempmail_plus_verification_started": "开始TempMailPlus验证流程",
|
||||||
|
"tempmail_plus_verification_completed": "TempMailPlus验证成功完成",
|
||||||
|
"tempmail_plus_verification_failed": "TempMailPlus验证失败:{error}"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"title": "Cursor 认证管理器",
|
"title": "Cursor 认证管理器",
|
||||||
@ -649,7 +660,9 @@
|
|||||||
"found_chrome_at": "找到 Chrome: {path}",
|
"found_chrome_at": "找到 Chrome: {path}",
|
||||||
"found_browser_user_data_dir": "找到 {browser} 用户数据目录: {path}",
|
"found_browser_user_data_dir": "找到 {browser} 用户数据目录: {path}",
|
||||||
"select_profile": "选择要使用的 {browser} 配置文件:",
|
"select_profile": "选择要使用的 {browser} 配置文件:",
|
||||||
"profile_list": "可用 {browser} 配置文件:"
|
"profile_list": "可用 {browser} 配置文件:",
|
||||||
|
"chrome_permissions_fixed": "已修复 Chrome 用户数据目录权限",
|
||||||
|
"chrome_permissions_fix_failed": "修复 Chrome 权限失败: {error}"
|
||||||
},
|
},
|
||||||
"browser_profile": {
|
"browser_profile": {
|
||||||
"title": "浏览器配置文件选择",
|
"title": "浏览器配置文件选择",
|
||||||
|
@ -212,6 +212,17 @@
|
|||||||
"could_not_track_processes": "無法跟踪{瀏覽器}進程:{error}",
|
"could_not_track_processes": "無法跟踪{瀏覽器}進程:{error}",
|
||||||
"human_verify_error": "無法驗證用戶是人類。重試...",
|
"human_verify_error": "無法驗證用戶是人類。重試...",
|
||||||
"tracking_processes": "跟踪{count} {瀏覽器}進程"
|
"tracking_processes": "跟踪{count} {瀏覽器}進程"
|
||||||
|
"using_tempmail_plus": "使用TempMailPlus進行郵箱驗證",
|
||||||
|
"tempmail_plus_enabled": "TempMailPlus已啟用",
|
||||||
|
"tempmail_plus_disabled": "TempMailPlus已禁用",
|
||||||
|
"tempmail_plus_config_missing": "TempMailPlus配置缺失",
|
||||||
|
"tempmail_plus_email_missing": "未配置TempMailPlus郵箱",
|
||||||
|
"tempmail_plus_epin_missing": "未配置TempMailPlus epin",
|
||||||
|
"tempmail_plus_initialized": "TempMailPlus初始化成功",
|
||||||
|
"tempmail_plus_init_failed": "TempMailPlus初始化失敗:{error}",
|
||||||
|
"tempmail_plus_verification_started": "開始TempMailPlus驗證流程",
|
||||||
|
"tempmail_plus_verification_completed": "TempMailPlus驗證成功完成",
|
||||||
|
"tempmail_plus_verification_failed": "TempMailPlus驗證失敗:{error}"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"title": "Cursor 認證管理器",
|
"title": "Cursor 認證管理器",
|
||||||
|
@ -483,6 +483,25 @@ class OAuthHandler:
|
|||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.error_configuring_browser_options', error=str(e)) if self.translator else f'Error configuring browser options: {e}'}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.error_configuring_browser_options', error=str(e)) if self.translator else f'Error configuring browser options: {e}'}{Style.RESET_ALL}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
def _fix_chrome_permissions(self, user_data_dir):
|
||||||
|
"""Fix permissions for Chrome user data directory"""
|
||||||
|
try:
|
||||||
|
if sys.platform == 'darwin': # macOS
|
||||||
|
import subprocess
|
||||||
|
import pwd
|
||||||
|
|
||||||
|
# Get current user
|
||||||
|
current_user = pwd.getpwuid(os.getuid()).pw_name
|
||||||
|
|
||||||
|
# Fix permissions for Chrome directory
|
||||||
|
chrome_dir = os.path.expanduser('~/Library/Application Support/Google/Chrome')
|
||||||
|
if os.path.exists(chrome_dir):
|
||||||
|
subprocess.run(['chmod', '-R', 'u+rwX', chrome_dir])
|
||||||
|
subprocess.run(['chown', '-R', f'{current_user}:staff', chrome_dir])
|
||||||
|
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.chrome_permissions_fixed') if self.translator else 'Fixed Chrome user data directory permissions'}{Style.RESET_ALL}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('oauth.chrome_permissions_fix_failed', error=str(e)) if self.translator else f'Failed to fix Chrome permissions: {str(e)}'}{Style.RESET_ALL}")
|
||||||
|
|
||||||
def handle_google_auth(self):
|
def handle_google_auth(self):
|
||||||
"""Handle Google OAuth authentication"""
|
"""Handle Google OAuth authentication"""
|
||||||
try:
|
try:
|
||||||
@ -493,6 +512,9 @@ class OAuthHandler:
|
|||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.browser_failed') if self.translator else 'Browser failed to initialize'}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.browser_failed') if self.translator else 'Browser failed to initialize'}{Style.RESET_ALL}")
|
||||||
return False, None
|
return False, None
|
||||||
|
|
||||||
|
# Get user data directory for later use
|
||||||
|
user_data_dir = self._get_user_data_directory()
|
||||||
|
|
||||||
# Navigate to auth URL
|
# Navigate to auth URL
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.navigating_to_authentication_page') if self.translator else 'Navigating to authentication page...'}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.navigating_to_authentication_page') if self.translator else 'Navigating to authentication page...'}{Style.RESET_ALL}")
|
||||||
@ -556,6 +578,8 @@ class OAuthHandler:
|
|||||||
try:
|
try:
|
||||||
if self.browser:
|
if self.browser:
|
||||||
self.browser.quit()
|
self.browser.quit()
|
||||||
|
# Fix Chrome permissions after browser is closed
|
||||||
|
self._fix_chrome_permissions(user_data_dir)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user