mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-08-02 20:47:35 +08:00
new locale language file
This commit is contained in:
parent
f139fa189d
commit
731db36121
@ -26,6 +26,7 @@ a = Analysis(
|
|||||||
('turnstilePatch', 'turnstilePatch'),
|
('turnstilePatch', 'turnstilePatch'),
|
||||||
('recaptchaPatch', 'recaptchaPatch'),
|
('recaptchaPatch', 'recaptchaPatch'),
|
||||||
('uBlock0.chromium', 'uBlock0.chromium'),
|
('uBlock0.chromium', 'uBlock0.chromium'),
|
||||||
|
('locales', 'locales'),
|
||||||
('cursor_auth.py', '.'),
|
('cursor_auth.py', '.'),
|
||||||
('reset_machine_manual.py', '.'),
|
('reset_machine_manual.py', '.'),
|
||||||
('cursor_register.py', '.'),
|
('cursor_register.py', '.'),
|
||||||
|
146
control.py
146
control.py
@ -1,11 +1,25 @@
|
|||||||
import time
|
import time
|
||||||
from colorama import Fore, Style
|
|
||||||
import random
|
import random
|
||||||
import os
|
import os
|
||||||
|
from colorama import Fore, Style, init
|
||||||
|
|
||||||
|
# 初始化colorama
|
||||||
|
init()
|
||||||
|
|
||||||
|
# 定义emoji常量
|
||||||
|
EMOJI = {
|
||||||
|
'MAIL': '📧',
|
||||||
|
'REFRESH': '🔄',
|
||||||
|
'SUCCESS': '✅',
|
||||||
|
'ERROR': '❌',
|
||||||
|
'INFO': 'ℹ️',
|
||||||
|
'CODE': '📱'
|
||||||
|
}
|
||||||
|
|
||||||
class BrowserControl:
|
class BrowserControl:
|
||||||
def __init__(self, browser):
|
def __init__(self, browser, translator=None):
|
||||||
self.browser = browser
|
self.browser = browser
|
||||||
|
self.translator = translator # 保存translator
|
||||||
self.sign_up_url = "https://authenticator.cursor.sh/sign-up"
|
self.sign_up_url = "https://authenticator.cursor.sh/sign-up"
|
||||||
self.current_tab = None # 当前标签页
|
self.current_tab = None # 当前标签页
|
||||||
self.signup_tab = None # 注册标签页
|
self.signup_tab = None # 注册标签页
|
||||||
@ -25,20 +39,20 @@ class BrowserControl:
|
|||||||
# 保存新标签页
|
# 保存新标签页
|
||||||
self.signup_tab = new_browser
|
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
|
return new_browser
|
||||||
except Exception as e:
|
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
|
return None
|
||||||
|
|
||||||
def switch_to_tab(self, browser):
|
def switch_to_tab(self, browser):
|
||||||
"""切换到指定浏览器窗口"""
|
"""切换到指定浏览器窗口"""
|
||||||
try:
|
try:
|
||||||
self.browser = browser
|
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
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{Fore.RED}Switch Tab Failed | 切换窗口时发生错误: {str(e)}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.switch_tab_failed', error=str(e))}{Style.RESET_ALL}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_current_tab(self):
|
def get_current_tab(self):
|
||||||
@ -48,24 +62,24 @@ class BrowserControl:
|
|||||||
def generate_new_email(self):
|
def generate_new_email(self):
|
||||||
"""点击新的按钮生成新邮箱"""
|
"""点击新的按钮生成新邮箱"""
|
||||||
try:
|
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")]')
|
new_button = self.browser.ele('xpath://button[contains(@class, "egenbut")]')
|
||||||
if new_button:
|
if new_button:
|
||||||
new_button.click()
|
new_button.click()
|
||||||
time.sleep(1) # 等待生成
|
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
|
return True
|
||||||
else:
|
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
|
return False
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
|
|
||||||
def select_email_domain(self, domain_index=None):
|
def select_email_domain(self, domain_index=None):
|
||||||
"""选择邮箱域名,如果不指定index则随机选择"""
|
"""选择邮箱域名,如果不指定index则随机选择"""
|
||||||
try:
|
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"]')
|
select_element = self.browser.ele('xpath://select[@id="seldom"]')
|
||||||
if select_element:
|
if select_element:
|
||||||
@ -88,21 +102,21 @@ class BrowserControl:
|
|||||||
if domain_index < len(all_options):
|
if domain_index < len(all_options):
|
||||||
# 获取选中选项的文本
|
# 获取选中选项的文本
|
||||||
selected_domain = all_options[domain_index].text
|
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()
|
all_options[domain_index].click()
|
||||||
time.sleep(1)
|
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
|
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
|
return False
|
||||||
else:
|
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
|
return False
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
|
|
||||||
def wait_for_page_load(self, seconds=2):
|
def wait_for_page_load(self, seconds=2):
|
||||||
@ -112,18 +126,18 @@ class BrowserControl:
|
|||||||
def navigate_to(self, url):
|
def navigate_to(self, url):
|
||||||
"""导航到指定URL"""
|
"""导航到指定URL"""
|
||||||
try:
|
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.browser.get(url)
|
||||||
self.wait_for_page_load()
|
self.wait_for_page_load()
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{Fore.RED}Visit {url} Failed | 访问 {url} 时发生错误: {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
|
return False
|
||||||
|
|
||||||
def copy_and_get_email(self):
|
def copy_and_get_email(self):
|
||||||
"""获取邮箱地址"""
|
"""获取邮箱地址"""
|
||||||
try:
|
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)
|
time.sleep(1)
|
||||||
@ -133,12 +147,12 @@ class BrowserControl:
|
|||||||
email_div = self.browser.ele('xpath://div[@class="segen"]//div[contains(@style, "color: #e5e5e5")]')
|
email_div = self.browser.ele('xpath://div[@class="segen"]//div[contains(@style, "color: #e5e5e5")]')
|
||||||
if email_div:
|
if email_div:
|
||||||
email_name = email_div.text.split()[0]
|
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:
|
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
|
return None
|
||||||
except Exception as e:
|
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
|
return None
|
||||||
|
|
||||||
# 直接使用上一步选择的域名
|
# 直接使用上一步选择的域名
|
||||||
@ -152,65 +166,47 @@ class BrowserControl:
|
|||||||
|
|
||||||
# 组合完整邮箱地址
|
# 组合完整邮箱地址
|
||||||
full_email = f"{email_name}{domain}"
|
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
|
return full_email
|
||||||
|
|
||||||
except Exception as e:
|
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
|
return None
|
||||||
|
|
||||||
def view_mailbox(self):
|
def view_mailbox(self):
|
||||||
"""点击查看邮箱按钮"""
|
"""点击查看邮箱按钮"""
|
||||||
try:
|
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, "查看邮箱")]')
|
view_button = self.browser.ele('xpath://button[contains(@class, "egenbut") and contains(.//span, "查看邮箱")]')
|
||||||
if view_button:
|
if view_button:
|
||||||
view_button.click()
|
view_button.click()
|
||||||
time.sleep(2) # 等待页面加载
|
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
|
return True
|
||||||
else:
|
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
|
return False
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
|
|
||||||
def refresh_mailbox(self):
|
def refresh_mailbox(self):
|
||||||
"""刷新邮箱获取最新信息"""
|
"""刷新邮箱获取最新信息"""
|
||||||
try:
|
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"]')
|
refresh_button = self.browser.ele('xpath://button[@id="refresh"]')
|
||||||
if refresh_button:
|
if refresh_button:
|
||||||
refresh_button.click()
|
refresh_button.click()
|
||||||
time.sleep(2) # 等待刷新完成
|
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
|
return True
|
||||||
else:
|
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
|
return False
|
||||||
except Exception as e:
|
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
|
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):
|
def get_verification_code(self):
|
||||||
"""从邮件中获取验证码"""
|
"""从邮件中获取验证码"""
|
||||||
@ -233,24 +229,24 @@ class BrowserControl:
|
|||||||
if code_div:
|
if code_div:
|
||||||
verification_code = code_div.text.strip()
|
verification_code = code_div.text.strip()
|
||||||
if verification_code.isdigit() and len(verification_code) == 6:
|
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
|
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
|
return None
|
||||||
|
|
||||||
except Exception as e:
|
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
|
return None
|
||||||
|
|
||||||
def fill_verification_code(self, code):
|
def fill_verification_code(self, code):
|
||||||
"""填写验证码"""
|
"""填写验证码"""
|
||||||
try:
|
try:
|
||||||
if not code or len(code) != 6:
|
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
|
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
|
email_tab = self.browser
|
||||||
@ -264,10 +260,10 @@ class BrowserControl:
|
|||||||
self.browser.actions.input(digit)
|
self.browser.actions.input(digit)
|
||||||
time.sleep(random.uniform(0.1, 0.3))
|
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)
|
time.sleep(5)
|
||||||
|
|
||||||
# 先访问登录页面确保登录状态
|
# 先访问登录页面确保登录状态
|
||||||
@ -278,7 +274,7 @@ class BrowserControl:
|
|||||||
# 获取cookies(第一次尝试)
|
# 获取cookies(第一次尝试)
|
||||||
token = self.get_cursor_session_token()
|
token = self.get_cursor_session_token()
|
||||||
if not 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)
|
time.sleep(3)
|
||||||
token = self.get_cursor_session_token()
|
token = self.get_cursor_session_token()
|
||||||
|
|
||||||
@ -287,7 +283,7 @@ class BrowserControl:
|
|||||||
|
|
||||||
# 获取到token后再访问设置页面
|
# 获取到token后再访问设置页面
|
||||||
settings_url = "https://www.cursor.com/settings"
|
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)
|
self.browser.get(settings_url)
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
@ -302,9 +298,9 @@ class BrowserControl:
|
|||||||
if usage_ele:
|
if usage_ele:
|
||||||
usage_info = usage_ele.text
|
usage_info = usage_ele.text
|
||||||
total_usage = usage_info.split("/")[-1].strip()
|
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:
|
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)
|
self.switch_to_tab(email_tab)
|
||||||
@ -312,7 +308,7 @@ class BrowserControl:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
|
|
||||||
def check_and_click_turnstile(self):
|
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"]')
|
verify_checkbox = self.browser.ele('xpath://label[contains(@class, "cb-lb")]//input[@type="checkbox"]')
|
||||||
if verify_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()
|
verify_checkbox.click()
|
||||||
time.sleep(2) # 等待验证完成
|
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 True
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
|
|
||||||
def get_cursor_session_token(self, max_attempts=3, retry_interval=2):
|
def get_cursor_session_token(self, max_attempts=3, retry_interval=2):
|
||||||
"""获取Cursor会话token"""
|
"""获取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
|
attempts = 0
|
||||||
|
|
||||||
while attempts < max_attempts:
|
while attempts < max_attempts:
|
||||||
@ -348,21 +344,21 @@ class BrowserControl:
|
|||||||
for cookie in all_cookies:
|
for cookie in all_cookies:
|
||||||
if cookie.get("name") == "WorkosCursorSessionToken":
|
if cookie.get("name") == "WorkosCursorSessionToken":
|
||||||
token = cookie["value"].split("%3A%3A")[1]
|
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
|
return token
|
||||||
|
|
||||||
attempts += 1
|
attempts += 1
|
||||||
if attempts < max_attempts:
|
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)
|
time.sleep(retry_interval)
|
||||||
else:
|
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:
|
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
|
attempts += 1
|
||||||
if attempts < max_attempts:
|
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)
|
time.sleep(retry_interval)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
@ -373,6 +369,6 @@ class BrowserControl:
|
|||||||
with open('cursor_tokens.txt', 'a', encoding='utf-8') as f:
|
with open('cursor_tokens.txt', 'a', encoding='utf-8') as f:
|
||||||
f.write(f"Token: {token}\n")
|
f.write(f"Token: {token}\n")
|
||||||
f.write("-" * 50 + "\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:
|
except Exception as e:
|
||||||
print(f"{Fore.RED}Save Token Failed | 保存Token时发生错误: {str(e)}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.save_token_failed', error=str(e))}{Style.RESET_ALL}")
|
@ -14,11 +14,13 @@ EMOJI = {
|
|||||||
'ERROR': '❌',
|
'ERROR': '❌',
|
||||||
'WARN': '⚠️',
|
'WARN': '⚠️',
|
||||||
'INFO': 'ℹ️',
|
'INFO': 'ℹ️',
|
||||||
'KEY': '🔑'
|
'FILE': '📄',
|
||||||
|
'KEY': '🔐'
|
||||||
}
|
}
|
||||||
|
|
||||||
class CursorAuth:
|
class CursorAuth:
|
||||||
def __init__(self):
|
def __init__(self, translator=None):
|
||||||
|
self.translator = translator
|
||||||
# 判断操作系统
|
# 判断操作系统
|
||||||
if os.name == "nt": # Windows
|
if os.name == "nt": # Windows
|
||||||
self.db_path = os.path.join(
|
self.db_path = os.path.join(
|
||||||
@ -54,7 +56,7 @@ class CursorAuth:
|
|||||||
|
|
||||||
# 重新连接数据库
|
# 重新连接数据库
|
||||||
conn = sqlite3.connect(self.db_path)
|
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()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
# 增加超时和其他优化设置
|
# 增加超时和其他优化设置
|
||||||
@ -91,7 +93,7 @@ class CursorAuth:
|
|||||||
print(f"{EMOJI['INFO']} {Fore.CYAN}Updating {key.split('/')[-1]}...{Style.RESET_ALL}")
|
print(f"{EMOJI['INFO']} {Fore.CYAN}Updating {key.split('/')[-1]}...{Style.RESET_ALL}")
|
||||||
|
|
||||||
cursor.execute("COMMIT")
|
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
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -99,14 +101,14 @@ class CursorAuth:
|
|||||||
raise e
|
raise e
|
||||||
|
|
||||||
except sqlite3.Error as 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
|
return False
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
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}")
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ os.environ["PYINSTALLER_VERBOSE"] = "0"
|
|||||||
# 初始化colorama
|
# 初始化colorama
|
||||||
init()
|
init()
|
||||||
|
|
||||||
# 定义emoji和颜色常量
|
# 定义emoji常量
|
||||||
EMOJI = {
|
EMOJI = {
|
||||||
'START': '🚀',
|
'START': '🚀',
|
||||||
'FORM': '📝',
|
'FORM': '📝',
|
||||||
@ -24,13 +24,15 @@ EMOJI = {
|
|||||||
'ERROR': '❌',
|
'ERROR': '❌',
|
||||||
'WAIT': '⏳',
|
'WAIT': '⏳',
|
||||||
'SUCCESS': '✅',
|
'SUCCESS': '✅',
|
||||||
'MAIL': '<EFBFBD><EFBFBD>',
|
'MAIL': '📧',
|
||||||
'KEY': '🔐',
|
'KEY': '🔐',
|
||||||
'UPDATE': '🔄'
|
'UPDATE': '🔄',
|
||||||
|
'INFO': 'ℹ️'
|
||||||
}
|
}
|
||||||
|
|
||||||
class CursorRegistration:
|
class CursorRegistration:
|
||||||
def __init__(self):
|
def __init__(self, translator=None):
|
||||||
|
self.translator = translator
|
||||||
# 设置为显示模式
|
# 设置为显示模式
|
||||||
os.environ['BROWSER_HEADLESS'] = 'False'
|
os.environ['BROWSER_HEADLESS'] = 'False'
|
||||||
self.browser_manager = BrowserManager()
|
self.browser_manager = BrowserManager()
|
||||||
@ -60,11 +62,11 @@ class CursorRegistration:
|
|||||||
return first_letter + rest_letters
|
return first_letter + rest_letters
|
||||||
|
|
||||||
def setup_email(self):
|
def setup_email(self):
|
||||||
"""Setup Temporary Email"""
|
"""设置邮箱"""
|
||||||
try:
|
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.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)
|
self.controller.navigate_to(self.mail_url)
|
||||||
@ -80,7 +82,7 @@ class CursorRegistration:
|
|||||||
# 获取邮箱地址
|
# 获取邮箱地址
|
||||||
self.email_address = self.controller.copy_and_get_email()
|
self.email_address = self.controller.copy_and_get_email()
|
||||||
if self.email_address:
|
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():
|
if self.controller.view_mailbox():
|
||||||
@ -89,14 +91,14 @@ class CursorRegistration:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
|
|
||||||
def register_cursor(self):
|
def register_cursor(self):
|
||||||
"""注册 Cursor 账号"""
|
"""注册 Cursor"""
|
||||||
signup_browser_manager = None
|
signup_browser_manager = None
|
||||||
try:
|
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
|
from browser import BrowserManager
|
||||||
@ -109,7 +111,7 @@ class CursorRegistration:
|
|||||||
|
|
||||||
# 填写注册表单
|
# 填写注册表单
|
||||||
if self.signup_tab.ele("@name=first_name"):
|
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)
|
self.signup_tab.ele("@name=first_name").input(self.first_name)
|
||||||
time.sleep(random.uniform(1, 2))
|
time.sleep(random.uniform(1, 2))
|
||||||
@ -121,14 +123,14 @@ class CursorRegistration:
|
|||||||
time.sleep(random.uniform(1, 2))
|
time.sleep(random.uniform(1, 2))
|
||||||
|
|
||||||
self.signup_tab.ele("@type=submit").click()
|
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 验证
|
# 处理 Turnstile 验证
|
||||||
self._handle_turnstile()
|
self._handle_turnstile()
|
||||||
|
|
||||||
# 设置密码
|
# 设置密码
|
||||||
if self.signup_tab.ele("@name=password"):
|
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)
|
self.signup_tab.ele("@name=password").input(self.password)
|
||||||
time.sleep(random.uniform(1, 2))
|
time.sleep(random.uniform(1, 2))
|
||||||
self.signup_tab.ele("@type=submit").click()
|
self.signup_tab.ele("@type=submit").click()
|
||||||
@ -147,21 +149,21 @@ class CursorRegistration:
|
|||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
timeout = 60 # 60秒超时
|
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):
|
for attempt in range(max_attempts):
|
||||||
# 检查是否超时
|
# 检查是否超时
|
||||||
if time.time() - start_time > timeout:
|
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
|
break
|
||||||
|
|
||||||
verification_code = self.controller.get_verification_code()
|
verification_code = self.controller.get_verification_code()
|
||||||
if 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
|
break
|
||||||
|
|
||||||
remaining_time = int(timeout - (time.time() - start_time))
|
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()
|
self.browser.refresh()
|
||||||
@ -173,7 +175,7 @@ class CursorRegistration:
|
|||||||
self.signup_tab.ele(f"@data-index={i}").input(digit)
|
self.signup_tab.ele(f"@data-index={i}").input(digit)
|
||||||
time.sleep(random.uniform(0.1, 0.3))
|
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)
|
time.sleep(3)
|
||||||
|
|
||||||
self._handle_turnstile()
|
self._handle_turnstile()
|
||||||
@ -181,7 +183,7 @@ class CursorRegistration:
|
|||||||
# 检查当前URL
|
# 检查当前URL
|
||||||
current_url = self.signup_tab.url
|
current_url = self.signup_tab.url
|
||||||
if "authenticator.cursor.sh" in current_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')
|
email_input = self.signup_tab.ele('@name=email')
|
||||||
@ -218,7 +220,7 @@ class CursorRegistration:
|
|||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while time.time() - start_time < max_wait:
|
while time.time() - start_time < max_wait:
|
||||||
if "cursor.com/settings" in self.signup_tab.url:
|
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
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
@ -231,11 +233,11 @@ class CursorRegistration:
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
else:
|
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
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
finally:
|
finally:
|
||||||
# 确保在任何情况下都关闭注册窗口
|
# 确保在任何情况下都关闭注册窗口
|
||||||
@ -244,7 +246,7 @@ class CursorRegistration:
|
|||||||
|
|
||||||
def _handle_turnstile(self):
|
def _handle_turnstile(self):
|
||||||
"""处理 Turnstile 验证"""
|
"""处理 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 # 增加等待时间
|
max_wait_time = 10 # 增加等待时间
|
||||||
@ -254,11 +256,10 @@ class CursorRegistration:
|
|||||||
try:
|
try:
|
||||||
# 检查是否超时
|
# 检查是否超时
|
||||||
if time.time() - start_time > max_wait_time:
|
if time.time() - start_time > max_wait_time:
|
||||||
print(f"{Fore.YELLOW}{EMOJI['WAIT']} Not Detect Turnstile | 未检测到 Turnstile 验证,继续下一步...{Style.RESET_ALL}")
|
print(f"{Fore.YELLOW}{EMOJI['WAIT']} {self.translator.get('register.no_turnstile')}...{Style.RESET_ALL}")
|
||||||
time.sleep(2) # 添加短暂延迟
|
time.sleep(2)
|
||||||
break
|
break
|
||||||
|
|
||||||
# 检查是否存在验证框
|
|
||||||
try:
|
try:
|
||||||
challengeCheck = (
|
challengeCheck = (
|
||||||
self.signup_tab.ele("@id=cf-turnstile", timeout=1)
|
self.signup_tab.ele("@id=cf-turnstile", timeout=1)
|
||||||
@ -270,43 +271,38 @@ class CursorRegistration:
|
|||||||
|
|
||||||
if challengeCheck:
|
if challengeCheck:
|
||||||
challengeCheck.click()
|
challengeCheck.click()
|
||||||
time.sleep(3) # 增加点击后的等待时间
|
time.sleep(3)
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Turnstile Passed | 验证通过{Style.RESET_ALL}")
|
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.turnstile_passed')}{Style.RESET_ALL}")
|
||||||
time.sleep(2) # 确保验证完全完成
|
time.sleep(2)
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 检查是否已经通过验证(检查下一步的元素是否存在)
|
|
||||||
try:
|
try:
|
||||||
if (self.signup_tab.ele("@name=password", timeout=0.5) or
|
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("@name=email", timeout=0.5) or
|
||||||
self.signup_tab.ele("@data-index=0", timeout=0.5)):
|
self.signup_tab.ele("@data-index=0", timeout=0.5)):
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Verification Passed | 验证已通过{Style.RESET_ALL}")
|
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.turnstile_passed')}{Style.RESET_ALL}")
|
||||||
time.sleep(2) # 添加短暂延迟
|
time.sleep(2)
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 等待短暂时间后继续检查
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} Turnstile Error | Turnstile 处理出错: {str(e)}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.error', error=str(e))}{Style.RESET_ALL}")
|
||||||
time.sleep(2) # 出错时等待更长时间
|
time.sleep(2)
|
||||||
break
|
break
|
||||||
|
|
||||||
# 最后再等待一下,确保页面加载完成
|
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
def _get_account_info(self):
|
def _get_account_info(self):
|
||||||
"""获取账户信息和 Token"""
|
"""获取账户信息和 Token"""
|
||||||
try:
|
try:
|
||||||
# 访问设置页面
|
|
||||||
self.signup_tab.get(self.settings_url)
|
self.signup_tab.get(self.settings_url)
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
# 获取账户额度信息
|
|
||||||
usage_selector = (
|
usage_selector = (
|
||||||
"css:div.col-span-2 > div > div > div > div > "
|
"css:div.col-span-2 > div > div > div > div > "
|
||||||
"div:nth-child(1) > div.flex.items-center.justify-between.gap-2 > "
|
"div:nth-child(1) > div.flex.items-center.justify-between.gap-2 > "
|
||||||
@ -317,8 +313,7 @@ class CursorRegistration:
|
|||||||
if usage_ele:
|
if usage_ele:
|
||||||
total_usage = usage_ele.text.split("/")[-1].strip()
|
total_usage = usage_ele.text.split("/")[-1].strip()
|
||||||
|
|
||||||
# 获取 Token
|
print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('register.get_token')}...{Style.RESET_ALL}")
|
||||||
print(f"{Fore.CYAN}{EMOJI['WAIT']} Get Cursor Session Token | 开始获取 Cursor Session Token...{Style.RESET_ALL}")
|
|
||||||
max_attempts = 30
|
max_attempts = 30
|
||||||
retry_interval = 2
|
retry_interval = 2
|
||||||
attempts = 0
|
attempts = 0
|
||||||
@ -329,46 +324,45 @@ class CursorRegistration:
|
|||||||
for cookie in cookies:
|
for cookie in cookies:
|
||||||
if cookie.get("name") == "WorkosCursorSessionToken":
|
if cookie.get("name") == "WorkosCursorSessionToken":
|
||||||
token = cookie["value"].split("%3A%3A")[1]
|
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)
|
self._save_account_info(token, total_usage)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
attempts += 1
|
attempts += 1
|
||||||
if attempts < max_attempts:
|
if attempts < max_attempts:
|
||||||
print(
|
print(f"{Fore.YELLOW}{EMOJI['WAIT']} {self.translator.get('register.token_attempt', attempt=attempts, time=retry_interval)}{Style.RESET_ALL}")
|
||||||
f"{Fore.YELLOW}{EMOJI['WAIT']} Try | 第 {attempts} times to get Token | 次尝试未获取到 Token,{retry_interval}秒后重试...{Style.RESET_ALL}"
|
|
||||||
)
|
|
||||||
time.sleep(retry_interval)
|
time.sleep(retry_interval)
|
||||||
else:
|
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:
|
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
|
attempts += 1
|
||||||
if attempts < max_attempts:
|
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)
|
time.sleep(retry_interval)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
|
|
||||||
def _save_account_info(self, token, total_usage):
|
def _save_account_info(self, token, total_usage):
|
||||||
"""保存账户信息到文件"""
|
"""保存账户信息到文件"""
|
||||||
try:
|
try:
|
||||||
# 先更新认证信息
|
# 先更新认证信息
|
||||||
print(f"{Fore.CYAN}{EMOJI['KEY']} 正在更新 Cursor 认证信息...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['KEY']} {self.translator.get('register.update_cursor_auth_info')}...{Style.RESET_ALL}")
|
||||||
if update_cursor_auth(email=self.email_address, access_token=token, refresh_token=token):
|
if self.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.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.cursor_auth_info_updated')}...{Style.RESET_ALL}")
|
||||||
else:
|
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
|
# 重置机器ID
|
||||||
print(f"{Fore.CYAN}{EMOJI['UPDATE']} Reset Machine ID | 正在重置机器ID...{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}{EMOJI['UPDATE']} {self.translator.get('register.reset_machine_id')}...{Style.RESET_ALL}")
|
||||||
MachineIDResetter().reset_machine_ids()
|
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:
|
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"Usage Limit: {total_usage}\n")
|
||||||
f.write(f"{'='*50}\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
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
@ -391,25 +385,30 @@ class CursorRegistration:
|
|||||||
try:
|
try:
|
||||||
if self.setup_email():
|
if self.setup_email():
|
||||||
if self.register_cursor():
|
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 True
|
||||||
return False
|
return False
|
||||||
finally:
|
finally:
|
||||||
if self.browser_manager:
|
if self.browser_manager:
|
||||||
self.browser_manager.quit()
|
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):
|
registration = CursorRegistration(translator)
|
||||||
"""
|
|
||||||
更新Cursor的认证信息的便捷函数
|
|
||||||
"""
|
|
||||||
auth_manager = CursorAuth()
|
|
||||||
return auth_manager.update_auth(email, access_token, refresh_token)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
registration = CursorRegistration()
|
|
||||||
registration.start()
|
registration.start()
|
||||||
|
|
||||||
|
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||||
|
input(f"{EMOJI['INFO']} {translator.get('register.press_enter')}...")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
from main import translator as main_translator
|
||||||
|
main(main_translator)
|
141
locales/en.json
Normal file
141
locales/en.json
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
}
|
115
locales/zh_cn.json
Normal file
115
locales/zh_cn.json
Normal file
@ -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失败"
|
||||||
|
}
|
||||||
|
}
|
115
locales/zh_tw.json
Normal file
115
locales/zh_tw.json
Normal file
@ -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失敗"
|
||||||
|
}
|
||||||
|
}
|
13
logo.py
13
logo.py
@ -1,4 +1,11 @@
|
|||||||
from colorama import Fore, Style, init
|
from colorama import Fore, Style, init
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
|
||||||
|
# 加載環境變量獲取版本號
|
||||||
|
load_dotenv()
|
||||||
|
version = os.getenv('VERSION', '1.0.0')
|
||||||
|
|
||||||
# 初始化 colorama
|
# 初始化 colorama
|
||||||
init()
|
init()
|
||||||
|
|
||||||
@ -11,9 +18,11 @@ CURSOR_LOGO = f"""
|
|||||||
╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ ██║ ██║ ██║╚██████╔╝
|
╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ ██║ ██║ ██║╚██████╔╝
|
||||||
╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝
|
╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝
|
||||||
{Fore.YELLOW}
|
{Fore.YELLOW}
|
||||||
Pro Version Activator
|
Pro Version Activator v{version}
|
||||||
{Fore.GREEN}
|
{Fore.GREEN}
|
||||||
Author: Pin Studios | yeongpin
|
Author: Pin Studios | yeongpin
|
||||||
|
{Fore.RED}
|
||||||
|
Press 4 to change language | 按下 4 键切换语言
|
||||||
{Style.RESET_ALL}
|
{Style.RESET_ALL}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
100
main.py
100
main.py
@ -1,5 +1,8 @@
|
|||||||
# main.py
|
# main.py
|
||||||
# This script allows the user to choose which script to run.
|
# This script allows the user to choose which script to run.
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
from logo import print_logo
|
from logo import print_logo
|
||||||
from colorama import Fore, Style, init
|
from colorama import Fore, Style, init
|
||||||
|
|
||||||
@ -16,58 +19,119 @@ EMOJI = {
|
|||||||
"RESET": "🔄",
|
"RESET": "🔄",
|
||||||
"MENU": "📋",
|
"MENU": "📋",
|
||||||
"ARROW": "➜",
|
"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():
|
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.YELLOW}{'─' * 40}{Style.RESET_ALL}")
|
||||||
print(f"{Fore.GREEN}0{Style.RESET_ALL}. {EMOJI['ERROR']} Exit Program | 退出程序")
|
print(f"{Fore.GREEN}0{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.exit')}")
|
||||||
print(f"{Fore.GREEN}1{Style.RESET_ALL}. {EMOJI['RESET']} Reset Machine Manual | 重置机器标识")
|
print(f"{Fore.GREEN}1{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.reset')}")
|
||||||
print(f"{Fore.GREEN}2{Style.RESET_ALL}. {EMOJI['SUCCESS']} Register Cursor | 注册 Cursor")
|
print(f"{Fore.GREEN}2{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register')}")
|
||||||
print(f"{Fore.GREEN}3{Style.RESET_ALL}. {EMOJI['ERROR']} Quit Cursor | 退出 Cursor")
|
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}")
|
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():
|
def main():
|
||||||
print_logo()
|
print_logo()
|
||||||
print_menu()
|
print_menu()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
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":
|
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}")
|
print(f"{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}")
|
||||||
return # 直接返回,不等待按键
|
return
|
||||||
elif choice == "1":
|
elif choice == "1":
|
||||||
import reset_machine_manual
|
import reset_machine_manual
|
||||||
reset_machine_manual.run()
|
reset_machine_manual.run(translator)
|
||||||
break
|
break
|
||||||
elif choice == "2":
|
elif choice == "2":
|
||||||
import cursor_register
|
import cursor_register
|
||||||
cursor_register.main()
|
cursor_register.main(translator)
|
||||||
break
|
break
|
||||||
elif choice == "3":
|
elif choice == "3":
|
||||||
import quit_cursor
|
import quit_cursor
|
||||||
quit_cursor.quit_cursor()
|
quit_cursor.quit_cursor(translator)
|
||||||
break
|
break
|
||||||
|
elif choice == "4":
|
||||||
|
if select_language():
|
||||||
|
print_menu()
|
||||||
|
continue
|
||||||
else:
|
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()
|
print_menu()
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
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}")
|
print(f"{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}")
|
||||||
return # 直接返回,不等待按键
|
return
|
||||||
except Exception as e:
|
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
|
break
|
||||||
|
|
||||||
# 只有在执行完其他选项后才显示按键退出提示
|
|
||||||
print(f"\n{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}")
|
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__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
@ -1,30 +1,30 @@
|
|||||||
import psutil
|
import psutil
|
||||||
import time
|
import time
|
||||||
from colorama import Fore, Style, init
|
from colorama import Fore, Style, init
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
# 初始化colorama
|
# 初始化colorama
|
||||||
init()
|
init()
|
||||||
|
|
||||||
# 定义emoji和颜色常量
|
# 定义emoji常量
|
||||||
EMOJI = {
|
EMOJI = {
|
||||||
"FILE": "📄",
|
"PROCESS": "⚙️",
|
||||||
"BACKUP": "💾",
|
|
||||||
"SUCCESS": "✅",
|
"SUCCESS": "✅",
|
||||||
"ERROR": "❌",
|
"ERROR": "❌",
|
||||||
"INFO": "ℹ️",
|
"INFO": "ℹ️",
|
||||||
"RESET": "🔄",
|
|
||||||
"PROCESS": "⚙️",
|
|
||||||
"WAIT": "⏳"
|
"WAIT": "⏳"
|
||||||
}
|
}
|
||||||
|
|
||||||
class CursorQuitter:
|
class CursorQuitter:
|
||||||
def __init__(self, timeout=5):
|
def __init__(self, timeout=5, translator=None):
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
|
self.translator = translator # 使用传入的翻译器
|
||||||
|
|
||||||
def quit_cursor(self):
|
def quit_cursor(self):
|
||||||
"""温和地关闭 Cursor 进程"""
|
"""温和地关闭 Cursor 进程"""
|
||||||
try:
|
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_processes = []
|
||||||
|
|
||||||
# 收集所有 Cursor 进程
|
# 收集所有 Cursor 进程
|
||||||
@ -36,20 +36,20 @@ class CursorQuitter:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if not cursor_processes:
|
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
|
return True
|
||||||
|
|
||||||
# 温和地请求进程终止
|
# 温和地请求进程终止
|
||||||
for proc in cursor_processes:
|
for proc in cursor_processes:
|
||||||
try:
|
try:
|
||||||
if proc.is_running():
|
if proc.is_running():
|
||||||
print(f"{Fore.YELLOW}{EMOJI['PROCESS']} Terminating Process | 正在终止进程 {proc.pid}...{Style.RESET_ALL}")
|
print(f"{Fore.YELLOW}{EMOJI['PROCESS']} {self.translator.get('quit_cursor.terminating', pid=proc.pid)}...{Style.RESET_ALL}")
|
||||||
proc.terminate() # 发送终止信号
|
proc.terminate()
|
||||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
||||||
continue
|
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()
|
start_time = time.time()
|
||||||
while time.time() - start_time < self.timeout:
|
while time.time() - start_time < self.timeout:
|
||||||
still_running = []
|
still_running = []
|
||||||
@ -61,28 +61,29 @@ class CursorQuitter:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if not still_running:
|
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
|
return True
|
||||||
|
|
||||||
# 等待一小段时间再检查
|
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
# 如果超时后仍有进程在运行
|
# 如果超时后仍有进程在运行
|
||||||
if still_running:
|
if still_running:
|
||||||
process_list = ", ".join([str(p.pid) for p in 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 False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
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
|
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()
|
return quitter.quit_cursor()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
quit_cursor()
|
# 如果直接运行,使用默认翻译器
|
||||||
|
from main import translator as main_translator
|
||||||
|
quit_cursor(main_translator)
|
@ -10,7 +10,7 @@ from colorama import Fore, Style, init
|
|||||||
# 初始化colorama
|
# 初始化colorama
|
||||||
init()
|
init()
|
||||||
|
|
||||||
# 定义emoji和颜色常量
|
# 定义emoji常量
|
||||||
EMOJI = {
|
EMOJI = {
|
||||||
"FILE": "📄",
|
"FILE": "📄",
|
||||||
"BACKUP": "💾",
|
"BACKUP": "💾",
|
||||||
@ -21,13 +21,14 @@ EMOJI = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MachineIDResetter:
|
class MachineIDResetter:
|
||||||
def __init__(self):
|
def __init__(self, translator=None):
|
||||||
|
self.translator = translator
|
||||||
|
|
||||||
# 判断操作系统
|
# 判断操作系统
|
||||||
if sys.platform == "win32": # Windows
|
if sys.platform == "win32": # Windows
|
||||||
appdata = os.getenv("APPDATA")
|
appdata = os.getenv("APPDATA")
|
||||||
if appdata is None:
|
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(
|
self.db_path = os.path.join(
|
||||||
appdata, "Cursor", "User", "globalStorage", "storage.json"
|
appdata, "Cursor", "User", "globalStorage", "storage.json"
|
||||||
)
|
)
|
||||||
@ -41,7 +42,7 @@ class MachineIDResetter:
|
|||||||
self.sqlite_path = os.path.abspath(os.path.expanduser(
|
self.sqlite_path = os.path.abspath(os.path.expanduser(
|
||||||
"~/Library/Application Support/Cursor/User/globalStorage/state.vscdb"
|
"~/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(
|
self.db_path = os.path.abspath(os.path.expanduser(
|
||||||
"~/.config/Cursor/User/globalStorage/storage.json"
|
"~/.config/Cursor/User/globalStorage/storage.json"
|
||||||
))
|
))
|
||||||
@ -49,7 +50,7 @@ class MachineIDResetter:
|
|||||||
"~/.config/Cursor/User/globalStorage/state.vscdb"
|
"~/.config/Cursor/User/globalStorage/state.vscdb"
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(f"Not Supported Os| 不支持的操作系统: {sys.platform}")
|
raise NotImplementedError(f"Not Supported OS: {sys.platform}")
|
||||||
|
|
||||||
def generate_new_ids(self):
|
def generate_new_ids(self):
|
||||||
"""生成新的机器ID"""
|
"""生成新的机器ID"""
|
||||||
@ -76,13 +77,11 @@ class MachineIDResetter:
|
|||||||
def update_sqlite_db(self, new_ids):
|
def update_sqlite_db(self, new_ids):
|
||||||
"""更新 SQLite 数据库中的机器ID"""
|
"""更新 SQLite 数据库中的机器ID"""
|
||||||
try:
|
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)
|
conn = sqlite3.connect(self.sqlite_path)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
# 确保表存在
|
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS ItemTable (
|
CREATE TABLE IF NOT EXISTS ItemTable (
|
||||||
key TEXT PRIMARY KEY,
|
key TEXT PRIMARY KEY,
|
||||||
@ -90,108 +89,89 @@ class MachineIDResetter:
|
|||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# 准备更新数据
|
|
||||||
updates = [
|
updates = [
|
||||||
(key, value) for key, value in new_ids.items()
|
(key, value) for key, value in new_ids.items()
|
||||||
]
|
]
|
||||||
|
|
||||||
# 使用参数化查询来避免 SQL 注入和处理长文本
|
|
||||||
for key, value in updates:
|
for key, value in updates:
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
INSERT OR REPLACE INTO ItemTable (key, value)
|
INSERT OR REPLACE INTO ItemTable (key, value)
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
""", (key, value))
|
""", (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.commit()
|
||||||
conn.close()
|
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
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
|
|
||||||
def reset_machine_ids(self):
|
def reset_machine_ids(self):
|
||||||
"""重置机器ID并备份原文件"""
|
"""重置机器ID并备份原文件"""
|
||||||
try:
|
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):
|
if not os.path.exists(self.db_path):
|
||||||
print(
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.not_found')}: {self.db_path}{Style.RESET_ALL}")
|
||||||
f"{Fore.RED}{EMOJI['ERROR']} Config File Not Found | 配置文件不存在: {self.db_path}{Style.RESET_ALL}"
|
|
||||||
)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 检查文件权限
|
|
||||||
if not os.access(self.db_path, os.R_OK | os.W_OK):
|
if not os.access(self.db_path, os.R_OK | os.W_OK):
|
||||||
print(
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.no_permission')}{Style.RESET_ALL}")
|
||||||
f"{Fore.RED}{EMOJI['ERROR']} Cannot Read or Write Config File, Please Check File Permissions | 无法读写配置文件,请检查文件权限!{Style.RESET_ALL}"
|
|
||||||
)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 读取现有配置
|
print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('reset.reading')}...{Style.RESET_ALL}")
|
||||||
print(f"{Fore.CYAN}{EMOJI['FILE']} Reading Current Config | 读取当前配置...{Style.RESET_ALL}")
|
|
||||||
with open(self.db_path, "r", encoding="utf-8") as f:
|
with open(self.db_path, "r", encoding="utf-8") as f:
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
|
|
||||||
# 只在没有备份文件时创建备份
|
|
||||||
backup_path = self.db_path + ".bak"
|
backup_path = self.db_path + ".bak"
|
||||||
if not os.path.exists(backup_path):
|
if not os.path.exists(backup_path):
|
||||||
print(
|
print(f"{Fore.YELLOW}{EMOJI['BACKUP']} {self.translator.get('reset.creating_backup')}: {backup_path}{Style.RESET_ALL}")
|
||||||
f"{Fore.YELLOW}{EMOJI['BACKUP']} Creating Config Backup | 创建配置备份: {backup_path}{Style.RESET_ALL}"
|
|
||||||
)
|
|
||||||
shutil.copy2(self.db_path, backup_path)
|
shutil.copy2(self.db_path, backup_path)
|
||||||
else:
|
else:
|
||||||
print(
|
print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.backup_exists')}{Style.RESET_ALL}")
|
||||||
f"{Fore.YELLOW}{EMOJI['INFO']} Backup File Already Exists, Skipping Backup Step | 已存在备份文件,跳过备份步骤{Style.RESET_ALL}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# 生成新的ID
|
print(f"{Fore.CYAN}{EMOJI['RESET']} {self.translator.get('reset.generating')}...{Style.RESET_ALL}")
|
||||||
print(f"{Fore.CYAN}{EMOJI['RESET']} Generating New Machine ID | 生成新的机器标识...{Style.RESET_ALL}")
|
|
||||||
new_ids = self.generate_new_ids()
|
new_ids = self.generate_new_ids()
|
||||||
|
|
||||||
# 更新配置
|
|
||||||
config.update(new_ids)
|
config.update(new_ids)
|
||||||
|
|
||||||
# 保存新配置到 JSON
|
print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('reset.saving_json')}...{Style.RESET_ALL}")
|
||||||
print(f"{Fore.CYAN}{EMOJI['FILE']} Saving New Config to JSON | 保存新配置到 JSON...{Style.RESET_ALL}")
|
|
||||||
with open(self.db_path, "w", encoding="utf-8") as f:
|
with open(self.db_path, "w", encoding="utf-8") as f:
|
||||||
json.dump(config, f, indent=4)
|
json.dump(config, f, indent=4)
|
||||||
|
|
||||||
# 更新 SQLite 数据库
|
|
||||||
self.update_sqlite_db(new_ids)
|
self.update_sqlite_db(new_ids)
|
||||||
|
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Machine ID Reset Successfully | 机器标识重置成功!{Style.RESET_ALL}")
|
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.success')}{Style.RESET_ALL}")
|
||||||
print(f"\n{Fore.CYAN}New Machine ID | 新的机器标识:{Style.RESET_ALL}")
|
print(f"\n{Fore.CYAN}{self.translator.get('reset.new_id')}:{Style.RESET_ALL}")
|
||||||
for key, value in new_ids.items():
|
for key, value in new_ids.items():
|
||||||
print(f"{EMOJI['INFO']} {key}: {Fore.GREEN}{value}{Style.RESET_ALL}")
|
print(f"{EMOJI['INFO']} {key}: {Fore.GREEN}{value}{Style.RESET_ALL}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except PermissionError as e:
|
except PermissionError as e:
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} Permission Error | 权限错误: {str(e)}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.permission_error', error=str(e))}{Style.RESET_ALL}")
|
||||||
print(
|
print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.run_as_admin')}{Style.RESET_ALL}")
|
||||||
f"{Fore.YELLOW}{EMOJI['INFO']} Please Try Running This Program as Administrator | 请尝试以管理员身份运行此程序{Style.RESET_ALL}"
|
|
||||||
)
|
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
|
|
||||||
def run():
|
def run(translator=None):
|
||||||
"""Main function to be called from main.py"""
|
"""Main function to be called from main.py"""
|
||||||
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
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}")
|
print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||||
|
|
||||||
resetter = MachineIDResetter()
|
resetter = MachineIDResetter(translator)
|
||||||
resetter.reset_machine_ids()
|
resetter.reset_machine_ids()
|
||||||
|
|
||||||
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
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__":
|
if __name__ == "__main__":
|
||||||
run()
|
# 如果直接运行,使用默认翻译器
|
||||||
|
from main import translator as main_translator
|
||||||
|
run(main_translator)
|
Loading…
x
Reference in New Issue
Block a user