mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-08-03 04:57:36 +08:00
Big Update - Fixed Human Verify Problem
This commit is contained in:
parent
1f29b2dbbe
commit
f4314cc6da
5
blacklist.txt
Normal file
5
blacklist.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
fr.nf
|
||||||
|
yopmail.com
|
||||||
|
1s.fr
|
||||||
|
xl.cx
|
||||||
|
fr.cr
|
@ -27,12 +27,15 @@ class BrowserManager:
|
|||||||
try:
|
try:
|
||||||
extension_path = self._get_extension_path()
|
extension_path = self._get_extension_path()
|
||||||
co.add_extension(extension_path)
|
co.add_extension(extension_path)
|
||||||
|
co.set_argument("--allow-extensions-in-incognito")
|
||||||
|
|
||||||
extension_block_path = self.get_extension_block()
|
extension_block_path = self.get_extension_block()
|
||||||
co.add_extension(extension_block_path)
|
co.add_extension(extension_block_path)
|
||||||
|
co.set_argument("--allow-extensions-in-incognito")
|
||||||
|
|
||||||
extension_recaptcha_path = self.get_extension_recaptcha()
|
extension_recaptcha_path = self.get_extension_recaptcha()
|
||||||
co.add_extension(extension_recaptcha_path)
|
co.add_extension(extension_recaptcha_path)
|
||||||
|
co.set_argument("--allow-extensions-in-incognito")
|
||||||
|
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
logging.warning(f"警告: {e}")
|
logging.warning(f"警告: {e}")
|
||||||
|
@ -32,7 +32,8 @@ a = Analysis(
|
|||||||
('cursor_register.py', '.'),
|
('cursor_register.py', '.'),
|
||||||
('browser.py', '.'),
|
('browser.py', '.'),
|
||||||
('control.py', '.'),
|
('control.py', '.'),
|
||||||
('.env', '.')
|
('.env', '.'),
|
||||||
|
('blacklist.txt', '.')
|
||||||
],
|
],
|
||||||
hiddenimports=[
|
hiddenimports=[
|
||||||
'cursor_auth',
|
'cursor_auth',
|
||||||
|
47
control.py
47
control.py
@ -77,41 +77,53 @@ class BrowserControl:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def select_email_domain(self, domain_index=None):
|
def select_email_domain(self, domain_index=None):
|
||||||
"""选择邮箱域名,如果不指定index则随机选择。避免选择fr.nf域名"""
|
"""选择邮箱域名,如果不指定index则随机选择"""
|
||||||
try:
|
try:
|
||||||
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}...{Style.RESET_ALL}")
|
||||||
|
|
||||||
|
# 读取黑名单域名
|
||||||
|
blacklist = []
|
||||||
|
try:
|
||||||
|
with open('blacklist.txt', 'r', encoding='utf-8') as f:
|
||||||
|
blacklist = [line.strip().lower() for line in f if line.strip()]
|
||||||
|
except FileNotFoundError:
|
||||||
|
# 如果文件不存在,创建一个包含已知黑名单域名的文件
|
||||||
|
with open('blacklist.txt', 'w', encoding='utf-8') as f:
|
||||||
|
f.write("fr.nf\nyopmail.com\n1s.fr\nfr.cr")
|
||||||
|
blacklist = ["fr.nf", "yopmail.com", "1s.fr", "fr.cr"]
|
||||||
|
|
||||||
# 找到下拉框
|
# 找到下拉框
|
||||||
select_element = self.browser.ele('xpath://select[@id="seldom"]')
|
select_element = self.browser.ele('xpath://select[@id="seldom"]')
|
||||||
if select_element:
|
if select_element:
|
||||||
# 获取所有选项,包括两个 optgroup 下的所有 option
|
# 获取所有选项
|
||||||
all_options = []
|
all_options = []
|
||||||
|
|
||||||
# 获取 "新的" 组下的选项
|
|
||||||
new_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 新的 --"]/option')
|
new_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 新的 --"]/option')
|
||||||
all_options.extend(new_options)
|
|
||||||
|
|
||||||
# 获取 "其他" 组下的选项
|
|
||||||
other_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 其他 --"]/option')
|
other_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 其他 --"]/option')
|
||||||
|
all_options.extend(new_options)
|
||||||
all_options.extend(other_options)
|
all_options.extend(other_options)
|
||||||
|
|
||||||
if all_options:
|
if all_options:
|
||||||
max_attempts = 5 # 最大尝试次数
|
max_attempts = 5
|
||||||
attempt = 0
|
attempt = 0
|
||||||
|
|
||||||
while attempt < max_attempts:
|
while attempt < max_attempts:
|
||||||
# 如果没有指定索引,随机选择一个
|
|
||||||
if domain_index is None:
|
if domain_index is None:
|
||||||
domain_index = random.randint(0, len(all_options) - 1)
|
domain_index = random.randint(0, len(all_options) - 1)
|
||||||
|
|
||||||
if domain_index < len(all_options):
|
if domain_index < len(all_options):
|
||||||
# 获取选中选项的文本
|
selected_domain = all_options[domain_index].text.lower()
|
||||||
selected_domain = all_options[domain_index].text
|
|
||||||
|
|
||||||
# 检查是否为fr.nf域名
|
# 检查域名是否在黑名单中
|
||||||
if "fr.nf" in selected_domain.lower():
|
is_blacklisted = False
|
||||||
print(f"{Fore.YELLOW}{EMOJI['INFO']} 检测到fr.nf域名,重新选择...{Style.RESET_ALL}")
|
for blocked_domain in blacklist:
|
||||||
domain_index = None # 重置索引以便重新随机选择
|
if blocked_domain in selected_domain:
|
||||||
attempt += 1
|
print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('control.blocked_domain', domain=blocked_domain)}{Style.RESET_ALL}")
|
||||||
|
domain_index = None
|
||||||
|
attempt += 1
|
||||||
|
is_blacklisted = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if is_blacklisted:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}: {selected_domain}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}: {selected_domain}{Style.RESET_ALL}")
|
||||||
@ -124,7 +136,7 @@ class BrowserControl:
|
|||||||
|
|
||||||
attempt += 1
|
attempt += 1
|
||||||
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} 无法找到合适的非fr.nf域名{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} 无法找到可用的域名{Style.RESET_ALL}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_available_domain_options', count=len(all_options))}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_available_domain_options', count=len(all_options))}{Style.RESET_ALL}")
|
||||||
@ -132,6 +144,7 @@ class BrowserControl:
|
|||||||
else:
|
else:
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_domain_select_box')}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_domain_select_box')}{Style.RESET_ALL}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.select_email_domain_failed', error=str(e))}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.select_email_domain_failed', error=str(e))}{Style.RESET_ALL}")
|
||||||
return False
|
return False
|
||||||
|
@ -96,237 +96,50 @@ class CursorRegistration:
|
|||||||
|
|
||||||
def register_cursor(self):
|
def register_cursor(self):
|
||||||
"""注册 Cursor"""
|
"""注册 Cursor"""
|
||||||
signup_browser_manager = 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 进行注册
|
||||||
from browser import BrowserManager
|
from new_signup import main as new_signup_main
|
||||||
signup_browser_manager = BrowserManager(noheader=False)
|
|
||||||
self.signup_tab = signup_browser_manager.init_browser()
|
|
||||||
|
|
||||||
# 访问注册页面
|
# 执行新的注册流程,传入 translator
|
||||||
self.signup_tab.get(self.sign_up_url)
|
result, browser_tab = new_signup_main(
|
||||||
time.sleep(2)
|
email=self.email_address,
|
||||||
|
password=self.password,
|
||||||
|
first_name=self.first_name,
|
||||||
|
last_name=self.last_name,
|
||||||
|
email_tab=self.email_tab,
|
||||||
|
controller=self.controller,
|
||||||
|
translator=self.translator
|
||||||
|
)
|
||||||
|
|
||||||
# 填写注册表单
|
if result:
|
||||||
if self.signup_tab.ele("@name=first_name"):
|
# 使用返回的浏览器实例获取账户信息
|
||||||
print(f"{Fore.CYAN}{EMOJI['FORM']} {self.translator.get('register.filling_form')}...{Style.RESET_ALL}")
|
self.signup_tab = browser_tab # 保存浏览器实例
|
||||||
|
success = self._get_account_info()
|
||||||
|
|
||||||
self.signup_tab.ele("@name=first_name").input(self.first_name)
|
# 获取信息后关闭浏览器
|
||||||
time.sleep(random.uniform(1, 2))
|
if browser_tab:
|
||||||
|
try:
|
||||||
|
browser_tab.quit()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
self.signup_tab.ele("@name=last_name").input(self.last_name)
|
return success
|
||||||
time.sleep(random.uniform(1, 2))
|
|
||||||
|
|
||||||
self.signup_tab.ele("@name=email").input(self.email_address)
|
return False
|
||||||
time.sleep(random.uniform(1, 2))
|
|
||||||
|
|
||||||
self.signup_tab.ele("@type=submit").click()
|
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.basic_info_submitted')}...{Style.RESET_ALL}")
|
|
||||||
|
|
||||||
# 处理 Turnstile 验证
|
|
||||||
self._handle_turnstile()
|
|
||||||
|
|
||||||
# 设置密码
|
|
||||||
if self.signup_tab.ele("@name=password"):
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['PASSWORD']} {self.translator.get('register.set_password')}...{Style.RESET_ALL}")
|
|
||||||
self.signup_tab.ele("@name=password").input(self.password)
|
|
||||||
time.sleep(random.uniform(1, 2))
|
|
||||||
self.signup_tab.ele("@type=submit").click()
|
|
||||||
|
|
||||||
self._handle_turnstile()
|
|
||||||
|
|
||||||
# 等待并获取验证码
|
|
||||||
time.sleep(5) # 等待验证码邮件
|
|
||||||
|
|
||||||
self.browser.refresh()
|
|
||||||
|
|
||||||
# 获取验证码,设置60秒超时
|
|
||||||
verification_code = None
|
|
||||||
max_attempts = 20 # 增加到10次尝试
|
|
||||||
retry_interval = 10 # 每5秒重试一次
|
|
||||||
start_time = time.time()
|
|
||||||
timeout = 160 # 60秒超时
|
|
||||||
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('register.start_getting_verification_code')}...{Style.RESET_ALL}")
|
|
||||||
|
|
||||||
for attempt in range(max_attempts):
|
|
||||||
# 检查是否超时
|
|
||||||
if time.time() - start_time > timeout:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.get_verification_code_timeout')}...{Style.RESET_ALL}")
|
|
||||||
break
|
|
||||||
|
|
||||||
verification_code = self.controller.get_verification_code()
|
|
||||||
if verification_code:
|
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.get_verification_code_success')}: {verification_code}{Style.RESET_ALL}")
|
|
||||||
break
|
|
||||||
|
|
||||||
remaining_time = int(timeout - (time.time() - start_time))
|
|
||||||
print(f"{Fore.YELLOW}{EMOJI['WAIT']} {self.translator.get('register.try_get_verification_code', attempt=attempt + 1, remaining_time=remaining_time)}...{Style.RESET_ALL}")
|
|
||||||
|
|
||||||
# 刷新邮箱
|
|
||||||
self.browser.refresh()
|
|
||||||
time.sleep(retry_interval)
|
|
||||||
|
|
||||||
if verification_code:
|
|
||||||
# 在注册页面填写验证码
|
|
||||||
for i, digit in enumerate(verification_code):
|
|
||||||
self.signup_tab.ele(f"@data-index={i}").input(digit)
|
|
||||||
time.sleep(random.uniform(0.1, 0.3))
|
|
||||||
|
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.verification_code_filled')}...{Style.RESET_ALL}")
|
|
||||||
time.sleep(3)
|
|
||||||
|
|
||||||
self._handle_turnstile()
|
|
||||||
|
|
||||||
# 检查当前URL
|
|
||||||
current_url = self.signup_tab.url
|
|
||||||
if "authenticator.cursor.sh" in current_url:
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['VERIFY']} {self.translator.get('register.detect_login_page')}...{Style.RESET_ALL}")
|
|
||||||
|
|
||||||
# 填写邮箱
|
|
||||||
email_input = self.signup_tab.ele('@name=email')
|
|
||||||
if email_input:
|
|
||||||
email_input.input(self.email_address)
|
|
||||||
time.sleep(random.uniform(1, 2))
|
|
||||||
|
|
||||||
# 点击提交
|
|
||||||
submit_button = self.signup_tab.ele('@type=submit')
|
|
||||||
if submit_button:
|
|
||||||
submit_button.click()
|
|
||||||
time.sleep(2)
|
|
||||||
|
|
||||||
# 处理 Turnstile 验证
|
|
||||||
self._handle_turnstile()
|
|
||||||
|
|
||||||
# 填写密码
|
|
||||||
password_input = self.signup_tab.ele('@name=password')
|
|
||||||
if password_input:
|
|
||||||
password_input.input(self.password)
|
|
||||||
time.sleep(random.uniform(1, 2))
|
|
||||||
|
|
||||||
# 点击提交
|
|
||||||
submit_button = self.signup_tab.ele('@type=submit')
|
|
||||||
if submit_button:
|
|
||||||
submit_button.click()
|
|
||||||
time.sleep(2)
|
|
||||||
|
|
||||||
# 处理 Turnstile 验证
|
|
||||||
self._handle_turnstile()
|
|
||||||
|
|
||||||
# 等待跳转到设置页面
|
|
||||||
max_wait = 30
|
|
||||||
start_time = time.time()
|
|
||||||
while time.time() - start_time < max_wait:
|
|
||||||
if "cursor.com/settings" in self.signup_tab.url:
|
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.login_success_and_jump_to_settings_page')}...{Style.RESET_ALL}")
|
|
||||||
break
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
# 获取账户信息
|
|
||||||
result = self._get_account_info()
|
|
||||||
|
|
||||||
# 关闭注册窗口
|
|
||||||
if signup_browser_manager:
|
|
||||||
signup_browser_manager.quit()
|
|
||||||
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.get_verification_code_timeout')}...{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
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:
|
||||||
# 确保在任何情况下都关闭注册窗口
|
# 确保在任何情况下都关闭浏览器
|
||||||
if signup_browser_manager:
|
if browser_tab:
|
||||||
signup_browser_manager.quit()
|
|
||||||
|
|
||||||
def _handle_turnstile(self):
|
|
||||||
"""处理 Turnstile 验证"""
|
|
||||||
try:
|
|
||||||
print(f"{Fore.YELLOW}{EMOJI['VERIFY']} {self.translator.get('register.handle_turnstile')}...{Style.RESET_ALL}")
|
|
||||||
|
|
||||||
max_retries = 2
|
|
||||||
retry_interval = (1, 2)
|
|
||||||
retry_count = 0
|
|
||||||
|
|
||||||
while retry_count < max_retries:
|
|
||||||
retry_count += 1
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('register.turnstile_attempt', attempt=retry_count)}...{Style.RESET_ALL}")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 尝试重置 turnstile
|
browser_tab.quit()
|
||||||
self.signup_tab.run_js("try { turnstile.reset() } catch(e) { }")
|
except:
|
||||||
time.sleep(2)
|
pass
|
||||||
|
|
||||||
# 定位验证框元素
|
|
||||||
challenge_check = (
|
|
||||||
self.signup_tab.ele("@id=cf-turnstile", timeout=2)
|
|
||||||
.child()
|
|
||||||
.shadow_root.ele("tag:iframe")
|
|
||||||
.ele("tag:body")
|
|
||||||
.sr("tag:input")
|
|
||||||
)
|
|
||||||
|
|
||||||
if challenge_check:
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('register.turnstile_detected')}...{Style.RESET_ALL}")
|
|
||||||
|
|
||||||
# 随机延时后点击验证
|
|
||||||
time.sleep(random.uniform(1, 3))
|
|
||||||
challenge_check.click()
|
|
||||||
time.sleep(2)
|
|
||||||
|
|
||||||
# 检查验证结果
|
|
||||||
if self._check_verification_success():
|
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.turnstile_passed')}{Style.RESET_ALL}")
|
|
||||||
return True
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('register.turnstile_attempt_failed', error=str(e))}{Style.RESET_ALL}")
|
|
||||||
|
|
||||||
# 检查是否已经验证成功
|
|
||||||
if self._check_verification_success():
|
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.turnstile_passed')}{Style.RESET_ALL}")
|
|
||||||
return True
|
|
||||||
|
|
||||||
# 随机延时后继续下一次尝试
|
|
||||||
time.sleep(random.uniform(*retry_interval))
|
|
||||||
|
|
||||||
# 超出最大重试次数
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.turnstile_max_retries', max=max_retries)}{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.turnstile_error', error=str(e))}{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _check_verification_success(self):
|
|
||||||
"""检查验证是否成功"""
|
|
||||||
try:
|
|
||||||
# 检查是否存在后续表单元素,这表示验证已通过
|
|
||||||
if (self.signup_tab.ele("@name=password", timeout=0.5) or
|
|
||||||
self.signup_tab.ele("@name=email", timeout=0.5) or
|
|
||||||
self.signup_tab.ele("@data-index=0", timeout=0.5) or
|
|
||||||
self.signup_tab.ele("Account Settings", timeout=0.5)):
|
|
||||||
return True
|
|
||||||
|
|
||||||
# 检查是否出现错误消息
|
|
||||||
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 self.signup_tab.ele(error_xpath):
|
|
||||||
return False
|
|
||||||
|
|
||||||
return False
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _get_account_info(self):
|
def _get_account_info(self):
|
||||||
"""获取账户信息和 Token"""
|
"""获取账户信息和 Token"""
|
||||||
|
@ -66,12 +66,25 @@
|
|||||||
},
|
},
|
||||||
"register": {
|
"register": {
|
||||||
"title": "Cursor Registration Tool",
|
"title": "Cursor Registration Tool",
|
||||||
|
|
||||||
|
|
||||||
"start": "Starting Registration Process",
|
"start": "Starting Registration Process",
|
||||||
|
"handling_turnstile": "Handling Turnstile",
|
||||||
|
"retry_verification": "Retry Verification",
|
||||||
|
"detect_turnstile": "Detect Turnstile",
|
||||||
|
"verification_success": "Verification Success",
|
||||||
|
"starting_browser": "Starting Browser",
|
||||||
|
"form_success": "Form Success",
|
||||||
|
"browser_started": "Browser Started",
|
||||||
|
"waiting_for_second_verification": "Waiting for Second Verification",
|
||||||
|
"waiting_for_verification_code": "Waiting for Verification Code",
|
||||||
|
"password_success": "Password Set Successfully",
|
||||||
|
"password_error": "Password Set Failed: {error}",
|
||||||
|
"waiting_for_page_load": "Waiting for Page Load",
|
||||||
|
"first_verification_passed": "First Verification Passed",
|
||||||
"mailbox": "Successfully Entered Mailbox",
|
"mailbox": "Successfully Entered Mailbox",
|
||||||
"register_start": "Start Register",
|
"register_start": "Start Register",
|
||||||
|
"form_submitted": "Form Submitted, Start Verification...",
|
||||||
"filling_form": "Fill Form",
|
"filling_form": "Fill Form",
|
||||||
|
"visiting_url": "Visiting URL",
|
||||||
"basic_info": "Basic Info Submitted",
|
"basic_info": "Basic Info Submitted",
|
||||||
"handle_turnstile": "Handle Turnstile",
|
"handle_turnstile": "Handle Turnstile",
|
||||||
"no_turnstile": "Not Detect Turnstile",
|
"no_turnstile": "Not Detect Turnstile",
|
||||||
@ -131,6 +144,7 @@
|
|||||||
},
|
},
|
||||||
"control": {
|
"control": {
|
||||||
"generate_email": "Generating New Email",
|
"generate_email": "Generating New Email",
|
||||||
|
"blocked_domain": "Blocked Domain",
|
||||||
"select_domain": "Selecting Random Domain",
|
"select_domain": "Selecting Random Domain",
|
||||||
"copy_email": "Copying Email Address",
|
"copy_email": "Copying Email Address",
|
||||||
"enter_mailbox": "Entering Mailbox",
|
"enter_mailbox": "Entering Mailbox",
|
||||||
@ -158,6 +172,7 @@
|
|||||||
"get_cursor_session_token_failed": "Get Cursor Session Token Failed",
|
"get_cursor_session_token_failed": "Get Cursor Session Token Failed",
|
||||||
"save_token_failed": "Save Token Failed",
|
"save_token_failed": "Save Token Failed",
|
||||||
"database_updated_successfully": "Database Updated Successfully",
|
"database_updated_successfully": "Database Updated Successfully",
|
||||||
"database_connection_closed": "Database Connection Closed"
|
"database_connection_closed": "Database Connection Closed",
|
||||||
|
"no_valid_verification_code": "No Valid Verification Code"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -67,10 +67,25 @@
|
|||||||
"register": {
|
"register": {
|
||||||
"title": "Cursor 注册工具",
|
"title": "Cursor 注册工具",
|
||||||
"start": "开始注册流程",
|
"start": "开始注册流程",
|
||||||
|
"browser_started": "浏览器已启动",
|
||||||
|
"password_success": "密码设置完成",
|
||||||
|
"password_error": "密码设置失败: {error}",
|
||||||
|
"waiting_for_page_load": "等待页面加载",
|
||||||
"mailbox": "成功进入邮箱",
|
"mailbox": "成功进入邮箱",
|
||||||
|
"waiting_for_second_verification": "等待第二阶段验证",
|
||||||
|
"waiting_for_verification_code": "等待验证码",
|
||||||
|
"first_verification_passed": "第一阶段验证通过",
|
||||||
"register_start": "开始注册流程",
|
"register_start": "开始注册流程",
|
||||||
|
"form_submitted": "表单已提交,开始验证...",
|
||||||
"filling_form": "填写注册信息",
|
"filling_form": "填写注册信息",
|
||||||
|
"visiting_url": "访问URL",
|
||||||
"basic_info": "基本信息提交完成",
|
"basic_info": "基本信息提交完成",
|
||||||
|
"handling_turnstile": "处理 Turnstile 验证",
|
||||||
|
"retry_verification": "重试验证",
|
||||||
|
"detect_turnstile": "检测 Turnstile 验证",
|
||||||
|
"verification_success": "验证成功",
|
||||||
|
"starting_browser": "启动浏览器",
|
||||||
|
"form_success": "表单提交成功",
|
||||||
"handle_turnstile": "处理 Turnstile 验证",
|
"handle_turnstile": "处理 Turnstile 验证",
|
||||||
"no_turnstile": "未检测到 Turnstile 验证",
|
"no_turnstile": "未检测到 Turnstile 验证",
|
||||||
"turnstile_passed": "验证通过",
|
"turnstile_passed": "验证通过",
|
||||||
@ -131,6 +146,7 @@
|
|||||||
"select_domain": "选择随机域名",
|
"select_domain": "选择随机域名",
|
||||||
"copy_email": "复制邮箱地址",
|
"copy_email": "复制邮箱地址",
|
||||||
"enter_mailbox": "进入邮箱",
|
"enter_mailbox": "进入邮箱",
|
||||||
|
"blocked_domain": "被屏蔽的域名",
|
||||||
"refresh_mailbox": "刷新邮箱",
|
"refresh_mailbox": "刷新邮箱",
|
||||||
"check_verification": "检查验证码",
|
"check_verification": "检查验证码",
|
||||||
"verification_found": "找到验证码",
|
"verification_found": "找到验证码",
|
||||||
@ -153,6 +169,7 @@
|
|||||||
"get_cursor_session_token": "获取Cursor Session Token",
|
"get_cursor_session_token": "获取Cursor Session Token",
|
||||||
"get_cursor_session_token_success": "获取Cursor Session Token成功",
|
"get_cursor_session_token_success": "获取Cursor Session Token成功",
|
||||||
"get_cursor_session_token_failed": "获取Cursor Session Token失败",
|
"get_cursor_session_token_failed": "获取Cursor Session Token失败",
|
||||||
"save_token_failed": "保存Token失败"
|
"save_token_failed": "保存Token失败",
|
||||||
|
"no_valid_verification_code": "没有有效的验证码"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -64,21 +64,32 @@
|
|||||||
"version_check_passed": "Cursor版本檢查通過",
|
"version_check_passed": "Cursor版本檢查通過",
|
||||||
"file_modified": "文件已修改"
|
"file_modified": "文件已修改"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"register": {
|
"register": {
|
||||||
"title": "Cursor 註冊工具",
|
"title": "Cursor 註冊工具",
|
||||||
"start": "開始註冊流程",
|
"start": "開始註冊流程",
|
||||||
"mailbox": "成功進入郵箱",
|
"mailbox": "成功進入郵箱",
|
||||||
|
"browser_started": "瀏覽器已啟動",
|
||||||
|
"waiting_for_page_load": "等待頁面加載",
|
||||||
|
"password_success": "密碼設置完成",
|
||||||
|
"password_error": "密碼設置失敗: {error}",
|
||||||
|
"visiting_url": "訪問URL",
|
||||||
|
"first_verification_passed": "第一階段驗證通過",
|
||||||
"register_start": "開始註冊流程",
|
"register_start": "開始註冊流程",
|
||||||
|
"form_submitted": "表單已提交,開始驗證...",
|
||||||
|
"waiting_for_second_verification": "等待第二階段驗證",
|
||||||
"filling_form": "填寫註冊信息",
|
"filling_form": "填寫註冊信息",
|
||||||
"basic_info": "基本信息提交完成",
|
"basic_info": "基本信息提交完成",
|
||||||
"handle_turnstile": "處理 Turnstile 驗證",
|
"handle_turnstile": "處理 Turnstile 驗證",
|
||||||
"no_turnstile": "未檢測到 Turnstile 驗證",
|
"no_turnstile": "未檢測到 Turnstile 驗證",
|
||||||
"turnstile_passed": "驗證通過",
|
"turnstile_passed": "驗證通過",
|
||||||
"verification_start": "開始獲取驗證碼",
|
"verification_start": "開始獲取驗證碼",
|
||||||
|
"waiting_for_verification_code": "等待驗證碼",
|
||||||
|
"handling_turnstile": "處理 Turnstile 驗證",
|
||||||
|
"retry_verification": "重試驗證",
|
||||||
|
"detect_turnstile": "檢測 Turnstile 驗證",
|
||||||
|
"verification_success": "驗證成功",
|
||||||
|
"starting_browser": "啟動瀏覽器",
|
||||||
|
"form_success": "表單提交成功",
|
||||||
"verification_timeout": "獲取驗證碼超時",
|
"verification_timeout": "獲取驗證碼超時",
|
||||||
"verification_not_found": "未找到驗證碼",
|
"verification_not_found": "未找到驗證碼",
|
||||||
"try_get_code": "第 {attempt} 次嘗試獲取驗證碼 | 剩餘時間: {time}秒",
|
"try_get_code": "第 {attempt} 次嘗試獲取驗證碼 | 剩餘時間: {time}秒",
|
||||||
@ -157,6 +168,8 @@
|
|||||||
"get_cursor_session_token": "獲取Cursor Session Token",
|
"get_cursor_session_token": "獲取Cursor Session Token",
|
||||||
"get_cursor_session_token_success": "獲取Cursor Session Token成功",
|
"get_cursor_session_token_success": "獲取Cursor Session Token成功",
|
||||||
"get_cursor_session_token_failed": "獲取Cursor Session Token失敗",
|
"get_cursor_session_token_failed": "獲取Cursor Session Token失敗",
|
||||||
"save_token_failed": "保存Token失敗"
|
"save_token_failed": "保存Token失敗",
|
||||||
|
"blocked_domain": "被屏蔽的域名",
|
||||||
|
"no_valid_verification_code": "沒有有效的驗證碼"
|
||||||
}
|
}
|
||||||
}
|
}
|
468
new_signup.py
Normal file
468
new_signup.py
Normal file
@ -0,0 +1,468 @@
|
|||||||
|
from DrissionPage import ChromiumOptions, ChromiumPage
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
import signal
|
||||||
|
import random
|
||||||
|
|
||||||
|
# 在文件开头添加全局变量
|
||||||
|
_translator = None
|
||||||
|
|
||||||
|
def cleanup_chrome_processes(translator=None):
|
||||||
|
"""清理所有Chrome相关进程"""
|
||||||
|
print("\n正在清理Chrome进程...")
|
||||||
|
try:
|
||||||
|
if os.name == 'nt':
|
||||||
|
os.system('taskkill /F /IM chrome.exe /T 2>nul')
|
||||||
|
os.system('taskkill /F /IM chromedriver.exe /T 2>nul')
|
||||||
|
else:
|
||||||
|
os.system('pkill -f chrome')
|
||||||
|
os.system('pkill -f chromedriver')
|
||||||
|
except Exception as e:
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.cleanup_error', error=str(e))}")
|
||||||
|
else:
|
||||||
|
print(f"清理进程时出错: {e}")
|
||||||
|
|
||||||
|
def signal_handler(signum, frame):
|
||||||
|
"""处理Ctrl+C信号"""
|
||||||
|
global _translator
|
||||||
|
if _translator:
|
||||||
|
print(f"{_translator.get('register.exit_signal')}")
|
||||||
|
else:
|
||||||
|
print("\n接收到退出信号,正在关闭...")
|
||||||
|
cleanup_chrome_processes(_translator)
|
||||||
|
os._exit(0)
|
||||||
|
|
||||||
|
def simulate_human_input(page, url, translator=None):
|
||||||
|
"""访问网址"""
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.visiting_url')}: {url}")
|
||||||
|
else:
|
||||||
|
print("正在访问网址...")
|
||||||
|
|
||||||
|
# 先访问空白页面
|
||||||
|
page.get('about:blank')
|
||||||
|
time.sleep(random.uniform(1.0, 2.0))
|
||||||
|
|
||||||
|
# 访问目标页面
|
||||||
|
page.get(url)
|
||||||
|
time.sleep(random.uniform(2.0, 3.0)) # 等待页面加载
|
||||||
|
|
||||||
|
def fill_signup_form(page, first_name, last_name, email, translator=None):
|
||||||
|
"""填写注册表单"""
|
||||||
|
try:
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.filling_form')}")
|
||||||
|
else:
|
||||||
|
print("\n正在填写注册表单...")
|
||||||
|
|
||||||
|
# 填写名字
|
||||||
|
first_name_input = page.ele("@name=first_name")
|
||||||
|
if first_name_input:
|
||||||
|
first_name_input.input(first_name)
|
||||||
|
time.sleep(random.uniform(0.5, 1.0))
|
||||||
|
|
||||||
|
# 填写姓氏
|
||||||
|
last_name_input = page.ele("@name=last_name")
|
||||||
|
if last_name_input:
|
||||||
|
last_name_input.input(last_name)
|
||||||
|
time.sleep(random.uniform(0.5, 1.0))
|
||||||
|
|
||||||
|
# 填写邮箱
|
||||||
|
email_input = page.ele("@name=email")
|
||||||
|
if email_input:
|
||||||
|
email_input.input(email)
|
||||||
|
time.sleep(random.uniform(0.5, 1.0))
|
||||||
|
|
||||||
|
# 点击提交按钮
|
||||||
|
submit_button = page.ele("@type=submit")
|
||||||
|
if submit_button:
|
||||||
|
submit_button.click()
|
||||||
|
time.sleep(random.uniform(2.0, 3.0))
|
||||||
|
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.form_success')}")
|
||||||
|
else:
|
||||||
|
print("表单填写完成")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.form_error', error=str(e))}")
|
||||||
|
else:
|
||||||
|
print(f"填写表单时出错: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def setup_driver(translator=None):
|
||||||
|
"""设置浏览器驱动"""
|
||||||
|
co = ChromiumOptions()
|
||||||
|
|
||||||
|
# 使用无痕模式
|
||||||
|
co.set_argument("--incognito")
|
||||||
|
|
||||||
|
# 设置随机端口
|
||||||
|
co.auto_port()
|
||||||
|
|
||||||
|
# 使用有头模式
|
||||||
|
co.headless(False)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 加载插件
|
||||||
|
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"{translator.get('register.extension_load_error', error=str(e))}")
|
||||||
|
else:
|
||||||
|
print(f"加载插件失败: {e}")
|
||||||
|
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.starting_browser')}")
|
||||||
|
else:
|
||||||
|
print("正在启动浏览器...")
|
||||||
|
page = ChromiumPage(co)
|
||||||
|
|
||||||
|
return page
|
||||||
|
|
||||||
|
def handle_turnstile(page, translator=None):
|
||||||
|
"""处理 Turnstile 验证"""
|
||||||
|
try:
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.handling_turnstile')}")
|
||||||
|
else:
|
||||||
|
print("\n正在处理 Turnstile 验证...")
|
||||||
|
|
||||||
|
max_retries = 2
|
||||||
|
retry_count = 0
|
||||||
|
|
||||||
|
while retry_count < max_retries:
|
||||||
|
retry_count += 1
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.retry_verification', attempt=retry_count)}")
|
||||||
|
else:
|
||||||
|
print(f"第 {retry_count} 次尝试验证...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 尝试重置 turnstile
|
||||||
|
page.run_js("try { turnstile.reset() } catch(e) { }")
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# 定位验证框元素
|
||||||
|
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"{translator.get('register.detect_turnstile')}")
|
||||||
|
else:
|
||||||
|
print("检测到验证框...")
|
||||||
|
|
||||||
|
# 随机延时后点击验证
|
||||||
|
time.sleep(random.uniform(1, 3))
|
||||||
|
challenge_check.click()
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# 检查验证结果
|
||||||
|
if check_verification_success(page, translator):
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.verification_success')}")
|
||||||
|
else:
|
||||||
|
print("验证通过!")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.verification_failed')}")
|
||||||
|
else:
|
||||||
|
print(f"验证尝试失败: {e}")
|
||||||
|
|
||||||
|
# 检查是否已经验证成功
|
||||||
|
if check_verification_success(page, translator):
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.verification_success')}")
|
||||||
|
else:
|
||||||
|
print("验证通过!")
|
||||||
|
return True
|
||||||
|
|
||||||
|
time.sleep(random.uniform(1, 2))
|
||||||
|
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.verification_failed')}")
|
||||||
|
else:
|
||||||
|
print("超出最大重试次数")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.verification_error', error=str(e))}")
|
||||||
|
else:
|
||||||
|
print(f"验证过程出错: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check_verification_success(page, translator=None):
|
||||||
|
"""检查验证是否成功"""
|
||||||
|
try:
|
||||||
|
# 检查是否存在后续表单元素,这表示验证已通过
|
||||||
|
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
|
||||||
|
|
||||||
|
# 检查是否出现错误消息
|
||||||
|
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):
|
||||||
|
"""生成随机密码"""
|
||||||
|
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"
|
||||||
|
return ''.join(random.choices(chars, k=length))
|
||||||
|
|
||||||
|
def fill_password(page, password, translator=None):
|
||||||
|
"""填写密码"""
|
||||||
|
try:
|
||||||
|
print("\n正在设置密码...")
|
||||||
|
password_input = page.ele("@name=password")
|
||||||
|
if password_input:
|
||||||
|
password_input.input(password)
|
||||||
|
time.sleep(random.uniform(0.5, 1.0))
|
||||||
|
|
||||||
|
submit_button = page.ele("@type=submit")
|
||||||
|
if submit_button:
|
||||||
|
submit_button.click()
|
||||||
|
time.sleep(random.uniform(2.0, 3.0))
|
||||||
|
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.password_success')}")
|
||||||
|
else:
|
||||||
|
print(f"密码设置完成: {password}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.password_error', error=str(e))}")
|
||||||
|
else:
|
||||||
|
print(f"设置密码时出错: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def handle_verification_code(browser_tab, email_tab, controller, email, password, translator=None):
|
||||||
|
"""处理验证码"""
|
||||||
|
try:
|
||||||
|
if translator:
|
||||||
|
print(f"\n{translator.get('register.waiting_for_verification_code')}")
|
||||||
|
else:
|
||||||
|
print("\n等待并获取验证码...")
|
||||||
|
time.sleep(5) # 等待验证码邮件
|
||||||
|
|
||||||
|
# 刷新邮箱页面
|
||||||
|
email_tab.refresh()
|
||||||
|
|
||||||
|
# 获取验证码,设置超时
|
||||||
|
verification_code = None
|
||||||
|
max_attempts = 20
|
||||||
|
retry_interval = 10
|
||||||
|
start_time = time.time()
|
||||||
|
timeout = 160
|
||||||
|
|
||||||
|
if translator:
|
||||||
|
print(f"\n{translator.get('register.start_getting_verification_code')}")
|
||||||
|
else:
|
||||||
|
print("开始获取验证码...")
|
||||||
|
|
||||||
|
for attempt in range(max_attempts):
|
||||||
|
# 检查是否超时
|
||||||
|
if time.time() - start_time > timeout:
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.verification_timeout')}")
|
||||||
|
else:
|
||||||
|
print("获取验证码超时...")
|
||||||
|
break
|
||||||
|
|
||||||
|
verification_code = controller.get_verification_code()
|
||||||
|
if verification_code:
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.verification_success')}")
|
||||||
|
else:
|
||||||
|
print(f"成功获取验证码: {verification_code}")
|
||||||
|
break
|
||||||
|
|
||||||
|
remaining_time = int(timeout - (time.time() - start_time))
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.try_get_code', attempt=attempt + 1, time=remaining_time)}")
|
||||||
|
else:
|
||||||
|
print(f"第 {attempt + 1} 次尝试获取验证码,剩余时间: {remaining_time}秒...")
|
||||||
|
|
||||||
|
# 刷新邮箱
|
||||||
|
email_tab.refresh()
|
||||||
|
time.sleep(retry_interval)
|
||||||
|
|
||||||
|
if verification_code:
|
||||||
|
# 在注册页面填写验证码
|
||||||
|
for i, digit in enumerate(verification_code):
|
||||||
|
browser_tab.ele(f"@data-index={i}").input(digit)
|
||||||
|
time.sleep(random.uniform(0.1, 0.3))
|
||||||
|
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.verification_success')}")
|
||||||
|
else:
|
||||||
|
print("验证码填写完成")
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# 处理最后一次 Turnstile 验证
|
||||||
|
if handle_turnstile(browser_tab, translator):
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.verification_success')}")
|
||||||
|
else:
|
||||||
|
print("最后一次验证通过!")
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# 直接访问设置页面
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.visiting_url')}: https://www.cursor.com/settings")
|
||||||
|
else:
|
||||||
|
print("访问设置页面...")
|
||||||
|
browser_tab.get("https://www.cursor.com/settings")
|
||||||
|
time.sleep(3) # 等待页面加载
|
||||||
|
|
||||||
|
# 直接返回成功,让 cursor_register.py 处理账户信息获取
|
||||||
|
return True
|
||||||
|
|
||||||
|
else:
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.verification_failed')}")
|
||||||
|
else:
|
||||||
|
print("最后一次验证失败")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.verification_error', error=str(e))}")
|
||||||
|
else:
|
||||||
|
print(f"处理验证码时出错: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def main(email=None, password=None, first_name=None, last_name=None, email_tab=None, controller=None, translator=None):
|
||||||
|
"""主函数,可以接收账号信息、邮箱标签页和翻译器"""
|
||||||
|
global _translator
|
||||||
|
_translator = translator # 保存到全局变量
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
|
|
||||||
|
page = None
|
||||||
|
success = False
|
||||||
|
try:
|
||||||
|
page = setup_driver(translator)
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.browser_started')}")
|
||||||
|
else:
|
||||||
|
print("浏览器已启动")
|
||||||
|
|
||||||
|
# 访问注册页面
|
||||||
|
url = "https://authenticator.cursor.sh/sign-up"
|
||||||
|
if translator:
|
||||||
|
print(f"\n{translator.get('register.visiting_url')}: {url}")
|
||||||
|
else:
|
||||||
|
print(f"\n正在访问: {url}")
|
||||||
|
|
||||||
|
# 访问页面
|
||||||
|
simulate_human_input(page, url, translator)
|
||||||
|
if translator:
|
||||||
|
print(f"{translator.get('register.waiting_for_page_load')}")
|
||||||
|
else:
|
||||||
|
print("等待页面加载...")
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
# 如果没有提供账号信息,则生成随机信息
|
||||||
|
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()
|
||||||
|
|
||||||
|
# 保存账号信息
|
||||||
|
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")
|
||||||
|
|
||||||
|
# 填写表单
|
||||||
|
if fill_signup_form(page, first_name, last_name, email, translator):
|
||||||
|
if translator:
|
||||||
|
print(f"\n{translator.get('register.form_submitted')}")
|
||||||
|
else:
|
||||||
|
print("\n表单已提交,开始验证...")
|
||||||
|
|
||||||
|
# 处理第一次 Turnstile 验证
|
||||||
|
if handle_turnstile(page, translator):
|
||||||
|
if translator:
|
||||||
|
print(f"\n{translator.get('register.first_verification_passed')}")
|
||||||
|
else:
|
||||||
|
print("\n第一阶段验证通过!")
|
||||||
|
|
||||||
|
# 填写密码
|
||||||
|
if fill_password(page, password, translator):
|
||||||
|
if translator:
|
||||||
|
print(f"\n{translator.get('register.waiting_for_second_verification')}")
|
||||||
|
else:
|
||||||
|
print("\n等待第二次验证...")
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# 处理第二次 Turnstile 验证
|
||||||
|
if handle_turnstile(page, translator):
|
||||||
|
if translator:
|
||||||
|
print(f"\n{translator.get('register.waiting_for_verification_code')}")
|
||||||
|
else:
|
||||||
|
print("\n开始处理验证码...")
|
||||||
|
if handle_verification_code(page, email_tab, controller, email, password, translator):
|
||||||
|
if translator:
|
||||||
|
print(f"\n{translator.get('register.verification_success')}")
|
||||||
|
else:
|
||||||
|
print("\n注册流程完成!")
|
||||||
|
success = True
|
||||||
|
return True, page # 返回成功状态和浏览器实例
|
||||||
|
else:
|
||||||
|
print("\n验证码处理失败")
|
||||||
|
else:
|
||||||
|
print("\n第二次验证失败")
|
||||||
|
else:
|
||||||
|
print("\n密码设置失败")
|
||||||
|
else:
|
||||||
|
print("\n第一次验证失败")
|
||||||
|
|
||||||
|
return False, None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"发生错误: {e}")
|
||||||
|
return False, None
|
||||||
|
finally:
|
||||||
|
if page and not success: # 只在失败时清理
|
||||||
|
try:
|
||||||
|
page.quit()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
cleanup_chrome_processes(translator)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main() # 直接运行时不传参数,使用随机生成的信息
|
Loading…
x
Reference in New Issue
Block a user