Update version to 1.7.15 and enhance GitHub + Cursor AI registration automation. Added Turkish language support, improved user confirmation prompts, and optimized logging. Updated CHANGELOG with new features and fixes.

This commit is contained in:
yeongpin 2025-03-22 16:14:27 +08:00
parent 902f6bd6f8
commit e0a7afd835
15 changed files with 286 additions and 318 deletions

4
.env
View File

@ -1,2 +1,2 @@
version=1.7.14 version=1.7.15
VERSION=1.7.14 VERSION=1.7.15

View File

@ -1,5 +1,21 @@
# Change Log # Change Log
## v1.7.15
1. Fix: Cant Verify the User is Human | 修復無法驗證用戶是否為人類
2. Added temporary email & GitHub + Cursor AI registration automation | 增加临时邮箱 & GitHub + Cursor AI 注册自动化
3. Added Turkish language support | 增加土耳其语支持
4. Removed outdated temporary option in Option 2 | 移除选项2中的过期临时添加项
5. Enhanced machine ID reset (Linux, Windows, macOS), bypasses Cursor free trial detection | 机器 ID 重置支持 Linux/Windows/macOS绕过 Cursor 免费试用检测
6. Expanded Cursor AI file detection, deep removal of leftover trial files | 扩展 Cursor AI 文件检测,深度清理残留试用文件
7. Optimized logging, replaced print with logging module, added verification steps | 日志优化,统一采用 logging 模块,增加验证步骤提示
8. Added retry mechanism for email verification | 增加邮箱验证重试机制
9. Automated GitHub OAuth login for Cursor AI | 自动 GitHub OAuth 登录 Cursor AI
10. Saved registered GitHub accounts and timestamps | 保存 GitHub 账户和注册时间戳
11. Added user confirmation before execution | 添加用户确认步骤,防止误操作
12. Displayed feature list & warnings before actions | 显示功能与风险警告
13. Improved Selenium flow and error handling | 增强 Selenium 流程与错误处理
14. Added Chrome process tracking and cleanup | 增加 Chrome 进程跟踪和清理
## v1.7.14 ## v1.7.14
1. Added a Russian locale to program, fixed a typo in readme.md. Also translated other files 1. Added a Russian locale to program, fixed a typo in readme.md. Also translated other files
為程式新增了俄語語系,修正了 readme.md 的拼寫錯誤,並翻譯了其他文件。 為程式新增了俄語語系,修正了 readme.md 的拼寫錯誤,並翻譯了其他文件。

View File

@ -188,16 +188,45 @@ def get_user_confirmation():
else: else:
print("Please enter 'yes' or 'no'.") print("Please enter 'yes' or 'no'.")
def main(): def main(translator=None):
logging.info("Starting GitHub + Cursor AI Registration Automation") logging.info("Starting GitHub + Cursor AI Registration Automation")
# Display features and warnings # 如果没有提供translator使用默认英文提示
if translator is None:
# Display features and warnings in English
display_features_and_warnings() display_features_and_warnings()
if not get_user_confirmation(): if not get_user_confirmation():
logging.info("Operation cancelled by user.") logging.info("Operation cancelled by user.")
print("❌ Operation cancelled.") print("❌ Operation cancelled.")
return return
else:
# 使用translator显示多语言提示
print(f"\n🚀 {translator.get('github_register.title')}")
print("=====================================")
print(f"{translator.get('github_register.features_header')}:")
print(f" - {translator.get('github_register.feature1')}")
print(f" - {translator.get('github_register.feature2')}")
print(f" - {translator.get('github_register.feature3')}")
print(f" - {translator.get('github_register.feature4')}")
print(f" - {translator.get('github_register.feature5')}")
print(f" - {translator.get('github_register.feature6')}")
print(f"\n⚠️ {translator.get('github_register.warnings_header')}:")
print(f" - {translator.get('github_register.warning1')}")
print(f" - {translator.get('github_register.warning2')}")
print(f" - {translator.get('github_register.warning3')}")
print(f" - {translator.get('github_register.warning4')}")
print("=====================================\n")
while True:
response = input(f"{translator.get('github_register.confirm')} (yes/no): ").lower().strip()
if response in ['yes', 'y']:
break
elif response in ['no', 'n']:
print(f"{translator.get('github_register.cancelled')}")
return
else:
print(f"{translator.get('github_register.invalid_choice')}")
try: try:
# Step 1: Generate temp email # Step 1: Generate temp email

View File

@ -16,7 +16,12 @@
"press_enter": "Drücken Sie Enter zum Beenden", "press_enter": "Drücken Sie Enter zum Beenden",
"disable_auto_update": "Cursor Auto-Update Deaktivieren", "disable_auto_update": "Cursor Auto-Update Deaktivieren",
"lifetime_access_enabled": "LEBENSLANGER ZUGRIFF AKTIVIERT", "lifetime_access_enabled": "LEBENSLANGER ZUGRIFF AKTIVIERT",
"totally_reset": "Cursor Vollständig Zurücksetzen" "totally_reset": "Cursor Vollständig Zurücksetzen",
"outdate": "Veraltet",
"temp_github_register": "Temporäre GitHub-Registrierung",
"admin_required": "Ausführen als ausführbare Datei, Administratorrechte erforderlich.",
"admin_required_continue": "Mit der aktuellen Version fortfahren...",
"coming_soon": "Bald verfügbar"
}, },
"languages": { "languages": {
"en": "Englisch", "en": "Englisch",

View File

@ -16,7 +16,12 @@
"press_enter": "Press Enter to Exit", "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", "lifetime_access_enabled": "LIFETIME ACCESS ENABLED",
"totally_reset": "Totally Reset Cursor" "totally_reset": "Totally Reset Cursor",
"outdate": "Outdated",
"temp_github_register": "Temporary GitHub Register",
"admin_required": "Running as executable, administrator privileges required.",
"admin_required_continue": "Continuing without administrator privileges.",
"coming_soon": "Coming Soon"
}, },
"languages": { "languages": {
"en": "English", "en": "English",
@ -382,5 +387,24 @@
"electron_localstorage_files_removed": "Electron localStorage files removed", "electron_localstorage_files_removed": "Electron localStorage files removed",
"electron_localstorage_files_removal_error": "Error removing Electron localStorage files: {error}", "electron_localstorage_files_removal_error": "Error removing Electron localStorage files: {error}",
"removing_electron_localstorage_files_completed": "Electron localStorage files removal completed" "removing_electron_localstorage_files_completed": "Electron localStorage files removal completed"
},
"github_register": {
"title": "GitHub + Cursor AI Registration Automation",
"features_header": "Features",
"feature1": "Generates a temporary email using 1secmail.",
"feature2": "Registers a new GitHub account with random credentials.",
"feature3": "Verifies the GitHub email automatically.",
"feature4": "Logs into Cursor AI using GitHub authentication.",
"feature5": "Resets the machine ID to bypass trial detection.",
"feature6": "Saves all credentials to a file.",
"warnings_header": "Warnings",
"warning1": "This script automates account creation, which may violate GitHub/Cursor terms of service.",
"warning2": "Requires internet access and administrative privileges.",
"warning3": "CAPTCHA or additional verification may interrupt automation.",
"warning4": "Use responsibly and at your own risk.",
"confirm": "Are you sure you want to proceed?",
"invalid_choice": "Invalid choice. Please enter 'yes' or 'no'",
"cancelled": "Operation cancelled",
"program_terminated": "Program terminated by user"
} }
} }

View File

@ -16,7 +16,10 @@
"press_enter": "Appuyez sur Entrée pour quitter", "press_enter": "Appuyez sur Entrée pour quitter",
"disable_auto_update": "Désactiver la Mise à Jour Automatique de Cursor", "disable_auto_update": "Désactiver la Mise à Jour Automatique de Cursor",
"lifetime_access_enabled": "ACCÈS À VIE ACTIVÉ", "lifetime_access_enabled": "ACCÈS À VIE ACTIVÉ",
"totally_reset": "Réinitialisation Complète de Cursor" "totally_reset": "Réinitialisation Complète de Cursor",
"outdate": "Obsolete",
"temp_github_register": "Inscription GitHub temporaire",
"coming_soon": "Bientôt"
}, },
"languages": { "languages": {
"en": "Anglais", "en": "Anglais",

View File

@ -16,7 +16,10 @@
"press_enter": "Druk op Enter om door te gaan.", "press_enter": "Druk op Enter om door te gaan.",
"disable_auto_update": "Cursor automatische updates uitschakelen", "disable_auto_update": "Cursor automatische updates uitschakelen",
"lifetime_access_enabled": "Levenslange toegang ingeschakeld", "lifetime_access_enabled": "Levenslange toegang ingeschakeld",
"totally_reset": "Cursor volledig resetten" "totally_reset": "Cursor volledig resetten",
"outdate": "Verouderd",
"temp_github_register": "Tijdelijke GitHub-registratie",
"coming_soon": "Binnenkort"
}, },
"languages": { "languages": {
"en": "Engels", "en": "Engels",
@ -278,7 +281,7 @@
"update_skipped": "Update overgeslagen.", "update_skipped": "Update overgeslagen.",
"invalid_choice": "Ongeldige keuze. Voer 'Y' of 'n' in.", "invalid_choice": "Ongeldige keuze. Voer 'Y' of 'n' in.",
"development_version": "Ontwikkelversie {current} > {latest}", "development_version": "Ontwikkelversie {current} > {latest}",
"changelog_title": "Changelog" "changelog_title": "Wijzigingslogboek"
}, },
"totally_reset": { "totally_reset": {
"title": "Cursor volledig herstellen", "title": "Cursor volledig herstellen",

View File

@ -16,7 +16,10 @@
"press_enter": "Pressione Enter para Sair", "press_enter": "Pressione Enter para Sair",
"disable_auto_update": "Desativar Atualização Automática do Cursor", "disable_auto_update": "Desativar Atualização Automática do Cursor",
"lifetime_access_enabled": "ACESSO VITALÍCIO HABILITADO", "lifetime_access_enabled": "ACESSO VITALÍCIO HABILITADO",
"totally_reset": "Redefinir Cursor Completamente" "totally_reset": "Redefinir Cursor Completamente",
"outdate": "Obsoleto",
"temp_github_register": "Registro temporário do GitHub",
"coming_soon": "Em breve"
}, },
"languages": { "languages": {
"en": "Inglês", "en": "Inglês",
@ -287,7 +290,7 @@
"update_skipped": "Atualização ignorada.", "update_skipped": "Atualização ignorada.",
"invalid_choice": "Escolha inválida. Por favor, digite 'Y' ou 'n'.", "invalid_choice": "Escolha inválida. Por favor, digite 'Y' ou 'n'.",
"development_version": "Versão de desenvolvimento {current} > {latest}", "development_version": "Versão de desenvolvimento {current} > {latest}",
"changelog_title": "Registro de mudanças" "changelog_title": "Registro de alterações"
}, },
"totally_reset": { "totally_reset": {
"title": "Redefinir Cursor Completamente", "title": "Redefinir Cursor Completamente",

View File

@ -16,7 +16,10 @@
"press_enter": "Нажмите Enter для выхода", "press_enter": "Нажмите Enter для выхода",
"disable_auto_update": "Отключить автоматическое обновление Cursor", "disable_auto_update": "Отключить автоматическое обновление Cursor",
"lifetime_access_enabled": "ВКЛЮЧЕН ПОЖИЗНЕННЫЙ ДОСТУП", "lifetime_access_enabled": "ВКЛЮЧЕН ПОЖИЗНЕННЫЙ ДОСТУП",
"totally_reset": "Полностью сбросить Cursor" "totally_reset": "Полностью сбросить Cursor",
"outdate": "Устаревший",
"temp_github_register": "Временная регистрация GitHub",
"coming_soon": "Скоро"
}, },
"languages": { "languages": {
"en": "Английский", "en": "Английский",
@ -287,7 +290,7 @@
"update_skipped": "Обновление пропущено.", "update_skipped": "Обновление пропущено.",
"invalid_choice": "Неверный выбор. Пожалуйста, введите 'Y' или 'n'.", "invalid_choice": "Неверный выбор. Пожалуйста, введите 'Y' или 'n'.",
"development_version": "Версия разработки {current} > {latest}", "development_version": "Версия разработки {current} > {latest}",
"changelog_title": "Журнал изменений" "changelog_title": "Список изменений"
}, },
"totally_reset": { "totally_reset": {
"title": "Полный сброс Cursor", "title": "Полный сброс Cursor",

View File

@ -16,7 +16,10 @@
"press_enter": ıkmak için Enter'a Basın", "press_enter": ıkmak için Enter'a Basın",
"disable_auto_update": "Cursor Otomatik Güncellemeyi Devre Dışı Bırak", "disable_auto_update": "Cursor Otomatik Güncellemeyi Devre Dışı Bırak",
"lifetime_access_enabled": "ÖMÜR BOYU ERİŞİM ETKİNLEŞTİRİLDİ", "lifetime_access_enabled": "ÖMÜR BOYU ERİŞİM ETKİNLEŞTİRİLDİ",
"totally_reset": "Cursor'ı Tamamen Sıfırla" "totally_reset": "Cursor'ı Tamamen Sıfırla",
"outdate": "güncel değil",
"temp_github_register": "Geçici GitHub Kaydı",
"coming_soon": "Yakında"
}, },
"languages": { "languages": {
"en": "English", "en": "English",
@ -290,7 +293,7 @@
"update_skipped": "Güncelleme atlanıyor.", "update_skipped": "Güncelleme atlanıyor.",
"invalid_choice": "Geçersiz seçim. Lütfen 'Y' veya 'n' girin.", "invalid_choice": "Geçersiz seçim. Lütfen 'Y' veya 'n' girin.",
"development_version": "Geliştirme Sürümü {current} > {latest}", "development_version": "Geliştirme Sürümü {current} > {latest}",
"changelog_title": "Değişiklik Günlüğü" "changelog_title": "Değişiklik günlüğü"
}, },
"totally_reset": { "totally_reset": {
"title": "Cursor'ı Tamamen Sıfırla", "title": "Cursor'ı Tamamen Sıfırla",

View File

@ -14,7 +14,10 @@
"press_enter": "Nhấn Enter để Thoát", "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", "lifetime_access_enabled": "ĐÃ BẬT TRUY CẬP TRỌN ĐỜI",
"totally_reset": "Đặt lại hoàn toàn Cursor" "totally_reset": "Đặt lại hoàn toàn Cursor",
"outdate": "Quá cũ",
"temp_github_register": "Đăng ký GitHub tạm thời",
"coming_soon": "Sắp ra mắt"
}, },
"languages": { "languages": {
"en": "Tiếng Anh", "en": "Tiếng Anh",
@ -93,7 +96,6 @@
"check_version_failed": "Kiểm Tra Phiên Bản Thất Bại: {error}", "check_version_failed": "Kiểm Tra Phiên Bản Thất Bại: {error}",
"stack_trace": "Dấu Vết Ngăn Xếp", "stack_trace": "Dấu Vết Ngăn Xếp",
"version_too_low": "Phiên Bản Cursor Quá Thấp: {version} < 0.45.0" "version_too_low": "Phiên Bản Cursor Quá Thấp: {version} < 0.45.0"
}, },
"register": { "register": {
"title": "Công Cụ Đăng Ký Cursor", "title": "Công Cụ Đăng Ký Cursor",
@ -286,7 +288,7 @@
"update_skipped": "Bỏ Qua Cập Nhật.", "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}", "development_version": "Phiên Bản Phát Triển {current} > {latest}",
"changelog_title": "Changelog" "changelog_title": "Nhật ký thay đổi"
}, },
"totally_reset": { "totally_reset": {
"title": "Đặt lại hoàn toàn Cursor", "title": "Đặt lại hoàn toàn Cursor",

View File

@ -16,7 +16,12 @@
"press_enter": "按回车键退出", "press_enter": "按回车键退出",
"disable_auto_update": "禁用 Cursor 自动更新", "disable_auto_update": "禁用 Cursor 自动更新",
"lifetime_access_enabled": "永久订阅", "lifetime_access_enabled": "永久订阅",
"totally_reset": "完全重置 Cursor" "totally_reset": "完全重置 Cursor",
"outdate": "过时",
"temp_github_register": "临时GitHub注册",
"admin_required": "运行可执行文件,需要管理员权限",
"admin_required_continue": "继续使用当前版本...",
"coming_soon": "即将推出"
}, },
"languages": { "languages": {
"en": "英语", "en": "英语",
@ -376,5 +381,24 @@
"electron_localstorage_files_removed": "Electron localStorage 文件已移除", "electron_localstorage_files_removed": "Electron localStorage 文件已移除",
"electron_localstorage_files_removal_error": "移除 Electron localStorage 文件时出错:{error}", "electron_localstorage_files_removal_error": "移除 Electron localStorage 文件时出错:{error}",
"removing_electron_localstorage_files_completed": "Electron localStorage 文件移除完成" "removing_electron_localstorage_files_completed": "Electron localStorage 文件移除完成"
},
"github_register": {
"title": "GitHub + Cursor AI 注册自动化",
"features_header": "功能",
"feature1": "使用 1secmail 生成临时邮箱",
"feature2": "使用随机凭证注册新的 GitHub 账户",
"feature3": "自动验证 GitHub 邮箱",
"feature4": "使用 GitHub 认证登录 Cursor AI",
"feature5": "重置机器 ID 以绕过试用检测",
"feature6": "保存所有凭证到文件",
"warnings_header": "警告",
"warning1": "此脚本自动化账户创建,可能违反 GitHub/Cursor 服务条款",
"warning2": "需要互联网访问和管理员权限",
"warning3": "CAPTCHA 或额外验证可能会中断自动化",
"warning4": "请负责任地使用,风险自负",
"confirm": "您确定要继续吗?",
"invalid_choice": "无效选择。请输入 'yes' 或 'no'",
"cancelled": "操作已取消",
"program_terminated": "程序已由用户终止"
} }
} }

View File

@ -14,7 +14,12 @@
"press_enter": "按返回鍵退出", "press_enter": "按返回鍵退出",
"disable_auto_update": "禁用 Cursor 自動更新", "disable_auto_update": "禁用 Cursor 自動更新",
"lifetime_access_enabled": "終身訪問已啟用", "lifetime_access_enabled": "終身訪問已啟用",
"totally_reset": "完全重置 Cursor" "totally_reset": "完全重置 Cursor",
"outdate": "過時",
"temp_github_register": "臨時GitHub註冊",
"admin_required": "運行可執行文件,需要管理員權限",
"admin_required_continue": "繼續使用當前版本...",
"coming_soon": "即將推出"
}, },
"languages": { "languages": {
"en": "英文", "en": "英文",
@ -263,7 +268,7 @@
"update_skipped": "跳過更新。", "update_skipped": "跳過更新。",
"invalid_choice": "選擇無效。請輸入 'Y' 或 'n'.", "invalid_choice": "選擇無效。請輸入 'Y' 或 'n'.",
"development_version": "開發版本 {current} > {latest}", "development_version": "開發版本 {current} > {latest}",
"changelog_title": "更新日" "changelog_title": "更新日"
}, },
"totally_reset": { "totally_reset": {
"title": "完全重置 Cursor", "title": "完全重置 Cursor",
@ -355,5 +360,24 @@
"electron_localstorage_files_removed": "已移除 Electron localStorage 檔案", "electron_localstorage_files_removed": "已移除 Electron localStorage 檔案",
"electron_localstorage_files_removal_error": "移除 Electron localStorage 檔案時出錯:{error}", "electron_localstorage_files_removal_error": "移除 Electron localStorage 檔案時出錯:{error}",
"removing_electron_localstorage_files_completed": "Electron localStorage 檔案移除完成" "removing_electron_localstorage_files_completed": "Electron localStorage 檔案移除完成"
},
"github_register": {
"title": "GitHub + Cursor AI 注册自动化",
"features_header": "功能",
"feature1": "使用 1secmail 生成临时邮箱",
"feature2": "使用随机凭证注册新的 GitHub 账户",
"feature3": "自动验证 GitHub 邮箱",
"feature4": "使用 GitHub 认证登录 Cursor AI",
"feature5": "重置机器 ID 以绕过试用检测",
"feature6": "保存所有凭证到文件",
"warnings_header": "警告",
"warning1": "此脚本自动化账户创建,可能违反 GitHub/Cursor 服务条款",
"warning2": "需要互联网访问和管理员权限",
"warning3": "CAPTCHA 或额外验证可能会中断自动化",
"warning4": "请负责任地使用,风险自负",
"confirm": "您确定要继续吗?",
"invalid_choice": "无效选择。请输入 'yes' 或 'no'",
"cancelled": "操作已取消",
"program_terminated": "程序已由用户终止"
} }
} }

31
main.py
View File

@ -109,6 +109,7 @@ class Translator:
0x0804: 'zh_cn', # Simplified Chinese 0x0804: 'zh_cn', # Simplified Chinese
0x0422: 'vi', # Vietnamese 0x0422: 'vi', # Vietnamese
0x0419: 'ru', # Russian 0x0419: 'ru', # Russian
0x0415: 'tr', # Turkish
} }
return language_map.get(layout_id, 'en') return language_map.get(layout_id, 'en')
@ -144,6 +145,8 @@ class Translator:
return 'pt' return 'pt'
elif system_locale.startswith('ru'): elif system_locale.startswith('ru'):
return 'ru' return 'ru'
elif system_locale.startswith('tr'):
return 'tr'
# Try to get language from LANG environment variable as fallback # Try to get language from LANG environment variable as fallback
env_lang = os.getenv('LANG', '').lower() env_lang = os.getenv('LANG', '').lower()
@ -163,6 +166,8 @@ class Translator:
return 'pt' return 'pt'
elif 'ru' in env_lang: elif 'ru' in env_lang:
return 'ru' return 'ru'
elif 'tr' in env_lang:
return 'tr'
return 'en' return 'en'
except: except:
@ -237,16 +242,17 @@ def print_menu():
print(f"{Fore.YELLOW}{'' * 40}{Style.RESET_ALL}") print(f"{Fore.YELLOW}{'' * 40}{Style.RESET_ALL}")
print(f"{Fore.GREEN}0{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.exit')}") 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}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}2{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register')} ({Fore.RED}{translator.get('menu.outdate')}{Style.RESET_ALL})")
print(f"{Fore.GREEN}3{Style.RESET_ALL}. 🌟 {translator.get('menu.register_google')}") 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.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.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.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}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}6{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.temp_github_register')}")
print(f"{Fore.GREEN}7{Style.RESET_ALL}. {EMOJI['LANG']} {translator.get('menu.select_language')}") print(f"{Fore.GREEN}7{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.quit')}")
print(f"{Fore.GREEN}8{Style.RESET_ALL}. {EMOJI['UPDATE']} {translator.get('menu.disable_auto_update')}") print(f"{Fore.GREEN}8{Style.RESET_ALL}. {EMOJI['LANG']} {translator.get('menu.select_language')}")
print(f"{Fore.GREEN}9{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.totally_reset')}") print(f"{Fore.GREEN}9{Style.RESET_ALL}. {EMOJI['UPDATE']} {translator.get('menu.disable_auto_update')}")
print(f"{Fore.GREEN}10{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.totally_reset')}")
print(f"{Fore.YELLOW}{'' * 40}{Style.RESET_ALL}") print(f"{Fore.YELLOW}{'' * 40}{Style.RESET_ALL}")
def select_language(): def select_language():
@ -424,11 +430,11 @@ def check_latest_version():
def main(): def main():
# Check for admin privileges if running as executable on Windows only # Check for admin privileges if running as executable on Windows only
if platform.system() == 'Windows' and is_frozen() and not is_admin(): if platform.system() == 'Windows' and is_frozen() and not is_admin():
print(f"{Fore.YELLOW}{EMOJI['ADMIN']} Running as executable, administrator privileges required.{Style.RESET_ALL}") print(f"{Fore.YELLOW}{EMOJI['ADMIN']} {translator.get('menu.admin_required')}{Style.RESET_ALL}")
if run_as_admin(): if run_as_admin():
sys.exit(0) # Exit after requesting admin privileges sys.exit(0) # Exit after requesting admin privileges
else: else:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Continuing without administrator privileges.{Style.RESET_ALL}") print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.admin_required_continue')}{Style.RESET_ALL}")
print_logo() print_logo()
@ -470,18 +476,23 @@ def main():
cursor_register_manual.main(translator) cursor_register_manual.main(translator)
print_menu() print_menu()
elif choice == "6": elif choice == "6":
import github_cursor_register
print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.coming_soon')}{Style.RESET_ALL}")
# github_cursor_register.main(translator)
print_menu()
elif choice == "7":
import quit_cursor import quit_cursor
quit_cursor.quit_cursor(translator) quit_cursor.quit_cursor(translator)
print_menu() print_menu()
elif choice == "7": elif choice == "8":
if select_language(): if select_language():
print_menu() print_menu()
continue continue
elif choice == "8": elif choice == "9":
import disable_auto_update import disable_auto_update
disable_auto_update.run(translator) disable_auto_update.run(translator)
print_menu() print_menu()
elif choice == "9": elif choice == "10":
import totally_reset_cursor import totally_reset_cursor
totally_reset_cursor.run(translator) totally_reset_cursor.run(translator)
print_menu() print_menu()

View File

@ -12,16 +12,32 @@ from config import get_config
# Add global variable at the beginning of the file # Add global variable at the beginning of the file
_translator = None _translator = None
# Add global variable to track our Chrome processes
_chrome_process_ids = []
def cleanup_chrome_processes(translator=None): def cleanup_chrome_processes(translator=None):
"""Clean all Chrome related processes""" """Clean only Chrome processes launched by this script"""
print("\nCleaning Chrome processes...") global _chrome_process_ids
if not _chrome_process_ids:
print("\nNo Chrome processes to clean...")
return
print("\nCleaning Chrome processes launched by this script...")
try: try:
if os.name == 'nt': if os.name == 'nt':
os.system('taskkill /F /IM chrome.exe /T 2>nul') for pid in _chrome_process_ids:
os.system('taskkill /F /IM chromedriver.exe /T 2>nul') try:
os.system(f'taskkill /F /PID {pid} /T 2>nul')
except:
pass
else: else:
os.system('pkill -f chrome') for pid in _chrome_process_ids:
os.system('pkill -f chromedriver') try:
os.kill(pid, signal.SIGTERM)
except:
pass
_chrome_process_ids = [] # Reset the list after cleanup
except Exception as e: except Exception as e:
if translator: if translator:
print(f"{Fore.RED}{translator.get('register.cleanup_error', error=str(e))}{Style.RESET_ALL}") print(f"{Fore.RED}{translator.get('register.cleanup_error', error=str(e))}{Style.RESET_ALL}")
@ -39,7 +55,7 @@ def signal_handler(signum, frame):
os._exit(0) os._exit(0)
def simulate_human_input(page, url, config, translator=None): def simulate_human_input(page, url, config, translator=None):
"""Visit URL with human-like behavior""" """Visit URL"""
if translator: if translator:
print(f"{Fore.CYAN}🚀 {translator.get('register.visiting_url')}: {url}{Style.RESET_ALL}") print(f"{Fore.CYAN}🚀 {translator.get('register.visiting_url')}: {url}{Style.RESET_ALL}")
@ -47,172 +63,42 @@ def simulate_human_input(page, url, config, translator=None):
page.get('about:blank') page.get('about:blank')
time.sleep(get_random_wait_time(config, 'page_load_wait')) time.sleep(get_random_wait_time(config, 'page_load_wait'))
# Add random mouse movements before visiting target page
try:
page.run_js("""
function simulateMouseMovement() {
const points = [];
const numPoints = Math.floor(Math.random() * 10) + 5;
for (let i = 0; i < numPoints; i++) {
points.push({
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight
});
}
points.forEach((point, i) => {
setTimeout(() => {
const event = new MouseEvent('mousemove', {
view: window,
bubbles: true,
cancelable: true,
clientX: point.x,
clientY: point.y
});
document.dispatchEvent(event);
}, i * (Math.random() * 200 + 50));
});
}
simulateMouseMovement();
""")
except:
pass # Ignore if JavaScript execution fails
# Visit target page # Visit target page
page.get(url) page.get(url)
time.sleep(get_random_wait_time(config, 'page_load_wait')) time.sleep(get_random_wait_time(config, 'page_load_wait'))
# Add some random scrolling
try:
page.run_js("""
function simulateHumanScroll() {
const maxScroll = Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.body.offsetHeight,
document.documentElement.offsetHeight,
document.body.clientHeight,
document.documentElement.clientHeight
);
const scrollPoints = [];
const numPoints = Math.floor(Math.random() * 3) + 2;
for (let i = 0; i < numPoints; i++) {
scrollPoints.push(Math.floor(Math.random() * maxScroll));
}
scrollPoints.sort((a, b) => a - b);
scrollPoints.forEach((point, i) => {
setTimeout(() => {
window.scrollTo({
top: point,
behavior: 'smooth'
});
}, i * (Math.random() * 1000 + 500));
});
}
simulateHumanScroll();
""")
except:
pass # Ignore if JavaScript execution fails
def simulate_human_typing(element, text, config):
"""Simulate human-like typing with random delays between keystrokes"""
for char in text:
element.input(char)
# Random delay between keystrokes (30-100ms)
time.sleep(random.uniform(0.03, 0.1))
time.sleep(get_random_wait_time(config, 'input_wait'))
def fill_signup_form(page, first_name, last_name, email, config, translator=None): def fill_signup_form(page, first_name, last_name, email, config, translator=None):
"""Fill signup form with human-like behavior""" """Fill signup form"""
max_retries = 5
retry_count = 0
while retry_count < max_retries:
try: try:
if translator: if translator:
print(f"{Fore.CYAN}📧 {translator.get('register.filling_form')} (Attempt {retry_count + 1}/{max_retries}){Style.RESET_ALL}") print(f"{Fore.CYAN}📧 {translator.get('register.filling_form')}{Style.RESET_ALL}")
else: else:
print(f"\n正在填写注册表单... (Attempt {retry_count + 1}/{max_retries})") print("\n正在填写注册表单...")
# Add random initial delay # Fill first name
time.sleep(random.uniform(0.5, 1.5))
# Fill first name with human-like typing
first_name_input = page.ele("@name=first_name") first_name_input = page.ele("@name=first_name")
if first_name_input: if first_name_input:
simulate_human_typing(first_name_input, first_name, config) first_name_input.input(first_name)
# Add random pause between fields time.sleep(get_random_wait_time(config, 'input_wait'))
time.sleep(random.uniform(0.3, 0.8))
# Fill last name with human-like typing # Fill last name
last_name_input = page.ele("@name=last_name") last_name_input = page.ele("@name=last_name")
if last_name_input: if last_name_input:
simulate_human_typing(last_name_input, last_name, config) last_name_input.input(last_name)
# Add random pause between fields time.sleep(get_random_wait_time(config, 'input_wait'))
time.sleep(random.uniform(0.3, 0.8))
# Fill email with human-like typing # Fill email
email_input = page.ele("@name=email") email_input = page.ele("@name=email")
if email_input: if email_input:
simulate_human_typing(email_input, email, config) email_input.input(email)
# Add random pause before submitting time.sleep(get_random_wait_time(config, 'input_wait'))
time.sleep(random.uniform(0.5, 1.2))
# Move mouse to submit button with human-like movement # Click submit button
submit_button = page.ele("@type=submit") submit_button = page.ele("@type=submit")
if submit_button: if submit_button:
try:
# Simulate mouse movement to button
page.run_js("""
function moveToButton(button) {
const rect = button.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
// Create a curved path to the button
const startX = Math.random() * window.innerWidth;
const startY = Math.random() * window.innerHeight;
const controlX = (startX + centerX) / 2 + (Math.random() - 0.5) * 100;
const controlY = (startY + centerY) / 2 + (Math.random() - 0.5) * 100;
const steps = 20;
for (let i = 0; i <= steps; i++) {
const t = i / steps;
const x = Math.pow(1-t, 2) * startX + 2 * (1-t) * t * controlX + Math.pow(t, 2) * centerX;
const y = Math.pow(1-t, 2) * startY + 2 * (1-t) * t * controlY + Math.pow(t, 2) * centerY;
setTimeout(() => {
const event = new MouseEvent('mousemove', {
view: window,
bubbles: true,
cancelable: true,
clientX: x,
clientY: y
});
document.dispatchEvent(event);
}, i * (Math.random() * 20 + 10));
}
}
moveToButton(document.querySelector('button[type="submit"]'));
""")
time.sleep(random.uniform(0.3, 0.6))
except:
pass # Ignore if JavaScript execution fails
submit_button.click() submit_button.click()
time.sleep(get_random_wait_time(config, 'submit_wait')) time.sleep(get_random_wait_time(config, 'submit_wait'))
# Check for human verification error
error_message = page.ele("text:Can't verify the user is human")
if error_message:
if translator:
print(f"{Fore.YELLOW}⚠️ {translator.get('register.human_verify_error')} (Attempt {retry_count + 1}/{max_retries}){Style.RESET_ALL}")
else:
print(f"Can't verify the user is human. Retrying... (Attempt {retry_count + 1}/{max_retries})")
retry_count += 1
# Add longer random delay between retries
time.sleep(random.uniform(2, 4))
continue
if translator: if translator:
print(f"{Fore.GREEN}{translator.get('register.form_success')}{Style.RESET_ALL}") print(f"{Fore.GREEN}{translator.get('register.form_success')}{Style.RESET_ALL}")
else: else:
@ -224,17 +110,6 @@ def fill_signup_form(page, first_name, last_name, email, config, translator=None
print(f"{Fore.RED}{translator.get('register.form_error', error=str(e))}{Style.RESET_ALL}") print(f"{Fore.RED}{translator.get('register.form_error', error=str(e))}{Style.RESET_ALL}")
else: else:
print(f"Error filling form: {e}") print(f"Error filling form: {e}")
retry_count += 1
if retry_count < max_retries:
time.sleep(get_random_wait_time(config, 'verification_retry_wait'))
continue
return False
if retry_count >= max_retries:
if translator:
print(f"{Fore.RED}{translator.get('register.max_retries_reached')}{Style.RESET_ALL}")
else:
print("Maximum retry attempts reached. Registration failed.")
return False return False
def get_default_chrome_path(): def get_default_chrome_path():
@ -304,7 +179,9 @@ def get_random_wait_time(config, timing_type='page_load_wait'):
return random.uniform(0.1, 0.8) # Return default value when error return random.uniform(0.1, 0.8) # Return default value when error
def setup_driver(translator=None): def setup_driver(translator=None):
"""Setup browser driver with randomized fingerprint""" """Setup browser driver"""
global _chrome_process_ids
try: try:
# Get config # Get config
config = get_config(translator) config = get_config(translator)
@ -326,42 +203,10 @@ def setup_driver(translator=None):
# Use incognito mode # Use incognito mode
co.set_argument("--incognito") co.set_argument("--incognito")
# Randomize browser fingerprint
# Random screen resolution
resolutions = [
"1920,1080", "1366,768", "1536,864", "1440,900",
"1280,720", "1600,900", "1024,768", "1680,1050"
]
window_size = random.choice(resolutions)
co.set_argument(f"--window-size={window_size}")
# Random user agent
user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
]
co.set_argument(f"--user-agent={random.choice(user_agents)}")
# Random color depth
color_depths = ["24", "30", "48"]
co.set_argument(f"--color-depth={random.choice(color_depths)}")
# Additional fingerprint randomization
co.set_argument("--disable-blink-features=AutomationControlled") # Hide automation
co.set_argument("--disable-features=IsolateOrigins,site-per-process")
# Random platform
platforms = ["Win32", "Win64", "MacIntel", "Linux x86_64"]
co.set_argument(f"--platform={random.choice(platforms)}")
# Random language
languages = ["en-US", "en-GB", "fr-FR", "de-DE", "es-ES", "it-IT"]
co.set_argument(f"--lang={random.choice(languages)}")
# Set random port # Set random port
co.set_argument("--no-sandbox") co.set_argument("--no-sandbox")
# Set random port
co.auto_port() co.auto_port()
# Use headless mode (must be set to False, simulate human operation) # Use headless mode (must be set to False, simulate human operation)
@ -384,63 +229,34 @@ def setup_driver(translator=None):
else: else:
print("Starting browser...") print("Starting browser...")
# Record Chrome processes before launching
before_pids = []
try:
import psutil
before_pids = [p.pid for p in psutil.process_iter() if 'chrome' in p.name().lower()]
except:
pass
# Launch browser
page = ChromiumPage(co) page = ChromiumPage(co)
# Additional JavaScript-based fingerprint randomization # Wait a moment for Chrome to fully launch
time.sleep(1)
# Record Chrome processes after launching and find new ones
try: try:
page.run_js(""" import psutil
// Override navigator properties after_pids = [p.pid for p in psutil.process_iter() if 'chrome' in p.name().lower()]
const originalNavigator = window.navigator; # Find new Chrome processes
const navigatorProxy = new Proxy(originalNavigator, { new_pids = [pid for pid in after_pids if pid not in before_pids]
get: function(target, key) { _chrome_process_ids.extend(new_pids)
switch (key) {
case 'webdriver':
return undefined;
case 'plugins':
return [
{ name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer' },
{ name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai' },
{ name: 'Native Client', filename: 'internal-nacl-plugin' }
];
case 'languages':
return ['en-US', 'en'];
default:
return target[key];
}
}
});
// Override permissions if _chrome_process_ids:
const originalPermissions = window.Permissions; print(f"Tracking {len(_chrome_process_ids)} Chrome processes")
window.Permissions = new Proxy(originalPermissions, { else:
get: function(target, key) { print(f"{Fore.YELLOW}Warning: No new Chrome processes detected to track{Style.RESET_ALL}")
if (key === 'prototype') { except Exception as e:
return { print(f"Warning: Could not track Chrome processes: {e}")
query: async () => ({ state: 'prompt' })
};
}
return target[key];
}
});
// Random canvas fingerprint
const originalGetContext = HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext = function() {
const context = originalGetContext.apply(this, arguments);
if (context && arguments[0] === '2d') {
const originalFillText = context.fillText;
context.fillText = function() {
const noise = Math.random() * 0.1;
context.rotate(noise);
originalFillText.apply(this, arguments);
context.rotate(-noise);
};
}
return context;
};
""")
except:
pass # Ignore if JavaScript execution fails
return config, page return config, page
@ -793,7 +609,9 @@ def handle_sign_in(browser_tab, email, password, translator=None):
def main(email=None, password=None, first_name=None, last_name=None, email_tab=None, controller=None, translator=None): def main(email=None, password=None, first_name=None, last_name=None, email_tab=None, controller=None, translator=None):
"""Main function, can receive account information, email tab, and translator""" """Main function, can receive account information, email tab, and translator"""
global _translator global _translator
global _chrome_process_ids
_translator = translator # Save to global variable _translator = translator # Save to global variable
_chrome_process_ids = [] # Reset the process IDs list
signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler) signal.signal(signal.SIGTERM, signal_handler)