Compare commits

..

34 Commits

Author SHA1 Message Date
yeongpin
4eac8a9e0e Update version to 1.7.12, enhance email creation logic, and add changelog display in the menu. Update locale files for improved translations and reflect changes in CHANGELOG.md. 2025-03-19 00:13:34 +08:00
yeongpin
fd2da5d701 Update version to 1.7.11 and add new blocked domains to block_domain.txt. Reflect changes in the environment configuration and enhance domain filtering capabilities. 2025-03-17 17:59:06 +08:00
yeongpin
a7433ec032 Add local blocked domains feature and enhance verification code retrieval with retry mechanism. Update CHANGELOG.md to reflect new feature. 2025-03-17 17:17:58 +08:00
yeongpin
bef2162509 Update CHANGELOG.md to include new features: auto-detect max use count, account deletion, and logic optimizations. 2025-03-17 17:11:27 +08:00
Pin Studios
eb6a5d5ac7 Merge pull request #262 from Nigel1992/update-locale-files
Update locale files
2025-03-17 17:00:35 +08:00
yeongpin
17212081ae Update version to 1.7.11, adding multi-language support for German, Dutch, and French. Update CHANGELOG.md to reflect new language additions and enhancements in the translation files. 2025-03-17 17:00:23 +08:00
Pin Studios
5544a78f6f Update block_domain.txt 2025-03-17 12:41:31 +08:00
Nigel1992
415da78768 Update locale files for Dutch, German, and French languages 2025-03-16 22:28:34 +01:00
Pin Studios
2cb788ddc1 Merge pull request #253 from BasaiCorp/main
Totally Reset Cusror
2025-03-16 12:48:02 +08:00
yeongpin
60ff9897f3 Update version to 1.7.10 and enhance totally_reset_cursor.py with multi-language support and new features. Update CHANGELOG.md to reflect changes. 2025-03-16 12:45:27 +08:00
BasaiCorp
21ca0a6b2d CLI Interface update 2025-03-16 09:44:31 +05:30
BasaiCorp
1dba533e93 COmmit v2.1 with machine id reset and all this one file will only do all for you but for account emails and registration please use https://github.com/yeongpin/cursor-free-vip 2025-03-16 09:28:53 +05:30
BasaiCorp
9146677bc4 update v2 of totally_reset_cursor.py 2025-03-16 09:18:54 +05:30
BasaiCorp
50366e319a Added totally_reset_cursor.py to fully reset Cursor AI 2025-03-16 09:05:17 +05:30
yeongpin
ad98bed98d Refactor: Remove GitHub trial reset feature and add development version check. Update translations for lifetime access and development version messages. 2025-03-16 10:54:43 +08:00
Pin Studios
6f2ec1b373 Merge pull request #250 from yeongpin/revert-248-feature/github-reset-trial
Revert "feat: Add GitHub-based trial reset"
2025-03-16 10:45:52 +08:00
Pin Studios
5574091273 Revert "feat: Add GitHub-based trial reset" 2025-03-16 10:44:40 +08:00
Pin Studios
0226c9e735 Update CHANGELOG.md 2025-03-16 10:18:35 +08:00
Pin Studios
375347a7a5 Update .env 2025-03-16 10:05:57 +08:00
Pin Studios
8301ea74d5 Delete pr_description.md 2025-03-16 10:05:41 +08:00
Pin Studios
96981a2c37 Merge pull request #248 from Nigel1992/feature/github-reset-trial
feat: Add GitHub-based trial reset
2025-03-16 10:04:44 +08:00
Nigel1992
975647765d feat: Add JavaScript trial reset code and update PR description 2025-03-15 23:52:39 +01:00
Nigel1992
808b1ba3dc feat: Add JavaScript trial reset code for automatic account deletion 2025-03-15 23:48:55 +01:00
Nigel1992
9595a8792f docs: Update PR description to include JavaScript trial reset code 2025-03-15 23:45:15 +01:00
Nigel1992
6b5dfab362 feat: Add GitHub-based trial reset with improved organization 2025-03-15 23:39:02 +01:00
Pin Studios
d5fceb2624 Update .env 2025-03-15 23:46:50 +08:00
Pin Studios
45046002df Merge pull request #243 from mALIk-sHAHId/feature/google-github-auth
feat: Add Google and GitHub OAuth Authentication with Lifetime Access…
2025-03-15 23:46:28 +08:00
mALIk-sHAHId
6bb33cec4c feat: Add Google and GitHub OAuth Authentication with Lifetime Access - Add OAuth integrations, update menu system, add multi-language support, and update documentation 2025-03-15 19:39:30 +05:30
Pin Studios
66f6197e6d Update block_domain.txt 2025-03-15 11:10:30 +08:00
Pin Studios
5514e47759 Update block_domain.txt 2025-03-15 10:29:03 +08:00
Pin Studios
3a53d59d52 Merge pull request #227 from distributedStorage/enhance-readme
doc: unify the README & CHANGELOG style
2025-03-14 23:02:31 +08:00
imbajin
c2e5499f19 doc: unify the README & CHANGELOG 2025-03-14 15:29:49 +08:00
Pin Studios
9a223756c5 Merge pull request #226 from distributedStorage/fix-download
fix(script): avoid empty version when call release api
2025-03-14 15:26:39 +08:00
imbajin
9b5912357d fix(script): avoid empty version when call release api
Also enhance the way for judging $?
2025-03-14 15:11:57 +08:00
20 changed files with 3324 additions and 350 deletions

4
.env
View File

@@ -1,2 +1,2 @@
version=1.7.07
VERSION=1.7.07
version=1.7.12
VERSION=1.7.12

View File

@@ -1,31 +1,64 @@
# Change Log
## v1.7.12
1. Add: Changelog Show in Menu | 增加更新日志在菜單中
2. Remake Create Mail Logic | 重做創建郵箱邏輯
3. Fix: Some Issues | 修復一些問題
## v1.7.11 ( Skip & Merge to v1.7.12 )
1. Add: Multi-language Support | 增加多語言支持
2. Add: German Language | 增加德語
3. Add: Dutch Language | 增加荷蘭語
4. Add: French Language | 增加法語
5. Add: Auto Detect Max Use Count | 增加自動檢測最大使用次數
6. Add: Detect & Auto Delete Account | 增加檢測 & 自動刪除賬號
7. Add: Optimize Some Logic | 優化一些邏輯
8. Add: Local Blocked Domains | 增加本地被屏蔽域名
9. Fix : Get Verification Code for None | 修復獲取驗證碼為 None
## v1.7.10
1. Add: Totally Reset Cursor | 增加完全重置 Cursor
2. Add: Multi-language Support for Totally Reset | 增加完全重置多語言支持
## v1.7.09
1. Add: Development Version Check | 增加開發版本檢查
2. Remove: Github Trial Reset | 移除 Github 試用重置
3. Fixed: Some Issues | 修復一些問題
## v1.7.08
1. Add: Google OAuth Authentication | 增加 Google OAuth 認證
2. Add: GitHub OAuth Authentication | 增加 GitHub OAuth 認證
3. Add: Lifetime Access for OAuth Users | 增加 OAuth 用戶終身訪問權限
4. Add: OAuth Authentication Integration | 增加 OAuth 認證集成
5. Update: Menu System with OAuth Options | 更新菜單系統,添加 OAuth 選項
6. Add: Multi-language Support for OAuth | 增加 OAuth 多語言支持
## v1.7.07
1. Add: Vietnamese Language | 增加越南語言
2. Add: Admin Privilege Management for Windows Executable | 增加Windows可執行文件管理員權限
3. Implement admin privilege detection for Windows platform | 實現Windows平台管理員權限檢測
2. Add: Admin Privilege Management for Windows Executable | 增加 Windows 可執行文件管理員權限
3. Implement admin privilege detection for Windows platform | 實現 Windows 平台管理員權限檢測
4. Add functions to check and request admin rights when running as a frozen executable | 增加檢查和請求管理員權限的功能
5. Enhance startup process with admin privilege verification | 增強啟動過程中的管理員權限驗證
6. Add new admin-related emoji to the EMOJI dictionary | 增加新的管理員相關表情符號到EMOJI字典
7. Provide fallback mechanism for non-Windows platforms (macos and linux ) | 提供非Windows平台macoslinux的回退機制
6. Add new admin-related emoji to the EMOJI dictionary | 增加新的管理員相關表情符號到 EMOJI 字典
7. Provide fallback mechanism for non-Windows platforms (macos and linux ) | 提供非 Windows 平台macoslinux的回退機制
These changes make the application more user-friendly by only requesting admin privileges when necessary (when running as an executable). | 這些改進使應用程序更易於使用,只在必要時(當作為可執行文件運行時)請求管理員權限。
## v1.7.06
1. Add: Update Confirm | 增加更新確認
2. Add: Update Skipped | 增加更新跳過
3. Add: Invalid Choice | 增加無效選擇
4. Fix: Cursor Path | 修復Cursor路徑
4. Fix: Cursor Path | 修復 Cursor 路徑
5. Fix: Path Encoding | 修復路徑編碼
6. Fix: Getting Verification Code | 修復獲取驗證碼
7. Fix: Setting Password | 修復設置密碼
8. Fix: Disable Auto Update | 修復禁用自動更新
9. Add Config.py | 增加Config.py
10. Add utils.py | 增加utils.py
9. Add Config.py | 增加 Config.py
10. Add utils.py | 增加 utils.py
11. Rebuild some logic | 重新構建一些邏輯
## v1.7.05
1. Fix: Cursor Version Check | 修復Cursor版本檢查
1. Fix: Cursor Version Check | 修復 Cursor 版本檢查
2. Fix: Small Problem | 修復一些小問題
@@ -36,10 +69,10 @@ These changes make the application more user-friendly by only requesting admin p
1. Hotfix: Small Problem | 修復一些小問題
## v1.7.02
1. Fix: Cursor Path | 修復Cursor路徑
1. Fix: Cursor Path | 修復 Cursor 路徑
2. Add: Config File | 增加配置文件
3. Remove: Workbench Cursor Path | 移除Workbench Cursor路徑
4. Remove: Cursor Main JS | 移除Cursor main.js
3. Remove: Workbench Cursor Path | 移除 Workbench Cursor 路徑
4. Remove: Cursor Main JS | 移除 Cursor main.js
## v1.7.01
- Refactoring: Extract configuration-related code from the `setup_driver` function to an independent `setup_config` function
@@ -54,10 +87,10 @@ These changes make the application more user-friendly by only requesting admin p
2. Add: Test some Bypass Code | 測試一些繞過代碼
## v1.6.01
1. Fix: Cursor Auth | 修復Cursor Auth
1. Fix: Cursor Auth | 修復 Cursor Auth
2. Add: Create Account Maximum Retry | 增加創建賬號最大重試次數
3. Fix: Cursor Auth Error | 修復Cursor Auth錯誤
4. Fix: Update Curl Faild | 修復更新Curl失敗
3. Fix: Cursor Auth Error | 修復 Cursor Auth 錯誤
4. Fix: Update Curl Faild | 修復更新 Curl 失敗
## v1.5.03
1. HOTFIX: Stuck on starting browser | 修復啟動瀏覽器卡住問題
@@ -80,8 +113,8 @@ These changes make the application more user-friendly by only requesting admin p
1. Add: Print Some Account Info | 增加打印一些賬號信息
## v1.4.07
1. Add Removed break statements after each operation | 修改結束event後的break暫停應用
2. Added print_menu() calls to show the menu again | 添加print_menu調用以再次顯示菜單
1. Add Removed break statements after each operation | 修改結束 event 後的 break 暫停應用
2. Added print_menu() calls to show the menu again | 添加 print_menu調用以再次顯示菜單
3. Updated error handling to show menu instead of exiting | 更新錯誤處理以顯示菜單而不是退出
## v1.4.06
@@ -96,7 +129,7 @@ These changes make the application more user-friendly by only requesting admin p
## v1.4.05
1. Fix: macOS Language Detection | 修復macOS語言檢測
1. Fix: macOS Language Detection | 修復 macOS 語言檢測
## v1.4.04
@@ -108,46 +141,46 @@ These changes make the application more user-friendly by only requesting admin p
## v1.4.03
1. Switch to API-based Registration System | 改用API註冊系統替代瀏覽器操作
2. Add Support for Latest Cursor Version | 增加支持最新版本Cursor
1. Switch to API-based Registration System | 改用 API 註冊系統替代瀏覽器操作
2. Add Support for Latest Cursor Version | 增加支持最新版本 Cursor
3. Enhance Translation System | 優化多語言翻譯系統
4. Add Database Connection Status Messages | 增加數據庫連接狀態提示
5. Improve Error Handling for Database Operations | 改進數據庫操作的錯誤處理
6. Add New API Integration | 新增API集成
6. Add New API Integration | 新增 API 集成
7. Optimize Performance and Stability | 優化性能和穩定性
## v1.4.01
1. Add Disable Cursor Auto Upgrade | 增加禁用Cursor自動升級
1. Add Disable Cursor Auto Upgrade | 增加禁用 Cursor 自動升級
## v1.3.02
1. Add Buy Me a Coffee | 增加請我喝杯咖啡
2. Add PayPal | 增加PayPal
2. Add PayPal | 增加 PayPal
3. Very Small Fix | 非常小的修復
4. Fix main.py option number | 修復main.py選項數量
4. Fix main.py option number | 修復 main.py 選項數量
## v1.3.01
1. Add Manual Email Input | 增加手動輸入郵箱地址
2. Add Manual Code Input | 增加手動輸入驗證碼
3. Fix Cursor Options | 修復Cursor選項
3. Fix Cursor Options | 修復 Cursor 選項
## v1.2.02
1. Add PBlock | 增加PBlock
2. Remove uBlock0.chromium | 移除uBlock0.chromium
1. Add PBlock | 增加 PBlock
2. Remove uBlock0.chromium | 移除 uBlock0.chromium
3. Optimize the logic of the script | 優化腳本邏輯
4. Optimize Size | 優化大小
## v1.2.01
1. Fix Cursor Cloudflare Human Verification Problem | 修復Cursor Cloudflare人機驗證問題
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問題
4. Fix Cursor Cloudflare Problem | 修復 Cursor Cloudflare 問題
## v1.1.01
@@ -156,15 +189,15 @@ These changes make the application more user-friendly by only requesting admin p
<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人機驗證問題
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啟動開發者問題
1. Hot Fix Mac Chrome Problem | 修復 Mac Chrome 問題
2. Fix Linux Start Donet Problem | 修復 Linux 啟動開發者問題
## v1.0.9
@@ -173,15 +206,15 @@ These changes make the application more user-friendly by only requesting admin p
<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版本重置機器
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
4. Add Remake main.js | 重做 main.js
## v1.0.8
1. Fix New 0.45 Version Reset Machine | 修復新0.45版本重置機器
1. Fix New 0.45 Version Reset Machine | 修復新 0.45 版本重置機器
2. Fix Locale Language | 修復多語言
3. Add Support Crypto Machine Regedit | 增加支持加密機器註冊
@@ -202,17 +235,17 @@ These changes make the application more user-friendly by only requesting admin p
## v1.0.6
1. Add Quit Cursor Option | 增加退出Cursor選項
2. Add Recaptcha Path Patch | 增加Recaptcha路徑修復
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瀏覽器控制問題
1. Fix: Mac Browser Control | 修復 Mac 瀏覽器控制問題
2. Fix: Verification Code Cant Patch | 修復驗證碼無法修復問題
3. Add Linux Support | 增加Linux支持
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>
@@ -220,7 +253,7 @@ These changes make the application more user-friendly by only requesting admin p
## v1.0.5
1. Remove MachineID | 移除機器碼ID
1. Remove MachineID | 移除機器碼 ID
2. Change to automatic registration account | 全面改為自動註冊賬號
3. Use your own exclusive new account | 使用自己獨享的新賬號
4. Fully automatic reset machine configuration | 全面自動化重置機器配置
@@ -231,16 +264,16 @@ These changes make the application more user-friendly by only requesting admin p
## v1.0.4
1. Fix: Cursor's configuration | 修復Cursor的配置問題
1. Fix: Cursor's configuration | 修復 Cursor 的配置問題
2. Fix Cloud Lame | 修復雲端慢速模式
## v1.0.3
1. Fix: Cursor's configuration | 修復Cursor的配置問題
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支持
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>
@@ -252,21 +285,21 @@ These changes make the application more user-friendly by only requesting admin p
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 問題
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模式
8. Fix: Cursor's configuration | 修復 Cursor 的配置問題
9. Fix cursor-slow mode | 修復 cursor-slow 模式
## v1.0.1
1. Fix: Reset machine ID | 修復了重置機器ID的問題
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的配置的問題
3. Fix: Auto upgrade to "pro" membership | 修復了 自動升級為 pro 會員的問題
4. Fix: Real-time send Token request | 修復了 實時發送 Token 請求的問題
5. Fix: Reset Cursor's configuration | 修復了 重置 Cursor 的配置的問題
@@ -278,7 +311,7 @@ These changes make the application more user-friendly by only requesting admin 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 聯繫作者
2. Add usage period,but can be contacted by leaving MachineID | 不得已才添加,但可以通過留下 MachineID 聯繫作者
<br>
<p align="center">

View File

@@ -1,4 +1,5 @@
# ➤ Cursor Free VIP
<div align="center">
<p align="center">
<img src="./images/logo.png" alt="Cursor Pro Logo" width="200" style="border-radius: 6px;"/>
@@ -12,45 +13,50 @@
[![Download](https://img.shields.io/github/downloads/yeongpin/cursor-free-vip/total?style=flat-square&logo=github&color=52c41a)](https://github.com/yeongpin/cursor-free-vip/releases/latest)
</p>
<h4>Support Latest 0.47.x Version | 支持最新0.47.x版本</h4>
<h4>Support Latest 0.47.x Version | 支持最新 0.47.x 版本</h4>
This is a tool to automatically register , 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.
這是一個自動化工具,自動註冊 ,支持 Windows 和 macOS 系統完成Auth驗證重置Cursor的配置。
這是一個自動化工具,自動註冊,支持 Windows 和 macOS 系統,完成 Auth 驗證,重置 Cursor 的配置。
<p align="center">
<img src="./images/new_2025-02-27_10-42-44.png" alt="new" width="400" style="border-radius: 6px;"/><br>
</p>
##### If you dont have google chrome , you can download it from [here](https://www.google.com/intl/en_pk/chrome/)
##### If you don't 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>
</div>
## 🔄 Change Log | 更新日志
[Watch Change Log | 查看更新日志](CHANGELOG.md)
## ✨ Features | 功能特點
* Automatically register Cursor membership<br>自動註冊Cursor會員<br>
* 🌟 Google OAuth Authentication with Lifetime Access<br>使用 Google OAuth 認證(終身訪問)<br>
* ⭐ GitHub OAuth Authentication with Lifetime Access<br>使用 GitHub OAuth 認證(終身訪問)<br>
* Automatically register Cursor membership<br>自動註冊 Cursor 會員<br>
* Support Windows and macOS systems<br>支持 Windows 和 macOS 系統<br>
* Complete Auth verification<br>完成Auth驗證<br>
* Complete Auth verification<br>完成 Auth 驗證<br>
* Reset Cursor's configuration<br>重置Cursor的配置<br>
* Reset Cursor's configuration<br>重置 Cursor 的配置<br>
* Multi-language support (English, 简体中文, 繁體中文, Vietnamese)<br>多語言支持(英文、简体中文、繁體中文、越南語)<br>
## 💻 System Support | 系統支持
|Windows|x64|✅|macOS|Intel|✅|
|:---:|:---:|:---:|:---:|:---:|:---:|
|Windows|x86|✅|macOS|Apple Silicon|✅|
|Linux|x64|✅|Linux|x86|✅|
|Linux|ARM64|✅|Linux|ARM64|✅|
| Windows | x64 | ✅ | macOS | Intel | ✅ |
|:-------:|:-----:|:-:|:-----:|:-------------:|:-:|
| Windows | x86 | ✅ | macOS | Apple Silicon | ✅ |
| Linux | x64 | ✅ | Linux | x86 | ✅ |
| Linux | ARM64 | ✅ | Linux | ARM64 | ✅ |
## 👀 How to use | 如何使用
@@ -58,28 +64,34 @@ This is a tool to automatically register , support Windows and macOS systems, co
<summary><b>⭐ Auto Run Script | 腳本自動化運行</b></summary>
**Linux/macOS**
```bash
curl -fsSL https://raw.githubusercontent.com/yeongpin/cursor-free-vip/main/scripts/install.sh -o install.sh && chmod +x install.sh && ./install.sh
```
**Windows**
```powershell
irm https://raw.githubusercontent.com/yeongpin/cursor-free-vip/main/scripts/install.ps1 | iex
```
</details>
<details>
<summary><b>⭐ Manual Reset Machine | 手動運行重置機器</b></summary>
**Linux/macOS**
```bash
curl -fsSL https://raw.githubusercontent.com/yeongpin/cursor-free-vip/main/scripts/reset.sh | sudo bash
```
**Windows**
```powershell
irm https://raw.githubusercontent.com/yeongpin/cursor-free-vip/main/scripts/reset.ps1 | iex
```
</details>
2. If you want to stop the script, please press Ctrl+C<br>要停止腳本,請按 Ctrl+C
@@ -140,6 +152,7 @@ retry_interval = 8-12
# Max Timeout | 最大超時時間
max_timeout = 160
```
</details>
* Use administrator to run the script <br>請使用管理員身份運行腳本
@@ -150,15 +163,11 @@ max_timeout = 160
* Please comply with the relevant software usage terms when using this tool <br>使用本工具時請遵守相關軟件使用條款
## 🚨 Common Issues | 常見問題
|如果遇到權限問題,請確保:| 此腳本以管理員身份運行 |
|:---:|:---:|
|If you encounter permission issues, please ensure: | This script is run with administrator privileges |
| 如果遇到權限問題,請確保: | 此腳本以管理員身份運行 |
|:--------------------------------------------------:|:------------------------------------------------:|
| If you encounter permission issues, please ensure: | This script is run with administrator privileges |
## 🤩 Contribution | 貢獻
@@ -170,12 +179,12 @@ max_timeout = 160
</a>
<br /><br />
## 📩 Disclaimer | 免責聲明
本工具僅供學習和研究使用,使用本工具所產生的任何後果由使用者自行承擔。 <br>
This tool is only for learning and research purposes, and any consequences arising from the use of this tool are borne by the user.
This tool is only for learning and research purposes, and any consequences arising from the use of this tool are borne
by the user.
## 💰 Buy Me a Coffee | 請我喝杯咖啡
@@ -202,9 +211,5 @@ This tool is only for learning and research purposes, and any consequences arisi
## 📝 License | 授權
本項目採用 [CC BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/) 授權。
本項目採用 [CC BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/) 授權。
Please refer to the [LICENSE](LICENSE.md) file for details.

View File

@@ -1,3 +1,9 @@
oakon.com
famamail.com
2925.com
indigobook.com
teihu.com
raleigh-construction.com
pastryofistanbul.com
linshiyouxiang.net
Mohmal.com

View File

@@ -33,7 +33,8 @@ a = Analysis(
('new_tempemail.py', '.'),
('quit_cursor.py', '.'),
('cursor_register_manual.py', '.'),
('.env', '.')
('.env', '.'),
('block_domain.txt', '.')
],
hiddenimports=[
'cursor_auth',

View File

@@ -0,0 +1,5 @@
from oauth_auth import main as oauth_main
def main(translator=None):
"""Handle GitHub OAuth registration"""
oauth_main('github', translator)

View File

@@ -0,0 +1,5 @@
from oauth_auth import main as oauth_main
def main(translator=None):
"""Handle Google OAuth registration"""
oauth_main('google', translator)

372
locales/de.json Normal file
View File

@@ -0,0 +1,372 @@
{
"menu": {
"title": "Verfügbare Optionen",
"exit": "Programm Beenden",
"reset": "Maschinen-ID Zurücksetzen",
"register": "Neues Cursor-Konto Registrieren",
"register_google": "Mit Google-Konto Registrieren",
"register_github": "Mit GitHub-Konto Registrieren",
"register_manual": "Cursor mit Benutzerdefinierter E-Mail Registrieren",
"quit": "Cursor-Anwendung Schließen",
"select_language": "Sprache Ändern",
"input_choice": "Bitte Auswahl eingeben ({choices})",
"invalid_choice": "Ungültige Auswahl. Bitte eine Nummer von {choices} eingeben",
"program_terminated": "Programm wurde vom Benutzer beendet",
"error_occurred": "Ein Fehler ist aufgetreten: {error}. Bitte erneut versuchen",
"press_enter": "Drücken Sie Enter zum Beenden",
"disable_auto_update": "Cursor Auto-Update Deaktivieren",
"lifetime_access_enabled": "LEBENSLANGER ZUGRIFF AKTIVIERT",
"totally_reset": "Cursor Vollständig Zurücksetzen"
},
"languages": {
"en": "English",
"zh_cn": "简体中文",
"zh_tw": "繁體中文",
"vi": "Tiếng Việt",
"nl": "Nederlands",
"de": "Deutsch",
"fr": "Français"
},
"quit_cursor": {
"start": "Beginne Cursor zu Beenden",
"no_process": "Kein Laufender Cursor-Prozess",
"terminating": "Beende Prozess {pid}",
"waiting": "Warte auf Prozessende",
"success": "Alle Cursor-Prozesse Beendet",
"timeout": "Prozess-Timeout: {pids}",
"error": "Fehler Aufgetreten: {error}"
},
"reset": {
"title": "Cursor Maschinen-ID Zurücksetzen Tool",
"checking": "Konfigurationsdatei Überprüfen",
"not_found": "Konfigurationsdatei Nicht Gefunden",
"no_permission": "Kann Konfigurationsdatei Nicht Lesen oder Schreiben, Bitte Dateiberechtigungen Überprüfen",
"reading": "Aktuelle Konfiguration Lesen",
"creating_backup": "Konfigurations-Backup Erstellen",
"backup_exists": "Backup-Datei Existiert Bereits, Backup-Schritt Überspringen",
"generating": "Neue Maschinen-ID Generieren",
"saving_json": "Neue Konfiguration in JSON Speichern",
"success": "Maschinen-ID Erfolgreich Zurückgesetzt",
"new_id": "Neue Maschinen-ID",
"permission_error": "Berechtigungsfehler: {error}",
"run_as_admin": "Bitte Versuchen Sie, Dieses Programm als Administrator Auszuführen",
"process_error": "Zurücksetzungsprozessfehler: {error}",
"updating_sqlite": "SQLite-Datenbank Aktualisieren",
"updating_pair": "Schlüssel-Wert-Paar Aktualisieren",
"sqlite_success": "SQLite-Datenbank Erfolgreich Aktualisiert",
"sqlite_error": "SQLite-Datenbank Aktualisierung Fehlgeschlagen: {error}",
"press_enter": "Drücken Sie Enter zum Fortfahren",
"unsupported_os": "Nicht Unterstütztes Betriebssystem: {os}",
"linux_path_not_found": "Linux-Pfad Nicht Gefunden",
"updating_system_ids": "System-IDs Aktualisieren",
"system_ids_updated": "System-IDs Erfolgreich Aktualisiert",
"system_ids_update_failed": "System-IDs Aktualisierung Fehlgeschlagen: {error}",
"windows_guid_updated": "Windows GUID Erfolgreich Aktualisiert",
"windows_permission_denied": "Windows Berechtigung Verweigert",
"windows_guid_update_failed": "Windows GUID Aktualisierung Fehlgeschlagen",
"macos_uuid_updated": "macOS UUID Erfolgreich Aktualisiert",
"plutil_command_failed": "plutil-Befehl Fehlgeschlagen",
"start_patching": "Patching getMachineId Starten",
"macos_uuid_update_failed": "macOS UUID Aktualisierung Fehlgeschlagen",
"current_version": "Aktuelle Cursor-Version: {version}",
"patch_completed": "Patching getMachineId Abgeschlossen",
"patch_failed": "Patching getMachineId Fehlgeschlagen: {error}",
"version_check_passed": "Cursor-Version Überprüfung Erfolgreich",
"file_modified": "Datei Geändert",
"version_less_than_0_45": "Cursor-Version < 0.45.0, Patching getMachineId Überspringen",
"detecting_version": "Cursor-Version Erkennen",
"patching_getmachineid": "Patching getMachineId",
"version_greater_than_0_45": "Cursor-Version >= 0.45.0, Patching getMachineId",
"permission_denied": "Berechtigung Verweigert: {error}",
"backup_created": "Backup Erstellt",
"update_success": "Update Erfolgreich",
"update_failed": "Update Fehlgeschlagen: {error}",
"windows_machine_guid_updated": "Windows Maschinen-GUID Erfolgreich Aktualisiert",
"reading_package_json": "package.json Lesen {path}",
"invalid_json_object": "Ungültiges JSON-Objekt",
"no_version_field": "Kein Versionsfeld in package.json Gefunden",
"version_field_empty": "Versionsfeld ist Leer",
"invalid_version_format": "Ungültiges Versionsformat: {version}",
"found_version": "Gefundene Version: {version}",
"version_parse_error": "Versions-Parse-Fehler: {error}",
"package_not_found": "Package.json Nicht Gefunden: {path}",
"check_version_failed": "Versionsüberprüfung Fehlgeschlagen: {error}",
"stack_trace": "Stack Trace",
"version_too_low": "Cursor-Version Zu Niedrig: {version} < 0.45.0"
},
"register": {
"title": "Cursor Registrierungstool",
"start": "Registrierungsprozess Starten...",
"handling_turnstile": "Sicherheitsüberprüfung Verarbeiten...",
"retry_verification": "Überprüfung Erneut Versuchen...",
"detect_turnstile": "Sicherheitsüberprüfung Überprüfen...",
"verification_success": "Sicherheitsüberprüfung Erfolgreich",
"starting_browser": "Browser Öffnen...",
"form_success": "Formular Erfolgreich Eingereicht",
"browser_started": "Browser Erfolgreich Geöffnet",
"waiting_for_second_verification": "Warten auf E-Mail-Verifizierung...",
"waiting_for_verification_code": "Warten auf Verifizierungscode...",
"password_success": "Passwort Erfolgreich Eingestellt",
"password_error": "Konnte Passwort Nicht Einstellen: {error}. Bitte Erneut Versuchen",
"waiting_for_page_load": "Seite Laden...",
"first_verification_passed": "Erste Überprüfung Erfolgreich",
"mailbox": "E-Mail-Postfach Erfolgreich Geöffnet",
"register_start": "Registrierung Starten",
"form_submitted": "Formular Eingereicht, Überprüfung Starten...",
"filling_form": "Formular Ausfüllen",
"visiting_url": "URL Besuchen",
"basic_info": "Grundlegende Informationen Eingereicht",
"handle_turnstile": "Turnstile Verarbeiten",
"no_turnstile": "Kein Turnstile Erkannt",
"turnstile_passed": "Turnstile Erfolgreich",
"verification_start": "Verifizierungscode Erhalten Starten",
"verification_timeout": "Verifizierungscode Timeout",
"verification_not_found": "Kein Verifizierungscode Gefunden",
"try_get_code": "Versuchen | {attempt} Verifizierungscode Erhalten | Verbleibende Zeit: {time}s",
"get_account": "Kontoinformationen Erhalten",
"get_token": "Cursor-Sitzungstoken Erhalten",
"token_success": "Token Erfolgreich Erhalten",
"token_attempt": "Versuchen | {attempt} Mal Token zu Erhalten | Erneut Versuchen in {time}s",
"token_max_attempts": "Maximale Versuche Erreicht ({max}) | Token Erhalten Fehlgeschlagen",
"token_failed": "Token Erhalten Fehlgeschlagen: {error}",
"account_error": "Kontoinformationen Erhalten Fehlgeschlagen: {error}",
"press_enter": "Drücken Sie Enter zum Fortfahren",
"browser_start": "Browser Starten",
"open_mailbox": "Mailbox-Seite Öffnen",
"email_error": "E-Mail-Adresse Erhalten Fehlgeschlagen",
"setup_error": "E-Mail-Einrichtungsfehler: {error}",
"start_getting_verification_code": "Verifizierungscode Erhalten Starten, Erneut Versuchen in 60s",
"get_verification_code_timeout": "Verifizierungscode Erhalten Timeout",
"get_verification_code_success": "Verifizierungscode Erfolgreich Erhalten",
"try_get_verification_code": "Versuchen | {attempt} Verifizierungscode Erhalten | Verbleibende Zeit: {remaining_time}s",
"verification_code_filled": "Verifizierungscode Ausgefüllt",
"login_success_and_jump_to_settings_page": "Anmeldung Erfolgreich und zu Einstellungsseite Springen",
"detect_login_page": "Anmeldeseite Erkennen, Anmeldung Starten...",
"cursor_registration_completed": "Cursor-Registrierung Abgeschlossen!",
"set_password": "Passwort Einstellen",
"basic_info_submitted": "Grundlegende Informationen Eingereicht",
"cursor_auth_info_updated": "Cursor-Authentifizierungsinformationen Aktualisiert",
"cursor_auth_info_update_failed": "Cursor-Authentifizierungsinformationen Aktualisierung Fehlgeschlagen",
"reset_machine_id": "Maschinen-ID Zurücksetzen",
"account_info_saved": "Kontoinformationen Gespeichert",
"save_account_info_failed": "Kontoinformationen Speichern Fehlgeschlagen",
"get_email_address": "E-Mail-Adresse Erhalten",
"update_cursor_auth_info": "Cursor-Authentifizierungsinformationen Aktualisieren",
"register_process_error": "Registrierungsprozessfehler: {error}",
"setting_password": "Passwort Einstellen",
"manual_code_input": "Manuelle Code-Eingabe",
"manual_email_input": "Manuelle E-Mail-Eingabe",
"password": "Passwort",
"first_name": "Vorname",
"last_name": "Nachname",
"exit_signal": "Exit-Signal",
"email_address": "E-Mail-Adresse",
"config_created": "Konfiguration Erstellt",
"verification_failed": "Verifizierung Fehlgeschlagen",
"verification_error": "Verifizierungsfehler: {error}",
"config_option_added": "Konfigurationsoption Hinzugefügt: {option}",
"config_updated": "Konfiguration Aktualisiert",
"password_submitted": "Passwort Eingereicht",
"total_usage": "Gesamtnutzung: {usage}",
"setting_on_password": "Passwort Einstellen",
"getting_code": "Verifizierungscode Erhalten, Erneut Versuchen in 60s"
},
"auth": {
"title": "Cursor Authentifizierungsmanager",
"checking_auth": "Authentifizierungsdatei Überprüfen",
"auth_not_found": "Authentifizierungsdatei Nicht Gefunden",
"auth_file_error": "Authentifizierungsdateifehler: {error}",
"reading_auth": "Authentifizierungsdatei Lesen",
"updating_auth": "Authentifizierungsinformationen Aktualisieren",
"auth_updated": "Authentifizierungsinformationen Erfolgreich Aktualisiert",
"auth_update_failed": "Authentifizierungsinformationen Aktualisierung Fehlgeschlagen: {error}",
"auth_file_created": "Authentifizierungsdatei Erstellt",
"auth_file_create_failed": "Authentifizierungsdatei Erstellen Fehlgeschlagen: {error}",
"press_enter": "Drücken Sie Enter zum Fortfahren",
"reset_machine_id": "Maschinen-ID Zurücksetzen",
"database_connection_closed": "Datenbankverbindung Geschlossen",
"database_updated_successfully": "Datenbank Erfolgreich Aktualisiert",
"connected_to_database": "Mit Datenbank Verbunden",
"updating_pair": "Schlüssel-Wert-Paar Aktualisieren",
"db_not_found": "Datenbankdatei Nicht Gefunden bei: {path}",
"db_permission_error": "Kann Nicht auf Datenbankdatei Zugreifen. Bitte Berechtigungen Überprüfen",
"db_connection_error": "Verbindung zur Datenbank Fehlgeschlagen: {error}"
},
"control": {
"generate_email": "Neue E-Mail Generieren",
"blocked_domain": "Gesperrte Domain",
"select_domain": "Zufällige Domain Auswählen",
"copy_email": "E-Mail-Adresse Kopieren",
"enter_mailbox": "Mailbox Betreten",
"refresh_mailbox": "Mailbox Aktualisieren",
"check_verification": "Verifizierungscode Überprüfen",
"verification_found": "Verifizierungscode Gefunden",
"verification_not_found": "Kein Verifizierungscode Gefunden",
"browser_error": "Browsersteuerungsfehler: {error}",
"navigation_error": "Navigationsfehler: {error}",
"email_copy_error": "E-Mail-Kopierfehler: {error}",
"mailbox_error": "Mailbox-Fehler: {error}",
"token_saved_to_file": "Token Gespeichert in cursor_tokens.txt",
"navigate_to": "Navigieren zu {url}",
"generate_email_success": "E-Mail Erfolgreich Generiert",
"select_email_domain": "E-Mail-Domain Auswählen",
"select_email_domain_success": "E-Mail-Domain Erfolgreich Ausgewählt",
"get_email_name": "E-Mail-Name Erhalten",
"get_email_name_success": "E-Mail-Name Erfolgreich Erhalten",
"get_email_address": "E-Mail-Adresse Erhalten",
"get_email_address_success": "E-Mail-Adresse Erfolgreich Erhalten",
"enter_mailbox_success": "Mailbox Erfolgreich Betreten",
"found_verification_code": "Verifizierungscode Gefunden",
"get_cursor_session_token": "Cursor-Sitzungstoken Erhalten",
"get_cursor_session_token_success": "Cursor-Sitzungstoken Erfolgreich Erhalten",
"get_cursor_session_token_failed": "Cursor-Sitzungstoken Erhalten Fehlgeschlagen",
"save_token_failed": "Token Speichern Fehlgeschlagen",
"database_updated_successfully": "Datenbank Erfolgreich Aktualisiert",
"database_connection_closed": "Datenbankverbindung Geschlossen",
"no_valid_verification_code": "Kein Gültiger Verifizierungscode"
},
"email": {
"starting_browser": "Browser Starten",
"visiting_site": "Besuche mail domains",
"create_success": "E-Mail Erfolgreich Erstellt",
"create_failed": "E-Mail Erstellen Fehlgeschlagen",
"create_error": "E-Mail-Erstellungsfehler: {error}",
"refreshing": "E-Mail Aktualisieren",
"refresh_success": "E-Mail Erfolgreich Aktualisiert",
"refresh_error": "E-Mail-Aktualisierungsfehler: {error}",
"refresh_button_not_found": "Aktualisierungsknopf Nicht Gefunden",
"verification_found": "Verifizierung Gefunden",
"verification_not_found": "Verifizierung Nicht Gefunden",
"verification_error": "Verifizierungsfehler: {error}",
"verification_code_found": "Verifizierungscode Gefunden",
"verification_code_not_found": "Verifizierungscode Nicht Gefunden",
"verification_code_error": "Verifizierungscodefehler: {error}",
"address": "E-Mail-Adresse",
"all_domains_blocked": "Alle Domains Gesperrt, Service Wechseln",
"no_available_domains_after_filtering": "Keine Verfügbaren Domains Nach Filterung",
"switching_service": "Wechseln zu {service} Service",
"domains_list_error": "Domains-Liste Erhalten Fehlgeschlagen: {error}",
"failed_to_get_available_domains": "Verfügbare Domains Erhalten Fehlgeschlagen",
"domains_excluded": "Ausgeschlossene Domains: {domains}",
"failed_to_create_account": "Konto Erstellen Fehlgeschlagen",
"account_creation_error": "Konto-Erstellungsfehler: {error}",
"domain_blocked": "Domain Blocked: {domain}"
},
"update": {
"title": "Cursor Auto-Update Deaktivieren",
"disable_success": "Auto-Update Deaktiviert Erfolgreich",
"disable_failed": "Auto-Update Deaktivieren Fehlgeschlagen: {error}",
"press_enter": "Drücken Sie Enter zum Fortfahren",
"start_disable": "Auto-Update Deaktivieren Starten",
"killing_processes": "Prozesse Töten",
"processes_killed": "Prozesse Getötet",
"removing_directory": "Verzeichnis Entfernen",
"directory_removed": "Verzeichnis Entfernt",
"creating_block_file": "Block-Datei Erstellen",
"block_file_created": "Block-Datei Erstellt"
},
"updater": {
"checking": "Updates prüfen...",
"new_version_available": "Neue Version verfügbar! (Aktuell: {current}, Neueste: {latest})",
"updating": "Zur neuesten Version aktualisieren. Das Programm wird automatisch neu starten.",
"up_to_date": "Sie verwenden die neueste Version.",
"check_failed": "Überprüfung auf Updates fehlgeschlagen: {error}",
"continue_anyway": "Mit der aktuellen Version fortfahren...",
"update_confirm": "Möchten Sie die neueste Version aktualisieren? (Y/n)",
"update_skipped": "Update überspringen.",
"invalid_choice": "Ungültige Auswahl. Bitte geben Sie 'Y' oder 'n' ein.",
"development_version": "Entwickler-Version {current} > {latest}",
"changelog_title": "Changelog"
},
"totally_reset": {
"title": "Cursor Vollständig Zurücksetzen",
"checking_config": "Konfigurationsdatei Überprüfen",
"config_not_found": "Konfigurationsdatei Nicht Gefunden",
"no_permission": "Kann Konfigurationsdatei Nicht Lesen oder Schreiben, Bitte Berechtigungen Überprüfen",
"reading_config": "Aktuelle Konfiguration Lesen",
"creating_backup": "Konfigurationsdatei Sichern",
"backup_exists": "Backup-Datei bereits vorhanden, Sicherungsschritt überspringen",
"generating_new_machine_id": "Neue Maschinen-ID Generieren",
"saving_new_config": "Neue Konfiguration in JSON Speichern",
"success": "Cursor Erfolgreich Zurückgesetzt",
"error": "Cursor Zurücksetzen Fehlgeschlagen: {error}",
"press_enter": "Drücken Sie Enter zum Beenden",
"reset_machine_id": "Maschinen-ID Zurücksetzen",
"database_connection_closed": "Datenbankverbindung Geschlossen",
"database_updated_successfully": "Datenbank Erfolgreich Aktualisiert",
"connected_to_database": "Mit Datenbank Verbunden",
"updating_pair": "Schlüssel-Wert-Paar Aktualisieren",
"db_not_found": "Datenbankdatei Nicht Gefunden bei: {path}",
"db_permission_error": "Kann Nicht auf Datenbankdatei Zugreifen. Bitte Berechtigungen Überprüfen",
"db_connection_error": "Verbindung zur Datenbank Fehlgeschlagen: {error}",
"feature_title": "FEATURES",
"feature_1": "Vollständige Entfernung von Cursor AI Einstellungen und Konfigurationen",
"feature_2": "Entfernt alle zwischengespeicherten Daten, einschließlich AI-Verlauf und Prompts",
"feature_3": "Maschinen-ID Zurücksetzen, um Trial-Erkennung zu umgehen",
"feature_4": "Erstellt neue zufällige Maschinen-IDs",
"feature_5": "Entfernt benutzerdefinierte Erweiterungen und Einstellungen",
"feature_6": "Zurücksetzt Trial-Informationen und Aktivierungsdaten",
"feature_7": "Tiefes Scannen für versteckte Lizenz- und Trial-bezogene Dateien",
"feature_8": "Sichert nicht-Cursor-Dateien und Anwendungen",
"feature_9": "Kompatibel mit Windows, macOS und Linux",
"disclaimer_title": "Disclaimer",
"disclaimer_1": "Dieses Tool wird alle Cursor AI Einstellungen,",
"disclaimer_2": "Konfigurationen und zwischengespeicherte Daten löschen. Diese Aktion kann nicht rückgängig gemacht werden.",
"disclaimer_3": "Ihre Code-Dateien werden NICHT beeinflusst, und das Tool ist so konzipiert,",
"disclaimer_4": "nur Cursor AI Editor-Dateien und Trial-Erkennungsmechanismen zu zielen.",
"disclaimer_5": "Andere Anwendungen auf Ihrem System werden NICHT beeinflusst.",
"disclaimer_6": "Sie müssen Cursor AI erneut einrichten, nachdem Sie dieses Tool ausgeführt haben.",
"disclaimer_7": "Verwenden Sie auf eigene Gefahr",
"confirm_title": "Sind Sie sicher, dass Sie fortfahren möchten?",
"confirm_1": "Diese Aktion wird alle Cursor AI Einstellungen,",
"confirm_2": "Konfigurationen und zwischengespeicherte Daten löschen. Diese Aktion kann nicht rückgängig gemacht werden.",
"confirm_3": "Ihre Code-Dateien werden NICHT beeinflusst, und das Tool ist so konzipiert,",
"confirm_4": "nur Cursor AI Editor-Dateien und Trial-Erkennungsmechanismen zu zielen.",
"confirm_5": "Andere Anwendungen auf Ihrem System werden NICHT beeinflusst.",
"confirm_6": "Sie müssen Cursor AI erneut einrichten, nachdem Sie dieses Tool ausgeführt haben.",
"confirm_7": "Verwenden Sie auf eigene Gefahr",
"invalid_choice": "Bitte geben Sie 'Y' oder 'n' ein",
"skipped_for_safety": "Übersprungen für Sicherheit (nicht Cursor-bezogen): {path}",
"deleted": "Gelöscht: {path}",
"error_deleting": "Fehler beim Löschen von {path}: {error}",
"not_found": "Datei nicht gefunden: {path}",
"resetting_machine_id": "Maschinen-IDs zurücksetzen, um Trial-Erkennung zu umgehen...",
"created_machine_id": "Neue Maschinen-ID erstellt: {path}",
"error_creating_machine_id": "Fehler beim Erstellen der Maschinen-ID-Datei {path}: {error}",
"error_searching": "Fehler beim Suchen nach Dateien in {path}: {error}",
"created_extended_trial_info": "Neue erweiterte Trial-Informationen erstellt: {path}",
"error_creating_trial_info": "Fehler beim Erstellen der Trial-Informationen-Datei {path}: {error}",
"resetting_cursor_ai_editor": "Cursor AI Editor zurücksetzen... Bitte warten.",
"reset_cancelled": "Reset abgebrochen. Ohne Änderungen verlassen.",
"windows_machine_id_modification_skipped": "Windows Maschinen-ID-Änderung übersprungen: {error}",
"linux_machine_id_modification_skipped": "Linux machine-id-Änderung übersprungen: {error}",
"note_complete_machine_id_reset_may_require_running_as_administrator": "Hinweis: Vollständiges Zurücksetzen der Maschinen-ID kann erfordern, dass Sie als Administrator ausführen",
"note_complete_system_machine_id_reset_may_require_sudo_privileges": "Hinweis: Vollständiges System-Maschinen-ID-Zurücksetzen kann sudo-Berechtigungen erfordern",
"windows_registry_instructions": "📝 HINWEIS: Für vollständiges Zurücksetzen auf Windows müssen Sie möglicherweise auch die Registrierungseinträge bereinigen.",
"windows_registry_instructions_2": " Führen Sie 'regedit' aus und suchen Sie nach Schlüsseln, die 'Cursor' oder 'CursorAI' enthalten, unter HKEY_CURRENT_USER\\Software\\ und löschen Sie sie.\n",
"reset_log_1": "Cursor AI wurde vollständig zurückgesetzt und Trial-Erkennung umgangen!",
"reset_log_2": "Bitte starten Sie Ihr System neu, um die Änderungen zu übernehmen.",
"reset_log_3": "Sie müssen Cursor AI erneut installieren und sollten jetzt einen neuen Trial-Zeitraum haben.",
"reset_log_4": "Für die besten Ergebnisse betrachten Sie auch:",
"reset_log_5": "Verwenden Sie eine andere E-Mail-Adresse beim Registrieren für einen neuen Trial",
"reset_log_6": "Wenn verfügbar, verwenden Sie einen VPN, um Ihre IP-Adresse zu ändern",
"reset_log_7": "Löschen Sie Ihre Browser-Cookies und Cache vor dem Besuch der Cursor AI-Website",
"reset_log_8": "Wenn Probleme bestehen, versuchen Sie, Cursor AI in einem anderen Speicherort zu installieren",
"reset_log_9": "Wenn Sie irgendwelche Probleme haben, gehen Sie zu Github Issue Tracker und erstellen Sie ein Problem unter https://github.com/yeongpin/cursor-free-vip/issues",
"unexpected_error": "Ein unerwarteter Fehler ist aufgetreten: {error}",
"report_issue": "Bitte melden Sie dieses Problem bei Github Issue Tracker unter https://github.com/yeongpin/cursor-free-vip/issues",
"keyboard_interrupt": "Prozess von Benutzer unterbrochen. Beenden...",
"return_to_main_menu": "Zurück zur Hauptseite...",
"process_interrupted": "Prozess unterbrochen. Beenden...",
"press_enter_to_return_to_main_menu": "Drücken Sie Enter, um zur Hauptseite zurückzukehren...",
"removing_known": "Bekannte Trial/Lizenz-Dateien entfernen",
"performing_deep_scan": "Tiefes Scannen nach zusätzlichen Trial/Lizenz-Dateien",
"found_additional_potential_license_trial_files": "Gefundene {count} zusätzliche potentielle Lizenz/Trial-Dateien",
"checking_for_electron_localstorage_files": "Überprüfen auf Electron localStorage-Dateien",
"no_additional_license_trial_files_found_in_deep_scan": "Keine zusätzlichen Lizenz/Trial-Dateien in tiefem Scan gefunden",
"removing_electron_localstorage_files": "Electron localStorage-Dateien entfernen",
"electron_localstorage_files_removed": "Electron localStorage-Dateien entfernt",
"electron_localstorage_files_removal_error": "Fehler beim Entfernen von Electron localStorage-Dateien: {error}",
"removing_electron_localstorage_files_completed": "Entfernen von Electron localStorage-Dateien abgeschlossen"
}
}

View File

@@ -4,6 +4,8 @@
"exit": "Exit Program",
"reset": "Reset Machine ID",
"register": "Register New Cursor Account",
"register_google": "Register with Google Account",
"register_github": "Register with GitHub Account",
"register_manual": "Register Cursor with Custom Email",
"quit": "Close Cursor Application",
"select_language": "Change Language",
@@ -12,13 +14,18 @@
"program_terminated": "Program was terminated by user",
"error_occurred": "An error occurred: {error}. Please try again",
"press_enter": "Press Enter to Exit",
"disable_auto_update": "Disable Cursor Auto-Update"
"disable_auto_update": "Disable Cursor Auto-Update",
"lifetime_access_enabled": "LIFETIME ACCESS ENABLED",
"totally_reset": "Totally Reset Cursor"
},
"languages": {
"en": "English",
"zh_cn": "简体中文",
"zh_tw": "繁體中文",
"vi": "Vietnamese"
"vi": "Vietnamese",
"nl": "Dutch",
"de": "German",
"fr": "French"
},
"quit_cursor": {
"start": "Start Quitting Cursor",
@@ -221,7 +228,7 @@
},
"email": {
"starting_browser": "Starting Browser",
"visiting_site": "Visiting mail.tm",
"visiting_site": "Visiting mail domains",
"create_success": "Email Created Successfully",
"create_failed": "Failed to Create Email",
"create_error": "Email Creation Error: {error}",
@@ -252,7 +259,8 @@
"blocked_domains_loaded_timeout_error": "Blocked Domains Loaded Timeout Error: {error}",
"available_domains_loaded": "Available Domains Loaded: {count}",
"domains_filtered": "Domains Filtered: {count}",
"trying_to_create_email": "Trying to create email: {email}"
"trying_to_create_email": "Trying to create email: {email}",
"domain_blocked": "Domain Blocked: {domain}"
},
"update": {
"title": "Disable Cursor Auto Update",
@@ -276,6 +284,99 @@
"continue_anyway": "Continuing with current version...",
"update_confirm": "Do you want to update to the latest version? (Y/n)",
"update_skipped": "Skipping update.",
"invalid_choice": "Invalid choice. Please enter 'Y' or 'n'."
"invalid_choice": "Invalid choice. Please enter 'Y' or 'n'.",
"development_version": "Development Version {current} > {latest}",
"changelog_title": "Changelog"
},
"totally_reset": {
"title": "Totally Reset Cursor",
"checking_config": "Checking Config File",
"config_not_found": "Config File Not Found",
"no_permission": "Cannot Read or Write Config File, Please Check File Permissions",
"reading_config": "Reading Current Config",
"creating_backup": "Creating Config Backup",
"backup_exists": "Backup File Already Exists, Skipping Backup Step",
"generating_new_machine_id": "Generating New Machine ID",
"saving_new_config": "Saving New Config to JSON",
"success": "Cursor Reset Successfully",
"error": "Cursor Reset Failed: {error}",
"press_enter": "Press Enter to Exit",
"reset_machine_id": "Reset Machine ID",
"database_connection_closed": "Database Connection Closed",
"database_updated_successfully": "Database Updated Successfully",
"connected_to_database": "Connected to Database",
"updating_pair": "Updating Key-Value Pair",
"db_not_found": "Database file not found at: {path}",
"db_permission_error": "Cannot access database file. Please check permissions",
"db_connection_error": "Failed to connect to database: {error}",
"feature_title": "FEATURES",
"feature_1": "Complete removal of Cursor AI settings and configurations",
"feature_2": "Clears all cached data including AI history and prompts",
"feature_3": "Resets machine ID to bypass trial detection",
"feature_4": "Creates new randomized machine identifiers",
"feature_5": "Removes custom extensions and preferences",
"feature_6": "Resets trial information and activation data",
"feature_7": "Deep scan for hidden license and trial-related files",
"feature_8": "Safely preserves non-Cursor files and applications",
"feature_9": "Compatible with Windows, macOS, and Linux",
"disclaimer_title": "DISCLAIMER",
"disclaimer_1": "This tool will permanently delete all Cursor AI settings,",
"disclaimer_2": "configurations, and cached data. This action cannot be undone.",
"disclaimer_3": "Your code files will NOT be affected, and the tool is designed",
"disclaimer_4": "to only target Cursor AI editor files and trial detection mechanisms.",
"disclaimer_5": "Other applications on your system will not be affected.",
"disclaimer_6": "You will need to set up Cursor AI again after running this tool.",
"disclaimer_7": "Use at your own risk",
"confirm_title": "Are you sure you want to proceed?",
"confirm_1": "This action will delete all Cursor AI settings,",
"confirm_2": "configurations, and cached data. This action cannot be undone.",
"confirm_3": "Your code files will NOT be affected, and the tool is designed",
"confirm_4": "to only target Cursor AI editor files and trial detection mechanisms.",
"confirm_5": "Other applications on your system will not be affected.",
"confirm_6": "You will need to set up Cursor AI again after running this tool.",
"confirm_7": "Use at your own risk",
"invalid_choice": "Please enter 'Y' or 'n'",
"skipped_for_safety": "Skipped for safety (not Cursor-related): {path}",
"deleted": "Deleted: {path}",
"error_deleting": "Error deleting {path}: {error}",
"not_found": "File not found: {path}",
"resetting_machine_id": "Resetting machine identifiers to bypass trial detection...",
"created_machine_id": "Created new machine ID: {path}",
"error_creating_machine_id": "Error creating machine ID file {path}: {error}",
"error_searching": "Error searching for files in {path}: {error}",
"created_extended_trial_info": "Created new extended trial info: {path}",
"error_creating_trial_info": "Error creating trial info file {path}: {error}",
"resetting_cursor_ai_editor": "Resetting Cursor AI Editor... Please wait.",
"reset_cancelled": "Reset cancelled. Exiting without making any changes.",
"windows_machine_id_modification_skipped": "Windows machine ID modification skipped: {error}",
"linux_machine_id_modification_skipped": "Linux machine-id modification skipped: {error}",
"note_complete_machine_id_reset_may_require_running_as_administrator": "Note: Complete machine ID reset may require running as administrator",
"note_complete_system_machine_id_reset_may_require_sudo_privileges": "Note: Complete system machine-id reset may require sudo privileges",
"windows_registry_instructions": "📝 NOTE: For complete reset on Windows, you might also need to clean registry entries.",
"windows_registry_instructions_2": " Run 'regedit' and search for keys containing 'Cursor' or 'CursorAI' under HKEY_CURRENT_USER\\Software\\ and delete them.\n",
"reset_log_1": "Cursor AI has been fully reset and trial detection bypassed!",
"reset_log_2": "Please restart your system for changes to take effect.",
"reset_log_3": "You will need to reinstall Cursor AI and should now have a fresh trial period.",
"reset_log_4": "For best results, consider also:",
"reset_log_5": "Use a different email address when registering for a new trial",
"reset_log_6": "If available, use a VPN to change your IP address",
"reset_log_7": "Clear your browser cookies and cache before visiting Cursor AI's website",
"reset_log_8": "If issues persist, try installing Cursor AI in a different location",
"reset_log_9": "If you encounter any issues, go to Github Issue Tracker and create an issue at https://github.com/yeongpin/cursor-free-vip/issues",
"unexpected_error": "An unexpected error occurred: {error}",
"report_issue": "Please report this issue to Github Issue Tracker at https://github.com/yeongpin/cursor-free-vip/issues",
"keyboard_interrupt": "Process interrupted by user. Exiting...",
"return_to_main_menu": "Returning to main menu...",
"process_interrupted": "Process interrupted. Exiting...",
"press_enter_to_return_to_main_menu": "Press Enter to return to main menu...",
"removing_known": "Removing known trial/license files",
"performing_deep_scan": "Performing deep scan for additional trial/license files",
"found_additional_potential_license_trial_files": "Found {count} additional potential license/trial files",
"checking_for_electron_localstorage_files": "Checking for Electron localStorage files",
"no_additional_license_trial_files_found_in_deep_scan": "No additional license/trial files found in deep scan",
"removing_electron_localstorage_files": "Removing Electron localStorage files",
"electron_localstorage_files_removed": "Electron localStorage files removed",
"electron_localstorage_files_removal_error": "Error removing Electron localStorage files: {error}",
"removing_electron_localstorage_files_completed": "Electron localStorage files removal completed"
}
}

372
locales/fr.json Normal file
View File

@@ -0,0 +1,372 @@
{
"menu": {
"title": "Options Disponibles",
"exit": "Quitter le Programme",
"reset": "Réinitialiser l'ID Machine",
"register": "Enregistrer un Nouveau Compte Cursor",
"register_google": "S'inscrire avec un Compte Google",
"register_github": "S'inscrire avec un Compte GitHub",
"register_manual": "Enregistrer Cursor avec un E-mail Personnalisé",
"quit": "Fermer l'Application Cursor",
"select_language": "Changer de Langue",
"input_choice": "Veuillez entrer votre choix ({choices})",
"invalid_choice": "Sélection invalide. Veuillez entrer un numéro de {choices}",
"program_terminated": "Programme terminé par l'utilisateur",
"error_occurred": "Une erreur s'est produite : {error}. Veuillez réessayer",
"press_enter": "Appuyez sur Entrée pour quitter",
"disable_auto_update": "Désactiver la Mise à Jour Automatique de Cursor",
"lifetime_access_enabled": "ACCÈS À VIE ACTIVÉ",
"totally_reset": "Réinitialisation Complète de Cursor"
},
"languages": {
"en": "English",
"zh_cn": "简体中文",
"zh_tw": "繁體中文",
"vi": "Tiếng Việt",
"nl": "Nederlands",
"de": "Deutsch",
"fr": "Français"
},
"quit_cursor": {
"start": "Début de la Fermeture de Cursor",
"no_process": "Aucun Processus Cursor en Cours",
"terminating": "Arrêt du Processus {pid}",
"waiting": "En Attente de la Fin du Processus",
"success": "Tous les Processus Cursor sont Fermés",
"timeout": "Délai d'Attente du Processus : {pids}",
"error": "Erreur Survenue : {error}"
},
"reset": {
"title": "Outil de Réinitialisation de l'ID Machine de Cursor",
"checking": "Vérification du Fichier de Configuration",
"not_found": "Fichier de Configuration Non Trouvé",
"no_permission": "Impossible de Lire ou d'Écrire le Fichier de Configuration, Veuillez Vérifier les Permissions",
"reading": "Lecture de la Configuration Actuelle",
"creating_backup": "Création d'une Sauvegarde de la Configuration",
"backup_exists": "Fichier de Sauvegarde Existe Déjà, Étape de Sauvegarde Ignorée",
"generating": "Génération d'un Nouvel ID Machine",
"saving_json": "Sauvegarde de la Nouvelle Configuration en JSON",
"success": "ID Machine Réinitialisé avec Succès",
"new_id": "Nouvel ID Machine",
"permission_error": "Erreur de Permission : {error}",
"run_as_admin": "Veuillez Essayer d'Exécuter ce Programme en tant qu'Administrateur",
"process_error": "Erreur de Processus de Réinitialisation : {error}",
"updating_sqlite": "Mise à Jour de la Base de Données SQLite",
"updating_pair": "Mise à Jour de la Paire Clé-Valeur",
"sqlite_success": "Base de Données SQLite Mise à Jour avec Succès",
"sqlite_error": "Échec de la Mise à Jour de la Base de Données SQLite : {error}",
"press_enter": "Appuyez sur Entrée pour Continuer",
"unsupported_os": "Système d'Exploitation Non Pris en Charge : {os}",
"linux_path_not_found": "Chemin Linux Non Trouvé",
"updating_system_ids": "Mise à Jour des IDs Système",
"system_ids_updated": "IDs Système Mis à Jour avec Succès",
"system_ids_update_failed": "Échec de la Mise à Jour des IDs Système : {error}",
"windows_guid_updated": "GUID Windows Mis à Jour avec Succès",
"windows_permission_denied": "Permission Windows Refusée",
"windows_guid_update_failed": "Échec de la Mise à Jour du GUID Windows",
"macos_uuid_updated": "UUID macOS Mis à Jour avec Succès",
"plutil_command_failed": "Commande plutil Échouée",
"start_patching": "Démarrage du Patching de getMachineId",
"macos_uuid_update_failed": "Échec de la Mise à Jour de l'UUID macOS",
"current_version": "Version Actuelle de Cursor : {version}",
"patch_completed": "Patching de getMachineId Terminé",
"patch_failed": "Échec du Patching de getMachineId : {error}",
"version_check_passed": "Vérification de la Version de Cursor Réussie",
"file_modified": "Fichier Modifié",
"version_less_than_0_45": "Version de Cursor < 0.45.0, Patching de getMachineId Ignoré",
"detecting_version": "Détection de la Version de Cursor",
"patching_getmachineid": "Patching de getMachineId",
"version_greater_than_0_45": "Version de Cursor >= 0.45.0, Patching de getMachineId",
"permission_denied": "Permission Refusée : {error}",
"backup_created": "Sauvegarde Créée",
"update_success": "Mise à Jour Réussie",
"update_failed": "Échec de la Mise à Jour : {error}",
"windows_machine_guid_updated": "GUID de la Machine Windows Mis à Jour avec Succès",
"reading_package_json": "Lecture du package.json {path}",
"invalid_json_object": "Objet JSON Invalide",
"no_version_field": "Aucun Champ de Version Trouvé dans le package.json",
"version_field_empty": "Champ de Version Vide",
"invalid_version_format": "Format de Version Invalide : {version}",
"found_version": "Version Trouvée : {version}",
"version_parse_error": "Erreur d'Analyse de la Version : {error}",
"package_not_found": "Package.json Non Trouvé : {path}",
"check_version_failed": "Échec de la Vérification de la Version : {error}",
"stack_trace": "Trace de la Pile",
"version_too_low": "Version de Cursor Trop Basse : {version} < 0.45.0"
},
"register": {
"title": "Outil d'Enregistrement de Cursor",
"start": "Démarrage du Processus d'Enregistrement...",
"handling_turnstile": "Traitement de la Vérification de Sécurité...",
"retry_verification": "Nouvelle Tentative de Vérification...",
"detect_turnstile": "Vérification de la Sécurité...",
"verification_success": "Vérification de Sécurité Réussie",
"starting_browser": "Ouverture du Navigateur...",
"form_success": "Formulaire Soumis avec Succès",
"browser_started": "Navigateur Ouvert avec Succès",
"waiting_for_second_verification": "En Attente de la Vérification par E-mail...",
"waiting_for_verification_code": "En Attente du Code de Vérification...",
"password_success": "Mot de Passe Défini avec Succès",
"password_error": "Impossible de Définir le Mot de Passe : {error}. Veuillez Réessayer",
"waiting_for_page_load": "Chargement de la Page...",
"first_verification_passed": "Première Vérification Réussie",
"mailbox": "Boîte de Réception Accédée avec Succès",
"register_start": "Démarrer l'Enregistrement",
"form_submitted": "Formulaire Soumis, Démarrage de la Vérification...",
"filling_form": "Remplissage du Formulaire",
"visiting_url": "Visite de l'URL",
"basic_info": "Informations de Base Soumises",
"handle_turnstile": "Traitement du Tourniquet",
"no_turnstile": "Aucun Tourniquet Détecté",
"turnstile_passed": "Tourniquet Réussi",
"verification_start": "Démarrage de l'Obtention du Code de Vérification",
"verification_timeout": "Délai d'Attente du Code de Vérification",
"verification_not_found": "Aucun Code de Vérification Trouvé",
"try_get_code": "Essayer | {attempt} d'Obtenir le Code de Vérification | Temps Restant : {time}s",
"get_account": "Obtention des Informations du Compte",
"get_token": "Obtention du Jeton de Session Cursor",
"token_success": "Jeton Obtenu avec Succès",
"token_attempt": "Essayer | {attempt} fois d'Obtenir le Jeton | Nouvelle Tentative dans {time}s",
"token_max_attempts": "Nombre Maximum de Tentatives Atteint ({max}) | Échec de l'Obtention du Jeton",
"token_failed": "Échec de l'Obtention du Jeton : {error}",
"account_error": "Échec de l'Obtention des Informations du Compte : {error}",
"press_enter": "Appuyez sur Entrée pour Continuer",
"browser_start": "Démarrage du Navigateur",
"open_mailbox": "Ouverture de la Page de la Boîte de Réception",
"email_error": "Échec de l'Obtention de l'Adresse E-mail",
"setup_error": "Erreur de Configuration de l'E-mail : {error}",
"start_getting_verification_code": "Démarrage de l'Obtention du Code de Vérification, Nouvelle Tentative dans 60s",
"get_verification_code_timeout": "Délai d'Attente de l'Obtention du Code de Vérification",
"get_verification_code_success": "Code de Vérification Obtenu avec Succès",
"try_get_verification_code": "Essayer | {attempt} d'Obtenir le Code de Vérification | Temps Restant : {remaining_time}s",
"verification_code_filled": "Code de Vérification Rempli",
"login_success_and_jump_to_settings_page": "Connexion Réussie et Accès à la Page des Paramètres",
"detect_login_page": "Détection de la Page de Connexion, Démarrage de la Connexion...",
"cursor_registration_completed": "Enregistrement de Cursor Terminé!",
"set_password": "Définir le Mot de Passe",
"basic_info_submitted": "Informations de Base Soumises",
"cursor_auth_info_updated": "Informations d'Authentification de Cursor Mises à Jour",
"cursor_auth_info_update_failed": "Échec de la Mise à Jour des Informations d'Authentification de Cursor",
"reset_machine_id": "Réinitialiser l'ID Machine",
"account_info_saved": "Informations du Compte Enregistrées",
"save_account_info_failed": "Échec de l'Enregistrement des Informations du Compte",
"get_email_address": "Obtenir l'Adresse E-mail",
"update_cursor_auth_info": "Mettre à Jour les Informations d'Authentification de Cursor",
"register_process_error": "Erreur du Processus d'Enregistrement : {error}",
"setting_password": "Définir le Mot de Passe",
"manual_code_input": "Saisie Manuelle du Code",
"manual_email_input": "Saisie Manuelle de l'E-mail",
"password": "Mot de Passe",
"first_name": "Prénom",
"last_name": "Nom de Famille",
"exit_signal": "Signal de Sortie",
"email_address": "Adresse E-mail",
"config_created": "Configuration Créée",
"verification_failed": "Échec de la Vérification",
"verification_error": "Erreur de Vérification : {error}",
"config_option_added": "Option de Configuration Ajoutée : {option}",
"config_updated": "Configuration Mise à Jour",
"password_submitted": "Mot de Passe Soumis",
"total_usage": "Utilisation Totale : {usage}",
"setting_on_password": "Définir le Mot de Passe",
"getting_code": "Obtention du Code de Vérification, Nouvelle Tentative dans 60s"
},
"auth": {
"title": "Gestionnaire d'Authentification de Cursor",
"checking_auth": "Vérification du Fichier d'Authentification",
"auth_not_found": "Fichier d'Authentification Non Trouvé",
"auth_file_error": "Erreur du Fichier d'Authentification : {error}",
"reading_auth": "Lecture du Fichier d'Authentification",
"updating_auth": "Mise à Jour des Informations d'Authentification",
"auth_updated": "Informations d'Authentification Mises à Jour avec Succès",
"auth_update_failed": "Échec de la Mise à Jour des Informations d'Authentification : {error}",
"auth_file_created": "Fichier d'Authentification Créé",
"auth_file_create_failed": "Échec de la Création du Fichier d'Authentification : {error}",
"press_enter": "Appuyez sur Entrée pour Continuer",
"reset_machine_id": "Réinitialiser l'ID Machine",
"database_connection_closed": "Connexion à la Base de Données Fermée",
"database_updated_successfully": "Base de Données Mise à Jour avec Succès",
"connected_to_database": "Connecté à la Base de Données",
"updating_pair": "Mise à Jour de la Paire Clé-Valeur",
"db_not_found": "Fichier de Base de Données Non Trouvé à : {path}",
"db_permission_error": "Impossible d'Accéder au Fichier de Base de Données. Veuillez Vérifier les Permissions",
"db_connection_error": "Échec de la Connexion à la Base de Données : {error}"
},
"control": {
"generate_email": "Générer un Nouvel E-mail",
"blocked_domain": "Domaine Bloqué",
"select_domain": "Sélectionner un Domaine Aléatoire",
"copy_email": "Copier l'Adresse E-mail",
"enter_mailbox": "Entrer dans la Boîte de Réception",
"refresh_mailbox": "Actualiser la Boîte de Réception",
"check_verification": "Vérifier le Code de Vérification",
"verification_found": "Code de Vérification Trouvé",
"verification_not_found": "Aucun Code de Vérification Trouvé",
"browser_error": "Erreur de Contrôle du Navigateur : {error}",
"navigation_error": "Erreur de Navigation : {error}",
"email_copy_error": "Erreur de Copie de l'E-mail : {error}",
"mailbox_error": "Erreur de la Boîte de Réception : {error}",
"token_saved_to_file": "Jeton Enregistré dans cursor_tokens.txt",
"navigate_to": "Naviguer vers {url}",
"generate_email_success": "E-mail Généré avec Succès",
"select_email_domain": "Sélectionner le Domaine de l'E-mail",
"select_email_domain_success": "Domaine de l'E-mail Sélectionné avec Succès",
"get_email_name": "Obtenir le Nom de l'E-mail",
"get_email_name_success": "Nom de l'E-mail Obtenu avec Succès",
"get_email_address": "Obtenir l'Adresse E-mail",
"get_email_address_success": "Adresse E-mail Obtenue avec Succès",
"enter_mailbox_success": "Entrée dans la Boîte de Réception Réussie",
"found_verification_code": "Code de Vérification Trouvé",
"get_cursor_session_token": "Obtenir le Jeton de Session Cursor",
"get_cursor_session_token_success": "Jeton de Session Cursor Obtenu avec Succès",
"get_cursor_session_token_failed": "Échec de l'Obtention du Jeton de Session Cursor",
"save_token_failed": "Échec de l'Enregistrement du Jeton",
"database_updated_successfully": "Base de Données Mise à Jour avec Succès",
"database_connection_closed": "Connexion à la Base de Données Fermée",
"no_valid_verification_code": "Aucun Code de Vérification Valide"
},
"email": {
"starting_browser": "Démarrage du Navigateur",
"visiting_site": "Visite de mail domains",
"create_success": "E-mail Créé avec Succès",
"create_failed": "Échec de la Création de l'E-mail",
"create_error": "Erreur de Création de l'E-mail : {error}",
"refreshing": "Actualisation de l'E-mail",
"refresh_success": "E-mail Actualisé avec Succès",
"refresh_error": "Erreur d'Actualisation de l'E-mail : {error}",
"refresh_button_not_found": "Bouton d'Actualisation Non Trouvé",
"verification_found": "Vérification Trouvée",
"verification_not_found": "Vérification Non Trouvée",
"verification_error": "Erreur de Vérification : {error}",
"verification_code_found": "Code de Vérification Trouvé",
"verification_code_not_found": "Code de Vérification Non Trouvé",
"verification_code_error": "Erreur de Code de Vérification : {error}",
"address": "Adresse E-mail",
"all_domains_blocked": "Tous les Domaines Sont Bloqués, Changement de Service",
"no_available_domains_after_filtering": "Aucun Domaine Disponible Après Filtrage",
"switching_service": "Changement vers le Service {service}",
"domains_list_error": "Échec de l'Obtention de la Liste des Domaines : {error}",
"failed_to_get_available_domains": "Échec de l'Obtention des Domaines Disponibles",
"domains_excluded": "Domaines Exclus : {domains}",
"failed_to_create_account": "Échec de la Création du Compte",
"account_creation_error": "Erreur de Création du Compte : {error}",
"domain_blocked": "Domaine Bloqué : {domain}"
},
"update": {
"title": "Désactivation de la Mise à Jour Automatique de Cursor",
"disable_success": "Mise à Jour Automatique Désactivée avec Succès",
"disable_failed": "Échec de la Désactivation de la Mise à Jour Automatique : {error}",
"press_enter": "Appuyez sur Entrée pour Continuer",
"start_disable": "Démarrage de la Désactivation de la Mise à Jour Automatique",
"killing_processes": "Tuer les Processus",
"processes_killed": "Processus Tuer",
"removing_directory": "Suppression du Dossier",
"directory_removed": "Dossier Supprimé",
"creating_block_file": "Création du Fichier de Blocage",
"block_file_created": "Fichier de Blocage Créé"
},
"updater": {
"checking": "Vérification des mises à jour...",
"new_version_available": "Nouvelle version disponible! (Version actuelle: {current}, Version la plus récente: {latest})",
"updating": "Mise à jour vers la version la plus récente. Le programme redémarrera automatiquement.",
"up_to_date": "Vous utilisez la version la plus récente.",
"check_failed": "Échec de la vérification des mises à jour: {error}",
"continue_anyway": "Continuer avec la version actuelle...",
"update_confirm": "Voulez-vous mettre à jour vers la version la plus récente? (O/n)",
"update_skipped": "Mise à jour ignorée.",
"invalid_choice": "Choix invalide. Veuillez entrer 'O' ou 'n'.",
"development_version": "Version de Développement {current} > {latest}",
"changelog_title": "Journal des modifications"
},
"totally_reset": {
"title": "Réinitialiser Complètement Cursor",
"checking_config": "Vérification du Fichier de Configuration",
"config_not_found": "Fichier de Configuration Non Trouvé",
"no_permission": "Impossible de Lire ou d'Écrire le Fichier de Configuration, Veuillez Vérifier les Permissions du Fichier",
"reading_config": "Lecture de la Configuration Actuelle",
"creating_backup": "Création de la Sauvegarde de la Configuration",
"backup_exists": "Fichier de Sauvegarde Déjà Existant, Passer à la Sauvegarde",
"generating_new_machine_id": "Génération d'un Nouvel ID Machine",
"saving_new_config": "Enregistrement de la Nouvelle Configuration dans JSON",
"success": "Réinitialisation de Cursor Réussie",
"error": "Réinitialisation de Cursor Échouée: {error}",
"press_enter": "Appuyez sur Entrée pour Continuer",
"reset_machine_id": "Réinitialiser l'ID Machine",
"database_connection_closed": "Connexion à la Base de Données Fermée",
"database_updated_successfully": "Base de Données Mise à Jour avec Succès",
"connected_to_database": "Connecté à la Base de Données",
"updating_pair": "Updating Key-Value Pair",
"db_not_found": "Database file not found at: {path}",
"db_permission_error": "Impossible d'Accéder au Fichier de Base de Données. Veuillez Vérifier les Permissions",
"db_connection_error": "Échec de la Connexion à la Base de Données : {error}",
"feature_title": "Fonctionnalités",
"feature_1": "Suppression complète des paramètres et configurations de Cursor AI",
"feature_2": "Efface tous les données mises en cache, y compris l'historique et les prompts",
"feature_3": "Réinitialise l'ID Machine pour contourner la détection de la période d'essai",
"feature_4": "Crée de nouveaux identifiants de machine aléatoires",
"feature_5": "Supprime les extensions personnalisées et les préférences",
"feature_6": "Réinitialise les informations de la période d'essai et les données d'activation",
"feature_7": "Analyse approfondie pour les fichiers cachés liés à la licence et à la période d'essai",
"feature_8": "Sauvegarde sécurisée des fichiers non liés à Cursor et applications",
"feature_9": "Compatible avec Windows, macOS et Linux",
"disclaimer_title": "DISCLAIMER",
"disclaimer_1": "Cet outil supprimera définitivement tous les paramètres et configurations de Cursor AI,",
"disclaimer_2": "configurations, et les données mises en cache. Cette action ne peut pas être annulée.",
"disclaimer_3": "Vos fichiers de code ne seront PAS affectés, et l'outil est conçu",
"disclaimer_4": "pour ne cibler que les fichiers de l'éditeur Cursor AI et les mécanismes de détection de la période d'essai.",
"disclaimer_5": "Les autres applications sur votre système ne seront PAS affectées.",
"disclaimer_6": "Vous devrez régler Cursor AI à nouveau après avoir exécuté cet outil.",
"disclaimer_7": "Utilisez à vos risques et périls",
"confirm_title": "Êtes-vous sûr de vouloir continuer?",
"confirm_1": "Cette action supprimera tous les paramètres et configurations de Cursor AI,",
"confirm_2": "configurations, et les données mises en cache. Cette action ne peut pas être annulée.",
"confirm_3": "Vos fichiers de code ne seront PAS affectés, et l'outil est conçu",
"confirm_4": "pour ne cibler que les fichiers de l'éditeur Cursor AI et les mécanismes de détection de la période d'essai.",
"confirm_5": "Les autres applications sur votre système ne seront PAS affectées.",
"confirm_6": "Vous devrez régler Cursor AI à nouveau après avoir exécuté cet outil.",
"confirm_7": "Utilisez à vos risques et périls",
"invalid_choice": "Veuillez entrer 'O' ou 'n'",
"skipped_for_safety": "Passé pour la sécurité (non lié à Cursor): {path}",
"deleted": "Supprimé: {path}",
"error_deleting": "Erreur de suppression de {path}: {error}",
"not_found": "Fichier non trouvé: {path}",
"resetting_machine_id": "Réinitialisation des identifiants de machine pour contourner la détection de la période d'essai...",
"created_machine_id": "Créé un nouvel ID machine: {path}",
"error_creating_machine_id": "Erreur de création du fichier ID machine {path}: {error}",
"error_searching": "Erreur de recherche dans {path}: {error}",
"created_extended_trial_info": "Créé un nouveau fichier d'informations de période d'essai étendue: {path}",
"error_creating_trial_info": "Erreur de création du fichier d'informations de période d'essai: {path}: {error}",
"resetting_cursor_ai_editor": "Réinitialisation de l'éditeur Cursor AI... Veuillez patienter.",
"reset_cancelled": "Réinitialisation annulée. Exiting sans faire de modifications.",
"windows_machine_id_modification_skipped": "Modification de l'ID machine Windows ignorée: {error}",
"linux_machine_id_modification_skipped": "Modification de l'ID machine Linux ignorée: {error}",
"note_complete_machine_id_reset_may_require_running_as_administrator": "Note: Réinitialisation complète de l'ID machine peut nécessiter d'exécuter en tant qu'administrateur",
"note_complete_system_machine_id_reset_may_require_sudo_privileges": "Note: Réinitialisation complète de l'ID machine peut nécessiter des privilèges sudo",
"windows_registry_instructions": "📝 NOTE: Pour la réinitialisation complète sur Windows, vous devrez peut-être également nettoyer les entrées du registre.",
"windows_registry_instructions_2": " Exécutez 'regedit' et recherchez les clés contenant 'Cursor' ou 'CursorAI' sous HKEY_CURRENT_USER\\Software\\ et supprimez-les.\n",
"reset_log_1": "Cursor AI a été complètement réinitialisé et la détection de la période d'essai a été contournée!",
"reset_log_2": "Veuillez redémarrer votre système pour que les modifications prennent effet.",
"reset_log_3": "Vous devrez réinstaller Cursor AI et devriez maintenant avoir une période d'essai fraîche.",
"reset_log_4": "Pour les meilleurs résultats, considérez également:",
"reset_log_5": "Utilisez une autre adresse e-mail lors de l'inscription pour une nouvelle période d'essai",
"reset_log_6": "Si disponible, utilisez un VPN pour changer votre adresse IP",
"reset_log_7": "Nettoyez les cookies et le cache de votre navigateur avant de visiter le site web de Cursor AI",
"reset_log_8": "Si les problèmes persistent, essayez d'installer Cursor AI dans un autre emplacement",
"reset_log_9": "Si vous rencontrez des problèmes, allez au suivi des problèmes Github et créez un problème à https://github.com/yeongpin/cursor-free-vip/issues",
"unexpected_error": "Une erreur inattendue est survenue: {error}",
"report_issue": "Veuillez signaler ce problème au suivi des problèmes Github à https://github.com/yeongpin/cursor-free-vip/issues",
"keyboard_interrupt": "Processus interrompu par l'utilisateur. Exiting...",
"return_to_main_menu": "Retour au menu principal...",
"process_interrupted": "Processus interrompu. Exiting...",
"press_enter_to_return_to_main_menu": "Appuyez sur Entrée pour retourner au menu principal...",
"removing_known": "Suppression des fichiers de période d'essai/licence connus",
"performing_deep_scan": "Exécution d'une analyse approfondie pour les fichiers de période d'essai/licence supplémentaires",
"found_additional_potential_license_trial_files": "Trouvé {count} fichiers de période d'essai/licence supplémentaires potentiels",
"checking_for_electron_localstorage_files": "Vérification des fichiers localStorage Electron",
"no_additional_license_trial_files_found_in_deep_scan": "Aucun fichier de licence/période d'essai supplémentaire trouvé dans l'analyse approfondie",
"removing_electron_localstorage_files": "Suppression des fichiers localStorage Electron",
"electron_localstorage_files_removed": "Fichiers localStorage Electron supprimés",
"electron_localstorage_files_removal_error": "Erreur de suppression des fichiers localStorage Electron: {error}",
"removing_electron_localstorage_files_completed": "Suppression des fichiers localStorage Electron terminée"
}
}

372
locales/nl.json Normal file
View File

@@ -0,0 +1,372 @@
{
"menu": {
"title": "Beschikbare opties",
"exit": "Programma afsluiten",
"reset": "Machine-ID resetten",
"register": "Nieuw Cursor-account registreren",
"register_google": "Registreren met Google-account",
"register_github": "Registreren met GitHub-account",
"register_manual": "Cursor registreren met aangepast e-mailadres",
"quit": "Cursor-applicatie sluiten",
"select_language": "Taal wijzigen",
"input_choice": "Voer uw keuze in: {choices}",
"invalid_choice": "Ongeldige selectie. Voer een nummer in uit {choices}.",
"program_terminated": "Programma is beëindigd door de gebruiker",
"error_occurred": "Er is een fout opgetreden: {error}. Probeer het opnieuw.",
"press_enter": "Druk op Enter om door te gaan.",
"disable_auto_update": "Cursor automatische updates uitschakelen",
"lifetime_access_enabled": "Levenslange toegang ingeschakeld",
"totally_reset": "Cursor volledig resetten"
},
"languages": {
"en": "English",
"zh_cn": "简体中文",
"zh_tw": "繁體中文",
"vi": "Tiếng Việt",
"nl": "Nederlands",
"de": "Deutsch",
"fr": "Français"
},
"quit_cursor": {
"start": "Start met afsluiten van Cursor",
"no_process": "Geen actief Cursor-proces",
"terminating": "Proces beëindigen {pid}",
"waiting": "Wachten tot het proces is afgesloten",
"success": "Alle Cursor-processen gesloten",
"timeout": "Proces time-out: {pids}",
"error": "Fout opgetreden: {error}"
},
"reset": {
"title": "Cursor Machine-ID Reset Tool",
"checking": "Configuratiebestand controleren",
"not_found": "Configuratiebestand niet gevonden",
"no_permission": "Kan configuratiebestand niet lezen of schrijven, controleer de bestandsrechten",
"reading": "Huidige configuratie lezen",
"creating_backup": "Configuratieback-up maken",
"backup_exists": "Back-upbestand bestaat al, back-upstap overslaan",
"generating": "Nieuwe Machine-ID genereren",
"saving_json": "Nieuwe configuratie opslaan naar JSON",
"success": "Machine-ID succesvol gereset",
"new_id": "Nieuwe Machine-ID",
"permission_error": "Toestemmingsfout: {error}",
"run_as_admin": "Probeer dit programma als beheerder uit te voeren",
"process_error": "Resetprocesfout: {error}",
"updating_sqlite": "SQLite-database bijwerken",
"updating_pair": "Sleutel-waarde paar bijwerken",
"sqlite_success": "SQLite-database succesvol bijgewerkt",
"sqlite_error": "SQLite-database bijwerken mislukt: {error}",
"press_enter": "Druk op Enter om door te gaan",
"unsupported_os": "Niet-ondersteund besturingssysteem: {os}",
"linux_path_not_found": "Linux-pad niet gevonden",
"updating_system_ids": "Systeem-ID's bijwerken",
"system_ids_updated": "Systeem-ID's succesvol bijgewerkt",
"system_ids_update_failed": "Systeem-ID's bijwerken mislukt: {error}",
"windows_guid_updated": "Windows GUID succesvol bijgewerkt",
"windows_permission_denied": "Windows toestemming geweigerd",
"windows_guid_update_failed": "Windows GUID bijwerken mislukt",
"macos_uuid_updated": "macOS UUID succesvol bijgewerkt",
"plutil_command_failed": "plutil-opdracht mislukt",
"start_patching": "Patching getMachineId starten",
"macos_uuid_update_failed": "macOS UUID bijwerken mislukt",
"current_version": "Huidige Cursor-versie: {version}",
"patch_completed": "Patching getMachineId voltooid",
"patch_failed": "Patching getMachineId mislukt: {error}",
"version_check_passed": "Cursor-versiecontrole geslaagd",
"file_modified": "Bestand gewijzigd",
"version_less_than_0_45": "Cursor-versie < 0.45.0, patching getMachineId overslaan",
"detecting_version": "Cursor-versie detecteren",
"patching_getmachineid": "Patching getMachineId",
"version_greater_than_0_45": "Cursor-versie >= 0.45.0, patching getMachineId",
"permission_denied": "Toestemming geweigerd: {error}",
"backup_created": "Back-up gemaakt",
"update_success": "Update geslaagd",
"update_failed": "Update mislukt: {error}",
"windows_machine_guid_updated": "Windows Machine GUID succesvol bijgewerkt",
"reading_package_json": "package.json lezen {path}",
"invalid_json_object": "Ongeldig JSON-object",
"no_version_field": "Geen versieveld gevonden in package.json",
"version_field_empty": "Versieveld is leeg",
"invalid_version_format": "Ongeldig versieformaat: {version}",
"found_version": "Gevonden versie: {version}",
"version_parse_error": "Versie parse-fout: {error}",
"package_not_found": "Package.json niet gevonden: {path}",
"check_version_failed": "Versiecontrole mislukt: {error}",
"stack_trace": "Stack Trace",
"version_too_low": "Cursor-versie te laag: {version} < 0.45.0"
},
"register": {
"title": "Cursor Registratietool",
"start": "Registratieproces starten...",
"handling_turnstile": "Beveiligingsverificatie verwerken...",
"retry_verification": "Verificatie opnieuw proberen...",
"detect_turnstile": "Beveiligingsverificatie controleren...",
"verification_success": "Beveiligingsverificatie geslaagd",
"starting_browser": "Browser openen...",
"form_success": "Formulier succesvol ingediend",
"browser_started": "Browser succesvol geopend",
"waiting_for_second_verification": "Wachten op e-mailverificatie...",
"waiting_for_verification_code": "Wachten op verificatiecode...",
"password_success": "Wachtwoord succesvol ingesteld",
"password_error": "Kon wachtwoord niet instellen: {error}. Probeer het opnieuw",
"waiting_for_page_load": "Pagina laden...",
"first_verification_passed": "Eerste verificatie geslaagd",
"mailbox": "E-mailinbox succesvol geopend",
"register_start": "Registratie starten",
"form_submitted": "Formulier ingediend, verificatie starten...",
"filling_form": "Formulier invullen",
"visiting_url": "URL bezoeken",
"basic_info": "Basisinformatie ingediend",
"handle_turnstile": "Turnstile verwerken",
"no_turnstile": "Geen Turnstile gedetecteerd",
"turnstile_passed": "Turnstile geslaagd",
"verification_start": "Verificatiecode verkrijgen starten",
"verification_timeout": "Verificatiecode time-out",
"verification_not_found": "Geen verificatiecode gevonden",
"try_get_code": "Probeer | {attempt} Verificatiecode verkrijgen | Tijd over: {time}s",
"get_account": "Accountinformatie verkrijgen",
"get_token": "Cursor-sessietoken verkrijgen",
"token_success": "Token succesvol verkregen",
"token_attempt": "Probeer | {attempt} keer om token te verkrijgen | Opnieuw proberen in {time}s",
"token_max_attempts": "Maximale pogingen bereikt ({max}) | Token verkrijgen mislukt",
"token_failed": "Token verkrijgen mislukt: {error}",
"account_error": "Accountinformatie verkrijgen mislukt: {error}",
"press_enter": "Druk op Enter om door te gaan",
"browser_start": "Browser starten",
"open_mailbox": "Mailboxpagina openen",
"email_error": "E-mailadres verkrijgen mislukt",
"setup_error": "E-mailinstelling fout: {error}",
"start_getting_verification_code": "Verificatiecode verkrijgen starten, opnieuw proberen in 60s",
"get_verification_code_timeout": "Verificatiecode verkrijgen time-out",
"get_verification_code_success": "Verificatiecode succesvol verkregen",
"try_get_verification_code": "Probeer | {attempt} Verificatiecode verkrijgen | Tijd over: {remaining_time}s",
"verification_code_filled": "Verificatiecode ingevuld",
"login_success_and_jump_to_settings_page": "Inloggen geslaagd en naar instellingenpagina springen",
"detect_login_page": "Inlogpagina detecteren, inloggen starten...",
"cursor_registration_completed": "Cursor-registratie voltooid!",
"set_password": "Wachtwoord instellen",
"basic_info_submitted": "Basisinformatie ingediend",
"cursor_auth_info_updated": "Cursor-authenticatie-informatie bijgewerkt",
"cursor_auth_info_update_failed": "Cursor-authenticatie-informatie bijwerken mislukt",
"reset_machine_id": "Machine-ID resetten",
"account_info_saved": "Accountinformatie opgeslagen",
"save_account_info_failed": "Accountinformatie opslaan mislukt",
"get_email_address": "E-mailadres verkrijgen",
"update_cursor_auth_info": "Cursor-authenticatie-informatie bijwerken",
"register_process_error": "Registratieprocesfout: {error}",
"setting_password": "Wachtwoord instellen",
"manual_code_input": "Handmatige code-invoer",
"manual_email_input": "Handmatige e-mailinvoer",
"password": "Wachtwoord",
"first_name": "Voornaam",
"last_name": "Achternaam",
"exit_signal": "Exit-signaal",
"email_address": "E-mailadres",
"config_created": "Configuratie aangemaakt",
"verification_failed": "Verificatie mislukt",
"verification_error": "Verificatiefout: {error}",
"config_option_added": "Configuratieoptie toegevoegd: {option}",
"config_updated": "Configuratie bijgewerkt",
"password_submitted": "Wachtwoord ingediend",
"total_usage": "Totaal gebruik: {usage}",
"setting_on_password": "Wachtwoord instellen",
"getting_code": "Verificatiecode verkrijgen, opnieuw proberen in 60s"
},
"auth": {
"title": "Cursor Authenticatiebeheer",
"checking_auth": "Authenticatiebestand controleren",
"auth_not_found": "Authenticatiebestand niet gevonden",
"auth_file_error": "Authenticatiebestandfout: {error}",
"reading_auth": "Authenticatiebestand lezen",
"updating_auth": "Authenticatie-informatie bijwerken",
"auth_updated": "Authenticatie-informatie succesvol bijgewerkt",
"auth_update_failed": "Authenticatie-informatie bijwerken mislukt: {error}",
"auth_file_created": "Authenticatiebestand aangemaakt",
"auth_file_create_failed": "Authenticatiebestand aanmaken mislukt: {error}",
"press_enter": "Druk op Enter om door te gaan",
"reset_machine_id": "Machine-ID resetten",
"database_connection_closed": "Databaseverbinding gesloten",
"database_updated_successfully": "Database succesvol bijgewerkt",
"connected_to_database": "Verbonden met database",
"updating_pair": "Sleutel-waarde paar bijwerken",
"db_not_found": "Databasebestand niet gevonden op: {path}",
"db_permission_error": "Kan geen toegang krijgen tot databasebestand. Controleer de rechten",
"db_connection_error": "Verbinding met database mislukt: {error}"
},
"control": {
"generate_email": "Nieuw e-mailadres genereren",
"blocked_domain": "Geblokkeerd domein",
"select_domain": "Willekeurig domein selecteren",
"copy_email": "E-mailadres kopiëren",
"enter_mailbox": "Mailbox betreden",
"refresh_mailbox": "Mailbox vernieuwen",
"check_verification": "Verificatiecode controleren",
"verification_found": "Verificatiecode gevonden",
"verification_not_found": "Geen verificatiecode gevonden",
"browser_error": "Browserbesturingsfout: {error}",
"navigation_error": "Navigatiefout: {error}",
"email_copy_error": "E-mailkopieerfout: {error}",
"mailbox_error": "Mailboxfout: {error}",
"token_saved_to_file": "Token opgeslagen in cursor_tokens.txt",
"navigate_to": "Navigeren naar {url}",
"generate_email_success": "E-mailadres succesvol gegenereerd",
"select_email_domain": "E-maildomein selecteren",
"select_email_domain_success": "E-maildomein succesvol geselecteerd",
"get_email_name": "E-mailnaam verkrijgen",
"get_email_name_success": "E-mailnaam succesvol verkregen",
"get_email_address": "E-mailadres verkrijgen",
"get_email_address_success": "E-mailadres succesvol verkregen",
"enter_mailbox_success": "Mailbox succesvol betreden",
"found_verification_code": "Verificatiecode gevonden",
"get_cursor_session_token": "Cursor-sessietoken verkrijgen",
"get_cursor_session_token_success": "Cursor-sessietoken succesvol verkregen",
"get_cursor_session_token_failed": "Cursor-sessietoken verkrijgen mislukt",
"save_token_failed": "Token opslaan mislukt",
"database_updated_successfully": "Database succesvol bijgewerkt",
"database_connection_closed": "Databaseverbinding gesloten",
"no_valid_verification_code": "Geen geldige verificatiecode"
},
"email": {
"starting_browser": "Browser starten",
"visiting_site": "Bezoek mail domains",
"create_success": "E-mail succesvol aangemaakt",
"create_failed": "E-mail aanmaken mislukt",
"create_error": "E-mail aanmaakfout: {error}",
"refreshing": "E-mail vernieuwen",
"refresh_success": "E-mail succesvol vernieuwd",
"refresh_error": "E-mail vernieuwingsfout: {error}",
"refresh_button_not_found": "Vernieuwknop niet gevonden",
"verification_found": "Verificatie gevonden",
"verification_not_found": "Verificatie niet gevonden",
"verification_error": "Verificatiefout: {error}",
"verification_code_found": "Verificatiecode gevonden",
"verification_code_not_found": "Verificatiecode niet gevonden",
"verification_code_error": "Verificatiecodefout: {error}",
"address": "E-mailadres",
"all_domains_blocked": "Alle domeinen geblokkeerd, service wisselen",
"no_available_domains_after_filtering": "Geen beschikbare domeinen na filteren",
"switching_service": "Wisselen naar {service} service",
"domains_list_error": "Domeinenlijst verkrijgen mislukt: {error}",
"failed_to_get_available_domains": "Verkrijgen van beschikbare domeinen mislukt",
"domains_excluded": "Uitgesloten domeinen: {domains}",
"failed_to_create_account": "Account aanmaken mislukt",
"account_creation_error": "Account aanmaakfout: {error}",
"domain_blocked": "Domein geblokkeerd: {domain}"
},
"update": {
"title": "Cursor automatische update uitschakelen",
"disable_success": "Automatische update is uitgeschakeld",
"disable_failed": "Automatische update uitschakelen mislukt: {error}",
"press_enter": "Druk op Enter om door te gaan",
"start_disable": "Automatische update uitschakelen starten",
"killing_processes": "Processen verwijderen",
"processes_killed": "Processen verwijderd",
"removing_directory": "Map verwijderen",
"directory_removed": "Map verwijderd",
"creating_block_file": "Blokkeerbestand aanmaken",
"block_file_created": "Blokkeerbestand aangemaakt"
},
"updater": {
"checking": "Controleren op updates...",
"new_version_available": "Er is een nieuwe versie beschikbaar! (Huidige versie: {current}, Laatste versie: {latest})",
"updating": "Aan het bijwerken naar de nieuwste versie. Het programma zal automatisch herstart worden.",
"up_to_date": "U gebruikt de nieuwste versie.",
"check_failed": "Controle op updates mislukt: {error}",
"continue_anyway": "Doorgaan met de huidige versie...",
"update_confirm": "Wil je de nieuwste versie gebruiken? (Y/n)",
"update_skipped": "Update overgeslagen.",
"invalid_choice": "Ongeldige keuze. Voer 'Y' of 'n' in.",
"development_version": "Ontwikkelversie {current} > {latest}",
"changelog_title": "Changelog"
},
"totally_reset": {
"title": "Cursor volledig herstellen",
"checking_config": "Configuratiebestand controleren",
"config_not_found": "Configuratiebestand niet gevonden",
"no_permission": "Kan geen toegang krijgen tot configuratiebestand. Controleer de rechten",
"reading_config": "Huidige configuratie lezen",
"creating_backup": "Configuratie-back-up aanmaken",
"backup_exists": "Back-up bestand bestaat, back-up stap overgeslagen",
"generating_new_machine_id": "Nieuwe machine-ID genereren",
"saving_new_config": "Nieuwe configuratie opslaan als JSON",
"success": "Cursor succesvol hersteld",
"error": "Cursor herstellen mislukt: {error}",
"press_enter": "Druk op Enter om door te gaan",
"reset_machine_id": "Machine-ID resetten",
"database_connection_closed": "Databaseverbinding gesloten",
"database_updated_successfully": "Database succesvol bijgewerkt",
"connected_to_database": "Verbonden met database",
"updating_pair": "Sleutel-waarde paar bijwerken",
"db_not_found": "Databasebestand niet gevonden op: {path}",
"db_permission_error": "Kan geen toegang krijgen tot databasebestand. Controleer de rechten",
"db_connection_error": "Verbinding met database mislukt: {error}",
"feature_title": "Functiebeschrijving",
"feature_1": "Compleet verwijderen van Cursor AI-instellingen en configuratie",
"feature_2": "Alle cachegegevens, inclusief AI-geschiedenis en prompts",
"feature_3": "Machine-ID resetten om de proefperiode te omzeilen",
"feature_4": "Nieuwe willekeurige machine-ID maken",
"feature_5": "Aangepaste extensies en voorkeuren verwijderen",
"feature_6": "Proefperiode- en activatiegegevens resetten",
"feature_7": "Diepe scan voor verborgen licentie- en proefperiodebestanden",
"feature_8": "Beveiligde niet-Cursor-bestanden en -toepassingen behouden",
"feature_9": "Compatibel met Windows, macOS en Linux",
"disclaimer_title": "Disclaimer",
"disclaimer_1": "Deze tool verwijdert alle Cursor AI-instellingen,",
"disclaimer_2": "configuratie en cachegegevens. Deze actie is niet ongedaan te maken.",
"disclaimer_3": "Uw codebestanden **worden niet** beïnvloed, de tool is bedoeld om",
"disclaimer_4": "Alleen gericht op Cursor AI-editorbestanden en proefperiodecontrolemechanisme.",
"disclaimer_5": "Andere systemtoepassingen worden niet beïnvloed.",
"disclaimer_6": "Na het uitvoeren van deze tool moet u Cursor AI opnieuw instellen.",
"disclaimer_7": "U accepteert de risico's zelf.",
"confirm_title": "Weet u zeker dat u wilt doorgaan?",
"confirm_1": "Deze actie verwijdert alle Cursor AI-instellingen,",
"confirm_2": "configuratie en cachegegevens. Deze actie is niet ongedaan te maken.",
"confirm_3": "Uw codebestanden **worden niet** beïnvloed, de tool is bedoeld om",
"confirm_4": "Alleen gericht op Cursor AI-editorbestanden en proefperiodecontrolemechanisme.",
"confirm_5": "Andere systemtoepassingen worden niet beïnvloed.",
"confirm_6": "Na het uitvoeren van deze tool moet u Cursor AI opnieuw instellen.",
"confirm_7": "U accepteert de risico's zelf.",
"invalid_choice": "Ongeldige keuze. Voer 'Y' of 'n' in.",
"skipped_for_safety": "Uit veiligheidsoverwegingen overgeslagen (niet Cursor-gerelateerd): {path}",
"deleted": "Verwijderd: {path}",
"error_deleting": "Verwijdering van {path} mislukt: {error}",
"not_found": "Bestand niet gevonden: {path}",
"resetting_machine_id": "Machine-ID resetten om proefperiode te omzeilen...",
"created_machine_id": "Nieuwe machine-ID gemaakt: {path}",
"error_creating_machine_id": "Machine-ID-bestand {path} aanmaken mislukt: {error}",
"error_searching": "Fout bij het zoeken naar bestand {path}: {error}",
"created_extended_trial_info": "Nieuwe uitgebreide proefperiode-informatie gemaakt: {path}",
"error_creating_trial_info": "Fout bij het aanmaken van proefperiode-informatiebestand {path}: {error}",
"resetting_cursor_ai_editor": "Cursor AI-editor resetten... Wacht even.",
"reset_cancelled": "Reset geannuleerd, geen wijzigingen aangebracht.",
"windows_machine_id_modification_skipped": "Windows machine-ID-aanpassing overgeslagen: {error}",
"linux_machine_id_modification_skipped": "Linux machine-id-aanpassing overgeslagen: {error}",
"note_complete_machine_id_reset_may_require_running_as_administrator": "Opmerking: Compleet machine-ID-reset kan vereisen dat u als beheerder uitvoert",
"note_complete_system_machine_id_reset_may_require_sudo_privileges": "Opmerking: Compleet systeem machine-ID-reset kan vereisen dat u sudo-rechten hebt",
"windows_registry_instructions": "📝 Opmerking: Compleet machine-ID-reset kan vereisen dat u als beheerder uitvoert",
"windows_registry_instructions_2": " Run 'regedit' en zoek naar de sleutels 'Cursor' of 'CursorAI' in HKEY_CURRENT_USER\\Software\\ en verwijder ze.\n",
"reset_log_1": "Cursor AI is volledig hersteld en heeft de proefperiode omzeild!",
"reset_log_2": "Start het systeem opnieuw om de wijzigingen te activeren.",
"reset_log_3": "U moet Cursor AI opnieuw installeren, er zou nu een nieuwe proefperiode moeten zijn.",
"reset_log_4": "Voor de beste resultaten raden we aan ook:",
"reset_log_5": "Nieuwe proefperiode registreren met een ander e-mailadres",
"reset_log_6": "Als mogelijk, VPN gebruiken om IP-adres te wijzigen",
"reset_log_7": "Voordat u naar de Cursor AI-website gaat, verwijdert u de cookies en cache van uw browser",
"reset_log_8": "Als het nog steeds niet werkt, probeert u Cursor AI op een andere locatie te installeren",
"reset_log_9": "Als u eventuele problemen ondervindt, stuurt u een probleem naar de Github Issue Tracker: https://github.com/yeongpin/cursor-free-vip/issues",
"unexpected_error": "Onverwachte fout: {error}",
"report_issue": "Rapporteer dit probleem op de Github Issue Tracker: https://github.com/yeongpin/cursor-free-vip/issues",
"keyboard_interrupt": "Gebruiker heeft proces afgebroken, afsluiten...",
"return_to_main_menu": "Terug naar hoofdmenu...",
"process_interrupted": "Proces afgebroken, afsluiten...",
"press_enter_to_return_to_main_menu": "Druk op Enter om terug te gaan naar het hoofdmenu...",
"removing_known": "Het verwijderen van bekende proefperiode- en licentiebestanden...",
"performing_deep_scan": "Een diepe scan wordt uitgevoerd om andere proefperiode- en licentiebestanden te vinden...",
"found_additional_potential_license_trial_files": "Er zijn {count} andere potentiële proefperiode- en licentiebestanden gevonden",
"checking_for_electron_localstorage_files": "Controleren op Electron localStorage-bestanden...",
"no_additional_license_trial_files_found_in_deep_scan": "Geen andere proefperiode- of licentiebestanden gevonden in diepe scan",
"removing_electron_localstorage_files": "Het verwijderen van Electron localStorage-bestanden...",
"electron_localstorage_files_removed": "Electron localStorage-bestanden verwijderd",
"electron_localstorage_files_removal_error": "Fout bij het verwijderen van Electron localStorage-bestanden: {error}",
"removing_electron_localstorage_files_completed": "Electron localStorage-bestanden verwijderd"
}
}

View File

@@ -12,13 +12,18 @@
"program_terminated": "Chương trình đã bị người dùng chấm dứt",
"error_occurred": "Đã xảy ra lỗi: {error}. Vui lòng thử lại",
"press_enter": "Nhấn Enter để Thoát",
"disable_auto_update": "Tắt TĐộng Cập Nhật Cursor"
"disable_auto_update": "Tắt tđộng cập nhật Cursor",
"lifetime_access_enabled": "ĐÃ BẬT TRUY CẬP TRỌN ĐỜI",
"totally_reset": "Đặt lại hoàn toàn Cursor"
},
"languages": {
"en": "English",
"zh_cn": "简体中文",
"zh_tw": "繁體中文",
"vi": "Tiếng Việt"
"vi": "Tiếng Việt",
"nl": "Dutch",
"de": "Germa",
"fr": "French"
},
"quit_cursor": {
"start": "Bắt Đầu Thoát Cursor",
@@ -221,7 +226,7 @@
},
"email": {
"starting_browser": "Đang Khởi Động Trình Duyệt",
"visiting_site": "Đang Truy Cập mail.tm",
"visiting_site": "Đang Truy Cập mail domains",
"create_success": "Tạo Email Thành Công",
"create_failed": "Tạo Email Thất Bại",
"create_error": "Lỗi Tạo Email: {error}",
@@ -252,7 +257,8 @@
"blocked_domains_loaded_timeout_error": "Lỗi Hết Thời Gian Tải Tên Miền Bị Chặn: {error}",
"available_domains_loaded": "Đã Tải Tên Miền Khả Dụng: {count}",
"domains_filtered": "Tên Miền Đã Lọc: {count}",
"trying_to_create_email": "Đang cố gắng tạo email: {email}"
"trying_to_create_email": "Đang cố gắng tạo email: {email}",
"domain_blocked": "Tên Miền Bị Chặn: {domain}"
},
"update": {
"title": "Tắt Tự Động Cập Nhật Cursor",
@@ -276,6 +282,99 @@
"continue_anyway": "Tiếp Tục Với Phiên Bản Hiện Tại...",
"update_confirm": "Bạn Có Muốn Cập Nhật Lên Phiên Bản Mới Nhất Không? (Y/n)",
"update_skipped": "Bỏ Qua Cập Nhật.",
"invalid_choice": "Lựa Chọn Không Hợp Lệ. Vui Lòng Nhập 'Y' Hoặc 'n'."
"invalid_choice": "Lựa Chọn Không Hợp Lệ. Vui Lòng Nhập 'Y' Hoặc 'n'.",
"development_version": "Phiên Bản Phát Triển {current} > {latest}",
"changelog_title": "Changelog"
},
"totally_reset": {
"title": "Đặt lại hoàn toàn Cursor",
"checking_config": "Đang kiểm tra tệp cấu hình",
"config_not_found": "Không tìm thấy tệp cấu hình",
"no_permission": "Không thể đọc hoặc ghi tệp cấu hình, vui lòng kiểm tra quyền tệp",
"reading_config": "Đang đọc cấu hình hiện tại",
"creating_backup": "Đang tạo bản sao lưu cấu hình",
"backup_exists": "Tệp sao lưu đã tồn tại, bỏ qua bước sao lưu",
"generating_new_machine_id": "Đang tạo ID máy mới",
"saving_new_config": "Đang lưu cấu hình mới vào JSON",
"success": "Đặt lại Cursor thành công",
"error": "Đặt lại Cursor thất bại: {error}",
"press_enter": "Nhấn Enter để thoát",
"reset_machine_id": "Đặt lại ID máy",
"database_connection_closed": "Kết nối cơ sở dữ liệu đã đóng",
"database_updated_successfully": "Cập nhật cơ sở dữ liệu thành công",
"connected_to_database": "Đã kết nối với cơ sở dữ liệu",
"updating_pair": "Đang cập nhật cặp khóa-giá trị",
"db_not_found": "Không tìm thấy tệp cơ sở dữ liệu tại: {path}",
"db_permission_error": "Không thể truy cập tệp cơ sở dữ liệu, vui lòng kiểm tra quyền",
"db_connection_error": "Kết nối cơ sở dữ liệu thất bại: {error}",
"feature_title": "TÍNH NĂNG",
"feature_1": "Xóa hoàn toàn các cài đặt và cấu hình của Cursor AI",
"feature_2": "Xóa tất cả dữ liệu bộ nhớ đệm bao gồm lịch sử và gợi ý AI",
"feature_3": "Đặt lại ID máy để vượt qua kiểm tra dùng thử",
"feature_4": "Tạo định danh máy ngẫu nhiên mới",
"feature_5": "Xóa tiện ích mở rộng và tùy chỉnh",
"feature_6": "Đặt lại thông tin dùng thử và dữ liệu kích hoạt",
"feature_7": "Quét sâu các tệp ẩn liên quan đến giấy phép và dùng thử",
"feature_8": "Bảo toàn các tệp và ứng dụng không liên quan đến Cursor",
"feature_9": "Tương thích với Windows, macOS và Linux",
"disclaimer_title": "LƯU Ý",
"disclaimer_1": "Công cụ này sẽ xóa vĩnh viễn tất cả cài đặt,",
"disclaimer_2": "cấu hình và dữ liệu bộ nhớ đệm của Cursor AI. Thao tác này không thể hoàn tác.",
"disclaimer_3": "Tệp mã nguồn của bạn sẽ KHÔNG bị ảnh hưởng, công cụ chỉ nhắm đến",
"disclaimer_4": "các tệp chỉnh sửa Cursor AI và cơ chế kiểm tra dùng thử.",
"disclaimer_5": "Các ứng dụng khác trên hệ thống của bạn sẽ không bị ảnh hưởng.",
"disclaimer_6": "Bạn sẽ cần thiết lập lại Cursor AI sau khi chạy công cụ này.",
"disclaimer_7": "Sử dụng dưới sự tự chịu trách nhiệm",
"confirm_title": "Bạn có chắc chắn muốn tiếp tục không?",
"confirm_1": "Hành động này sẽ xóa tất cả cài đặt,",
"confirm_2": "cấu hình và dữ liệu bộ nhớ đệm của Cursor AI. Hành động này không thể hoàn tác.",
"confirm_3": "Tệp mã nguồn của bạn sẽ KHÔNG bị ảnh hưởng, công cụ chỉ nhắm đến",
"confirm_4": "các tệp chỉnh sửa Cursor AI và cơ chế kiểm tra dùng thử.",
"confirm_5": "Các ứng dụng khác trên hệ thống của bạn sẽ không bị ảnh hưởng.",
"confirm_6": "Bạn sẽ cần thiết lập lại Cursor AI sau khi chạy công cụ này.",
"confirm_7": "Sử dụng dưới sự tự chịu trách nhiệm",
"invalid_choice": "Vui lòng nhập 'Y' hoặc 'n'",
"skipped_for_safety": "Bỏ qua vì an toàn (không liên quan đến Cursor): {path}",
"deleted": "Đã xóa: {path}",
"error_deleting": "Lỗi khi xóa {path}: {error}",
"not_found": "Không tìm thấy tệp: {path}",
"resetting_machine_id": "Đang đặt lại ID máy để vượt qua kiểm tra dùng thử...",
"created_machine_id": "Đã tạo ID máy mới: {path}",
"error_creating_machine_id": "Lỗi khi tạo tệp ID máy {path}: {error}",
"error_searching": "Lỗi khi tìm kiếm tệp trong {path}: {error}",
"created_extended_trial_info": "Đã tạo thông tin dùng thử mở rộng mới: {path}",
"error_creating_trial_info": "Lỗi khi tạo tệp thông tin dùng thử {path}: {error}",
"resetting_cursor_ai_editor": "Đang đặt lại Cursor AI Editor... Vui lòng chờ.",
"reset_cancelled": "Đã hủy đặt lại. Thoát mà không thực hiện thay đổi nào.",
"windows_machine_id_modification_skipped": "Bỏ qua sửa đổi ID máy Windows: {error}",
"linux_machine_id_modification_skipped": "Bỏ qua sửa đổi machine-id Linux: {error}",
"note_complete_machine_id_reset_may_require_running_as_administrator": "Lưu ý: Đặt lại ID máy hoàn toàn có thể yêu cầu chạy dưới quyền quản trị viên",
"note_complete_system_machine_id_reset_may_require_sudo_privileges": "Lưu ý: Đặt lại machine-id hệ thống hoàn toàn có thể yêu cầu quyền sudo",
"windows_registry_instructions": "📝 LƯU Ý: Để đặt lại hoàn toàn trên Windows, bạn có thể cần dọn dẹp các mục registry.",
"windows_registry_instructions_2": " Chạy 'regedit' và tìm kiếm khóa chứa 'Cursor' hoặc 'CursorAI' dưới HKEY_CURRENT_USER\\Software\\ và xóa chúng.\n",
"reset_log_1": "Cursor AI đã được đặt lại hoàn toàn và vượt qua kiểm tra dùng thử!",
"reset_log_2": "Vui lòng khởi động lại hệ thống để thay đổi có hiệu lực.",
"reset_log_3": "Bạn cần cài đặt lại Cursor AI và sẽ có kỳ dùng thử mới.",
"reset_log_4": "Để có kết quả tốt nhất, bạn có thể cân nhắc:",
"reset_log_5": "Sử dụng địa chỉ email khác khi đăng ký dùng thử mới",
"reset_log_6": "Nếu có thể, sử dụng VPN để thay đổi địa chỉ IP",
"reset_log_7": "Xóa cookie và bộ nhớ cache trình duyệt trước khi truy cập trang web Cursor AI",
"reset_log_8": "Nếu vẫn gặp sự cố, hãy thử cài Cursor AI vào vị trí khác",
"reset_log_9": "Nếu gặp bất kỳ vấn đề nào, hãy truy cập Github Issue Tracker và tạo issue tại https://github.com/yeongpin/cursor-free-vip/issues",
"unexpected_error": "Đã xảy ra lỗi không mong muốn: {error}",
"report_issue": "Vui lòng báo cáo sự cố này tại Github Issue Tracker: https://github.com/yeongpin/cursor-free-vip/issues",
"keyboard_interrupt": "Quá trình bị người dùng hủy. Đang thoát...",
"return_to_main_menu": "Trở về menu chính...",
"process_interrupted": "Quá trình bị gián đoạn. Đang thoát...",
"press_enter_to_return_to_main_menu": "Nhấn Enter để trở về menu chính...",
"removing_known": "Đang xóa các tệp thử nghiệm/giấy phép đã biết",
"performing_deep_scan": "Đang quét sâu để tìm thêm tệp thử nghiệm/giấy phép",
"found_additional_potential_license_trial_files": "Đã tìm thấy {count} tệp thử nghiệm/giấy phép tiềm năng bổ sung",
"checking_for_electron_localstorage_files": "Đang kiểm tra các tệp Electron localStorage",
"no_additional_license_trial_files_found_in_deep_scan": "Không tìm thấy thêm tệp thử nghiệm/giấy phép nào trong quá trình quét sâu",
"removing_electron_localstorage_files": "Đang xóa các tệp Electron localStorage",
"electron_localstorage_files_removed": "Đã xóa các tệp Electron localStorage",
"electron_localstorage_files_removal_error": "Lỗi khi xóa các tệp Electron localStorage: {error}",
"removing_electron_localstorage_files_completed": "Đã hoàn tất việc xóa các tệp Electron localStorage"
}
}

View File

@@ -4,6 +4,8 @@
"exit": "退出程序",
"reset": "重置机器标识",
"register": "注册新 Cursor 账号",
"register_google": "使用 Google 账号注册",
"register_github": "使用 GitHub 账号注册",
"register_manual": "使用自定义邮箱注册",
"quit": "关闭 Cursor 应用",
"select_language": "更改语言",
@@ -12,13 +14,18 @@
"program_terminated": "程序已被用户终止",
"error_occurred": "发生错误:{error},请重试",
"press_enter": "按回车键退出",
"disable_auto_update": "禁用 Cursor 自动更新"
"disable_auto_update": "禁用 Cursor 自动更新",
"lifetime_access_enabled": "永久订阅",
"totally_reset": "完全重置 Cursor"
},
"languages": {
"en": "English",
"zh_cn": "简体中文",
"zh_tw": "繁體中文",
"vi": "Vietnamese"
"vi": "Vietnamese",
"nl": "Dutch",
"de": "German",
"fr": "French"
},
"quit_cursor": {
"start": "开始退出 Cursor",
@@ -217,7 +224,7 @@
},
"email": {
"starting_browser": "启动浏览器",
"visiting_site": "访问 mail.tm",
"visiting_site": "访问 邮箱服务网站",
"create_success": "邮箱创建成功",
"create_failed": "邮箱创建失败",
"create_error": "邮箱创建错误: {error}",
@@ -248,7 +255,8 @@
"blocked_domains_loaded_timeout_error": "加载被屏蔽的域名超时错误: {error}",
"available_domains_loaded": "获取到 {count} 个可用域名",
"domains_filtered": "过滤后剩餘 {count} 個可用域名",
"trying_to_create_email": "尝试创建邮箱: {email}"
"trying_to_create_email": "尝试创建邮箱: {email}",
"domain_blocked": "域名被屏蔽: {domain}"
},
"update": {
"title": "禁用 Cursor 自动更新",
@@ -272,6 +280,99 @@
"continue_anyway": "继续使用当前版本...",
"update_confirm": "是否要更新到最新版本? (Y/n)",
"update_skipped": "跳过更新。",
"invalid_choice": "选择无效。请输入 'Y' 或 'n'."
"invalid_choice": "选择无效。请输入 'Y' 或 'n'.",
"development_version": "开发版本 {current} > {latest}",
"changelog_title": "更新日志"
},
"totally_reset": {
"title": "完全重置 Cursor",
"checking_config": "正在检查配置文件",
"config_not_found": "未找到配置文件",
"no_permission": "无法读取或写入配置文件,请检查文件权限",
"reading_config": "正在读取当前配置",
"creating_backup": "正在创建配置备份",
"backup_exists": "备份文件已存在,跳过备份步骤",
"generating_new_machine_id": "正在生成新的机器 ID",
"saving_new_config": "正在将新配置保存为 JSON",
"success": "Cursor 重置成功",
"error": "Cursor 重置失败:{error}",
"press_enter": "按回车键退出",
"reset_machine_id": "重置机器 ID",
"database_connection_closed": "数据库连接已关闭",
"database_updated_successfully": "数据库更新成功",
"connected_to_database": "已连接到数据库",
"updating_pair": "正在更新键值对",
"db_not_found": "未找到数据库文件,路径:{path}",
"db_permission_error": "无法访问数据库文件,请检查权限",
"db_connection_error": "连接数据库失败:{error}",
"feature_title": "功能介绍",
"feature_1": "完全移除 Cursor AI 设置和配置",
"feature_2": "清除所有缓存数据,包括 AI 历史记录和提示",
"feature_3": "重置机器 ID 以绕过试用检测",
"feature_4": "创建新的随机机器标识符",
"feature_5": "移除自定义扩展和偏好设置",
"feature_6": "重置试用信息和激活数据",
"feature_7": "深度扫描隐藏的授权和试用相关文件",
"feature_8": "安全保留非 Cursor 文件和应用程序",
"feature_9": "兼容 Windows、macOS 和 Linux",
"disclaimer_title": "免责声明",
"disclaimer_1": "该工具将永久删除所有 Cursor AI 设置、",
"disclaimer_2": "配置和缓存数据。此操作无法撤销。",
"disclaimer_3": "您的代码文件 **不会** 受到影响,工具设计为",
"disclaimer_4": "仅针对 Cursor AI 编辑器文件和试用检测机制。",
"disclaimer_5": "系统中的其他应用程序不会受到影响。",
"disclaimer_6": "运行此工具后,您需要重新设置 Cursor AI。",
"disclaimer_7": "请自行承担风险",
"confirm_title": "您确定要继续吗?",
"confirm_1": "该操作将删除所有 Cursor AI 设置、",
"confirm_2": "配置和缓存数据。此操作无法撤销。",
"confirm_3": "您的代码文件 **不会** 受到影响,工具设计为",
"confirm_4": "仅针对 Cursor AI 编辑器文件和试用检测机制。",
"confirm_5": "系统中的其他应用程序不会受到影响。",
"confirm_6": "运行此工具后,您需要重新设置 Cursor AI。",
"confirm_7": "请自行承担风险",
"invalid_choice": "请输入 'Y' 或 'n'",
"skipped_for_safety": "出于安全原因跳过(非 Cursor 相关):{path}",
"deleted": "已删除:{path}",
"error_deleting": "删除 {path} 时出错:{error}",
"not_found": "未找到文件:{path}",
"resetting_machine_id": "正在重置机器 ID 以绕过试用检测...",
"created_machine_id": "已创建新的机器 ID{path}",
"error_creating_machine_id": "创建机器 ID 文件 {path} 时出错:{error}",
"error_searching": "在 {path} 搜索文件时出错:{error}",
"created_extended_trial_info": "已创建新的扩展试用信息:{path}",
"error_creating_trial_info": "创建试用信息文件 {path} 时出错:{error}",
"resetting_cursor_ai_editor": "正在重置 Cursor AI 编辑器... 请稍候。",
"reset_cancelled": "重置已取消,未进行任何更改。",
"windows_machine_id_modification_skipped": "跳过 Windows 机器 ID 修改:{error}",
"linux_machine_id_modification_skipped": "跳过 Linux machine-id 修改:{error}",
"note_complete_machine_id_reset_may_require_running_as_administrator": "注意:完整的机器 ID 重置可能需要以管理员身份运行",
"note_complete_system_machine_id_reset_may_require_sudo_privileges": "注意:完整的系统 machine-id 重置可能需要 sudo 权限",
"windows_registry_instructions": "📝 注意:在 Windows 上进行完整重置,您可能还需要清理注册表项。",
"windows_registry_instructions_2": " 运行 'regedit' 并搜索 HKEY_CURRENT_USER\\Software\\ 下包含 'Cursor' 或 'CursorAI' 的键并删除它们。\n",
"reset_log_1": "Cursor AI 已完全重置并绕过试用检测!",
"reset_log_2": "请重启系统以使更改生效。",
"reset_log_3": "您需要重新安装 Cursor AI现在应该有一个新的试用期。",
"reset_log_4": "为了获得最佳效果,建议还可以:",
"reset_log_5": "注册新试用时使用不同的邮箱地址",
"reset_log_6": "如果可能,使用 VPN 更改 IP 地址",
"reset_log_7": "访问 Cursor AI 网站前清除浏览器的 Cookie 和缓存",
"reset_log_8": "如果仍有问题,尝试将 Cursor AI 安装到不同位置",
"reset_log_9": "如遇到任何问题,请到 Github Issue Tracker 提交问题https://github.com/yeongpin/cursor-free-vip/issues",
"unexpected_error": "发生意外错误:{error}",
"report_issue": "请在 Github Issue Tracker 报告此问题https://github.com/yeongpin/cursor-free-vip/issues",
"keyboard_interrupt": "用户中断进程,正在退出...",
"return_to_main_menu": "返回主菜单...",
"process_interrupted": "进程已中断,正在退出...",
"press_enter_to_return_to_main_menu": "按回车键返回主菜单...",
"removing_known": "正在移除已知的试用/授权文件",
"performing_deep_scan": "正在进行深度扫描以查找其他试用/授权文件",
"found_additional_potential_license_trial_files": "发现 {count} 个其他潜在的试用/授权文件",
"checking_for_electron_localstorage_files": "正在检查 Electron localStorage 文件",
"no_additional_license_trial_files_found_in_deep_scan": "深度扫描中未发现其他试用/授权文件",
"removing_electron_localstorage_files": "正在移除 Electron localStorage 文件",
"electron_localstorage_files_removed": "Electron localStorage 文件已移除",
"electron_localstorage_files_removal_error": "移除 Electron localStorage 文件时出错:{error}",
"removing_electron_localstorage_files_completed": "Electron localStorage 文件移除完成"
}
}

View File

@@ -12,13 +12,18 @@
"program_terminated": "程式已被使用者終止",
"error_occurred": "發生錯誤:{error},請重試",
"press_enter": "按返回鍵退出",
"disable_auto_update": "用 Cursor 自動更新"
"disable_auto_update": "用 Cursor 自動更新",
"lifetime_access_enabled": "終身訪問已啟用",
"totally_reset": "完全重置 Cursor"
},
"languages": {
"en": "English",
"zh_cn": "简体中文",
"zh_tw": "繁體中文",
"vi": "Vietnamese"
"vi": "Vietnamese",
"nl": "Dutch",
"de": "German",
"fr": "French"
},
"quit_cursor": {
"start": "開始退出 Cursor",
@@ -199,7 +204,7 @@
},
"email": {
"starting_browser": "啟動瀏覽器",
"visiting_site": "訪問 mail.tm",
"visiting_site": "訪問 郵箱網站",
"create_success": "郵箱創建成功",
"create_failed": "郵箱創建失敗",
"create_error": "郵箱創建錯誤: {error}",
@@ -254,6 +259,99 @@
"continue_anyway": "繼續使用當前版本...",
"update_confirm": "是否要更新到最新版本? (Y/n)",
"update_skipped": "跳過更新。",
"invalid_choice": "選擇無效。請輸入 'Y' 或 'n'."
}
"invalid_choice": "選擇無效。請輸入 'Y' 或 'n'.",
"development_version": "開發版本 {current} > {latest}",
"changelog_title": "更新日志"
},
"totally_reset": {
"title": "完全重置 Cursor",
"checking_config": "正在檢查配置檔案",
"config_not_found": "找不到配置檔案",
"no_permission": "無法讀取或寫入配置檔案,請檢查檔案權限",
"reading_config": "正在讀取當前配置",
"creating_backup": "正在建立配置備份",
"backup_exists": "備份檔案已存在,跳過備份步驟",
"generating_new_machine_id": "正在生成新的機器 ID",
"saving_new_config": "正在將新配置保存到 JSON",
"success": "Cursor 重置成功",
"error": "Cursor 重置失敗:{error}",
"press_enter": "按 Enter 鍵退出",
"reset_machine_id": "重置機器 ID",
"database_connection_closed": "資料庫連線已關閉",
"database_updated_successfully": "資料庫更新成功",
"connected_to_database": "已連接到資料庫",
"updating_pair": "正在更新鍵值對",
"db_not_found": "未找到資料庫檔案,路徑:{path}",
"db_permission_error": "無法訪問資料庫檔案,請檢查權限",
"db_connection_error": "連接資料庫失敗:{error}",
"feature_title": "功能特色",
"feature_1": "完全移除 Cursor AI 設定與配置",
"feature_2": "清除所有快取資料,包括 AI 歷史與提示",
"feature_3": "重置機器 ID 以繞過試用偵測",
"feature_4": "建立新的隨機機器標識",
"feature_5": "移除自訂擴充功能與偏好設定",
"feature_6": "重置試用資訊與啟動資料",
"feature_7": "深度掃描隱藏的授權與試用相關檔案",
"feature_8": "安全保留非 Cursor 相關檔案與應用程式",
"feature_9": "相容於 Windows、macOS 與 Linux",
"disclaimer_title": "免責聲明",
"disclaimer_1": "此工具將永久刪除所有 Cursor AI 設定、",
"disclaimer_2": "配置與快取資料。此操作無法還原。",
"disclaimer_3": "您的程式碼檔案將 **不會** 受到影響,且此工具僅針對",
"disclaimer_4": "Cursor AI 編輯器檔案與試用偵測機制。",
"disclaimer_5": "系統中的其他應用程式不會受到影響。",
"disclaimer_6": "執行此工具後,您需要重新設定 Cursor AI。",
"disclaimer_7": "請自行承擔風險",
"confirm_title": "您確定要繼續嗎?",
"confirm_1": "此操作將刪除所有 Cursor AI 設定、",
"confirm_2": "配置與快取資料。此操作無法還原。",
"confirm_3": "您的程式碼檔案將 **不會** 受到影響,且此工具僅針對",
"confirm_4": "Cursor AI 編輯器檔案與試用偵測機制。",
"confirm_5": "系統中的其他應用程式不會受到影響。",
"confirm_6": "執行此工具後,您需要重新設定 Cursor AI。",
"confirm_7": "請自行承擔風險",
"invalid_choice": "請輸入 'Y' 或 'n'",
"skipped_for_safety": "出於安全考量跳過(與 Cursor 無關):{path}",
"deleted": "已刪除:{path}",
"error_deleting": "刪除 {path} 時出錯:{error}",
"not_found": "未找到檔案:{path}",
"resetting_machine_id": "正在重置機器 ID 以繞過試用偵測...",
"created_machine_id": "已建立新的機器 ID{path}",
"error_creating_machine_id": "建立機器 ID 檔案 {path} 時出錯:{error}",
"error_searching": "在 {path} 搜尋檔案時出錯:{error}",
"created_extended_trial_info": "已建立新的擴展試用資訊:{path}",
"error_creating_trial_info": "建立試用資訊檔案 {path} 時出錯:{error}",
"resetting_cursor_ai_editor": "正在重置 Cursor AI 編輯器... 請稍候。",
"reset_cancelled": "重置已取消,未進行任何更改。",
"windows_machine_id_modification_skipped": "跳過 Windows 機器 ID 修改:{error}",
"linux_machine_id_modification_skipped": "跳過 Linux machine-id 修改:{error}",
"note_complete_machine_id_reset_may_require_running_as_administrator": "注意:完整的機器 ID 重置可能需要以管理員身份執行",
"note_complete_system_machine_id_reset_may_require_sudo_privileges": "注意:完整的系統 machine-id 重置可能需要 sudo 權限",
"windows_registry_instructions": "📝 注意:在 Windows 上進行完整重置,您可能還需要清理登錄檔項目。",
"windows_registry_instructions_2": " 執行 'regedit' 並搜尋 HKEY_CURRENT_USER\\Software\\ 下包含 'Cursor' 或 'CursorAI' 的鍵並刪除它們。\n",
"reset_log_1": "Cursor AI 已完全重置並繞過試用偵測!",
"reset_log_2": "請重新啟動系統以使更改生效。",
"reset_log_3": "您需要重新安裝 Cursor AI現在應該有全新的試用期。",
"reset_log_4": "為獲得最佳效果,建議還可以:",
"reset_log_5": "註冊新試用時使用不同的電子郵件地址",
"reset_log_6": "若有可能,使用 VPN 變更 IP 地址",
"reset_log_7": "在造訪 Cursor AI 網站前清除瀏覽器的 Cookie 與快取",
"reset_log_8": "若仍有問題,嘗試將 Cursor AI 安裝到不同位置",
"reset_log_9": "若遇到任何問題,請到 Github Issue Tracker 提交問題https://github.com/yeongpin/cursor-free-vip/issues",
"unexpected_error": "發生非預期錯誤:{error}",
"report_issue": "請在 Github Issue Tracker 回報此問題https://github.com/yeongpin/cursor-free-vip/issues",
"keyboard_interrupt": "使用者中斷流程,正在退出...",
"return_to_main_menu": "返回主選單...",
"process_interrupted": "流程已中斷,正在退出...",
"press_enter_to_return_to_main_menu": "按 Enter 鍵返回主選單...",
"removing_known": "正在移除已知的試用/授權檔案",
"performing_deep_scan": "正在進行深度掃描以查找其他試用/授權檔案",
"found_additional_potential_license_trial_files": "找到 {count} 個其他潛在試用/授權檔案",
"checking_for_electron_localstorage_files": "正在檢查 Electron localStorage 檔案",
"no_additional_license_trial_files_found_in_deep_scan": "深度掃描中未發現其他試用/授權檔案",
"removing_electron_localstorage_files": "正在移除 Electron localStorage 檔案",
"electron_localstorage_files_removed": "已移除 Electron localStorage 檔案",
"electron_localstorage_files_removal_error": "移除 Electron localStorage 檔案時出錯:{error}",
"removing_electron_localstorage_files_completed": "Electron localStorage 檔案移除完成"
}
}

112
main.py
View File

@@ -133,6 +133,13 @@ class Translator:
return 'en'
elif system_locale.startswith('vi'):
return 'vi'
elif system_locale.startswith('nl'):
return 'nl'
elif system_locale.startswith('de'):
return 'de'
elif system_locale.startswith('fr'):
return 'fr'
# Try to get language from LANG environment variable as fallback
@@ -143,7 +150,12 @@ class Translator:
return 'zh_cn'
elif 'vi' in env_lang:
return 'vi'
elif 'nl' in env_lang:
return 'nl'
elif 'de' in env_lang:
return 'de'
elif 'fr' in env_lang:
return 'fr'
return 'en'
except:
@@ -219,10 +231,15 @@ def print_menu():
print(f"{Fore.GREEN}0{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.exit')}")
print(f"{Fore.GREEN}1{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.reset')}")
print(f"{Fore.GREEN}2{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register')}")
print(f"{Fore.GREEN}3{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register_manual')}")
print(f"{Fore.GREEN}4{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.quit')}")
print(f"{Fore.GREEN}5{Style.RESET_ALL}. {EMOJI['LANG']} {translator.get('menu.select_language')}")
print(f"{Fore.GREEN}6{Style.RESET_ALL}. {EMOJI['UPDATE']} {translator.get('menu.disable_auto_update')}")
print(f"{Fore.GREEN}3{Style.RESET_ALL}. 🌟 {translator.get('menu.register_google')}")
print(f"{Fore.YELLOW} ┗━━ 🔥 {translator.get('menu.lifetime_access_enabled')} 🔥{Style.RESET_ALL}")
print(f"{Fore.GREEN}4{Style.RESET_ALL}. {translator.get('menu.register_github')}")
print(f"{Fore.YELLOW} ┗━━ 🚀 {translator.get('menu.lifetime_access_enabled')} 🚀{Style.RESET_ALL}")
print(f"{Fore.GREEN}5{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register_manual')}")
print(f"{Fore.GREEN}6{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.quit')}")
print(f"{Fore.GREEN}7{Style.RESET_ALL}. {EMOJI['LANG']} {translator.get('menu.select_language')}")
print(f"{Fore.GREEN}8{Style.RESET_ALL}. {EMOJI['UPDATE']} {translator.get('menu.disable_auto_update')}")
print(f"{Fore.GREEN}9{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.totally_reset')}")
print(f"{Fore.YELLOW}{'' * 40}{Style.RESET_ALL}")
def select_language():
@@ -277,9 +294,66 @@ def check_latest_version():
if not latest_version:
raise Exception("Invalid version format received")
if latest_version != version:
# Parse versions for proper comparison
def parse_version(version_str):
"""Parse version string into tuple for proper comparison"""
try:
return tuple(map(int, version_str.split('.')))
except ValueError:
# Fallback to string comparison if parsing fails
return version_str
current_version_tuple = parse_version(version)
latest_version_tuple = parse_version(latest_version)
# Compare versions properly
is_newer_version_available = False
if isinstance(current_version_tuple, tuple) and isinstance(latest_version_tuple, tuple):
is_newer_version_available = current_version_tuple < latest_version_tuple
else:
# Fallback to string comparison
is_newer_version_available = version != latest_version
if is_newer_version_available:
print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('updater.new_version_available', current=version, latest=latest_version)}{Style.RESET_ALL}")
# get and show changelog
try:
changelog_url = "https://raw.githubusercontent.com/yeongpin/cursor-free-vip/main/CHANGELOG.md"
changelog_response = requests.get(changelog_url, timeout=10)
if changelog_response.status_code == 200:
changelog_content = changelog_response.text
# get latest version changelog
latest_version_pattern = f"## v{latest_version}"
changelog_sections = changelog_content.split("## v")
latest_changes = None
for section in changelog_sections:
if section.startswith(latest_version):
latest_changes = section
break
if latest_changes:
print(f"\n{Fore.CYAN}{'' * 40}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{translator.get('updater.changelog_title')}:{Style.RESET_ALL}")
# show changelog content (max 10 lines)
changes_lines = latest_changes.strip().split('\n')
for i, line in enumerate(changes_lines[1:11]): # skip version number line, max 10 lines
if line.strip():
print(f"{Fore.WHITE}{line.strip()}{Style.RESET_ALL}")
# if changelog more than 10 lines, show ellipsis
if len(changes_lines) > 11:
print(f"{Fore.WHITE}...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{'' * 40}{Style.RESET_ALL}")
except Exception as changelog_error:
# get changelog failed
pass
# Ask user if they want to update
while True:
choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('updater.update_confirm', choices='Y/n')}: {Style.RESET_ALL}").lower()
@@ -324,7 +398,11 @@ def check_latest_version():
print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('updater.manual_update_required')}{Style.RESET_ALL}")
return
else:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('updater.up_to_date')}{Style.RESET_ALL}")
# If current version is newer or equal to latest version
if current_version_tuple > latest_version_tuple:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('updater.development_version', current=version, latest=latest_version)}{Style.RESET_ALL}")
else:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('updater.up_to_date')}{Style.RESET_ALL}")
except requests.exceptions.RequestException as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('updater.network_error', error=str(e))}{Style.RESET_ALL}")
@@ -358,7 +436,7 @@ def main():
while True:
try:
choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices='0-6')}: {Style.RESET_ALL}")
choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices='0-9')}: {Style.RESET_ALL}")
if choice == "0":
print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.exit')}...{Style.RESET_ALL}")
@@ -373,21 +451,33 @@ def main():
cursor_register.main(translator)
print_menu()
elif choice == "3":
import cursor_register_google
cursor_register_google.main(translator)
print_menu()
elif choice == "4":
import cursor_register_github
cursor_register_github.main(translator)
print_menu()
elif choice == "5":
import cursor_register_manual
cursor_register_manual.main(translator)
print_menu()
elif choice == "4":
elif choice == "6":
import quit_cursor
quit_cursor.quit_cursor(translator)
print_menu()
elif choice == "5":
elif choice == "7":
if select_language():
print_menu()
continue
elif choice == "6":
elif choice == "8":
import disable_auto_update
disable_auto_update.run(translator)
print_menu()
elif choice == "9":
import totally_reset_cursor
totally_reset_cursor.run(translator)
print_menu()
else:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}")
print_menu()

View File

@@ -6,6 +6,7 @@ from colorama import Fore, Style, init
import requests
import random
import string
from utils import get_random_wait_time
# Initialize colorama
init()
@@ -13,17 +14,8 @@ init()
class NewTempEmail:
def __init__(self, translator=None):
self.translator = translator
# Randomly choose between mail.tm and mail.gw
self.services = [
{"name": "mail.tm", "api_url": "https://api.mail.tm"},
{"name": "mail.gw", "api_url": "https://api.mail.gw"}
]
self.selected_service = random.choice(self.services)
self.api_url = self.selected_service["api_url"]
self.token = None
self.email = None
self.password = None
self.blocked_domains = self.get_blocked_domains()
self.page = None
self.setup_browser()
def get_blocked_domains(self):
"""Get blocked domains list"""
@@ -38,12 +30,37 @@ class NewTempEmail:
else:
print(f"{Fore.CYAN} 已加载 {len(domains)} 个被屏蔽的域名{Style.RESET_ALL}")
return domains
return []
return self._load_local_blocked_domains()
except Exception as e:
if self.translator:
print(f"{Fore.YELLOW}⚠️ {self.translator.get('email.blocked_domains_error', error=str(e))}{Style.RESET_ALL}")
else:
print(f"{Fore.YELLOW}⚠️ 获取被屏蔽域名列表失败: {str(e)}{Style.RESET_ALL}")
return self._load_local_blocked_domains()
def _load_local_blocked_domains(self):
"""Load blocked domains from local file as fallback"""
try:
local_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "block_domain.txt")
if os.path.exists(local_path):
with open(local_path, 'r', encoding='utf-8') as f:
domains = [line.strip() for line in f.readlines() if line.strip()]
if self.translator:
print(f"{Fore.CYAN} {self.translator.get('email.local_blocked_domains_loaded', count=len(domains))}{Style.RESET_ALL}")
else:
print(f"{Fore.CYAN} 已从本地加载 {len(domains)} 个被屏蔽的域名{Style.RESET_ALL}")
return domains
else:
if self.translator:
print(f"{Fore.YELLOW}⚠️ {self.translator.get('email.local_blocked_domains_not_found')}{Style.RESET_ALL}")
else:
print(f"{Fore.YELLOW}⚠️ 本地被屏蔽域名文件不存在{Style.RESET_ALL}")
return []
except Exception as e:
if self.translator:
print(f"{Fore.YELLOW}⚠️ {self.translator.get('email.local_blocked_domains_error', error=str(e))}{Style.RESET_ALL}")
else:
print(f"{Fore.YELLOW}⚠️ 读取本地被屏蔽域名文件失败: {str(e)}{Style.RESET_ALL}")
return []
def exclude_blocked_domains(self, domains):
@@ -65,184 +82,132 @@ class NewTempEmail:
return filtered_domains
def _generate_credentials(self):
"""generate random username and password"""
username = ''.join(random.choices(string.ascii_lowercase + string.digits, k=10))
password = ''.join(random.choices(string.ascii_letters + string.digits + string.punctuation, k=12))
return username, password
def create_email(self):
"""create temporary email"""
max_retries = 3 # Maximum number of retries
attempt = 0 # Current attempt count
def get_extension_block(self):
"""获取插件路径"""
root_dir = os.getcwd()
extension_path = os.path.join(root_dir, "PBlock")
while attempt < max_retries:
attempt += 1
if hasattr(sys, "_MEIPASS"):
extension_path = os.path.join(sys._MEIPASS, "PBlock")
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:
if self.translator:
print(f"{Fore.CYAN} {self.translator.get('email.visiting_site').replace('mail.tm', self.selected_service['name'])}{Style.RESET_ALL}")
else:
print(f"{Fore.CYAN} 正在访问 {self.selected_service['name']}...{Style.RESET_ALL}")
# Get available domain list
try:
domains_response = requests.get(f"{self.api_url}/domains", timeout=10)
if domains_response.status_code != 200:
print(f"{Fore.RED}{self.translator.get('email.domains_list_error', error=domains_response.status_code)}{Style.RESET_ALL}")
print(f"{Fore.RED}{self.translator.get('email.domains_list_error', error=domains_response.text)}{Style.RESET_ALL}")
raise Exception(f"{self.translator.get('email.failed_to_get_available_domains') if self.translator else 'Failed to get available domains'}")
domains = domains_response.json()["hydra:member"]
print(f"{Fore.CYAN} {self.translator.get('email.available_domains_loaded', count=len(domains))}{Style.RESET_ALL}")
if not domains:
raise Exception(f"{self.translator.get('email.no_available_domains') if self.translator else '没有可用域名'}")
except Exception as e:
print(f"{Fore.RED}❌ 获取域名列表时出错: {str(e)}{Style.RESET_ALL}")
raise
# Exclude blocked domains
try:
filtered_domains = self.exclude_blocked_domains(domains)
if self.translator:
print(f"{Fore.CYAN} {self.translator.get('email.domains_filtered', count=len(filtered_domains))}{Style.RESET_ALL}")
else:
print(f"{Fore.CYAN} 过滤后剩余 {len(filtered_domains)} 个可用域名{Style.RESET_ALL}")
if not filtered_domains:
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.all_domains_blocked')}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 所有域名都被屏蔽了,尝试切换服务{Style.RESET_ALL}")
# Switch to another service
for service in self.services:
if service["api_url"] != self.api_url:
self.selected_service = service
self.api_url = service["api_url"]
if self.translator:
print(f"{Fore.CYAN} {self.translator.get('email.switching_service', service=service['name'])}{Style.RESET_ALL}")
else:
print(f"{Fore.CYAN} 切换到 {service['name']} 服务{Style.RESET_ALL}")
return self.create_email() # Recursively call
raise Exception(f"{self.translator.get('email.no_available_domains_after_filtering') if self.translator else '过滤后没有可用域名'}")
except Exception as e:
print(f"{Fore.RED}❌ 过滤域名时出错: {str(e)}{Style.RESET_ALL}")
raise
# Generate random username and password
try:
username, password = self._generate_credentials()
self.password = password
# Create email account
selected_domain = filtered_domains[0]['domain']
email = f"{username}@{selected_domain}"
if self.translator:
print(f"{Fore.CYAN} {self.translator.get('email.trying_to_create_email', email=email)}{Style.RESET_ALL}")
else:
print(f"{Fore.CYAN} 尝试创建邮箱: {email}{Style.RESET_ALL}")
account_data = {
"address": email,
"password": password
}
except Exception as e:
print(f"{Fore.RED}❌ 生成凭据时出错: {str(e)}{Style.RESET_ALL}")
raise
# Create account
try:
create_response = requests.post(f"{self.api_url}/accounts", json=account_data, timeout=15)
if create_response.status_code != 201:
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.failed_to_create_account', error=create_response.status_code)}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 创建账户失败: 状态码 {create_response.status_code}{Style.RESET_ALL}")
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.failed_to_create_account', error=create_response.text)}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 响应内容: {create_response.text}{Style.RESET_ALL}")
# If it's a domain problem, try the next available domain
if len(filtered_domains) > 1 and ("domain" in create_response.text.lower() or "address" in create_response.text.lower()):
print(f"{Fore.YELLOW}⚠️ 尝试使用下一个可用域名...{Style.RESET_ALL}")
# Add current domain to blocked list
if selected_domain not in self.blocked_domains:
self.blocked_domains.append(selected_domain)
# Recursively call yourself
return self.create_email()
raise Exception(f"{self.translator.get('email.failed_to_create_account') if self.translator else '创建账户失败'}")
except Exception as e:
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.failed_to_create_account', error=str(e))}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 创建账户时出错: {str(e)}{Style.RESET_ALL}")
raise
# Get access token
try:
token_data = {
"address": email,
"password": password
}
token_response = requests.post(f"{self.api_url}/token", json=token_data, timeout=10)
if token_response.status_code != 200:
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.failed_to_get_access_token', error=token_response.status_code)}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 获取令牌失败: 状态码 {token_response.status_code}{Style.RESET_ALL}")
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.failed_to_get_access_token', error=token_response.text)}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ 响应内容: {token_response.text}{Style.RESET_ALL}")
raise Exception(f"{self.translator.get('email.failed_to_get_access_token') if self.translator else '获取访问令牌失败'}")
self.token = token_response.json()["token"]
self.email = email
except Exception as e:
print(f"{Fore.RED}❌ 获取令牌时出错: {str(e)}{Style.RESET_ALL}")
raise
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
extension_path = self.get_extension_block()
co.set_argument("--allow-extensions-in-incognito")
co.add_extension(extension_path)
except Exception as e:
if attempt < max_retries:
print(f"{Fore.YELLOW}⚠️ 尝试重新创建邮箱... (尝试 {attempt}/{max_retries}){Style.RESET_ALL}")
if self.translator:
print(f"{Fore.YELLOW}⚠️ {self.translator.get('email.extension_load_error')}: {str(e)}{Style.RESET_ALL}")
else:
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
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.blocked_domains = self.get_blocked_domains()
# 访问网站
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: # 验证是否是有效的邮箱地址
# 检查域名是否被屏蔽
domain = email.split('@')[1]
if self.blocked_domains and domain in self.blocked_domains:
if self.translator:
print(f"{Fore.YELLOW}⚠️ {self.translator.get('email.domain_blocked')}: {domain}{Style.RESET_ALL}")
else:
print(f"{Fore.YELLOW}⚠️ 域名已被屏蔽: {domain},尝试重新创建邮箱{Style.RESET_ALL}")
# 重新创建邮箱
return self.create_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):
"""close browser"""
"""关闭浏览器"""
if self.page:
self.page.quit()
def refresh_inbox(self):
"""refresh inbox"""
"""刷新邮箱"""
try:
if self.translator:
print(f"{Fore.CYAN}🔄 {self.translator.get('email.refreshing')}{Style.RESET_ALL}")
else:
print(f"{Fore.CYAN}🔄 正在刷新邮箱...{Style.RESET_ALL}")
# Use API to get latest email
headers = {"Authorization": f"Bearer {self.token}"}
response = requests.get(f"{self.api_url}/messages", headers=headers)
if response.status_code == 200:
# 点击刷新按钮
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:
@@ -250,9 +215,9 @@ class NewTempEmail:
return True
if self.translator:
print(f"{Fore.RED}{self.translator.get('email.refresh_failed')}{Style.RESET_ALL}")
print(f"{Fore.RED}{self.translator.get('email.refresh_button_not_found')}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}刷新邮箱失败{Style.RESET_ALL}")
print(f"{Fore.RED}未找到刷新按钮{Style.RESET_ALL}")
return False
except Exception as e:
@@ -263,26 +228,19 @@ class NewTempEmail:
return False
def check_for_cursor_email(self):
"""Check if there is a Cursor verification email"""
"""检查是否有 Cursor 的验证邮件"""
try:
# Use API to get email list
headers = {"Authorization": f"Bearer {self.token}"}
response = requests.get(f"{self.api_url}/messages", headers=headers)
if response.status_code == 200:
messages = response.json()["hydra:member"]
for message in messages:
if message["from"]["address"] == "no-reply@cursor.sh" and "Verify your email address" in message["subject"]:
# Get email content
message_id = message["id"]
message_response = requests.get(f"{self.api_url}/messages/{message_id}", headers=headers)
if message_response.status_code == 200:
if self.translator:
print(f"{Fore.GREEN}{self.translator.get('email.verification_found')}{Style.RESET_ALL}")
else:
print(f"{Fore.GREEN}✅ 找到验证邮件{Style.RESET_ALL}")
return True
# 查找验证邮件 - 使用更精确的选择器
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:
@@ -297,35 +255,18 @@ class NewTempEmail:
return False
def get_verification_code(self):
"""get verification code"""
"""获取验证码"""
try:
# Use API to get email list
headers = {"Authorization": f"Bearer {self.token}"}
response = requests.get(f"{self.api_url}/messages", headers=headers)
if response.status_code == 200:
messages = response.json()["hydra:member"]
for message in messages:
if message["from"]["address"] == "no-reply@cursor.sh" and "Verify your email address" in message["subject"]:
# Get email content
message_id = message["id"]
message_response = requests.get(f"{self.api_url}/messages/{message_id}", headers=headers)
if message_response.status_code == 200:
# Extract verification code from email content
email_content = message_response.json()["text"]
# Find 6-digit verification code
import re
code_match = re.search(r'\b\d{6}\b', email_content)
if code_match:
code = code_match.group(0)
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
# 查找验证码元素
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:
@@ -350,7 +291,7 @@ def main(translator=None):
else:
print(f"\n{Fore.CYAN}📧 临时邮箱地址: {email}{Style.RESET_ALL}")
# Test refresh function
# 测试刷新功能
while True:
if translator:
choice = input(f"\n{translator.get('email.refresh_prompt')}: ").lower()
@@ -365,4 +306,4 @@ def main(translator=None):
temp_email.close()
if __name__ == "__main__":
main()
main()

826
oauth_auth.py Normal file
View File

@@ -0,0 +1,826 @@
import os
from colorama import Fore, Style, init
import time
import random
import webbrowser
import sys
import json
from DrissionPage import ChromiumPage, ChromiumOptions
from cursor_auth import CursorAuth
from utils import get_random_wait_time, get_default_chrome_path
from config import get_config
import platform
# Initialize colorama
init()
# Define emoji constants
EMOJI = {
'START': '🚀',
'OAUTH': '🔑',
'SUCCESS': '',
'ERROR': '',
'WAIT': '',
'INFO': ''
}
class OAuthHandler:
def __init__(self, translator=None):
self.translator = translator
self.config = get_config(translator)
os.environ['BROWSER_HEADLESS'] = 'False'
self.browser = None
def _get_active_profile(self, user_data_dir):
"""Find the existing default/active Chrome profile"""
try:
# List all profile directories
profiles = []
for item in os.listdir(user_data_dir):
if item == 'Default' or (item.startswith('Profile ') and os.path.isdir(os.path.join(user_data_dir, item))):
profiles.append(item)
if not profiles:
print(f"{Fore.YELLOW}{EMOJI['INFO']} No Chrome profiles found, using Default{Style.RESET_ALL}")
return 'Default'
# First check if Default profile exists
if 'Default' in profiles:
print(f"{Fore.CYAN}{EMOJI['INFO']} Found Default Chrome profile{Style.RESET_ALL}")
return 'Default'
# If no Default profile, check Local State for last used profile
local_state_path = os.path.join(user_data_dir, 'Local State')
if os.path.exists(local_state_path):
with open(local_state_path, 'r', encoding='utf-8') as f:
local_state = json.load(f)
# Get info about last used profile
profile_info = local_state.get('profile', {})
last_used = profile_info.get('last_used', '')
info_cache = profile_info.get('info_cache', {})
# Try to find an active profile
for profile in profiles:
profile_path = profile.replace('\\', '/')
if profile_path in info_cache:
#print(f"{Fore.CYAN}{EMOJI['INFO']} Using existing Chrome profile: {profile}{Style.RESET_ALL}")
return profile
# If no profile found in Local State, use the first available profile
print(f"{Fore.CYAN}{EMOJI['INFO']} Using first available Chrome profile: {profiles[0]}{Style.RESET_ALL}")
return profiles[0]
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Error finding Chrome profile, using Default: {str(e)}{Style.RESET_ALL}")
return 'Default'
def setup_browser(self):
"""Setup browser for OAuth flow using active profile"""
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} Initializing browser setup...{Style.RESET_ALL}")
# Platform-specific initialization
platform_name = platform.system().lower()
print(f"{Fore.CYAN}{EMOJI['INFO']} Detected platform: {platform_name}{Style.RESET_ALL}")
# Kill existing browser processes
self._kill_browser_processes()
# Get browser paths and user data directory
user_data_dir = self._get_user_data_directory()
chrome_path = self._get_browser_path()
if not chrome_path:
raise Exception(f"No compatible browser found. Please install Google Chrome or Chromium.\nSupported browsers for {platform_name}:\n" +
"- Windows: Google Chrome, Chromium\n" +
"- macOS: Google Chrome, Chromium\n" +
"- Linux: Google Chrome, Chromium, chromium-browser")
# Get active profile
active_profile = self._get_active_profile(user_data_dir)
print(f"{Fore.CYAN}{EMOJI['INFO']} Using browser profile: {active_profile}{Style.RESET_ALL}")
# Configure browser options
co = self._configure_browser_options(chrome_path, user_data_dir, active_profile)
print(f"{Fore.CYAN}{EMOJI['INFO']} Starting browser at: {chrome_path}{Style.RESET_ALL}")
self.browser = ChromiumPage(co)
# Verify browser launched successfully
if not self.browser:
raise Exception("Failed to initialize browser instance")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Browser setup completed successfully{Style.RESET_ALL}")
return True
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Browser setup failed: {str(e)}{Style.RESET_ALL}")
if "DevToolsActivePort file doesn't exist" in str(e):
print(f"{Fore.YELLOW}{EMOJI['INFO']} Try running with administrator/root privileges{Style.RESET_ALL}")
elif "Chrome failed to start" in str(e):
print(f"{Fore.YELLOW}{EMOJI['INFO']} Make sure Chrome/Chromium is properly installed{Style.RESET_ALL}")
return False
def _kill_browser_processes(self):
"""Kill existing browser processes based on platform"""
try:
if os.name == 'nt': # Windows
processes = ['chrome.exe', 'chromium.exe']
for proc in processes:
os.system(f'taskkill /f /im {proc} >nul 2>&1')
else: # Linux/Mac
processes = ['chrome', 'chromium', 'chromium-browser']
for proc in processes:
os.system(f'pkill -f {proc} >/dev/null 2>&1')
time.sleep(1) # Wait for processes to close
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Warning: Could not kill existing browser processes: {e}{Style.RESET_ALL}")
def _get_user_data_directory(self):
"""Get the appropriate user data directory based on platform"""
try:
if os.name == 'nt': # Windows
possible_paths = [
os.path.expandvars(r'%LOCALAPPDATA%\Google\Chrome\User Data'),
os.path.expandvars(r'%LOCALAPPDATA%\Chromium\User Data')
]
elif sys.platform == 'darwin': # macOS
possible_paths = [
os.path.expanduser('~/Library/Application Support/Google/Chrome'),
os.path.expanduser('~/Library/Application Support/Chromium')
]
else: # Linux
possible_paths = [
os.path.expanduser('~/.config/google-chrome'),
os.path.expanduser('~/.config/chromium'),
'/usr/bin/google-chrome',
'/usr/bin/chromium-browser'
]
# Try each possible path
for path in possible_paths:
if os.path.exists(path):
print(f"{Fore.CYAN}{EMOJI['INFO']} Found browser data directory: {path}{Style.RESET_ALL}")
return path
# Create temporary profile if no existing profile found
temp_profile = os.path.join(os.path.expanduser('~'), '.cursor_temp_profile')
print(f"{Fore.YELLOW}{EMOJI['INFO']} Creating temporary profile at: {temp_profile}{Style.RESET_ALL}")
os.makedirs(temp_profile, exist_ok=True)
return temp_profile
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Error getting user data directory: {e}{Style.RESET_ALL}")
raise
def _get_browser_path(self):
"""Get the browser executable path based on platform"""
try:
# Try default path first
chrome_path = get_default_chrome_path()
if chrome_path and os.path.exists(chrome_path):
return chrome_path
print(f"{Fore.YELLOW}{EMOJI['INFO']} Searching for alternative browser installations...{Style.RESET_ALL}")
# Platform-specific paths
if os.name == 'nt': # Windows
alt_paths = [
r'C:\Program Files\Google\Chrome\Application\chrome.exe',
r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe',
r'C:\Program Files\Chromium\Application\chrome.exe',
os.path.expandvars(r'%ProgramFiles%\Google\Chrome\Application\chrome.exe'),
os.path.expandvars(r'%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe')
]
elif sys.platform == 'darwin': # macOS
alt_paths = [
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Chromium.app/Contents/MacOS/Chromium',
'~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'~/Applications/Chromium.app/Contents/MacOS/Chromium'
]
else: # Linux
alt_paths = [
'/usr/bin/google-chrome',
'/usr/bin/chromium-browser',
'/usr/bin/chromium',
'/snap/bin/chromium',
'/usr/local/bin/chrome',
'/usr/local/bin/chromium'
]
# Try each alternative path
for path in alt_paths:
expanded_path = os.path.expanduser(path)
if os.path.exists(expanded_path):
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Found browser at: {expanded_path}{Style.RESET_ALL}")
return expanded_path
return None
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Error finding browser path: {e}{Style.RESET_ALL}")
return None
def _configure_browser_options(self, chrome_path, user_data_dir, active_profile):
"""Configure browser options based on platform"""
try:
co = ChromiumOptions()
co.set_paths(browser_path=chrome_path, user_data_path=user_data_dir)
co.set_argument(f'--profile-directory={active_profile}')
# Basic options
co.set_argument('--no-first-run')
co.set_argument('--no-default-browser-check')
co.set_argument('--disable-gpu')
# Platform-specific options
if sys.platform.startswith('linux'):
co.set_argument('--no-sandbox')
co.set_argument('--disable-dev-shm-usage')
co.set_argument('--disable-setuid-sandbox')
elif sys.platform == 'darwin':
co.set_argument('--disable-gpu-compositing')
elif os.name == 'nt':
co.set_argument('--disable-features=TranslateUI')
co.set_argument('--disable-features=RendererCodeIntegrity')
return co
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Error configuring browser options: {e}{Style.RESET_ALL}")
raise
def handle_google_auth(self):
"""Handle Google OAuth authentication"""
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.google_start')}{Style.RESET_ALL}")
# Setup browser
if not self.setup_browser():
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.browser_failed')}{Style.RESET_ALL}")
return False, None
# Navigate to auth URL
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} Navigating to authentication page...{Style.RESET_ALL}")
self.browser.get("https://authenticator.cursor.sh/sign-up")
time.sleep(get_random_wait_time(self.config, 'page_load_wait'))
# Look for Google auth button
selectors = [
"//a[contains(@href,'GoogleOAuth')]",
"//a[contains(@class,'auth-method-button') and contains(@href,'GoogleOAuth')]",
"(//a[contains(@class,'auth-method-button')])[1]" # First auth button as fallback
]
auth_btn = None
for selector in selectors:
try:
auth_btn = self.browser.ele(f"xpath:{selector}", timeout=2)
if auth_btn and auth_btn.is_displayed():
break
except:
continue
if not auth_btn:
raise Exception("Could not find Google authentication button")
# Click the button and wait for page load
print(f"{Fore.CYAN}{EMOJI['INFO']} Starting Google authentication...{Style.RESET_ALL}")
auth_btn.click()
time.sleep(get_random_wait_time(self.config, 'page_load_wait'))
# Check if we're on account selection page
if "accounts.google.com" in self.browser.url:
print(f"{Fore.CYAN}{EMOJI['INFO']} Please select your Google account to continue...{Style.RESET_ALL}")
try:
self.browser.run_js("""
alert('Please select your Google account to continue with Cursor authentication');
""")
except:
pass # Alert is optional
# Wait for authentication to complete
auth_info = self._wait_for_auth()
if not auth_info:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.timeout')}{Style.RESET_ALL}")
return False, None
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.success')}{Style.RESET_ALL}")
return True, auth_info
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Authentication error: {str(e)}{Style.RESET_ALL}")
return False, None
finally:
try:
if self.browser:
self.browser.quit()
except:
pass
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.failed', error=str(e))}{Style.RESET_ALL}")
return False, None
def _wait_for_auth(self):
"""Wait for authentication to complete and extract auth info"""
try:
max_wait = 300 # 5 minutes
start_time = time.time()
check_interval = 2 # Check every 2 seconds
print(f"{Fore.CYAN}{EMOJI['WAIT']} Waiting for authentication (timeout: 5 minutes)...{Style.RESET_ALL}")
while time.time() - start_time < max_wait:
try:
# Check for authentication cookies
cookies = self.browser.cookies()
for cookie in cookies:
if cookie.get("name") == "WorkosCursorSessionToken":
value = cookie.get("value", "")
token = None
if "::" in value:
token = value.split("::")[-1]
elif "%3A%3A" in value:
token = value.split("%3A%3A")[-1]
if token:
# Get email from settings page
print(f"{Fore.CYAN}{EMOJI['INFO']} Authentication successful, getting account info...{Style.RESET_ALL}")
self.browser.get("https://www.cursor.com/settings")
time.sleep(3)
email = None
try:
email_element = self.browser.ele("css:div[class='flex w-full flex-col gap-2'] div:nth-child(2) p:nth-child(2)")
if email_element:
email = email_element.text
print(f"{Fore.CYAN}{EMOJI['INFO']} Found email: {email}{Style.RESET_ALL}")
except:
email = "user@cursor.sh" # Fallback email
# Check usage count
try:
usage_element = self.browser.ele("css:div[class='flex flex-col gap-4 lg:flex-row'] div:nth-child(1) div:nth-child(1) span:nth-child(2)")
if usage_element:
usage_text = usage_element.text
print(f"{Fore.CYAN}{EMOJI['INFO']} Usage count: {usage_text}{Style.RESET_ALL}")
# Check if account is expired
if usage_text.strip() == "150 / 150":
print(f"{Fore.YELLOW}{EMOJI['INFO']} Account has reached maximum usage, creating new account...{Style.RESET_ALL}")
# Delete current account
if self._delete_current_account():
# Start new authentication
print(f"{Fore.CYAN}{EMOJI['INFO']} Starting new authentication process...{Style.RESET_ALL}")
return self.handle_google_auth()
else:
print(f"{Fore.RED}{EMOJI['ERROR']} Failed to delete expired account{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Could not check usage count: {str(e)}{Style.RESET_ALL}")
return {"email": email, "token": token}
# Also check URL as backup
if "cursor.com/settings" in self.browser.url:
print(f"{Fore.CYAN}{EMOJI['INFO']} Detected successful login{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Waiting for authentication... ({str(e)}){Style.RESET_ALL}")
time.sleep(check_interval)
print(f"{Fore.RED}{EMOJI['ERROR']} Authentication timeout{Style.RESET_ALL}")
return None
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Error while waiting for authentication: {str(e)}{Style.RESET_ALL}")
return None
def handle_github_auth(self):
"""Handle GitHub OAuth authentication"""
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.github_start')}{Style.RESET_ALL}")
# Setup browser
if not self.setup_browser():
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.browser_failed')}{Style.RESET_ALL}")
return False, None
# Navigate to auth URL
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} Navigating to authentication page...{Style.RESET_ALL}")
self.browser.get("https://authenticator.cursor.sh/sign-up")
time.sleep(get_random_wait_time(self.config, 'page_load_wait'))
# Look for GitHub auth button
selectors = [
"//a[contains(@href,'GitHubOAuth')]",
"//a[contains(@class,'auth-method-button') and contains(@href,'GitHubOAuth')]",
"(//a[contains(@class,'auth-method-button')])[2]" # Second auth button as fallback
]
auth_btn = None
for selector in selectors:
try:
auth_btn = self.browser.ele(f"xpath:{selector}", timeout=2)
if auth_btn and auth_btn.is_displayed():
break
except:
continue
if not auth_btn:
raise Exception("Could not find GitHub authentication button")
# Click the button and wait for page load
print(f"{Fore.CYAN}{EMOJI['INFO']} Starting GitHub authentication...{Style.RESET_ALL}")
auth_btn.click()
time.sleep(get_random_wait_time(self.config, 'page_load_wait'))
# Wait for authentication to complete
auth_info = self._wait_for_auth()
if not auth_info:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.timeout')}{Style.RESET_ALL}")
return False, None
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.success')}{Style.RESET_ALL}")
return True, auth_info
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Authentication error: {str(e)}{Style.RESET_ALL}")
return False, None
finally:
try:
if self.browser:
self.browser.quit()
except:
pass
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.failed', error=str(e))}{Style.RESET_ALL}")
return False, None
def _handle_oauth(self, auth_type):
"""Handle OAuth authentication for both Google and GitHub
Args:
auth_type (str): Type of authentication ('google' or 'github')
"""
try:
if not self.setup_browser():
return False, None
# Navigate to auth URL
self.browser.get("https://authenticator.cursor.sh/sign-up")
time.sleep(get_random_wait_time(self.config, 'page_load_wait'))
# Set selectors based on auth type
if auth_type == "google":
selectors = [
"//a[@class='rt-reset rt-BaseButton rt-r-size-3 rt-variant-surface rt-high-contrast rt-Button auth-method-button_AuthMethodButton__irESX'][contains(@href,'GoogleOAuth')]",
"(//a[@class='rt-reset rt-BaseButton rt-r-size-3 rt-variant-surface rt-high-contrast rt-Button auth-method-button_AuthMethodButton__irESX'])[1]"
]
else: # github
selectors = [
"(//a[@class='rt-reset rt-BaseButton rt-r-size-3 rt-variant-surface rt-high-contrast rt-Button auth-method-button_AuthMethodButton__irESX'])[2]"
]
# Wait for the button to be available
auth_btn = None
max_button_wait = 30 # 30 seconds
button_start_time = time.time()
while time.time() - button_start_time < max_button_wait:
for selector in selectors:
try:
auth_btn = self.browser.ele(f"xpath:{selector}", timeout=1)
if auth_btn and auth_btn.is_displayed():
break
except:
continue
if auth_btn:
break
time.sleep(1)
if auth_btn:
# Click the button and wait for page load
auth_btn.click()
time.sleep(get_random_wait_time(self.config, 'page_load_wait'))
# Check if we're on account selection page
if auth_type == "google" and "accounts.google.com" in self.browser.url:
alert_js = """
alert('Please select your Google account manually to continue with Cursor authentication');
"""
try:
self.browser.run_js(alert_js)
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Alert display failed: {str(e)}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} Please select your Google account manually to continue with Cursor authentication...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} Waiting for authentication to complete...{Style.RESET_ALL}")
# Wait for authentication to complete
max_wait = 300 # 5 minutes
start_time = time.time()
last_url = self.browser.url
print(f"{Fore.CYAN}{EMOJI['WAIT']} Checking authentication status...{Style.RESET_ALL}")
while time.time() - start_time < max_wait:
try:
# Check for authentication cookies
cookies = self.browser.cookies()
for cookie in cookies:
if cookie.get("name") == "WorkosCursorSessionToken":
value = cookie.get("value", "")
if "::" in value:
token = value.split("::")[-1]
elif "%3A%3A" in value:
token = value.split("%3A%3A")[-1]
if token:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Authentication successful!{Style.RESET_ALL}")
# Navigate to settings page
print(f"{Fore.CYAN}{EMOJI['INFO']} Navigating to settings page...{Style.RESET_ALL}")
self.browser.get("https://www.cursor.com/settings")
time.sleep(3) # Wait for settings page to load
# Get email from settings page
try:
email_element = self.browser.ele("css:div[class='flex w-full flex-col gap-2'] div:nth-child(2) p:nth-child(2)")
if email_element:
actual_email = email_element.text
print(f"{Fore.CYAN}{EMOJI['INFO']} Found email: {actual_email}{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Could not find email: {str(e)}{Style.RESET_ALL}")
actual_email = "user@cursor.sh"
# Check usage count
try:
usage_element = self.browser.ele("css:div[class='flex flex-col gap-4 lg:flex-row'] div:nth-child(1) div:nth-child(1) span:nth-child(2)")
if usage_element:
usage_text = usage_element.text
print(f"{Fore.CYAN}{EMOJI['INFO']} Usage count: {usage_text}{Style.RESET_ALL}")
# Check if account is expired
if usage_text.strip() == "150 / 150": # Changed back to actual condition
print(f"{Fore.YELLOW}{EMOJI['INFO']} Account has reached maximum usage, deleting...{Style.RESET_ALL}")
delete_js = """
function deleteAccount() {
return new Promise((resolve, reject) => {
fetch('https://www.cursor.com/api/dashboard/delete-account', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
credentials: 'include'
})
.then(response => {
if (response.status === 200) {
resolve('Account deleted successfully');
} else {
reject('Failed to delete account: ' + response.status);
}
})
.catch(error => {
reject('Error: ' + error);
});
});
}
return deleteAccount();
"""
try:
result = self.browser.run_js(delete_js)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Delete account result: {result}{Style.RESET_ALL}")
# Navigate back to auth page and repeat authentication
print(f"{Fore.CYAN}{EMOJI['INFO']} Starting re-authentication process...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} Redirecting to authenticator.cursor.sh...{Style.RESET_ALL}")
# Explicitly navigate to the authentication page
#self.browser.get("https://authenticator.cursor.sh/sign-up")
# time.sleep(get_random_wait_time(self.config, 'page_load_wait'))
# Call handle_google_auth again to repeat the entire process
print(f"{Fore.CYAN}{EMOJI['INFO']} Starting new Google authentication...{Style.RESET_ALL}")
return self.handle_google_auth()
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Failed to delete account or re-authenticate: {str(e)}{Style.RESET_ALL}")
else:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Account is still valid (Usage: {usage_text}){Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Could not find usage count: {str(e)}{Style.RESET_ALL}")
# Remove the browser stay open prompt and input wait
return True, {"email": actual_email, "token": token}
# Also check URL as backup
current_url = self.browser.url
if "cursor.com/settings" in current_url:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Already on settings page!{Style.RESET_ALL}")
time.sleep(1)
cookies = self.browser.cookies()
for cookie in cookies:
if cookie.get("name") == "WorkosCursorSessionToken":
value = cookie.get("value", "")
if "::" in value:
token = value.split("::")[-1]
elif "%3A%3A" in value:
token = value.split("%3A%3A")[-1]
if token:
# Get email and check usage here too
try:
email_element = self.browser.ele("css:div[class='flex w-full flex-col gap-2'] div:nth-child(2) p:nth-child(2)")
if email_element:
actual_email = email_element.text
print(f"{Fore.CYAN}{EMOJI['INFO']} Found email: {actual_email}{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Could not find email: {str(e)}{Style.RESET_ALL}")
actual_email = "user@cursor.sh"
# Check usage count
try:
usage_element = self.browser.ele("css:div[class='flex flex-col gap-4 lg:flex-row'] div:nth-child(1) div:nth-child(1) span:nth-child(2)")
if usage_element:
usage_text = usage_element.text
print(f"{Fore.CYAN}{EMOJI['INFO']} Usage count: {usage_text}{Style.RESET_ALL}")
# Check if account is expired
if usage_text.strip() == "150 / 150": # Changed back to actual condition
print(f"{Fore.YELLOW}{EMOJI['INFO']} Account has reached maximum usage, deleting...{Style.RESET_ALL}")
delete_js = """
function deleteAccount() {
return new Promise((resolve, reject) => {
fetch('https://www.cursor.com/api/dashboard/delete-account', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
credentials: 'include'
})
.then(response => {
if (response.status === 200) {
resolve('Account deleted successfully');
} else {
reject('Failed to delete account: ' + response.status);
}
})
.catch(error => {
reject('Error: ' + error);
});
});
}
return deleteAccount();
"""
try:
result = self.browser.run_js(delete_js)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Delete account result: {result}{Style.RESET_ALL}")
# Navigate back to auth page and repeat authentication
print(f"{Fore.CYAN}{EMOJI['INFO']} Starting re-authentication process...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} Redirecting to authenticator.cursor.sh...{Style.RESET_ALL}")
# Explicitly navigate to the authentication page
self.browser.get("https://authenticator.cursor.sh/sign-up")
time.sleep(get_random_wait_time(self.config, 'page_load_wait'))
# Call handle_google_auth again to repeat the entire process
print(f"{Fore.CYAN}{EMOJI['INFO']} Starting new Google authentication...{Style.RESET_ALL}")
return self.handle_google_auth()
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Failed to delete account or re-authenticate: {str(e)}{Style.RESET_ALL}")
else:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Account is still valid (Usage: {usage_text}){Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Could not find usage count: {str(e)}{Style.RESET_ALL}")
# Remove the browser stay open prompt and input wait
return True, {"email": actual_email, "token": token}
elif current_url != last_url:
print(f"{Fore.CYAN}{EMOJI['INFO']} Page changed, checking auth...{Style.RESET_ALL}")
last_url = current_url
time.sleep(get_random_wait_time(self.config, 'page_load_wait'))
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Status check error: {str(e)}{Style.RESET_ALL}")
time.sleep(1)
continue
time.sleep(1)
print(f"{Fore.RED}{EMOJI['ERROR']} Authentication timeout{Style.RESET_ALL}")
return False, None
print(f"{Fore.RED}{EMOJI['ERROR']} Authentication button not found{Style.RESET_ALL}")
return False, None
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Authentication failed: {str(e)}{Style.RESET_ALL}")
return False, None
finally:
if self.browser:
self.browser.quit()
def _extract_auth_info(self):
"""Extract authentication information after successful OAuth"""
try:
# Get cookies with retry
max_retries = 3
for attempt in range(max_retries):
try:
cookies = self.browser.cookies()
if cookies:
break
time.sleep(1)
except:
if attempt == max_retries - 1:
raise
time.sleep(1)
# Debug cookie information
print(f"{Fore.CYAN}{EMOJI['INFO']} Found {len(cookies)} cookies{Style.RESET_ALL}")
email = None
token = None
for cookie in cookies:
name = cookie.get("name", "")
if name == "WorkosCursorSessionToken":
try:
value = cookie.get("value", "")
if "::" in value:
token = value.split("::")[-1]
elif "%3A%3A" in value:
token = value.split("%3A%3A")[-1]
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Token extraction error: {str(e)}{Style.RESET_ALL}")
elif name == "cursor_email":
email = cookie.get("value")
if email and token:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Authentication successful - Email: {email}{Style.RESET_ALL}")
return True, {"email": email, "token": token}
else:
missing = []
if not email:
missing.append("email")
if not token:
missing.append("token")
print(f"{Fore.RED}{EMOJI['ERROR']} Missing authentication data: {', '.join(missing)}{Style.RESET_ALL}")
return False, None
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} Failed to extract auth info: {str(e)}{Style.RESET_ALL}")
return False, None
def main(auth_type, translator=None):
"""Main function to handle OAuth authentication
Args:
auth_type (str): Type of authentication ('google' or 'github')
translator: Translator instance for internationalization
"""
handler = OAuthHandler(translator)
if auth_type.lower() == 'google':
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('oauth.google_start')}{Style.RESET_ALL}")
success, auth_info = handler.handle_google_auth()
elif auth_type.lower() == 'github':
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('oauth.github_start')}{Style.RESET_ALL}")
success, auth_info = handler.handle_github_auth()
else:
print(f"{Fore.RED}{EMOJI['ERROR']} Invalid authentication type{Style.RESET_ALL}")
return False
if success and auth_info:
# Update Cursor authentication
auth_manager = CursorAuth(translator)
if auth_manager.update_auth(
email=auth_info["email"],
access_token=auth_info["token"],
refresh_token=auth_info["token"]
):
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('oauth.auth_update_success')}{Style.RESET_ALL}")
# Close the browser after successful authentication
if handler.browser:
handler.browser.quit()
print(f"{Fore.CYAN}{EMOJI['INFO']} Browser closed{Style.RESET_ALL}")
return True
else:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('oauth.auth_update_failed')}{Style.RESET_ALL}")
return False

15
scripts/install.sh Normal file → Executable file
View File

@@ -39,14 +39,17 @@ get_downloads_dir() {
# Get latest version
get_latest_version() {
echo -e "${CYAN} Checking latest version...${NC}"
local latest_release
latest_release=$(curl -s https://api.github.com/repos/yeongpin/cursor-free-vip/releases/latest)
if [ $? -ne 0 ]; then
latest_release=$(curl -s https://api.github.com/repos/yeongpin/cursor-free-vip/releases/latest) || {
echo -e "${RED}❌ Cannot get latest version information${NC}"
exit 1
fi
}
VERSION=$(echo "$latest_release" | grep -o '"tag_name": ".*"' | cut -d'"' -f4 | tr -d 'v')
if [ -z "$VERSION" ]; then
echo -e "${RED}❌ Failed to parse version from GitHub API response:\n${latest_release}"
exit 1
fi
echo -e "${GREEN}✅ Found latest version: ${VERSION}${NC}"
}
@@ -170,9 +173,7 @@ install_cursor_free_vip() {
fi
echo -e "${CYAN} Setting executable permissions...${NC}"
chmod +x "${binary_path}"
if [ $? -eq 0 ]; then
if chmod +x "${binary_path}"; then
echo -e "${GREEN}✅ Installation completed!${NC}"
echo -e "${CYAN} Program downloaded to: ${binary_path}${NC}"
echo -e "${CYAN} Starting program...${NC}"

509
totally_reset_cursor.py Normal file
View File

@@ -0,0 +1,509 @@
import os
import shutil
import platform
import time
import sys
import glob
import json
import uuid
import random
import string
import re
from datetime import datetime
import subprocess
from colorama import Fore, Style, init
from main import translator
from main import EMOJI
# Initialize colorama
init()
# Define emoji and color constants
EMOJI = {
"FILE": "📄",
"BACKUP": "💾",
"SUCCESS": "",
"ERROR": "",
"INFO": "",
"RESET": "🔄",
"MENU": "📋",
"ARROW": "",
"LANG": "🌐",
"UPDATE": "🔄",
"ADMIN": "🔐",
"STOP": "🛑",
"DISCLAIMER": "⚠️",
"WARNING": "⚠️"
}
def display_banner():
"""Displays a stylized banner for the tool."""
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['STOP']} {translator.get('totally_reset.title')} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
def display_features():
"""Displays the features of the Cursor AI Reset Tool."""
print(f"\n{Fore.CYAN}{EMOJI['MENU']} {translator.get('totally_reset.feature_title')}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.feature_1')} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.feature_2')} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.feature_3')} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.feature_4')} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.feature_5')} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.feature_6')} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.feature_7')} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.feature_8')} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.feature_9')} {Style.RESET_ALL}\n")
def display_disclaimer():
"""Displays a disclaimer for the user."""
print(f"\n{Fore.RED}{EMOJI['DISCLAIMER']} {translator.get('totally_reset.disclaimer_title')}{Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.disclaimer_1')} {Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.disclaimer_2')} {Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.disclaimer_3')} {Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.disclaimer_4')} {Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.disclaimer_5')} {Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.disclaimer_6')} {Style.RESET_ALL}")
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.disclaimer_7')} {Style.RESET_ALL} \n")
def get_confirmation():
"""Gets confirmation from the user to proceed."""
while True:
choice = input(f"{Fore.RED}{EMOJI['WARNING']} {translator.get('totally_reset.confirm_title')} (Y/n): ").strip().lower()
if choice == "y" or choice == "":
return True
elif choice == "n":
return False
else:
print(f"{EMOJI['ERROR']} {translator.get('totally_reset.invalid_choice')}")
def remove_dir(path):
"""Removes a directory if it exists and logs the action."""
# Safety check to ensure we're only deleting Cursor-related directories
if not is_cursor_related(path):
print(f"{Fore.RED}{EMOJI['WARNING']} {translator.get('totally_reset.skipped_for_safety', path=path)} {Style.RESET_ALL}")
return
if os.path.exists(path):
try:
shutil.rmtree(path, ignore_errors=True)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('totally_reset.deleted', path=path)} {Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('totally_reset.error_deleting', path=path, error=str(e))} {Style.RESET_ALL}")
else:
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.not_found', path=path)} {Style.RESET_ALL}")
def remove_file(path):
"""Removes a file if it exists and logs the action."""
# Safety check to ensure we're only deleting Cursor-related files
if not is_cursor_related(path):
print(f"{Fore.RED}{EMOJI['WARNING']} {translator.get('totally_reset.skipped_for_safety', path=path)} {Style.RESET_ALL}")
return
if os.path.isfile(path):
try:
os.remove(path)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('totally_reset.deleted', path=path)} {Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('totally_reset.error_deleting', path=path, error=str(e))} {Style.RESET_ALL}")
else:
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.not_found', path=path)} {Style.RESET_ALL}")
def is_cursor_related(path):
"""
Safety function to verify a path is related to Cursor before deletion.
Returns True if the path appears to be related to Cursor AI.
"""
# Skip .vscode check as it's shared with VS Code
if path.endswith(".vscode"):
return False
# Check if path contains cursor-related terms
cursor_terms = ["cursor", "cursorai", "cursor-electron"]
# Convert path to lowercase for case-insensitive matching
lower_path = path.lower()
# Return True if any cursor term is present in the path
for term in cursor_terms:
if term in lower_path:
return True
# Check specific known Cursor file patterns
cursor_patterns = [
r"\.cursor_.*$",
r"cursor-.*\.json$",
r"cursor_.*\.json$",
r"cursor-machine-id$",
r"trial_info\.json$",
r"license\.json$"
]
for pattern in cursor_patterns:
if re.search(pattern, lower_path):
return True
# If it's a specific file that we know is only for Cursor
if os.path.basename(lower_path) in [
"cursor_trial_data",
"cursor-state.json",
"cursor-machine-id",
"ai-settings.json",
"cursor.desktop"
]:
return True
return False
def find_cursor_license_files(base_path, pattern):
"""Finds files matching a pattern that might contain license information."""
try:
matches = []
for root, dirnames, filenames in os.walk(base_path):
for filename in filenames:
# Check if filename matches any pattern before adding to matches
if any(p.lower() in filename.lower() for p in pattern):
full_path = os.path.join(root, filename)
# Extra safety check to ensure it's cursor-related
if is_cursor_related(full_path):
matches.append(full_path)
return matches
except Exception as e:
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.error_searching', path=base_path, error=str(e))} {Style.RESET_ALL}")
return []
def generate_new_machine_id():
"""Generates a new random machine ID."""
return str(uuid.uuid4())
def create_fake_machine_id(path):
"""Creates a new machine ID file with random ID."""
if not is_cursor_related(path):
return
try:
new_id = generate_new_machine_id()
directory = os.path.dirname(path)
# Ensure directory exists
if not os.path.exists(directory):
os.makedirs(directory)
with open(path, 'w') as f:
f.write(new_id)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('totally_reset.created_machine_id', path=path)} {Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('totally_reset.error_creating_machine_id', path=path, error=str(e))} {Style.RESET_ALL}")
def reset_machine_id(system, home):
"""Resets machine ID in all possible locations."""
print(f"\n{Fore.CYAN}{EMOJI['RESET']} {translator.get('totally_reset.resetting_machine_id')} {Style.RESET_ALL}")
# Common machine ID locations based on OS
if system == "Windows":
machine_id_paths = [
os.path.join(home, "AppData", "Roaming", "Cursor", "cursor-machine-id"),
os.path.join(home, "AppData", "Local", "Cursor", "cursor-machine-id"),
os.path.join(home, "AppData", "Roaming", "cursor-electron", "cursor-machine-id"),
os.path.join(home, "AppData", "Local", "cursor-electron", "cursor-machine-id"),
os.path.join(home, ".cursor-machine-id"),
]
elif system == "Darwin": # macOS
machine_id_paths = [
os.path.join(home, "Library", "Application Support", "Cursor", "cursor-machine-id"),
os.path.join(home, "Library", "Application Support", "cursor-electron", "cursor-machine-id"),
os.path.join(home, ".cursor-machine-id"),
]
elif system == "Linux":
machine_id_paths = [
os.path.join(home, ".config", "Cursor", "cursor-machine-id"),
os.path.join(home, ".config", "cursor-electron", "cursor-machine-id"),
os.path.join(home, ".cursor-machine-id"),
]
# First remove existing machine IDs
for path in machine_id_paths:
remove_file(path)
# Then create new randomized IDs
for path in machine_id_paths:
create_fake_machine_id(path)
# Try to reset system machine ID if possible (with appropriate permissions)
if system == "Windows":
try:
# Windows: Create a temporary VBS script to reset machine GUID
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.note_complete_machine_id_reset_may_require_running_as_administrator')} {Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.windows_machine_id_modification_skipped', error=str(e))} {Style.RESET_ALL}")
elif system == "Linux":
try:
# Linux: Create a random machine-id in /etc/ (needs sudo)
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.note_complete_system_machine_id_reset_may_require_sudo_privileges')} {Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.linux_machine_id_modification_skipped', error=str(e))} {Style.RESET_ALL}")
def create_fake_trial_info(path, system, home):
"""Creates fake trial information to extend trial period."""
if not is_cursor_related(path):
return
try:
# Generate future expiry date (90 days from now)
future_date = (datetime.now().timestamp() + (90 * 24 * 60 * 60)) * 1000 # milliseconds
# Create fake trial info
fake_trial = {
"trialStartTimestamp": datetime.now().timestamp() * 1000,
"trialEndTimestamp": future_date,
"hasUsedTrial": False,
"machineId": generate_new_machine_id()
}
directory = os.path.dirname(path)
# Ensure directory exists
if not os.path.exists(directory):
os.makedirs(directory)
with open(path, 'w') as f:
json.dump(fake_trial, f)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('totally_reset.created_extended_trial_info', path=path)} {Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('totally_reset.error_creating_trial_info', path=path, error=str(e))} {Style.RESET_ALL}")
def reset_cursor():
"""Completely resets Cursor AI by removing all settings, caches, and extensions."""
system = platform.system()
home = os.path.expanduser("~")
display_banner()
display_features()
display_disclaimer()
if not get_confirmation():
print(f"\n{Fore.CYAN}{EMOJI['STOP']} {translator.get('totally_reset.reset_cancelled')} {Style.RESET_ALL}")
return
print(f"\n{Fore.CYAN}{EMOJI['RESET']} {translator.get('totally_reset.resetting_cursor_ai_editor')} {Style.RESET_ALL}")
# Define paths based on OS
if system == "Windows":
cursor_paths = [
os.path.join(home, "AppData", "Roaming", "Cursor"),
os.path.join(home, "AppData", "Local", "Cursor"),
os.path.join(home, "AppData", "Roaming", "cursor-electron"),
os.path.join(home, "AppData", "Local", "cursor-electron"),
os.path.join(home, "AppData", "Local", "CursorAI"),
os.path.join(home, "AppData", "Roaming", "CursorAI"),
# os.path.join(home, ".vscode"), # Removed to avoid affecting VS Code
os.path.join(home, "AppData", "Local", "Temp", "Cursor"), # Temporary data
os.path.join(home, "AppData", "Local", "Temp", "cursor-updater"),
os.path.join(home, "AppData", "Local", "Programs", "cursor"),
]
# Additional locations for license/trial files on Windows
license_search_paths = [
os.path.join(home, "AppData", "Roaming"),
os.path.join(home, "AppData", "Local"),
os.path.join(home, "AppData", "LocalLow"),
]
# Registry instructions for Windows
print(f"\n{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.windows_registry_instructions')} {Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.windows_registry_instructions_2')} {Style.RESET_ALL}")
elif system == "Darwin": # macOS
cursor_paths = [
os.path.join(home, "Library", "Application Support", "Cursor"),
os.path.join(home, "Library", "Application Support", "cursor-electron"),
os.path.join(home, "Library", "Caches", "Cursor"),
os.path.join(home, "Library", "Caches", "cursor-electron"),
os.path.join(home, "Library", "Preferences", "Cursor"),
os.path.join(home, "Library", "Preferences", "cursor-electron"),
os.path.join(home, "Library", "Saved Application State", "com.cursor.Cursor.savedState"),
os.path.join(home, "Library", "HTTPStorages", "com.cursor.Cursor"),
os.path.join(home, "Library", "WebKit", "com.cursor.Cursor"),
# os.path.join(home, ".vscode"), # Removed to avoid affecting VS Code
"/Applications/Cursor.app", # Main application location
]
# Additional locations for license/trial files on macOS
license_search_paths = [
os.path.join(home, "Library", "Application Support"),
os.path.join(home, "Library", "Preferences"),
os.path.join(home, "Library", "Caches"),
]
elif system == "Linux":
cursor_paths = [
os.path.join(home, ".config", "Cursor"),
os.path.join(home, ".config", "cursor-electron"),
os.path.join(home, ".cache", "Cursor"),
os.path.join(home, ".cache", "cursor-electron"),
os.path.join(home, ".local", "share", "Cursor"),
os.path.join(home, ".local", "share", "cursor-electron"),
# os.path.join(home, ".vscode"), # Removed to avoid affecting VS Code
os.path.join(home, ".local", "share", "applications", "cursor.desktop"),
os.path.join("/usr", "share", "applications", "cursor.desktop"),
os.path.join("/opt", "Cursor"),
]
# Additional locations for license/trial files on Linux
license_search_paths = [
os.path.join(home, ".config"),
os.path.join(home, ".local", "share"),
os.path.join(home, ".cache"),
]
else:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('totally_reset.unsupported_os')} {Style.RESET_ALL}")
return
# Remove main Cursor directories
print(f"\n{Fore.CYAN}{EMOJI['RESET']} {translator.get('totally_reset.removing_main_cursor_directories_and_files')} {Style.RESET_ALL}")
for path in cursor_paths:
remove_dir(path)
# Reset machine identifiers (this creates new ones)
reset_machine_id(system, home)
# Known trial/license file patterns
file_patterns = [
".cursor_trial_data",
"trial_info.json",
"license.json",
"cursor-license",
"cursor_license",
"cursor-auth",
"cursor_auth",
"cursor_subscription",
"cursor-subscription",
"cursor-state",
"cursorstate",
"cursorsettings",
"cursor-settings",
"ai-settings.json",
"cursor-machine-id",
"cursor_machine_id",
"cursor-storage"
]
# Direct known trial file paths
cursor_trial_files = [
os.path.join(home, ".cursor_trial_data"),
os.path.join(home, ".cursor_license"),
os.path.join(home, ".cursor-machine-id"),
os.path.join(home, ".cursor-state.json"),
]
# OS-specific known trial/license files
if system == "Windows":
cursor_trial_files.extend([
os.path.join(home, "AppData", "Local", "Cursor", "trial_info.json"),
os.path.join(home, "AppData", "Local", "Cursor", "license.json"),
os.path.join(home, "AppData", "Roaming", "Cursor", "trial_info.json"),
os.path.join(home, "AppData", "Roaming", "Cursor", "license.json"),
os.path.join(home, "AppData", "Roaming", "Cursor", "cursor-machine-id"),
os.path.join(home, "AppData", "Local", "Cursor", "cursor-machine-id"),
os.path.join(home, "AppData", "Local", "Cursor", "ai-settings.json"),
os.path.join(home, "AppData", "Roaming", "Cursor", "ai-settings.json"),
])
elif system == "Darwin": # macOS
cursor_trial_files.extend([
os.path.join(home, "Library", "Application Support", "Cursor", "trial_info.json"),
os.path.join(home, "Library", "Application Support", "Cursor", "license.json"),
os.path.join(home, "Library", "Preferences", "Cursor", "trial_info.json"),
os.path.join(home, "Library", "Preferences", "Cursor", "license.json"),
os.path.join(home, "Library", "Application Support", "Cursor", "cursor-machine-id"),
os.path.join(home, "Library", "Application Support", "Cursor", "ai-settings.json"),
])
elif system == "Linux":
cursor_trial_files.extend([
os.path.join(home, ".config", "Cursor", "trial_info.json"),
os.path.join(home, ".config", "Cursor", "license.json"),
os.path.join(home, ".local", "share", "Cursor", "trial_info.json"),
os.path.join(home, ".local", "share", "Cursor", "license.json"),
os.path.join(home, ".config", "Cursor", "cursor-machine-id"),
os.path.join(home, ".config", "Cursor", "ai-settings.json"),
])
# Remove known trial/license files
print(f"\n{Fore.CYAN}{EMOJI['RESET']} {translator.get('totally_reset.removing_known')} {Style.RESET_ALL}")
for path in cursor_trial_files:
remove_file(path)
# Deep search for additional trial/license files
print(f"\n{Fore.CYAN}{EMOJI['RESET']} {translator.get('totally_reset.performing_deep_scan')} {Style.RESET_ALL}")
all_found_files = []
for base_path in license_search_paths:
if os.path.exists(base_path):
found_files = find_cursor_license_files(base_path, file_patterns)
all_found_files.extend(found_files)
if all_found_files:
print(f"\n🔎 {translator.get('totally_reset.found_additional_potential_license_trial_files', count=len(all_found_files))}\n")
for file_path in all_found_files:
remove_file(file_path)
else:
print(f"\n{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.no_additional_license_trial_files_found_in_deep_scan')} {Style.RESET_ALL}")
# Check for and remove localStorage files that might contain settings
print(f"\n{Fore.CYAN}{EMOJI['RESET']} {translator.get('totally_reset.checking_for_electron_localstorage_files')} {Style.RESET_ALL}")
if system == "Windows":
local_storage_paths = glob.glob(os.path.join(home, "AppData", "Roaming", "*cursor*", "Local Storage", "leveldb", "*"))
local_storage_paths += glob.glob(os.path.join(home, "AppData", "Local", "*cursor*", "Local Storage", "leveldb", "*"))
elif system == "Darwin":
local_storage_paths = glob.glob(os.path.join(home, "Library", "Application Support", "*cursor*", "Local Storage", "leveldb", "*"))
elif system == "Linux":
local_storage_paths = glob.glob(os.path.join(home, ".config", "*cursor*", "Local Storage", "leveldb", "*"))
for path in local_storage_paths:
if is_cursor_related(path):
remove_file(path)
# Create new trial files with extended expiration
print(f"\n{Fore.CYAN}{EMOJI['RESET']} {translator.get('totally_reset.creating_new_trial_information_with_extended_period')} {Style.RESET_ALL}")
if system == "Windows":
create_fake_trial_info(os.path.join(home, "AppData", "Local", "Cursor", "trial_info.json"), system, home)
create_fake_trial_info(os.path.join(home, "AppData", "Roaming", "Cursor", "trial_info.json"), system, home)
elif system == "Darwin":
create_fake_trial_info(os.path.join(home, "Library", "Application Support", "Cursor", "trial_info.json"), system, home)
elif system == "Linux":
create_fake_trial_info(os.path.join(home, ".config", "Cursor", "trial_info.json"), system, home)
print(f"\n{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('totally_reset.reset_log_1')}")
print(f" {translator.get('totally_reset.reset_log_2')}")
print(f" {translator.get('totally_reset.reset_log_3')}")
print(f"\n{Fore.GREEN}{EMOJI['INFO']} {translator.get('totally_reset.reset_log_4')} {Style.RESET_ALL}")
print(f" {translator.get('totally_reset.reset_log_5')} {Style.RESET_ALL}")
print(f" {translator.get('totally_reset.reset_log_6')} {Style.RESET_ALL}")
print(f" {translator.get('totally_reset.reset_log_7')} {Style.RESET_ALL}")
print(f" {translator.get('totally_reset.reset_log_8')} {Style.RESET_ALL}")
print(f"\n{Fore.RED}{EMOJI['INFO']} {translator.get('totally_reset.reset_log_9')} {Style.RESET_ALL}")
if __name__ == "__main__":
try:
reset_cursor()
except KeyboardInterrupt:
print(f"\n\n{Fore.RED}{EMOJI['STOP']} {translator.get('totally_reset.keyboard_interrupt')} {Style.RESET_ALL}")
sys.exit(1)
except Exception as e:
print(f"\n{Fore.RED}{EMOJI['ERROR']} {translator.get('totally_reset.unexpected_error', error=str(e))}{Style.RESET_ALL}")
print(f" {translator.get('totally_reset.report_issue')}")
sys.exit(1)
def run(translator=None):
"""Entry point for the totally reset cursor functionality when called from the main menu."""
try:
reset_cursor()
input(f"\n\n{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.return_to_main_menu')} {Style.RESET_ALL}")
except KeyboardInterrupt:
print(f"\n\n{Fore.RED}{EMOJI['STOP']} {translator.get('totally_reset.process_interrupted')} {Style.RESET_ALL}")
except Exception as e:
print(f"\n{Fore.RED}{EMOJI['ERROR']} {translator.get('totally_reset.unexpected_error', error=str(e))}{Style.RESET_ALL}")
print(f" {translator.get('totally_reset.report_issue')}")
input(f"\n{Fore.CYAN}{EMOJI['INFO']} {translator.get('totally_reset.press_enter_to_return_to_main_menu')} {Style.RESET_ALL}")

View File

@@ -1,6 +1,7 @@
import os
import sys
import platform
import random
def get_user_documents_path():
"""Get user documents path"""
@@ -29,4 +30,40 @@ def get_linux_cursor_path():
]
# return the first path that exists
return next((path for path in possible_paths if os.path.exists(path)), possible_paths[0])
return next((path for path in possible_paths if os.path.exists(path)), possible_paths[0])
def get_random_wait_time(config, timing_key):
"""Get random wait time based on configuration timing settings
Args:
config (dict): Configuration dictionary containing timing settings
timing_key (str): Key to look up in the timing settings
Returns:
float: Random wait time in seconds
"""
try:
# Get timing value from config
timing = config.get('Timing', {}).get(timing_key)
if not timing:
# Default to 0.5-1.5 seconds if timing not found
return random.uniform(0.5, 1.5)
# Check if timing is a range (e.g., "0.5-1.5" or "0.5,1.5")
if isinstance(timing, str):
if '-' in timing:
min_time, max_time = map(float, timing.split('-'))
elif ',' in timing:
min_time, max_time = map(float, timing.split(','))
else:
# Single value, use it as both min and max
min_time = max_time = float(timing)
else:
# If timing is a number, use it as both min and max
min_time = max_time = float(timing)
return random.uniform(min_time, max_time)
except (ValueError, TypeError, AttributeError):
# Return default value if any error occurs
return random.uniform(0.5, 1.5)