diff --git a/cursor_register_manual.py b/cursor_register_manual.py new file mode 100644 index 0000000..6a6d3d3 --- /dev/null +++ b/cursor_register_manual.py @@ -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) \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index 40b3b67..ddc10cf 100644 --- a/locales/en.json +++ b/locales/en.json @@ -4,6 +4,7 @@ "exit": "Exit Program", "reset": "Reset Machine Manual", "register": "Register Cursor", + "register_manual": "Register Cursor With Manual Email", "quit": "Quit Cursor", "select_language": "Select Language", "input_choice": "Enter your choice ({choices})", @@ -123,7 +124,9 @@ "get_email_address": "Get Email Address", "update_cursor_auth_info": "Update Cursor Auth Info", "register_process_error": "Register Process Error: {error}", - "setting_password": "Setting Password" + "setting_password": "Setting Password", + "manual_code_input": "Manual Code Input", + "manual_email_input": "Manual Email Input" }, "auth": { "title": "Cursor Auth Manager", diff --git a/locales/zh_cn.json b/locales/zh_cn.json index 7244afd..77af844 100644 --- a/locales/zh_cn.json +++ b/locales/zh_cn.json @@ -4,6 +4,7 @@ "exit": "退出程序", "reset": "重置机器标识", "register": "注册 Cursor", + "register_manual": "手动指定邮箱注册 Cursor", "quit": "退出 Cursor", "select_language": "选择语言", "input_choice": "输入选择 ({choices})", @@ -123,7 +124,9 @@ "get_email_address": "获取邮箱地址", "register_process_error": "注册流程错误: {error}", "update_cursor_auth_info": "更新Cursor认证信息", - "setting_password": "设置密码" + "setting_password": "设置密码", + "manual_code_input": "手动输入验证码", + "manual_email_input": "手动输入邮箱" }, "auth": { "title": "Cursor 认证管理器", diff --git a/locales/zh_tw.json b/locales/zh_tw.json index 9a98792..cdfa242 100644 --- a/locales/zh_tw.json +++ b/locales/zh_tw.json @@ -4,6 +4,7 @@ "exit": "退出程序", "reset": "重置機器標識", "register": "註冊 Cursor", + "register_manual": "手動指定郵箱註冊 Cursor", "quit": "退出 Cursor", "select_language": "選擇語言", "input_choice": "輸入選擇 ({choices})", @@ -123,7 +124,9 @@ "get_email_address": "獲取郵箱地址", "register_process_error": "註冊流程錯誤: {error}", "update_cursor_auth_info": "更新Cursor認證信息", - "setting_password": "設置密碼" + "setting_password": "設置密碼", + "manual_code_input": "手動輸入驗證碼", + "manual_email_input": "手動輸入郵箱地址" }, "auth": { "title": "Cursor 認證管理器", diff --git a/main.py b/main.py index 33f7fea..76d4049 100644 --- a/main.py +++ b/main.py @@ -71,8 +71,9 @@ def print_menu(): print(f"{Fore.GREEN}0{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.exit')}") print(f"{Fore.GREEN}1{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.reset')}") print(f"{Fore.GREEN}2{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register')}") - print(f"{Fore.GREEN}3{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.quit')}") - print(f"{Fore.GREEN}4{Style.RESET_ALL}. {EMOJI['LANG']} {translator.get('menu.select_language')}") + print(f"{Fore.GREEN}3{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register_manual')}") + print(f"{Fore.GREEN}4{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.quit')}") + print(f"{Fore.GREEN}5{Style.RESET_ALL}. {EMOJI['LANG']} {translator.get('menu.select_language')}") print(f"{Fore.YELLOW}{'─' * 40}{Style.RESET_ALL}") def select_language(): @@ -117,10 +118,14 @@ def main(): cursor_register.main(translator) break elif choice == "3": + import cursor_register_manual + cursor_register_manual.main(translator) + break + elif choice == "4": import quit_cursor quit_cursor.quit_cursor(translator) break - elif choice == "4": + elif choice == "5": if select_language(): print_menu() continue diff --git a/new_signup.py b/new_signup.py index 3b46c57..f17969d 100644 --- a/new_signup.py +++ b/new_signup.py @@ -275,23 +275,126 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password else: print("\n等待并获取验证码...") - # 添加调试信息 - print(f"\n{Fore.CYAN}DEBUG: email_tab exists: {email_tab is not None}{Style.RESET_ALL}") - - time.sleep(5) # 等待验证码邮件 - - # 使用已有的 email_tab 刷新邮箱 - email_tab.refresh_inbox() - time.sleep(3) - - # 检查邮箱是否有验证码邮件 - if email_tab.check_for_cursor_email(): - verification_code = email_tab.get_verification_code() + # 检查是否使用手动输入验证码 + if hasattr(controller, 'get_verification_code') and email_tab is None: # 手动模式 + verification_code = controller.get_verification_code() 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)) + + 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) + + # 访问设置页面 + print("访问设置页面...") + browser_tab.get("https://www.cursor.com/settings") + time.sleep(3) # 等待页面加载 + return True, browser_tab + + return False, None + + # 自动获取验证码逻辑 + elif email_tab: + print("等待验证码邮件...") + time.sleep(5) # 等待验证码邮件 + + # 使用已有的 email_tab 刷新邮箱 + email_tab.refresh_inbox() + time.sleep(3) + + # 检查邮箱是否有验证码邮件 + if email_tab.check_for_cursor_email(): + verification_code = email_tab.get_verification_code() + 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"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}") + else: + print("验证码填写完成") + time.sleep(3) + + # 处理最后一次 Turnstile 验证 + if handle_turnstile(browser_tab, translator): + if translator: + print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}") + else: + print("最后一次验证通过!") + time.sleep(2) + + # 访问设置页面 + if translator: + print(f"{Fore.CYAN}🔑 {translator.get('register.visiting_url')}: https://www.cursor.com/settings{Style.RESET_ALL}") + else: + print("访问设置页面...") + browser_tab.get("https://www.cursor.com/settings") + time.sleep(3) # 等待页面加载 + return True, browser_tab + + else: + if translator: + print(f"{Fore.RED}❌ {translator.get('register.verification_failed')}{Style.RESET_ALL}") + else: + print("最后一次验证失败") + return False, None + + # 获取验证码,设置超时 + verification_code = None + max_attempts = 20 + retry_interval = 10 + start_time = time.time() + timeout = 160 + + if translator: + print(f"{Fore.CYAN}{translator.get('register.start_getting_verification_code')}{Style.RESET_ALL}") + else: + print("开始获取验证码...") + + for attempt in range(max_attempts): + # 检查是否超时 + if time.time() - start_time > timeout: + if translator: + print(f"{Fore.RED}❌ {translator.get('register.verification_timeout')}{Style.RESET_ALL}") + else: + print("获取验证码超时...") + break + + verification_code = controller.get_verification_code() + if verification_code: + if translator: + print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}") + else: + print(f"成功获取验证码: {verification_code}") + 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}") + else: + print(f"第 {attempt + 1} 次尝试获取验证码,剩余时间: {remaining_time}秒...") + + # 刷新邮箱 + email_tab.refresh_inbox() + 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"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}") else: @@ -306,105 +409,32 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password print("最后一次验证通过!") time.sleep(2) - # 访问设置页面 + # 直接访问设置页面 if translator: - print(f"{Fore.CYAN}🔑 {translator.get('register.visiting_url')}: https://www.cursor.com/settings{Style.RESET_ALL}") + print(f"{Fore.CYAN}{translator.get('register.visiting_url')}: https://www.cursor.com/settings{Style.RESET_ALL}") else: print("访问设置页面...") browser_tab.get("https://www.cursor.com/settings") time.sleep(3) # 等待页面加载 - return True - else: - print("最后一次验证失败") - return False - return False - - # 获取验证码,设置超时 - verification_code = None - max_attempts = 20 - retry_interval = 10 - start_time = time.time() - timeout = 160 - - if translator: - print(f"{Fore.CYAN}{translator.get('register.start_getting_verification_code')}{Style.RESET_ALL}") - else: - print("开始获取验证码...") - - for attempt in range(max_attempts): - # 检查是否超时 - if time.time() - start_time > timeout: - if translator: - print(f"{Fore.RED}❌ {translator.get('register.verification_timeout')}{Style.RESET_ALL}") + # 直接返回成功,让 cursor_register.py 处理账户信息获取 + return True, browser_tab + else: - print("获取验证码超时...") - break + if translator: + print(f"{Fore.RED}❌ {translator.get('register.verification_failed')}{Style.RESET_ALL}") + else: + print("最后一次验证失败") + return False, None - verification_code = controller.get_verification_code() - if verification_code: - if translator: - print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}") - else: - print(f"成功获取验证码: {verification_code}") - 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}") - else: - print(f"第 {attempt + 1} 次尝试获取验证码,剩余时间: {remaining_time}秒...") + return False, None - # 刷新邮箱 - email_tab.refresh_inbox() - 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"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}") - else: - print("验证码填写完成") - time.sleep(3) - - # 处理最后一次 Turnstile 验证 - if handle_turnstile(browser_tab, translator): - if translator: - print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}") - else: - print("最后一次验证通过!") - time.sleep(2) - - # 直接访问设置页面 - if translator: - print(f"{Fore.CYAN}{translator.get('register.visiting_url')}: https://www.cursor.com/settings{Style.RESET_ALL}") - else: - print("访问设置页面...") - browser_tab.get("https://www.cursor.com/settings") - time.sleep(3) # 等待页面加载 - - # 直接返回成功,让 cursor_register.py 处理账户信息获取 - return True - - else: - if translator: - print(f"{Fore.RED}❌ {translator.get('register.verification_failed')}{Style.RESET_ALL}") - else: - print("最后一次验证失败") - return False - - 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"处理验证码时出错: {e}") - return False + return False, None def handle_sign_in(browser_tab, email, password, translator=None): """处理登录流程""" @@ -530,12 +560,8 @@ def main(email=None, password=None, first_name=None, last_name=None, email_tab=N else: print("\n开始处理验证码...") if handle_verification_code(page, email_tab, controller, email, password, translator): - if translator: - print(f"\n{Fore.GREEN}{translator.get('register.verification_success')}{Style.RESET_ALL}") - else: - print("\n注册流程完成!") success = True - return True, page # 返回成功状态和浏览器实例 + return True, page # 返回浏览器实例 else: print("\n验证码处理失败") else: diff --git a/new_tempemail.py b/new_tempemail.py index 70636e1..cdca8b9 100644 --- a/new_tempemail.py +++ b/new_tempemail.py @@ -16,10 +16,10 @@ class NewTempEmail: def get_extension_block(self): """获取插件路径""" root_dir = os.getcwd() - extension_path = os.path.join(root_dir, "uBlock0.chromium") + extension_path = os.path.join(root_dir, "PBlock") if hasattr(sys, "_MEIPASS"): - extension_path = os.path.join(sys._MEIPASS, "uBlock0.chromium") + extension_path = os.path.join(sys._MEIPASS, "PBlock") if not os.path.exists(extension_path): raise FileNotFoundError(f"插件不存在: {extension_path}")