mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-08-02 12:47:34 +08:00
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:
parent
902f6bd6f8
commit
e0a7afd835
16
CHANGELOG.md
16
CHANGELOG.md
@ -1,5 +1,21 @@
|
||||
# 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
|
||||
1. Added a Russian locale to program, fixed a typo in readme.md. Also translated other files |
|
||||
為程式新增了俄語語系,修正了 readme.md 的拼寫錯誤,並翻譯了其他文件。
|
||||
|
@ -188,16 +188,45 @@ def get_user_confirmation():
|
||||
else:
|
||||
print("Please enter 'yes' or 'no'.")
|
||||
|
||||
def main():
|
||||
def main(translator=None):
|
||||
logging.info("Starting GitHub + Cursor AI Registration Automation")
|
||||
|
||||
# Display features and warnings
|
||||
display_features_and_warnings()
|
||||
|
||||
if not get_user_confirmation():
|
||||
logging.info("Operation cancelled by user.")
|
||||
print("❌ Operation cancelled.")
|
||||
return
|
||||
# 如果没有提供translator,使用默认英文提示
|
||||
if translator is None:
|
||||
# Display features and warnings in English
|
||||
display_features_and_warnings()
|
||||
|
||||
if not get_user_confirmation():
|
||||
logging.info("Operation cancelled by user.")
|
||||
print("❌ Operation cancelled.")
|
||||
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:
|
||||
# Step 1: Generate temp email
|
||||
|
@ -16,7 +16,12 @@
|
||||
"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"
|
||||
"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": {
|
||||
"en": "Englisch",
|
||||
|
@ -16,7 +16,12 @@
|
||||
"press_enter": "Press Enter to Exit",
|
||||
"disable_auto_update": "Disable Cursor Auto-Update",
|
||||
"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": {
|
||||
"en": "English",
|
||||
@ -382,5 +387,24 @@
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
@ -16,7 +16,10 @@
|
||||
"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"
|
||||
"totally_reset": "Réinitialisation Complète de Cursor",
|
||||
"outdate": "Obsolete",
|
||||
"temp_github_register": "Inscription GitHub temporaire",
|
||||
"coming_soon": "Bientôt"
|
||||
},
|
||||
"languages": {
|
||||
"en": "Anglais",
|
||||
|
@ -16,7 +16,10 @@
|
||||
"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"
|
||||
"totally_reset": "Cursor volledig resetten",
|
||||
"outdate": "Verouderd",
|
||||
"temp_github_register": "Tijdelijke GitHub-registratie",
|
||||
"coming_soon": "Binnenkort"
|
||||
},
|
||||
"languages": {
|
||||
"en": "Engels",
|
||||
@ -278,7 +281,7 @@
|
||||
"update_skipped": "Update overgeslagen.",
|
||||
"invalid_choice": "Ongeldige keuze. Voer 'Y' of 'n' in.",
|
||||
"development_version": "Ontwikkelversie {current} > {latest}",
|
||||
"changelog_title": "Changelog"
|
||||
"changelog_title": "Wijzigingslogboek"
|
||||
},
|
||||
"totally_reset": {
|
||||
"title": "Cursor volledig herstellen",
|
||||
|
@ -16,7 +16,10 @@
|
||||
"press_enter": "Pressione Enter para Sair",
|
||||
"disable_auto_update": "Desativar Atualização Automática do Cursor",
|
||||
"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": {
|
||||
"en": "Inglês",
|
||||
@ -287,7 +290,7 @@
|
||||
"update_skipped": "Atualização ignorada.",
|
||||
"invalid_choice": "Escolha inválida. Por favor, digite 'Y' ou 'n'.",
|
||||
"development_version": "Versão de desenvolvimento {current} > {latest}",
|
||||
"changelog_title": "Registro de mudanças"
|
||||
"changelog_title": "Registro de alterações"
|
||||
},
|
||||
"totally_reset": {
|
||||
"title": "Redefinir Cursor Completamente",
|
||||
|
@ -16,7 +16,10 @@
|
||||
"press_enter": "Нажмите Enter для выхода",
|
||||
"disable_auto_update": "Отключить автоматическое обновление Cursor",
|
||||
"lifetime_access_enabled": "ВКЛЮЧЕН ПОЖИЗНЕННЫЙ ДОСТУП",
|
||||
"totally_reset": "Полностью сбросить Cursor"
|
||||
"totally_reset": "Полностью сбросить Cursor",
|
||||
"outdate": "Устаревший",
|
||||
"temp_github_register": "Временная регистрация GitHub",
|
||||
"coming_soon": "Скоро"
|
||||
},
|
||||
"languages": {
|
||||
"en": "Английский",
|
||||
@ -287,7 +290,7 @@
|
||||
"update_skipped": "Обновление пропущено.",
|
||||
"invalid_choice": "Неверный выбор. Пожалуйста, введите 'Y' или 'n'.",
|
||||
"development_version": "Версия разработки {current} > {latest}",
|
||||
"changelog_title": "Журнал изменений"
|
||||
"changelog_title": "Список изменений"
|
||||
},
|
||||
"totally_reset": {
|
||||
"title": "Полный сброс Cursor",
|
||||
|
@ -16,7 +16,10 @@
|
||||
"press_enter": "Çıkmak için Enter'a Basın",
|
||||
"disable_auto_update": "Cursor Otomatik Güncellemeyi Devre Dışı Bırak",
|
||||
"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": {
|
||||
"en": "English",
|
||||
@ -290,7 +293,7 @@
|
||||
"update_skipped": "Güncelleme atlanıyor.",
|
||||
"invalid_choice": "Geçersiz seçim. Lütfen 'Y' veya 'n' girin.",
|
||||
"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": {
|
||||
"title": "Cursor'ı Tamamen Sıfırla",
|
||||
|
@ -14,7 +14,10 @@
|
||||
"press_enter": "Nhấn Enter để Thoát",
|
||||
"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"
|
||||
"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": {
|
||||
"en": "Tiếng Anh",
|
||||
@ -93,7 +96,6 @@
|
||||
"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",
|
||||
"version_too_low": "Phiên Bản Cursor Quá Thấp: {version} < 0.45.0"
|
||||
|
||||
},
|
||||
"register": {
|
||||
"title": "Công Cụ Đăng Ký Cursor",
|
||||
@ -286,7 +288,7 @@
|
||||
"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'.",
|
||||
"development_version": "Phiên Bản Phát Triển {current} > {latest}",
|
||||
"changelog_title": "Changelog"
|
||||
"changelog_title": "Nhật ký thay đổi"
|
||||
},
|
||||
"totally_reset": {
|
||||
"title": "Đặt lại hoàn toàn Cursor",
|
||||
|
@ -16,7 +16,12 @@
|
||||
"press_enter": "按回车键退出",
|
||||
"disable_auto_update": "禁用 Cursor 自动更新",
|
||||
"lifetime_access_enabled": "永久订阅",
|
||||
"totally_reset": "完全重置 Cursor"
|
||||
"totally_reset": "完全重置 Cursor",
|
||||
"outdate": "过时",
|
||||
"temp_github_register": "临时GitHub注册",
|
||||
"admin_required": "运行可执行文件,需要管理员权限",
|
||||
"admin_required_continue": "继续使用当前版本...",
|
||||
"coming_soon": "即将推出"
|
||||
},
|
||||
"languages": {
|
||||
"en": "英语",
|
||||
@ -376,5 +381,24 @@
|
||||
"electron_localstorage_files_removed": "Electron localStorage 文件已移除",
|
||||
"electron_localstorage_files_removal_error": "移除 Electron localStorage 文件时出错:{error}",
|
||||
"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": "程序已由用户终止"
|
||||
}
|
||||
}
|
@ -14,7 +14,12 @@
|
||||
"press_enter": "按返回鍵退出",
|
||||
"disable_auto_update": "禁用 Cursor 自動更新",
|
||||
"lifetime_access_enabled": "終身訪問已啟用",
|
||||
"totally_reset": "完全重置 Cursor"
|
||||
"totally_reset": "完全重置 Cursor",
|
||||
"outdate": "過時",
|
||||
"temp_github_register": "臨時GitHub註冊",
|
||||
"admin_required": "運行可執行文件,需要管理員權限",
|
||||
"admin_required_continue": "繼續使用當前版本...",
|
||||
"coming_soon": "即將推出"
|
||||
},
|
||||
"languages": {
|
||||
"en": "英文",
|
||||
@ -263,7 +268,7 @@
|
||||
"update_skipped": "跳過更新。",
|
||||
"invalid_choice": "選擇無效。請輸入 'Y' 或 'n'.",
|
||||
"development_version": "開發版本 {current} > {latest}",
|
||||
"changelog_title": "更新日志"
|
||||
"changelog_title": "更新日誌"
|
||||
},
|
||||
"totally_reset": {
|
||||
"title": "完全重置 Cursor",
|
||||
@ -355,5 +360,24 @@
|
||||
"electron_localstorage_files_removed": "已移除 Electron localStorage 檔案",
|
||||
"electron_localstorage_files_removal_error": "移除 Electron localStorage 檔案時出錯:{error}",
|
||||
"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
31
main.py
@ -109,6 +109,7 @@ class Translator:
|
||||
0x0804: 'zh_cn', # Simplified Chinese
|
||||
0x0422: 'vi', # Vietnamese
|
||||
0x0419: 'ru', # Russian
|
||||
0x0415: 'tr', # Turkish
|
||||
}
|
||||
|
||||
return language_map.get(layout_id, 'en')
|
||||
@ -144,6 +145,8 @@ class Translator:
|
||||
return 'pt'
|
||||
elif system_locale.startswith('ru'):
|
||||
return 'ru'
|
||||
elif system_locale.startswith('tr'):
|
||||
return 'tr'
|
||||
|
||||
# Try to get language from LANG environment variable as fallback
|
||||
env_lang = os.getenv('LANG', '').lower()
|
||||
@ -163,6 +166,8 @@ class Translator:
|
||||
return 'pt'
|
||||
elif 'ru' in env_lang:
|
||||
return 'ru'
|
||||
elif 'tr' in env_lang:
|
||||
return 'tr'
|
||||
|
||||
return 'en'
|
||||
except:
|
||||
@ -237,16 +242,17 @@ def print_menu():
|
||||
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}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.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.GREEN}6{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.temp_github_register')}")
|
||||
print(f"{Fore.GREEN}7{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.quit')}")
|
||||
print(f"{Fore.GREEN}8{Style.RESET_ALL}. {EMOJI['LANG']} {translator.get('menu.select_language')}")
|
||||
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}")
|
||||
|
||||
def select_language():
|
||||
@ -424,11 +430,11 @@ def check_latest_version():
|
||||
def main():
|
||||
# Check for admin privileges if running as executable on Windows only
|
||||
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():
|
||||
sys.exit(0) # Exit after requesting admin privileges
|
||||
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()
|
||||
|
||||
@ -470,18 +476,23 @@ def main():
|
||||
cursor_register_manual.main(translator)
|
||||
print_menu()
|
||||
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
|
||||
quit_cursor.quit_cursor(translator)
|
||||
print_menu()
|
||||
elif choice == "7":
|
||||
elif choice == "8":
|
||||
if select_language():
|
||||
print_menu()
|
||||
continue
|
||||
elif choice == "8":
|
||||
elif choice == "9":
|
||||
import disable_auto_update
|
||||
disable_auto_update.run(translator)
|
||||
print_menu()
|
||||
elif choice == "9":
|
||||
elif choice == "10":
|
||||
import totally_reset_cursor
|
||||
totally_reset_cursor.run(translator)
|
||||
print_menu()
|
||||
|
374
new_signup.py
374
new_signup.py
@ -12,16 +12,32 @@ from config import get_config
|
||||
# Add global variable at the beginning of the file
|
||||
_translator = None
|
||||
|
||||
# Add global variable to track our Chrome processes
|
||||
_chrome_process_ids = []
|
||||
|
||||
def cleanup_chrome_processes(translator=None):
|
||||
"""Clean all Chrome related processes"""
|
||||
print("\nCleaning Chrome processes...")
|
||||
"""Clean only Chrome processes launched by this script"""
|
||||
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:
|
||||
if os.name == 'nt':
|
||||
os.system('taskkill /F /IM chrome.exe /T 2>nul')
|
||||
os.system('taskkill /F /IM chromedriver.exe /T 2>nul')
|
||||
for pid in _chrome_process_ids:
|
||||
try:
|
||||
os.system(f'taskkill /F /PID {pid} /T 2>nul')
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
os.system('pkill -f chrome')
|
||||
os.system('pkill -f chromedriver')
|
||||
for pid in _chrome_process_ids:
|
||||
try:
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
except:
|
||||
pass
|
||||
_chrome_process_ids = [] # Reset the list after cleanup
|
||||
except Exception as e:
|
||||
if translator:
|
||||
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)
|
||||
|
||||
def simulate_human_input(page, url, config, translator=None):
|
||||
"""Visit URL with human-like behavior"""
|
||||
"""Visit URL"""
|
||||
if translator:
|
||||
print(f"{Fore.CYAN}🚀 {translator.get('register.visiting_url')}: {url}{Style.RESET_ALL}")
|
||||
|
||||
@ -47,194 +63,53 @@ def simulate_human_input(page, url, config, translator=None):
|
||||
page.get('about:blank')
|
||||
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
|
||||
page.get(url)
|
||||
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):
|
||||
"""Fill signup form with human-like behavior"""
|
||||
max_retries = 5
|
||||
retry_count = 0
|
||||
|
||||
while retry_count < max_retries:
|
||||
try:
|
||||
if translator:
|
||||
print(f"{Fore.CYAN}📧 {translator.get('register.filling_form')} (Attempt {retry_count + 1}/{max_retries}){Style.RESET_ALL}")
|
||||
else:
|
||||
print(f"\n正在填写注册表单... (Attempt {retry_count + 1}/{max_retries})")
|
||||
|
||||
# Add random initial delay
|
||||
time.sleep(random.uniform(0.5, 1.5))
|
||||
|
||||
# Fill first name with human-like typing
|
||||
first_name_input = page.ele("@name=first_name")
|
||||
if first_name_input:
|
||||
simulate_human_typing(first_name_input, first_name, config)
|
||||
# Add random pause between fields
|
||||
time.sleep(random.uniform(0.3, 0.8))
|
||||
|
||||
# Fill last name with human-like typing
|
||||
last_name_input = page.ele("@name=last_name")
|
||||
if last_name_input:
|
||||
simulate_human_typing(last_name_input, last_name, config)
|
||||
# Add random pause between fields
|
||||
time.sleep(random.uniform(0.3, 0.8))
|
||||
|
||||
# Fill email with human-like typing
|
||||
email_input = page.ele("@name=email")
|
||||
if email_input:
|
||||
simulate_human_typing(email_input, email, config)
|
||||
# Add random pause before submitting
|
||||
time.sleep(random.uniform(0.5, 1.2))
|
||||
|
||||
# Move mouse to submit button with human-like movement
|
||||
submit_button = page.ele("@type=submit")
|
||||
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()
|
||||
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:
|
||||
print(f"{Fore.GREEN}✅ {translator.get('register.form_success')}{Style.RESET_ALL}")
|
||||
else:
|
||||
print("Form filled successfully")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
if translator:
|
||||
print(f"{Fore.RED}❌ {translator.get('register.form_error', error=str(e))}{Style.RESET_ALL}")
|
||||
else:
|
||||
print(f"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:
|
||||
"""Fill signup form"""
|
||||
try:
|
||||
if translator:
|
||||
print(f"{Fore.RED}❌ {translator.get('register.max_retries_reached')}{Style.RESET_ALL}")
|
||||
print(f"{Fore.CYAN}📧 {translator.get('register.filling_form')}{Style.RESET_ALL}")
|
||||
else:
|
||||
print("Maximum retry attempts reached. Registration failed.")
|
||||
print("\n正在填写注册表单...")
|
||||
|
||||
# Fill first name
|
||||
first_name_input = page.ele("@name=first_name")
|
||||
if first_name_input:
|
||||
first_name_input.input(first_name)
|
||||
time.sleep(get_random_wait_time(config, 'input_wait'))
|
||||
|
||||
# Fill last name
|
||||
last_name_input = page.ele("@name=last_name")
|
||||
if last_name_input:
|
||||
last_name_input.input(last_name)
|
||||
time.sleep(get_random_wait_time(config, 'input_wait'))
|
||||
|
||||
# Fill email
|
||||
email_input = page.ele("@name=email")
|
||||
if email_input:
|
||||
email_input.input(email)
|
||||
time.sleep(get_random_wait_time(config, 'input_wait'))
|
||||
|
||||
# Click submit button
|
||||
submit_button = page.ele("@type=submit")
|
||||
if submit_button:
|
||||
submit_button.click()
|
||||
time.sleep(get_random_wait_time(config, 'submit_wait'))
|
||||
|
||||
if translator:
|
||||
print(f"{Fore.GREEN}✅ {translator.get('register.form_success')}{Style.RESET_ALL}")
|
||||
else:
|
||||
print("Form filled successfully")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
if translator:
|
||||
print(f"{Fore.RED}❌ {translator.get('register.form_error', error=str(e))}{Style.RESET_ALL}")
|
||||
else:
|
||||
print(f"Error filling form: {e}")
|
||||
return False
|
||||
|
||||
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
|
||||
|
||||
def setup_driver(translator=None):
|
||||
"""Setup browser driver with randomized fingerprint"""
|
||||
"""Setup browser driver"""
|
||||
global _chrome_process_ids
|
||||
|
||||
try:
|
||||
# Get config
|
||||
config = get_config(translator)
|
||||
@ -326,42 +203,10 @@ def setup_driver(translator=None):
|
||||
# Use incognito mode
|
||||
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
|
||||
co.set_argument("--no-sandbox")
|
||||
|
||||
# Set random port
|
||||
co.auto_port()
|
||||
|
||||
# Use headless mode (must be set to False, simulate human operation)
|
||||
@ -384,64 +229,35 @@ def setup_driver(translator=None):
|
||||
else:
|
||||
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)
|
||||
|
||||
# Additional JavaScript-based fingerprint randomization
|
||||
try:
|
||||
page.run_js("""
|
||||
// Override navigator properties
|
||||
const originalNavigator = window.navigator;
|
||||
const navigatorProxy = new Proxy(originalNavigator, {
|
||||
get: function(target, key) {
|
||||
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
|
||||
const originalPermissions = window.Permissions;
|
||||
window.Permissions = new Proxy(originalPermissions, {
|
||||
get: function(target, key) {
|
||||
if (key === 'prototype') {
|
||||
return {
|
||||
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
|
||||
# Wait a moment for Chrome to fully launch
|
||||
time.sleep(1)
|
||||
|
||||
# Record Chrome processes after launching and find new ones
|
||||
try:
|
||||
import psutil
|
||||
after_pids = [p.pid for p in psutil.process_iter() if 'chrome' in p.name().lower()]
|
||||
# Find new Chrome processes
|
||||
new_pids = [pid for pid in after_pids if pid not in before_pids]
|
||||
_chrome_process_ids.extend(new_pids)
|
||||
|
||||
if _chrome_process_ids:
|
||||
print(f"Tracking {len(_chrome_process_ids)} Chrome processes")
|
||||
else:
|
||||
print(f"{Fore.YELLOW}Warning: No new Chrome processes detected to track{Style.RESET_ALL}")
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not track Chrome processes: {e}")
|
||||
|
||||
return config, page
|
||||
|
||||
except Exception as e:
|
||||
@ -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):
|
||||
"""Main function, can receive account information, email tab, and translator"""
|
||||
global _translator
|
||||
global _chrome_process_ids
|
||||
_translator = translator # Save to global variable
|
||||
_chrome_process_ids = [] # Reset the process IDs list
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
|
Loading…
x
Reference in New Issue
Block a user