new locale language file

This commit is contained in:
yeongpin 2025-01-15 13:35:09 +08:00
parent f139fa189d
commit 731db36121
12 changed files with 664 additions and 241 deletions

4
.env
View File

@ -1,2 +1,2 @@
version=1.0.6
VERSION=1.0.6
version=1.0.7
VERSION=1.0.7

View File

@ -26,6 +26,7 @@ a = Analysis(
('turnstilePatch', 'turnstilePatch'),
('recaptchaPatch', 'recaptchaPatch'),
('uBlock0.chromium', 'uBlock0.chromium'),
('locales', 'locales'),
('cursor_auth.py', '.'),
('reset_machine_manual.py', '.'),
('cursor_register.py', '.'),

View File

@ -1,11 +1,25 @@
import time
from colorama import Fore, Style
import random
import os
from colorama import Fore, Style, init
# 初始化colorama
init()
# 定义emoji常量
EMOJI = {
'MAIL': '📧',
'REFRESH': '🔄',
'SUCCESS': '',
'ERROR': '',
'INFO': '',
'CODE': '📱'
}
class BrowserControl:
def __init__(self, browser):
def __init__(self, browser, translator=None):
self.browser = browser
self.translator = translator # 保存translator
self.sign_up_url = "https://authenticator.cursor.sh/sign-up"
self.current_tab = None # 当前标签页
self.signup_tab = None # 注册标签页
@ -25,20 +39,20 @@ class BrowserControl:
# 保存新标签页
self.signup_tab = new_browser
print(f"{Fore.GREEN}Create New Tab Success | 成功创建新窗口{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.create_new_tab_success')}{Style.RESET_ALL}")
return new_browser
except Exception as e:
print(f"{Fore.RED}Create New Tab Failed | 创建新窗口时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.create_new_tab_failed', error=str(e))}{Style.RESET_ALL}")
return None
def switch_to_tab(self, browser):
"""切换到指定浏览器窗口"""
try:
self.browser = browser
print(f"{Fore.GREEN}Switch Tab Success | 成功切换窗口{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.switch_tab_success')}{Style.RESET_ALL}")
return True
except Exception as e:
print(f"{Fore.RED}Switch Tab Failed | 切换窗口时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.switch_tab_failed', error=str(e))}{Style.RESET_ALL}")
return False
def get_current_tab(self):
@ -48,24 +62,24 @@ class BrowserControl:
def generate_new_email(self):
"""点击新的按钮生成新邮箱"""
try:
print(f"{Fore.CYAN}Click Generate New Email | 点击生成新邮箱...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.generate_email')}...{Style.RESET_ALL}")
new_button = self.browser.ele('xpath://button[contains(@class, "egenbut")]')
if new_button:
new_button.click()
time.sleep(1) # 等待生成
print(f"{Fore.GREEN}Generate New Email | 成功生成新邮箱{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.generate_email_success')}{Style.RESET_ALL}")
return True
else:
print(f"{Fore.RED}No Generate Button Found | 未找到生成按钮{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.generate_email_failed')}{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}Generate New Email Failed | 生成新邮箱时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.browser_error', error=str(e))}{Style.RESET_ALL}")
return False
def select_email_domain(self, domain_index=None):
"""选择邮箱域名如果不指定index则随机选择"""
try:
print(f"{Fore.CYAN}Select Email Domain | 选择邮箱域名...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}...{Style.RESET_ALL}")
# 找到下拉框
select_element = self.browser.ele('xpath://select[@id="seldom"]')
if select_element:
@ -88,21 +102,21 @@ class BrowserControl:
if domain_index < len(all_options):
# 获取选中选项的文本
selected_domain = all_options[domain_index].text
print(f"{Fore.CYAN}Select Email Domain | 选择域名: {selected_domain}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}: {selected_domain}{Style.RESET_ALL}")
# 点击选择
all_options[domain_index].click()
time.sleep(1)
print(f"{Fore.GREEN}Select Email Domain | 成功选择邮箱域名{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.select_email_domain_success')}{Style.RESET_ALL}")
return True
print(f"{Fore.RED}No Available Domain Options | 未找到可用的域名选项,总共有 {len(all_options)} 个选项{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_available_domain_options', count=len(all_options))}{Style.RESET_ALL}")
return False
else:
print(f"{Fore.RED}No Domain Select Box Found | 未找到域名选择框{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_domain_select_box')}{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}Select Email Domain Failed | 选择邮箱域名时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.select_email_domain_failed', error=str(e))}{Style.RESET_ALL}")
return False
def wait_for_page_load(self, seconds=2):
@ -112,18 +126,18 @@ class BrowserControl:
def navigate_to(self, url):
"""导航到指定URL"""
try:
print(f"{Fore.CYAN}Navigate to {url} | 正在访问 {url}...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.navigate_to', url=url)}...{Style.RESET_ALL}")
self.browser.get(url)
self.wait_for_page_load()
return True
except Exception as e:
print(f"{Fore.RED}Visit {url} Failed | 访问 {url} 时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.browser_error', error=str(e))}{Style.RESET_ALL}")
return False
def copy_and_get_email(self):
"""获取邮箱地址"""
try:
print(f"{Fore.CYAN}Get Email Info | 获取邮箱信息...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.generate_email')}...{Style.RESET_ALL}")
# 等待元素加载
time.sleep(1)
@ -133,12 +147,12 @@ class BrowserControl:
email_div = self.browser.ele('xpath://div[@class="segen"]//div[contains(@style, "color: #e5e5e5")]')
if email_div:
email_name = email_div.text.split()[0]
print(f"{Fore.CYAN}Get Email Name | 找到邮箱名称: {email_name}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.get_email_name')}: {email_name}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}Get Email Name Failed | 无法找到邮箱名称元素{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_name_failed')}{Style.RESET_ALL}")
return None
except Exception as e:
print(f"{Fore.RED}Get Email Name Failed | 获取邮箱名称时出错: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_name_failed', error=str(e))}{Style.RESET_ALL}")
return None
# 直接使用上一步选择的域名
@ -152,65 +166,47 @@ class BrowserControl:
# 组合完整邮箱地址
full_email = f"{email_name}{domain}"
print(f"{Fore.GREEN}Get Email Address | 完整邮箱地址: {full_email}{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['MAIL']} {self.translator.get('control.get_email_address')}: {full_email}{Style.RESET_ALL}")
return full_email
except Exception as e:
print(f"{Fore.RED}Get Email Address Failed | 获取邮箱地址时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_address_failed', error=str(e))}{Style.RESET_ALL}")
return None
def view_mailbox(self):
"""点击查看邮箱按钮"""
try:
print(f"{Fore.CYAN}Enter Mailbox | 正在进入邮箱...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.enter_mailbox')}...{Style.RESET_ALL}")
view_button = self.browser.ele('xpath://button[contains(@class, "egenbut") and contains(.//span, "查看邮箱")]')
if view_button:
view_button.click()
time.sleep(2) # 等待页面加载
print(f"{Fore.GREEN}Successfully Entered Mailbox | 成功进入邮箱{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.enter_mailbox_success')}{Style.RESET_ALL}")
return True
else:
print(f"{Fore.RED}No View Mailbox Button Found | 未找到查看邮箱按钮{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_view_mailbox_button')}{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}Enter Mailbox Failed | 进入邮箱时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.enter_mailbox_failed', error=str(e))}{Style.RESET_ALL}")
return False
def refresh_mailbox(self):
"""刷新邮箱获取最新信息"""
try:
print(f"{Fore.CYAN}Refresh Mailbox | 正在刷新邮箱...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.refresh_mailbox')}...{Style.RESET_ALL}")
refresh_button = self.browser.ele('xpath://button[@id="refresh"]')
if refresh_button:
refresh_button.click()
time.sleep(2) # 等待刷新完成
print(f"{Fore.GREEN}Mailbox Refreshed Successfully | 邮箱刷新成功{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.refresh_mailbox_success')}{Style.RESET_ALL}")
return True
else:
print(f"{Fore.RED}No Refresh Button Found | 未找到刷新按钮{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_refresh_button')}{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}Refresh Mailbox Failed | 刷新邮箱时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.refresh_mailbox_failed', error=str(e))}{Style.RESET_ALL}")
return False
def check_and_click_recaptcha(self):
"""检查并点击验证码复选框"""
try:
# 使用环境变量或配置文件中预设的坐标
click_x = int(os.getenv('RECAPTCHA_X', '100')) # 默认值100
click_y = int(os.getenv('RECAPTCHA_Y', '100')) # 默认值100
print(f"{Fore.CYAN}使用预设坐标点击: x={click_x}, y={click_y}{Style.RESET_ALL}")
# 直接点击预设坐标
self.browser.page.mouse.click(click_x, click_y)
print(f"{Fore.GREEN}Clicked reCAPTCHA Position | 已点击 reCAPTCHA 位置{Style.RESET_ALL}")
time.sleep(1)
return True
except Exception as e:
print(f"{Fore.YELLOW}Click reCAPTCHA Failed | 点击 reCAPTCHA 失败: {str(e)}{Style.RESET_ALL}")
return False
def get_verification_code(self):
"""从邮件中获取验证码"""
@ -233,24 +229,24 @@ class BrowserControl:
if code_div:
verification_code = code_div.text.strip()
if verification_code.isdigit() and len(verification_code) == 6:
print(f"{Fore.GREEN}Found Verification Code | 找到验证码: {verification_code}{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.found_verification_code')}: {verification_code}{Style.RESET_ALL}")
return verification_code
print(f"{Fore.YELLOW}No Valid Verification Code Found | 未找到有效验证码{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{EMOJI['ERROR']} {self.translator.get('control.no_valid_verification_code')}{Style.RESET_ALL}")
return None
except Exception as e:
print(f"{Fore.RED}Get Verification Code Error | 获取验证码时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_verification_code_error', error=str(e))}{Style.RESET_ALL}")
return None
def fill_verification_code(self, code):
"""填写验证码"""
try:
if not code or len(code) != 6:
print(f"{Fore.RED}Verification Code Format Error | 验证码格式不正确{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.verification_code_format_error')}{Style.RESET_ALL}")
return False
print(f"{Fore.CYAN}Fill Verification Code | 正在填写验证码...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.fill_verification_code')}...{Style.RESET_ALL}")
# 记住当前标签页(邮箱页面)
email_tab = self.browser
@ -264,10 +260,10 @@ class BrowserControl:
self.browser.actions.input(digit)
time.sleep(random.uniform(0.1, 0.3))
print(f"{Fore.GREEN}Verification Code Filled | 验证码填写完成{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.verification_code_filled')}{Style.RESET_ALL}")
# 等待页面加载和登录完成
print(f"{Fore.CYAN}Wait for Login | 等待登录完成...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.wait_for_login')}...{Style.RESET_ALL}")
time.sleep(5)
# 先访问登录页面确保登录状态
@ -278,7 +274,7 @@ class BrowserControl:
# 获取cookies第一次尝试
token = self.get_cursor_session_token()
if not token:
print(f"{Fore.YELLOW}Get Token Failed | 首次获取token失败等待后重试...{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{EMOJI['ERROR']} {self.translator.get('control.get_token_failed')}...{Style.RESET_ALL}")
time.sleep(3)
token = self.get_cursor_session_token()
@ -287,7 +283,7 @@ class BrowserControl:
# 获取到token后再访问设置页面
settings_url = "https://www.cursor.com/settings"
print(f"{Fore.CYAN}Get Account Info | 正在访问设置页面获取账户信息...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.get_account_info')}...{Style.RESET_ALL}")
self.browser.get(settings_url)
time.sleep(2)
@ -302,9 +298,9 @@ class BrowserControl:
if usage_ele:
usage_info = usage_ele.text
total_usage = usage_info.split("/")[-1].strip()
print(f"{Fore.GREEN}Account Usage Limit | 账户可用额度上限: {total_usage}{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['INFO']} {self.translator.get('control.account_usage_limit')}: {total_usage}{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}Get Account Usage Failed | 获取账户额度信息失败: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_account_usage_failed', error=str(e))}{Style.RESET_ALL}")
# 切换回邮箱页面
self.switch_to_tab(email_tab)
@ -312,7 +308,7 @@ class BrowserControl:
return True
except Exception as e:
print(f"{Fore.RED}Fill Verification Code Failed | 填写验证码时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.fill_verification_code_failed', error=str(e))}{Style.RESET_ALL}")
return False
def check_and_click_turnstile(self):
@ -324,19 +320,19 @@ class BrowserControl:
# 查找验证框
verify_checkbox = self.browser.ele('xpath://label[contains(@class, "cb-lb")]//input[@type="checkbox"]')
if verify_checkbox:
print(f"{Fore.CYAN}Find Turnstile Verification Box | 找到 Turnstile 验证框,尝试点击...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.find_turnstile_verification_box')}...{Style.RESET_ALL}")
verify_checkbox.click()
time.sleep(2) # 等待验证完成
print(f"{Fore.GREEN}Clicked Turnstile Verification Box | 已点击 Turnstile 验证框{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.clicked_turnstile_verification_box')}{Style.RESET_ALL}")
return True
return False
except Exception as e:
print(f"{Fore.YELLOW}Check and Click Turnstile Failed | 未找到 Turnstile 验证框或点击失败: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{EMOJI['ERROR']} {self.translator.get('control.check_and_click_turnstile_failed', error=str(e))}{Style.RESET_ALL}")
return False
def get_cursor_session_token(self, max_attempts=3, retry_interval=2):
"""获取Cursor会话token"""
print(f"{Fore.CYAN}Get Cursor Session Token | 开始获取cookie...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('control.get_cursor_session_token')}...{Style.RESET_ALL}")
attempts = 0
while attempts < max_attempts:
@ -348,21 +344,21 @@ class BrowserControl:
for cookie in all_cookies:
if cookie.get("name") == "WorkosCursorSessionToken":
token = cookie["value"].split("%3A%3A")[1]
print(f"{Fore.GREEN}成功获取CursorSessionToken: {token}{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.get_cursor_session_token_success')}: {token}{Style.RESET_ALL}")
return token
attempts += 1
if attempts < max_attempts:
print(f"{Fore.YELLOW} Try | 第 {attempts} 次尝试未获取到CursorSessionToken{retry_interval}秒后重试...{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{EMOJI['ERROR']} {self.translator.get('control.get_cursor_session_token_failed', attempts=attempts, retry_interval=retry_interval)}...{Style.RESET_ALL}")
time.sleep(retry_interval)
else:
print(f"{Fore.RED}Reach Max Attempts ({max_attempts}) | 已达到最大尝试次数({max_attempts})获取CursorSessionToken失败{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.reach_max_attempts', max_attempts=max_attempts)}{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}获取cookie失败: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_cookie_failed', error=str(e))}{Style.RESET_ALL}")
attempts += 1
if attempts < max_attempts:
print(f"{Fore.YELLOW}Will Retry in {retry_interval} seconds | 将在 {retry_interval} 秒后重试...{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{EMOJI['ERROR']} {self.translator.get('control.will_retry_in', retry_interval=retry_interval)}...{Style.RESET_ALL}")
time.sleep(retry_interval)
return None
@ -373,6 +369,6 @@ class BrowserControl:
with open('cursor_tokens.txt', 'a', encoding='utf-8') as f:
f.write(f"Token: {token}\n")
f.write("-" * 50 + "\n")
print(f"{Fore.GREEN}Token Saved to cursor_tokens.txt | Token已保存到 cursor_tokens.txt{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.token_saved_to_file')}{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}Save Token Failed | 保存Token时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.save_token_failed', error=str(e))}{Style.RESET_ALL}")

View File

@ -14,11 +14,13 @@ EMOJI = {
'ERROR': '',
'WARN': '⚠️',
'INFO': '',
'KEY': '🔑'
'FILE': '📄',
'KEY': '🔐'
}
class CursorAuth:
def __init__(self):
def __init__(self, translator=None):
self.translator = translator
# 判断操作系统
if os.name == "nt": # Windows
self.db_path = os.path.join(
@ -54,7 +56,7 @@ class CursorAuth:
# 重新连接数据库
conn = sqlite3.connect(self.db_path)
print(f"{EMOJI['INFO']} {Fore.GREEN}Successfully connected to database | 成功连接到数据库{Style.RESET_ALL}")
print(f"{EMOJI['INFO']} {Fore.GREEN}{self.translator.get('auth.connected_to_database')}{Style.RESET_ALL}")
cursor = conn.cursor()
# 增加超时和其他优化设置
@ -91,7 +93,7 @@ class CursorAuth:
print(f"{EMOJI['INFO']} {Fore.CYAN}Updating {key.split('/')[-1]}...{Style.RESET_ALL}")
cursor.execute("COMMIT")
print(f"{EMOJI['SUCCESS']} {Fore.GREEN}Database updated successfully | 数据库更新成功{Style.RESET_ALL}")
print(f"{EMOJI['SUCCESS']} {Fore.GREEN}{self.translator.get('auth.database_updated_successfully')}{Style.RESET_ALL}")
return True
except Exception as e:
@ -99,14 +101,14 @@ class CursorAuth:
raise e
except sqlite3.Error as e:
print(f"\n{EMOJI['ERROR']} {Fore.RED}Database error | 数据库错误: {str(e)}{Style.RESET_ALL}")
print(f"\n{EMOJI['ERROR']} {Fore.RED}{self.translator.get('auth.database_error', error=str(e))}{Style.RESET_ALL}")
return False
except Exception as e:
print(f"\n{EMOJI['ERROR']} {Fore.RED}An error occurred | 发生错误: {str(e)}{Style.RESET_ALL}")
print(f"\n{EMOJI['ERROR']} {Fore.RED}{self.translator.get('auth.an_error_occurred', error=str(e))}{Style.RESET_ALL}")
return False
finally:
if conn:
conn.close()
print(f"{EMOJI['DB']} {Fore.CYAN}Database connection closed | 数据库连接已关闭{Style.RESET_ALL}")
print(f"{EMOJI['DB']} {Fore.CYAN}{self.translator.get('auth.database_connection_closed')}{Style.RESET_ALL}")

View File

@ -13,7 +13,7 @@ os.environ["PYINSTALLER_VERBOSE"] = "0"
# 初始化colorama
init()
# 定义emoji和颜色常量
# 定义emoji常量
EMOJI = {
'START': '🚀',
'FORM': '📝',
@ -24,13 +24,15 @@ EMOJI = {
'ERROR': '',
'WAIT': '',
'SUCCESS': '',
'MAIL': '<EFBFBD><EFBFBD>',
'MAIL': '📧',
'KEY': '🔐',
'UPDATE': '🔄'
'UPDATE': '🔄',
'INFO': ''
}
class CursorRegistration:
def __init__(self):
def __init__(self, translator=None):
self.translator = translator
# 设置为显示模式
os.environ['BROWSER_HEADLESS'] = 'False'
self.browser_manager = BrowserManager()
@ -60,11 +62,11 @@ class CursorRegistration:
return first_letter + rest_letters
def setup_email(self):
"""Setup Temporary Email"""
"""设置邮箱"""
try:
print(f"{Fore.CYAN}Staring Browser | 正在启动浏览器...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.browser_start')}...{Style.RESET_ALL}")
self.browser = self.browser_manager.init_browser()
self.controller = BrowserControl(self.browser)
self.controller = BrowserControl(self.browser, self.translator)
# 打开邮箱生成器页面(第一个标签页)
self.controller.navigate_to(self.mail_url)
@ -80,7 +82,7 @@ class CursorRegistration:
# 获取邮箱地址
self.email_address = self.controller.copy_and_get_email()
if self.email_address:
print(f"{Fore.CYAN}Get Email Address | 获取到的邮箱地址: {self.email_address}{Style.RESET_ALL}")
print(f"{EMOJI['MAIL']}{Fore.CYAN} {self.translator.get('register.get_email_address')}: {self.email_address}{Style.RESET_ALL}")
# 进入邮箱
if self.controller.view_mailbox():
@ -89,14 +91,14 @@ class CursorRegistration:
return False
except Exception as e:
print(f"{Fore.RED}Error Occured | 发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.setup_error', error=str(e))}{Style.RESET_ALL}")
return False
def register_cursor(self):
"""注册 Cursor 账号"""
"""注册 Cursor"""
signup_browser_manager = None
try:
print(f"\n{Fore.CYAN}{EMOJI['START']}Start Register | 开始 Cursor 注册流程{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.register_start')}...{Style.RESET_ALL}")
# 创建新的浏览器实例用于注册
from browser import BrowserManager
@ -109,7 +111,7 @@ class CursorRegistration:
# 填写注册表单
if self.signup_tab.ele("@name=first_name"):
print(f"{Fore.YELLOW}{EMOJI['FORM']}Fill Form | 填写注册信息...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['FORM']} {self.translator.get('register.filling_form')}...{Style.RESET_ALL}")
self.signup_tab.ele("@name=first_name").input(self.first_name)
time.sleep(random.uniform(1, 2))
@ -121,14 +123,14 @@ class CursorRegistration:
time.sleep(random.uniform(1, 2))
self.signup_tab.ele("@type=submit").click()
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Basic Info Submitted | 基本信息提交完成{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.basic_info_submitted')}...{Style.RESET_ALL}")
# 处理 Turnstile 验证
self._handle_turnstile()
# 设置密码
if self.signup_tab.ele("@name=password"):
print(f"{Fore.YELLOW}{EMOJI['PASSWORD']} Set Password | 设置密码...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['PASSWORD']} {self.translator.get('register.set_password')}...{Style.RESET_ALL}")
self.signup_tab.ele("@name=password").input(self.password)
time.sleep(random.uniform(1, 2))
self.signup_tab.ele("@type=submit").click()
@ -147,21 +149,21 @@ class CursorRegistration:
start_time = time.time()
timeout = 60 # 60秒超时
print(f"{Fore.CYAN}{EMOJI['WAIT']} Start Getting Verification Code | 开始获取验证码将在60秒内尝试...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('register.start_getting_verification_code')}...{Style.RESET_ALL}")
for attempt in range(max_attempts):
# 检查是否超时
if time.time() - start_time > timeout:
print(f"{Fore.RED}{EMOJI['ERROR']} Get Verification Code Timeout | 获取验证码超时{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.get_verification_code_timeout')}...{Style.RESET_ALL}")
break
verification_code = self.controller.get_verification_code()
if verification_code:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Get Verification Code Success | 成功获取验证码: {verification_code}{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.get_verification_code_success')}: {verification_code}{Style.RESET_ALL}")
break
remaining_time = int(timeout - (time.time() - start_time))
print(f"{Fore.YELLOW}{EMOJI['WAIT']} Try | 第 {attempt + 1} Get Verification Code | 次尝试未获取到验证码Time Remaining | 剩余时间: {remaining_time}{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{EMOJI['WAIT']} {self.translator.get('register.try_get_verification_code', attempt=attempt + 1, remaining_time=remaining_time)}...{Style.RESET_ALL}")
# 刷新邮箱
self.browser.refresh()
@ -173,7 +175,7 @@ class CursorRegistration:
self.signup_tab.ele(f"@data-index={i}").input(digit)
time.sleep(random.uniform(0.1, 0.3))
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Verification Code Filled | 验证码填写完成{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.verification_code_filled')}...{Style.RESET_ALL}")
time.sleep(3)
self._handle_turnstile()
@ -181,7 +183,7 @@ class CursorRegistration:
# 检查当前URL
current_url = self.signup_tab.url
if "authenticator.cursor.sh" in current_url:
print(f"{Fore.CYAN}{EMOJI['VERIFY']} Detect Login Page | 检测到登录页面,开始登录...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['VERIFY']} {self.translator.get('register.detect_login_page')}...{Style.RESET_ALL}")
# 填写邮箱
email_input = self.signup_tab.ele('@name=email')
@ -218,7 +220,7 @@ class CursorRegistration:
start_time = time.time()
while time.time() - start_time < max_wait:
if "cursor.com/settings" in self.signup_tab.url:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Login Success and Jump to Settings Page | 成功登录并跳转到设置页面{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.login_success_and_jump_to_settings_page')}...{Style.RESET_ALL}")
break
time.sleep(1)
@ -231,11 +233,11 @@ class CursorRegistration:
return result
else:
print(f"{Fore.RED}{EMOJI['ERROR']} Get Verification Code Timeout | 未能在60秒内获取到验证码{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.get_verification_code_timeout')}...{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Register Process Error | 注册过程出错: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.register_process_error', error=str(e))}{Style.RESET_ALL}")
return False
finally:
# 确保在任何情况下都关闭注册窗口
@ -244,7 +246,7 @@ class CursorRegistration:
def _handle_turnstile(self):
"""处理 Turnstile 验证"""
print(f"{Fore.YELLOW}{EMOJI['VERIFY']} Handle Turnstile | 处理 Turnstile 验证...{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{EMOJI['VERIFY']} {self.translator.get('register.handle_turnstile')}...{Style.RESET_ALL}")
# 设置最大等待时间(秒)
max_wait_time = 10 # 增加等待时间
@ -254,11 +256,10 @@ class CursorRegistration:
try:
# 检查是否超时
if time.time() - start_time > max_wait_time:
print(f"{Fore.YELLOW}{EMOJI['WAIT']} Not Detect Turnstile | 未检测到 Turnstile 验证,继续下一步...{Style.RESET_ALL}")
time.sleep(2) # 添加短暂延迟
print(f"{Fore.YELLOW}{EMOJI['WAIT']} {self.translator.get('register.no_turnstile')}...{Style.RESET_ALL}")
time.sleep(2)
break
# 检查是否存在验证框
try:
challengeCheck = (
self.signup_tab.ele("@id=cf-turnstile", timeout=1)
@ -270,43 +271,38 @@ class CursorRegistration:
if challengeCheck:
challengeCheck.click()
time.sleep(3) # 增加点击后的等待时间
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Turnstile Passed | 验证通过{Style.RESET_ALL}")
time.sleep(2) # 确保验证完全完成
time.sleep(3)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.turnstile_passed')}{Style.RESET_ALL}")
time.sleep(2)
break
except:
pass
# 检查是否已经通过验证(检查下一步的元素是否存在)
try:
if (self.signup_tab.ele("@name=password", timeout=0.5) or
self.signup_tab.ele("@name=email", timeout=0.5) or
self.signup_tab.ele("@data-index=0", timeout=0.5)):
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Verification Passed | 验证已通过{Style.RESET_ALL}")
time.sleep(2) # 添加短暂延迟
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.turnstile_passed')}{Style.RESET_ALL}")
time.sleep(2)
break
except:
pass
# 等待短暂时间后继续检查
time.sleep(1)
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Turnstile Error | Turnstile 处理出错: {str(e)}{Style.RESET_ALL}")
time.sleep(2) # 出错时等待更长时间
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.error', error=str(e))}{Style.RESET_ALL}")
time.sleep(2)
break
# 最后再等待一下,确保页面加载完成
time.sleep(2)
def _get_account_info(self):
"""获取账户信息和 Token"""
try:
# 访问设置页面
self.signup_tab.get(self.settings_url)
time.sleep(2)
# 获取账户额度信息
usage_selector = (
"css:div.col-span-2 > div > div > div > div > "
"div:nth-child(1) > div.flex.items-center.justify-between.gap-2 > "
@ -317,8 +313,7 @@ class CursorRegistration:
if usage_ele:
total_usage = usage_ele.text.split("/")[-1].strip()
# 获取 Token
print(f"{Fore.CYAN}{EMOJI['WAIT']} Get Cursor Session Token | 开始获取 Cursor Session Token...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('register.get_token')}...{Style.RESET_ALL}")
max_attempts = 30
retry_interval = 2
attempts = 0
@ -329,46 +324,45 @@ class CursorRegistration:
for cookie in cookies:
if cookie.get("name") == "WorkosCursorSessionToken":
token = cookie["value"].split("%3A%3A")[1]
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Get Token Success | Token 获取成功{Style.RESET_ALL}")
# 保存账户信息
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.token_success')}{Style.RESET_ALL}")
self._save_account_info(token, total_usage)
return True
attempts += 1
if attempts < max_attempts:
print(
f"{Fore.YELLOW}{EMOJI['WAIT']} Try | 第 {attempts} times to get Token | 次尝试未获取到 Token{retry_interval}秒后重试...{Style.RESET_ALL}"
)
print(f"{Fore.YELLOW}{EMOJI['WAIT']} {self.translator.get('register.token_attempt', attempt=attempts, time=retry_interval)}{Style.RESET_ALL}")
time.sleep(retry_interval)
else:
print(f"{Fore.RED}{EMOJI['ERROR']} Reach Max Attempts ({max_attempts}) | 已达到最大尝试次数({max_attempts}),获取 Token 失败{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.token_max_attempts', max=max_attempts)}{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Get Token Failed | 获取 Token 失败: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.token_failed', error=str(e))}{Style.RESET_ALL}")
attempts += 1
if attempts < max_attempts:
print(f"{Fore.YELLOW}{EMOJI['WAIT']} Will Retry in {retry_interval} seconds | 将在 {retry_interval} 秒后重试...{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{EMOJI['WAIT']} {self.translator.get('register.token_attempt', attempt=attempts, time=retry_interval)}{Style.RESET_ALL}")
time.sleep(retry_interval)
return False
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Get Account Info Failed | 获取账户信息失败: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.account_error', error=str(e))}{Style.RESET_ALL}")
return False
def _save_account_info(self, token, total_usage):
"""保存账户信息到文件"""
try:
# 先更新认证信息
print(f"{Fore.CYAN}{EMOJI['KEY']} 正在更新 Cursor 认证信息...{Style.RESET_ALL}")
if update_cursor_auth(email=self.email_address, access_token=token, refresh_token=token):
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Cursor Auth Info Updated | 认证信息更新成功{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['KEY']} {self.translator.get('register.update_cursor_auth_info')}...{Style.RESET_ALL}")
if self.update_cursor_auth(email=self.email_address, access_token=token, refresh_token=token):
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.cursor_auth_info_updated')}...{Style.RESET_ALL}")
else:
print(f"{Fore.RED}{EMOJI['ERROR']} Cursor Auth Info Update Failed | 认证信息更新失败{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.cursor_auth_info_update_failed')}...{Style.RESET_ALL}")
# 重置机器ID
print(f"{Fore.CYAN}{EMOJI['UPDATE']} Reset Machine ID | 正在重置机器ID...{Style.RESET_ALL}")
MachineIDResetter().reset_machine_ids()
print(f"{Fore.CYAN}{EMOJI['UPDATE']} {self.translator.get('register.reset_machine_id')}...{Style.RESET_ALL}")
resetter = MachineIDResetter(self.translator) # 创建实例时传入translator
if not resetter.reset_machine_ids(): # 直接调用reset_machine_ids方法
raise Exception("Failed to reset machine ID")
# 保存账户信息到文件
with open('cursor_accounts.txt', 'a', encoding='utf-8') as f:
@ -379,11 +373,11 @@ class CursorRegistration:
f.write(f"Usage Limit: {total_usage}\n")
f.write(f"{'='*50}\n")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Account Info Saved to cursor_accounts.txt | 账户信息已保存到 cursor_accounts.txt{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.account_info_saved')}...{Style.RESET_ALL}")
return True
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Save Account Info Failed | 保存账户信息失败: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.save_account_info_failed', error=str(e))}{Style.RESET_ALL}")
return False
def start(self):
@ -391,25 +385,30 @@ class CursorRegistration:
try:
if self.setup_email():
if self.register_cursor():
print(f"\n{Fore.GREEN}{EMOJI['DONE']} Cursor Registration Completed | 注册完成!{Style.RESET_ALL}")
print(f"\n{Fore.GREEN}{EMOJI['DONE']} {self.translator.get('register.cursor_registration_completed')}...{Style.RESET_ALL}")
return True
return False
finally:
if self.browser_manager:
self.browser_manager.quit()
def update_cursor_auth(self, email=None, access_token=None, refresh_token=None):
"""更新Cursor的认证信息的便捷函数"""
auth_manager = CursorAuth(translator=self.translator)
return auth_manager.update_auth(email, access_token, refresh_token)
def main(translator=None):
"""Main function to be called from main.py"""
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['START']} {translator.get('register.title')}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
def update_cursor_auth(email=None, access_token=None, refresh_token=None):
"""
更新Cursor的认证信息的便捷函数
"""
auth_manager = CursorAuth()
return auth_manager.update_auth(email, access_token, refresh_token)
def main():
registration = CursorRegistration()
registration = CursorRegistration(translator)
registration.start()
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
input(f"{EMOJI['INFO']} {translator.get('register.press_enter')}...")
if __name__ == "__main__":
main()
from main import translator as main_translator
main(main_translator)

141
locales/en.json Normal file
View 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
View 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
View 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
View File

@ -1,4 +1,11 @@
from colorama import Fore, Style, init
from dotenv import load_dotenv
import os
# 加載環境變量獲取版本號
load_dotenv()
version = os.getenv('VERSION', '1.0.0')
# 初始化 colorama
init()
@ -11,9 +18,11 @@ CURSOR_LOGO = f"""
{Fore.YELLOW}
Pro Version Activator
Pro Version Activator v{version}
{Fore.GREEN}
Author: Pin Studios | yeongpin
Author: Pin Studios | yeongpin
{Fore.RED}
Press 4 to change language | 按下 4 键切换语言
{Style.RESET_ALL}
"""

100
main.py
View File

@ -1,5 +1,8 @@
# main.py
# This script allows the user to choose which script to run.
import os
import sys
import json
from logo import print_logo
from colorama import Fore, Style, init
@ -16,58 +19,119 @@ EMOJI = {
"RESET": "🔄",
"MENU": "📋",
"ARROW": "",
"LANG": "🌐"
}
class Translator:
def __init__(self):
self.current_language = 'zh_tw' # 默认语言
self.translations = {}
self.load_translations()
def load_translations(self):
"""加载所有可用的翻译"""
locales_dir = os.path.join(os.path.dirname(__file__), 'locales')
if hasattr(sys, '_MEIPASS'):
locales_dir = os.path.join(sys._MEIPASS, 'locales')
for file in os.listdir(locales_dir):
if file.endswith('.json'):
lang_code = file[:-5] # 移除 .json
with open(os.path.join(locales_dir, file), 'r', encoding='utf-8') as f:
self.translations[lang_code] = json.load(f)
def get(self, key, **kwargs):
"""获取翻译文本"""
keys = key.split('.')
value = self.translations.get(self.current_language, {})
for k in keys:
value = value.get(k, key)
return value.format(**kwargs) if kwargs else value
def set_language(self, lang_code):
"""设置当前语言"""
if lang_code in self.translations:
self.current_language = lang_code
return True
return False
# 创建翻译器实例
translator = Translator()
def print_menu():
"""打印菜单选项"""
print(f"\n{Fore.CYAN}{EMOJI['MENU']} Available Options | 可用选项:{Style.RESET_ALL}")
print(f"\n{Fore.CYAN}{EMOJI['MENU']} {translator.get('menu.title')}:{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{'' * 40}{Style.RESET_ALL}")
print(f"{Fore.GREEN}0{Style.RESET_ALL}. {EMOJI['ERROR']} Exit Program | 退出程序")
print(f"{Fore.GREEN}1{Style.RESET_ALL}. {EMOJI['RESET']} Reset Machine Manual | 重置机器标识")
print(f"{Fore.GREEN}2{Style.RESET_ALL}. {EMOJI['SUCCESS']} Register Cursor | 注册 Cursor")
print(f"{Fore.GREEN}3{Style.RESET_ALL}. {EMOJI['ERROR']} Quit Cursor | 退出 Cursor")
# 在这里添加更多选项
print(f"{Fore.GREEN}0{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.exit')}")
print(f"{Fore.GREEN}1{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.reset')}")
print(f"{Fore.GREEN}2{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register')}")
print(f"{Fore.GREEN}3{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.quit')}")
print(f"{Fore.GREEN}4{Style.RESET_ALL}. {EMOJI['LANG']} {translator.get('menu.select_language')}")
print(f"{Fore.YELLOW}{'' * 40}{Style.RESET_ALL}")
def select_language():
"""语言选择菜单"""
print(f"\n{Fore.CYAN}{EMOJI['LANG']} {translator.get('menu.select_language')}:{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{'' * 40}{Style.RESET_ALL}")
languages = translator.get('languages')
for i, (code, name) in enumerate(languages.items()):
print(f"{Fore.GREEN}{i}{Style.RESET_ALL}. {name}")
try:
choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices='0-' + str(len(languages)-1))}: {Style.RESET_ALL}")
if choice.isdigit() and 0 <= int(choice) < len(languages):
lang_code = list(languages.keys())[int(choice)]
translator.set_language(lang_code)
return True
except (ValueError, IndexError):
pass
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}")
return False
def main():
print_logo()
print_menu()
while True:
try:
choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}Enter your choice (0-3) | 输入选择 (0-3): {Style.RESET_ALL}")
choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices='0-4')}: {Style.RESET_ALL}")
if choice == "0":
print(f"\n{Fore.YELLOW}{EMOJI['INFO']} Exiting program... | 正在退出程序...{Style.RESET_ALL}")
print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.exit')}...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{'' * 50}{Style.RESET_ALL}")
return # 直接返回,不等待按键
return
elif choice == "1":
import reset_machine_manual
reset_machine_manual.run()
reset_machine_manual.run(translator)
break
elif choice == "2":
import cursor_register
cursor_register.main()
cursor_register.main(translator)
break
elif choice == "3":
import quit_cursor
quit_cursor.quit_cursor()
quit_cursor.quit_cursor(translator)
break
elif choice == "4":
if select_language():
print_menu()
continue
else:
print(f"{Fore.RED}{EMOJI['ERROR']} Invalid choice. Please try again | 无效选择,请重试{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}")
print_menu()
except KeyboardInterrupt:
print(f"\n{Fore.YELLOW}{EMOJI['INFO']} Program terminated by user | 程序被用户终止{Style.RESET_ALL}")
print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.program_terminated')}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{'' * 50}{Style.RESET_ALL}")
return # 直接返回,不等待按键
return
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} An error occurred | 发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.error_occurred', error=str(e))}{Style.RESET_ALL}")
break
# 只有在执行完其他选项后才显示按键退出提示
print(f"\n{Fore.CYAN}{'' * 50}{Style.RESET_ALL}")
input(f"{EMOJI['INFO']} Press Enter to Exit | 按回车键退出...{Style.RESET_ALL}")
input(f"{EMOJI['INFO']} {translator.get('menu.press_enter')}...{Style.RESET_ALL}")
if __name__ == "__main__":
main()

View File

@ -1,30 +1,30 @@
import psutil
import time
from colorama import Fore, Style, init
import sys
import os
# 初始化colorama
init()
# 定义emoji和颜色常量
# 定义emoji常量
EMOJI = {
"FILE": "📄",
"BACKUP": "💾",
"PROCESS": "⚙️",
"SUCCESS": "",
"ERROR": "",
"INFO": "",
"RESET": "🔄",
"PROCESS": "⚙️",
"WAIT": ""
}
class CursorQuitter:
def __init__(self, timeout=5):
def __init__(self, timeout=5, translator=None):
self.timeout = timeout
self.translator = translator # 使用传入的翻译器
def quit_cursor(self):
"""温和地关闭 Cursor 进程"""
try:
print(f"{Fore.CYAN}{EMOJI['PROCESS']} Start Quitting Cursor | 开始退出 Cursor...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['PROCESS']} {self.translator.get('quit_cursor.start')}...{Style.RESET_ALL}")
cursor_processes = []
# 收集所有 Cursor 进程
@ -36,20 +36,20 @@ class CursorQuitter:
continue
if not cursor_processes:
print(f"{Fore.GREEN}{EMOJI['INFO']} No Running Cursor Process | 未发现运行中的 Cursor 进程{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['INFO']} {self.translator.get('quit_cursor.no_process')}{Style.RESET_ALL}")
return True
# 温和地请求进程终止
for proc in cursor_processes:
try:
if proc.is_running():
print(f"{Fore.YELLOW}{EMOJI['PROCESS']} Terminating Process | 正在终止进程 {proc.pid}...{Style.RESET_ALL}")
proc.terminate() # 发送终止信号
print(f"{Fore.YELLOW}{EMOJI['PROCESS']} {self.translator.get('quit_cursor.terminating', pid=proc.pid)}...{Style.RESET_ALL}")
proc.terminate()
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
# 等待进程自然终止
print(f"{Fore.CYAN}{EMOJI['WAIT']} Waiting for Process to Exit | 等待进程退出...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['WAIT']} {self.translator.get('quit_cursor.waiting')}...{Style.RESET_ALL}")
start_time = time.time()
while time.time() - start_time < self.timeout:
still_running = []
@ -61,28 +61,29 @@ class CursorQuitter:
continue
if not still_running:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} All Cursor Processes Closed | 所有 Cursor 进程已正常关闭{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('quit_cursor.success')}{Style.RESET_ALL}")
return True
# 等待一小段时间再检查
time.sleep(0.5)
# 如果超时后仍有进程在运行
if still_running:
process_list = ", ".join([str(p.pid) for p in still_running])
print(f"{Fore.RED}{EMOJI['ERROR']} Process Timeout | 以下进程未能在规定时间内关闭: {process_list}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('quit_cursor.timeout', pids=process_list)}{Style.RESET_ALL}")
return False
return True
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Error Occurred | 关闭 Cursor 进程时发生错误: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('quit_cursor.error', error=str(e))}{Style.RESET_ALL}")
return False
def quit_cursor(timeout=5):
def quit_cursor(translator=None, timeout=5):
"""便捷函数,用于直接调用退出功能"""
quitter = CursorQuitter(timeout)
quitter = CursorQuitter(timeout, translator)
return quitter.quit_cursor()
if __name__ == "__main__":
quit_cursor()
# 如果直接运行,使用默认翻译器
from main import translator as main_translator
quit_cursor(main_translator)

View File

@ -10,7 +10,7 @@ from colorama import Fore, Style, init
# 初始化colorama
init()
# 定义emoji和颜色常量
# 定义emoji常量
EMOJI = {
"FILE": "📄",
"BACKUP": "💾",
@ -21,13 +21,14 @@ EMOJI = {
}
class MachineIDResetter:
def __init__(self):
def __init__(self, translator=None):
self.translator = translator
# 判断操作系统
if sys.platform == "win32": # Windows
appdata = os.getenv("APPDATA")
if appdata is None:
raise EnvironmentError("APPDATA Environment Variable Not Set | APPDATA 环境变量未设置")
raise EnvironmentError("APPDATA Environment Variable Not Set")
self.db_path = os.path.join(
appdata, "Cursor", "User", "globalStorage", "storage.json"
)
@ -41,7 +42,7 @@ class MachineIDResetter:
self.sqlite_path = os.path.abspath(os.path.expanduser(
"~/Library/Application Support/Cursor/User/globalStorage/state.vscdb"
))
elif sys.platform == "linux": # Linux 和其他类Unix系统
elif sys.platform == "linux": # Linux
self.db_path = os.path.abspath(os.path.expanduser(
"~/.config/Cursor/User/globalStorage/storage.json"
))
@ -49,7 +50,7 @@ class MachineIDResetter:
"~/.config/Cursor/User/globalStorage/state.vscdb"
))
else:
raise NotImplementedError(f"Not Supported Os| 不支持的操作系统: {sys.platform}")
raise NotImplementedError(f"Not Supported OS: {sys.platform}")
def generate_new_ids(self):
"""生成新的机器ID"""
@ -76,13 +77,11 @@ class MachineIDResetter:
def update_sqlite_db(self, new_ids):
"""更新 SQLite 数据库中的机器ID"""
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} Updating SQLite Database | 正在更新 SQLite 数据库...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.updating_sqlite')}...{Style.RESET_ALL}")
# 创建数据库连接
conn = sqlite3.connect(self.sqlite_path)
cursor = conn.cursor()
# 确保表存在
cursor.execute("""
CREATE TABLE IF NOT EXISTS ItemTable (
key TEXT PRIMARY KEY,
@ -90,108 +89,89 @@ class MachineIDResetter:
)
""")
# 准备更新数据
updates = [
(key, value) for key, value in new_ids.items()
]
# 使用参数化查询来避免 SQL 注入和处理长文本
for key, value in updates:
cursor.execute("""
INSERT OR REPLACE INTO ItemTable (key, value)
VALUES (?, ?)
""", (key, value))
print(f"{EMOJI['INFO']} {Fore.CYAN}Updating Key-Value Pair | 更新键值对: {key}{Style.RESET_ALL}")
print(f"{EMOJI['INFO']} {Fore.CYAN}{self.translator.get('reset.updating_pair')}: {key}{Style.RESET_ALL}")
# 提交更改并关闭连接
conn.commit()
conn.close()
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} SQLite Database Updated Successfully | 数据库更新成功!{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.sqlite_success')}{Style.RESET_ALL}")
return True
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} SQLite Database Update Failed | 数据库更新失败: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.sqlite_error', error=str(e))}{Style.RESET_ALL}")
return False
def reset_machine_ids(self):
"""重置机器ID并备份原文件"""
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} Checking Config File | 正在检查配置文件...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.checking')}...{Style.RESET_ALL}")
# 检查JSON文件是否存在
if not os.path.exists(self.db_path):
print(
f"{Fore.RED}{EMOJI['ERROR']} Config File Not Found | 配置文件不存在: {self.db_path}{Style.RESET_ALL}"
)
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.not_found')}: {self.db_path}{Style.RESET_ALL}")
return False
# 检查文件权限
if not os.access(self.db_path, os.R_OK | os.W_OK):
print(
f"{Fore.RED}{EMOJI['ERROR']} Cannot Read or Write Config File, Please Check File Permissions | 无法读写配置文件,请检查文件权限!{Style.RESET_ALL}"
)
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.no_permission')}{Style.RESET_ALL}")
return False
# 读取现有配置
print(f"{Fore.CYAN}{EMOJI['FILE']} Reading Current Config | 读取当前配置...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('reset.reading')}...{Style.RESET_ALL}")
with open(self.db_path, "r", encoding="utf-8") as f:
config = json.load(f)
# 只在没有备份文件时创建备份
backup_path = self.db_path + ".bak"
if not os.path.exists(backup_path):
print(
f"{Fore.YELLOW}{EMOJI['BACKUP']} Creating Config Backup | 创建配置备份: {backup_path}{Style.RESET_ALL}"
)
print(f"{Fore.YELLOW}{EMOJI['BACKUP']} {self.translator.get('reset.creating_backup')}: {backup_path}{Style.RESET_ALL}")
shutil.copy2(self.db_path, backup_path)
else:
print(
f"{Fore.YELLOW}{EMOJI['INFO']} Backup File Already Exists, Skipping Backup Step | 已存在备份文件,跳过备份步骤{Style.RESET_ALL}"
)
print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.backup_exists')}{Style.RESET_ALL}")
# 生成新的ID
print(f"{Fore.CYAN}{EMOJI['RESET']} Generating New Machine ID | 生成新的机器标识...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['RESET']} {self.translator.get('reset.generating')}...{Style.RESET_ALL}")
new_ids = self.generate_new_ids()
# 更新配置
config.update(new_ids)
# 保存新配置到 JSON
print(f"{Fore.CYAN}{EMOJI['FILE']} Saving New Config to JSON | 保存新配置到 JSON...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('reset.saving_json')}...{Style.RESET_ALL}")
with open(self.db_path, "w", encoding="utf-8") as f:
json.dump(config, f, indent=4)
# 更新 SQLite 数据库
self.update_sqlite_db(new_ids)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Machine ID Reset Successfully | 机器标识重置成功!{Style.RESET_ALL}")
print(f"\n{Fore.CYAN}New Machine ID | 新的机器标识:{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.success')}{Style.RESET_ALL}")
print(f"\n{Fore.CYAN}{self.translator.get('reset.new_id')}:{Style.RESET_ALL}")
for key, value in new_ids.items():
print(f"{EMOJI['INFO']} {key}: {Fore.GREEN}{value}{Style.RESET_ALL}")
return True
except PermissionError as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Permission Error | 权限错误: {str(e)}{Style.RESET_ALL}")
print(
f"{Fore.YELLOW}{EMOJI['INFO']} Please Try Running This Program as Administrator | 请尝试以管理员身份运行此程序{Style.RESET_ALL}"
)
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.permission_error', error=str(e))}{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.run_as_admin')}{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Reset Process Error | 重置过程出错: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.process_error', error=str(e))}{Style.RESET_ALL}")
return False
def run():
def run(translator=None):
"""Main function to be called from main.py"""
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['RESET']} Cursor Machine ID Reset Tool | Cursor 机器标识重置工具{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['RESET']} {translator.get('reset.title')}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
resetter = MachineIDResetter()
resetter = MachineIDResetter(translator)
resetter.reset_machine_ids()
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
input(f"{EMOJI['INFO']} Press Enter to Exit | 按回车键退出...")
input(f"{EMOJI['INFO']} {translator.get('reset.press_enter')}...")
if __name__ == "__main__":
run()
# 如果直接运行,使用默认翻译器
from main import translator as main_translator
run(main_translator)