cursor-free-vip/cursor_register_manual.py

291 lines
13 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from colorama import Fore, Style, init
import time
import random
from faker import Faker
from cursor_auth import CursorAuth
from reset_machine_manual import MachineIDResetter
from get_user_token import get_token_from_cookie
from config import get_config
from account_manager import AccountManager
os.environ["PYTHONVERBOSE"] = "0"
os.environ["PYINSTALLER_VERBOSE"] = "0"
# Initialize colorama
init()
# Define emoji constants
EMOJI = {
'START': '🚀',
'FORM': '📝',
'VERIFY': '🔄',
'PASSWORD': '🔑',
'CODE': '📱',
'DONE': '',
'ERROR': '',
'WAIT': '',
'SUCCESS': '',
'MAIL': '📧',
'KEY': '🔐',
'UPDATE': '🔄',
'INFO': ''
}
class CursorRegistration:
def __init__(self, translator=None):
self.translator = translator
# Set to display mode
os.environ['BROWSER_HEADLESS'] = 'False'
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
# initialize Faker instance
self.faker = Faker()
# generate account information
self.password = self._generate_password()
self.first_name = self.faker.first_name()
self.last_name = self.faker.last_name()
# modify the first letter of the first name(keep the original function)
new_first_letter = random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
self.first_name = new_first_letter + self.first_name[1:]
print(f"\n{Fore.CYAN}{EMOJI['PASSWORD']} {self.translator.get('register.password')}: {self.password} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['FORM']} {self.translator.get('register.first_name')}: {self.first_name} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['FORM']} {self.translator.get('register.last_name')}: {self.last_name} {Style.RESET_ALL}")
def _generate_password(self, length=12):
"""Generate password"""
return self.faker.password(length=length, special_chars=True, digits=True, upper_case=True, lower_case=True)
def setup_email(self):
"""Setup Email"""
try:
# Try to get a suggested email
account_manager = AccountManager(self.translator)
suggested_email = account_manager.suggest_email(self.first_name, self.last_name)
if suggested_email:
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.suggest_email', suggested_email=suggested_email) if self.translator else f'Suggested email: {suggested_email}'}")
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.use_suggested_email_or_enter') if self.translator else 'Type "yes" to use this email or enter your own email:'}")
user_input = input().strip()
if user_input.lower() == 'yes' or user_input.lower() == 'y':
self.email_address = suggested_email
else:
# User input is their own email address
self.email_address = user_input
else:
# If there's no suggested email
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()
# Validate if the email is valid
if '@' not in self.email_address:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.invalid_email') if self.translator else 'Invalid email address'}{Style.RESET_ALL}")
return False
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('register.email_address')}: {self.email_address}" + "\n" + f"{Style.RESET_ALL}")
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):
"""Manually Get Verification Code"""
try:
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:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.invalid_code') if self.translator else 'Invalid verification code'}{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):
"""Register Cursor"""
browser_tab = None
try:
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, self.translator)
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('register.using_tempmail_plus')}{Style.RESET_ALL}")
# Use new_signup.py directly for registration
from new_signup import main as new_signup_main
# 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=email_tab, # Pass email_tab if tempmail_plus is enabled
controller=self, # Pass self instead of self.controller
translator=self.translator
)
if result:
# 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()
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:
# Ensure browser is closed in any case
if browser_tab:
try:
browser_tab.quit()
except:
pass
def _get_account_info(self):
"""Get Account Information and 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"Total Usage: {total_usage}\n")
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 = get_token_from_cookie(cookie["value"], self.translator)
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):
"""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, auth_type="Auth_0"):
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}")
# Reset machine ID
print(f"{Fore.CYAN}{EMOJI['UPDATE']} {self.translator.get('register.reset_machine_id')}...{Style.RESET_ALL}")
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 using AccountManager
account_manager = AccountManager(self.translator)
if account_manager.save_account_info(self.email_address, self.password, token, total_usage):
return True
else:
return False
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):
"""Start Registration Process"""
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:
# Close email tab
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, auth_type="Auth_0"):
"""Convenient function to update Cursor authentication information"""
auth_manager = CursorAuth(translator=self.translator)
return auth_manager.update_auth(email, access_token, refresh_token, auth_type)
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)