mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-04-24 08:25:23 +00:00
692 lines
30 KiB
Python
692 lines
30 KiB
Python
from DrissionPage import ChromiumOptions, ChromiumPage
|
|
import time
|
|
import os
|
|
import signal
|
|
import random
|
|
from colorama import Fore, Style
|
|
import configparser
|
|
from pathlib import Path
|
|
import sys
|
|
from config import get_config
|
|
from utils import get_default_browser_path as utils_get_default_browser_path
|
|
|
|
# Add global variable at the beginning of the file
|
|
_translator = None
|
|
|
|
# Add global variable to track our Chrome processes
|
|
_chrome_process_ids = []
|
|
|
|
def cleanup_chrome_processes(translator=None):
|
|
"""Clean only Chrome processes launched by this script"""
|
|
global _chrome_process_ids
|
|
|
|
if not _chrome_process_ids:
|
|
print("\nNo Chrome processes to clean...")
|
|
return
|
|
|
|
print("\nCleaning Chrome processes launched by this script...")
|
|
try:
|
|
if os.name == 'nt':
|
|
for pid in _chrome_process_ids:
|
|
try:
|
|
os.system(f'taskkill /F /PID {pid} /T 2>nul')
|
|
except:
|
|
pass
|
|
else:
|
|
for pid in _chrome_process_ids:
|
|
try:
|
|
os.kill(pid, signal.SIGTERM)
|
|
except:
|
|
pass
|
|
_chrome_process_ids = [] # Reset the list after cleanup
|
|
except Exception as e:
|
|
if translator:
|
|
print(f"{Fore.RED}❌ {translator.get('register.cleanup_error', error=str(e))}{Style.RESET_ALL}")
|
|
else:
|
|
print(f"清理进程时出错: {e}")
|
|
|
|
def signal_handler(signum, frame):
|
|
"""Handle Ctrl+C signal"""
|
|
global _translator
|
|
if _translator:
|
|
print(f"{Fore.CYAN}{_translator.get('register.exit_signal')}{Style.RESET_ALL}")
|
|
else:
|
|
print("\n接收到退出信号,正在关闭...")
|
|
cleanup_chrome_processes(_translator)
|
|
os._exit(0)
|
|
|
|
def simulate_human_input(page, url, config, translator=None):
|
|
"""Visit URL"""
|
|
if translator:
|
|
print(f"{Fore.CYAN}🚀 {translator.get('register.visiting_url')}: {url}{Style.RESET_ALL}")
|
|
|
|
# First visit blank page
|
|
page.get('about:blank')
|
|
time.sleep(get_random_wait_time(config, 'page_load_wait'))
|
|
|
|
# Visit target page
|
|
page.get(url)
|
|
time.sleep(get_random_wait_time(config, 'page_load_wait'))
|
|
|
|
def fill_signup_form(page, first_name, last_name, email, config, translator=None):
|
|
"""Fill signup form"""
|
|
try:
|
|
if translator:
|
|
print(f"{Fore.CYAN}📧 {translator.get('register.filling_form')}{Style.RESET_ALL}")
|
|
else:
|
|
print("\n正在填写注册表单...")
|
|
|
|
# Fill first name
|
|
first_name_input = page.ele("@name=first_name")
|
|
if first_name_input:
|
|
first_name_input.input(first_name)
|
|
time.sleep(get_random_wait_time(config, 'input_wait'))
|
|
|
|
# Fill last name
|
|
last_name_input = page.ele("@name=last_name")
|
|
if last_name_input:
|
|
last_name_input.input(last_name)
|
|
time.sleep(get_random_wait_time(config, 'input_wait'))
|
|
|
|
# Fill email
|
|
email_input = page.ele("@name=email")
|
|
if email_input:
|
|
email_input.input(email)
|
|
time.sleep(get_random_wait_time(config, 'input_wait'))
|
|
|
|
# Click submit button
|
|
submit_button = page.ele("@type=submit")
|
|
if submit_button:
|
|
submit_button.click()
|
|
time.sleep(get_random_wait_time(config, 'submit_wait'))
|
|
|
|
if translator:
|
|
print(f"{Fore.GREEN}✅ {translator.get('register.form_success')}{Style.RESET_ALL}")
|
|
else:
|
|
print("Form filled successfully")
|
|
return True
|
|
|
|
except Exception as e:
|
|
if translator:
|
|
print(f"{Fore.RED}❌ {translator.get('register.form_error', error=str(e))}{Style.RESET_ALL}")
|
|
else:
|
|
print(f"Error filling form: {e}")
|
|
return False
|
|
|
|
def get_user_documents_path():
|
|
"""Get user Documents folder path"""
|
|
if sys.platform == "win32":
|
|
return os.path.join(os.path.expanduser("~"), "Documents")
|
|
elif sys.platform == "darwin":
|
|
return os.path.join(os.path.expanduser("~"), "Documents")
|
|
else: # Linux
|
|
# Get actual user's home directory
|
|
sudo_user = os.environ.get('SUDO_USER')
|
|
if sudo_user:
|
|
return os.path.join("/home", sudo_user, "Documents")
|
|
return os.path.join(os.path.expanduser("~"), "Documents")
|
|
|
|
def get_random_wait_time(config, timing_type='page_load_wait'):
|
|
"""
|
|
Get random wait time from config
|
|
Args:
|
|
config: ConfigParser object
|
|
timing_type: Type of timing to get (page_load_wait, input_wait, submit_wait)
|
|
Returns:
|
|
float: Random wait time or fixed time
|
|
"""
|
|
try:
|
|
if not config.has_section('Timing'):
|
|
return random.uniform(0.1, 0.8) # Default value
|
|
|
|
if timing_type == 'random':
|
|
min_time = float(config.get('Timing', 'min_random_time', fallback='0.1'))
|
|
max_time = float(config.get('Timing', 'max_random_time', fallback='0.8'))
|
|
return random.uniform(min_time, max_time)
|
|
|
|
time_value = config.get('Timing', timing_type, fallback='0.1-0.8')
|
|
|
|
# Check if it's a fixed time value
|
|
if '-' not in time_value and ',' not in time_value:
|
|
return float(time_value) # Return fixed time
|
|
|
|
# Process range time
|
|
min_time, max_time = map(float, time_value.split('-' if '-' in time_value else ','))
|
|
return random.uniform(min_time, max_time)
|
|
except:
|
|
return random.uniform(0.1, 0.8) # Return default value when error
|
|
|
|
def setup_driver(translator=None):
|
|
"""Setup browser driver"""
|
|
global _chrome_process_ids
|
|
|
|
try:
|
|
# Get config
|
|
config = get_config(translator)
|
|
|
|
# Get browser type and path
|
|
browser_type = config.get('Browser', 'default_browser', fallback='chrome')
|
|
browser_path = config.get('Browser', f'{browser_type}_path', fallback=utils_get_default_browser_path(browser_type))
|
|
|
|
if not browser_path or not os.path.exists(browser_path):
|
|
if translator:
|
|
print(f"{Fore.YELLOW}⚠️ {browser_type} {translator.get('register.browser_path_invalid')}{Style.RESET_ALL}")
|
|
browser_path = utils_get_default_browser_path(browser_type)
|
|
|
|
# For backward compatibility, also check Chrome path
|
|
if browser_type == 'chrome':
|
|
chrome_path = config.get('Chrome', 'chromepath', fallback=None)
|
|
if chrome_path and os.path.exists(chrome_path):
|
|
browser_path = chrome_path
|
|
|
|
# Set browser options
|
|
co = ChromiumOptions()
|
|
|
|
# Set browser path
|
|
co.set_browser_path(browser_path)
|
|
|
|
# Use incognito mode
|
|
co.set_argument("--incognito")
|
|
|
|
if sys.platform == "linux":
|
|
# Set Linux specific options
|
|
co.set_argument("--no-sandbox")
|
|
|
|
# Set random port
|
|
co.auto_port()
|
|
|
|
# Use headless mode (must be set to False, simulate human operation)
|
|
co.headless(False)
|
|
|
|
# Log browser info
|
|
if translator:
|
|
print(f"{Fore.CYAN}🌐 {translator.get('register.using_browser', browser=browser_type, path=browser_path)}{Style.RESET_ALL}")
|
|
|
|
try:
|
|
# Load extension
|
|
extension_path = os.path.join(os.getcwd(), "turnstilePatch")
|
|
if os.path.exists(extension_path):
|
|
co.set_argument("--allow-extensions-in-incognito")
|
|
co.add_extension(extension_path)
|
|
except Exception as e:
|
|
if translator:
|
|
print(f"{Fore.RED}❌ {translator.get('register.extension_load_error', error=str(e))}{Style.RESET_ALL}")
|
|
else:
|
|
print(f"Error loading extension: {e}")
|
|
|
|
if translator:
|
|
print(f"{Fore.CYAN}🚀 {translator.get('register.starting_browser')}{Style.RESET_ALL}")
|
|
else:
|
|
print("Starting browser...")
|
|
|
|
# Record Chrome processes before launching
|
|
before_pids = []
|
|
try:
|
|
import psutil
|
|
browser_process_names = {
|
|
'chrome': ['chrome', 'chromium'],
|
|
'edge': ['msedge', 'edge'],
|
|
'firefox': ['firefox'],
|
|
'brave': ['brave', 'brave-browser']
|
|
}
|
|
process_names = browser_process_names.get(browser_type, ['chrome'])
|
|
before_pids = [p.pid for p in psutil.process_iter() if any(name in p.name().lower() for name in process_names)]
|
|
except:
|
|
pass
|
|
|
|
# Launch browser
|
|
page = ChromiumPage(co)
|
|
|
|
# Wait a moment for browser to fully launch
|
|
time.sleep(1)
|
|
|
|
# Record browser processes after launching and find new ones
|
|
try:
|
|
import psutil
|
|
process_names = browser_process_names.get(browser_type, ['chrome'])
|
|
after_pids = [p.pid for p in psutil.process_iter() if any(name in p.name().lower() for name in process_names)]
|
|
# Find new browser processes
|
|
new_pids = [pid for pid in after_pids if pid not in before_pids]
|
|
_chrome_process_ids.extend(new_pids)
|
|
|
|
if _chrome_process_ids:
|
|
print(f"{translator.get('register.tracking_processes', count=len(_chrome_process_ids), browser=browser_type)}")
|
|
else:
|
|
print(f"{Fore.YELLOW}Warning: {translator.get('register.no_new_processes_detected', browser=browser_type)}{Style.RESET_ALL}")
|
|
except Exception as e:
|
|
print(f"{translator.get('register.could_not_track_processes', browser=browser_type, error=str(e))}")
|
|
|
|
return config, page
|
|
|
|
except Exception as e:
|
|
if translator:
|
|
print(f"{Fore.RED}❌ {translator.get('register.browser_setup_error', error=str(e))}{Style.RESET_ALL}")
|
|
else:
|
|
print(f"Error setting up browser: {e}")
|
|
raise
|
|
|
|
def handle_turnstile(page, config, translator=None):
|
|
"""Handle Turnstile verification"""
|
|
try:
|
|
if translator:
|
|
print(f"{Fore.CYAN}🔄 {translator.get('register.handling_turnstile')}{Style.RESET_ALL}")
|
|
else:
|
|
print("\nHandling Turnstile verification...")
|
|
|
|
# from config
|
|
turnstile_time = float(config.get('Turnstile', 'handle_turnstile_time', fallback='2'))
|
|
random_time_str = config.get('Turnstile', 'handle_turnstile_random_time', fallback='1-3')
|
|
|
|
# Parse random time range
|
|
try:
|
|
min_time, max_time = map(float, random_time_str.split('-'))
|
|
except:
|
|
min_time, max_time = 1, 3 # Default value
|
|
|
|
max_retries = 2
|
|
retry_count = 0
|
|
|
|
while retry_count < max_retries:
|
|
retry_count += 1
|
|
if translator:
|
|
print(f"{Fore.CYAN}🔄 {translator.get('register.retry_verification', attempt=retry_count)}{Style.RESET_ALL}")
|
|
else:
|
|
print(f"Attempt {retry_count} of verification...")
|
|
|
|
try:
|
|
# Try to reset turnstile
|
|
page.run_js("try { turnstile.reset() } catch(e) { }")
|
|
time.sleep(turnstile_time) # from config
|
|
|
|
# Locate verification box element
|
|
challenge_check = (
|
|
page.ele("@id=cf-turnstile", timeout=2)
|
|
.child()
|
|
.shadow_root.ele("tag:iframe")
|
|
.ele("tag:body")
|
|
.sr("tag:input")
|
|
)
|
|
|
|
if challenge_check:
|
|
if translator:
|
|
print(f"{Fore.CYAN}🔄 {translator.get('register.detect_turnstile')}{Style.RESET_ALL}")
|
|
else:
|
|
print("Detected verification box...")
|
|
|
|
# from config
|
|
time.sleep(random.uniform(min_time, max_time))
|
|
challenge_check.click()
|
|
time.sleep(turnstile_time) # from config
|
|
|
|
# check verification result
|
|
if check_verification_success(page, translator):
|
|
if translator:
|
|
print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}")
|
|
else:
|
|
print("Verification successful!")
|
|
return True
|
|
|
|
except Exception as e:
|
|
if translator:
|
|
print(f"{Fore.RED}❌ {translator.get('register.verification_failed')}{Style.RESET_ALL}")
|
|
else:
|
|
print(f"Verification attempt failed: {e}")
|
|
|
|
# Check if verification has been successful
|
|
if check_verification_success(page, translator):
|
|
if translator:
|
|
print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}")
|
|
else:
|
|
print("Verification successful!")
|
|
return True
|
|
|
|
time.sleep(random.uniform(min_time, max_time))
|
|
|
|
if translator:
|
|
print(f"{Fore.RED}❌ {translator.get('register.verification_failed')}{Style.RESET_ALL}")
|
|
else:
|
|
print("Exceeded maximum retry attempts")
|
|
return False
|
|
|
|
except Exception as e:
|
|
if translator:
|
|
print(f"{Fore.RED}❌ {translator.get('register.verification_error', error=str(e))}{Style.RESET_ALL}")
|
|
else:
|
|
print(f"Error in verification process: {e}")
|
|
return False
|
|
|
|
def check_verification_success(page, translator=None):
|
|
"""Check if verification is successful"""
|
|
try:
|
|
# Check if there is a subsequent form element, indicating verification has passed
|
|
if (page.ele("@name=password", timeout=0.5) or
|
|
page.ele("@name=email", timeout=0.5) or
|
|
page.ele("@data-index=0", timeout=0.5) or
|
|
page.ele("Account Settings", timeout=0.5)):
|
|
return True
|
|
|
|
# Check if there is an error message
|
|
error_messages = [
|
|
'xpath://div[contains(text(), "Can\'t verify the user is human")]',
|
|
'xpath://div[contains(text(), "Error: 600010")]',
|
|
'xpath://div[contains(text(), "Please try again")]'
|
|
]
|
|
|
|
for error_xpath in error_messages:
|
|
if page.ele(error_xpath):
|
|
return False
|
|
|
|
return False
|
|
except:
|
|
return False
|
|
|
|
def generate_password(length=12):
|
|
"""Generate random password"""
|
|
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"
|
|
return ''.join(random.choices(chars, k=length))
|
|
|
|
def fill_password(page, password: str, config, translator=None):
|
|
"""
|
|
Fill password form
|
|
"""
|
|
try:
|
|
print(f"{Fore.CYAN}🔑 {translator.get('register.setting_password') if translator else 'Setting password'}{Style.RESET_ALL}")
|
|
|
|
# Fill password
|
|
password_input = page.ele("@name=password")
|
|
print(f"{Fore.CYAN}🔑 {translator.get('register.setting_on_password')}: {password}{Style.RESET_ALL}")
|
|
if password_input:
|
|
password_input.input(password)
|
|
|
|
# Click submit button
|
|
submit_button = page.ele("@type=submit")
|
|
if submit_button:
|
|
submit_button.click()
|
|
time.sleep(get_random_wait_time(config, 'submit_wait'))
|
|
|
|
print(f"{Fore.GREEN}✅ {translator.get('register.password_submitted') if translator else 'Password submitted'}{Style.RESET_ALL}")
|
|
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"{Fore.RED}❌ {translator.get('register.password_error', error=str(e)) if translator else f'Error setting password: {str(e)}'}{Style.RESET_ALL}")
|
|
|
|
return False
|
|
|
|
def handle_verification_code(browser_tab, email_tab, controller, config, translator=None):
|
|
"""Handle verification code"""
|
|
try:
|
|
if translator:
|
|
print(f"\n{Fore.CYAN}🔄 {translator.get('register.waiting_for_verification_code')}{Style.RESET_ALL}")
|
|
|
|
# Check if using manual input verification code
|
|
if hasattr(controller, 'get_verification_code') and email_tab is None: # Manual mode
|
|
verification_code = controller.get_verification_code()
|
|
if verification_code:
|
|
# Fill verification code in registration page
|
|
for i, digit in enumerate(verification_code):
|
|
browser_tab.ele(f"@data-index={i}").input(digit)
|
|
time.sleep(get_random_wait_time(config, 'verification_code_input'))
|
|
|
|
print(f"{translator.get('register.verification_success')}")
|
|
time.sleep(get_random_wait_time(config, 'verification_success_wait'))
|
|
|
|
# Handle last Turnstile verification
|
|
if handle_turnstile(browser_tab, config, translator):
|
|
if translator:
|
|
print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}")
|
|
time.sleep(get_random_wait_time(config, 'verification_retry_wait'))
|
|
|
|
# Visit settings page
|
|
print(f"{Fore.CYAN}🔑 {translator.get('register.visiting_url')}: https://www.cursor.com/settings{Style.RESET_ALL}")
|
|
browser_tab.get("https://www.cursor.com/settings")
|
|
time.sleep(get_random_wait_time(config, 'settings_page_load_wait'))
|
|
return True, browser_tab
|
|
|
|
return False, None
|
|
|
|
# Automatic verification code logic
|
|
elif email_tab:
|
|
print(f"{Fore.CYAN}🔄 {translator.get('register.waiting_for_verification_code')}{Style.RESET_ALL}")
|
|
time.sleep(get_random_wait_time(config, 'email_check_initial_wait'))
|
|
|
|
# Use existing email_tab to refresh email
|
|
email_tab.refresh_inbox()
|
|
time.sleep(get_random_wait_time(config, 'email_refresh_wait'))
|
|
|
|
# Check if there is a verification code email
|
|
if email_tab.check_for_cursor_email():
|
|
verification_code = email_tab.get_verification_code()
|
|
if verification_code:
|
|
# Fill verification code in registration page
|
|
for i, digit in enumerate(verification_code):
|
|
browser_tab.ele(f"@data-index={i}").input(digit)
|
|
time.sleep(get_random_wait_time(config, 'verification_code_input'))
|
|
|
|
if translator:
|
|
print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}")
|
|
time.sleep(get_random_wait_time(config, 'verification_success_wait'))
|
|
|
|
# Handle last Turnstile verification
|
|
if handle_turnstile(browser_tab, config, translator):
|
|
if translator:
|
|
print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}")
|
|
time.sleep(get_random_wait_time(config, 'verification_retry_wait'))
|
|
|
|
# Visit settings page
|
|
if translator:
|
|
print(f"{Fore.CYAN}🔑 {translator.get('register.visiting_url')}: https://www.cursor.com/settings{Style.RESET_ALL}")
|
|
browser_tab.get("https://www.cursor.com/settings")
|
|
time.sleep(get_random_wait_time(config, 'settings_page_load_wait'))
|
|
return True, browser_tab
|
|
|
|
else:
|
|
if translator:
|
|
print(f"{Fore.RED}❌ {translator.get('register.verification_failed')}{Style.RESET_ALL}")
|
|
else:
|
|
print("最后一次验证失败")
|
|
return False, None
|
|
|
|
# Get verification code, set timeout
|
|
verification_code = None
|
|
max_attempts = 20
|
|
retry_interval = get_random_wait_time(config, 'retry_interval') # Use get_random_wait_time
|
|
start_time = time.time()
|
|
timeout = float(config.get('Timing', 'max_timeout', fallback='160')) # This can be kept unchanged because it is a fixed value
|
|
|
|
if translator:
|
|
print(f"{Fore.CYAN}{translator.get('register.start_getting_verification_code')}{Style.RESET_ALL}")
|
|
|
|
for attempt in range(max_attempts):
|
|
# Check if timeout
|
|
if time.time() - start_time > timeout:
|
|
if translator:
|
|
print(f"{Fore.RED}❌ {translator.get('register.verification_timeout')}{Style.RESET_ALL}")
|
|
break
|
|
|
|
verification_code = controller.get_verification_code()
|
|
if verification_code:
|
|
if translator:
|
|
print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}")
|
|
break
|
|
|
|
remaining_time = int(timeout - (time.time() - start_time))
|
|
if translator:
|
|
print(f"{Fore.CYAN}{translator.get('register.try_get_code', attempt=attempt + 1, time=remaining_time)}{Style.RESET_ALL}")
|
|
|
|
# Refresh email
|
|
email_tab.refresh_inbox()
|
|
time.sleep(retry_interval) # Use get_random_wait_time
|
|
|
|
if verification_code:
|
|
# Fill verification code in registration page
|
|
for i, digit in enumerate(verification_code):
|
|
browser_tab.ele(f"@data-index={i}").input(digit)
|
|
time.sleep(get_random_wait_time(config, 'verification_code_input'))
|
|
|
|
if translator:
|
|
print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}")
|
|
time.sleep(get_random_wait_time(config, 'verification_success_wait'))
|
|
|
|
# Handle last Turnstile verification
|
|
if handle_turnstile(browser_tab, config, translator):
|
|
if translator:
|
|
print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}")
|
|
time.sleep(get_random_wait_time(config, 'verification_retry_wait'))
|
|
|
|
# Visit settings page
|
|
if translator:
|
|
print(f"{Fore.CYAN}{translator.get('register.visiting_url')}: https://www.cursor.com/settings{Style.RESET_ALL}")
|
|
browser_tab.get("https://www.cursor.com/settings")
|
|
time.sleep(get_random_wait_time(config, 'settings_page_load_wait'))
|
|
|
|
# Return success directly, let cursor_register.py handle account information acquisition
|
|
return True, browser_tab
|
|
|
|
else:
|
|
if translator:
|
|
print(f"{Fore.RED}❌ {translator.get('register.verification_failed')}{Style.RESET_ALL}")
|
|
return False, None
|
|
|
|
return False, None
|
|
|
|
except Exception as e:
|
|
if translator:
|
|
print(f"{Fore.RED}❌ {translator.get('register.verification_error', error=str(e))}{Style.RESET_ALL}")
|
|
return False, None
|
|
|
|
def handle_sign_in(browser_tab, email, password, translator=None):
|
|
"""Handle login process"""
|
|
try:
|
|
# Check if on login page
|
|
sign_in_header = browser_tab.ele('xpath://h1[contains(text(), "Sign in")]')
|
|
if not sign_in_header:
|
|
return True # If not on login page, it means login is successful
|
|
|
|
print(f"{Fore.CYAN}检测到登录页面,开始登录...{Style.RESET_ALL}")
|
|
|
|
# Fill email
|
|
email_input = browser_tab.ele('@name=email')
|
|
if email_input:
|
|
email_input.input(email)
|
|
time.sleep(1)
|
|
|
|
# Click Continue
|
|
continue_button = browser_tab.ele('xpath://button[contains(@class, "BrandedButton") and text()="Continue"]')
|
|
if continue_button:
|
|
continue_button.click()
|
|
time.sleep(2)
|
|
|
|
# Handle Turnstile verification
|
|
if handle_turnstile(browser_tab, translator):
|
|
# Fill password
|
|
password_input = browser_tab.ele('@name=password')
|
|
if password_input:
|
|
password_input.input(password)
|
|
time.sleep(1)
|
|
|
|
# Click Sign in
|
|
sign_in_button = browser_tab.ele('xpath://button[@name="intent" and @value="password"]')
|
|
if sign_in_button:
|
|
sign_in_button.click()
|
|
time.sleep(2)
|
|
|
|
# Handle last Turnstile verification
|
|
if handle_turnstile(browser_tab, translator):
|
|
print(f"{Fore.GREEN}Login successful!{Style.RESET_ALL}")
|
|
time.sleep(3)
|
|
return True
|
|
|
|
print(f"{Fore.RED}Login failed{Style.RESET_ALL}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"{Fore.RED}Login process error: {str(e)}{Style.RESET_ALL}")
|
|
return False
|
|
|
|
def main(email=None, password=None, first_name=None, last_name=None, email_tab=None, controller=None, translator=None):
|
|
"""Main function, can receive account information, email tab, and translator"""
|
|
global _translator
|
|
global _chrome_process_ids
|
|
_translator = translator # Save to global variable
|
|
_chrome_process_ids = [] # Reset the process IDs list
|
|
|
|
signal.signal(signal.SIGINT, signal_handler)
|
|
signal.signal(signal.SIGTERM, signal_handler)
|
|
|
|
page = None
|
|
success = False
|
|
try:
|
|
config, page = setup_driver(translator)
|
|
if translator:
|
|
print(f"{Fore.CYAN}🚀 {translator.get('register.browser_started')}{Style.RESET_ALL}")
|
|
|
|
# Visit registration page
|
|
url = "https://authenticator.cursor.sh/sign-up"
|
|
|
|
# Visit page
|
|
simulate_human_input(page, url, config, translator)
|
|
if translator:
|
|
print(f"{Fore.CYAN}🔄 {translator.get('register.waiting_for_page_load')}{Style.RESET_ALL}")
|
|
time.sleep(get_random_wait_time(config, 'page_load_wait'))
|
|
|
|
# If account information is not provided, generate random information
|
|
if not all([email, password, first_name, last_name]):
|
|
first_name = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz', k=6)).capitalize()
|
|
last_name = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz', k=6)).capitalize()
|
|
email = f"{first_name.lower()}{random.randint(100,999)}@example.com"
|
|
password = generate_password()
|
|
|
|
# Save account information
|
|
with open('test_accounts.txt', 'a', encoding='utf-8') as f:
|
|
f.write(f"\n{'='*50}\n")
|
|
f.write(f"Email: {email}\n")
|
|
f.write(f"Password: {password}\n")
|
|
f.write(f"{'='*50}\n")
|
|
|
|
# Fill form
|
|
if fill_signup_form(page, first_name, last_name, email, config, translator):
|
|
if translator:
|
|
print(f"\n{Fore.GREEN}✅ {translator.get('register.form_submitted')}{Style.RESET_ALL}")
|
|
|
|
# Handle first Turnstile verification
|
|
if handle_turnstile(page, config, translator):
|
|
if translator:
|
|
print(f"\n{Fore.GREEN}✅ {translator.get('register.first_verification_passed')}{Style.RESET_ALL}")
|
|
|
|
# Fill password
|
|
if fill_password(page, password, config, translator):
|
|
if translator:
|
|
print(f"\n{Fore.CYAN}🔄 {translator.get('register.waiting_for_second_verification')}{Style.RESET_ALL}")
|
|
|
|
# Handle second Turnstile verification
|
|
if handle_turnstile(page, config, translator):
|
|
if translator:
|
|
print(f"\n{Fore.CYAN}🔄 {translator.get('register.waiting_for_verification_code')}{Style.RESET_ALL}")
|
|
if handle_verification_code(page, email_tab, controller, config, translator):
|
|
success = True
|
|
return True, page
|
|
else:
|
|
print(f"\n{Fore.RED}❌ {translator.get('register.verification_code_processing_failed') if translator else 'Verification code processing failed'}{Style.RESET_ALL}")
|
|
else:
|
|
print(f"\n{Fore.RED}❌ {translator.get('register.second_verification_failed') if translator else 'Second verification failed'}{Style.RESET_ALL}")
|
|
else:
|
|
print(f"\n{Fore.RED}❌ {translator.get('register.second_verification_failed') if translator else 'Second verification failed'}{Style.RESET_ALL}")
|
|
else:
|
|
print(f"\n{Fore.RED}❌ {translator.get('register.first_verification_failed') if translator else 'First verification failed'}{Style.RESET_ALL}")
|
|
|
|
return False, None
|
|
|
|
except Exception as e:
|
|
print(f"发生错误: {e}")
|
|
return False, None
|
|
finally:
|
|
if page and not success: # Only clean up when failed
|
|
try:
|
|
page.quit()
|
|
except:
|
|
pass
|
|
cleanup_chrome_processes(translator)
|
|
|
|
if __name__ == "__main__":
|
|
main() # Run without parameters, use randomly generated information |