mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-08-02 20:47:35 +08:00
247 lines
9.7 KiB
Python
247 lines
9.7 KiB
Python
import os
|
||
import sys
|
||
import json
|
||
import uuid
|
||
import hashlib
|
||
import shutil
|
||
import sqlite3
|
||
import logging
|
||
from colorama import Fore, Style, init
|
||
|
||
# 设置日志记录
|
||
logging.basicConfig(
|
||
level=logging.INFO,
|
||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||
handlers=[
|
||
logging.StreamHandler(),
|
||
logging.FileHandler('reset_machine.log', encoding='utf-8')
|
||
]
|
||
)
|
||
logger = logging.getLogger(__name__)
|
||
|
||
# 初始化colorama
|
||
init()
|
||
|
||
# 定义emoji常量
|
||
EMOJI = {
|
||
"FILE": "📄",
|
||
"BACKUP": "💾",
|
||
"SUCCESS": "✅",
|
||
"ERROR": "❌",
|
||
"INFO": "ℹ️",
|
||
"RESET": "🔄",
|
||
}
|
||
|
||
class MachineIDResetter:
|
||
def __init__(self, translator=None):
|
||
self.translator = translator
|
||
|
||
# 判断操作系统
|
||
if sys.platform == "win32": # Windows
|
||
appdata = os.getenv("APPDATA")
|
||
if appdata is None:
|
||
raise EnvironmentError("APPDATA Environment Variable Not Set")
|
||
self.db_path = os.path.join(
|
||
appdata, "Cursor", "User", "globalStorage", "storage.json"
|
||
)
|
||
self.sqlite_path = os.path.join(
|
||
appdata, "Cursor", "User", "globalStorage", "state.vscdb"
|
||
)
|
||
elif sys.platform == "darwin": # macOS
|
||
self.db_path = os.path.abspath(os.path.expanduser(
|
||
"~/Library/Application Support/Cursor/User/globalStorage/storage.json"
|
||
))
|
||
self.sqlite_path = os.path.abspath(os.path.expanduser(
|
||
"~/Library/Application Support/Cursor/User/globalStorage/state.vscdb"
|
||
))
|
||
elif sys.platform == "linux": # Linux
|
||
self.db_path = os.path.abspath(os.path.expanduser(
|
||
"~/.config/Cursor/User/globalStorage/storage.json"
|
||
))
|
||
self.sqlite_path = os.path.abspath(os.path.expanduser(
|
||
"~/.config/Cursor/User/globalStorage/state.vscdb"
|
||
))
|
||
else:
|
||
raise NotImplementedError(f"Not Supported OS: {sys.platform}")
|
||
|
||
def generate_new_ids(self):
|
||
"""生成新的机器ID"""
|
||
# 生成新的UUID
|
||
dev_device_id = str(uuid.uuid4())
|
||
|
||
# 生成新的machineId (64个字符的十六进制)
|
||
machine_id = hashlib.sha256(os.urandom(32)).hexdigest()
|
||
|
||
# 生成新的macMachineId (128个字符的十六进制)
|
||
mac_machine_id = hashlib.sha512(os.urandom(64)).hexdigest()
|
||
|
||
# 生成新的sqmId
|
||
sqm_id = "{" + str(uuid.uuid4()).upper() + "}"
|
||
|
||
return {
|
||
"telemetry.devDeviceId": dev_device_id,
|
||
"telemetry.macMachineId": mac_machine_id,
|
||
"telemetry.machineId": machine_id,
|
||
"telemetry.sqmId": sqm_id,
|
||
"storage.serviceMachineId": dev_device_id, # 添加 storage.serviceMachineId
|
||
}
|
||
|
||
def update_sqlite_db(self, new_ids):
|
||
"""更新 SQLite 数据库中的机器ID"""
|
||
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()
|
||
|
||
cursor.execute("""
|
||
CREATE TABLE IF NOT EXISTS ItemTable (
|
||
key TEXT PRIMARY KEY,
|
||
value TEXT
|
||
)
|
||
""")
|
||
|
||
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):
|
||
"""更新系统级别的ID"""
|
||
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()
|
||
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}")
|
||
logger.error(f"System IDs update failed: {e}")
|
||
return False
|
||
|
||
def _update_windows_machine_guid(self):
|
||
"""更新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)
|
||
logger.info("Windows MachineGuid updated successfully")
|
||
except PermissionError:
|
||
logger.error("Permission denied: Run as administrator to update Windows MachineGuid")
|
||
raise
|
||
except Exception as e:
|
||
logger.error(f"Failed to update Windows MachineGuid: {e}")
|
||
raise
|
||
|
||
def _update_macos_platform_uuid(self, new_ids):
|
||
"""更新macOS Platform UUID"""
|
||
try:
|
||
uuid_file = "/var/root/Library/Preferences/SystemConfiguration/com.apple.platform.uuid.plist"
|
||
if os.path.exists(uuid_file):
|
||
# 使用sudo来执行plutil命令
|
||
cmd = f'sudo plutil -replace "UUID" -string "{new_ids["telemetry.macMachineId"]}" "{uuid_file}"'
|
||
result = os.system(cmd)
|
||
if result == 0:
|
||
logger.info("macOS Platform UUID updated successfully")
|
||
else:
|
||
raise Exception("Failed to execute plutil command")
|
||
except Exception as e:
|
||
logger.error(f"Failed to update macOS Platform UUID: {e}")
|
||
raise
|
||
|
||
def reset_machine_ids(self):
|
||
"""重置机器ID并备份原文件"""
|
||
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()
|
||
|
||
# 更新配置文件
|
||
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)
|
||
|
||
# 更新SQLite数据库
|
||
self.update_sqlite_db(new_ids)
|
||
|
||
# 更新系统ID
|
||
self.update_system_ids(new_ids)
|
||
|
||
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 run(translator=None):
|
||
"""便捷函数,用于直接调用重置功能"""
|
||
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) # 正確傳遞 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) |