diff --git a/.env b/.env index 1f99b3e..6725646 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -version=1.8.06 -VERSION=1.8.06 +version=1.8.07 +VERSION=1.8.07 diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bdfb5c..66ff682 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## v1.8.07 +1. Add: Bypass Cursor Version Check | 添加繞過 Cursor 版本檢查 +2. Add: Multilanguage support for bypass | 添加繞過的多語言支持 +3. Fix: Some Issues | 修復一些問題 + ## v1.8.06 1. Add: Google Account Deletion Feature | 添加 Google 账号删除功能 2. Update: Menu with new account deletion option | 更新菜单添加账号删除选项 diff --git a/bypass_version.py b/bypass_version.py new file mode 100644 index 0000000..3658361 --- /dev/null +++ b/bypass_version.py @@ -0,0 +1,158 @@ +import os +import json +import shutil +import platform +import configparser +import time +from colorama import Fore, Style, init +import sys +import traceback +from utils import get_user_documents_path + +# Initialize colorama +init() + +# Define emoji constants +EMOJI = { + 'INFO': 'ℹ️', + 'SUCCESS': '✅', + 'ERROR': '❌', + 'WARNING': '⚠️', + 'FILE': '📄', + 'BACKUP': '💾', + 'RESET': '🔄', + 'VERSION': '🏷️' +} + +def get_product_json_path(translator=None): + """Get Cursor product.json path""" + system = platform.system() + + # Read configuration + config_dir = os.path.join(get_user_documents_path(), ".cursor-free-vip") + config_file = os.path.join(config_dir, "config.ini") + config = configparser.ConfigParser() + + if os.path.exists(config_file): + config.read(config_file) + + if system == "Windows": + localappdata = os.environ.get("LOCALAPPDATA") + if not localappdata: + raise OSError(translator.get('bypass.localappdata_not_found') if translator else "LOCALAPPDATA environment variable not found") + + product_json_path = os.path.join(localappdata, "Programs", "Cursor", "resources", "app", "product.json") + + # Check if path exists in config + if 'WindowsPaths' in config and 'cursor_path' in config['WindowsPaths']: + cursor_path = config.get('WindowsPaths', 'cursor_path') + product_json_path = os.path.join(cursor_path, "product.json") + + elif system == "Darwin": # macOS + product_json_path = "/Applications/Cursor.app/Contents/Resources/app/product.json" + + elif system == "Linux": + # Try multiple common paths + possible_paths = [ + "/opt/Cursor/resources/app/product.json", + "/usr/share/cursor/resources/app/product.json", + "/usr/lib/cursor/app/product.json" + ] + + # Add extracted AppImage paths + extracted_usr_paths = os.path.expanduser("~/squashfs-root/usr/share/cursor/resources/app/product.json") + if os.path.exists(extracted_usr_paths): + possible_paths.append(extracted_usr_paths) + + for path in possible_paths: + if os.path.exists(path): + product_json_path = path + break + else: + raise OSError(translator.get('bypass.product_json_not_found') if translator else "product.json not found in common Linux paths") + + else: + raise OSError(translator.get('bypass.unsupported_os', system=system) if translator else f"Unsupported operating system: {system}") + + if not os.path.exists(product_json_path): + raise OSError(translator.get('bypass.file_not_found', path=product_json_path) if translator else f"File not found: {product_json_path}") + + return product_json_path + +def compare_versions(version1, version2): + """Compare two version strings""" + v1_parts = [int(x) for x in version1.split('.')] + v2_parts = [int(x) for x in version2.split('.')] + + for i in range(max(len(v1_parts), len(v2_parts))): + v1 = v1_parts[i] if i < len(v1_parts) else 0 + v2 = v2_parts[i] if i < len(v2_parts) else 0 + if v1 < v2: + return -1 + elif v1 > v2: + return 1 + + return 0 + +def bypass_version(translator=None): + """Bypass Cursor version check by modifying product.json""" + try: + print(f"\n{Fore.CYAN}{EMOJI['INFO']} {translator.get('bypass.starting') if translator else 'Starting Cursor version bypass...'}{Style.RESET_ALL}") + + # Get product.json path + product_json_path = get_product_json_path(translator) + print(f"{Fore.CYAN}{EMOJI['FILE']} {translator.get('bypass.found_product_json', path=product_json_path) if translator else f'Found product.json: {product_json_path}'}{Style.RESET_ALL}") + + # Check file permissions + if not os.access(product_json_path, os.W_OK): + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('bypass.no_write_permission', path=product_json_path) if translator else f'No write permission for file: {product_json_path}'}{Style.RESET_ALL}") + return False + + # Read product.json + try: + with open(product_json_path, "r", encoding="utf-8") as f: + product_data = json.load(f) + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('bypass.read_failed', error=str(e)) if translator else f'Failed to read product.json: {str(e)}'}{Style.RESET_ALL}") + return False + + # Get current version + current_version = product_data.get("version", "0.0.0") + print(f"{Fore.CYAN}{EMOJI['VERSION']} {translator.get('bypass.current_version', version=current_version) if translator else f'Current version: {current_version}'}{Style.RESET_ALL}") + + # Check if version needs to be modified + if compare_versions(current_version, "0.46.0") < 0: + # Create backup + timestamp = time.strftime("%Y%m%d%H%M%S") + backup_path = f"{product_json_path}.{timestamp}" + shutil.copy2(product_json_path, backup_path) + print(f"{Fore.GREEN}{EMOJI['BACKUP']} {translator.get('bypass.backup_created', path=backup_path) if translator else f'Backup created: {backup_path}'}{Style.RESET_ALL}") + + # Modify version + new_version = "0.48.7" + product_data["version"] = new_version + + # Save modified product.json + try: + with open(product_json_path, "w", encoding="utf-8") as f: + json.dump(product_data, f, indent=2) + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('bypass.version_updated', old=current_version, new=new_version) if translator else f'Version updated from {current_version} to {new_version}'}{Style.RESET_ALL}") + return True + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('bypass.write_failed', error=str(e)) if translator else f'Failed to write product.json: {str(e)}'}{Style.RESET_ALL}") + return False + else: + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('bypass.no_update_needed', version=current_version) if translator else f'No update needed. Current version {current_version} is already >= 0.46.0'}{Style.RESET_ALL}") + return True + + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('bypass.bypass_failed', error=str(e)) if translator else f'Version bypass failed: {str(e)}'}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('bypass.stack_trace') if translator else 'Stack trace'}: {traceback.format_exc()}{Style.RESET_ALL}") + return False + +def main(translator=None): + """Main function""" + return bypass_version(translator) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index fe13c2c..64aa0b8 100644 --- a/locales/en.json +++ b/locales/en.json @@ -669,5 +669,25 @@ "found_email": "Found email: {email}", "email_not_found": "Email not found: {error}", "confirm_prompt": "Are you sure you want to proceed? (y/N): " + }, + "bypass": { + "starting": "Starting Cursor version bypass...", + "found_product_json": "Found product.json: {path}", + "no_write_permission": "No write permission for file: {path}", + "read_failed": "Failed to read product.json: {error}", + "current_version": "Current version: {version}", + "backup_created": "Backup created: {path}", + "version_updated": "Version updated from {old} to {new}", + "write_failed": "Failed to write product.json: {error}", + "no_update_needed": "No update needed. Current version {version} is already >= 0.46.0", + "bypass_failed": "Version bypass failed: {error}", + "stack_trace": "Stack trace", + "localappdata_not_found": "LOCALAPPDATA environment variable not found", + "product_json_not_found": "product.json not found in common Linux paths", + "unsupported_os": "Unsupported operating system: {system}", + "file_not_found": "File not found: {path}", + "title": "Cursor Version Bypass Tool", + "description": "This tool modifies Cursor's product.json to bypass version restrictions", + "menu_option": "Bypass Cursor Version Check" } } \ No newline at end of file diff --git a/locales/zh_cn.json b/locales/zh_cn.json index ae51086..bfd88e0 100644 --- a/locales/zh_cn.json +++ b/locales/zh_cn.json @@ -647,5 +647,25 @@ "email_not_found": "未找到邮箱: {error}", "found_danger_zone": "已找到危险区域部分", "confirm_prompt": "您确定要继续吗?(y/N): " + }, + "bypass": { + "starting": "开始绕过 Cursor 版本限制...", + "found_product_json": "找到 product.json: {path}", + "no_write_permission": "没有写入权限: {path}", + "read_failed": "读取 product.json 失败: {error}", + "current_version": "当前版本: {version}", + "backup_created": "备份创建: {path}", + "version_updated": "版本从 {old} 更新到 {new}", + "write_failed": "写入 product.json 失败: {error}", + "no_update_needed": "不需要更新。当前版本 {version} 已 >= 0.46.0", + "bypass_failed": "绕过版本限制失败: {error}", + "stack_trace": "堆栈跟踪", + "localappdata_not_found": "LOCALAPPDATA 环境变量未找到", + "product_json_not_found": "product.json 未在常见 Linux 路径中找到", + "unsupported_os": "不支持的操作系统: {system}", + "file_not_found": "文件未找到: {path}", + "title": "Cursor 版本绕过工具", + "description": "此工具修改 Cursor 的 product.json 以绕过版本限制", + "menu_option": "绕过 Cursor 版本检查" } } \ No newline at end of file diff --git a/locales/zh_tw.json b/locales/zh_tw.json index 0c3207c..85b2dd2 100644 --- a/locales/zh_tw.json +++ b/locales/zh_tw.json @@ -629,5 +629,25 @@ "found_danger_zone": "已找到危險區域部分", "confirm_prompt": "您確定要繼續嗎?(y/N): ", "typed_delete_js": "已使用 JavaScript 輸入\"Delete\"" + }, + "bypass": { + "starting": "開始繞過 Cursor 版本限制...", + "found_product_json": "找到 product.json: {path}", + "no_write_permission": "沒有寫入權限: {path}", + "read_failed": "讀取 product.json 失敗: {error}", + "current_version": "當前版本: {version}", + "backup_created": "備份已創建: {path}", + "version_updated": "版本從 {old} 更新到 {new}", + "write_failed": "寫入 product.json 失敗: {error}", + "no_update_needed": "不需要更新。當前版本 {version} 已 >= 0.46.0", + "bypass_failed": "繞過版本限制失敗: {error}", + "stack_trace": "堆疊跟踪", + "localappdata_not_found": "LOCALAPPDATA 環境變量未找到", + "product_json_not_found": "product.json 未在常見 Linux 路徑中找到", + "unsupported_os": "不支持的操作系統: {system}", + "file_not_found": "文件未找到: {path}", + "title": "Cursor 版本繞過工具", + "description": "此工具修改 Cursor 的 product.json 以繞過版本限制", + "menu_option": "繞過 Cursor 版本檢查" } } \ No newline at end of file diff --git a/main.py b/main.py index 28ca30e..fe5b570 100644 --- a/main.py +++ b/main.py @@ -275,8 +275,8 @@ def print_menu(): 0: f"{Fore.GREEN}0{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.exit')}", 1: f"{Fore.GREEN}1{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.reset')}", 2: f"{Fore.GREEN}2{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register')} ({Fore.RED}{translator.get('menu.outdate')}{Style.RESET_ALL})", - 3: f"{Fore.GREEN}3{Style.RESET_ALL}. {EMOJI['SUN']} {translator.get('menu.register_google')} {EMOJI['ROCKET']} ({Fore.YELLOW}{translator.get('menu.lifetime_access_enabled')}{Style.RESET_ALL})", - 4: f"{Fore.GREEN}4{Style.RESET_ALL}. {EMOJI['STAR']} {translator.get('menu.register_github')} {EMOJI['ROCKET']} ({Fore.YELLOW}{translator.get('menu.lifetime_access_enabled')}{Style.RESET_ALL})", + 3: f"{Fore.GREEN}3{Style.RESET_ALL}. {EMOJI['SUN']} {translator.get('menu.register_google')} {EMOJI['ROCKET']} ({Fore.YELLOW}{translator.get('menu.lifetime_access_enabled')} ({Fore.RED}{translator.get('menu.outdate')}{Style.RESET_ALL}))", + 4: f"{Fore.GREEN}4{Style.RESET_ALL}. {EMOJI['STAR']} {translator.get('menu.register_github')} {EMOJI['ROCKET']} ({Fore.YELLOW}{translator.get('menu.lifetime_access_enabled')} ({Fore.RED}{translator.get('menu.outdate')}{Style.RESET_ALL}))", 5: f"{Fore.GREEN}5{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register_manual')}", 6: f"{Fore.GREEN}6{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.temp_github_register')}", 7: f"{Fore.GREEN}7{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.quit')}", diff --git a/totally_reset_cursor.py b/totally_reset_cursor.py index 5bb23b4..c89f828 100644 --- a/totally_reset_cursor.py +++ b/totally_reset_cursor.py @@ -111,7 +111,7 @@ def get_cursor_paths(translator=None) -> Tuple[str, str]: # For Linux, try to find the first existing path if the configured one doesn't exist if system == "Linux" and not os.path.exists(base_path): for path in default_paths["Linux"]: - if os.path.exists(path): + if os.path.exists(path): base_path = path # Update config with the found path config.set(section, 'cursor_path', path) @@ -529,7 +529,7 @@ class MachineIDResetter: self.db_path = config.get('LinuxPaths', 'storage_path') self.sqlite_path = config.get('LinuxPaths', 'sqlite_path') - else: + else: raise NotImplementedError(f"Not Supported OS: {sys.platform}") # Save any changes to config file