diff --git a/.env b/.env index 324480b..162f08a 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -version=1.6.03 -VERSION=1.6.03 +version=1.7.01 +VERSION=1.7.01 diff --git a/CHANGELOG.md b/CHANGELOG.md index fcdf01f..d940331 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## v1.7.01 +- Refactoring: Extract configuration-related code from the `setup_driver` function to an independent `setup_config` function +- Optimization: Improve code maintainability and make configuration management and browser settings more clear +- Improvement: The creation and update logic of the configuration file is clearer and more independent + ## v1.6.03 1. Hotfix: Small Problem | 修復一些問題 diff --git a/README.md b/README.md index b88e271..4a7e324 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,21 @@ irm https://raw.githubusercontent.com/yeongpin/cursor-free-vip/main/scripts/rese ## ❗ Note | 注意事項 +📝 Config | 文件配置 +`Win / Macos / Linux Path | 路徑 [Documents/.cursor-free-vip/config.ini]` + +``` +[Chrome] +# Default Google Chrome Path | 默認Google Chrome 遊覽器路徑 +chromepath = C:\Program Files\Google/Chrome/Application/chrome.exe + +[Turnstile] +# Handle Tuenstile Wait Time | 等待人機驗證時間 +handle_turnstile_time = 2 +# Handle Tuenstile Wait Random Time (must merge 1-3 or 1,3) | 等待人機驗證隨機時間(必須是 1-3 或者 1,3 這樣的組合) +handle_turnstile_random_time = 1-3 +``` + * Use administrator to run the script
請使用管理員身份運行腳本 * Confirm that Cursor is closed before running the script
請確保在運行腳本前已經關閉 Cursor
@@ -98,9 +113,9 @@ irm https://raw.githubusercontent.com/yeongpin/cursor-free-vip/main/scripts/rese ## 🚨 Common Issues | 常見問題 -|如果遇到權限問題,請確保:|If you encounter permission issues, please ensure:| +|如果遇到權限問題,請確保:| 此腳本以管理員身份運行 | |:---:|:---:| -| 此腳本以管理員身份運行 | This script is run with administrator privileges | +|If you encounter permission issues, please ensure: | This script is run with administrator privileges | diff --git a/locales/en.json b/locales/en.json index 6356d39..3d048a8 100644 --- a/locales/en.json +++ b/locales/en.json @@ -136,7 +136,12 @@ "first_name": "First Name", "last_name": "Last Name", "exit_signal": "Exit Signal", - "email_address": "Email Address" + "email_address": "Email Address", + "config_created": "Config Created", + "verification_failed": "Verification Failed", + "verification_error": "Verification Error: {error}", + "config_option_added": "Config Option Added: {option}", + "config_updated": "Config Updated" }, "auth": { "title": "Cursor Auth Manager", diff --git a/locales/zh_cn.json b/locales/zh_cn.json index 108abeb..622aa81 100644 --- a/locales/zh_cn.json +++ b/locales/zh_cn.json @@ -136,7 +136,12 @@ "first_name": "名字", "last_name": "姓氏", "exit_signal": "退出信号", - "email_address": "邮箱地址" + "email_address": "邮箱地址", + "config_created": "配置已创建", + "verification_failed": "验证失败", + "verification_error": "验证错误: {error}", + "config_option_added": "配置项已添加: {option}", + "config_updated": "配置已更新" }, "auth": { "title": "Cursor 认证管理器", diff --git a/locales/zh_tw.json b/locales/zh_tw.json index 9ceafb9..ff96193 100644 --- a/locales/zh_tw.json +++ b/locales/zh_tw.json @@ -117,7 +117,12 @@ "first_name": "名字", "last_name": "姓氏", "exit_signal": "退出信號", - "email_address": "郵箱地址" + "email_address": "郵箱地址", + "config_created": "配置已創建", + "verification_failed": "驗證失敗", + "verification_error": "驗證錯誤: {error}", + "config_option_added": "配置項已添加: {option}", + "config_updated": "配置已更新" }, "auth": { "title": "Cursor 認證管理器", diff --git a/new_signup.py b/new_signup.py index fe34bbf..37b3538 100644 --- a/new_signup.py +++ b/new_signup.py @@ -4,6 +4,9 @@ import os import signal import random from colorama import Fore, Style +import configparser +from pathlib import Path +import sys # 在文件开头添加全局变量 _translator = None @@ -94,43 +97,181 @@ def fill_signup_form(page, first_name, last_name, email, translator=None): print(f"填写表单时出错: {e}") return False -def setup_driver(translator=None): - """设置浏览器驱动""" - co = ChromiumOptions() - - # 使用无痕模式 - co.set_argument("--incognito") +def get_default_chrome_path(): + """Get default Chrome path""" + if sys.platform == "win32": + paths = [ + os.path.join(os.environ.get('PROGRAMFILES', ''), 'Google/Chrome/Application/chrome.exe'), + os.path.join(os.environ.get('PROGRAMFILES(X86)', ''), 'Google/Chrome/Application/chrome.exe'), + os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Google/Chrome/Application/chrome.exe') + ] + elif sys.platform == "darwin": + paths = [ + "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" + ] + else: # Linux + paths = [ + "/usr/bin/google-chrome", + "/usr/bin/google-chrome-stable" + ] - # 设置随机端口 - co.set_argument("--no-sandbox") - - # 设置随机端口 - co.auto_port() - - # 使用有头模式(一定要设置为False,模擬人類操作) - co.headless(False) - + for path in paths: + if os.path.exists(path): + return path + return "" + +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 parse_random_time(time_str): + """解析随机时间范围配置""" 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) + if '-' in time_str: + min_time, max_time = map(float, time_str.split('-')) + elif ',' in time_str: + min_time, max_time = map(float, time_str.split(',')) + else: + min_time = max_time = float(time_str) + return min_time, max_time + except: + return 1, 3 # 默认值 + +def setup_config(translator=None): + """Setup configuration file and return config object""" + try: + # Set configuration file path + config_dir = os.path.join(get_user_documents_path(), ".cursor-free-vip") + config_file = os.path.join(config_dir, "config.ini") + + # Create config directory (if it doesn't exist) + os.makedirs(config_dir, exist_ok=True) + + # Read or create configuration file + config = configparser.ConfigParser() + + # 默认配置 + default_config = { + 'Chrome': { + 'chromepath': get_default_chrome_path() + }, + 'Turnstile': { + 'handle_turnstile_time': '2', + 'handle_turnstile_random_time': '1-3' + } + } + + if os.path.exists(config_file): + config.read(config_file) + config_modified = False + + # 检查并添加缺失的配置项 + for section, options in default_config.items(): + if not config.has_section(section): + config.add_section(section) + config_modified = True + for option, value in options.items(): + if not config.has_option(section, option): + config.set(section, option, value) + config_modified = True + if translator: + print(f"{Fore.YELLOW}ℹ️ {translator.get('register.config_option_added', option=f'{section}.{option}') if translator else f'添加配置项: {section}.{option}'}{Style.RESET_ALL}") + + # 如果有新增配置项,保存文件 + if config_modified: + with open(config_file, 'w', encoding='utf-8') as f: + config.write(f) + if translator: + print(f"{Fore.GREEN}✅ {translator.get('register.config_updated') if translator else '配置文件已更新'}{Style.RESET_ALL}") + else: + # 创建新配置文件 + config = configparser.ConfigParser() + for section, options in default_config.items(): + config.add_section(section) + for option, value in options.items(): + config.set(section, option, value) + + with open(config_file, 'w', encoding='utf-8') as f: + config.write(f) + if translator: + print(f"{Fore.GREEN}✅ {translator.get('register.config_created') if translator else '已创建配置文件'}: {config_file}{Style.RESET_ALL}") + + return config + 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"加载插件失败: {e}") - - if translator: - print(f"{Fore.CYAN}🚀 {translator.get('register.starting_browser')}{Style.RESET_ALL}") - else: - print("正在启动浏览器...") - page = ChromiumPage(co) - - return page + print(f"{Fore.RED}❌ {translator.get('register.config_setup_error', error=str(e)) if translator else f'配置设置出错: {str(e)}'}{Style.RESET_ALL}") + raise -def handle_turnstile(page, translator=None): +def setup_driver(translator=None): + """Setup browser driver""" + try: + # 获取配置 + config = setup_config(translator) + + # Get Chrome path + chrome_path = config.get('Chrome', 'chromepath', fallback=get_default_chrome_path()) + + if not chrome_path or not os.path.exists(chrome_path): + if translator: + print(f"{Fore.YELLOW}⚠️ {translator.get('register.chrome_path_invalid') if translator else 'Chrome路径无效,使用默认路径'}{Style.RESET_ALL}") + chrome_path = get_default_chrome_path() + + # Set browser options + co = ChromiumOptions() + + # Set Chrome path + co.set_browser_path(chrome_path) + + # Use incognito mode + co.set_argument("--incognito") + + # 设置随机端口 + co.set_argument("--no-sandbox") + + # 设置随机端口 + co.auto_port() + + # 使用有头模式(一定要设置为False,模拟人类操作) + 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"{Fore.RED}❌ {translator.get('register.extension_load_error', error=str(e))}{Style.RESET_ALL}") + else: + print(f"加载插件失败: {e}") + + if translator: + print(f"{Fore.CYAN}🚀 {translator.get('register.starting_browser')}{Style.RESET_ALL}") + else: + print("正在启动浏览器...") + + page = ChromiumPage(co) + 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"设置浏览器时出错: {e}") + raise + +def handle_turnstile(page, config, translator=None): """处理 Turnstile 验证""" try: if translator: @@ -138,6 +279,11 @@ def handle_turnstile(page, translator=None): else: print("\n正在处理 Turnstile 验证...") + # 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') + min_random_time, max_random_time = parse_random_time(random_time_str) + max_retries = 2 retry_count = 0 @@ -151,7 +297,7 @@ def handle_turnstile(page, translator=None): try: # 尝试重置 turnstile page.run_js("try { turnstile.reset() } catch(e) { }") - time.sleep(2) + time.sleep(turnstile_time) # from config # 定位验证框元素 challenge_check = ( @@ -168,12 +314,12 @@ def handle_turnstile(page, translator=None): else: print("检测到验证框...") - # 随机延时后点击验证 - time.sleep(random.uniform(1, 3)) + # from config + time.sleep(random.uniform(min_random_time, max_random_time)) challenge_check.click() - time.sleep(2) + 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}") @@ -195,7 +341,7 @@ def handle_turnstile(page, translator=None): print("验证通过!") return True - time.sleep(random.uniform(1, 2)) + time.sleep(random.uniform(min_random_time, max_random_time)) if translator: print(f"{Fore.RED}❌ {translator.get('register.verification_failed')}{Style.RESET_ALL}") @@ -240,34 +386,51 @@ def generate_password(length=12): chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*" return ''.join(random.choices(chars, k=length)) -def fill_password(page, password, translator=None): - """填写密码""" +def fill_password(page, password: str, translator=None) -> bool: + """ + 填写密码表单 + """ try: - if translator: - print(f"{Fore.CYAN}🔑 {translator.get('register.setting_password')}{Style.RESET_ALL}") - else: - print(f"\n{translator.get('register.setting_password')}") - password_input = page.ele("@name=password") + print(f"{Fore.CYAN}🔑 {translator.get('register.setting_password') if translator else '设置密码'}{Style.RESET_ALL}") + + # 等待密码框出现 + max_retries = 5 + for i in range(max_retries): + try: + # 使用 DrissionPage 的方式查找密码输入框 + password_input = page.ele('@type=password', timeout=3) + if password_input: + break + time.sleep(2) + except: + if i == max_retries - 1: + print(f"{Fore.RED}❌ {translator.get('register.password_field_not_found') if translator else '未找到密码输入框'}{Style.RESET_ALL}") + return False + continue + if password_input: + # 清除可能存在的旧值 + password_input.click() + time.sleep(0.5) password_input.input(password) - time.sleep(random.uniform(0.5, 1.0)) - - submit_button = page.ele("@type=submit") + time.sleep(1) + + # 查找并点击提交按钮 + submit_button = page.ele('@type=submit') if submit_button: submit_button.click() - time.sleep(random.uniform(2.0, 3.0)) - - if translator: - print(f"{Fore.GREEN}✅ {translator.get('register.password_success')}{Style.RESET_ALL}") + time.sleep(2) + return True else: - print(f"{translator.get('register.password_success')}: {password}") - return True - - except Exception as e: - if translator: - print(f"{Fore.RED}❌ {translator.get('register.password_error', error=str(e))}{Style.RESET_ALL}") + print(f"{Fore.RED}❌ {translator.get('register.continue_button_not_found') if translator else '未找到继续按钮'}{Style.RESET_ALL}") + return False else: - print(f"{translator.get('register.password_error')}: {e}") + print(f"{Fore.RED}❌ {translator.get('register.password_input_failed') if translator else '密码输入失败'}{Style.RESET_ALL}") + return False + + except Exception as e: + print(f"{Fore.RED}❌ {translator.get('register.password_setting_error', error=str(e)) if translator else f'设置密码时出错: {str(e)}'}{Style.RESET_ALL}") + return False def handle_verification_code(browser_tab, email_tab, controller, email, password, translator=None): @@ -275,8 +438,6 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password try: if translator: print(f"\n{Fore.CYAN}{translator.get('register.waiting_for_verification_code')}{Style.RESET_ALL}") - else: - print(f"\n{translator.get('register.waiting_for_verification_code')}") # 检查是否使用手动输入验证码 if hasattr(controller, 'get_verification_code') and email_tab is None: # 手动模式 @@ -293,13 +454,11 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password # 处理最后一次 Turnstile 验证 if handle_turnstile(browser_tab, translator): if translator: - print(f"{translator.get('register.verification_success')}") - else: - print(f"{translator.get('register.verification_success')}") + print(f"{Fore.GREEN}✅ {translator.get('register.verification_success')}{Style.RESET_ALL}") time.sleep(2) # 访问设置页面 - print(f"{translator.get('register.visiting_url')}: https://www.cursor.com/settings") + 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(3) # 等待页面加载 return True, browser_tab @@ -325,23 +484,17 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password 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 @@ -362,31 +515,23 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password 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() @@ -400,23 +545,17 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password 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) # 等待页面加载 @@ -426,8 +565,6 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password else: if translator: print(f"{Fore.RED}❌ {translator.get('register.verification_failed')}{Style.RESET_ALL}") - else: - print("最后一次验证失败") return False, None return False, None @@ -435,8 +572,6 @@ def handle_verification_code(browser_tab, email_tab, controller, email, password 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, None def handle_sign_in(browser_tab, email, password, translator=None): @@ -499,25 +634,19 @@ def main(email=None, password=None, first_name=None, last_name=None, email_tab=N page = None success = False try: - page = setup_driver(translator) + config, page = setup_driver(translator) if translator: print(f"{Fore.CYAN}🚀 {translator.get('register.browser_started')}{Style.RESET_ALL}") - else: - print("浏览器已启动") # 访问注册页面 url = "https://authenticator.cursor.sh/sign-up" if translator: print(f"\n{Fore.CYAN}{translator.get('register.visiting_url')}: {url}{Style.RESET_ALL}") - else: - print(f"\n正在访问: {url}") # 访问页面 simulate_human_input(page, url, translator) if translator: print(f"{Fore.CYAN}{translator.get('register.waiting_for_page_load')}{Style.RESET_ALL}") - else: - print("等待页面加载...") time.sleep(5) # 如果没有提供账号信息,则生成随机信息 @@ -538,41 +667,33 @@ def main(email=None, password=None, first_name=None, last_name=None, email_tab=N if fill_signup_form(page, first_name, last_name, email, translator): if translator: print(f"\n{Fore.GREEN}{translator.get('register.form_submitted')}{Style.RESET_ALL}") - else: - print("\n表单已提交,开始验证...") # 处理第一次 Turnstile 验证 - if handle_turnstile(page, translator): + if handle_turnstile(page, config, translator): if translator: print(f"\n{Fore.GREEN}{translator.get('register.first_verification_passed')}{Style.RESET_ALL}") - else: - print("\n第一阶段验证通过!") # 填写密码 if fill_password(page, password, translator): if translator: print(f"\n{Fore.CYAN}{translator.get('register.waiting_for_second_verification')}{Style.RESET_ALL}") - else: - print("\n等待第二次验证...") time.sleep(2) # 处理第二次 Turnstile 验证 - if handle_turnstile(page, translator): + if handle_turnstile(page, config, translator): if translator: print(f"\n{Fore.CYAN}{translator.get('register.waiting_for_verification_code')}{Style.RESET_ALL}") - else: - print("\n开始处理验证码...") if handle_verification_code(page, email_tab, controller, email, password, translator): success = True return True, page # 返回浏览器实例 else: - print("\n验证码处理失败") + print(f"\n{Fore.RED} {translator.get('register.verification_code_processing_failed') if translator else '验证码处理失败'}{Style.RESET_ALL}") else: - print("\n第二次验证失败") + print(f"\n{Fore.RED} {translator.get('register.second_verification_failed') if translator else '第二次验证失败'}{Style.RESET_ALL}") else: - print("\n密码设置失败") + print(f"\n{Fore.RED} {translator.get('register.second_verification_failed') if translator else '第二次验证失败'}{Style.RESET_ALL}") else: - print("\n第一次验证失败") + print(f"\n{Fore.RED} {translator.get('register.first_verification_failed') if translator else '第一次验证失败'}{Style.RESET_ALL}") return False, None diff --git a/new_tempemail.py b/new_tempemail.py index 63dedd7..2ea0f19 100644 --- a/new_tempemail.py +++ b/new_tempemail.py @@ -7,7 +7,7 @@ import requests import random import string -# 初始化 colorama +# Initialize colorama init() class NewTempEmail: @@ -34,7 +34,7 @@ class NewTempEmail: # Split text and remove empty lines domains = [line.strip() for line in response.text.split('\n') if line.strip()] if self.translator: - print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.blocked_domains_loaded', count=len(domains))}{Style.RESET_ALL}") + print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.blocked_domains_loaded', count=len(domains))}{Style.RESET_ALL}") else: print(f"{Fore.CYAN}ℹ️ 已加载 {len(domains)} 个被屏蔽的域名{Style.RESET_ALL}") return domains @@ -80,11 +80,11 @@ class NewTempEmail: attempt += 1 try: if self.translator: - print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.visiting_site').replace('mail.tm', self.selected_service['name'])}{Style.RESET_ALL}") + print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.visiting_site').replace('mail.tm', self.selected_service['name'])}{Style.RESET_ALL}") else: print(f"{Fore.CYAN}ℹ️ 正在访问 {self.selected_service['name']}...{Style.RESET_ALL}") - # 获取可用域名列表 + # Get available domain list try: domains_response = requests.get(f"{self.api_url}/domains", timeout=10) if domains_response.status_code != 200: @@ -93,7 +93,7 @@ class NewTempEmail: raise Exception(f"{self.translator.get('email.failed_to_get_available_domains') if self.translator else 'Failed to get available domains'}") domains = domains_response.json()["hydra:member"] - print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.available_domains_loaded', count=len(domains))}{Style.RESET_ALL}") + print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.available_domains_loaded', count=len(domains))}{Style.RESET_ALL}") if not domains: raise Exception(f"{self.translator.get('email.no_available_domains') if self.translator else '没有可用域名'}") @@ -101,11 +101,11 @@ class NewTempEmail: print(f"{Fore.RED}❌ 获取域名列表时出错: {str(e)}{Style.RESET_ALL}") raise - # 排除被屏蔽的域名 + # Exclude blocked domains try: filtered_domains = self.exclude_blocked_domains(domains) if self.translator: - print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.domains_filtered', count=len(filtered_domains))}{Style.RESET_ALL}") + print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.domains_filtered', count=len(filtered_domains))}{Style.RESET_ALL}") else: print(f"{Fore.CYAN}ℹ️ 过滤后剩余 {len(filtered_domains)} 个可用域名{Style.RESET_ALL}") @@ -115,33 +115,33 @@ class NewTempEmail: else: print(f"{Fore.RED}❌ 所有域名都被屏蔽了,尝试切换服务{Style.RESET_ALL}") - # 切换到另一个服务 + # Switch to another service for service in self.services: if service["api_url"] != self.api_url: self.selected_service = service self.api_url = service["api_url"] if self.translator: - print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.switching_service', service=service['name'])}{Style.RESET_ALL}") + print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.switching_service', service=service['name'])}{Style.RESET_ALL}") else: print(f"{Fore.CYAN}ℹ️ 切换到 {service['name']} 服务{Style.RESET_ALL}") - return self.create_email() # 递归调用 + return self.create_email() # Recursively call raise Exception(f"{self.translator.get('email.no_available_domains_after_filtering') if self.translator else '过滤后没有可用域名'}") except Exception as e: print(f"{Fore.RED}❌ 过滤域名时出错: {str(e)}{Style.RESET_ALL}") raise - # 生成随机用户名和密码 + # Generate random username and password try: username, password = self._generate_credentials() self.password = password - # 创建邮箱账户 + # Create email account selected_domain = filtered_domains[0]['domain'] email = f"{username}@{selected_domain}" if self.translator: - print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.trying_to_create_email', email=email)}{Style.RESET_ALL}") + print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.trying_to_create_email', email=email)}{Style.RESET_ALL}") else: print(f"{Fore.CYAN}ℹ️ 尝试创建邮箱: {email}{Style.RESET_ALL}") @@ -153,7 +153,7 @@ class NewTempEmail: print(f"{Fore.RED}❌ 生成凭据时出错: {str(e)}{Style.RESET_ALL}") raise - # 创建账户 + # Create account try: create_response = requests.post(f"{self.api_url}/accounts", json=account_data, timeout=15) @@ -167,13 +167,13 @@ class NewTempEmail: else: print(f"{Fore.RED}❌ 响应内容: {create_response.text}{Style.RESET_ALL}") - # 如果是域名问题,尝试下一个域名 + # If it's a domain problem, try the next available domain if len(filtered_domains) > 1 and ("domain" in create_response.text.lower() or "address" in create_response.text.lower()): print(f"{Fore.YELLOW}⚠️ 尝试使用下一个可用域名...{Style.RESET_ALL}") - # 将当前域名添加到屏蔽列表 + # Add current domain to blocked list if selected_domain not in self.blocked_domains: self.blocked_domains.append(selected_domain) - # 递归调用自己 + # Recursively call yourself return self.create_email() raise Exception(f"{self.translator.get('email.failed_to_create_account') if self.translator else '创建账户失败'}") @@ -184,7 +184,7 @@ class NewTempEmail: print(f"{Fore.RED}❌ 创建账户时出错: {str(e)}{Style.RESET_ALL}") raise - # 获取访问令牌 + # Get access token try: token_data = { "address": email, @@ -238,7 +238,7 @@ class NewTempEmail: else: print(f"{Fore.CYAN}🔄 正在刷新邮箱...{Style.RESET_ALL}") - # 使用 API 获取最新邮件 + # Use API to get latest email headers = {"Authorization": f"Bearer {self.token}"} response = requests.get(f"{self.api_url}/messages", headers=headers) @@ -265,7 +265,7 @@ class NewTempEmail: def check_for_cursor_email(self): """检查是否有 Cursor 的验证邮件""" try: - # 使用 API 获取邮件列表 + # Use API to get email list headers = {"Authorization": f"Bearer {self.token}"} response = requests.get(f"{self.api_url}/messages", headers=headers) @@ -273,7 +273,7 @@ class NewTempEmail: messages = response.json()["hydra:member"] for message in messages: if message["from"]["address"] == "no-reply@cursor.sh" and "Verify your email address" in message["subject"]: - # 获取邮件内容 + # Get email content message_id = message["id"] message_response = requests.get(f"{self.api_url}/messages/{message_id}", headers=headers) if message_response.status_code == 200: @@ -299,7 +299,7 @@ class NewTempEmail: def get_verification_code(self): """get verification code""" try: - # 使用 API 获取邮件列表 + # Use API to get email list headers = {"Authorization": f"Bearer {self.token}"} response = requests.get(f"{self.api_url}/messages", headers=headers) @@ -307,14 +307,14 @@ class NewTempEmail: messages = response.json()["hydra:member"] for message in messages: if message["from"]["address"] == "no-reply@cursor.sh" and "Verify your email address" in message["subject"]: - # 获取邮件内容 + # Get email content message_id = message["id"] message_response = requests.get(f"{self.api_url}/messages/{message_id}", headers=headers) if message_response.status_code == 200: - # 从邮件内容中提取验证码 + # Extract verification code from email content email_content = message_response.json()["text"] - # 查找6位数字验证码 + # Find 6-digit verification code import re code_match = re.search(r'\b\d{6}\b', email_content) @@ -350,7 +350,7 @@ def main(translator=None): else: print(f"\n{Fore.CYAN}📧 临时邮箱地址: {email}{Style.RESET_ALL}") - # 测试刷新功能 + # Test refresh function while True: if translator: choice = input(f"\n{translator.get('email.refresh_prompt')}: ").lower() diff --git a/reset_machine_manual.py b/reset_machine_manual.py index 3600ed0..fafedc9 100644 --- a/reset_machine_manual.py +++ b/reset_machine_manual.py @@ -171,9 +171,16 @@ def modify_workbench_js(file_path: str, translator=None) -> bool: with open(file_path, "r", encoding="utf-8", errors="ignore") as main_file: content = main_file.read() - # Define replacement patterns - CButton_old_pattern = r'$(k,E(Ks,{title:"Upgrade to Pro",size:"small",get codicon(){return F.rocket},get onClick(){return t.pay}}),null)' - CButton_new_pattern = r'$(k,E(Ks,{title:"yeongpin GitHub",size:"small",get codicon(){return F.rocket},get onClick(){return function(){window.open("https://github.com/yeongpin/cursor-free-vip","_blank")}}}),null)' + if sys.platform == "win32": + # Define replacement patterns + CButton_old_pattern = r'$(k,E(Ks,{title:"Upgrade to Pro",size:"small",get codicon(){return F.rocket},get onClick(){return t.pay}}),null)' + CButton_new_pattern = r'$(k,E(Ks,{title:"yeongpin GitHub",size:"small",get codicon(){return F.rocket},get onClick(){return function(){window.open("https://github.com/yeongpin/cursor-free-vip","_blank")}}}),null)' + elif sys.platform == "linux": + CButton_old_pattern = r'$(k,E(Ks,{title:"Upgrade to Pro",size:"small",get codicon(){return F.rocket},get onClick(){return t.pay}}),null)' + CButton_new_pattern = r'$(k,E(Ks,{title:"yeongpin GitHub",size:"small",get codicon(){return F.rocket},get onClick(){return function(){window.open("https://github.com/yeongpin/cursor-free-vip","_blank")}}}),null)' + elif sys.platform == "darwin": + CButton_old_pattern = r'M(x,I(as,{title:"Upgrade to Pro",size:"small",get codicon(){return $.rocket},get onClick(){return t.pay}}),null)' + CButton_new_pattern = r'M(x,I(as,{title:"yeongpin GitHub",size:"small",get codicon(){return $.rocket},get onClick(){return function(){window.open("https://github.com/yeongpin/cursor-free-vip","_blank")}}}),null)' CBadge_old_pattern = r'
Pro Trial' CBadge_new_pattern = r'
Pro' @@ -330,11 +337,20 @@ class MachineIDResetter: "~/Library/Application Support/Cursor/User/globalStorage/state.vscdb" )) elif sys.platform == "linux": # Linux - self.db_path = os.path.abspath(os.path.expanduser( - "~/.config/Cursor/User/globalStorage/storage.json" + # 获取实际用户的主目录 + sudo_user = os.environ.get('SUDO_USER') + if sudo_user: + actual_home = f"/home/{sudo_user}" + else: + actual_home = os.path.expanduser("~") + + self.db_path = os.path.abspath(os.path.join( + actual_home, + ".config/Cursor/User/globalStorage/storage.json" )) - self.sqlite_path = os.path.abspath(os.path.expanduser( - "~/.config/Cursor/User/globalStorage/state.vscdb" + self.sqlite_path = os.path.abspath(os.path.join( + actual_home, + ".config/Cursor/User/globalStorage/state.vscdb" )) else: raise NotImplementedError(f"Not Supported OS: {sys.platform}")