Compare commits

...

31 Commits

Author SHA1 Message Date
yeongpin
887239d80c change other mail site 2025-02-13 11:11:08 +08:00
yeongpin
5d944fa3b1 update readme 2025-02-12 15:45:32 +08:00
yeongpin
654157b371 fix update readme 2025-02-12 14:36:54 +08:00
yeongpin
f4314cc6da Big Update - Fixed Human Verify Problem 2025-02-12 14:31:11 +08:00
yeongpin
1f29b2dbbe update readme 2025-02-11 16:58:20 +08:00
yeongpin
9c2b3f2fc8 update 2025-02-11 16:53:18 +08:00
yeongpin
8e20a0ed3d update env 2025-02-11 16:50:52 +08:00
yeongpin
4122701468 test2 2025-02-08 23:07:23 +08:00
yeongpin
1ee9813155 test1 2025-02-08 23:05:50 +08:00
yeongpin
a9e4b3a5c6 test 2025-02-08 23:02:22 +08:00
yeongpin
a83851d441 update new build.yml 2025-02-08 22:54:02 +08:00
yeongpin
1e290d0417 build.yml update 2025-02-08 22:50:05 +08:00
yeongpin
53ab15604e update build 2025-02-08 22:45:32 +08:00
yeongpin
638916e5ef update github 2025-02-08 22:38:11 +08:00
yeongpin
9500ce1249 update new build 2025-02-08 22:22:19 +08:00
yeongpin
721c13cb2f update build 2025-02-08 22:16:02 +08:00
yeongpin
a04eed2c6b update build.yml 2025-02-08 22:12:17 +08:00
yeongpin
8107bede63 update remake 2025-02-08 22:10:00 +08:00
yeongpin
4166bc5135 update reissue 2025-02-08 22:04:14 +08:00
yeongpin
69994d2486 update v4 2025-02-08 22:02:01 +08:00
yeongpin
ffcb8ec140 update 2025-02-08 22:00:19 +08:00
yeongpin
b61b61c607 add workflow 2025-02-08 21:57:44 +08:00
yeongpin
7326d0eeb0 newest reset machine 2025-02-08 21:52:16 +08:00
yeongpin
371f00645d update readme 2025-02-05 19:33:42 +08:00
yeongpin
a873291481 update env 2025-02-05 19:22:01 +08:00
yeongpin
7710ea4bb3 Update support 0.45 2025-02-05 19:21:34 +08:00
yeongpin
13483eed77 update auth message & reset message 2025-01-17 10:12:18 +08:00
yeongpin
eb69f933af Update & Fix reset machine problem 2025-01-15 17:14:05 +08:00
yeongpin
54cd8cf323 Update 107 2025-01-15 13:54:38 +08:00
yeongpin
4e0289c86c Update New107 images 2025-01-15 13:46:54 +08:00
yeongpin
af4a1c4065 Update Readme 2025-01-15 13:44:22 +08:00
20 changed files with 1695 additions and 272 deletions

4
.env
View File

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

206
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,206 @@
name: Build Executables
on:
workflow_dispatch:
inputs:
version:
description: 'Version number (e.g. 1.0.9)'
required: true
default: '1.0.9-dev'
permissions:
contents: write
actions: write
packages: write
jobs:
create-tag:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # 获取所有标签
- name: Delete existing tag if exists
run: |
if git ls-remote --tags origin | grep -q "refs/tags/v${{ github.event.inputs.version }}"; then
git push origin --delete "v${{ github.event.inputs.version }}" || true
git tag -d "v${{ github.event.inputs.version }}" || true
fi
- name: Create Tag
run: |
git tag "v${{ github.event.inputs.version }}"
git push origin "v${{ github.event.inputs.version }}"
build-windows:
needs: create-tag
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Set version
shell: bash
run: echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pyinstaller
pip install -r requirements.txt
- name: Build EXE
run: |
pyinstaller build.spec
- name: Upload Windows artifact
uses: actions/upload-artifact@v4
with:
name: CursorFreeVIP_${{ env.VERSION }}_windows.exe
path: dist/*
build-macos-arm64:
needs: create-tag
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Set version
shell: bash
run: echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pyinstaller
pip install -r requirements.txt
- name: Build MacOS ARM executable
run: |
pyinstaller build.spec
- name: Upload MacOS ARM artifact
uses: actions/upload-artifact@v4
with:
name: CursorFreeVIP_${{ env.VERSION }}_mac_arm64
path: dist/*
build-linux:
needs: create-tag
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Set version
shell: bash
run: echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pyinstaller
pip install -r requirements.txt
- name: Build Linux executable
run: |
pyinstaller build.spec
- name: Upload Linux artifact
uses: actions/upload-artifact@v4
with:
name: CursorFreeVIP_${{ env.VERSION }}_linux
path: dist/*
build-macos-intel:
needs: create-tag
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Set version
shell: bash
run: echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
- name: Install dependencies
run: |
arch -x86_64 pip3 install --upgrade pip
arch -x86_64 pip3 install pyinstaller
arch -x86_64 pip3 install -r requirements.txt
- name: Build MacOS Intel executable
env:
TARGET_ARCH: 'x86_64'
run: |
arch -x86_64 python3 -m PyInstaller build.spec
- name: Upload MacOS Intel artifact
uses: actions/upload-artifact@v4
with:
name: CursorFreeVIP_${{ env.VERSION }}_mac_intel
path: dist/*
create-release:
needs: [build-windows, build-macos-arm64, build-linux, build-macos-intel]
runs-on: ubuntu-22.04
steps:
- name: Get version
shell: bash
run: echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release files
run: |
cd artifacts
# 重命名文件为最终的可执行文件名
mv CursorFreeVIP_${{ env.VERSION }}_windows.exe/CursorFreeVIP.exe CursorFreeVIP_${{ env.VERSION }}_windows.exe
mv CursorFreeVIP_${{ env.VERSION }}_mac_arm64/CursorFreeVIP CursorFreeVIP_${{ env.VERSION }}_mac_arm64
mv CursorFreeVIP_${{ env.VERSION }}_linux/CursorFreeVIP CursorFreeVIP_${{ env.VERSION }}_linux
mv CursorFreeVIP_${{ env.VERSION }}_mac_intel/CursorFreeVIP CursorFreeVIP_${{ env.VERSION }}_mac_intel
# 删除空目录
rm -rf */
ls -la
- name: Create Release
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ env.VERSION }}
files: |
artifacts/CursorFreeVIP_${{ env.VERSION }}_windows.exe
artifacts/CursorFreeVIP_${{ env.VERSION }}_mac_arm64
artifacts/CursorFreeVIP_${{ env.VERSION }}_linux
artifacts/CursorFreeVIP_${{ env.VERSION }}_mac_intel
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -11,13 +11,14 @@
[![Stars](https://img.shields.io/github/stars/yeongpin/cursor-free-vip?style=flat-square&logo=github)](https://github.com/yeongpin/cursor-free-vip/stargazers) [![Stars](https://img.shields.io/github/stars/yeongpin/cursor-free-vip?style=flat-square&logo=github)](https://github.com/yeongpin/cursor-free-vip/stargazers)
</p> </p>
<h4>Support Latest 0.45.11 Version | 支持最新0.45.11版本</h4>
This is a tool to automatically register (except for Google verification code), support Windows and macOS systems, complete Auth verification, and reset Cursor's configuration. This is a tool to automatically register (except for Google verification code), support Windows and macOS systems, complete Auth verification, and reset Cursor's configuration.
這是一個自動化工具自動註冊除了Google驗證碼),支持 Windows 和 macOS 系統完成Auth驗證重置Cursor的配置。 這是一個自動化工具自動註冊除了Google驗證碼),支持 Windows 和 macOS 系統完成Auth驗證重置Cursor的配置。
<p align="center"> <p align="center">
<img src="./images/pro_2025-01-14_14-40-37.png" alt="new" width="400"/><br> <img src="./images/new107_2025-01-15_13-53-56.png" alt="new" width="400"/><br>
</p> </p>
<br> <br>
@@ -25,11 +26,11 @@ This is a tool to automatically register (except for Google verification code),
<img src="./images/free_2025-01-14_14-59-15.png" alt="free" width="400"/><br> <img src="./images/free_2025-01-14_14-59-15.png" alt="free" width="400"/><br>
</p> </p>
## ⚠️ Google Recaptcha need to be manually verified, don't be lazy, move your fingers, verify it, otherwise it will keep prompting you to verify ⚠️ ##### ⚠️ Google Recaptcha need to be manually verified, don't be lazy, move your fingers, verify it, otherwise it will keep prompting you to verify ⚠️
### If you dont have google chrome , you can download it from [here](https://www.google.com/intl/en_pk/chrome/) ##### If you dont have google chrome , you can download it from [here](https://www.google.com/intl/en_pk/chrome/)
## ⚠️ 郵箱驗證 需要手動驗證,不要那麼懶,動一動手指,驗證一下,不然會一直提示你驗證 ⚠️ ##### ⚠️ 郵箱驗證 需要手動驗證,不要那麼懶,動一動手指,驗證一下,不然會一直提示你驗證 ⚠️
### 如果沒有Google Chrome可以從[這裡](https://www.google.com/intl/en_pk/chrome/)下載 ##### 如果沒有Google Chrome可以從[這裡](https://www.google.com/intl/en_pk/chrome/)下載
</p> </p>
</div> </div>
@@ -37,6 +38,51 @@ This is a tool to automatically register (except for Google verification code),
## 🔄 更新日志 ## 🔄 更新日志
<details open> <details open>
<summary>v1.1.01</summary>
<p align="center">
<img src="./images/cloudflare_2025-02-12_13-43-21.png" alt="free" width="400"/><br>
</p>
1. Hot Fix Cursor Cloudflare Problem | 修復Cursor Cloudflare問題
2. Fix Cursor Cloudflare Human Verification Problem | 修復Cursor Cloudflare人機驗證問題
3. Remake signup logic | 重做註冊邏輯
</details>
<details>
<summary>Other Version Change Log</summary>
<details>
<summary>v1.0.10</summary>
1. Hot Fix Mac Chrome Problem | 修復Mac Chrome問題
2. Fix Linux Start Donet Problem | 修復Linux啟動開發者問題
</details>
<details>
<summary>v1.0.9</summary>
<p align="center">
<img src="./images/cloudflare_2025-02-12_13-43-21.png.png" alt="free" width="400"/><br>
</p>
1. Fixed New 0.45.x Version Reset Machine | 修復新0.45版本重置機器
2. Fix Locale Language | 修復多語言
3. Add Support Crypto Machine Regedit | 增加支持加密機器註冊
4. Add Remake main.js | 重做main.js
</details>
<details>
<summary>v1.0.8</summary>
1. Fix New 0.45 Version Reset Machine | 修復新0.45版本重置機器
2. Fix Locale Language | 修復多語言
3. Add Support Crypto Machine Regedit | 增加支持加密機器註冊
</details>
<details>
<summary>v1.0.7 - HotFix</summary>
1. Fix Reset Machine | 修復重置機器
2. Fix Locale Language | 修復多語言
</details>
<details>
<summary>v1.0.7</summary> <summary>v1.0.7</summary>
1. Add Locale Language Support | 增加多語言支持 1. Add Locale Language Support | 增加多語言支持
@@ -130,6 +176,7 @@ This is a tool to automatically register (except for Google verification code),
<img src="./images/pro_2025-01-11_16-24-03.png" alt="Cursor Pro Logo" width="400"/><br> <img src="./images/pro_2025-01-11_16-24-03.png" alt="Cursor Pro Logo" width="400"/><br>
</p> </p>
</details> </details>
</details>
## ✨ Features | 功能特點 ## ✨ Features | 功能特點
@@ -153,9 +200,7 @@ This is a tool to automatically register (except for Google verification code),
|Linux|ARM64|✅|Linux|ARM64|✅| |Linux|ARM64|✅|Linux|ARM64|✅|
## 👀 How to use | 如何使用 ## 👀 How to use | 如何使用
|⚠Must logout your account before running the script⚠|⚠️必須先登出你的帳戶再運行腳本⚠️ |
|:---:|:---:|
<br>
<details open> <details open>
<summary><b>⭐ Auto Run Script | 腳本自動化運行</b></summary> <summary><b>⭐ Auto Run Script | 腳本自動化運行</b></summary>
@@ -190,8 +235,6 @@ irm https://raw.githubusercontent.com/yeongpin/cursor-free-vip/main/scripts/rese
* Confirm that Cursor is closed before running the script <br>請確保在運行腳本前已經關閉 Cursor<br> * Confirm that Cursor is closed before running the script <br>請確保在運行腳本前已經關閉 Cursor<br>
* Do not close this script when using Cursor <br>使用Cursor時請勿關閉此腳本<br>
* This tool is only for learning and research purposes <br>此工具僅供學習和研究使用<br> * This tool is only for learning and research purposes <br>此工具僅供學習和研究使用<br>
* Please comply with the relevant software usage terms when using this tool <br>使用本工具時請遵守相關軟件使用條款 * Please comply with the relevant software usage terms when using this tool <br>使用本工具時請遵守相關軟件使用條款

5
blacklist.txt Normal file
View File

@@ -0,0 +1,5 @@
fr.nf
yopmail.com
1s.fr
xl.cx
fr.cr

View File

@@ -2,6 +2,7 @@ from DrissionPage import ChromiumOptions, ChromiumPage
import sys import sys
import os import os
import logging import logging
import random
class BrowserManager: class BrowserManager:
@@ -26,27 +27,71 @@ class BrowserManager:
try: try:
extension_path = self._get_extension_path() extension_path = self._get_extension_path()
co.add_extension(extension_path) co.add_extension(extension_path)
co.set_argument("--allow-extensions-in-incognito")
extension_block_path = self.get_extension_block() extension_block_path = self.get_extension_block()
co.add_extension(extension_block_path) co.add_extension(extension_block_path)
co.set_argument("--allow-extensions-in-incognito")
extension_recaptcha_path = self.get_extension_recaptcha() extension_recaptcha_path = self.get_extension_recaptcha()
co.add_extension(extension_recaptcha_path) co.add_extension(extension_recaptcha_path)
co.set_argument("--allow-extensions-in-incognito")
except FileNotFoundError as e: except FileNotFoundError as e:
logging.warning(f"警告: {e}") logging.warning(f"警告: {e}")
# 设置更真实的用户代理
co.set_user_agent( co.set_user_agent(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.92 Safari/537.36" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
) )
# 基本设置
co.set_pref("credentials_enable_service", False) co.set_pref("credentials_enable_service", False)
co.set_pref("profile.password_manager_enabled", False)
# 禁用自动化标志
co.set_pref("useAutomationExtension", False)
co.set_pref("excludeSwitches", ["enable-automation"])
# WebGL 和 GPU 设置
co.set_pref("webgl.disabled", False)
co.set_pref("webgl.enable_webgl2", True)
# 设置语言和地区
co.set_pref("intl.accept_languages", "en-US,en")
# 基本命令行参数
co.set_argument("--disable-blink-features=AutomationControlled")
co.set_argument("--hide-crash-restore-bubble") co.set_argument("--hide-crash-restore-bubble")
co.set_argument("--no-first-run")
co.set_argument("--no-default-browser-check")
co.set_argument("--disable-popup-blocking")
# 性能和稳定性参数
co.set_argument("--disable-dev-shm-usage")
co.set_argument("--disable-gpu")
co.set_argument("--no-sandbox")
co.set_argument("--ignore-certificate-errors")
# WebGL 相关参数
co.set_argument("--use-gl=swiftshader")
co.set_argument("--enable-webgl")
# 随机端口
co.auto_port() co.auto_port()
# Mac 系统特殊处理 # 系统特定设置
if sys.platform == "darwin": if sys.platform == "darwin": # macOS
co.set_argument("--no-sandbox")
co.set_argument("--disable-gpu") co.set_argument("--disable-gpu")
co.set_argument("--no-sandbox")
elif sys.platform == "win32": # Windows
co.set_argument("--disable-software-rasterizer")
# 设置窗口大小
window_width = random.randint(1024, 1920)
window_height = random.randint(768, 1080)
co.set_argument(f"--window-size={window_width},{window_height}")
return co return co

View File

@@ -31,7 +31,9 @@ a = Analysis(
('reset_machine_manual.py', '.'), ('reset_machine_manual.py', '.'),
('cursor_register.py', '.'), ('cursor_register.py', '.'),
('browser.py', '.'), ('browser.py', '.'),
('control.py', '.') ('control.py', '.'),
('.env', '.'),
('blacklist.txt', '.')
], ],
hiddenimports=[ hiddenimports=[
'cursor_auth', 'cursor_auth',

View File

@@ -80,41 +80,71 @@ class BrowserControl:
"""选择邮箱域名如果不指定index则随机选择""" """选择邮箱域名如果不指定index则随机选择"""
try: try:
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}...{Style.RESET_ALL}") print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}...{Style.RESET_ALL}")
# 读取黑名单域名
blacklist = []
try:
with open('blacklist.txt', 'r', encoding='utf-8') as f:
blacklist = [line.strip().lower() for line in f if line.strip()]
except FileNotFoundError:
# 如果文件不存在,创建一个包含已知黑名单域名的文件
with open('blacklist.txt', 'w', encoding='utf-8') as f:
f.write("fr.nf\nyopmail.com\n1s.fr\nfr.cr")
blacklist = ["fr.nf", "yopmail.com", "1s.fr", "fr.cr"]
# 找到下拉框 # 找到下拉框
select_element = self.browser.ele('xpath://select[@id="seldom"]') select_element = self.browser.ele('xpath://select[@id="seldom"]')
if select_element: if select_element:
# 获取所有选项,包括两个 optgroup 下的所有 option # 获取所有选项
all_options = [] all_options = []
# 获取 "新的" 组下的选项
new_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 新的 --"]/option') new_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 新的 --"]/option')
all_options.extend(new_options)
# 获取 "其他" 组下的选项
other_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 其他 --"]/option') other_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 其他 --"]/option')
all_options.extend(new_options)
all_options.extend(other_options) all_options.extend(other_options)
if all_options: if all_options:
# 如果没有指定索引,随机选择一个 max_attempts = 5
if domain_index is None: attempt = 0
domain_index = random.randint(0, len(all_options) - 1)
if domain_index < len(all_options): while attempt < max_attempts:
# 获取选中选项的文本 if domain_index is None:
selected_domain = all_options[domain_index].text domain_index = random.randint(0, len(all_options) - 1)
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}: {selected_domain}{Style.RESET_ALL}")
# 点击选择 if domain_index < len(all_options):
all_options[domain_index].click() selected_domain = all_options[domain_index].text.lower()
time.sleep(1)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.select_email_domain_success')}{Style.RESET_ALL}") # 检查域名是否在黑名单中
return True is_blacklisted = False
for blocked_domain in blacklist:
if blocked_domain in selected_domain:
print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('control.blocked_domain', domain=blocked_domain)}{Style.RESET_ALL}")
domain_index = None
attempt += 1
is_blacklisted = True
break
if is_blacklisted:
continue
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}{EMOJI['SUCCESS']} {self.translator.get('control.select_email_domain_success')}{Style.RESET_ALL}")
return True
attempt += 1
print(f"{Fore.RED}{EMOJI['ERROR']} 无法找到可用的域名{Style.RESET_ALL}")
return False
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_available_domain_options', count=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}{EMOJI['ERROR']} {self.translator.get('control.no_domain_select_box')}{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}{EMOJI['ERROR']} {self.translator.get('control.select_email_domain_failed', error=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

View File

@@ -56,7 +56,7 @@ class CursorAuth:
# 重新连接数据库 # 重新连接数据库
conn = sqlite3.connect(self.db_path) conn = sqlite3.connect(self.db_path)
print(f"{EMOJI['INFO']} {Fore.GREEN}{self.translator.get('auth.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()
# 增加超时和其他优化设置 # 增加超时和其他优化设置
@@ -90,7 +90,7 @@ class CursorAuth:
UPDATE ItemTable SET value = ? UPDATE ItemTable SET value = ?
WHERE key = ? WHERE key = ?
""", (value, key)) """, (value, key))
print(f"{EMOJI['INFO']} {Fore.CYAN}Updating {key.split('/')[-1]}...{Style.RESET_ALL}") print(f"{EMOJI['INFO']} {Fore.CYAN} {self.translator.get('auth.updating_pair')} {key.split('/')[-1]}...{Style.RESET_ALL}")
cursor.execute("COMMIT") cursor.execute("COMMIT")
print(f"{EMOJI['SUCCESS']} {Fore.GREEN}{self.translator.get('auth.database_updated_successfully')}{Style.RESET_ALL}") print(f"{EMOJI['SUCCESS']} {Fore.GREEN}{self.translator.get('auth.database_updated_successfully')}{Style.RESET_ALL}")
@@ -101,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}{self.translator.get('auth.database_error', 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}{self.translator.get('auth.an_error_occurred', error=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}{self.translator.get('auth.database_connection_closed')}{Style.RESET_ALL}") print(f"{EMOJI['DB']} {Fore.CYAN} {self.translator.get('auth.database_connection_closed')}{Style.RESET_ALL}")

View File

@@ -65,238 +65,75 @@ class CursorRegistration:
"""设置邮箱""" """设置邮箱"""
try: try:
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.browser_start')}...{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.translator)
# 打开邮箱生成器页面(第一个标签页) # 使用 new_tempemail 创建临时邮箱,传入 translator
self.controller.navigate_to(self.mail_url) from new_tempemail import NewTempEmail
self.email_tab = self.browser # 保存邮箱标签页 self.temp_email = NewTempEmail(self.translator) # 传入 translator
self.controller.email_tab = self.email_tab # 同时保存到controller
# 生成新邮箱 # 创建临时邮箱
self.controller.generate_new_email() email_address = self.temp_email.create_email()
if not email_address:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.email_create_failed')}{Style.RESET_ALL}")
return False
# 选择随机域名 # 保存邮箱地址和浏览器实例
self.controller.select_email_domain() self.email_address = email_address
self.email_tab = self.temp_email # 传递 NewTempEmail 实例而不是 page
self.controller = BrowserControl(self.temp_email.page, self.translator)
# 获取邮箱地址 return True
self.email_address = self.controller.copy_and_get_email()
if self.email_address:
print(f"{EMOJI['MAIL']}{Fore.CYAN} {self.translator.get('register.get_email_address')}: {self.email_address}{Style.RESET_ALL}")
# 进入邮箱
if self.controller.view_mailbox():
return True
return False
except Exception as e: except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.setup_error', error=str(e))}{Style.RESET_ALL}") print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.email_setup_failed', error=str(e))}{Style.RESET_ALL}")
return False return False
def register_cursor(self): def register_cursor(self):
"""注册 Cursor""" """注册 Cursor"""
signup_browser_manager = None browser_tab = None
try: try:
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.register_start')}...{Style.RESET_ALL}") print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.register_start')}...{Style.RESET_ALL}")
# 创建新的浏览器实例用于注册 # 直接使用 new_signup.py 进行注册
from browser import BrowserManager from new_signup import main as new_signup_main
signup_browser_manager = BrowserManager(noheader=True)
self.signup_tab = signup_browser_manager.init_browser()
# 访问注册页面 # 执行新的注册流程,传入 translator
self.signup_tab.get(self.sign_up_url) result, browser_tab = new_signup_main(
time.sleep(2) email=self.email_address,
password=self.password,
# 填写注册表单 first_name=self.first_name,
if self.signup_tab.ele("@name=first_name"): last_name=self.last_name,
print(f"{Fore.CYAN}{EMOJI['FORM']} {self.translator.get('register.filling_form')}...{Style.RESET_ALL}") email_tab=self.email_tab,
controller=self.controller,
self.signup_tab.ele("@name=first_name").input(self.first_name) translator=self.translator
time.sleep(random.uniform(1, 2)) )
self.signup_tab.ele("@name=last_name").input(self.last_name)
time.sleep(random.uniform(1, 2))
self.signup_tab.ele("@name=email").input(self.email_address)
time.sleep(random.uniform(1, 2))
self.signup_tab.ele("@type=submit").click()
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.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()
self._handle_turnstile() if result:
# 使用返回的浏览器实例获取账户信息
# 等待并获取验证码 self.signup_tab = browser_tab # 保存浏览器实例
time.sleep(5) # 等待验证码邮件 success = self._get_account_info()
self.browser.refresh() # 获取信息后关闭浏览器
if browser_tab:
try:
browser_tab.quit()
except:
pass
return success
# 获取验证码设置60秒超时 return False
verification_code = None
max_attempts = 10 # 增加到10次尝试
retry_interval = 5 # 每5秒重试一次
start_time = time.time()
timeout = 60 # 60秒超时
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']} {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']} {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']} {self.translator.get('register.try_get_verification_code', attempt=attempt + 1, remaining_time=remaining_time)}...{Style.RESET_ALL}")
# 刷新邮箱
self.browser.refresh()
time.sleep(retry_interval)
if verification_code:
# 在注册页面填写验证码
for i, digit in enumerate(verification_code):
self.signup_tab.ele(f"@data-index={i}").input(digit)
time.sleep(random.uniform(0.1, 0.3))
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.verification_code_filled')}...{Style.RESET_ALL}")
time.sleep(3)
self._handle_turnstile()
# 检查当前URL
current_url = self.signup_tab.url
if "authenticator.cursor.sh" in current_url:
print(f"{Fore.CYAN}{EMOJI['VERIFY']} {self.translator.get('register.detect_login_page')}...{Style.RESET_ALL}")
# 填写邮箱
email_input = self.signup_tab.ele('@name=email')
if email_input:
email_input.input(self.email_address)
time.sleep(random.uniform(1, 2))
# 点击提交
submit_button = self.signup_tab.ele('@type=submit')
if submit_button:
submit_button.click()
time.sleep(2)
# 处理 Turnstile 验证
self._handle_turnstile()
# 填写密码
password_input = self.signup_tab.ele('@name=password')
if password_input:
password_input.input(self.password)
time.sleep(random.uniform(1, 2))
# 点击提交
submit_button = self.signup_tab.ele('@type=submit')
if submit_button:
submit_button.click()
time.sleep(2)
# 处理 Turnstile 验证
self._handle_turnstile()
# 等待跳转到设置页面
max_wait = 30
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']} {self.translator.get('register.login_success_and_jump_to_settings_page')}...{Style.RESET_ALL}")
break
time.sleep(1)
# 获取账户信息
result = self._get_account_info()
# 关闭注册窗口
if signup_browser_manager:
signup_browser_manager.quit()
return result
else:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.get_verification_code_timeout')}...{Style.RESET_ALL}")
return False
except Exception as e: except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.register_process_error', 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:
# 确保在任何情况下都关闭注册窗口 # 确保在任何情况下都关闭浏览器
if signup_browser_manager: if browser_tab:
signup_browser_manager.quit()
def _handle_turnstile(self):
"""处理 Turnstile 验证"""
print(f"{Fore.YELLOW}{EMOJI['VERIFY']} {self.translator.get('register.handle_turnstile')}...{Style.RESET_ALL}")
# 设置最大等待时间(秒)
max_wait_time = 10 # 增加等待时间
start_time = time.time()
while True:
try:
# 检查是否超时
if time.time() - start_time > max_wait_time:
print(f"{Fore.YELLOW}{EMOJI['WAIT']} {self.translator.get('register.no_turnstile')}...{Style.RESET_ALL}")
time.sleep(2)
break
try: try:
challengeCheck = ( browser_tab.quit()
self.signup_tab.ele("@id=cf-turnstile", timeout=1)
.child()
.shadow_root.ele("tag:iframe")
.ele("tag:body")
.sr("tag:input")
)
if challengeCheck:
challengeCheck.click()
time.sleep(3)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('register.turnstile_passed')}{Style.RESET_ALL}")
time.sleep(2)
break
except: except:
pass 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']} {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']} {self.translator.get('register.error', error=str(e))}{Style.RESET_ALL}")
time.sleep(2)
break
time.sleep(2)
def _get_account_info(self): def _get_account_info(self):
"""获取账户信息和 Token""" """获取账户信息和 Token"""
try: try:
@@ -389,8 +226,12 @@ class CursorRegistration:
return True return True
return False return False
finally: finally:
if self.browser_manager: # 关闭邮箱标签页
self.browser_manager.quit() if hasattr(self, 'temp_email'):
try:
self.temp_email.close()
except:
pass
def update_cursor_auth(self, email=None, access_token=None, refresh_token=None): def update_cursor_auth(self, email=None, access_token=None, refresh_token=None):
"""更新Cursor的认证信息的便捷函数""" """更新Cursor的认证信息的便捷函数"""

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

View File

@@ -45,14 +45,46 @@
"updating_pair": "Updating Key-Value Pair", "updating_pair": "Updating Key-Value Pair",
"sqlite_success": "SQLite Database Updated Successfully", "sqlite_success": "SQLite Database Updated Successfully",
"sqlite_error": "SQLite Database Update Failed: {error}", "sqlite_error": "SQLite Database Update Failed: {error}",
"press_enter": "Press Enter to Exit" "press_enter": "Press Enter to Exit",
"unsupported_os": "Unsupported OS: {os}",
"linux_path_not_found": "Linux Path Not Found",
"updating_system_ids": "Updating System IDs",
"system_ids_updated": "System IDs Updated Successfully",
"system_ids_update_failed": "System IDs Update Failed: {error}",
"windows_guid_updated": "Windows GUID Updated Successfully",
"windows_permission_denied": "Windows Permission Denied",
"windows_guid_update_failed": "Windows GUID Update Failed",
"macos_uuid_updated": "macOS UUID Updated Successfully",
"plutil_command_failed": "plutil Command Failed",
"start_patching": "Starting Patching getMachineId",
"macos_uuid_update_failed": "macOS UUID Update Failed",
"current_version": "Current Cursor Version: {version}",
"patch_completed": "Patching getMachineId Completed",
"patch_failed": "Patching getMachineId Failed: {error}",
"version_check_passed": "Cursor Version Check Passed",
"file_modified": "File Modified"
}, },
"register": { "register": {
"title": "Cursor Registration Tool", "title": "Cursor Registration Tool",
"start": "Starting Registration Process", "start": "Starting Registration Process",
"handling_turnstile": "Handling Turnstile",
"retry_verification": "Retry Verification",
"detect_turnstile": "Detect Turnstile",
"verification_success": "Verification Success",
"starting_browser": "Starting Browser",
"form_success": "Form Success",
"browser_started": "Browser Started",
"waiting_for_second_verification": "Waiting for Second Verification",
"waiting_for_verification_code": "Waiting for Verification Code",
"password_success": "Password Set Successfully",
"password_error": "Password Set Failed: {error}",
"waiting_for_page_load": "Waiting for Page Load",
"first_verification_passed": "First Verification Passed",
"mailbox": "Successfully Entered Mailbox", "mailbox": "Successfully Entered Mailbox",
"register_start": "Start Register", "register_start": "Start Register",
"form_submitted": "Form Submitted, Start Verification...",
"filling_form": "Fill Form", "filling_form": "Fill Form",
"visiting_url": "Visiting URL",
"basic_info": "Basic Info Submitted", "basic_info": "Basic Info Submitted",
"handle_turnstile": "Handle Turnstile", "handle_turnstile": "Handle Turnstile",
"no_turnstile": "Not Detect Turnstile", "no_turnstile": "Not Detect Turnstile",
@@ -90,7 +122,8 @@
"save_account_info_failed": "Save Account Info Failed", "save_account_info_failed": "Save Account Info Failed",
"get_email_address": "Get Email Address", "get_email_address": "Get Email Address",
"update_cursor_auth_info": "Update Cursor Auth Info", "update_cursor_auth_info": "Update Cursor Auth Info",
"register_process_error": "Register Process Error: {error}" "register_process_error": "Register Process Error: {error}",
"setting_password": "Setting Password"
}, },
"auth": { "auth": {
"title": "Cursor Auth Manager", "title": "Cursor Auth Manager",
@@ -107,10 +140,12 @@
"reset_machine_id": "Reset Machine ID", "reset_machine_id": "Reset Machine ID",
"database_connection_closed": "Database Connection Closed", "database_connection_closed": "Database Connection Closed",
"database_updated_successfully": "Database Updated Successfully", "database_updated_successfully": "Database Updated Successfully",
"connected_to_database": "Connected to Database" "connected_to_database": "Connected to Database",
"updating_pair": "Updating Key-Value Pair"
}, },
"control": { "control": {
"generate_email": "Generating New Email", "generate_email": "Generating New Email",
"blocked_domain": "Blocked Domain",
"select_domain": "Selecting Random Domain", "select_domain": "Selecting Random Domain",
"copy_email": "Copying Email Address", "copy_email": "Copying Email Address",
"enter_mailbox": "Entering Mailbox", "enter_mailbox": "Entering Mailbox",
@@ -136,6 +171,27 @@
"get_cursor_session_token": "Get Cursor Session Token", "get_cursor_session_token": "Get Cursor Session Token",
"get_cursor_session_token_success": "Get Cursor Session Token Success", "get_cursor_session_token_success": "Get Cursor Session Token Success",
"get_cursor_session_token_failed": "Get Cursor Session Token Failed", "get_cursor_session_token_failed": "Get Cursor Session Token Failed",
"save_token_failed": "Save Token Failed" "save_token_failed": "Save Token Failed",
"database_updated_successfully": "Database Updated Successfully",
"database_connection_closed": "Database Connection Closed",
"no_valid_verification_code": "No Valid Verification Code"
},
"email": {
"starting_browser": "Starting Browser",
"visiting_site": "Visiting smailpro.com",
"create_success": "Email Created Successfully",
"create_failed": "Failed to Create Email",
"create_error": "Email Creation Error: {error}",
"refreshing": "Refreshing Email",
"refresh_success": "Email Refreshed Successfully",
"refresh_error": "Email Refresh Error: {error}",
"refresh_button_not_found": "Refresh Button Not Found",
"verification_found": "Verification Found",
"verification_not_found": "Verification Not Found",
"verification_error": "Verification Error: {error}",
"verification_code_found": "Verification Code Found",
"verification_code_not_found": "Verification Code Not Found",
"verification_code_error": "Verification Code Error: {error}",
"address": "Email Address"
} }
} }

View File

@@ -26,13 +26,66 @@
"timeout": "以下进程未能在规定时间内关闭: {pids}", "timeout": "以下进程未能在规定时间内关闭: {pids}",
"error": "关闭 Cursor 进程时发生错误: {error}" "error": "关闭 Cursor 进程时发生错误: {error}"
}, },
"reset": {
"title": "Cursor 机器标识重置工具",
"checking": "检查配置文件",
"not_found": "配置文件未找到",
"no_permission": "无法读取或写入配置文件,请检查文件权限",
"reading": "读取当前配置",
"creating_backup": "创建配置备份",
"backup_exists": "备份文件已存在,跳过备份步骤",
"generating": "生成新机器标识",
"saving_json": "保存新配置到JSON",
"success": "机器标识重置成功",
"new_id": "新机器标识",
"permission_error": "权限错误: {error}",
"run_as_admin": "请尝试以管理员身份运行此程序",
"process_error": "重置进程错误: {error}",
"updating_sqlite": "更新SQLite数据库",
"updating_pair": "更新键值对",
"sqlite_success": "SQLite数据库更新成功",
"sqlite_error": "SQLite数据库更新失败: {error}",
"press_enter": "按回车键退出",
"updating_system_ids": "更新系统ID",
"system_ids_updated": "系统ID更新成功",
"system_ids_update_failed": "系统ID更新失败: {error}",
"unsupported_os": "不支持的操作系统: {os}",
"linux_path_not_found": "Linux路径未找到",
"windows_guid_updated": "Windows GUID更新成功",
"windows_permission_denied": "Windows权限拒绝",
"windows_guid_update_failed": "Windows GUID更新失败",
"macos_uuid_updated": "macOS UUID更新成功",
"plutil_command_failed": "plutil命令失败",
"macos_uuid_update_failed": "macOS UUID更新失败",
"start_patching": "开始修补getMachineId",
"current_version": "当前Cursor版本: {version}",
"patch_completed": "getMachineId修补完成",
"patch_failed": "getMachineId修补失败: {error}",
"version_check_passed": "Cursor版本检查通过",
"file_modified": "文件已修改"
},
"register": { "register": {
"title": "Cursor 注册工具", "title": "Cursor 注册工具",
"start": "开始注册流程", "start": "开始注册流程",
"browser_started": "浏览器已启动",
"password_success": "密码设置完成",
"password_error": "密码设置失败: {error}",
"waiting_for_page_load": "等待页面加载",
"mailbox": "成功进入邮箱", "mailbox": "成功进入邮箱",
"waiting_for_second_verification": "等待第二阶段验证",
"waiting_for_verification_code": "等待验证码",
"first_verification_passed": "第一阶段验证通过",
"register_start": "开始注册流程", "register_start": "开始注册流程",
"form_submitted": "表单已提交,开始验证...",
"filling_form": "填写注册信息", "filling_form": "填写注册信息",
"visiting_url": "访问URL",
"basic_info": "基本信息提交完成", "basic_info": "基本信息提交完成",
"handling_turnstile": "处理 Turnstile 验证",
"retry_verification": "重试验证",
"detect_turnstile": "检测 Turnstile 验证",
"verification_success": "验证成功",
"starting_browser": "启动浏览器",
"form_success": "表单提交成功",
"handle_turnstile": "处理 Turnstile 验证", "handle_turnstile": "处理 Turnstile 验证",
"no_turnstile": "未检测到 Turnstile 验证", "no_turnstile": "未检测到 Turnstile 验证",
"turnstile_passed": "验证通过", "turnstile_passed": "验证通过",
@@ -68,7 +121,9 @@
"account_info_saved": "账户信息已保存", "account_info_saved": "账户信息已保存",
"save_account_info_failed": "保存账户信息失败", "save_account_info_failed": "保存账户信息失败",
"get_email_address": "获取邮箱地址", "get_email_address": "获取邮箱地址",
"register_process_error": "注册流程错误: {error}" "register_process_error": "注册流程错误: {error}",
"update_cursor_auth_info": "更新Cursor认证信息",
"setting_password": "设置密码"
}, },
"auth": { "auth": {
"title": "Cursor 认证管理器", "title": "Cursor 认证管理器",
@@ -81,13 +136,18 @@
"auth_update_failed": "认证信息更新失败: {error}", "auth_update_failed": "认证信息更新失败: {error}",
"auth_file_created": "认证文件已创建", "auth_file_created": "认证文件已创建",
"auth_file_create_failed": "认证文件创建失败: {error}", "auth_file_create_failed": "认证文件创建失败: {error}",
"press_enter": "按回车键退出" "press_enter": "按回车键退出",
"connected_to_database": "已连接到数据库",
"database_updated_successfully": "数据库更新成功",
"database_connection_closed": "数据库连接已关闭",
"updating_pair": "更新键值对"
}, },
"control": { "control": {
"generate_email": "生成新邮箱", "generate_email": "生成新邮箱",
"select_domain": "选择随机域名", "select_domain": "选择随机域名",
"copy_email": "复制邮箱地址", "copy_email": "复制邮箱地址",
"enter_mailbox": "进入邮箱", "enter_mailbox": "进入邮箱",
"blocked_domain": "被屏蔽的域名",
"refresh_mailbox": "刷新邮箱", "refresh_mailbox": "刷新邮箱",
"check_verification": "检查验证码", "check_verification": "检查验证码",
"verification_found": "找到验证码", "verification_found": "找到验证码",
@@ -110,6 +170,25 @@
"get_cursor_session_token": "获取Cursor Session Token", "get_cursor_session_token": "获取Cursor Session Token",
"get_cursor_session_token_success": "获取Cursor Session Token成功", "get_cursor_session_token_success": "获取Cursor Session Token成功",
"get_cursor_session_token_failed": "获取Cursor Session Token失败", "get_cursor_session_token_failed": "获取Cursor Session Token失败",
"save_token_failed": "保存Token失败" "save_token_failed": "保存Token失败",
"no_valid_verification_code": "没有有效的验证码"
},
"email": {
"starting_browser": "启动浏览器",
"visiting_site": "访问 smailpro.com",
"create_success": "邮箱创建成功",
"create_failed": "邮箱创建失败",
"create_error": "邮箱创建错误: {error}",
"refreshing": "刷新邮箱",
"refresh_success": "邮箱刷新成功",
"refresh_error": "邮箱刷新错误: {error}",
"refresh_button_not_found": "未找到刷新按钮",
"verification_found": "找到验证码",
"verification_not_found": "未找到验证码",
"verification_error": "验证错误: {error}",
"verification_code_found": "找到验证码",
"verification_code_not_found": "未找到验证码",
"verification_code_error": "验证码错误: {error}",
"address": "邮箱地址"
} }
} }

View File

@@ -26,17 +26,70 @@
"timeout": "以下進程未能在規定時間內關閉: {pids}", "timeout": "以下進程未能在規定時間內關閉: {pids}",
"error": "關閉 Cursor 進程時發生錯誤: {error}" "error": "關閉 Cursor 進程時發生錯誤: {error}"
}, },
"reset": {
"title": "Cursor 機器標識重置工具",
"checking": "檢查配置文件",
"not_found": "配置文件未找到",
"no_permission": "無法讀取或寫入配置文件,請檢查文件權限",
"reading": "讀取當前配置",
"creating_backup": "創建配置備份",
"backup_exists": "備份文件已存在,跳過備份步驟",
"generating": "生成新機器標識",
"saving_json": "保存新配置到JSON",
"success": "機器標識重置成功",
"new_id": "新機器標識",
"permission_error": "權限錯誤: {error}",
"run_as_admin": "請嘗試以管理員身份運行此程序",
"process_error": "重置進程錯誤: {error}",
"updating_sqlite": "更新SQLite數據庫",
"updating_pair": "更新鍵值對",
"sqlite_success": "SQLite數據庫更新成功",
"sqlite_error": "SQLite數據庫更新失敗: {error}",
"press_enter": "按回車鍵退出",
"updating_system_ids": "更新系統ID",
"system_ids_updated": "系統ID更新成功",
"system_ids_update_failed": "系統ID更新失敗: {error}",
"unsupported_os": "不支持的操作系統: {os}",
"linux_path_not_found": "Linux路徑未找到",
"windows_guid_updated": "Windows GUID更新成功",
"windows_permission_denied": "Windows權限拒絕",
"windows_guid_update_failed": "Windows GUID更新失敗",
"macos_uuid_updated": "macOS UUID更新成功",
"plutil_command_failed": "plutil命令失敗",
"macos_uuid_update_failed": "macOS UUID更新失敗",
"start_patching": "開始修補getMachineId",
"current_version": "當前Cursor版本: {version}",
"patch_completed": "getMachineId修補完成",
"patch_failed": "getMachineId修補失敗: {error}",
"version_check_passed": "Cursor版本檢查通過",
"file_modified": "文件已修改"
},
"register": { "register": {
"title": "Cursor 註冊工具", "title": "Cursor 註冊工具",
"start": "開始註冊流程", "start": "開始註冊流程",
"mailbox": "成功進入郵箱", "mailbox": "成功進入郵箱",
"browser_started": "瀏覽器已啟動",
"waiting_for_page_load": "等待頁面加載",
"password_success": "密碼設置完成",
"password_error": "密碼設置失敗: {error}",
"visiting_url": "訪問URL",
"first_verification_passed": "第一階段驗證通過",
"register_start": "開始註冊流程", "register_start": "開始註冊流程",
"form_submitted": "表單已提交,開始驗證...",
"waiting_for_second_verification": "等待第二階段驗證",
"filling_form": "填寫註冊信息", "filling_form": "填寫註冊信息",
"basic_info": "基本信息提交完成", "basic_info": "基本信息提交完成",
"handle_turnstile": "處理 Turnstile 驗證", "handle_turnstile": "處理 Turnstile 驗證",
"no_turnstile": "未檢測到 Turnstile 驗證", "no_turnstile": "未檢測到 Turnstile 驗證",
"turnstile_passed": "驗證通過", "turnstile_passed": "驗證通過",
"verification_start": "開始獲取驗證碼", "verification_start": "開始獲取驗證碼",
"waiting_for_verification_code": "等待驗證碼",
"handling_turnstile": "處理 Turnstile 驗證",
"retry_verification": "重試驗證",
"detect_turnstile": "檢測 Turnstile 驗證",
"verification_success": "驗證成功",
"starting_browser": "啟動瀏覽器",
"form_success": "表單提交成功",
"verification_timeout": "獲取驗證碼超時", "verification_timeout": "獲取驗證碼超時",
"verification_not_found": "未找到驗證碼", "verification_not_found": "未找到驗證碼",
"try_get_code": "第 {attempt} 次嘗試獲取驗證碼 | 剩餘時間: {time}秒", "try_get_code": "第 {attempt} 次嘗試獲取驗證碼 | 剩餘時間: {time}秒",
@@ -68,7 +121,9 @@
"account_info_saved": "賬戶信息已保存", "account_info_saved": "賬戶信息已保存",
"save_account_info_failed": "保存賬戶信息失敗", "save_account_info_failed": "保存賬戶信息失敗",
"get_email_address": "獲取郵箱地址", "get_email_address": "獲取郵箱地址",
"register_process_error": "註冊流程錯誤: {error}" "register_process_error": "註冊流程錯誤: {error}",
"update_cursor_auth_info": "更新Cursor認證信息",
"setting_password": "設置密碼"
}, },
"auth": { "auth": {
"title": "Cursor 認證管理器", "title": "Cursor 認證管理器",
@@ -81,7 +136,11 @@
"auth_update_failed": "認證信息更新失敗: {error}", "auth_update_failed": "認證信息更新失敗: {error}",
"auth_file_created": "認證文件已創建", "auth_file_created": "認證文件已創建",
"auth_file_create_failed": "認證文件創建失敗: {error}", "auth_file_create_failed": "認證文件創建失敗: {error}",
"press_enter": "按回車鍵退出" "press_enter": "按回車鍵退出",
"connected_to_database": "已連接到數據庫",
"database_updated_successfully": "數據庫更新成功",
"database_connection_closed": "數據庫連接已關閉",
"updating_pair": "更新鍵值對"
}, },
"control": { "control": {
"generate_email": "生成新郵箱", "generate_email": "生成新郵箱",
@@ -110,6 +169,27 @@
"get_cursor_session_token": "獲取Cursor Session Token", "get_cursor_session_token": "獲取Cursor Session Token",
"get_cursor_session_token_success": "獲取Cursor Session Token成功", "get_cursor_session_token_success": "獲取Cursor Session Token成功",
"get_cursor_session_token_failed": "獲取Cursor Session Token失敗", "get_cursor_session_token_failed": "獲取Cursor Session Token失敗",
"save_token_failed": "保存Token失敗" "save_token_failed": "保存Token失敗",
} "blocked_domain": "被屏蔽的域名",
"no_valid_verification_code": "沒有有效的驗證碼"
},
"email": {
"starting_browser": "啟動瀏覽器",
"visiting_site": "訪問 smailpro.com",
"create_success": "郵箱創建成功",
"create_failed": "郵箱創建失敗",
"create_error": "郵箱創建錯誤: {error}",
"refreshing": "刷新郵箱",
"refresh_success": "郵箱刷新成功",
"refresh_error": "郵箱刷新錯誤: {error}",
"refresh_button_not_found": "未找到刷新按鈕",
"verification_found": "找到驗證碼",
"verification_not_found": "未找到驗證碼",
"verification_error": "驗證錯誤: {error}",
"verification_code_found": "找到驗證碼",
"verification_code_not_found": "未找到驗證碼",
"verification_code_error": "驗證碼錯誤: {error}",
"address": "郵箱地址"
}
} }

11
logo.py
View File

@@ -2,8 +2,14 @@ from colorama import Fore, Style, init
from dotenv import load_dotenv from dotenv import load_dotenv
import os import os
# 加載環境變量獲取版本號 # 獲取當前腳本所在目錄
load_dotenv() current_dir = os.path.dirname(os.path.abspath(__file__))
# 構建.env文件的完整路徑
env_path = os.path.join(current_dir, '.env')
# 加載環境變量,指定.env文件路徑
load_dotenv(env_path)
# 獲取版本號,如果未找到則使用默認值
version = os.getenv('VERSION', '1.0.0') version = os.getenv('VERSION', '1.0.0')
# 初始化 colorama # 初始化 colorama
@@ -29,6 +35,5 @@ CURSOR_LOGO = f"""
def print_logo(): def print_logo():
print(CURSOR_LOGO) print(CURSOR_LOGO)
if __name__ == "__main__": if __name__ == "__main__":
print_logo() print_logo()

16
main.py
View File

@@ -42,11 +42,17 @@ class Translator:
def get(self, key, **kwargs): def get(self, key, **kwargs):
"""获取翻译文本""" """获取翻译文本"""
keys = key.split('.') try:
value = self.translations.get(self.current_language, {}) keys = key.split('.')
for k in keys: value = self.translations.get(self.current_language, {})
value = value.get(k, key) for k in keys:
return value.format(**kwargs) if kwargs else value if isinstance(value, dict):
value = value.get(k, key)
else:
return key # 如果中間值不是字典返回原始key
return value.format(**kwargs) if kwargs else value
except Exception:
return key # 出現任何錯誤時返回原始key
def set_language(self, lang_code): def set_language(self, lang_code):
"""设置当前语言""" """设置当前语言"""

563
new_signup.py Normal file
View File

@@ -0,0 +1,563 @@
from DrissionPage import ChromiumOptions, ChromiumPage
import time
import os
import signal
import random
from colorama import Fore, Style
# 在文件开头添加全局变量
_translator = None
def cleanup_chrome_processes(translator=None):
"""清理所有Chrome相关进程"""
print("\n正在清理Chrome进程...")
try:
if os.name == 'nt':
os.system('taskkill /F /IM chrome.exe /T 2>nul')
os.system('taskkill /F /IM chromedriver.exe /T 2>nul')
else:
os.system('pkill -f chrome')
os.system('pkill -f chromedriver')
except Exception as e:
if translator:
print(f"{Fore.RED}{translator.get('register.cleanup_error', error=str(e))}{Style.RESET_ALL}")
else:
print(f"清理进程时出错: {e}")
def signal_handler(signum, frame):
"""处理Ctrl+C信号"""
global _translator
if _translator:
print(f"{Fore.CYAN}{_translator.get('register.exit_signal')}{Style.RESET_ALL}")
else:
print("\n接收到退出信号,正在关闭...")
cleanup_chrome_processes(_translator)
os._exit(0)
def simulate_human_input(page, url, translator=None):
"""访问网址"""
if translator:
print(f"{Fore.CYAN}🚀 {translator.get('register.visiting_url')}: {url}{Style.RESET_ALL}")
else:
print("正在访问网址...")
# 先访问空白页面
page.get('about:blank')
time.sleep(random.uniform(1.0, 2.0))
# 访问目标页面
page.get(url)
time.sleep(random.uniform(2.0, 3.0)) # 等待页面加载
def fill_signup_form(page, first_name, last_name, email, translator=None):
"""填写注册表单"""
try:
if translator:
print(f"{Fore.CYAN}📧 {translator.get('register.filling_form')}{Style.RESET_ALL}")
else:
print("\n正在填写注册表单...")
# 填写名字
first_name_input = page.ele("@name=first_name")
if first_name_input:
first_name_input.input(first_name)
time.sleep(random.uniform(0.5, 1.0))
# 填写姓氏
last_name_input = page.ele("@name=last_name")
if last_name_input:
last_name_input.input(last_name)
time.sleep(random.uniform(0.5, 1.0))
# 填写邮箱
email_input = page.ele("@name=email")
if email_input:
email_input.input(email)
time.sleep(random.uniform(0.5, 1.0))
# 点击提交按钮
submit_button = page.ele("@type=submit")
if submit_button:
submit_button.click()
time.sleep(random.uniform(2.0, 3.0))
if translator:
print(f"{Fore.GREEN}{translator.get('register.form_success')}{Style.RESET_ALL}")
else:
print("表单填写完成")
return True
except Exception as e:
if translator:
print(f"{Fore.RED}{translator.get('register.form_error', error=str(e))}{Style.RESET_ALL}")
else:
print(f"填写表单时出错: {e}")
return False
def setup_driver(translator=None):
"""设置浏览器驱动"""
co = ChromiumOptions()
# 使用无痕模式
co.set_argument("--incognito")
co.set_argument("--headless=new")
# 设置随机端口
co.auto_port()
# 使用有头模式
co.headless(False)
try:
# 加载插件
extension_path = os.path.join(os.getcwd(), "turnstilePatch")
if os.path.exists(extension_path):
co.set_argument("--allow-extensions-in-incognito")
co.add_extension(extension_path)
except Exception as e:
if translator:
print(f"{Fore.RED}{translator.get('register.extension_load_error', error=str(e))}{Style.RESET_ALL}")
else:
print(f"加载插件失败: {e}")
if translator:
print(f"{Fore.CYAN}🚀 {translator.get('register.starting_browser')}{Style.RESET_ALL}")
else:
print("正在启动浏览器...")
page = ChromiumPage(co)
return page
def handle_turnstile(page, translator=None):
"""处理 Turnstile 验证"""
try:
if translator:
print(f"{Fore.CYAN}🔄 {translator.get('register.handling_turnstile')}{Style.RESET_ALL}")
else:
print("\n正在处理 Turnstile 验证...")
max_retries = 2
retry_count = 0
while retry_count < max_retries:
retry_count += 1
if translator:
print(f"{Fore.CYAN}🔄 {translator.get('register.retry_verification', attempt=retry_count)}{Style.RESET_ALL}")
else:
print(f"{retry_count} 次尝试验证...")
try:
# 尝试重置 turnstile
page.run_js("try { turnstile.reset() } catch(e) { }")
time.sleep(2)
# 定位验证框元素
challenge_check = (
page.ele("@id=cf-turnstile", timeout=2)
.child()
.shadow_root.ele("tag:iframe")
.ele("tag:body")
.sr("tag:input")
)
if challenge_check:
if translator:
print(f"{Fore.CYAN}🔄 {translator.get('register.detect_turnstile')}{Style.RESET_ALL}")
else:
print("检测到验证框...")
# 随机延时后点击验证
time.sleep(random.uniform(1, 3))
challenge_check.click()
time.sleep(2)
# 检查验证结果
if check_verification_success(page, translator):
if translator:
print(f"{Fore.GREEN}{translator.get('register.verification_success')}{Style.RESET_ALL}")
else:
print("验证通过!")
return True
except Exception as e:
if translator:
print(f"{Fore.RED}{translator.get('register.verification_failed')}{Style.RESET_ALL}")
else:
print(f"验证尝试失败: {e}")
# 检查是否已经验证成功
if check_verification_success(page, translator):
if translator:
print(f"{Fore.GREEN}{translator.get('register.verification_success')}{Style.RESET_ALL}")
else:
print("验证通过!")
return True
time.sleep(random.uniform(1, 2))
if translator:
print(f"{Fore.RED}{translator.get('register.verification_failed')}{Style.RESET_ALL}")
else:
print("超出最大重试次数")
return False
except Exception as e:
if translator:
print(f"{Fore.RED}{translator.get('register.verification_error', error=str(e))}{Style.RESET_ALL}")
else:
print(f"验证过程出错: {e}")
return False
def check_verification_success(page, translator=None):
"""检查验证是否成功"""
try:
# 检查是否存在后续表单元素,这表示验证已通过
if (page.ele("@name=password", timeout=0.5) or
page.ele("@name=email", timeout=0.5) or
page.ele("@data-index=0", timeout=0.5) or
page.ele("Account Settings", timeout=0.5)):
return True
# 检查是否出现错误消息
error_messages = [
'xpath://div[contains(text(), "Can\'t verify the user is human")]',
'xpath://div[contains(text(), "Error: 600010")]',
'xpath://div[contains(text(), "Please try again")]'
]
for error_xpath in error_messages:
if page.ele(error_xpath):
return False
return False
except:
return False
def generate_password(length=12):
"""生成随机密码"""
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"
return ''.join(random.choices(chars, k=length))
def fill_password(page, password, translator=None):
"""填写密码"""
try:
if translator:
print(f"{Fore.CYAN}🔑 {translator.get('register.setting_password')}{Style.RESET_ALL}")
else:
print("\n正在设置密码...")
password_input = page.ele("@name=password")
if password_input:
password_input.input(password)
time.sleep(random.uniform(0.5, 1.0))
submit_button = page.ele("@type=submit")
if submit_button:
submit_button.click()
time.sleep(random.uniform(2.0, 3.0))
if translator:
print(f"{Fore.GREEN}{translator.get('register.password_success')}{Style.RESET_ALL}")
else:
print(f"密码设置完成: {password}")
return True
except Exception as e:
if translator:
print(f"{Fore.RED}{translator.get('register.password_error', error=str(e))}{Style.RESET_ALL}")
else:
print(f"设置密码时出错: {e}")
return False
def handle_verification_code(browser_tab, email_tab, controller, email, password, translator=None):
"""处理验证码"""
try:
if translator:
print(f"\n{Fore.CYAN}{translator.get('register.waiting_for_verification_code')}{Style.RESET_ALL}")
else:
print("\n等待并获取验证码...")
# 添加调试信息
print(f"\n{Fore.CYAN}DEBUG: email_tab exists: {email_tab is not None}{Style.RESET_ALL}")
time.sleep(5) # 等待验证码邮件
# 使用已有的 email_tab 刷新邮箱
email_tab.refresh_inbox()
time.sleep(3)
# 检查邮箱是否有验证码邮件
if email_tab.check_for_cursor_email():
verification_code = email_tab.get_verification_code()
if verification_code:
# 在注册页面填写验证码
for i, digit in enumerate(verification_code):
browser_tab.ele(f"@data-index={i}").input(digit)
time.sleep(random.uniform(0.1, 0.3))
if translator:
print(f"{Fore.GREEN}{translator.get('register.verification_success')}{Style.RESET_ALL}")
else:
print("验证码填写完成")
time.sleep(3)
# 处理最后一次 Turnstile 验证
if handle_turnstile(browser_tab, translator):
if translator:
print(f"{Fore.GREEN}{translator.get('register.verification_success')}{Style.RESET_ALL}")
else:
print("最后一次验证通过!")
time.sleep(2)
# 访问设置页面
if translator:
print(f"{Fore.CYAN}🔑 {translator.get('register.visiting_url')}: https://www.cursor.com/settings{Style.RESET_ALL}")
else:
print("访问设置页面...")
browser_tab.get("https://www.cursor.com/settings")
time.sleep(3) # 等待页面加载
return True
else:
print("最后一次验证失败")
return False
return False
# 获取验证码,设置超时
verification_code = None
max_attempts = 20
retry_interval = 10
start_time = time.time()
timeout = 160
if translator:
print(f"{Fore.CYAN}{translator.get('register.start_getting_verification_code')}{Style.RESET_ALL}")
else:
print("开始获取验证码...")
for attempt in range(max_attempts):
# 检查是否超时
if time.time() - start_time > timeout:
if translator:
print(f"{Fore.RED}{translator.get('register.verification_timeout')}{Style.RESET_ALL}")
else:
print("获取验证码超时...")
break
verification_code = controller.get_verification_code()
if verification_code:
if translator:
print(f"{Fore.GREEN}{translator.get('register.verification_success')}{Style.RESET_ALL}")
else:
print(f"成功获取验证码: {verification_code}")
break
remaining_time = int(timeout - (time.time() - start_time))
if translator:
print(f"{Fore.CYAN}{translator.get('register.try_get_code', attempt=attempt + 1, time=remaining_time)}{Style.RESET_ALL}")
else:
print(f"{attempt + 1} 次尝试获取验证码,剩余时间: {remaining_time}秒...")
# 刷新邮箱
email_tab.refresh_inbox()
time.sleep(retry_interval)
if verification_code:
# 在注册页面填写验证码
for i, digit in enumerate(verification_code):
browser_tab.ele(f"@data-index={i}").input(digit)
time.sleep(random.uniform(0.1, 0.3))
if translator:
print(f"{Fore.GREEN}{translator.get('register.verification_success')}{Style.RESET_ALL}")
else:
print("验证码填写完成")
time.sleep(3)
# 处理最后一次 Turnstile 验证
if handle_turnstile(browser_tab, translator):
if translator:
print(f"{Fore.GREEN}{translator.get('register.verification_success')}{Style.RESET_ALL}")
else:
print("最后一次验证通过!")
time.sleep(2)
# 直接访问设置页面
if translator:
print(f"{Fore.CYAN}{translator.get('register.visiting_url')}: https://www.cursor.com/settings{Style.RESET_ALL}")
else:
print("访问设置页面...")
browser_tab.get("https://www.cursor.com/settings")
time.sleep(3) # 等待页面加载
# 直接返回成功,让 cursor_register.py 处理账户信息获取
return True
else:
if translator:
print(f"{Fore.RED}{translator.get('register.verification_failed')}{Style.RESET_ALL}")
else:
print("最后一次验证失败")
return False
return False
except Exception as e:
if translator:
print(f"{Fore.RED}{translator.get('register.verification_error', error=str(e))}{Style.RESET_ALL}")
else:
print(f"处理验证码时出错: {e}")
return False
def handle_sign_in(browser_tab, email, password, translator=None):
"""处理登录流程"""
try:
# 检查是否在登录页面
sign_in_header = browser_tab.ele('xpath://h1[contains(text(), "Sign in")]')
if not sign_in_header:
return True # 如果不是登录页面,说明已经登录成功
print(f"{Fore.CYAN}检测到登录页面,开始登录...{Style.RESET_ALL}")
# 填写邮箱
email_input = browser_tab.ele('@name=email')
if email_input:
email_input.input(email)
time.sleep(1)
# 点击 Continue
continue_button = browser_tab.ele('xpath://button[contains(@class, "BrandedButton") and text()="Continue"]')
if continue_button:
continue_button.click()
time.sleep(2)
# 处理 Turnstile 验证
if handle_turnstile(browser_tab, translator):
# 填写密码
password_input = browser_tab.ele('@name=password')
if password_input:
password_input.input(password)
time.sleep(1)
# 点击 Sign in
sign_in_button = browser_tab.ele('xpath://button[@name="intent" and @value="password"]')
if sign_in_button:
sign_in_button.click()
time.sleep(2)
# 处理最后一次 Turnstile 验证
if handle_turnstile(browser_tab, translator):
print(f"{Fore.GREEN}登录成功!{Style.RESET_ALL}")
time.sleep(3)
return True
print(f"{Fore.RED}登录失败{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}登录过程出错: {str(e)}{Style.RESET_ALL}")
return False
def main(email=None, password=None, first_name=None, last_name=None, email_tab=None, controller=None, translator=None):
"""主函数,可以接收账号信息、邮箱标签页和翻译器"""
global _translator
_translator = translator # 保存到全局变量
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
page = None
success = False
try:
page = setup_driver(translator)
if translator:
print(f"{Fore.CYAN}🚀 {translator.get('register.browser_started')}{Style.RESET_ALL}")
else:
print("浏览器已启动")
# 访问注册页面
url = "https://authenticator.cursor.sh/sign-up"
if translator:
print(f"\n{Fore.CYAN}{translator.get('register.visiting_url')}: {url}{Style.RESET_ALL}")
else:
print(f"\n正在访问: {url}")
# 访问页面
simulate_human_input(page, url, translator)
if translator:
print(f"{Fore.CYAN}{translator.get('register.waiting_for_page_load')}{Style.RESET_ALL}")
else:
print("等待页面加载...")
time.sleep(5)
# 如果没有提供账号信息,则生成随机信息
if not all([email, password, first_name, last_name]):
first_name = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz', k=6)).capitalize()
last_name = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz', k=6)).capitalize()
email = f"{first_name.lower()}{random.randint(100,999)}@example.com"
password = generate_password()
# 保存账号信息
with open('test_accounts.txt', 'a', encoding='utf-8') as f:
f.write(f"\n{'='*50}\n")
f.write(f"Email: {email}\n")
f.write(f"Password: {password}\n")
f.write(f"{'='*50}\n")
# 填写表单
if fill_signup_form(page, first_name, last_name, email, translator):
if translator:
print(f"\n{Fore.GREEN}{translator.get('register.form_submitted')}{Style.RESET_ALL}")
else:
print("\n表单已提交,开始验证...")
# 处理第一次 Turnstile 验证
if handle_turnstile(page, translator):
if translator:
print(f"\n{Fore.GREEN}{translator.get('register.first_verification_passed')}{Style.RESET_ALL}")
else:
print("\n第一阶段验证通过!")
# 填写密码
if fill_password(page, password, translator):
if translator:
print(f"\n{Fore.CYAN}{translator.get('register.waiting_for_second_verification')}{Style.RESET_ALL}")
else:
print("\n等待第二次验证...")
time.sleep(2)
# 处理第二次 Turnstile 验证
if handle_turnstile(page, translator):
if translator:
print(f"\n{Fore.CYAN}{translator.get('register.waiting_for_verification_code')}{Style.RESET_ALL}")
else:
print("\n开始处理验证码...")
if handle_verification_code(page, email_tab, controller, email, password, translator):
if translator:
print(f"\n{Fore.GREEN}{translator.get('register.verification_success')}{Style.RESET_ALL}")
else:
print("\n注册流程完成!")
success = True
return True, page # 返回成功状态和浏览器实例
else:
print("\n验证码处理失败")
else:
print("\n第二次验证失败")
else:
print("\n密码设置失败")
else:
print("\n第一次验证失败")
return False, None
except Exception as e:
print(f"发生错误: {e}")
return False, None
finally:
if page and not success: # 只在失败时清理
try:
page.quit()
except:
pass
cleanup_chrome_processes(translator)
if __name__ == "__main__":
main() # 直接运行时不传参数,使用随机生成的信息

226
new_tempemail.py Normal file
View File

@@ -0,0 +1,226 @@
from DrissionPage import ChromiumPage, ChromiumOptions
import time
import os
import sys
from colorama import Fore, Style, init
# 初始化 colorama
init()
class NewTempEmail:
def __init__(self, translator=None):
self.translator = translator
self.page = None
self.setup_browser()
def get_extension_block(self):
"""获取插件路径"""
root_dir = os.getcwd()
extension_path = os.path.join(root_dir, "uBlock0.chromium")
if hasattr(sys, "_MEIPASS"):
extension_path = os.path.join(sys._MEIPASS, "uBlock0.chromium")
if not os.path.exists(extension_path):
raise FileNotFoundError(f"插件不存在: {extension_path}")
return extension_path
def setup_browser(self):
"""设置浏览器"""
try:
if self.translator:
print(f"{Fore.CYAN} {self.translator.get('email.starting_browser')}{Style.RESET_ALL}")
else:
print(f"{Fore.CYAN} 正在启动浏览器...{Style.RESET_ALL}")
# 创建浏览器选项
co = ChromiumOptions()
co.set_argument("--headless=new")
co.auto_port() # 自动设置端口
# 加载 uBlock 插件
try:
extension_path = self.get_extension_block()
co.set_argument("--allow-extensions-in-incognito")
co.add_extension(extension_path)
except Exception as e:
if self.translator:
print(f"{Fore.YELLOW}⚠️ {self.translator.get('email.extension_load_error')}: {str(e)}{Style.RESET_ALL}")
else:
print(f"{Fore.YELLOW}⚠️ 加载插件失败: {str(e)}{Style.RESET_ALL}")
self.page = ChromiumPage(co)
return True
except Exception as e:
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.browser_start_error')}: {str(e)}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 启动浏览器失败: {str(e)}{Style.RESET_ALL}")
return False
def create_email(self):
"""创建临时邮箱"""
try:
if self.translator:
print(f"{Fore.CYAN} {self.translator.get('email.visiting_site')}{Style.RESET_ALL}")
else:
print(f"{Fore.CYAN} 正在访问 smailpro.com...{Style.RESET_ALL}")
# 访问网站
self.page.get("https://smailpro.com/")
time.sleep(2)
# 点击创建邮箱按钮
create_button = self.page.ele('xpath://button[@title="Create temporary email"]')
if create_button:
create_button.click()
time.sleep(1)
# 点击弹窗中的 Create 按钮
modal_create_button = self.page.ele('xpath://button[contains(text(), "Create")]')
if modal_create_button:
modal_create_button.click()
time.sleep(2)
# 获取邮箱地址 - 修改选择器
email_div = self.page.ele('xpath://div[@class="text-base sm:text-lg md:text-xl text-gray-700"]')
if email_div:
email = email_div.text.strip()
if '@' in email: # 验证是否是有效的邮箱地址
if self.translator:
print(f"{Fore.GREEN}{self.translator.get('email.create_success')}: {email}{Style.RESET_ALL}")
else:
print(f"{Fore.GREEN}✅ 创建邮箱成功: {email}{Style.RESET_ALL}")
return email
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.create_failed')}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 创建邮箱失败{Style.RESET_ALL}")
return None
except Exception as e:
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.create_error')}: {str(e)}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 创建邮箱出错: {str(e)}{Style.RESET_ALL}")
return None
def close(self):
"""关闭浏览器"""
if self.page:
self.page.quit()
def refresh_inbox(self):
"""刷新邮箱"""
try:
if self.translator:
print(f"{Fore.CYAN}🔄 {self.translator.get('email.refreshing')}{Style.RESET_ALL}")
else:
print(f"{Fore.CYAN}🔄 正在刷新邮箱...{Style.RESET_ALL}")
# 点击刷新按钮
refresh_button = self.page.ele('xpath://button[@id="refresh"]')
if refresh_button:
refresh_button.click()
time.sleep(2) # 等待刷新完成
if self.translator:
print(f"{Fore.GREEN}{self.translator.get('email.refresh_success')}{Style.RESET_ALL}")
else:
print(f"{Fore.GREEN}✅ 邮箱刷新成功{Style.RESET_ALL}")
return True
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.refresh_button_not_found')}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 未找到刷新按钮{Style.RESET_ALL}")
return False
except Exception as e:
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.refresh_error')}: {str(e)}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 刷新邮箱出错: {str(e)}{Style.RESET_ALL}")
return False
def check_for_cursor_email(self):
"""检查是否有 Cursor 的验证邮件"""
try:
# 查找验证邮件 - 使用更精确的选择器
email_div = self.page.ele('xpath://div[contains(@class, "p-2") and contains(@class, "cursor-pointer") and contains(@class, "bg-white") and contains(@class, "shadow") and .//b[text()="no-reply@cursor.sh"] and .//span[text()="Verify your email address"]]')
if email_div:
if self.translator:
print(f"{Fore.GREEN}{self.translator.get('email.verification_found')}{Style.RESET_ALL}")
else:
print(f"{Fore.GREEN}✅ 找到验证邮件{Style.RESET_ALL}")
# 使用 JavaScript 点击元素
self.page.run_js('arguments[0].click()', email_div)
time.sleep(2) # 等待邮件内容加载
return True
if self.translator:
print(f"{Fore.YELLOW}⚠️ {self.translator.get('email.verification_not_found')}{Style.RESET_ALL}")
else:
print(f"{Fore.YELLOW}⚠️ 未找到验证邮件{Style.RESET_ALL}")
return False
except Exception as e:
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.verification_error')}: {str(e)}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 检查验证邮件出错: {str(e)}{Style.RESET_ALL}")
return False
def get_verification_code(self):
"""获取验证码"""
try:
# 查找验证码元素
code_element = self.page.ele('xpath://td//div[contains(@style, "font-size:28px") and contains(@style, "letter-spacing:2px")]')
if code_element:
code = code_element.text.strip()
if code.isdigit() and len(code) == 6:
if self.translator:
print(f"{Fore.GREEN}{self.translator.get('email.verification_code_found')}: {code}{Style.RESET_ALL}")
else:
print(f"{Fore.GREEN}✅ 获取验证码成功: {code}{Style.RESET_ALL}")
return code
if self.translator:
print(f"{Fore.YELLOW}⚠️ {self.translator.get('email.verification_code_not_found')}{Style.RESET_ALL}")
else:
print(f"{Fore.YELLOW}⚠️ 未找到有效的验证码{Style.RESET_ALL}")
return None
except Exception as e:
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.verification_code_error')}: {str(e)}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 获取验证码出错: {str(e)}{Style.RESET_ALL}")
return None
def main(translator=None):
temp_email = NewTempEmail(translator)
try:
email = temp_email.create_email()
if email:
if translator:
print(f"\n{Fore.CYAN}📧 {translator.get('email.address')}: {email}{Style.RESET_ALL}")
else:
print(f"\n{Fore.CYAN}📧 临时邮箱地址: {email}{Style.RESET_ALL}")
# 测试刷新功能
while True:
if translator:
choice = input(f"\n{translator.get('email.refresh_prompt')}: ").lower()
else:
choice = input("\n按 R 刷新邮箱,按 Q 退出: ").lower()
if choice == 'r':
temp_email.refresh_inbox()
elif choice == 'q':
break
finally:
temp_email.close()
if __name__ == "__main__":
main()

View File

@@ -5,7 +5,11 @@ import uuid
import hashlib import hashlib
import shutil import shutil
import sqlite3 import sqlite3
import platform
import re
import tempfile
from colorama import Fore, Style, init from colorama import Fore, Style, init
from typing import Tuple
# 初始化colorama # 初始化colorama
init() init()
@@ -20,6 +24,173 @@ EMOJI = {
"RESET": "🔄", "RESET": "🔄",
} }
def get_cursor_paths(translator=None) -> Tuple[str, str]:
"""根据不同操作系统获取 Cursor 相关路径"""
system = platform.system()
paths_map = {
"Darwin": {
"base": "/Applications/Cursor.app/Contents/Resources/app",
"package": "package.json",
"main": "out/main.js",
},
"Windows": {
"base": os.path.join(
os.getenv("LOCALAPPDATA", ""), "Programs", "Cursor", "resources", "app"
),
"package": "package.json",
"main": "out/main.js",
},
"Linux": {
"bases": ["/opt/Cursor/resources/app", "/usr/share/cursor/resources/app"],
"package": "package.json",
"main": "out/main.js",
},
}
if system not in paths_map:
raise OSError(translator.get('reset.unsupported_os', system=system) if translator else f"不支持的操作系统: {system}")
if system == "Linux":
for base in paths_map["Linux"]["bases"]:
pkg_path = os.path.join(base, paths_map["Linux"]["package"])
if os.path.exists(pkg_path):
return (pkg_path, os.path.join(base, paths_map["Linux"]["main"]))
raise OSError(translator.get('reset.linux_path_not_found') if translator else "在 Linux 系统上未找到 Cursor 安装路径")
base_path = paths_map[system]["base"]
return (
os.path.join(base_path, paths_map[system]["package"]),
os.path.join(base_path, paths_map[system]["main"]),
)
def version_check(version: str, min_version: str = "", max_version: str = "", translator=None) -> bool:
"""版本号检查"""
version_pattern = r"^\d+\.\d+\.\d+$"
try:
if not re.match(version_pattern, version):
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.invalid_version_format', version=version)}{Style.RESET_ALL}")
return False
def parse_version(ver: str) -> Tuple[int, ...]:
return tuple(map(int, ver.split(".")))
current = parse_version(version)
if min_version and current < parse_version(min_version):
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.version_too_low', version=version, min_version=min_version)}{Style.RESET_ALL}")
return False
if max_version and current > parse_version(max_version):
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.version_too_high', version=version, max_version=max_version)}{Style.RESET_ALL}")
return False
return True
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.version_check_error', error=str(e))}{Style.RESET_ALL}")
return False
def check_cursor_version(translator) -> bool:
"""检查 Cursor 版本"""
try:
pkg_path, _ = get_cursor_paths(translator)
with open(pkg_path, "r", encoding="utf-8") as f:
version = json.load(f)["version"]
return version_check(version, min_version="0.45.0", translator=translator)
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.check_version_failed', error=str(e))}{Style.RESET_ALL}")
return False
def modify_main_js(main_path: str, translator) -> bool:
"""修改 main.js 文件"""
try:
original_stat = os.stat(main_path)
original_mode = original_stat.st_mode
original_uid = original_stat.st_uid
original_gid = original_stat.st_gid
with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file:
with open(main_path, "r", encoding="utf-8") as main_file:
content = main_file.read()
patterns = {
r"async getMachineId\(\)\{return [^??]+\?\?([^}]+)\}": r"async getMachineId(){return \1}",
r"async getMacMachineId\(\)\{return [^??]+\?\?([^}]+)\}": r"async getMacMachineId(){return \1}",
}
for pattern, replacement in patterns.items():
content = re.sub(pattern, replacement, content)
tmp_file.write(content)
tmp_path = tmp_file.name
shutil.copy2(main_path, main_path + ".old")
shutil.move(tmp_path, main_path)
os.chmod(main_path, original_mode)
if os.name != "nt":
os.chown(main_path, original_uid, original_gid)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.file_modified')}{Style.RESET_ALL}")
return True
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.modify_file_failed', error=str(e))}{Style.RESET_ALL}")
if "tmp_path" in locals():
os.unlink(tmp_path)
return False
def patch_cursor_get_machine_id(translator) -> bool:
"""修补 Cursor getMachineId 函数"""
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.start_patching')}...{Style.RESET_ALL}")
# 获取路径
pkg_path, main_path = get_cursor_paths(translator)
# 检查文件权限
for file_path in [pkg_path, main_path]:
if not os.path.isfile(file_path):
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.file_not_found', path=file_path)}{Style.RESET_ALL}")
return False
if not os.access(file_path, os.W_OK):
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.no_write_permission', path=file_path)}{Style.RESET_ALL}")
return False
# 获取版本号
try:
with open(pkg_path, "r", encoding="utf-8") as f:
version = json.load(f)["version"]
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.current_version', version=version)}{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.read_version_failed', error=str(e))}{Style.RESET_ALL}")
return False
# 检查版本
if not version_check(version, min_version="0.45.0", translator=translator):
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.version_not_supported')}{Style.RESET_ALL}")
return False
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.version_check_passed')}{Style.RESET_ALL}")
# 备份文件
backup_path = main_path + ".bak"
if not os.path.exists(backup_path):
shutil.copy2(main_path, backup_path)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.backup_created', path=backup_path)}{Style.RESET_ALL}")
# 修改文件
if not modify_main_js(main_path, translator):
return False
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.patch_completed')}{Style.RESET_ALL}")
return True
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.patch_failed', error=str(e))}{Style.RESET_ALL}")
return False
class MachineIDResetter: class MachineIDResetter:
def __init__(self, translator=None): def __init__(self, translator=None):
self.translator = translator self.translator = translator
@@ -98,7 +269,7 @@ class MachineIDResetter:
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}{self.translator.get('reset.updating_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()
@@ -109,6 +280,59 @@ class MachineIDResetter:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.sqlite_error', error=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 update_system_ids(self, new_ids):
"""更新系统级别的ID"""
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.updating_system_ids')}...{Style.RESET_ALL}")
if sys.platform.startswith("win"):
self._update_windows_machine_guid()
elif sys.platform == "darwin":
self._update_macos_platform_uuid(new_ids)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.system_ids_updated')}{Style.RESET_ALL}")
return True
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.system_ids_update_failed', error=str(e))}{Style.RESET_ALL}")
return False
def _update_windows_machine_guid(self):
"""更新Windows MachineGuid"""
try:
import winreg
key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Cryptography",
0,
winreg.KEY_WRITE | winreg.KEY_WOW64_64KEY
)
new_guid = str(uuid.uuid4())
winreg.SetValueEx(key, "MachineGuid", 0, winreg.REG_SZ, new_guid)
winreg.CloseKey(key)
print("Windows MachineGuid updated successfully")
except PermissionError:
print("Permission denied: Run as administrator to update Windows MachineGuid")
raise
except Exception as e:
print(f"Failed to update Windows MachineGuid: {e}")
raise
def _update_macos_platform_uuid(self, new_ids):
"""更新macOS Platform UUID"""
try:
uuid_file = "/var/root/Library/Preferences/SystemConfiguration/com.apple.platform.uuid.plist"
if os.path.exists(uuid_file):
# 使用sudo来执行plutil命令
cmd = f'sudo plutil -replace "UUID" -string "{new_ids["telemetry.macMachineId"]}" "{uuid_file}"'
result = os.system(cmd)
if result == 0:
print("macOS Platform UUID updated successfully")
else:
raise Exception("Failed to execute plutil command")
except Exception as e:
print(f"Failed to update macOS Platform UUID: {e}")
raise
def reset_machine_ids(self): def reset_machine_ids(self):
"""重置机器ID并备份原文件""" """重置机器ID并备份原文件"""
try: try:
@@ -136,14 +360,27 @@ class MachineIDResetter:
print(f"{Fore.CYAN}{EMOJI['RESET']} {self.translator.get('reset.generating')}...{Style.RESET_ALL}") print(f"{Fore.CYAN}{EMOJI['RESET']} {self.translator.get('reset.generating')}...{Style.RESET_ALL}")
new_ids = self.generate_new_ids() new_ids = self.generate_new_ids()
# 更新配置文件
config.update(new_ids) config.update(new_ids)
print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('reset.saving_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: 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)
# 更新系统ID
self.update_system_ids(new_ids)
# 检查 Cursor 版本并执行相应的操作
greater_than_0_45 = check_cursor_version(self.translator)
if greater_than_0_45:
print(f"{Fore.CYAN}{EMOJI['INFO']} 检测到 Cursor 版本 >= 0.45.0,正在修补 getMachineId...{Style.RESET_ALL}")
patch_cursor_get_machine_id(self.translator)
else:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Cursor 版本 < 0.45.0,跳过 getMachineId 修补{Style.RESET_ALL}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.success')}{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}") 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():
@@ -160,18 +397,17 @@ class MachineIDResetter:
return False return False
def run(translator=None): def run(translator=None):
"""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']} {translator.get('reset.title')}{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(translator) resetter = MachineIDResetter(translator) # 正確傳遞 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']} {translator.get('reset.press_enter')}...") input(f"{EMOJI['INFO']} {translator.get('reset.press_enter')}...")
if __name__ == "__main__": if __name__ == "__main__":
# 如果直接运行,使用默认翻译器
from main import translator as main_translator from main import translator as main_translator
run(main_translator) run(main_translator)