diff --git a/.env b/.env
index 95a7d79..1199388 100644
--- a/.env
+++ b/.env
@@ -1,2 +1,2 @@
-version=1.7.17
-VERSION=1.7.17
+version=1.8.05
+VERSION=1.8.05
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index fd90d39..b27e0d4 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.17'
+ default: '1.8.04'
permissions:
contents: write
diff --git a/.gitignore b/.gitignore
index 654a570..2e4e1d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,8 @@ build.py
build.sh
ENV/
test.py
+new_tempemail_smail.py
+new_tempemail_api.py
install.bat
run.bat
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 63b9d6f..3f9bfcd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,49 @@
# Change Log
-## v1.7.18 (Pre-Release)
-1. Fix: No Write Permission | 修復沒有寫入權限
+## v1.8.05
+1. Fix: Linux Path Not Found | 修復linuxpath問題
+2. Add: support for detecting both 150/150 and 50/50 usage limits | 添加偵測50 或者150的使用量
+3. Improve: usage parsing and validation | 檢測使用量
+
+## v1.8.04
+1. Update totally_reset_cursor.py | 更新 totally_reset_cursor.py
+2. Fix: improve Linux Chrome visibility and root user handling | 修復 Linux Chrome 可見性以及 root 用戶處理
+3. Fix: improve Linux path handling and fix permission issues | 修復 Linux 路徑處理以及修復權限問題
+4. Fix: Some Issues | 修復一些問題
+
+## v1.8.03
+1. Fix: Improve Linux path handling and add case-insensitive Cursor directory detection | 修復Linux系統路徑錯誤以及添加cursor 路徑偵測
2. Fix: Some Issues | 修復一些問題
+## v1.8.02
+1. Add: New Temp Email | 增加新臨時郵箱
+2. Add: Config Options | 增加配置選項
+3. Add: Update Windows Machine ID | 增加更新 Windows 機器 ID
+4. Add: Contributors Options | 增加貢獻者選項
+5. Add: Check update enable Options In config | 增加在 config 中檢查更新選項
+6. Add: Show account info enabled options in config | 增加在 config 中顯示賬號信息選項
+7. Optimize Row & Colume Options | 優化行與列選項
+8. Fix: Too Many Free Trial On Some Machine | 修復某些機器上太多免費試用
+9. Fix: Disable Auto Update | 修復禁用自動更新
+10. Fix: Linux Chrome Not Open Correct | 修復 Linux Chrome 未正確打開
+11. Fix: Some Issues | 修復一些問題
+
+## v1.8.01
+1. Add: Cursor Account Info | 增加 Cursor 賬號信息
+2. Fix: Disable Auto Update | 修復禁用自動更新
+3. Add: 0.48.x Version Support | 增加 0.48.x 版本支持
+4. Revert: Totally Reser Cursor to Beta | 恢復完全重置 Cursor 到 Beta
+5. Reopen: Totally Reset Cursor | 重新開啟完全重置 Cursor
+6. Fix: Logo.py Center | 修復 Logo.py 居中
+7. Fix: Linux Chrome Not Open Correct | 修復 Linux Chrome 未正確打開
+8. Fix: Some Issues | 修復一些問題
+
+## v1.7.18
+1. Fix: No Write Permission | 修復沒有寫入權限
+2. Fix: Improve Linux path detection and config handling | 修正 linux 路徑和config寫入讀取
+3. Fix: Locale path_no_exist missing | 修正 path_no_exist 語言遺失
+4. Fix: Some Issues | 修復一些問題
+
## v1.7.17
1. Fix: Remove 10 options Totally Reset Cursor | 修復完全重置 Cursor 選項
diff --git a/README.md b/README.md
index 825144c..1f62b46 100644
--- a/README.md
+++ b/README.md
@@ -13,10 +13,16 @@
[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
-Pro Trial'
+ CBadge_new_pattern = r'
Pro'
+
+ CToast_old_pattern = r'notifications-toasts'
+ CToast_new_pattern = r'notifications-toasts hidden'
+
+ # Replace content
+ content = content.replace(CButton_old_pattern, CButton_new_pattern)
+ content = content.replace(CBadge_old_pattern, CBadge_new_pattern)
+ content = content.replace(CToast_old_pattern, CToast_new_pattern)
+
+ # Write to temporary file
+ tmp_file.write(content)
+ tmp_path = tmp_file.name
+
+ # Backup original file
+ backup_path = file_path + ".backup"
+ if os.path.exists(backup_path):
+ os.remove(backup_path)
+ shutil.copy2(file_path, backup_path)
+
+ # Move temporary file to original position
+ if os.path.exists(file_path):
+ os.remove(file_path)
+ shutil.move(tmp_path, file_path)
+
+ # Restore original permissions
+ os.chmod(file_path, original_mode)
+ if os.name != "nt": # Not Windows
+ os.chown(file_path, original_uid, original_gid)
+
+ print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.file_modified')}{Style.RESET_ALL}")
+ return True
+
+ except Exception as e:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.modify_file_failed', error=str(e))}{Style.RESET_ALL}")
+ if "tmp_path" in locals():
+ try:
+ os.unlink(tmp_path)
+ except:
+ pass
+ return False
+
+def modify_main_js(main_path: str, translator) -> bool:
+ """Modify main.js file"""
+ try:
+ original_stat = os.stat(main_path)
+ original_mode = original_stat.st_mode
+ original_uid = original_stat.st_uid
+ original_gid = original_stat.st_gid
+
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file:
+ with open(main_path, "r", encoding="utf-8") as main_file:
+ content = main_file.read()
+
+ patterns = {
+ r"async getMachineId\(\)\{return [^??]+\?\?([^}]+)\}": r"async getMachineId(){return \1}",
+ r"async getMacMachineId\(\)\{return [^??]+\?\?([^}]+)\}": r"async getMacMachineId(){return \1}",
+ }
+
+ for pattern, replacement in patterns.items():
+ content = re.sub(pattern, replacement, content)
+
+ tmp_file.write(content)
+ tmp_path = tmp_file.name
+
+ shutil.copy2(main_path, main_path + ".old")
+ shutil.move(tmp_path, main_path)
+
+ os.chmod(main_path, original_mode)
+ if os.name != "nt":
+ os.chown(main_path, original_uid, original_gid)
+
+ print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.file_modified')}{Style.RESET_ALL}")
+ return True
+
+ except Exception as e:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.modify_file_failed', error=str(e))}{Style.RESET_ALL}")
+ if "tmp_path" in locals():
+ os.unlink(tmp_path)
+ return False
+
+def patch_cursor_get_machine_id(translator) -> bool:
+ """Patch Cursor getMachineId function"""
+ try:
+ print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.start_patching')}...{Style.RESET_ALL}")
+
+ # Get paths
+ pkg_path, main_path = get_cursor_paths(translator)
+
+ # Check file permissions
+ for file_path in [pkg_path, main_path]:
+ if not os.path.isfile(file_path):
+ print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.file_not_found', path=file_path)}{Style.RESET_ALL}")
+ return False
+ if not os.access(file_path, os.W_OK):
+ print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.no_write_permission', path=file_path)}{Style.RESET_ALL}")
+ return False
+
+ # Get version number
+ try:
+ with open(pkg_path, "r", encoding="utf-8") as f:
+ version = json.load(f)["version"]
+ print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.current_version', version=version)}{Style.RESET_ALL}")
+ except Exception as e:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.read_version_failed', error=str(e))}{Style.RESET_ALL}")
+ return False
+
+ # Check version
+ if not version_check(version, min_version="0.45.0", translator=translator):
+ print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.version_not_supported')}{Style.RESET_ALL}")
+ return False
+
+ print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.version_check_passed')}{Style.RESET_ALL}")
+
+ # Backup file
+ backup_path = main_path + ".bak"
+ if not os.path.exists(backup_path):
+ shutil.copy2(main_path, backup_path)
+ print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.backup_created', path=backup_path)}{Style.RESET_ALL}")
+
+ # Modify file
+ if not modify_main_js(main_path, translator):
+ return False
+
+ print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.patch_completed')}{Style.RESET_ALL}")
+ return True
+
+ except Exception as e:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.patch_failed', error=str(e))}{Style.RESET_ALL}")
+ return False
+
+class MachineIDResetter:
+ def __init__(self, translator=None):
+ self.translator = translator
+
+ # 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 not os.path.exists(config_file):
+ raise FileNotFoundError(f"Config file not found: {config_file}")
+
+ config.read(config_file, encoding='utf-8')
+
+ # Check operating system
+ if sys.platform == "win32": # Windows
+ appdata = os.getenv("APPDATA")
+ if appdata is None:
+ raise EnvironmentError("APPDATA Environment Variable Not Set")
+
+ if not config.has_section('WindowsPaths'):
+ config.add_section('WindowsPaths')
+ config.set('WindowsPaths', 'storage_path', os.path.join(
+ appdata, "Cursor", "User", "globalStorage", "storage.json"
+ ))
+ config.set('WindowsPaths', 'sqlite_path', os.path.join(
+ appdata, "Cursor", "User", "globalStorage", "state.vscdb"
+ ))
+
+ self.db_path = config.get('WindowsPaths', 'storage_path')
+ self.sqlite_path = config.get('WindowsPaths', 'sqlite_path')
+
+ elif sys.platform == "darwin": # macOS
+ if not config.has_section('MacPaths'):
+ config.add_section('MacPaths')
+ config.set('MacPaths', 'storage_path', os.path.abspath(os.path.expanduser(
+ "~/Library/Application Support/Cursor/User/globalStorage/storage.json"
+ )))
+ config.set('MacPaths', 'sqlite_path', os.path.abspath(os.path.expanduser(
+ "~/Library/Application Support/Cursor/User/globalStorage/state.vscdb"
+ )))
+
+ self.db_path = config.get('MacPaths', 'storage_path')
+ self.sqlite_path = config.get('MacPaths', 'sqlite_path')
+
+ elif sys.platform == "linux": # Linux
+ if not config.has_section('LinuxPaths'):
+ config.add_section('LinuxPaths')
+ # Get actual user's home directory
+ sudo_user = os.environ.get('SUDO_USER')
+ actual_home = f"/home/{sudo_user}" if sudo_user else os.path.expanduser("~")
+
+ config.set('LinuxPaths', 'storage_path', os.path.abspath(os.path.join(
+ actual_home,
+ ".config/cursor/User/globalStorage/storage.json"
+ )))
+ config.set('LinuxPaths', 'sqlite_path', os.path.abspath(os.path.join(
+ actual_home,
+ ".config/cursor/User/globalStorage/state.vscdb"
+ )))
+
+ self.db_path = config.get('LinuxPaths', 'storage_path')
+ self.sqlite_path = config.get('LinuxPaths', 'sqlite_path')
+
else:
- print(f"{Fore.RED}{translator.get('totally_reset.invalid_choice')}{Style.RESET_ALL}")
+ raise NotImplementedError(f"Not Supported OS: {sys.platform}")
-def reset_cursor(translator=None):
- print(f"\n{Fore.GREEN}{EMOJI['RESET']} {translator.get('totally_reset.resetting_cursor')}\n")
+ # Save any changes to config file
+ with open(config_file, 'w', encoding='utf-8') as f:
+ config.write(f)
- # Platform-specific paths
- paths = []
- if platform.system() == "Linux":
- paths = [
- os.path.expanduser("~/.cursor"),
- os.path.expanduser("~/.local/share/cursor"),
- os.path.expanduser("~/.config/cursor"),
- os.path.expanduser("~/.cache/cursor"),
- "/usr/local/bin/cursor",
- "/opt/cursor",
- "/usr/bin/cursor",
- os.path.expanduser("~/.cursor/machine-id.db"),
- os.path.expanduser("~/.local/share/Cursor"),
- os.path.expanduser("~/.config/Cursor"),
- os.path.expanduser("~/.cache/Cursor")
- ]
- elif platform.system() == "Darwin": # macOS
- paths = [
- os.path.expanduser("~/Library/Application Support/Cursor"),
- os.path.expanduser("~/Library/Caches/Cursor"),
- "/Applications/Cursor.app",
- os.path.expanduser("~/Library/Preferences/com.cursor.app.plist"),
- ]
- elif platform.system() == "Windows":
- paths = [
- os.path.expanduser("~\\AppData\\Local\\Cursor"),
- os.path.expanduser("~\\AppData\\Roaming\\Cursor"),
- os.path.expanduser("~\\.cursor"),
- os.path.expanduser("~\\.config\\Cursor"),
- os.path.expanduser("~\\.cache\\Cursor"),
- "C:\\Program Files\\Cursor",
- "C:\\Program Files (x86)\\Cursor",
- "C:\\Users\\%USERNAME%\\AppData\\Local\\Cursor",
- "C:\\Users\\%USERNAME%\\AppData\\Roaming\\Cursor",
- ]
+ def generate_new_ids(self):
+ """Generate new machine ID"""
+ # Generate new UUID
+ dev_device_id = str(uuid.uuid4())
- # Remove directories
- for path in paths:
- delete_directory(path, translator)
+ # Generate new machineId (64 characters of hexadecimal)
+ machine_id = hashlib.sha256(os.urandom(32)).hexdigest()
- # Remove common files related to Cursor
- files = [
- os.path.expanduser("~/.cursor/machine-id.db"),
- os.path.expanduser("~/.local/share/cursor.db"),
- os.path.expanduser("~/.config/cursor/preferences.json"),
- os.path.expanduser("~/.cache/cursor.log"),
- ]
+ # Generate new macMachineId (128 characters of hexadecimal)
+ mac_machine_id = hashlib.sha512(os.urandom(64)).hexdigest()
- for file in files:
- delete_file(file, translator)
+ # Generate new sqmId
+ sqm_id = "{" + str(uuid.uuid4()).upper() + "}"
- # Extra cleanup (wildcard search)
- print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('totally_reset.deep_scanning')}")
- base_dirs = ["/tmp", "/var/tmp", os.path.expanduser("~")] # Linux and macOS
- if platform.system() == "Windows":
- base_dirs = ["C:\\Temp", "C:\\Windows\\Temp", os.path.expanduser("~")] # Windows
+ self.update_machine_id_file(dev_device_id)
- for base in base_dirs:
- for root, dirs, files in os.walk(base):
- for dir in dirs:
- if "cursor" in dir.lower():
- delete_directory(os.path.join(root, dir), translator)
- for file in files:
- if "cursor" in file.lower():
- delete_file(os.path.join(root, file), translator)
+ return {
+ "telemetry.devDeviceId": dev_device_id,
+ "telemetry.macMachineId": mac_machine_id,
+ "telemetry.machineId": machine_id,
+ "telemetry.sqmId": sqm_id,
+ "storage.serviceMachineId": dev_device_id, # Add storage.serviceMachineId
+ }
- # Reset machine ID
- reset_machine_id(translator)
+ def update_sqlite_db(self, new_ids):
+ """Update machine ID in SQLite database"""
+ try:
+ print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.updating_sqlite')}...{Style.RESET_ALL}")
+
+ conn = sqlite3.connect(self.sqlite_path)
+ cursor = conn.cursor()
- print(f"\n{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('totally_reset.cursor_reset_completed')}")
+ cursor.execute("""
+ CREATE TABLE IF NOT EXISTS ItemTable (
+ key TEXT PRIMARY KEY,
+ value TEXT
+ )
+ """)
-def main(translator=None):
- start_time = time.time()
+ updates = [
+ (key, value) for key, value in new_ids.items()
+ ]
+
+ for key, value in updates:
+ cursor.execute("""
+ INSERT OR REPLACE INTO ItemTable (key, value)
+ VALUES (?, ?)
+ """, (key, value))
+ print(f"{EMOJI['INFO']} {Fore.CYAN} {self.translator.get('reset.updating_pair')}: {key}{Style.RESET_ALL}")
+
+ conn.commit()
+ conn.close()
+ print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.sqlite_success')}{Style.RESET_ALL}")
+ return True
+
+ except Exception as e:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.sqlite_error', error=str(e))}{Style.RESET_ALL}")
+ return False
+
+ def update_system_ids(self, new_ids):
+ """Update system-level IDs"""
+ try:
+ print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.updating_system_ids')}...{Style.RESET_ALL}")
+
+ if sys.platform.startswith("win"):
+ self._update_windows_machine_guid()
+ self._update_windows_machine_id()
+ elif sys.platform == "darwin":
+ self._update_macos_platform_uuid(new_ids)
+
+ print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.system_ids_updated')}{Style.RESET_ALL}")
+ return True
+ except Exception as e:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.system_ids_update_failed', error=str(e))}{Style.RESET_ALL}")
+ return False
+
+ def _update_windows_machine_guid(self):
+ """Update Windows MachineGuid"""
+ try:
+ import winreg
+ key = winreg.OpenKey(
+ winreg.HKEY_LOCAL_MACHINE,
+ "SOFTWARE\\Microsoft\\Cryptography",
+ 0,
+ winreg.KEY_WRITE | winreg.KEY_WOW64_64KEY
+ )
+ new_guid = str(uuid.uuid4())
+ winreg.SetValueEx(key, "MachineGuid", 0, winreg.REG_SZ, new_guid)
+ winreg.CloseKey(key)
+ print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.windows_machine_guid_updated')}{Style.RESET_ALL}")
+ except PermissionError:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.permission_denied')}{Style.RESET_ALL}")
+ raise
+ except Exception as e:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.update_windows_machine_guid_failed', error=str(e))}{Style.RESET_ALL}")
+ raise
- # Display features and warnings
- display_features_and_warnings(translator)
-
- # Get user confirmation
- if get_user_confirmation(translator):
- reset_cursor(translator)
- end_time = time.time()
- print(f"\n{Fore.GREEN}⏱️ {translator.get('totally_reset.completed_in', time=f'{end_time - start_time:.2f} seconds')}{Style.RESET_ALL}")
- else:
- print(f"\n{Fore.RED}❌ {translator.get('totally_reset.operation_cancelled')}{Style.RESET_ALL}")
+ def _update_windows_machine_id(self):
+ """Update Windows MachineId in SQMClient registry"""
+ try:
+ import winreg
+ # 1. Generate new GUID
+ new_guid = "{" + str(uuid.uuid4()).upper() + "}"
+ print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.new_machine_id')}: {new_guid}{Style.RESET_ALL}")
+
+ # 2. Open the registry key
+ try:
+ key = winreg.OpenKey(
+ winreg.HKEY_LOCAL_MACHINE,
+ r"SOFTWARE\Microsoft\SQMClient",
+ 0,
+ winreg.KEY_WRITE | winreg.KEY_WOW64_64KEY
+ )
+ except FileNotFoundError:
+ # If the key does not exist, create it
+ key = winreg.CreateKey(
+ winreg.HKEY_LOCAL_MACHINE,
+ r"SOFTWARE\Microsoft\SQMClient"
+ )
+
+ # 3. Set MachineId value
+ winreg.SetValueEx(key, "MachineId", 0, winreg.REG_SZ, new_guid)
+ winreg.CloseKey(key)
+
+ print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.windows_machine_id_updated')}{Style.RESET_ALL}")
+ return True
+
+ except PermissionError:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.permission_denied')}{Style.RESET_ALL}")
+ print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('reset.run_as_admin')}{Style.RESET_ALL}")
+ return False
+ except Exception as e:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.update_windows_machine_id_failed', error=str(e))}{Style.RESET_ALL}")
+ return False
+
-if __name__ == '__main__':
- from main import translator
- main(translator)
+ def _update_macos_platform_uuid(self, new_ids):
+ """Update macOS Platform UUID"""
+ try:
+ uuid_file = "/var/root/Library/Preferences/SystemConfiguration/com.apple.platform.uuid.plist"
+ if os.path.exists(uuid_file):
+ # Use sudo to execute plutil command
+ cmd = f'sudo plutil -replace "UUID" -string "{new_ids["telemetry.macMachineId"]}" "{uuid_file}"'
+ result = os.system(cmd)
+ if result == 0:
+ print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.macos_platform_uuid_updated')}{Style.RESET_ALL}")
+ else:
+ raise Exception(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.failed_to_execute_plutil_command')}{Style.RESET_ALL}")
+ except Exception as e:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.update_macos_platform_uuid_failed', error=str(e))}{Style.RESET_ALL}")
+ raise
+
+ def reset_machine_ids(self):
+ """Reset machine ID and backup original file"""
+ try:
+ print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('reset.checking')}...{Style.RESET_ALL}")
+
+ if not os.path.exists(self.db_path):
+ print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.not_found')}: {self.db_path}{Style.RESET_ALL}")
+ return False
+
+ if not os.access(self.db_path, os.R_OK | os.W_OK):
+ print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.no_permission')}{Style.RESET_ALL}")
+ return False
+
+ print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('reset.reading')}...{Style.RESET_ALL}")
+ with open(self.db_path, "r", encoding="utf-8") as f:
+ config = json.load(f)
+
+ backup_path = self.db_path + ".bak"
+ if not os.path.exists(backup_path):
+ print(f"{Fore.YELLOW}{EMOJI['BACKUP']} {self.translator.get('reset.creating_backup')}: {backup_path}{Style.RESET_ALL}")
+ shutil.copy2(self.db_path, backup_path)
+ else:
+ print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.backup_exists')}{Style.RESET_ALL}")
+
+ print(f"{Fore.CYAN}{EMOJI['RESET']} {self.translator.get('reset.generating')}...{Style.RESET_ALL}")
+ new_ids = self.generate_new_ids()
+
+ # Update configuration file
+ config.update(new_ids)
+
+ print(f"{Fore.CYAN}{EMOJI['FILE']} {self.translator.get('reset.saving_json')}...{Style.RESET_ALL}")
+ with open(self.db_path, "w", encoding="utf-8") as f:
+ json.dump(config, f, indent=4)
+
+ # Update SQLite database
+ self.update_sqlite_db(new_ids)
+
+ # Update system IDs
+ self.update_system_ids(new_ids)
+
+
+ # Modify workbench.desktop.main.js
+ workbench_path = get_workbench_cursor_path(self.translator)
+ modify_workbench_js(workbench_path, self.translator)
+
+ # 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}")
+
+ 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}")
+ for key, value in new_ids.items():
+ print(f"{EMOJI['INFO']} {key}: {Fore.GREEN}{value}{Style.RESET_ALL}")
+
+ return True
+
+ except PermissionError as e:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.permission_error', error=str(e))}{Style.RESET_ALL}")
+ print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.run_as_admin')}{Style.RESET_ALL}")
+ return False
+ except Exception as e:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.process_error', error=str(e))}{Style.RESET_ALL}")
+ return False
+
+ def update_machine_id_file(self, machine_id: str) -> bool:
+ """
+ Update machineId file with new machine_id
+ Args:
+ machine_id (str): New machine ID to write
+ Returns:
+ bool: True if successful, False otherwise
+ """
+ try:
+ # Get the machineId file path
+ machine_id_path = get_cursor_machine_id_path()
+
+ # Create directory if it doesn't exist
+ os.makedirs(os.path.dirname(machine_id_path), exist_ok=True)
+
+ # Create backup if file exists
+ if os.path.exists(machine_id_path):
+ backup_path = machine_id_path + ".backup"
+ try:
+ shutil.copy2(machine_id_path, backup_path)
+ print(f"{Fore.GREEN}{EMOJI['INFO']} {self.translator.get('reset.backup_created', path=backup_path) if self.translator else f'Backup created at: {backup_path}'}{Style.RESET_ALL}")
+ except Exception as e:
+ print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.backup_creation_failed', error=str(e)) if self.translator else f'Could not create backup: {str(e)}'}{Style.RESET_ALL}")
+
+ # Write new machine ID to file
+ with open(machine_id_path, "w", encoding="utf-8") as f:
+ f.write(machine_id)
+
+ print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.update_success') if self.translator else 'Successfully updated machineId file'}{Style.RESET_ALL}")
+ return True
+
+ except Exception as e:
+ error_msg = f"Failed to update machineId file: {str(e)}"
+ if self.translator:
+ error_msg = self.translator.get('reset.update_failed', error=str(e))
+ print(f"{Fore.RED}{EMOJI['ERROR']} {error_msg}{Style.RESET_ALL}")
+ return False
+
+def run(translator=None):
+ config = get_config(translator)
+ if not config:
+ return False
+ print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
+ print(f"{Fore.CYAN}{EMOJI['RESET']} {translator.get('reset.title')}{Style.RESET_ALL}")
+ print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
+
+ resetter = MachineIDResetter(translator) # Correctly pass translator
+ resetter.reset_machine_ids()
+
+ print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
+ input(f"{EMOJI['INFO']} {translator.get('reset.press_enter')}...")
+
+if __name__ == "__main__":
+ from main import translator as main_translator
+ run(main_translator)