diff --git a/.env b/.env index a0f3e47..6963d7b 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -version=1.7.04 -VERSION=1.7.04 +version=1.7.05 +VERSION=1.7.05 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c5f847d..e79cc10 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ on: version: description: 'Version number (e.g. 1.0.9)' required: true - default: '1.7.04' + default: '1.7.05' permissions: contents: write diff --git a/CHANGELOG.md b/CHANGELOG.md index c7b34fd..c2b783a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## v1.7.05 +1. Fix: Cursor Version Check | 修復Cursor版本檢查 +2. Fix: Small Problem | 修復一些小問題 + + ## v1.7.04 1. Hotfix: Small Problem | 修復一些小問題 diff --git a/locales/en.json b/locales/en.json index 03f9245..768d9a6 100644 --- a/locales/en.json +++ b/locales/en.json @@ -72,7 +72,20 @@ "permission_denied": "Permission Denied: {error}", "backup_created": "Backup Created", "update_success": "Update Success", - "update_failed": "Update Failed: {error}" + "update_failed": "Update Failed: {error}", + "windows_machine_guid_updated": "Windows Machine GUID Updated Successfully", + "reading_package_json": "Reading package.json {path}", + "invalid_json_object": "Invalid JSON Object", + "no_version_field": "No Version Field Found in package.json", + "version_field_empty": "Version Field is Empty", + "invalid_version_format": "Invalid Version Format: {version}", + "found_version": "Found Version: {version}", + "version_parse_error": "Version Parse Error: {error}", + "package_not_found": "Package.json Not Found: {path}", + "check_version_failed": "Check Version Failed: {error}", + "stack_trace": "Stack Trace", + "version_too_low": "Cursor Version Too Low: {version} < 0.45.0" + }, "register": { "title": "Cursor Registration Tool", diff --git a/locales/zh_cn.json b/locales/zh_cn.json index bf35fdc..c18277a 100644 --- a/locales/zh_cn.json +++ b/locales/zh_cn.json @@ -72,7 +72,19 @@ "permission_denied": "权限拒绝: {error}", "backup_created": "备份已创建", "update_success": "更新成功", - "update_failed": "更新失败: {error}" + "update_failed": "更新失败: {error}", + "windows_machine_guid_updated": "Windows机器GUID更新成功", + "reading_package_json": "读取package.json {path}", + "invalid_json_object": "JSON对象无效", + "no_version_field": "package.json中没有版本字段", + "version_field_empty": "版本字段为空", + "invalid_version_format": "版本格式无效: {version}", + "found_version": "找到版本: {version}", + "version_parse_error": "版本解析错误: {error}", + "package_not_found": "package.json未找到: {path}", + "check_version_failed": "检查版本失败: {error}", + "stack_trace": "堆栈跟踪", + "version_too_low": "Cursor版本太低: {version} < 0.45.0" }, "register": { "title": "Cursor 注册工具", diff --git a/locales/zh_tw.json b/locales/zh_tw.json index 8cba3fb..a9e2b5a 100644 --- a/locales/zh_tw.json +++ b/locales/zh_tw.json @@ -72,8 +72,21 @@ "permission_denied": "權限拒絕: {error}", "backup_created": "備份已創建", "update_success": "更新成功", - "update_failed": "更新失敗: {error}" + "update_failed": "更新失敗: {error}", + "windows_machine_guid_updated": "Windows機器GUID更新成功", + "reading_package_json": "讀取package.json {path}", + "invalid_json_object": "JSON對象無效", + "no_version_field": "package.json中沒有版本字段", + "version_field_empty": "版本字段為空", + "invalid_version_format": "版本格式無效: {version}", + "found_version": "找到版本: {version}", + "version_parse_error": "版本解析錯誤: {error}", + "package_not_found": "package.json未找到: {path}", + "check_version_failed": "檢查版本失敗: {error}", + "stack_trace": "堆疊跟踪", + "version_too_low": "Cursor版本太低: {version} < 0.45.0" }, + "register": { "title": "Cursor 註冊工具", "start": "正在啟動註冊流程...", diff --git a/main.py b/main.py index d8002ba..5cccf0e 100644 --- a/main.py +++ b/main.py @@ -285,6 +285,14 @@ def check_latest_version(): def main(): print_logo() + + # 初始化配置 + from new_signup import setup_config + config = setup_config(translator) + if not config: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.config_init_failed')}{Style.RESET_ALL}") + return + check_latest_version() # Add version check before showing menu print_menu() diff --git a/new_signup.py b/new_signup.py index 03dcb9f..eacfe83 100644 --- a/new_signup.py +++ b/new_signup.py @@ -207,21 +207,25 @@ def setup_config(translator=None): default_config['WindowsPaths'] = { 'storage_path': os.path.join(appdata, "Cursor", "User", "globalStorage", "storage.json"), 'sqlite_path': os.path.join(appdata, "Cursor", "User", "globalStorage", "state.vscdb"), - 'machine_id_path': os.path.join(os.getenv("APPDATA"), "Cursor", "machineId") + 'machine_id_path': os.path.join(os.getenv("APPDATA"), "Cursor", "machineId"), + 'cursor_path': os.path.join(os.getenv("LOCALAPPDATA", ""), "Programs", "Cursor", "resources", "app") } elif sys.platform == "darwin": default_config['MacPaths'] = { 'storage_path': os.path.abspath(os.path.expanduser("~/Library/Application Support/Cursor/User/globalStorage/storage.json")), 'sqlite_path': os.path.abspath(os.path.expanduser("~/Library/Application Support/Cursor/User/globalStorage/state.vscdb")), - 'machine_id_path': os.path.expanduser("~/Library/Application Support/Cursor/machineId") + 'machine_id_path': os.path.expanduser("~/Library/Application Support/Cursor/machineId"), + 'cursor_path': "/Applications/Cursor.app/Contents/Resources/app" } elif sys.platform == "linux": sudo_user = os.environ.get('SUDO_USER') actual_home = f"/home/{sudo_user}" if sudo_user else os.path.expanduser("~") + default_config['LinuxPaths'] = { 'storage_path': os.path.abspath(os.path.join(actual_home, ".config/Cursor/User/globalStorage/storage.json")), 'sqlite_path': os.path.abspath(os.path.join(actual_home, ".config/Cursor/User/globalStorage/state.vscdb")), - 'machine_id_path': os.path.expanduser("~/.config/Cursor/machineId") + 'machine_id_path': os.path.expanduser("~/.config/Cursor/machineId"), + 'cursor_path': "/opt/Cursor/resources/app" # 默認路徑 } if os.path.exists(config_file): diff --git a/reset_machine_manual.py b/reset_machine_manual.py index 65d28c1..4c6c056 100644 --- a/reset_machine_manual.py +++ b/reset_machine_manual.py @@ -12,6 +12,7 @@ from colorama import Fore, Style, init from typing import Tuple import configparser from new_signup import get_user_documents_path +import traceback # Initialize colorama init() @@ -29,42 +30,45 @@ EMOJI = { def get_cursor_paths(translator=None) -> Tuple[str, str]: """ Get Cursor related paths""" system = platform.system() - - paths_map = { - "Darwin": { - "base": "/Applications/Cursor.app/Contents/Resources/app", - "package": "package.json", - "main": "out/main.js", - }, - "Windows": { - "base": os.path.join( - os.getenv("LOCALAPPDATA", ""), "Programs", "Cursor", "resources", "app" - ), - "package": "package.json", - "main": "out/main.js", - }, - "Linux": { - "bases": ["/opt/Cursor/resources/app", "/usr/share/cursor/resources/app"], - "package": "package.json", - "main": "out/main.js", - }, - } - - if system not in paths_map: + + # 讀取配置文件 + config = configparser.ConfigParser() + config_dir = os.path.join(get_user_documents_path(), ".cursor-free-vip") + config_file = os.path.join(config_dir, "config.ini") + + if not os.path.exists(config_file): + raise OSError(translator.get('reset.config_not_found') if translator else "找不到配置文件") + + config.read(config_file) + + # 根據系統獲取路徑 + if system == "Darwin": + section = 'MacPaths' + elif system == "Windows": + section = 'WindowsPaths' + elif system == "Linux": + section = 'LinuxPaths' + else: raise OSError(translator.get('reset.unsupported_os', system=system) if translator else f"不支持的操作系统: {system}") - - if system == "Linux": - for base in paths_map["Linux"]["bases"]: - pkg_path = os.path.join(base, paths_map["Linux"]["package"]) - if os.path.exists(pkg_path): - return (pkg_path, os.path.join(base, paths_map["Linux"]["main"])) - raise OSError(translator.get('reset.linux_path_not_found') if translator else "在 Linux 系统上未找到 Cursor 安装路径") - - base_path = paths_map[system]["base"] - return ( - os.path.join(base_path, paths_map[system]["package"]), - os.path.join(base_path, paths_map[system]["main"]), - ) + + if not config.has_section(section) or not config.has_option(section, 'cursor_path'): + raise OSError(translator.get('reset.path_not_configured') if translator else "未配置 Cursor 路徑") + + base_path = config.get(section, 'cursor_path') + + if not os.path.exists(base_path): + raise OSError(translator.get('reset.path_not_found', path=base_path) if translator else f"找不到 Cursor 路徑: {base_path}") + + pkg_path = os.path.join(base_path, "package.json") + main_path = os.path.join(base_path, "out/main.js") + + # 檢查文件是否存在 + if not os.path.exists(pkg_path): + raise OSError(translator.get('reset.package_not_found', path=pkg_path) if translator else f"找不到 package.json: {pkg_path}") + if not os.path.exists(main_path): + raise OSError(translator.get('reset.main_not_found', path=main_path) if translator else f"找不到 main.js: {main_path}") + + return (pkg_path, main_path) def get_cursor_machine_id_path(translator=None) -> str: """ @@ -176,11 +180,60 @@ def check_cursor_version(translator) -> bool: """Check Cursor version""" try: pkg_path, _ = get_cursor_paths(translator) - with open(pkg_path, "r", encoding="utf-8") as f: - version = json.load(f)["version"] - return version_check(version, min_version="0.45.0", translator=translator) + print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.reading_package_json', path=pkg_path)}{Style.RESET_ALL}") + + try: + with open(pkg_path, "r", encoding="utf-8") as f: + data = json.load(f) + except UnicodeDecodeError: + # 如果 UTF-8 讀取失敗,嘗試其他編碼 + with open(pkg_path, "r", encoding="latin-1") as f: + data = json.load(f) + + if not isinstance(data, dict): + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.invalid_json_object')}{Style.RESET_ALL}") + return False + + if "version" not in data: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.no_version_field')}{Style.RESET_ALL}") + return False + + version = str(data["version"]).strip() + if not version: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.version_field_empty')}{Style.RESET_ALL}") + return False + + print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.found_version', version=version)}{Style.RESET_ALL}") + + # 檢查版本格式 + if not re.match(r"^\d+\.\d+\.\d+$", version): + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.invalid_version_format', version=version)}{Style.RESET_ALL}") + return False + + # 比較版本 + try: + current = tuple(map(int, version.split("."))) + min_ver = (0, 45, 0) # 直接使用元組而不是字符串 + + if current >= min_ver: + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.version_check_passed', version=version, min_version='0.45.0')}{Style.RESET_ALL}") + return True + else: + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('reset.version_too_low', version=version, min_version='0.45.0')}{Style.RESET_ALL}") + return False + except ValueError as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.version_parse_error', error=str(e))}{Style.RESET_ALL}") + return False + + except FileNotFoundError as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.package_not_found', path=pkg_path)}{Style.RESET_ALL}") + return False + except json.JSONDecodeError as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.invalid_json_object')}{Style.RESET_ALL}") + return False except Exception as e: print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.check_version_failed', error=str(e))}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('reset.stack_trace')}: {traceback.format_exc()}{Style.RESET_ALL}") return False def modify_workbench_js(file_path: str, translator=None) -> bool: @@ -576,12 +629,12 @@ class MachineIDResetter: ### Remove In v1.7.02 # Check Cursor version and perform corresponding actions - # greater_than_0_45 = check_cursor_version(self.translator) - # if greater_than_0_45: - # print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.detecting_version')} >= 0.45.0,{self.translator.get('reset.patching_getmachineid')}{Style.RESET_ALL}") - # patch_cursor_get_machine_id(self.translator) - # else: - # print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.version_less_than_0_45')}{Style.RESET_ALL}") + greater_than_0_45 = check_cursor_version(self.translator) + if greater_than_0_45: + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.detecting_version')} >= 0.45.0,{self.translator.get('reset.patching_getmachineid')}{Style.RESET_ALL}") + patch_cursor_get_machine_id(self.translator) + else: + print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.version_less_than_0_45')}{Style.RESET_ALL}") print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.success')}{Style.RESET_ALL}") print(f"\n{Fore.CYAN}{self.translator.get('reset.new_id')}:{Style.RESET_ALL}")