mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-10-05 01:02:48 +08:00
Add manual Cursor registration with manual email input
This commit is contained in:
260
cursor_register_manual.py
Normal file
260
cursor_register_manual.py
Normal file
@@ -0,0 +1,260 @@
|
||||
import os
|
||||
from colorama import Fore, Style, init
|
||||
import time
|
||||
import random
|
||||
from browser import BrowserManager
|
||||
from control import BrowserControl
|
||||
from cursor_auth import CursorAuth
|
||||
from reset_machine_manual import MachineIDResetter
|
||||
|
||||
os.environ["PYTHONVERBOSE"] = "0"
|
||||
os.environ["PYINSTALLER_VERBOSE"] = "0"
|
||||
|
||||
# 初始化colorama
|
||||
init()
|
||||
|
||||
# 定义emoji常量
|
||||
EMOJI = {
|
||||
'START': '🚀',
|
||||
'FORM': '📝',
|
||||
'VERIFY': '🔄',
|
||||
'PASSWORD': '🔑',
|
||||
'CODE': '📱',
|
||||
'DONE': '✨',
|
||||
'ERROR': '❌',
|
||||
'WAIT': '⏳',
|
||||
'SUCCESS': '✅',
|
||||
'MAIL': '📧',
|
||||
'KEY': '🔐',
|
||||
'UPDATE': '🔄',
|
||||
'INFO': 'ℹ️'
|
||||
}
|
||||
|
||||
class CursorRegistration:
|
||||
def __init__(self, translator=None):
|
||||
self.translator = translator
|
||||
# 设置为显示模式
|
||||
os.environ['BROWSER_HEADLESS'] = 'False'
|
||||
self.browser_manager = BrowserManager()
|
||||
self.browser = None
|
||||
self.controller = None
|
||||
self.sign_up_url = "https://authenticator.cursor.sh/sign-up"
|
||||
self.settings_url = "https://www.cursor.com/settings"
|
||||
self.email_address = None
|
||||
self.signup_tab = None
|
||||
self.email_tab = None
|
||||
|
||||
# 账号信息
|
||||
self.password = self._generate_password()
|
||||
self.first_name = self._generate_name()
|
||||
self.last_name = self._generate_name()
|
||||
|
||||
def _generate_password(self, length=12):
|
||||
"""Generate Random Password"""
|
||||
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"
|
||||
return ''.join(random.choices(chars, k=length))
|
||||
|
||||
def _generate_name(self, length=6):
|
||||
"""Generate Random Name"""
|
||||
first_letter = random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
rest_letters = ''.join(random.choices("abcdefghijklmnopqrstuvwxyz", k=length-1))
|
||||
return first_letter + rest_letters
|
||||
|
||||
def setup_email(self):
|
||||
"""设置邮箱"""
|
||||
try:
|
||||
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.manual_email_input') if self.translator else '请输入邮箱地址:'}")
|
||||
self.email_address = input().strip()
|
||||
|
||||
if '@' not in self.email_address:
|
||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.invalid_email') if self.translator else '无效的邮箱地址'}{Style.RESET_ALL}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.email_setup_failed', error=str(e))}{Style.RESET_ALL}")
|
||||
return False
|
||||
|
||||
def get_verification_code(self):
|
||||
"""手动获取验证码"""
|
||||
try:
|
||||
print(f"{Fore.CYAN}{EMOJI['CODE']} {self.translator.get('register.manual_code_input') if self.translator else '请输入验证码:'}{Style.RESET_ALL}")
|
||||
code = input().strip()
|
||||
|
||||
if not code.isdigit() or len(code) != 6:
|
||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.invalid_code') if self.translator else '无效的验证码'}{Style.RESET_ALL}")
|
||||
return None
|
||||
|
||||
return code
|
||||
|
||||
except Exception as e:
|
||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.code_input_failed', error=str(e))}{Style.RESET_ALL}")
|
||||
return None
|
||||
|
||||
def register_cursor(self):
|
||||
"""注册 Cursor"""
|
||||
browser_tab = None
|
||||
try:
|
||||
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.register_start')}...{Style.RESET_ALL}")
|
||||
|
||||
# 直接使用 new_signup.py 进行注册
|
||||
from new_signup import main as new_signup_main
|
||||
|
||||
# 执行新的注册流程,传入 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
|
||||
translator=self.translator
|
||||
)
|
||||
|
||||
if result:
|
||||
# 使用返回的浏览器实例获取账户信息
|
||||
self.signup_tab = browser_tab # 保存浏览器实例
|
||||
success = self._get_account_info()
|
||||
|
||||
# 获取信息后关闭浏览器
|
||||
if browser_tab:
|
||||
try:
|
||||
browser_tab.quit()
|
||||
except:
|
||||
pass
|
||||
|
||||
return success
|
||||
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.register_process_error', error=str(e))}{Style.RESET_ALL}")
|
||||
return False
|
||||
finally:
|
||||
# 确保在任何情况下都关闭浏览器
|
||||
if browser_tab:
|
||||
try:
|
||||
browser_tab.quit()
|
||||
except:
|
||||
pass
|
||||
|
||||
def _get_account_info(self):
|
||||
"""获取账户信息和 Token"""
|
||||
try:
|
||||
self.signup_tab.get(self.settings_url)
|
||||
time.sleep(2)
|
||||
|
||||
usage_selector = (
|
||||
"css:div.col-span-2 > div > div > div > div > "
|
||||
"div:nth-child(1) > div.flex.items-center.justify-between.gap-2 > "
|
||||
"span.font-mono.text-sm\\/\\[0\\.875rem\\]"
|
||||
)
|
||||
usage_ele = self.signup_tab.ele(usage_selector)
|
||||
total_usage = "未知"
|
||||
if usage_ele:
|
||||
total_usage = usage_ele.text.split("/")[-1].strip()
|
||||
|
||||
print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('register.get_token')}...{Style.RESET_ALL}")
|
||||
max_attempts = 30
|
||||
retry_interval = 2
|
||||
attempts = 0
|
||||
|
||||
while attempts < max_attempts:
|
||||
try:
|
||||
cookies = self.signup_tab.cookies()
|
||||
for cookie in cookies:
|
||||
if cookie.get("name") == "WorkosCursorSessionToken":
|
||||
token = cookie["value"].split("%3A%3A")[1]
|
||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.token_success')}{Style.RESET_ALL}")
|
||||
self._save_account_info(token, total_usage)
|
||||
return True
|
||||
|
||||
attempts += 1
|
||||
if attempts < max_attempts:
|
||||
print(f"{Fore.YELLOW}{EMOJI['WAIT']} {self.translator.get('register.token_attempt', attempt=attempts, time=retry_interval)}{Style.RESET_ALL}")
|
||||
time.sleep(retry_interval)
|
||||
else:
|
||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.token_max_attempts', max=max_attempts)}{Style.RESET_ALL}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.token_failed', error=str(e))}{Style.RESET_ALL}")
|
||||
attempts += 1
|
||||
if attempts < max_attempts:
|
||||
print(f"{Fore.YELLOW}{EMOJI['WAIT']} {self.translator.get('register.token_attempt', attempt=attempts, time=retry_interval)}{Style.RESET_ALL}")
|
||||
time.sleep(retry_interval)
|
||||
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.account_error', error=str(e))}{Style.RESET_ALL}")
|
||||
return False
|
||||
|
||||
def _save_account_info(self, token, total_usage):
|
||||
"""保存账户信息到文件"""
|
||||
try:
|
||||
# 先更新认证信息
|
||||
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
|
||||
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方法
|
||||
raise Exception("Failed to reset machine ID")
|
||||
|
||||
# 保存账户信息到文件
|
||||
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")
|
||||
f.write(f"Password: {self.password}\n")
|
||||
f.write(f"Token: {token}\n")
|
||||
f.write(f"Usage Limit: {total_usage}\n")
|
||||
f.write(f"{'='*50}\n")
|
||||
|
||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.account_info_saved')}...{Style.RESET_ALL}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.save_account_info_failed', error=str(e))}{Style.RESET_ALL}")
|
||||
return False
|
||||
|
||||
def start(self):
|
||||
"""启动注册流程"""
|
||||
try:
|
||||
if self.setup_email():
|
||||
if self.register_cursor():
|
||||
print(f"\n{Fore.GREEN}{EMOJI['DONE']} {self.translator.get('register.cursor_registration_completed')}...{Style.RESET_ALL}")
|
||||
return True
|
||||
return False
|
||||
finally:
|
||||
# 关闭邮箱标签页
|
||||
if hasattr(self, 'temp_email'):
|
||||
try:
|
||||
self.temp_email.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
def update_cursor_auth(self, email=None, access_token=None, refresh_token=None):
|
||||
"""更新Cursor的认证信息的便捷函数"""
|
||||
auth_manager = CursorAuth(translator=self.translator)
|
||||
return auth_manager.update_auth(email, access_token, refresh_token)
|
||||
|
||||
def main(translator=None):
|
||||
"""Main function to be called from main.py"""
|
||||
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||
print(f"{Fore.CYAN}{EMOJI['START']} {translator.get('register.title')}{Style.RESET_ALL}")
|
||||
print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||
|
||||
registration = CursorRegistration(translator)
|
||||
registration.start()
|
||||
|
||||
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||
input(f"{EMOJI['INFO']} {translator.get('register.press_enter')}...")
|
||||
|
||||
if __name__ == "__main__":
|
||||
from main import translator as main_translator
|
||||
main(main_translator)
|
Reference in New Issue
Block a user