From 731db36121713c4a0ecedd0f2e61669e84193ab0 Mon Sep 17 00:00:00 2001 From: yeongpin Date: Wed, 15 Jan 2025 13:35:09 +0800 Subject: [PATCH] new locale language file --- .env | 4 +- build.spec | 1 + control.py | 146 +++++++++++++++++++--------------------- cursor_auth.py | 16 +++-- cursor_register.py | 137 +++++++++++++++++++------------------ locales/en.json | 141 ++++++++++++++++++++++++++++++++++++++ locales/zh_cn.json | 115 +++++++++++++++++++++++++++++++ locales/zh_tw.json | 115 +++++++++++++++++++++++++++++++ logo.py | 13 +++- main.py | 100 ++++++++++++++++++++++----- quit_cursor.py | 37 +++++----- reset_machine_manual.py | 80 +++++++++------------- 12 files changed, 664 insertions(+), 241 deletions(-) create mode 100644 locales/en.json create mode 100644 locales/zh_cn.json create mode 100644 locales/zh_tw.json diff --git a/.env b/.env index 1fda2c5..cb14df6 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -version=1.0.6 -VERSION=1.0.6 +version=1.0.7 +VERSION=1.0.7 diff --git a/build.spec b/build.spec index b2b780e..24f8a9f 100644 --- a/build.spec +++ b/build.spec @@ -26,6 +26,7 @@ a = Analysis( ('turnstilePatch', 'turnstilePatch'), ('recaptchaPatch', 'recaptchaPatch'), ('uBlock0.chromium', 'uBlock0.chromium'), + ('locales', 'locales'), ('cursor_auth.py', '.'), ('reset_machine_manual.py', '.'), ('cursor_register.py', '.'), diff --git a/control.py b/control.py index 889335b..2629596 100644 --- a/control.py +++ b/control.py @@ -1,11 +1,25 @@ import time -from colorama import Fore, Style import random import os +from colorama import Fore, Style, init + +# 初始化colorama +init() + +# 定义emoji常量 +EMOJI = { + 'MAIL': '📧', + 'REFRESH': '🔄', + 'SUCCESS': '✅', + 'ERROR': '❌', + 'INFO': 'ℹ️', + 'CODE': '📱' +} class BrowserControl: - def __init__(self, browser): + def __init__(self, browser, translator=None): self.browser = browser + self.translator = translator # 保存translator self.sign_up_url = "https://authenticator.cursor.sh/sign-up" self.current_tab = None # 当前标签页 self.signup_tab = None # 注册标签页 @@ -25,20 +39,20 @@ class BrowserControl: # 保存新标签页 self.signup_tab = new_browser - print(f"{Fore.GREEN}Create New Tab Success | 成功创建新窗口{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.create_new_tab_success')}{Style.RESET_ALL}") return new_browser except Exception as e: - print(f"{Fore.RED}Create New Tab Failed | 创建新窗口时发生错误: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.create_new_tab_failed', error=str(e))}{Style.RESET_ALL}") return None def switch_to_tab(self, browser): """切换到指定浏览器窗口""" try: self.browser = browser - print(f"{Fore.GREEN}Switch Tab Success | 成功切换窗口{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.switch_tab_success')}{Style.RESET_ALL}") return True - except Exception as e: - print(f"{Fore.RED}Switch Tab Failed | 切换窗口时发生错误: {str(e)}{Style.RESET_ALL}") + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.switch_tab_failed', error=str(e))}{Style.RESET_ALL}") return False def get_current_tab(self): @@ -48,24 +62,24 @@ class BrowserControl: def generate_new_email(self): """点击新的按钮生成新邮箱""" try: - print(f"{Fore.CYAN}Click Generate New Email | 点击生成新邮箱...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.generate_email')}...{Style.RESET_ALL}") new_button = self.browser.ele('xpath://button[contains(@class, "egenbut")]') if new_button: new_button.click() time.sleep(1) # 等待生成 - print(f"{Fore.GREEN}Generate New Email | 成功生成新邮箱{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.generate_email_success')}{Style.RESET_ALL}") return True else: - print(f"{Fore.RED}No Generate Button Found | 未找到生成按钮{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.generate_email_failed')}{Style.RESET_ALL}") return False except Exception as e: - print(f"{Fore.RED}Generate New Email Failed | 生成新邮箱时发生错误: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.browser_error', error=str(e))}{Style.RESET_ALL}") return False def select_email_domain(self, domain_index=None): """选择邮箱域名,如果不指定index则随机选择""" try: - print(f"{Fore.CYAN}Select Email Domain | 选择邮箱域名...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}...{Style.RESET_ALL}") # 找到下拉框 select_element = self.browser.ele('xpath://select[@id="seldom"]') if select_element: @@ -88,21 +102,21 @@ class BrowserControl: if domain_index < len(all_options): # 获取选中选项的文本 selected_domain = all_options[domain_index].text - print(f"{Fore.CYAN}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}") # 点击选择 all_options[domain_index].click() time.sleep(1) - print(f"{Fore.GREEN}Select Email Domain | 成功选择邮箱域名{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.select_email_domain_success')}{Style.RESET_ALL}") return True - print(f"{Fore.RED}No Available Domain Options | 未找到可用的域名选项,总共有 {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}") return False else: - print(f"{Fore.RED}No Domain Select Box Found | 未找到域名选择框{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_domain_select_box')}{Style.RESET_ALL}") return False except Exception as e: - print(f"{Fore.RED}Select Email Domain Failed | 选择邮箱域名时发生错误: {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 def wait_for_page_load(self, seconds=2): @@ -112,18 +126,18 @@ class BrowserControl: def navigate_to(self, url): """导航到指定URL""" try: - print(f"{Fore.CYAN}Navigate to {url} | 正在访问 {url}...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.navigate_to', url=url)}...{Style.RESET_ALL}") self.browser.get(url) self.wait_for_page_load() return True except Exception as e: - print(f"{Fore.RED}Visit {url} Failed | 访问 {url} 时发生错误: {str(e)}{Style.RESET_ALL}") - return False + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.browser_error', error=str(e))}{Style.RESET_ALL}") + return False def copy_and_get_email(self): """获取邮箱地址""" try: - print(f"{Fore.CYAN}Get Email Info | 获取邮箱信息...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.generate_email')}...{Style.RESET_ALL}") # 等待元素加载 time.sleep(1) @@ -133,12 +147,12 @@ class BrowserControl: email_div = self.browser.ele('xpath://div[@class="segen"]//div[contains(@style, "color: #e5e5e5")]') if email_div: email_name = email_div.text.split()[0] - print(f"{Fore.CYAN}Get Email Name | 找到邮箱名称: {email_name}{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.get_email_name')}: {email_name}{Style.RESET_ALL}") else: - print(f"{Fore.RED}Get Email Name Failed | 无法找到邮箱名称元素{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_name_failed')}{Style.RESET_ALL}") return None except Exception as e: - print(f"{Fore.RED}Get Email Name Failed | 获取邮箱名称时出错: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_name_failed', error=str(e))}{Style.RESET_ALL}") return None # 直接使用上一步选择的域名 @@ -152,65 +166,47 @@ class BrowserControl: # 组合完整邮箱地址 full_email = f"{email_name}{domain}" - print(f"{Fore.GREEN}Get Email Address | 完整邮箱地址: {full_email}{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['MAIL']} {self.translator.get('control.get_email_address')}: {full_email}{Style.RESET_ALL}") return full_email except Exception as e: - print(f"{Fore.RED}Get Email Address Failed | 获取邮箱地址时发生错误: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_address_failed', error=str(e))}{Style.RESET_ALL}") return None def view_mailbox(self): """点击查看邮箱按钮""" try: - print(f"{Fore.CYAN}Enter Mailbox | 正在进入邮箱...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.enter_mailbox')}...{Style.RESET_ALL}") view_button = self.browser.ele('xpath://button[contains(@class, "egenbut") and contains(.//span, "查看邮箱")]') if view_button: view_button.click() time.sleep(2) # 等待页面加载 - print(f"{Fore.GREEN}Successfully Entered Mailbox | 成功进入邮箱{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.enter_mailbox_success')}{Style.RESET_ALL}") return True else: - print(f"{Fore.RED}No View Mailbox Button Found | 未找到查看邮箱按钮{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_view_mailbox_button')}{Style.RESET_ALL}") return False except Exception as e: - print(f"{Fore.RED}Enter Mailbox Failed | 进入邮箱时发生错误: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.enter_mailbox_failed', error=str(e))}{Style.RESET_ALL}") return False def refresh_mailbox(self): """刷新邮箱获取最新信息""" try: - print(f"{Fore.CYAN}Refresh Mailbox | 正在刷新邮箱...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.refresh_mailbox')}...{Style.RESET_ALL}") refresh_button = self.browser.ele('xpath://button[@id="refresh"]') if refresh_button: refresh_button.click() time.sleep(2) # 等待刷新完成 - print(f"{Fore.GREEN}Mailbox Refreshed Successfully | 邮箱刷新成功{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.refresh_mailbox_success')}{Style.RESET_ALL}") return True else: - print(f"{Fore.RED}No Refresh Button Found | 未找到刷新按钮{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_refresh_button')}{Style.RESET_ALL}") return False except Exception as e: - print(f"{Fore.RED}Refresh Mailbox Failed | 刷新邮箱时发生错误: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.refresh_mailbox_failed', error=str(e))}{Style.RESET_ALL}") return False - def check_and_click_recaptcha(self): - """检查并点击验证码复选框""" - try: - # 使用环境变量或配置文件中预设的坐标 - click_x = int(os.getenv('RECAPTCHA_X', '100')) # 默认值100 - click_y = int(os.getenv('RECAPTCHA_Y', '100')) # 默认值100 - - print(f"{Fore.CYAN}使用预设坐标点击: x={click_x}, y={click_y}{Style.RESET_ALL}") - - # 直接点击预设坐标 - self.browser.page.mouse.click(click_x, click_y) - print(f"{Fore.GREEN}Clicked reCAPTCHA Position | 已点击 reCAPTCHA 位置{Style.RESET_ALL}") - time.sleep(1) - return True - - except Exception as e: - print(f"{Fore.YELLOW}Click reCAPTCHA Failed | 点击 reCAPTCHA 失败: {str(e)}{Style.RESET_ALL}") - return False def get_verification_code(self): """从邮件中获取验证码""" @@ -233,24 +229,24 @@ class BrowserControl: if code_div: verification_code = code_div.text.strip() if verification_code.isdigit() and len(verification_code) == 6: - print(f"{Fore.GREEN}Found Verification Code | 找到验证码: {verification_code}{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.found_verification_code')}: {verification_code}{Style.RESET_ALL}") return verification_code - print(f"{Fore.YELLOW}No Valid Verification Code Found | 未找到有效验证码{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['ERROR']} {self.translator.get('control.no_valid_verification_code')}{Style.RESET_ALL}") return None except Exception as e: - print(f"{Fore.RED}Get Verification Code Error | 获取验证码时发生错误: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_verification_code_error', error=str(e))}{Style.RESET_ALL}") return None def fill_verification_code(self, code): """填写验证码""" try: if not code or len(code) != 6: - print(f"{Fore.RED}Verification Code Format Error | 验证码格式不正确{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.verification_code_format_error')}{Style.RESET_ALL}") return False - print(f"{Fore.CYAN}Fill Verification Code | 正在填写验证码...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.fill_verification_code')}...{Style.RESET_ALL}") # 记住当前标签页(邮箱页面) email_tab = self.browser @@ -264,10 +260,10 @@ class BrowserControl: self.browser.actions.input(digit) time.sleep(random.uniform(0.1, 0.3)) - print(f"{Fore.GREEN}Verification Code Filled | 验证码填写完成{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.verification_code_filled')}{Style.RESET_ALL}") # 等待页面加载和登录完成 - print(f"{Fore.CYAN}Wait for Login | 等待登录完成...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.wait_for_login')}...{Style.RESET_ALL}") time.sleep(5) # 先访问登录页面确保登录状态 @@ -278,7 +274,7 @@ class BrowserControl: # 获取cookies(第一次尝试) token = self.get_cursor_session_token() if not token: - print(f"{Fore.YELLOW}Get Token Failed | 首次获取token失败,等待后重试...{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['ERROR']} {self.translator.get('control.get_token_failed')}...{Style.RESET_ALL}") time.sleep(3) token = self.get_cursor_session_token() @@ -287,7 +283,7 @@ class BrowserControl: # 获取到token后再访问设置页面 settings_url = "https://www.cursor.com/settings" - print(f"{Fore.CYAN}Get Account Info | 正在访问设置页面获取账户信息...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.get_account_info')}...{Style.RESET_ALL}") self.browser.get(settings_url) time.sleep(2) @@ -302,9 +298,9 @@ class BrowserControl: if usage_ele: usage_info = usage_ele.text total_usage = usage_info.split("/")[-1].strip() - print(f"{Fore.GREEN}Account Usage Limit | 账户可用额度上限: {total_usage}{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['INFO']} {self.translator.get('control.account_usage_limit')}: {total_usage}{Style.RESET_ALL}") except Exception as e: - print(f"{Fore.RED}Get Account Usage Failed | 获取账户额度信息失败: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_account_usage_failed', error=str(e))}{Style.RESET_ALL}") # 切换回邮箱页面 self.switch_to_tab(email_tab) @@ -312,7 +308,7 @@ class BrowserControl: return True except Exception as e: - print(f"{Fore.RED}Fill Verification Code Failed | 填写验证码时发生错误: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.fill_verification_code_failed', error=str(e))}{Style.RESET_ALL}") return False def check_and_click_turnstile(self): @@ -324,19 +320,19 @@ class BrowserControl: # 查找验证框 verify_checkbox = self.browser.ele('xpath://label[contains(@class, "cb-lb")]//input[@type="checkbox"]') if verify_checkbox: - print(f"{Fore.CYAN}Find Turnstile Verification Box | 找到 Turnstile 验证框,尝试点击...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.find_turnstile_verification_box')}...{Style.RESET_ALL}") verify_checkbox.click() time.sleep(2) # 等待验证完成 - print(f"{Fore.GREEN}Clicked Turnstile Verification Box | 已点击 Turnstile 验证框{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.clicked_turnstile_verification_box')}{Style.RESET_ALL}") return True return False except Exception as e: - print(f"{Fore.YELLOW}Check and Click Turnstile Failed | 未找到 Turnstile 验证框或点击失败: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['ERROR']} {self.translator.get('control.check_and_click_turnstile_failed', error=str(e))}{Style.RESET_ALL}") return False def get_cursor_session_token(self, max_attempts=3, retry_interval=2): """获取Cursor会话token""" - print(f"{Fore.CYAN}Get Cursor Session Token | 开始获取cookie...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.get_cursor_session_token')}...{Style.RESET_ALL}") attempts = 0 while attempts < max_attempts: @@ -348,21 +344,21 @@ class BrowserControl: for cookie in all_cookies: if cookie.get("name") == "WorkosCursorSessionToken": token = cookie["value"].split("%3A%3A")[1] - print(f"{Fore.GREEN}成功获取CursorSessionToken: {token}{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.get_cursor_session_token_success')}: {token}{Style.RESET_ALL}") return token attempts += 1 if attempts < max_attempts: - print(f"{Fore.YELLOW} Try | 第 {attempts} 次尝试未获取到CursorSessionToken,{retry_interval}秒后重试...{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['ERROR']} {self.translator.get('control.get_cursor_session_token_failed', attempts=attempts, retry_interval=retry_interval)}...{Style.RESET_ALL}") time.sleep(retry_interval) else: - print(f"{Fore.RED}Reach Max Attempts ({max_attempts}) | 已达到最大尝试次数({max_attempts}),获取CursorSessionToken失败{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.reach_max_attempts', max_attempts=max_attempts)}{Style.RESET_ALL}") except Exception as e: - print(f"{Fore.RED}获取cookie失败: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_cookie_failed', error=str(e))}{Style.RESET_ALL}") attempts += 1 if attempts < max_attempts: - print(f"{Fore.YELLOW}Will Retry in {retry_interval} seconds | 将在 {retry_interval} 秒后重试...{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['ERROR']} {self.translator.get('control.will_retry_in', retry_interval=retry_interval)}...{Style.RESET_ALL}") time.sleep(retry_interval) return None @@ -373,6 +369,6 @@ class BrowserControl: with open('cursor_tokens.txt', 'a', encoding='utf-8') as f: f.write(f"Token: {token}\n") f.write("-" * 50 + "\n") - print(f"{Fore.GREEN}Token Saved to cursor_tokens.txt | Token已保存到 cursor_tokens.txt{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.token_saved_to_file')}{Style.RESET_ALL}") except Exception as e: - print(f"{Fore.RED}Save Token Failed | 保存Token时发生错误: {str(e)}{Style.RESET_ALL}") \ No newline at end of file + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.save_token_failed', error=str(e))}{Style.RESET_ALL}") \ No newline at end of file diff --git a/cursor_auth.py b/cursor_auth.py index 0bce421..a1e29bf 100644 --- a/cursor_auth.py +++ b/cursor_auth.py @@ -14,11 +14,13 @@ EMOJI = { 'ERROR': '❌', 'WARN': '⚠️', 'INFO': 'ℹ️', - 'KEY': '🔑' + 'FILE': '📄', + 'KEY': '🔐' } class CursorAuth: - def __init__(self): + def __init__(self, translator=None): + self.translator = translator # 判断操作系统 if os.name == "nt": # Windows self.db_path = os.path.join( @@ -54,7 +56,7 @@ class CursorAuth: # 重新连接数据库 conn = sqlite3.connect(self.db_path) - print(f"{EMOJI['INFO']} {Fore.GREEN}Successfully connected to database | 成功连接到数据库{Style.RESET_ALL}") + print(f"{EMOJI['INFO']} {Fore.GREEN}{self.translator.get('auth.connected_to_database')}{Style.RESET_ALL}") cursor = conn.cursor() # 增加超时和其他优化设置 @@ -91,7 +93,7 @@ class CursorAuth: print(f"{EMOJI['INFO']} {Fore.CYAN}Updating {key.split('/')[-1]}...{Style.RESET_ALL}") cursor.execute("COMMIT") - print(f"{EMOJI['SUCCESS']} {Fore.GREEN}Database updated successfully | 数据库更新成功{Style.RESET_ALL}") + print(f"{EMOJI['SUCCESS']} {Fore.GREEN}{self.translator.get('auth.database_updated_successfully')}{Style.RESET_ALL}") return True except Exception as e: @@ -99,14 +101,14 @@ class CursorAuth: raise e except sqlite3.Error as e: - print(f"\n{EMOJI['ERROR']} {Fore.RED}Database error | 数据库错误: {str(e)}{Style.RESET_ALL}") + print(f"\n{EMOJI['ERROR']} {Fore.RED}{self.translator.get('auth.database_error', error=str(e))}{Style.RESET_ALL}") return False except Exception as e: - print(f"\n{EMOJI['ERROR']} {Fore.RED}An error occurred | 发生错误: {str(e)}{Style.RESET_ALL}") + print(f"\n{EMOJI['ERROR']} {Fore.RED}{self.translator.get('auth.an_error_occurred', error=str(e))}{Style.RESET_ALL}") return False finally: if conn: conn.close() - print(f"{EMOJI['DB']} {Fore.CYAN}Database connection closed | 数据库连接已关闭{Style.RESET_ALL}") + print(f"{EMOJI['DB']} {Fore.CYAN}{self.translator.get('auth.database_connection_closed')}{Style.RESET_ALL}") diff --git a/cursor_register.py b/cursor_register.py index cb24e4c..f016fef 100644 --- a/cursor_register.py +++ b/cursor_register.py @@ -13,7 +13,7 @@ os.environ["PYINSTALLER_VERBOSE"] = "0" # 初始化colorama init() -# 定义emoji和颜色常量 +# 定义emoji常量 EMOJI = { 'START': '🚀', 'FORM': '📝', @@ -24,13 +24,15 @@ EMOJI = { 'ERROR': '❌', 'WAIT': '⏳', 'SUCCESS': '✅', - 'MAIL': '��', + 'MAIL': '📧', 'KEY': '🔐', - 'UPDATE': '🔄' + 'UPDATE': '🔄', + 'INFO': 'ℹ️' } class CursorRegistration: - def __init__(self): + def __init__(self, translator=None): + self.translator = translator # 设置为显示模式 os.environ['BROWSER_HEADLESS'] = 'False' self.browser_manager = BrowserManager() @@ -60,11 +62,11 @@ class CursorRegistration: return first_letter + rest_letters def setup_email(self): - """Setup Temporary Email""" + """设置邮箱""" try: - print(f"{Fore.CYAN}Staring Browser | 正在启动浏览器...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.browser_start')}...{Style.RESET_ALL}") self.browser = self.browser_manager.init_browser() - self.controller = BrowserControl(self.browser) + self.controller = BrowserControl(self.browser, self.translator) # 打开邮箱生成器页面(第一个标签页) self.controller.navigate_to(self.mail_url) @@ -80,7 +82,7 @@ class CursorRegistration: # 获取邮箱地址 self.email_address = self.controller.copy_and_get_email() if self.email_address: - print(f"{Fore.CYAN}Get Email Address | 获取到的邮箱地址: {self.email_address}{Style.RESET_ALL}") + print(f"{EMOJI['MAIL']}{Fore.CYAN} {self.translator.get('register.get_email_address')}: {self.email_address}{Style.RESET_ALL}") # 进入邮箱 if self.controller.view_mailbox(): @@ -89,14 +91,14 @@ class CursorRegistration: return False except Exception as e: - print(f"{Fore.RED}Error Occured | 发生错误: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.setup_error', error=str(e))}{Style.RESET_ALL}") return False def register_cursor(self): - """注册 Cursor 账号""" + """注册 Cursor""" signup_browser_manager = None try: - print(f"\n{Fore.CYAN}{EMOJI['START']}Start Register | 开始 Cursor 注册流程{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.register_start')}...{Style.RESET_ALL}") # 创建新的浏览器实例用于注册 from browser import BrowserManager @@ -109,7 +111,7 @@ class CursorRegistration: # 填写注册表单 if self.signup_tab.ele("@name=first_name"): - print(f"{Fore.YELLOW}{EMOJI['FORM']}Fill Form | 填写注册信息...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['FORM']} {self.translator.get('register.filling_form')}...{Style.RESET_ALL}") self.signup_tab.ele("@name=first_name").input(self.first_name) time.sleep(random.uniform(1, 2)) @@ -121,14 +123,14 @@ class CursorRegistration: time.sleep(random.uniform(1, 2)) self.signup_tab.ele("@type=submit").click() - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Basic Info Submitted | 基本信息提交完成{Style.RESET_ALL}") + 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.YELLOW}{EMOJI['PASSWORD']} Set Password | 设置密码...{Style.RESET_ALL}") + 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() @@ -147,21 +149,21 @@ class CursorRegistration: start_time = time.time() timeout = 60 # 60秒超时 - print(f"{Fore.CYAN}{EMOJI['WAIT']} Start Getting Verification Code | 开始获取验证码,将在60秒内尝试...{Style.RESET_ALL}") + 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']} Get Verification Code Timeout | 获取验证码超时{Style.RESET_ALL}") + 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']} Get Verification Code Success | 成功获取验证码: {verification_code}{Style.RESET_ALL}") + 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']} Try | 第 {attempt + 1} Get Verification Code | 次尝试未获取到验证码,Time Remaining | 剩余时间: {remaining_time}秒{Style.RESET_ALL}") + 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() @@ -173,7 +175,7 @@ class CursorRegistration: self.signup_tab.ele(f"@data-index={i}").input(digit) time.sleep(random.uniform(0.1, 0.3)) - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Verification Code Filled | 验证码填写完成{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.verification_code_filled')}...{Style.RESET_ALL}") time.sleep(3) self._handle_turnstile() @@ -181,7 +183,7 @@ class CursorRegistration: # 检查当前URL current_url = self.signup_tab.url if "authenticator.cursor.sh" in current_url: - print(f"{Fore.CYAN}{EMOJI['VERIFY']} Detect Login Page | 检测到登录页面,开始登录...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['VERIFY']} {self.translator.get('register.detect_login_page')}...{Style.RESET_ALL}") # 填写邮箱 email_input = self.signup_tab.ele('@name=email') @@ -218,7 +220,7 @@ class CursorRegistration: 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']} Login Success and Jump to Settings Page | 成功登录并跳转到设置页面{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.login_success_and_jump_to_settings_page')}...{Style.RESET_ALL}") break time.sleep(1) @@ -231,11 +233,11 @@ class CursorRegistration: return result else: - print(f"{Fore.RED}{EMOJI['ERROR']} Get Verification Code Timeout | 未能在60秒内获取到验证码{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.get_verification_code_timeout')}...{Style.RESET_ALL}") return False except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} Register Process 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 finally: # 确保在任何情况下都关闭注册窗口 @@ -244,7 +246,7 @@ class CursorRegistration: def _handle_turnstile(self): """处理 Turnstile 验证""" - print(f"{Fore.YELLOW}{EMOJI['VERIFY']} Handle Turnstile | 处理 Turnstile 验证...{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['VERIFY']} {self.translator.get('register.handle_turnstile')}...{Style.RESET_ALL}") # 设置最大等待时间(秒) max_wait_time = 10 # 增加等待时间 @@ -254,11 +256,10 @@ class CursorRegistration: try: # 检查是否超时 if time.time() - start_time > max_wait_time: - print(f"{Fore.YELLOW}{EMOJI['WAIT']} Not Detect Turnstile | 未检测到 Turnstile 验证,继续下一步...{Style.RESET_ALL}") - time.sleep(2) # 添加短暂延迟 + print(f"{Fore.YELLOW}{EMOJI['WAIT']} {self.translator.get('register.no_turnstile')}...{Style.RESET_ALL}") + time.sleep(2) break - # 检查是否存在验证框 try: challengeCheck = ( self.signup_tab.ele("@id=cf-turnstile", timeout=1) @@ -270,43 +271,38 @@ class CursorRegistration: if challengeCheck: challengeCheck.click() - time.sleep(3) # 增加点击后的等待时间 - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Turnstile Passed | 验证通过{Style.RESET_ALL}") - time.sleep(2) # 确保验证完全完成 + time.sleep(3) + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.turnstile_passed')}{Style.RESET_ALL}") + time.sleep(2) break except: pass - # 检查是否已经通过验证(检查下一步的元素是否存在) 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)): - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Verification Passed | 验证已通过{Style.RESET_ALL}") - time.sleep(2) # 添加短暂延迟 + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.turnstile_passed')}{Style.RESET_ALL}") + time.sleep(2) break except: pass - # 等待短暂时间后继续检查 time.sleep(1) except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} Turnstile Error | Turnstile 处理出错: {str(e)}{Style.RESET_ALL}") - time.sleep(2) # 出错时等待更长时间 + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.error', error=str(e))}{Style.RESET_ALL}") + time.sleep(2) break - # 最后再等待一下,确保页面加载完成 time.sleep(2) 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 > " @@ -317,8 +313,7 @@ class CursorRegistration: if usage_ele: total_usage = usage_ele.text.split("/")[-1].strip() - # 获取 Token - print(f"{Fore.CYAN}{EMOJI['WAIT']} Get Cursor Session Token | 开始获取 Cursor Session Token...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('register.get_token')}...{Style.RESET_ALL}") max_attempts = 30 retry_interval = 2 attempts = 0 @@ -329,46 +324,45 @@ class CursorRegistration: for cookie in cookies: if cookie.get("name") == "WorkosCursorSessionToken": token = cookie["value"].split("%3A%3A")[1] - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Get Token Success | Token 获取成功{Style.RESET_ALL}") - # 保存账户信息 + 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']} Try | 第 {attempts} times to get Token | 次尝试未获取到 Token,{retry_interval}秒后重试...{Style.RESET_ALL}" - ) + 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']} Reach Max Attempts ({max_attempts}) | 已达到最大尝试次数({max_attempts}),获取 Token 失败{Style.RESET_ALL}") + 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']} Get Token Failed | 获取 Token 失败: {str(e)}{Style.RESET_ALL}") + 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']} Will Retry in {retry_interval} seconds | 将在 {retry_interval} 秒后重试...{Style.RESET_ALL}") + 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']} Get Account Info Failed | 获取账户信息失败: {str(e)}{Style.RESET_ALL}") + 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']} 正在更新 Cursor 认证信息...{Style.RESET_ALL}") - if update_cursor_auth(email=self.email_address, access_token=token, refresh_token=token): - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Cursor Auth Info Updated | 认证信息更新成功{Style.RESET_ALL}") + 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']} Cursor Auth Info Update Failed | 认证信息更新失败{Style.RESET_ALL}") + 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']} Reset Machine ID | 正在重置机器ID...{Style.RESET_ALL}") - MachineIDResetter().reset_machine_ids() + 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: @@ -379,11 +373,11 @@ class CursorRegistration: f.write(f"Usage Limit: {total_usage}\n") f.write(f"{'='*50}\n") - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Account Info Saved to cursor_accounts.txt | 账户信息已保存到 cursor_accounts.txt{Style.RESET_ALL}") + 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']} Save Account Info Failed | 保存账户信息失败: {str(e)}{Style.RESET_ALL}") + 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): @@ -391,25 +385,30 @@ class CursorRegistration: try: if self.setup_email(): if self.register_cursor(): - print(f"\n{Fore.GREEN}{EMOJI['DONE']} Cursor Registration Completed | 注册完成!{Style.RESET_ALL}") + print(f"\n{Fore.GREEN}{EMOJI['DONE']} {self.translator.get('register.cursor_registration_completed')}...{Style.RESET_ALL}") return True return False finally: if self.browser_manager: self.browser_manager.quit() + 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}") -def update_cursor_auth(email=None, access_token=None, refresh_token=None): - """ - 更新Cursor的认证信息的便捷函数 - """ - auth_manager = CursorAuth() - return auth_manager.update_auth(email, access_token, refresh_token) - -def main(): - registration = CursorRegistration() + 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__": - main() \ No newline at end of file + 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 new file mode 100644 index 0000000..4b27679 --- /dev/null +++ b/locales/en.json @@ -0,0 +1,141 @@ +{ + "menu": { + "title": "Available Options", + "exit": "Exit Program", + "reset": "Reset Machine Manual", + "register": "Register Cursor", + "quit": "Quit Cursor", + "select_language": "Select Language", + "input_choice": "Enter your choice ({choices})", + "invalid_choice": "Invalid choice. Please try again", + "program_terminated": "Program terminated by user", + "error_occurred": "An error occurred: {error}", + "press_enter": "Press Enter to Exit" + }, + "languages": { + "en": "English", + "zh_cn": "简体中文", + "zh_tw": "繁體中文" + }, + "quit_cursor": { + "start": "Start Quitting Cursor", + "no_process": "No Running Cursor Process", + "terminating": "Terminating Process {pid}", + "waiting": "Waiting for Process to Exit", + "success": "All Cursor Processes Closed", + "timeout": "Process Timeout: {pids}", + "error": "Error Occurred: {error}" + }, + "reset": { + "title": "Cursor Machine ID Reset Tool", + "checking": "Checking Config File", + "not_found": "Config File Not Found", + "no_permission": "Cannot Read or Write Config File, Please Check File Permissions", + "reading": "Reading Current Config", + "creating_backup": "Creating Config Backup", + "backup_exists": "Backup File Already Exists, Skipping Backup Step", + "generating": "Generating New Machine ID", + "saving_json": "Saving New Config to JSON", + "success": "Machine ID Reset Successfully", + "new_id": "New Machine ID", + "permission_error": "Permission Error: {error}", + "run_as_admin": "Please Try Running This Program as Administrator", + "process_error": "Reset Process Error: {error}", + "updating_sqlite": "Updating SQLite Database", + "updating_pair": "Updating Key-Value Pair", + "sqlite_success": "SQLite Database Updated Successfully", + "sqlite_error": "SQLite Database Update Failed: {error}", + "press_enter": "Press Enter to Exit" + }, + "register": { + "title": "Cursor Registration Tool", + "start": "Starting Registration Process", + "mailbox": "Successfully Entered Mailbox", + "register_start": "Start Register", + "filling_form": "Fill Form", + "basic_info": "Basic Info Submitted", + "handle_turnstile": "Handle Turnstile", + "no_turnstile": "Not Detect Turnstile", + "turnstile_passed": "Turnstile Passed", + "verification_start": "Start Getting Verification Code", + "verification_timeout": "Get Verification Code Timeout", + "verification_not_found": "No Verification Code Found", + "try_get_code": "Try | {attempt} Get Verification Code | Time Remaining: {time}s", + "get_account": "Getting Account Info", + "get_token": "Get Cursor Session Token", + "token_success": "Get Token Success", + "token_attempt": "Try | {attempt} times to get Token | Will retry in {time}s", + "token_max_attempts": "Reach Max Attempts ({max}) | Failed to get Token", + "token_failed": "Get Token Failed: {error}", + "account_error": "Get Account Info Failed: {error}", + "press_enter": "Press Enter to Exit", + "browser_start": "Starting Browser", + "open_mailbox": "Opening Mailbox Page", + "email_error": "Failed to Get Email Address", + "setup_error": "Email Setup Error: {error}", + "start_getting_verification_code": "Start Getting Verification Code, Will Try in 60s", + "get_verification_code_timeout": "Get Verification Code Timeout", + "get_verification_code_success": "Get Verification Code Success", + "try_get_verification_code": "Try | {attempt} Get Verification Code | Time Remaining: {remaining_time}s", + "verification_code_filled": "Verification Code Filled", + "login_success_and_jump_to_settings_page": "Login Success and Jump to Settings Page", + "detect_login_page": "Detect Login Page, Start Login...", + "cursor_registration_completed": "Cursor Registration Completed!", + "set_password": "Set Password", + "basic_info_submitted": "Basic Info Submitted", + "cursor_auth_info_updated": "Cursor Auth Info Updated", + "cursor_auth_info_update_failed": "Cursor Auth Info Update Failed", + "reset_machine_id": "Reset Machine ID", + "account_info_saved": "Account Info Saved", + "save_account_info_failed": "Save Account Info Failed", + "get_email_address": "Get Email Address", + "update_cursor_auth_info": "Update Cursor Auth Info", + "register_process_error": "Register Process Error: {error}" + }, + "auth": { + "title": "Cursor Auth Manager", + "checking_auth": "Checking Auth File", + "auth_not_found": "Auth File Not Found", + "auth_file_error": "Auth File Error: {error}", + "reading_auth": "Reading Auth File", + "updating_auth": "Updating Auth Info", + "auth_updated": "Auth Info Updated Successfully", + "auth_update_failed": "Auth Info Update Failed: {error}", + "auth_file_created": "Auth File Created", + "auth_file_create_failed": "Auth File Create Failed: {error}", + "press_enter": "Press Enter to Exit", + "reset_machine_id": "Reset Machine ID", + "database_connection_closed": "Database Connection Closed", + "database_updated_successfully": "Database Updated Successfully", + "connected_to_database": "Connected to Database" + }, + "control": { + "generate_email": "Generating New Email", + "select_domain": "Selecting Random Domain", + "copy_email": "Copying Email Address", + "enter_mailbox": "Entering Mailbox", + "refresh_mailbox": "Refreshing Mailbox", + "check_verification": "Checking Verification Code", + "verification_found": "Verification Code Found", + "verification_not_found": "No Verification Code Found", + "browser_error": "Browser Control Error: {error}", + "navigation_error": "Navigation Error: {error}", + "email_copy_error": "Email Copy Error: {error}", + "mailbox_error": "Mailbox Error: {error}", + "token_saved_to_file": "Token Saved to cursor_tokens.txt", + "navigate_to": "Navigating to {url}", + "generate_email_success": "Generate Email Success", + "select_email_domain": "Select Email Domain", + "select_email_domain_success": "Select Email Domain Success", + "get_email_name": "Get Email Name", + "get_email_name_success": "Get Email Name Success", + "get_email_address": "Get Email Address", + "get_email_address_success": "Get Email Address Success", + "enter_mailbox_success": "Enter Mailbox Success", + "found_verification_code": "Found Verification Code", + "get_cursor_session_token": "Get Cursor Session Token", + "get_cursor_session_token_success": "Get Cursor Session Token Success", + "get_cursor_session_token_failed": "Get Cursor Session Token Failed", + "save_token_failed": "Save Token Failed" + } +} \ No newline at end of file diff --git a/locales/zh_cn.json b/locales/zh_cn.json new file mode 100644 index 0000000..88393db --- /dev/null +++ b/locales/zh_cn.json @@ -0,0 +1,115 @@ +{ + "menu": { + "title": "可用选项", + "exit": "退出程序", + "reset": "重置机器标识", + "register": "注册 Cursor", + "quit": "退出 Cursor", + "select_language": "选择语言", + "input_choice": "输入选择 ({choices})", + "invalid_choice": "无效选择,请重试", + "program_terminated": "程序被用户终止", + "error_occurred": "发生错误: {error}", + "press_enter": "按回车键退出" + }, + "languages": { + "en": "English", + "zh_cn": "简体中文", + "zh_tw": "繁體中文" + }, + "quit_cursor": { + "start": "开始退出 Cursor", + "no_process": "未发现运行中的 Cursor 进程", + "terminating": "正在终止进程 {pid}", + "waiting": "等待进程退出", + "success": "所有 Cursor 进程已正常关闭", + "timeout": "以下进程未能在规定时间内关闭: {pids}", + "error": "关闭 Cursor 进程时发生错误: {error}" + }, + "register": { + "title": "Cursor 注册工具", + "start": "开始注册流程", + "mailbox": "成功进入邮箱", + "register_start": "开始注册流程", + "filling_form": "填写注册信息", + "basic_info": "基本信息提交完成", + "handle_turnstile": "处理 Turnstile 验证", + "no_turnstile": "未检测到 Turnstile 验证", + "turnstile_passed": "验证通过", + "verification_start": "开始获取验证码", + "verification_timeout": "获取验证码超时", + "verification_not_found": "未找到验证码", + "try_get_code": "第 {attempt} 次尝试获取验证码 | 剩余时间: {time}秒", + "get_account": "获取账户信息", + "get_token": "获取 Cursor Session Token", + "token_success": "Token 获取成功", + "token_attempt": "第 {attempt} 次尝试未获取到 Token,{time}秒后重试", + "token_max_attempts": "已达到最大尝试次数({max}),获取 Token 失败", + "token_failed": "获取 Token 失败: {error}", + "account_error": "获取账户信息失败: {error}", + "press_enter": "按回车键退出", + "browser_start": "正在启动浏览器", + "open_mailbox": "正在打开邮箱页面", + "email_error": "获取邮箱地址失败", + "setup_error": "邮箱设置出错: {error}", + "start_getting_verification_code": "开始获取验证码,将在60秒内尝试...", + "get_verification_code_timeout": "获取验证码超时", + "get_verification_code_success": "成功获取验证码", + "try_get_verification_code": "第 {attempt} 次尝试未获取到验证码,剩余时间: {remaining_time}秒", + "verification_code_filled": "验证码填写完成", + "login_success_and_jump_to_settings_page": "成功登录并跳转到设置页面", + "detect_login_page": "检测到登录页面,开始登录...", + "cursor_registration_completed": "注册完成!", + "set_password": "设置密码", + "basic_info_submitted": "基本信息提交完成", + "cursor_auth_info_updated": "Cursor 认证信息更新成功", + "cursor_auth_info_update_failed": "Cursor 认证信息更新失败", + "reset_machine_id": "重置机器ID", + "account_info_saved": "账户信息已保存", + "save_account_info_failed": "保存账户信息失败", + "get_email_address": "获取邮箱地址", + "register_process_error": "注册流程错误: {error}" + }, + "auth": { + "title": "Cursor 认证管理器", + "checking_auth": "检查认证文件", + "auth_not_found": "未找到认证文件", + "auth_file_error": "认证文件错误: {error}", + "reading_auth": "读取认证文件", + "updating_auth": "更新认证信息", + "auth_updated": "认证信息更新成功", + "auth_update_failed": "认证信息更新失败: {error}", + "auth_file_created": "认证文件已创建", + "auth_file_create_failed": "认证文件创建失败: {error}", + "press_enter": "按回车键退出" + }, + "control": { + "generate_email": "生成新邮箱", + "select_domain": "选择随机域名", + "copy_email": "复制邮箱地址", + "enter_mailbox": "进入邮箱", + "refresh_mailbox": "刷新邮箱", + "check_verification": "检查验证码", + "verification_found": "找到验证码", + "verification_not_found": "未找到验证码", + "browser_error": "浏览器控制错误: {error}", + "navigation_error": "导航错误: {error}", + "email_copy_error": "邮箱复制错误: {error}", + "mailbox_error": "邮箱错误: {error}", + "token_saved_to_file": "Token已保存到 cursor_tokens.txt", + "navigate_to": "导航到 {url}", + "generate_email_success": "生成邮箱成功", + "select_email_domain": "选择邮箱域名", + "select_email_domain_success": "选择邮箱域名成功", + "get_email_name": "获取邮箱名称", + "get_email_name_success": "获取邮箱名称成功", + "get_email_address": "获取邮箱地址", + "get_email_address_success": "获取邮箱地址成功", + "enter_mailbox_success": "进入邮箱成功", + "found_verification_code": "找到验证码", + "get_cursor_session_token": "获取Cursor Session Token", + "get_cursor_session_token_success": "获取Cursor Session Token成功", + "get_cursor_session_token_failed": "获取Cursor Session Token失败", + "save_token_failed": "保存Token失败" + } +} \ No newline at end of file diff --git a/locales/zh_tw.json b/locales/zh_tw.json new file mode 100644 index 0000000..851e9f2 --- /dev/null +++ b/locales/zh_tw.json @@ -0,0 +1,115 @@ +{ + "menu": { + "title": "可用選項", + "exit": "退出程序", + "reset": "重置機器標識", + "register": "註冊 Cursor", + "quit": "退出 Cursor", + "select_language": "選擇語言", + "input_choice": "輸入選擇 ({choices})", + "invalid_choice": "無效選擇,請重試", + "program_terminated": "程序被用戶終止", + "error_occurred": "發生錯誤: {error}", + "press_enter": "按回車鍵退出" + }, + "languages": { + "en": "English", + "zh_cn": "简体中文", + "zh_tw": "繁體中文" + }, + "quit_cursor": { + "start": "開始退出 Cursor", + "no_process": "未發現運行中的 Cursor 進程", + "terminating": "正在終止進程 {pid}", + "waiting": "等待進程退出", + "success": "所有 Cursor 進程已正常關閉", + "timeout": "以下進程未能在規定時間內關閉: {pids}", + "error": "關閉 Cursor 進程時發生錯誤: {error}" + }, + "register": { + "title": "Cursor 註冊工具", + "start": "開始註冊流程", + "mailbox": "成功進入郵箱", + "register_start": "開始註冊流程", + "filling_form": "填寫註冊信息", + "basic_info": "基本信息提交完成", + "handle_turnstile": "處理 Turnstile 驗證", + "no_turnstile": "未檢測到 Turnstile 驗證", + "turnstile_passed": "驗證通過", + "verification_start": "開始獲取驗證碼", + "verification_timeout": "獲取驗證碼超時", + "verification_not_found": "未找到驗證碼", + "try_get_code": "第 {attempt} 次嘗試獲取驗證碼 | 剩餘時間: {time}秒", + "get_account": "獲取賬戶信息", + "get_token": "獲取 Cursor Session Token", + "token_success": "Token 獲取成功", + "token_attempt": "第 {attempt} 次嘗試未獲取到 Token,{time}秒後重試", + "token_max_attempts": "已達到最大嘗試次數({max}),獲取 Token 失敗", + "token_failed": "獲取 Token 失敗: {error}", + "account_error": "獲取賬戶信息失敗: {error}", + "press_enter": "按回車鍵退出", + "browser_start": "正在啟動瀏覽器", + "open_mailbox": "正在打開郵箱頁面", + "email_error": "獲取郵箱地址失敗", + "setup_error": "郵箱設置出錯: {error}", + "start_getting_verification_code": "開始獲取驗證碼,將在60秒內嘗試...", + "get_verification_code_timeout": "獲取驗證碼超時", + "get_verification_code_success": "成功獲取驗證碼", + "try_get_verification_code": "第 {attempt} 次嘗試未獲取到驗證碼,剩餘時間: {remaining_time}秒", + "verification_code_filled": "驗證碼填寫完成", + "login_success_and_jump_to_settings_page": "成功登錄並跳轉到設置頁面", + "detect_login_page": "檢測到登錄頁面,開始登錄...", + "cursor_registration_completed": "註冊完成!", + "set_password": "設置密碼", + "basic_info_submitted": "基本信息提交完成", + "cursor_auth_info_updated": "Cursor 認證信息更新成功", + "cursor_auth_info_update_failed": "Cursor 認證信息更新失敗", + "reset_machine_id": "重置機器ID", + "account_info_saved": "賬戶信息已保存", + "save_account_info_failed": "保存賬戶信息失敗", + "get_email_address": "獲取郵箱地址", + "register_process_error": "註冊流程錯誤: {error}" + }, + "auth": { + "title": "Cursor 認證管理器", + "checking_auth": "檢查認證文件", + "auth_not_found": "未找到認證文件", + "auth_file_error": "認證文件錯誤: {error}", + "reading_auth": "讀取認證文件", + "updating_auth": "更新認證信息", + "auth_updated": "認證信息更新成功", + "auth_update_failed": "認證信息更新失敗: {error}", + "auth_file_created": "認證文件已創建", + "auth_file_create_failed": "認證文件創建失敗: {error}", + "press_enter": "按回車鍵退出" + }, + "control": { + "generate_email": "生成新郵箱", + "select_domain": "選擇隨機域名", + "copy_email": "複製郵箱地址", + "enter_mailbox": "進入郵箱", + "refresh_mailbox": "刷新郵箱", + "check_verification": "檢查驗證碼", + "verification_found": "找到驗證碼", + "verification_not_found": "未找到驗證碼", + "browser_error": "瀏覽器控制錯誤: {error}", + "navigation_error": "導航錯誤: {error}", + "email_copy_error": "郵箱複製錯誤: {error}", + "mailbox_error": "郵箱錯誤: {error}", + "token_saved_to_file": "Token已保存到 cursor_tokens.txt", + "navigate_to": "導航到 {url}", + "generate_email_success": "生成郵箱成功", + "select_email_domain": "選擇郵箱域名", + "select_email_domain_success": "選擇郵箱域名成功", + "get_email_name": "獲取郵箱名稱", + "get_email_name_success": "獲取郵箱名稱成功", + "get_email_address": "獲取郵箱地址", + "get_email_address_success": "獲取郵箱地址成功", + "enter_mailbox_success": "進入郵箱成功", + "found_verification_code": "找到驗證碼", + "get_cursor_session_token": "獲取Cursor Session Token", + "get_cursor_session_token_success": "獲取Cursor Session Token成功", + "get_cursor_session_token_failed": "獲取Cursor Session Token失敗", + "save_token_failed": "保存Token失敗" + } +} \ No newline at end of file diff --git a/logo.py b/logo.py index 72d3cb8..a8c61e6 100644 --- a/logo.py +++ b/logo.py @@ -1,4 +1,11 @@ from colorama import Fore, Style, init +from dotenv import load_dotenv +import os + +# 加載環境變量獲取版本號 +load_dotenv() +version = os.getenv('VERSION', '1.0.0') + # 初始化 colorama init() @@ -11,9 +18,11 @@ CURSOR_LOGO = f""" ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ ██║ ██║ ██║╚██████╔╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ {Fore.YELLOW} - Pro Version Activator + Pro Version Activator v{version} {Fore.GREEN} - Author: Pin Studios | yeongpin + Author: Pin Studios | yeongpin +{Fore.RED} + Press 4 to change language | 按下 4 键切换语言 {Style.RESET_ALL} """ diff --git a/main.py b/main.py index f8742e4..38742a6 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,8 @@ # main.py # This script allows the user to choose which script to run. +import os +import sys +import json from logo import print_logo from colorama import Fore, Style, init @@ -16,58 +19,119 @@ EMOJI = { "RESET": "🔄", "MENU": "📋", "ARROW": "➜", + "LANG": "🌐" } +class Translator: + def __init__(self): + self.current_language = 'zh_tw' # 默认语言 + self.translations = {} + self.load_translations() + + def load_translations(self): + """加载所有可用的翻译""" + locales_dir = os.path.join(os.path.dirname(__file__), 'locales') + if hasattr(sys, '_MEIPASS'): + locales_dir = os.path.join(sys._MEIPASS, 'locales') + + for file in os.listdir(locales_dir): + if file.endswith('.json'): + lang_code = file[:-5] # 移除 .json + with open(os.path.join(locales_dir, file), 'r', encoding='utf-8') as f: + self.translations[lang_code] = json.load(f) + + def get(self, key, **kwargs): + """获取翻译文本""" + keys = key.split('.') + value = self.translations.get(self.current_language, {}) + for k in keys: + value = value.get(k, key) + return value.format(**kwargs) if kwargs else value + + def set_language(self, lang_code): + """设置当前语言""" + if lang_code in self.translations: + self.current_language = lang_code + return True + return False + +# 创建翻译器实例 +translator = Translator() + def print_menu(): """打印菜单选项""" - print(f"\n{Fore.CYAN}{EMOJI['MENU']} Available Options | 可用选项:{Style.RESET_ALL}") + print(f"\n{Fore.CYAN}{EMOJI['MENU']} {translator.get('menu.title')}:{Style.RESET_ALL}") print(f"{Fore.YELLOW}{'─' * 40}{Style.RESET_ALL}") - print(f"{Fore.GREEN}0{Style.RESET_ALL}. {EMOJI['ERROR']} Exit Program | 退出程序") - print(f"{Fore.GREEN}1{Style.RESET_ALL}. {EMOJI['RESET']} Reset Machine Manual | 重置机器标识") - print(f"{Fore.GREEN}2{Style.RESET_ALL}. {EMOJI['SUCCESS']} Register Cursor | 注册 Cursor") - print(f"{Fore.GREEN}3{Style.RESET_ALL}. {EMOJI['ERROR']} Quit Cursor | 退出 Cursor") - # 在这里添加更多选项 + 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.YELLOW}{'─' * 40}{Style.RESET_ALL}") +def select_language(): + """语言选择菜单""" + print(f"\n{Fore.CYAN}{EMOJI['LANG']} {translator.get('menu.select_language')}:{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{'─' * 40}{Style.RESET_ALL}") + + languages = translator.get('languages') + for i, (code, name) in enumerate(languages.items()): + print(f"{Fore.GREEN}{i}{Style.RESET_ALL}. {name}") + + try: + choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices='0-' + str(len(languages)-1))}: {Style.RESET_ALL}") + if choice.isdigit() and 0 <= int(choice) < len(languages): + lang_code = list(languages.keys())[int(choice)] + translator.set_language(lang_code) + return True + except (ValueError, IndexError): + pass + + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}") + return False + def main(): print_logo() print_menu() while True: try: - choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}Enter your choice (0-3) | 输入选择 (0-3): {Style.RESET_ALL}") + choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices='0-4')}: {Style.RESET_ALL}") if choice == "0": - print(f"\n{Fore.YELLOW}{EMOJI['INFO']} Exiting program... | 正在退出程序...{Style.RESET_ALL}") + print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.exit')}...{Style.RESET_ALL}") print(f"{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}") - return # 直接返回,不等待按键 + return elif choice == "1": import reset_machine_manual - reset_machine_manual.run() + reset_machine_manual.run(translator) break elif choice == "2": import cursor_register - cursor_register.main() + cursor_register.main(translator) break elif choice == "3": import quit_cursor - quit_cursor.quit_cursor() + quit_cursor.quit_cursor(translator) break + elif choice == "4": + if select_language(): + print_menu() + continue else: - print(f"{Fore.RED}{EMOJI['ERROR']} Invalid choice. Please try again | 无效选择,请重试{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}") print_menu() except KeyboardInterrupt: - print(f"\n{Fore.YELLOW}{EMOJI['INFO']} Program terminated by user | 程序被用户终止{Style.RESET_ALL}") + print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.program_terminated')}{Style.RESET_ALL}") print(f"{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}") - return # 直接返回,不等待按键 + return except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} An error occurred | 发生错误: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.error_occurred', error=str(e))}{Style.RESET_ALL}") break - # 只有在执行完其他选项后才显示按键退出提示 print(f"\n{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}") - input(f"{EMOJI['INFO']} Press Enter to Exit | 按回车键退出...{Style.RESET_ALL}") + input(f"{EMOJI['INFO']} {translator.get('menu.press_enter')}...{Style.RESET_ALL}") if __name__ == "__main__": main() \ No newline at end of file diff --git a/quit_cursor.py b/quit_cursor.py index f7f5421..40b54f5 100644 --- a/quit_cursor.py +++ b/quit_cursor.py @@ -1,30 +1,30 @@ import psutil import time from colorama import Fore, Style, init +import sys +import os # 初始化colorama init() -# 定义emoji和颜色常量 +# 定义emoji常量 EMOJI = { - "FILE": "📄", - "BACKUP": "💾", + "PROCESS": "⚙️", "SUCCESS": "✅", "ERROR": "❌", "INFO": "ℹ️", - "RESET": "🔄", - "PROCESS": "⚙️", "WAIT": "⏳" } class CursorQuitter: - def __init__(self, timeout=5): + def __init__(self, timeout=5, translator=None): self.timeout = timeout + self.translator = translator # 使用传入的翻译器 def quit_cursor(self): """温和地关闭 Cursor 进程""" try: - print(f"{Fore.CYAN}{EMOJI['PROCESS']} Start Quitting Cursor | 开始退出 Cursor...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['PROCESS']} {self.translator.get('quit_cursor.start')}...{Style.RESET_ALL}") cursor_processes = [] # 收集所有 Cursor 进程 @@ -36,20 +36,20 @@ class CursorQuitter: continue if not cursor_processes: - print(f"{Fore.GREEN}{EMOJI['INFO']} No Running Cursor Process | 未发现运行中的 Cursor 进程{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['INFO']} {self.translator.get('quit_cursor.no_process')}{Style.RESET_ALL}") return True # 温和地请求进程终止 for proc in cursor_processes: try: if proc.is_running(): - print(f"{Fore.YELLOW}{EMOJI['PROCESS']} Terminating Process | 正在终止进程 {proc.pid}...{Style.RESET_ALL}") - proc.terminate() # 发送终止信号 + print(f"{Fore.YELLOW}{EMOJI['PROCESS']} {self.translator.get('quit_cursor.terminating', pid=proc.pid)}...{Style.RESET_ALL}") + proc.terminate() except (psutil.NoSuchProcess, psutil.AccessDenied): continue # 等待进程自然终止 - print(f"{Fore.CYAN}{EMOJI['WAIT']} Waiting for Process to Exit | 等待进程退出...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('quit_cursor.waiting')}...{Style.RESET_ALL}") start_time = time.time() while time.time() - start_time < self.timeout: still_running = [] @@ -61,28 +61,29 @@ class CursorQuitter: continue if not still_running: - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} All Cursor Processes Closed | 所有 Cursor 进程已正常关闭{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('quit_cursor.success')}{Style.RESET_ALL}") return True - # 等待一小段时间再检查 time.sleep(0.5) # 如果超时后仍有进程在运行 if still_running: process_list = ", ".join([str(p.pid) for p in still_running]) - print(f"{Fore.RED}{EMOJI['ERROR']} Process Timeout | 以下进程未能在规定时间内关闭: {process_list}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('quit_cursor.timeout', pids=process_list)}{Style.RESET_ALL}") return False return True except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} Error Occurred | 关闭 Cursor 进程时发生错误: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('quit_cursor.error', error=str(e))}{Style.RESET_ALL}") return False -def quit_cursor(timeout=5): +def quit_cursor(translator=None, timeout=5): """便捷函数,用于直接调用退出功能""" - quitter = CursorQuitter(timeout) + quitter = CursorQuitter(timeout, translator) return quitter.quit_cursor() if __name__ == "__main__": - quit_cursor() \ No newline at end of file + # 如果直接运行,使用默认翻译器 + from main import translator as main_translator + quit_cursor(main_translator) \ No newline at end of file diff --git a/reset_machine_manual.py b/reset_machine_manual.py index 3c765b2..5474327 100644 --- a/reset_machine_manual.py +++ b/reset_machine_manual.py @@ -10,7 +10,7 @@ from colorama import Fore, Style, init # 初始化colorama init() -# 定义emoji和颜色常量 +# 定义emoji常量 EMOJI = { "FILE": "📄", "BACKUP": "💾", @@ -21,13 +21,14 @@ EMOJI = { } class MachineIDResetter: - def __init__(self): + def __init__(self, translator=None): + self.translator = translator # 判断操作系统 if sys.platform == "win32": # Windows appdata = os.getenv("APPDATA") if appdata is None: - raise EnvironmentError("APPDATA Environment Variable Not Set | APPDATA 环境变量未设置") + raise EnvironmentError("APPDATA Environment Variable Not Set") self.db_path = os.path.join( appdata, "Cursor", "User", "globalStorage", "storage.json" ) @@ -41,7 +42,7 @@ class MachineIDResetter: self.sqlite_path = os.path.abspath(os.path.expanduser( "~/Library/Application Support/Cursor/User/globalStorage/state.vscdb" )) - elif sys.platform == "linux": # Linux 和其他类Unix系统 + elif sys.platform == "linux": # Linux self.db_path = os.path.abspath(os.path.expanduser( "~/.config/Cursor/User/globalStorage/storage.json" )) @@ -49,7 +50,7 @@ class MachineIDResetter: "~/.config/Cursor/User/globalStorage/state.vscdb" )) else: - raise NotImplementedError(f"Not Supported Os| 不支持的操作系统: {sys.platform}") + raise NotImplementedError(f"Not Supported OS: {sys.platform}") def generate_new_ids(self): """生成新的机器ID""" @@ -76,13 +77,11 @@ class MachineIDResetter: def update_sqlite_db(self, new_ids): """更新 SQLite 数据库中的机器ID""" try: - print(f"{Fore.CYAN}{EMOJI['INFO']} Updating SQLite Database | 正在更新 SQLite 数据库...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.updating_sqlite')}...{Style.RESET_ALL}") - # 创建数据库连接 conn = sqlite3.connect(self.sqlite_path) cursor = conn.cursor() - # 确保表存在 cursor.execute(""" CREATE TABLE IF NOT EXISTS ItemTable ( key TEXT PRIMARY KEY, @@ -90,108 +89,89 @@ class MachineIDResetter: ) """) - # 准备更新数据 updates = [ (key, value) for key, value in new_ids.items() ] - # 使用参数化查询来避免 SQL 注入和处理长文本 for key, value in updates: cursor.execute(""" INSERT OR REPLACE INTO ItemTable (key, value) VALUES (?, ?) """, (key, value)) - print(f"{EMOJI['INFO']} {Fore.CYAN}Updating Key-Value Pair | 更新键值对: {key}{Style.RESET_ALL}") + print(f"{EMOJI['INFO']} {Fore.CYAN}{self.translator.get('reset.updating_pair')}: {key}{Style.RESET_ALL}") - # 提交更改并关闭连接 conn.commit() conn.close() - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} SQLite Database Updated Successfully | 数据库更新成功!{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.sqlite_success')}{Style.RESET_ALL}") return True except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} SQLite Database Update Failed | 数据库更新失败: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.sqlite_error', error=str(e))}{Style.RESET_ALL}") return False def reset_machine_ids(self): """重置机器ID并备份原文件""" try: - print(f"{Fore.CYAN}{EMOJI['INFO']} Checking Config File | 正在检查配置文件...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.checking')}...{Style.RESET_ALL}") - # 检查JSON文件是否存在 if not os.path.exists(self.db_path): - print( - f"{Fore.RED}{EMOJI['ERROR']} Config File Not Found | 配置文件不存在: {self.db_path}{Style.RESET_ALL}" - ) + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.not_found')}: {self.db_path}{Style.RESET_ALL}") return False - # 检查文件权限 if not os.access(self.db_path, os.R_OK | os.W_OK): - print( - f"{Fore.RED}{EMOJI['ERROR']} Cannot Read or Write Config File, Please Check File Permissions | 无法读写配置文件,请检查文件权限!{Style.RESET_ALL}" - ) + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.no_permission')}{Style.RESET_ALL}") return False - # 读取现有配置 - print(f"{Fore.CYAN}{EMOJI['FILE']} Reading Current Config | 读取当前配置...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('reset.reading')}...{Style.RESET_ALL}") with open(self.db_path, "r", encoding="utf-8") as f: config = json.load(f) - # 只在没有备份文件时创建备份 backup_path = self.db_path + ".bak" if not os.path.exists(backup_path): - print( - f"{Fore.YELLOW}{EMOJI['BACKUP']} Creating Config Backup | 创建配置备份: {backup_path}{Style.RESET_ALL}" - ) + print(f"{Fore.YELLOW}{EMOJI['BACKUP']} {self.translator.get('reset.creating_backup')}: {backup_path}{Style.RESET_ALL}") shutil.copy2(self.db_path, backup_path) else: - print( - f"{Fore.YELLOW}{EMOJI['INFO']} Backup File Already Exists, Skipping Backup Step | 已存在备份文件,跳过备份步骤{Style.RESET_ALL}" - ) + print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.backup_exists')}{Style.RESET_ALL}") - # 生成新的ID - print(f"{Fore.CYAN}{EMOJI['RESET']} Generating New Machine ID | 生成新的机器标识...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['RESET']} {self.translator.get('reset.generating')}...{Style.RESET_ALL}") new_ids = self.generate_new_ids() - # 更新配置 config.update(new_ids) - # 保存新配置到 JSON - print(f"{Fore.CYAN}{EMOJI['FILE']} Saving New Config to JSON | 保存新配置到 JSON...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('reset.saving_json')}...{Style.RESET_ALL}") with open(self.db_path, "w", encoding="utf-8") as f: json.dump(config, f, indent=4) - # 更新 SQLite 数据库 self.update_sqlite_db(new_ids) - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Machine ID Reset Successfully | 机器标识重置成功!{Style.RESET_ALL}") - print(f"\n{Fore.CYAN}New Machine ID | 新的机器标识:{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.success')}{Style.RESET_ALL}") + print(f"\n{Fore.CYAN}{self.translator.get('reset.new_id')}:{Style.RESET_ALL}") for key, value in new_ids.items(): print(f"{EMOJI['INFO']} {key}: {Fore.GREEN}{value}{Style.RESET_ALL}") return True except PermissionError as e: - print(f"{Fore.RED}{EMOJI['ERROR']} Permission Error | 权限错误: {str(e)}{Style.RESET_ALL}") - print( - f"{Fore.YELLOW}{EMOJI['INFO']} Please Try Running This Program as Administrator | 请尝试以管理员身份运行此程序{Style.RESET_ALL}" - ) + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.permission_error', error=str(e))}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.run_as_admin')}{Style.RESET_ALL}") return False except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} Reset Process Error | 重置过程出错: {str(e)}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.process_error', error=str(e))}{Style.RESET_ALL}") return False -def run(): +def run(translator=None): """Main function to be called from main.py""" print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}") - print(f"{Fore.CYAN}{EMOJI['RESET']} Cursor Machine ID Reset Tool | Cursor 机器标识重置工具{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['RESET']} {translator.get('reset.title')}{Style.RESET_ALL}") print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}") - resetter = MachineIDResetter() + resetter = MachineIDResetter(translator) resetter.reset_machine_ids() print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}") - input(f"{EMOJI['INFO']} Press Enter to Exit | 按回车键退出...") + input(f"{EMOJI['INFO']} {translator.get('reset.press_enter')}...") if __name__ == "__main__": - run() \ No newline at end of file + # 如果直接运行,使用默认翻译器 + from main import translator as main_translator + run(main_translator) \ No newline at end of file