diff --git a/.env b/.env index 1199388..48cb412 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ version=1.8.05 -VERSION=1.8.05 +VERSION=1.8.06 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f9bfcd..4bc0cd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## v1.8.06 +1. Add: Google Account Deletion Feature | 添加 Google 账号删除功能 +2. Update: Menu with new account deletion option | 更新菜单添加账号删除选项 +3. Add: Multilanguage support for account deletion | 添加账号删除功能的多语言支持 + ## v1.8.05 1. Fix: Linux Path Not Found | 修復linuxpath問題 2. Add: support for detecting both 150/150 and 50/50 usage limits | 添加偵測50 或者150的使用量 diff --git a/README.md b/README.md index 1f62b46..3060c57 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,8 @@ Always clean your browser's cache and cookies. If possible, use a VPN to create * Reset Cursor's configuration
重置 Cursor 的配置
+* Delete Cursor Google Account
删除 Cursor Google 账号
+ * Multi-language support (English, 简体中文, 繁體中文, Vietnamese)
多語言支持(英文、简体中文、繁體中文、越南語)
## 💻 System Support | 系統支持 diff --git a/delete_cursor_google.py b/delete_cursor_google.py new file mode 100644 index 0000000..39b3457 --- /dev/null +++ b/delete_cursor_google.py @@ -0,0 +1,386 @@ +from oauth_auth import OAuthHandler +import time +from colorama import Fore, Style, init +import sys + +# Initialize colorama +init() + +# Define emoji constants +EMOJI = { + 'START': '🚀', + 'DELETE': '🗑️', + 'SUCCESS': '✅', + 'ERROR': '❌', + 'WAIT': '⏳', + 'INFO': 'ℹ️', + 'WARNING': '⚠️' +} + +class CursorGoogleAccountDeleter(OAuthHandler): + def __init__(self, translator=None): + super().__init__(translator, auth_type='google') + + def delete_google_account(self): + """Delete Cursor account using Google OAuth""" + try: + # Setup browser and select profile + if not self.setup_browser(): + return False + + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('account_delete.starting_process') if self.translator else 'Starting account deletion process...'}{Style.RESET_ALL}") + + # Navigate to Cursor auth page - using the same URL as in registration + self.browser.get("https://authenticator.cursor.sh/sign-up") + time.sleep(2) + + # Click Google auth button using same selectors as in registration + selectors = [ + "//a[contains(@href,'GoogleOAuth')]", + "//a[contains(@class,'auth-method-button') and contains(@href,'GoogleOAuth')]", + "(//a[contains(@class,'auth-method-button')])[1]" # First auth button as fallback + ] + + auth_btn = None + for selector in selectors: + try: + auth_btn = self.browser.ele(f"xpath:{selector}", timeout=2) + if auth_btn: + break + except: + continue + + if not auth_btn: + raise Exception(self.translator.get('account_delete.google_button_not_found') if self.translator else "Google login button not found") + + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('account_delete.logging_in') if self.translator else 'Logging in with Google...'}{Style.RESET_ALL}") + auth_btn.click() + + # Wait for authentication to complete using a more robust method + print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('account_delete.waiting_for_auth', fallback='Waiting for Google authentication...')}{Style.RESET_ALL}") + + # Dynamic wait for authentication + max_wait_time = 120 # Increase maximum wait time to 120 seconds + start_time = time.time() + check_interval = 3 # Check every 3 seconds + google_account_alert_shown = False # Track if we've shown the alert already + + while time.time() - start_time < max_wait_time: + current_url = self.browser.url + + # If we're already on the settings or dashboard page, we're successful + if "/dashboard" in current_url or "/settings" in current_url or "cursor.com" in current_url: + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('account_delete.login_successful') if self.translator else 'Login successful'}{Style.RESET_ALL}") + break + + # If we're on Google accounts page or accounts.google.com, wait for user selection + if "accounts.google.com" in current_url: + # Only show the alert once to avoid spamming + if not google_account_alert_shown: + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('account_delete.select_google_account', fallback='Please select your Google account...')}{Style.RESET_ALL}") + # Alert to indicate user action needed + try: + self.browser.run_js(""" + alert('Please select your Google account to continue with Cursor authentication'); + """) + google_account_alert_shown = True # Mark that we've shown the alert + except: + pass # Alert is optional + + # Sleep before checking again + time.sleep(check_interval) + else: + # If the loop completed without breaking, it means we hit the timeout + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('account_delete.auth_timeout', fallback='Authentication timeout, continuing anyway...')}{Style.RESET_ALL}") + + # Check current URL to determine next steps + current_url = self.browser.url + + # If we're already on the settings page, no need to navigate + if "/settings" in current_url and "cursor.com" in current_url: + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('account_delete.already_on_settings', fallback='Already on settings page')}{Style.RESET_ALL}") + # If we're on the dashboard or any Cursor page but not settings, navigate to settings + elif "cursor.com" in current_url or "authenticator.cursor.sh" in current_url: + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('account_delete.navigating_to_settings', fallback='Navigating to settings page...')}{Style.RESET_ALL}") + self.browser.get("https://www.cursor.com/settings") + # If we're still on Google auth or somewhere else, try directly going to settings + else: + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('account_delete.login_redirect_failed', fallback='Login redirection failed, trying direct navigation...')}{Style.RESET_ALL}") + self.browser.get("https://www.cursor.com/settings") + + # Wait for the settings page to load + time.sleep(3) # Reduced from 5 seconds + + # First look for the email element to confirm we're logged in + try: + email_element = self.browser.ele("css:div[class='flex w-full flex-col gap-2'] div:nth-child(2) p:nth-child(2)") + if email_element: + email = email_element.text + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('account_delete.found_email', email=email, fallback=f'Found email: {email}')}{Style.RESET_ALL}") + except Exception as e: + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('account_delete.email_not_found', error=str(e), fallback=f'Email not found: {str(e)}')}{Style.RESET_ALL}") + + # Click on "Advanced" tab or dropdown - keep only the successful approach + advanced_found = False + + # Direct JavaScript querySelector approach that worked according to logs + try: + advanced_element_js = self.browser.run_js(""" + // Try to find the Advanced dropdown using querySelector with the exact classes + let advancedElement = document.querySelector('div.mb-0.flex.cursor-pointer.items-center.text-xs:not([style*="display: none"])'); + + // If not found, try a more general approach + if (!advancedElement) { + const allDivs = document.querySelectorAll('div'); + for (const div of allDivs) { + if (div.textContent.includes('Advanced') && + div.className.includes('mb-0') && + div.className.includes('flex') && + div.className.includes('cursor-pointer')) { + advancedElement = div; + break; + } + } + } + + // Click the element if found + if (advancedElement) { + advancedElement.click(); + return true; + } + + return false; + """) + + if advanced_element_js: + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Found and clicked Advanced using direct JavaScript selector{Style.RESET_ALL}") + advanced_found = True + time.sleep(1) # Reduced from 2 seconds + except Exception as e: + print(f"{Fore.YELLOW}{EMOJI['WARNING']} JavaScript querySelector approach failed: {str(e)}{Style.RESET_ALL}") + + if not advanced_found: + # Fallback to direct URL navigation which is faster and more reliable + try: + self.browser.get("https://www.cursor.com/settings?tab=advanced") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('account_delete.direct_advanced_navigation', fallback='Trying direct navigation to advanced tab')}{Style.RESET_ALL}") + advanced_found = True + except: + raise Exception(self.translator.get('account_delete.advanced_tab_not_found') if self.translator else "Advanced option not found after multiple attempts") + + # Wait for dropdown/tab content to load + time.sleep(2) # Reduced from 4 seconds + + # Find and click the "Delete Account" button + delete_button_found = False + + # Simplified approach for delete button based on what worked + delete_button_selectors = [ + 'xpath://button[contains(., "Delete Account")]', + 'xpath://button[text()="Delete Account"]', + 'xpath://div[contains(text(), "Delete Account")]', + 'xpath://button[contains(text(), "Delete") and contains(text(), "Account")]' + ] + + for selector in delete_button_selectors: + try: + delete_button = self.browser.ele(selector, timeout=2) + if delete_button: + delete_button.click() + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('account_delete.delete_button_clicked') if self.translator else 'Clicked on Delete Account button'}{Style.RESET_ALL}") + delete_button_found = True + break + except: + continue + + if not delete_button_found: + raise Exception(self.translator.get('account_delete.delete_button_not_found') if self.translator else "Delete Account button not found") + + # Wait for confirmation dialog to appear + time.sleep(2) + + # Check if we need to input "Delete" at all - some modals might not require it + input_required = True + try: + # Try detecting if the DELETE button is already enabled + delete_button_enabled = self.browser.run_js(""" + const buttons = Array.from(document.querySelectorAll('button')); + const deleteButtons = buttons.filter(btn => + btn.textContent.trim() === 'DELETE' || + btn.textContent.trim() === 'Delete' + ); + + if (deleteButtons.length > 0) { + return !deleteButtons.some(btn => btn.disabled); + } + return false; + """) + + if delete_button_enabled: + print(f"{Fore.CYAN}{EMOJI['INFO']} DELETE button appears to be enabled already. Input may not be required.{Style.RESET_ALL}") + input_required = False + except: + pass + + # Type "Delete" in the confirmation input - only if required + delete_input_found = False + + if input_required: + # Try common selectors for the input field + delete_input_selectors = [ + 'xpath://input[@placeholder="Delete"]', + 'xpath://div[contains(@class, "modal")]//input', + 'xpath://input', + 'css:input' + ] + + for selector in delete_input_selectors: + try: + delete_input = self.browser.ele(selector, timeout=3) + if delete_input: + delete_input.clear() + delete_input.input("Delete") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Typed \"Delete\" in confirmation box{Style.RESET_ALL}") + delete_input_found = True + time.sleep(2) + break + except: + # Try direct JavaScript input as fallback + try: + self.browser.run_js(f""" + arguments[0].value = "Delete"; + const event = new Event('input', {{ bubbles: true }}); + arguments[0].dispatchEvent(event); + const changeEvent = new Event('change', {{ bubbles: true }}); + arguments[0].dispatchEvent(changeEvent); + """, delete_input) + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Typed \"Delete\" using JavaScript{Style.RESET_ALL}") + delete_input_found = True + time.sleep(2) + break + except: + continue + + if not delete_input_found: + print(f"{Fore.YELLOW}{EMOJI['WARNING']} Delete confirmation input not found, continuing anyway{Style.RESET_ALL}") + time.sleep(2) + + # Wait before clicking the final DELETE button + time.sleep(2) + + # Click on the final DELETE button + confirm_button_found = False + + # Use JavaScript approach for the DELETE button + try: + delete_button_js = self.browser.run_js(""" + // Try to find the DELETE button by exact text content + const buttons = Array.from(document.querySelectorAll('button')); + const deleteButton = buttons.find(btn => + btn.textContent.trim() === 'DELETE' || + btn.textContent.trim() === 'Delete' + ); + + if (deleteButton) { + console.log("Found DELETE button with JavaScript"); + deleteButton.click(); + return true; + } + + // If not found by text, try to find right-most button in the modal + const modalButtons = Array.from(document.querySelectorAll('.relative button, [role="dialog"] button, .modal button, [aria-modal="true"] button')); + + if (modalButtons.length > 1) { + modalButtons.sort((a, b) => { + const rectA = a.getBoundingClientRect(); + const rectB = b.getBoundingClientRect(); + return rectB.right - rectA.right; + }); + + console.log("Clicking right-most button in modal"); + modalButtons[0].click(); + return true; + } else if (modalButtons.length === 1) { + console.log("Clicking single button found in modal"); + modalButtons[0].click(); + return true; + } + + return false; + """) + + if delete_button_js: + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Clicked DELETE button{Style.RESET_ALL}") + confirm_button_found = True + except: + pass + + if not confirm_button_found: + # Fallback to simple selectors + delete_button_selectors = [ + 'xpath://button[text()="DELETE"]', + 'xpath://div[contains(@class, "modal")]//button[last()]' + ] + + for selector in delete_button_selectors: + try: + delete_button = self.browser.ele(selector, timeout=2) + if delete_button: + delete_button.click() + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Account deleted successfully!{Style.RESET_ALL}") + confirm_button_found = True + break + except: + continue + + if not confirm_button_found: + raise Exception(self.translator.get('account_delete.confirm_button_not_found') if self.translator else "Confirm button not found") + + # Wait a moment to see the confirmation + time.sleep(2) + + return True + + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('account_delete.error', error=str(e)) if self.translator else f'Error during account deletion: {str(e)}'}{Style.RESET_ALL}") + return False + finally: + # Clean up browser + if self.browser: + try: + self.browser.quit() + except: + pass + +def main(translator=None): + """Main function to handle Google account deletion""" + print(f"\n{Fore.CYAN}{EMOJI['START']} {translator.get('account_delete.title') if translator else 'Cursor Google Account Deletion Tool'}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{'─' * 50}{Style.RESET_ALL}") + + deleter = CursorGoogleAccountDeleter(translator) + + try: + # Ask for confirmation + print(f"{Fore.RED}{EMOJI['WARNING']} {translator.get('account_delete.warning') if translator else 'WARNING: This will permanently delete your Cursor account. This action cannot be undone.'}{Style.RESET_ALL}") + confirm = input(f"{Fore.RED}Are you sure you want to proceed? (y/N): {Style.RESET_ALL}").lower() + + if confirm != 'y': + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('account_delete.cancelled') if translator else 'Account deletion cancelled.'}{Style.RESET_ALL}") + return + + success = deleter.delete_google_account() + + if success: + print(f"\n{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('account_delete.success') if translator else 'Your Cursor account has been successfully deleted!'}{Style.RESET_ALL}") + else: + print(f"\n{Fore.RED}{EMOJI['ERROR']} {translator.get('account_delete.failed') if translator else 'Account deletion process failed or was cancelled.'}{Style.RESET_ALL}") + + except KeyboardInterrupt: + print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('account_delete.interrupted') if translator else 'Account deletion process interrupted by user.'}{Style.RESET_ALL}") + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('account_delete.unexpected_error', error=str(e)) if translator else f'Unexpected error: {str(e)}'}{Style.RESET_ALL}") + finally: + print(f"{Fore.YELLOW}{'─' * 50}{Style.RESET_ALL}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index 6868432..05e29cc 100644 --- a/locales/en.json +++ b/locales/en.json @@ -25,7 +25,8 @@ "coming_soon": "Coming Soon", "fixed_soon": "Fixed Soon", "contribute": "Contribute to the Project", - "config": "Show Config" + "config": "Show Config", + "delete_google_account": "Delete Cursor Google Account" }, "languages": { "en": "English", @@ -433,7 +434,24 @@ "cursor_reset_completed": "Cursor AI Editor has been fully reset and trial detection bypassed!", "cursor_reset_failed": "Cursor AI Editor reset failed: {error}", "cursor_reset_cancelled": "Cursor AI Editor reset cancelled. Exiting without making any changes.", - "operation_cancelled": "Operation cancelled. Exiting without making any changes." + "operation_cancelled": "Operation cancelled. Exiting without making any changes.", + "navigating_to_settings": "Navigating to settings page...", + "already_on_settings": "Already on settings page", + "login_redirect_failed": "Login redirection failed, trying direct navigation...", + "advanced_tab_not_found": "Advanced tab not found after multiple attempts", + "advanced_tab_retry": "Advanced tab not found, attempt {attempt}/{max_attempts}", + "advanced_tab_error": "Error finding Advanced tab: {error}", + "advanced_tab_clicked": "Clicked on Advanced tab", + "direct_advanced_navigation": "Trying direct navigation to advanced tab", + "delete_button_not_found": "Delete Account button not found after multiple attempts", + "delete_button_retry": "Delete button not found, attempt {attempt}/{max_attempts}", + "delete_button_error": "Error finding Delete button: {error}", + "delete_button_clicked": "Clicked on Delete Account button", + "found_danger_zone": "Found Danger Zone section", + "delete_input_not_found": "Delete confirmation input not found after multiple attempts", + "delete_input_retry": "Delete input not found, attempt {attempt}/{max_attempts}", + "delete_input_error": "Error finding Delete input: {error}", + "delete_input_not_found_continuing": "Delete confirmation input not found, trying to continue anyway" }, "github_register": { "title": "GitHub + Cursor AI Registration Automation", @@ -594,5 +612,48 @@ "profile_selected": "Selected profile: {profile}", "invalid_selection": "Invalid selection. Please try again", "warning_chrome_close": "Warning: This will close all running Chrome processes" + }, + "account_delete": { + "title": "Cursor Google Account Deletion Tool", + "warning": "WARNING: This will permanently delete your Cursor account. This action cannot be undone.", + "cancelled": "Account deletion cancelled.", + "starting_process": "Starting account deletion process...", + "google_button_not_found": "Google login button not found", + "logging_in": "Logging in with Google...", + "waiting_for_auth": "Waiting for Google authentication...", + "login_successful": "Login successful", + "unexpected_page": "Unexpected page after login: {url}", + "trying_settings": "Trying to navigate to settings page...", + "select_google_account": "Please select your Google account...", + "auth_timeout": "Authentication timeout, continuing anyway...", + "navigating_to_settings": "Navigating to settings page...", + "already_on_settings": "Already on settings page", + "login_redirect_failed": "Login redirection failed, trying direct navigation...", + "advanced_tab_not_found": "Advanced tab not found after multiple attempts", + "advanced_tab_retry": "Advanced tab not found, attempt {attempt}/{max_attempts}", + "advanced_tab_error": "Error finding Advanced tab: {error}", + "advanced_tab_clicked": "Clicked on Advanced tab", + "direct_advanced_navigation": "Trying direct navigation to advanced tab", + "delete_button_not_found": "Delete Account button not found after multiple attempts", + "delete_button_retry": "Delete button not found, attempt {attempt}/{max_attempts}", + "delete_button_error": "Error finding Delete button: {error}", + "delete_button_clicked": "Clicked on Delete Account button", + "found_danger_zone": "Found Danger Zone section", + "delete_input_not_found": "Delete confirmation input not found after multiple attempts", + "delete_input_retry": "Delete input not found, attempt {attempt}/{max_attempts}", + "delete_input_error": "Error finding Delete input: {error}", + "delete_input_not_found_continuing": "Delete confirmation input not found, trying to continue anyway", + "typed_delete": "Typed \"Delete\" in confirmation box", + "confirm_button_not_found": "Confirm button not found after multiple attempts", + "confirm_button_retry": "Confirm button not found, attempt {attempt}/{max_attempts}", + "confirm_button_error": "Error finding Confirm button: {error}", + "account_deleted": "Account deleted successfully!", + "error": "Error during account deletion: {error}", + "success": "Your Cursor account has been successfully deleted!", + "failed": "Account deletion process failed or was cancelled.", + "interrupted": "Account deletion process interrupted by user.", + "unexpected_error": "Unexpected error: {error}", + "found_email": "Found email: {email}", + "email_not_found": "Email not found: {error}" } } \ No newline at end of file diff --git a/locales/zh_cn.json b/locales/zh_cn.json index f94ce50..321e807 100644 --- a/locales/zh_cn.json +++ b/locales/zh_cn.json @@ -25,7 +25,8 @@ "coming_soon": "即将推出", "fixed_soon": "即将修复", "contribute": "贡献项目", - "config": "显示配置" + "config": "显示配置", + "delete_google_account": "删除 Cursor Google 账号" }, "languages": { "en": "英语", @@ -589,5 +590,48 @@ "profile_selected": "已选择配置文件:{profile}", "invalid_selection": "选择无效。请重试", "warning_chrome_close": "警告:这将关闭所有正在运行的Chrome进程" + }, + "account_delete": { + "title": "Cursor Google 账号删除工具", + "warning": "警告:这将永久删除您的 Cursor 账号。此操作无法撤销。", + "cancelled": "账号删除已取消。", + "starting_process": "开始账号删除过程...", + "google_button_not_found": "未找到 Google 登录按钮", + "logging_in": "正在使用 Google 登录...", + "waiting_for_auth": "等待 Google 验证...", + "login_successful": "登录成功", + "unexpected_page": "登录后页面异常:{url}", + "trying_settings": "尝试导航到设置页面...", + "select_google_account": "请选择您的 Google 账号...", + "auth_timeout": "认证超时,继续执行...", + "navigating_to_settings": "正在导航到设置页面...", + "already_on_settings": "已在设置页面", + "login_redirect_failed": "登录重定向失败,尝试直接导航...", + "advanced_tab_not_found": "多次尝试后未找到高级选项卡", + "advanced_tab_retry": "未找到高级选项卡,尝试 {attempt}/{max_attempts}", + "advanced_tab_error": "查找高级选项卡时出错:{error}", + "advanced_tab_clicked": "已点击高级选项卡", + "direct_advanced_navigation": "尝试直接导航到高级选项卡", + "delete_button_not_found": "多次尝试后未找到删除账号按钮", + "delete_button_retry": "未找到删除按钮,尝试 {attempt}/{max_attempts}", + "delete_button_error": "查找删除按钮时出错:{error}", + "delete_button_clicked": "已点击删除账号按钮", + "delete_input_not_found": "多次尝试后未找到删除确认输入框", + "delete_input_retry": "未找到删除输入框,尝试 {attempt}/{max_attempts}", + "delete_input_error": "查找删除输入框时出错:{error}", + "delete_input_not_found_continuing": "未找到删除确认输入框,尝试继续执行...", + "typed_delete": "已在确认框中输入\"Delete\"", + "confirm_button_not_found": "多次尝试后未找到确认按钮", + "confirm_button_retry": "未找到确认按钮,尝试 {attempt}/{max_attempts}", + "confirm_button_error": "查找确认按钮时出错:{error}", + "account_deleted": "账号删除成功!", + "error": "账号删除过程中出错:{error}", + "success": "您的 Cursor 账号已成功删除!", + "failed": "账号删除过程失败或已取消。", + "interrupted": "账号删除过程被用户中断。", + "unexpected_error": "意外错误:{error}", + "found_email": "找到邮箱:{email}", + "email_not_found": "未找到邮箱: {error}", + "found_danger_zone": "已找到危险区域部分" } } \ No newline at end of file diff --git a/main.py b/main.py index 7a2ad94..89d7c07 100644 --- a/main.py +++ b/main.py @@ -285,7 +285,8 @@ def print_menu(): 10: f"{Fore.GREEN}10{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.totally_reset')}", 11: f"{Fore.GREEN}11{Style.RESET_ALL}. {EMOJI['CONTRIBUTE']} {translator.get('menu.contribute')}", 12: f"{Fore.GREEN}12{Style.RESET_ALL}. {EMOJI['SETTINGS']} {translator.get('menu.config')}", - 13: f"{Fore.GREEN}13{Style.RESET_ALL}. {EMOJI['SETTINGS']} {translator.get('menu.select_chrome_profile')}" + 13: f"{Fore.GREEN}13{Style.RESET_ALL}. {EMOJI['SETTINGS']} {translator.get('menu.select_chrome_profile')}", + 14: f"{Fore.GREEN}14{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.delete_google_account', fallback='Delete Cursor Google Account')}" } # Automatically calculate the number of menu items in the left and right columns @@ -557,7 +558,7 @@ def main(): while True: try: - choice_num = 13 + choice_num = 14 choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices=f'0-{choice_num}')}: {Style.RESET_ALL}") if choice == "0": @@ -621,6 +622,10 @@ def main(): if user_data_dir: oauth._select_profile(user_data_dir) print_menu() + elif choice == "14": + import delete_cursor_google + delete_cursor_google.main(translator) + print_menu() else: print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}") print_menu()