Compare commits

..

26 Commits

Author SHA1 Message Date
yeongpin
637f923c16 change changelog 2025-02-13 11:42:48 +08:00
yeongpin
1cc93ffc22 fix & optimize 2025-02-13 11:33:20 +08:00
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
18 changed files with 1563 additions and 680 deletions

4
.env
View File

@@ -1,2 +1,2 @@
version=1.0.8 version=1.2.01
VERSION=1.0.8 VERSION=1.2.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 }}

145
CHANGELOG.md Normal file
View File

@@ -0,0 +1,145 @@
# Change Log
## v1.2.01
1. Fix Cursor Cloudflare Human Verification Problem | 修復Cursor Cloudflare人機驗證問題
2. Change to automatic registration account | 全面改為自動註冊賬號
3. Change Mail Site | 改變郵箱網站
4. Fix Cursor Cloudflare Problem | 修復Cursor Cloudflare問題
## v1.1.01
<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 | 重做註冊邏輯
## v1.0.10
1. Hot Fix Mac Chrome Problem | 修復Mac Chrome問題
2. Fix Linux Start Donet Problem | 修復Linux啟動開發者問題
## v1.0.9
<p align="center">
<img src="./images/cloudflare_2025-02-12_13-43-21.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
## v1.0.8
1. Fix New 0.45 Version Reset Machine | 修復新0.45版本重置機器
2. Fix Locale Language | 修復多語言
3. Add Support Crypto Machine Regedit | 增加支持加密機器註冊
## v1.0.7 - HotFix
1. Fix Reset Machine | 修復重置機器
2. Fix Locale Language | 修復多語言
## v1.0.7
1. Add Locale Language Support | 增加多語言支持
<p align="center">
<img src="./images/locale_2025-01-15_13-40-08.png" alt="locale" width="400"/><br>
</p>
## v1.0.6
1. Add Quit Cursor Option | 增加退出Cursor選項
2. Add Recaptcha Path Patch | 增加Recaptcha路徑修復
3. Fix Admin Permission | 修復管理員權限問題
4. Remove all need admin permission | 移除所有需要管理員權限
## v1.0.5 - HotFix
1. Fix: Mac Browser Control | 修復Mac瀏覽器控制問題
2. Fix: Verification Code Cant Patch | 修復驗證碼無法修復問題
3. Add Linux Support | 增加Linux支持
<p align="center">
<img src="./images/fix_2025-01-14_21-30-43.png" alt="fix" width="400"/><br>
</p>
## v1.0.5
1. Remove MachineID | 移除機器碼ID
2. Change to automatic registration account | 全面改為自動註冊賬號
3. Use your own exclusive new account | 使用自己獨享的新賬號
4. Fully automatic reset machine configuration | 全面自動化重置機器配置
<p align="center">
<img src="./images/pro_2025-01-14_14-40-37.png" alt="Why" width="400"/><br>
</p>
## v1.0.4
1. Fix: Cursor's configuration | 修復Cursor的配置問題
2. Fix Cloud Lame | 修復雲端慢速模式
## v1.0.3
1. Fix: Cursor's configuration | 修復Cursor的配置問題
2. Add Manual Reset Machine | 增加手動重置機器
3. Add CDN Cloud Control WatchDog | 增加CDN雲端控制WatchDog
4. Add Mac OS Support | 增加Mac OS支持
5. 759 ++ People use , but star only a few | 759 ++人使用,但只有幾個人點贊
<p align="center">
<img src="./images/what_2025-01-13_13-32-54.png" alt="Why" width="400"/><br>
</p>
## v1.0.2
1. Fix: Some known issues | 修復了一些已知問題
2. Add cloud control device code | 增加雲端控制設備碼
3. Cloud reset device code | 雲端重置設備碼
4. Remove official WatchDog monitoring | 移除官方WatchDog監控
5. Remove Proxy official prompt | 移除Proxy 官方提示
6. Fix: Too Many Computer | 修復Too Many Computer 問題
7. Fix Billing Issue | 修復計費問題
8. Fix: Cursor's configuration | 修復Cursor的配置問題
9. Fix cursor-slow mode | 修復cursor-slow模式
## v1.0.1
1. Fix: Reset machine ID | 修復了重置機器ID的問題
2. Fix: Bypass membership check | 修復了 繞過會員檢查的問題
3. Fix: Auto upgrade to "pro" membership | 修復了 自動升級為pro會員的問題
4. Fix: Real-time send Token request | 修復了 實時發送Token請求的問題
5. Fix: Reset Cursor's configuration | 修復了 重置Cursor的配置的問題
## v1.0
1. Preview Image | 預覽圖<br>
<p align="center">
<img src="./images/pro_2025-01-11_00-50-40.png" alt="Cursor Pro Logo" width="400"/><br>
</p>
<p align="center">
<img src="./images/pro_2025-01-11_00-51-07.png" alt="Cursor Pro Logo" width="400"/><br>
</p>
2. Add usage period,but can be contacted by leaving MachineID | 不得已才添加但可以通過留下MachineID 聯繫作者
<br>
<p align="center">
<img src="./images/pro_2025-01-11_16-24-03.png" alt="Cursor Pro Logo" width="400"/><br>
</p>

128
README.md
View File

@@ -11,8 +11,9 @@
[![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 , support Windows and macOS systems, complete Auth verification, and reset Cursor's configuration.
這是一個自動化工具自動註冊除了Google驗證碼),支持 Windows 和 macOS 系統完成Auth驗證重置Cursor的配置。 這是一個自動化工具自動註冊除了Google驗證碼),支持 Windows 和 macOS 系統完成Auth驗證重置Cursor的配置。
@@ -20,132 +21,21 @@ This is a tool to automatically register (except for Google verification code),
<img src="./images/new107_2025-01-15_13-53-56.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> ##### If you dont have google chrome , you can download it from [here](https://www.google.com/intl/en_pk/chrome/)
<p align="center">
<img src="./images/free_2025-01-14_14-59-15.png" alt="free" width="400"/><br>
</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 Chrome可以從[這裡](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/)下載
</p> </p>
</div> </div>
## 🔄 更新日志 ## 🔄 Change Log | 更新日志
<details open> [Watch Change Log | 查看更新日志](CHANGELOG.md)
<summary>v1.0.7 - HotFix</summary>
1. Fix Reset Machine | 修復重置機器
2. Fix Locale Language | 修復多語言
</details>
<details>
<summary>Other Version Change Log</summary>
<details>
<summary>v1.0.7</summary>
1. Add Locale Language Support | 增加多語言支持
<p align="center">
<img src="./images/locale_2025-01-15_13-40-08.png" alt="locale" width="400"/><br>
</p>
</details>
<details>
<summary>v1.0.6</summary>
1. Add Quit Cursor Option | 增加退出Cursor選項
2. Add Recaptcha Path Patch | 增加Recaptcha路徑修復
3. Fix Admin Permission | 修復管理員權限問題
4. Remove all need admin permission | 移除所有需要管理員權限
</details>
<details>
<summary>v1.0.5 - HotFix</summary>
1. Fix: Mac Browser Control | 修復Mac瀏覽器控制問題
2. Fix: Verification Code Cant Patch | 修復驗證碼無法修復問題
3. Add Linux Support | 增加Linux支持
<p align="center">
<img src="./images/fix_2025-01-14_21-30-43.png" alt="fix" width="400"/><br>
</p>
</details>
<details>
<summary>v1.0.5</summary>
1. Remove MachineID | 移除機器碼ID
2. Change to automatic registration account | 全面改為自動註冊賬號
3. Use your own exclusive new account | 使用自己獨享的新賬號
4. Fully automatic reset machine configuration | 全面自動化重置機器配置
<p align="center">
<img src="./images/pro_2025-01-14_14-40-37.png" alt="Why" width="400"/><br>
</p>
</details>
<details>
<summary>v1.0.4</summary>
1. Fix: Cursor's configuration | 修復Cursor的配置問題
2. Fix Cloud Lame | 修復雲端慢速模式
</details>
<details>
<summary>v1.0.3</summary>
1. Fix: Cursor's configuration | 修復Cursor的配置問題
2. Add Manual Reset Machine | 增加手動重置機器
3. Add CDN Cloud Control WatchDog | 增加CDN雲端控制WatchDog
4. Add Mac OS Support | 增加Mac OS支持
5. 759 ++ People use , but star only a few | 759 ++人使用,但只有幾個人點贊
<p align="center">
<img src="./images/what_2025-01-13_13-32-54.png" alt="Why" width="400"/><br>
</p>
</details>
<details>
<summary>v1.0.2</summary>
1. Fix: Some known issues | 修復了一些已知問題
2. Add cloud control device code | 增加雲端控制設備碼
3. Cloud reset device code | 雲端重置設備碼
4. Remove official WatchDog monitoring | 移除官方WatchDog監控
5. Remove Proxy official prompt | 移除Proxy 官方提示
6. Fix: Too Many Computer | 修復Too Many Computer 問題
7. Fix Billing Issue | 修復計費問題
8. Fix: Cursor's configuration | 修復Cursor的配置問題
9. Fix cursor-slow mode | 修復cursor-slow模式
</details>
<details>
<summary>v1.0.1</summary>
1. Fix: Reset machine ID | 修復了重置機器ID的問題
2. Fix: Bypass membership check | 修復了 繞過會員檢查的問題
3. Fix: Auto upgrade to "pro" membership | 修復了 自動升級為pro會員的問題
4. Fix: Real-time send Token request | 修復了 實時發送Token請求的問題
5. Fix: Reset Cursor's configuration | 修復了 重置Cursor的配置的問題
</details>
<details>
<summary>v1.0</summary>
1. Preview Image | 預覽圖<br>
<p align="center">
<img src="./images/pro_2025-01-11_00-50-40.png" alt="Cursor Pro Logo" width="400"/><br>
</p>
<p align="center">
<img src="./images/pro_2025-01-11_00-51-07.png" alt="Cursor Pro Logo" width="400"/><br>
</p>
2. Add usage period,but can be contacted by leaving MachineID | 不得已才添加但可以通過留下MachineID 聯繫作者
<br>
<p align="center">
<img src="./images/pro_2025-01-11_16-24-03.png" alt="Cursor Pro Logo" width="400"/><br>
</p>
</details>
</details>
## ✨ Features | 功能特點 ## ✨ Features | 功能特點
* Automatically register Cursor membership<br>自動註冊Cursor會員<br> * Automatically register Cursor membership<br>自動註冊Cursor會員<br>
* Except for Google verification code<br>除了Google驗證碼<br>
* Support Windows and macOS systems<br>支持 Windows 和 macOS 系統<br> * Support Windows and macOS systems<br>支持 Windows 和 macOS 系統<br>
* Complete Auth verification<br>完成Auth驗證<br> * Complete Auth verification<br>完成Auth驗證<br>
@@ -162,9 +52,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>
@@ -199,8 +87,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>使用本工具時請遵守相關軟件使用條款

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,36 @@ 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()
co.add_extension(extension_recaptcha_path)
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_argument("--hide-crash-restore-bubble")
# 随机端口
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
@@ -76,19 +86,6 @@ class BrowserManager:
return extension_path return extension_path
def get_extension_recaptcha(self):
"""获取插件路径"""
root_dir = os.getcwd()
extension_path = os.path.join(root_dir, "recaptchaPatch")
if hasattr(sys, "_MEIPASS"):
extension_path = os.path.join(sys._MEIPASS, "recaptchaPatch")
if not os.path.exists(extension_path):
raise FileNotFoundError(f"插件不存在: {extension_path}")
return extension_path
def quit(self): def quit(self):
"""关闭浏览器""" """关闭浏览器"""
if self.browser: if self.browser:

View File

@@ -24,7 +24,6 @@ a = Analysis(
binaries=[], binaries=[],
datas=[ datas=[
('turnstilePatch', 'turnstilePatch'), ('turnstilePatch', 'turnstilePatch'),
('recaptchaPatch', 'recaptchaPatch'),
('uBlock0.chromium', 'uBlock0.chromium'), ('uBlock0.chromium', 'uBlock0.chromium'),
('locales', 'locales'), ('locales', 'locales'),
('cursor_auth.py', '.'), ('cursor_auth.py', '.'),

View File

@@ -59,83 +59,6 @@ class BrowserControl:
"""获取当前标签页""" """获取当前标签页"""
return self.browser return self.browser
def generate_new_email(self):
"""点击新的按钮生成新邮箱"""
try:
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}{EMOJI['SUCCESS']} {self.translator.get('control.generate_email_success')}{Style.RESET_ALL}")
return True
else:
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}{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则随机选择。避免选择fr.nf域名"""
try:
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:
# 获取所有选项,包括两个 optgroup 下的所有 option
all_options = []
# 获取 "新的" 组下的选项
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')
all_options.extend(other_options)
if all_options:
max_attempts = 5 # 最大尝试次数
attempt = 0
while attempt < max_attempts:
# 如果没有指定索引,随机选择一个
if domain_index is None:
domain_index = random.randint(0, len(all_options) - 1)
if domain_index < len(all_options):
# 获取选中选项的文本
selected_domain = all_options[domain_index].text
# 检查是否为fr.nf域名
if "fr.nf" in selected_domain.lower():
print(f"{Fore.YELLOW}{EMOJI['INFO']} 检测到fr.nf域名重新选择...{Style.RESET_ALL}")
domain_index = None # 重置索引以便重新随机选择
attempt += 1
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']} 无法找到合适的非fr.nf域名{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}")
return False
else:
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}{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): def wait_for_page_load(self, seconds=2):
"""等待页面加载""" """等待页面加载"""
time.sleep(seconds) time.sleep(seconds)
@@ -151,80 +74,6 @@ class BrowserControl:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.browser_error', error=str(e))}{Style.RESET_ALL}") print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.browser_error', error=str(e))}{Style.RESET_ALL}")
return False return False
def copy_and_get_email(self):
"""获取邮箱地址"""
try:
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.generate_email')}...{Style.RESET_ALL}")
# 等待元素加载
time.sleep(1)
# 获取邮箱名称
try:
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}{EMOJI['MAIL']} {self.translator.get('control.get_email_name')}: {email_name}{Style.RESET_ALL}")
else:
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}{EMOJI['ERROR']} {self.translator.get('control.get_email_name_failed', error=str(e))}{Style.RESET_ALL}")
return None
# 直接使用上一步选择的域名
try:
domain = self.browser.ele('xpath://select[@id="seldom"]').value
if not domain: # 如果获取不到value尝试获取选中的选项文本
selected_option = self.browser.ele('xpath://select[@id="seldom"]/option[1]')
domain = selected_option.text if selected_option else "@yopmail.com" # 使用默认域名作为后备
except:
domain = "@yopmail.com" # 如果出错,使用默认域名
# 组合完整邮箱地址
full_email = f"{email_name}{domain}"
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}{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}{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}{EMOJI['SUCCESS']} {self.translator.get('control.enter_mailbox_success')}{Style.RESET_ALL}")
return True
else:
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}{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}{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}{EMOJI['SUCCESS']} {self.translator.get('control.refresh_mailbox_success')}{Style.RESET_ALL}")
return True
else:
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}{EMOJI['ERROR']} {self.translator.get('control.refresh_mailbox_failed', error=str(e))}{Style.RESET_ALL}")
return False
def get_verification_code(self): def get_verification_code(self):
"""从邮件中获取验证码""" """从邮件中获取验证码"""
try: try:

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=False)
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,
last_name=self.last_name,
email_tab=self.email_tab,
controller=self.controller,
translator=self.translator
)
# 填写注册表单 if result:
if self.signup_tab.ele("@name=first_name"): # 使用返回的浏览器实例获取账户信息
print(f"{Fore.CYAN}{EMOJI['FORM']} {self.translator.get('register.filling_form')}...{Style.RESET_ALL}") self.signup_tab = browser_tab # 保存浏览器实例
success = self._get_account_info()
self.signup_tab.ele("@name=first_name").input(self.first_name) # 获取信息后关闭浏览器
time.sleep(random.uniform(1, 2)) if browser_tab:
try:
browser_tab.quit()
except:
pass
self.signup_tab.ele("@name=last_name").input(self.last_name) return success
time.sleep(random.uniform(1, 2))
self.signup_tab.ele("@name=email").input(self.email_address) return False
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()
# 等待并获取验证码
time.sleep(5) # 等待验证码邮件
self.browser.refresh()
# 获取验证码设置60秒超时
verification_code = None
max_attempts = 20 # 增加到10次尝试
retry_interval = 10 # 每5秒重试一次
start_time = time.time()
timeout = 160 # 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: 137 KiB

View File

@@ -46,16 +46,45 @@
"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", "updating_system_ids": "Updating System IDs",
"system_ids_updated": "System IDs Updated Successfully", "system_ids_updated": "System IDs Updated Successfully",
"system_ids_update_failed": "System IDs Update Failed: {error}" "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",
@@ -93,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",
@@ -115,6 +145,7 @@
}, },
"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",
@@ -142,6 +173,25 @@
"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_updated_successfully": "Database Updated Successfully",
"database_connection_closed": "Database Connection Closed" "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

@@ -48,15 +48,44 @@
"press_enter": "按回车键退出", "press_enter": "按回车键退出",
"updating_system_ids": "更新系统ID", "updating_system_ids": "更新系统ID",
"system_ids_updated": "系统ID更新成功", "system_ids_updated": "系统ID更新成功",
"system_ids_update_failed": "系统ID更新失败: {error}" "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": "验证通过",
@@ -93,7 +122,8 @@
"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认证信息" "update_cursor_auth_info": "更新Cursor认证信息",
"setting_password": "设置密码"
}, },
"auth": { "auth": {
"title": "Cursor 认证管理器", "title": "Cursor 认证管理器",
@@ -117,6 +147,7 @@
"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": "找到验证码",
@@ -139,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

@@ -48,19 +48,48 @@
"press_enter": "按回車鍵退出", "press_enter": "按回車鍵退出",
"updating_system_ids": "更新系統ID", "updating_system_ids": "更新系統ID",
"system_ids_updated": "系統ID更新成功", "system_ids_updated": "系統ID更新成功",
"system_ids_update_failed": "系統ID更新失敗: {error}" "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}秒",
@@ -93,7 +122,8 @@
"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認證信息" "update_cursor_auth_info": "更新Cursor認證信息",
"setting_password": "設置密碼"
}, },
"auth": { "auth": {
"title": "Cursor 認證管理器", "title": "Cursor 認證管理器",
@@ -139,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": "郵箱地址"
} }
} }

562
new_signup.py Normal file
View File

@@ -0,0 +1,562 @@
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.auto_port()
# 使用有头模式(一定要设置为False模擬人類操作)
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

@@ -1,22 +0,0 @@
{
"manifest_version": 3,
"name": "Recaptcha Blocker",
"version": "1.0",
"description": "Blocks reCAPTCHA from loading",
"content_scripts": [
{
"matches": ["*://yopmail.com/zh/wm*"],
"js": ["script.js"],
"run_at": "document_start",
"all_frames": true
}
],
"permissions": [
"webNavigation",
"activeTab"
],
"host_permissions": [
"*://yopmail.com/*",
"*://*.google.com/*"
]
}

View File

@@ -1,123 +0,0 @@
// Debug logging function
function log(message) {
console.log(`[reCAPTCHA Bypass] ${new Date().toISOString()}: ${message}`);
}
// Function to get element by selector
function qSelector(selector) {
return document.querySelector(selector);
}
// Constants
const MAX_ATTEMPTS = 1;
const SELECTORS = {
CHECK_BOX: ".recaptcha-checkbox-border",
AUDIO_BUTTON: "#recaptcha-audio-button",
PLAY_BUTTON: ".rc-audiochallenge-play-button .rc-button-default",
AUDIO_SOURCE: "#audio-source",
IMAGE_SELECT: "#rc-imageselect",
RESPONSE_FIELD: ".rc-audiochallenge-response-field",
AUDIO_ERROR_MESSAGE: ".rc-audiochallenge-error-message",
AUDIO_RESPONSE: "#audio-response",
RELOAD_BUTTON: "#recaptcha-reload-button",
RECAPTCHA_STATUS: "#recaptcha-accessible-status",
DOSCAPTCHA: ".rc-doscaptcha-body",
VERIFY_BUTTON: "#recaptcha-verify-button"
};
// Function to check if element is hidden
function isHidden(el) {
return (el.offsetParent === null);
}
// Function to handle the bypass process
async function bypassRecaptcha() {
try {
log('Starting bypass process...');
log('Waiting 3 seconds before starting...');
await new Promise(resolve => setTimeout(resolve, 3000));
let solved = false;
let checkBoxClicked = false;
let requestCount = 0;
const recaptchaInitialStatus = qSelector(SELECTORS.RECAPTCHA_STATUS) ?
qSelector(SELECTORS.RECAPTCHA_STATUS).innerText : "";
log('Initial reCAPTCHA status: ' + recaptchaInitialStatus);
// Main bypass logic
try {
if (!checkBoxClicked && qSelector(SELECTORS.CHECK_BOX) &&
!isHidden(qSelector(SELECTORS.CHECK_BOX))) {
log('Clicking checkbox...');
qSelector(SELECTORS.CHECK_BOX).click();
checkBoxClicked = true;
}
// Check if the captcha is solved
if (qSelector(SELECTORS.RECAPTCHA_STATUS) &&
(qSelector(SELECTORS.RECAPTCHA_STATUS).innerText != recaptchaInitialStatus)) {
solved = true;
log('SOLVED!');
}
if (requestCount > MAX_ATTEMPTS) {
log('Attempted Max Retries. Stopping the solver');
solved = true;
}
// Stop solving when Automated queries message is shown
if (qSelector(SELECTORS.DOSCAPTCHA) &&
qSelector(SELECTORS.DOSCAPTCHA).innerText.length > 0) {
log('Automated Queries Detected');
}
} catch (err) {
log(`Error in main bypass logic: ${err.message}`);
}
log('Bypass process completed');
// If not solved, retry after delay
if (!solved && requestCount < MAX_ATTEMPTS) {
requestCount++;
log(`Retrying... Attempt ${requestCount} of ${MAX_ATTEMPTS}`);
setTimeout(bypassRecaptcha, 2000);
}
} catch (e) {
log(`Bypass failed: ${e.message}`);
}
}
// Create a MutationObserver to watch for reCAPTCHA elements
log('Setting up MutationObserver...');
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1 && // Element node
((node.tagName === 'SCRIPT' && node.src && node.src.includes('recaptcha')) ||
(node.tagName === 'IFRAME' && node.src && node.src.includes('recaptcha')))) {
log(`Detected new reCAPTCHA element: ${node.tagName} - ${node.src}`);
bypassRecaptcha();
}
});
});
});
// Start observing
observer.observe(document, {
childList: true,
subtree: true
});
log('MutationObserver started');
// Run on page load
if (document.readyState === 'loading') {
log('Document still loading, waiting for DOMContentLoaded');
document.addEventListener('DOMContentLoaded', bypassRecaptcha);
} else {
log('Document already loaded, starting bypass process');
bypassRecaptcha();
}

View File

@@ -5,19 +5,11 @@ import uuid
import hashlib import hashlib
import shutil import shutil
import sqlite3 import sqlite3
import logging import platform
import re
import tempfile
from colorama import Fore, Style, init from colorama import Fore, Style, init
from typing import Tuple
# 设置日志记录
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(),
logging.FileHandler('reset_machine.log', encoding='utf-8')
]
)
logger = logging.getLogger(__name__)
# 初始化colorama # 初始化colorama
init() init()
@@ -32,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
@@ -135,7 +294,6 @@ class MachineIDResetter:
return True return True
except Exception as e: except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.system_ids_update_failed', error=str(e))}{Style.RESET_ALL}") print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.system_ids_update_failed', error=str(e))}{Style.RESET_ALL}")
logger.error(f"System IDs update failed: {e}")
return False return False
def _update_windows_machine_guid(self): def _update_windows_machine_guid(self):
@@ -151,12 +309,12 @@ class MachineIDResetter:
new_guid = str(uuid.uuid4()) new_guid = str(uuid.uuid4())
winreg.SetValueEx(key, "MachineGuid", 0, winreg.REG_SZ, new_guid) winreg.SetValueEx(key, "MachineGuid", 0, winreg.REG_SZ, new_guid)
winreg.CloseKey(key) winreg.CloseKey(key)
logger.info("Windows MachineGuid updated successfully") print("Windows MachineGuid updated successfully")
except PermissionError: except PermissionError:
logger.error("Permission denied: Run as administrator to update Windows MachineGuid") print("Permission denied: Run as administrator to update Windows MachineGuid")
raise raise
except Exception as e: except Exception as e:
logger.error(f"Failed to update Windows MachineGuid: {e}") print(f"Failed to update Windows MachineGuid: {e}")
raise raise
def _update_macos_platform_uuid(self, new_ids): def _update_macos_platform_uuid(self, new_ids):
@@ -168,11 +326,11 @@ class MachineIDResetter:
cmd = f'sudo plutil -replace "UUID" -string "{new_ids["telemetry.macMachineId"]}" "{uuid_file}"' cmd = f'sudo plutil -replace "UUID" -string "{new_ids["telemetry.macMachineId"]}" "{uuid_file}"'
result = os.system(cmd) result = os.system(cmd)
if result == 0: if result == 0:
logger.info("macOS Platform UUID updated successfully") print("macOS Platform UUID updated successfully")
else: else:
raise Exception("Failed to execute plutil command") raise Exception("Failed to execute plutil command")
except Exception as e: except Exception as e:
logger.error(f"Failed to update macOS Platform UUID: {e}") print(f"Failed to update macOS Platform UUID: {e}")
raise raise
def reset_machine_ids(self): def reset_machine_ids(self):
@@ -215,6 +373,14 @@ class MachineIDResetter:
# 更新系统ID # 更新系统ID
self.update_system_ids(new_ids) 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():