mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-04-28 09:05:28 +00:00
feat: Added Google OAuth Acc Deletion Tool
This commit is contained in:
parent
d8799cdf2e
commit
b3e7c101d3
@ -1,5 +1,10 @@
|
|||||||
# Change Log
|
# 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
|
## v1.8.05
|
||||||
1. Fix: Linux Path Not Found | 修復linuxpath問題
|
1. Fix: Linux Path Not Found | 修復linuxpath問題
|
||||||
2. Add: support for detecting both 150/150 and 50/50 usage limits | 添加偵測50 或者150的使用量
|
2. Add: support for detecting both 150/150 and 50/50 usage limits | 添加偵測50 或者150的使用量
|
||||||
|
@ -54,6 +54,8 @@ Always clean your browser's cache and cookies. If possible, use a VPN to create
|
|||||||
|
|
||||||
* Reset Cursor's configuration<br>重置 Cursor 的配置<br>
|
* Reset Cursor's configuration<br>重置 Cursor 的配置<br>
|
||||||
|
|
||||||
|
* Delete Cursor Google Account<br>删除 Cursor Google 账号<br>
|
||||||
|
|
||||||
* Multi-language support (English, 简体中文, 繁體中文, Vietnamese)<br>多語言支持(英文、简体中文、繁體中文、越南語)<br>
|
* Multi-language support (English, 简体中文, 繁體中文, Vietnamese)<br>多語言支持(英文、简体中文、繁體中文、越南語)<br>
|
||||||
|
|
||||||
## 💻 System Support | 系統支持
|
## 💻 System Support | 系統支持
|
||||||
|
386
delete_cursor_google.py
Normal file
386
delete_cursor_google.py
Normal file
@ -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()
|
@ -25,7 +25,8 @@
|
|||||||
"coming_soon": "Coming Soon",
|
"coming_soon": "Coming Soon",
|
||||||
"fixed_soon": "Fixed Soon",
|
"fixed_soon": "Fixed Soon",
|
||||||
"contribute": "Contribute to the Project",
|
"contribute": "Contribute to the Project",
|
||||||
"config": "Show Config"
|
"config": "Show Config",
|
||||||
|
"delete_google_account": "Delete Cursor Google Account"
|
||||||
},
|
},
|
||||||
"languages": {
|
"languages": {
|
||||||
"en": "English",
|
"en": "English",
|
||||||
@ -433,7 +434,24 @@
|
|||||||
"cursor_reset_completed": "Cursor AI Editor has been fully reset and trial detection bypassed!",
|
"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_failed": "Cursor AI Editor reset failed: {error}",
|
||||||
"cursor_reset_cancelled": "Cursor AI Editor reset cancelled. Exiting without making any changes.",
|
"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": {
|
"github_register": {
|
||||||
"title": "GitHub + Cursor AI Registration Automation",
|
"title": "GitHub + Cursor AI Registration Automation",
|
||||||
@ -594,5 +612,48 @@
|
|||||||
"profile_selected": "Selected profile: {profile}",
|
"profile_selected": "Selected profile: {profile}",
|
||||||
"invalid_selection": "Invalid selection. Please try again",
|
"invalid_selection": "Invalid selection. Please try again",
|
||||||
"warning_chrome_close": "Warning: This will close all running Chrome processes"
|
"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}"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,7 +25,8 @@
|
|||||||
"coming_soon": "即将推出",
|
"coming_soon": "即将推出",
|
||||||
"fixed_soon": "即将修复",
|
"fixed_soon": "即将修复",
|
||||||
"contribute": "贡献项目",
|
"contribute": "贡献项目",
|
||||||
"config": "显示配置"
|
"config": "显示配置",
|
||||||
|
"delete_google_account": "删除 Cursor Google 账号"
|
||||||
},
|
},
|
||||||
"languages": {
|
"languages": {
|
||||||
"en": "英语",
|
"en": "英语",
|
||||||
@ -589,5 +590,48 @@
|
|||||||
"profile_selected": "已选择配置文件:{profile}",
|
"profile_selected": "已选择配置文件:{profile}",
|
||||||
"invalid_selection": "选择无效。请重试",
|
"invalid_selection": "选择无效。请重试",
|
||||||
"warning_chrome_close": "警告:这将关闭所有正在运行的Chrome进程"
|
"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": "已找到危险区域部分"
|
||||||
}
|
}
|
||||||
}
|
}
|
9
main.py
9
main.py
@ -285,7 +285,8 @@ def print_menu():
|
|||||||
10: f"{Fore.GREEN}10{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.totally_reset')}",
|
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')}",
|
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')}",
|
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
|
# Automatically calculate the number of menu items in the left and right columns
|
||||||
@ -557,7 +558,7 @@ def main():
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
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}")
|
choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices=f'0-{choice_num}')}: {Style.RESET_ALL}")
|
||||||
|
|
||||||
if choice == "0":
|
if choice == "0":
|
||||||
@ -621,6 +622,10 @@ def main():
|
|||||||
if user_data_dir:
|
if user_data_dir:
|
||||||
oauth._select_profile(user_data_dir)
|
oauth._select_profile(user_data_dir)
|
||||||
print_menu()
|
print_menu()
|
||||||
|
elif choice == "14":
|
||||||
|
import delete_cursor_google
|
||||||
|
delete_cursor_google.main(translator)
|
||||||
|
print_menu()
|
||||||
else:
|
else:
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}")
|
||||||
print_menu()
|
print_menu()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user