diff --git a/locales/bg.json b/locales/bg.json index 0bac505..9936acc 100644 --- a/locales/bg.json +++ b/locales/bg.json @@ -30,7 +30,9 @@ "exiting": "Излизане ......", "bypass_version_check": "Пропусни проверката на версията на Cursor", "check_user_authorized": "Провери оторизацията на потребителя", - "select_chrome_profile": "Избери Chrome профил" + "select_chrome_profile": "Избери Chrome профил", + "bypass_token_limit": "Заобикаляне на ограничението на токените", + "restore_machine_id": "Възстановяване на машинен идентификатор от резервно копие" }, "languages": { "en": "English", @@ -410,5 +412,48 @@ "profile_selected": "Избран профил: {profile}", "invalid_selection": "Невалиден избор. Моля, опитайте отново", "warning_chrome_close": "Предупреждение: Това ще затвори всички работещи Chrome процеси" + }, + "restore": { + "title": "Възстановяване на машинен идентификатор от резервно копие", + "starting": "Стартиране на процеса на възстановяване на машинния идентификатор", + "no_backups_found": "Не са намерени резервни копия", + "available_backups": "Налични резервни копия", + "select_backup": "Изберете резервно копие за възстановяване", + "to_cancel": "за отказ", + "operation_cancelled": "Операцията е отменена", + "invalid_selection": "Невалиден избор", + "please_enter_number": "Моля, въведете валиден номер", + "missing_id": "Липсващ идентификатор: {id}", + "read_backup_failed": "Неуспешно четене на резервното копие: {error}", + "current_file_not_found": "Текущият файл за съхранение не е намерен", + "current_backup_created": "Създадено е резервно копие на текущия файл за съхранение", + "storage_updated": "Файлът за съхранение е успешно актуализиран", + "update_failed": "Неуспешно актуализиране на файла за съхранение: {error}", + "sqlite_not_found": "SQLite базата данни не е намерена", + "updating_sqlite": "Актуализиране на SQLite базата данни", + "updating_pair": "Актуализиране на двойката ключ-стойност", + "sqlite_updated": "SQLite базата данни е успешно актуализирана", + "sqlite_update_failed": "Неуспешно актуализиране на SQLite базата данни: {error}", + "machine_id_backup_created": "Създадено е резервно копие на файла с машинния идентификатор", + "backup_creation_failed": "Неуспешно създаване на резервно копие: {error}", + "machine_id_updated": "Файлът с машинния идентификатор е успешно актуализиран", + "machine_id_update_failed": "Неуспешно актуализиране на файла с машинния идентификатор: {error}", + "updating_system_ids": "Актуализиране на системните идентификатори", + "system_ids_update_failed": "Неуспешно актуализиране на системните идентификатори: {error}", + "permission_denied": "Достъпът е отказан. Опитайте да стартирате като администратор", + "windows_machine_guid_updated": "Windows машинният GUID е успешно актуализиран", + "update_windows_machine_guid_failed": "Неуспешно актуализиране на Windows машинния GUID: {error}", + "windows_machine_id_updated": "Windows машинният идентификатор е успешно актуализиран", + "update_windows_machine_id_failed": "Неуспешно актуализиране на Windows машинния идентификатор: {error}", + "sqm_client_key_not_found": "Регистърният ключ SQMClient не е намерен", + "update_windows_system_ids_failed": "Неуспешно актуализиране на Windows системните идентификатори: {error}", + "macos_platform_uuid_updated": "macOS платформеният UUID е успешно актуализиран", + "failed_to_execute_plutil_command": "Неуспешно изпълнение на plutil командата", + "update_macos_system_ids_failed": "Неуспешно актуализиране на macOS системните идентификатори: {error}", + "ids_to_restore": "Машинни идентификатори за възстановяване", + "confirm": "Сигурни ли сте, че искате да възстановите тези идентификатори?", + "success": "Машинният идентификатор е успешно възстановен", + "process_error": "Грешка при процеса на възстановяване: {error}", + "press_enter": "Натиснете Enter, за да продължите" } } \ No newline at end of file diff --git a/locales/de.json b/locales/de.json index 5a5fc2d..19358ad 100644 --- a/locales/de.json +++ b/locales/de.json @@ -31,7 +31,9 @@ "operation_cancelled_by_user": "Vorgang vom Benutzer abgebrochen", "exiting": "Wird beendet ……", "bypass_version_check": "Cursor Versionsprüfung Überspringen", - "check_user_authorized": "Benutzerautorisierung Prüfen" + "check_user_authorized": "Benutzerautorisierung Prüfen", + "bypass_token_limit": "Token-Limit umgehen", + "restore_machine_id": "Geräte-ID aus Backup wiederherstellen" }, "languages": { "en": "Englisch", @@ -407,5 +409,48 @@ "profile_selected": "Ausgewähltes Profil: {profile}", "invalid_selection": "Ungültige Auswahl. Bitte versuchen Sie es erneut", "warning_chrome_close": "Warnung: Dies wird alle laufenden Chrome-Prozesse beenden" + }, + "restore": { + "title": "Geräte-ID aus Backup wiederherstellen", + "starting": "Starte Wiederherstellungsprozess für Geräte-ID", + "no_backups_found": "Keine Backup-Dateien gefunden", + "available_backups": "Verfügbare Backup-Dateien", + "select_backup": "Wählen Sie ein Backup zur Wiederherstellung aus", + "to_cancel": "zum Abbrechen", + "operation_cancelled": "Vorgang abgebrochen", + "invalid_selection": "Ungültige Auswahl", + "please_enter_number": "Bitte geben Sie eine gültige Zahl ein", + "missing_id": "Fehlende ID: {id}", + "read_backup_failed": "Backup-Datei konnte nicht gelesen werden: {error}", + "current_file_not_found": "Aktuelle Speicherdatei nicht gefunden", + "current_backup_created": "Backup der aktuellen Speicherdatei erstellt", + "storage_updated": "Speicherdatei erfolgreich aktualisiert", + "update_failed": "Aktualisierung der Speicherdatei fehlgeschlagen: {error}", + "sqlite_not_found": "SQLite-Datenbank nicht gefunden", + "updating_sqlite": "Aktualisiere SQLite-Datenbank", + "updating_pair": "Aktualisiere Schlüssel-Wert-Paar", + "sqlite_updated": "SQLite-Datenbank erfolgreich aktualisiert", + "sqlite_update_failed": "Aktualisierung der SQLite-Datenbank fehlgeschlagen: {error}", + "machine_id_backup_created": "Backup der machineId-Datei erstellt", + "backup_creation_failed": "Backup-Erstellung fehlgeschlagen: {error}", + "machine_id_updated": "machineId-Datei erfolgreich aktualisiert", + "machine_id_update_failed": "Aktualisierung der machineId-Datei fehlgeschlagen: {error}", + "updating_system_ids": "Aktualisiere System-IDs", + "system_ids_update_failed": "Aktualisierung der System-IDs fehlgeschlagen: {error}", + "permission_denied": "Zugriff verweigert. Bitte versuchen Sie es mit Administratorrechten", + "windows_machine_guid_updated": "Windows-Geräte-GUID erfolgreich aktualisiert", + "update_windows_machine_guid_failed": "Aktualisierung des Windows-Geräte-GUID fehlgeschlagen: {error}", + "windows_machine_id_updated": "Windows-Geräte-ID erfolgreich aktualisiert", + "update_windows_machine_id_failed": "Aktualisierung der Windows-Geräte-ID fehlgeschlagen: {error}", + "sqm_client_key_not_found": "SQMClient-Registrierungsschlüssel nicht gefunden", + "update_windows_system_ids_failed": "Aktualisierung der Windows-System-IDs fehlgeschlagen: {error}", + "macos_platform_uuid_updated": "macOS-Plattform-UUID erfolgreich aktualisiert", + "failed_to_execute_plutil_command": "Ausführung des plutil-Befehls fehlgeschlagen", + "update_macos_system_ids_failed": "Aktualisierung der macOS-System-IDs fehlgeschlagen: {error}", + "ids_to_restore": "Wiederherzustellende Geräte-IDs", + "confirm": "Sind Sie sicher, dass Sie diese IDs wiederherstellen möchten?", + "success": "Geräte-ID erfolgreich wiederhergestellt", + "process_error": "Fehler beim Wiederherstellungsprozess: {error}", + "press_enter": "Drücken Sie Enter, um fortzufahren" } } \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index 4e40521..c3cd89d 100644 --- a/locales/en.json +++ b/locales/en.json @@ -32,7 +32,8 @@ "exiting": "Exiting ……", "bypass_version_check": "Bypass Cursor Version Check", "check_user_authorized": "Check User Authorized", - "bypass_token_limit": "Bypass Token Limit" + "bypass_token_limit": "Bypass Token Limit", + "restore_machine_id": "Restore Machine ID from Backup" }, "languages": { "en": "English", @@ -764,5 +765,48 @@ "connection_error": "Connection error to refresh server", "unexpected_error": "Unexpected error during token refresh: {error}", "extraction_error": "Error extracting token: {error}" + }, + "restore": { + "title": "Restore Machine ID from Backup", + "starting": "Starting Machine ID Restore Process", + "no_backups_found": "No backup files found", + "available_backups": "Available backup files", + "select_backup": "Select backup to restore", + "to_cancel": "to cancel", + "operation_cancelled": "Operation cancelled", + "invalid_selection": "Invalid selection", + "please_enter_number": "Please enter a valid number", + "missing_id": "Missing ID: {id}", + "read_backup_failed": "Failed to read backup file: {error}", + "current_file_not_found": "Current storage file not found", + "current_backup_created": "Created backup of current storage file", + "storage_updated": "Storage file updated successfully", + "update_failed": "Failed to update storage file: {error}", + "sqlite_not_found": "SQLite database not found", + "updating_sqlite": "Updating SQLite database", + "updating_pair": "Updating key-value pair", + "sqlite_updated": "SQLite database updated successfully", + "sqlite_update_failed": "Failed to update SQLite database: {error}", + "machine_id_backup_created": "Created backup of machineId file", + "backup_creation_failed": "Failed to create backup: {error}", + "machine_id_updated": "machineId file updated successfully", + "machine_id_update_failed": "Failed to update machineId file: {error}", + "updating_system_ids": "Updating system IDs", + "system_ids_update_failed": "Failed to update system IDs: {error}", + "permission_denied": "Permission denied. Please try running as administrator", + "windows_machine_guid_updated": "Windows Machine GUID updated successfully", + "update_windows_machine_guid_failed": "Failed to update Windows Machine GUID: {error}", + "windows_machine_id_updated": "Windows Machine ID updated successfully", + "update_windows_machine_id_failed": "Failed to update Windows Machine ID: {error}", + "sqm_client_key_not_found": "SQMClient registry key not found", + "update_windows_system_ids_failed": "Failed to update Windows system IDs: {error}", + "macos_platform_uuid_updated": "macOS Platform UUID updated successfully", + "failed_to_execute_plutil_command": "Failed to execute plutil command", + "update_macos_system_ids_failed": "Failed to update macOS system IDs: {error}", + "ids_to_restore": "Machine IDs to restore", + "confirm": "Are you sure you want to restore these IDs?", + "success": "Machine ID restored successfully", + "process_error": "Restore process error: {error}", + "press_enter": "Press Enter to continue" } -} \ No newline at end of file +} \ No newline at end of file diff --git a/locales/es.json b/locales/es.json index d2a16aa..24316c9 100644 --- a/locales/es.json +++ b/locales/es.json @@ -30,7 +30,9 @@ "operation_cancelled_by_user": "Operación cancelada por el usuario", "exiting": "Saliendo ……", "bypass_version_check": "Omitir Verificación de Versión de Cursor", - "check_user_authorized": "Verificar Usuario Autorizado" + "check_user_authorized": "Verificar Usuario Autorizado", + "bypass_token_limit": "Omitir límite de tokens", + "restore_machine_id": "Restaurar ID de máquina desde copia de seguridad" }, "languages": { "en": "Inglés", @@ -465,5 +467,48 @@ "profile_selected": "Perfil seleccionado: {profile}", "invalid_selection": "Selección inválida. Por favor, intente de nuevo", "warning_chrome_close": "Advertencia: Esto cerrará todos los procesos de Chrome en ejecución" + }, + "restore": { + "title": "Restaurar ID de máquina desde copia de seguridad", + "starting": "Iniciando proceso de restauración de ID de máquina", + "no_backups_found": "No se encontraron copias de seguridad", + "available_backups": "Copias de seguridad disponibles", + "select_backup": "Seleccione una copia de seguridad para restaurar", + "to_cancel": "para cancelar", + "operation_cancelled": "Operación cancelada", + "invalid_selection": "Selección inválida", + "please_enter_number": "Por favor, introduzca un número válido", + "missing_id": "ID faltante: {id}", + "read_backup_failed": "Error al leer el archivo de copia de seguridad: {error}", + "current_file_not_found": "No se encontró el archivo de almacenamiento actual", + "current_backup_created": "Se creó una copia de seguridad del archivo de almacenamiento actual", + "storage_updated": "Archivo de almacenamiento actualizado con éxito", + "update_failed": "Error al actualizar el archivo de almacenamiento: {error}", + "sqlite_not_found": "No se encontró la base de datos SQLite", + "updating_sqlite": "Actualizando base de datos SQLite", + "updating_pair": "Actualizando par clave-valor", + "sqlite_updated": "Base de datos SQLite actualizada con éxito", + "sqlite_update_failed": "Error al actualizar la base de datos SQLite: {error}", + "machine_id_backup_created": "Se creó una copia de seguridad del archivo machineId", + "backup_creation_failed": "Error al crear la copia de seguridad: {error}", + "machine_id_updated": "Archivo machineId actualizado con éxito", + "machine_id_update_failed": "Error al actualizar el archivo machineId: {error}", + "updating_system_ids": "Actualizando IDs del sistema", + "system_ids_update_failed": "Error al actualizar los IDs del sistema: {error}", + "permission_denied": "Permiso denegado. Intente ejecutar como administrador", + "windows_machine_guid_updated": "GUID de máquina Windows actualizado con éxito", + "update_windows_machine_guid_failed": "Error al actualizar el GUID de máquina Windows: {error}", + "windows_machine_id_updated": "ID de máquina Windows actualizado con éxito", + "update_windows_machine_id_failed": "Error al actualizar el ID de máquina Windows: {error}", + "sqm_client_key_not_found": "No se encontró la clave de registro SQMClient", + "update_windows_system_ids_failed": "Error al actualizar los IDs del sistema Windows: {error}", + "macos_platform_uuid_updated": "UUID de plataforma macOS actualizado con éxito", + "failed_to_execute_plutil_command": "Error al ejecutar el comando plutil", + "update_macos_system_ids_failed": "Error al actualizar los IDs del sistema macOS: {error}", + "ids_to_restore": "IDs de máquina a restaurar", + "confirm": "¿Está seguro de que desea restaurar estos IDs?", + "success": "ID de máquina restaurado con éxito", + "process_error": "Error en el proceso de restauración: {error}", + "press_enter": "Presione Enter para continuar" } -} +} \ No newline at end of file diff --git a/locales/fr.json b/locales/fr.json index a371eb3..c0a7cc5 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -28,7 +28,9 @@ "operation_cancelled_by_user": "Opération annulée par l'utilisateur", "exiting": "Fermeture ……", "bypass_version_check": "Ignorer la Vérification de Version de Cursor", - "check_user_authorized": "Vérifier l'Autorisation de l'Utilisateur" + "check_user_authorized": "Vérifier l'Autorisation de l'Utilisateur", + "bypass_token_limit": "Contourner la limite de tokens", + "restore_machine_id": "Restaurer l'ID de machine depuis une sauvegarde" }, "languages": { "en": "Anglais", @@ -404,5 +406,48 @@ "profile_selected": "Profil sélectionné : {profile}", "invalid_selection": "Sélection invalide. Veuillez réessayer", "warning_chrome_close": "Attention : Cela fermera tous les processus Chrome en cours d'exécution" + }, + "restore": { + "title": "Restaurer l'ID de machine depuis une sauvegarde", + "starting": "Démarrage du processus de restauration de l'ID de machine", + "no_backups_found": "Aucune sauvegarde trouvée", + "available_backups": "Sauvegardes disponibles", + "select_backup": "Sélectionnez une sauvegarde à restaurer", + "to_cancel": "pour annuler", + "operation_cancelled": "Opération annulée", + "invalid_selection": "Sélection invalide", + "please_enter_number": "Veuillez entrer un numéro valide", + "missing_id": "ID manquant : {id}", + "read_backup_failed": "Échec de lecture du fichier de sauvegarde : {error}", + "current_file_not_found": "Fichier de stockage actuel introuvable", + "current_backup_created": "Sauvegarde du fichier de stockage actuel créée", + "storage_updated": "Fichier de stockage mis à jour avec succès", + "update_failed": "Échec de la mise à jour du fichier de stockage : {error}", + "sqlite_not_found": "Base de données SQLite introuvable", + "updating_sqlite": "Mise à jour de la base de données SQLite", + "updating_pair": "Mise à jour de la paire clé-valeur", + "sqlite_updated": "Base de données SQLite mise à jour avec succès", + "sqlite_update_failed": "Échec de la mise à jour de la base de données SQLite : {error}", + "machine_id_backup_created": "Sauvegarde du fichier machineId créée", + "backup_creation_failed": "Échec de création de la sauvegarde : {error}", + "machine_id_updated": "Fichier machineId mis à jour avec succès", + "machine_id_update_failed": "Échec de la mise à jour du fichier machineId : {error}", + "updating_system_ids": "Mise à jour des ID système", + "system_ids_update_failed": "Échec de la mise à jour des ID système : {error}", + "permission_denied": "Permission refusée. Veuillez essayer d'exécuter en tant qu'administrateur", + "windows_machine_guid_updated": "GUID de machine Windows mis à jour avec succès", + "update_windows_machine_guid_failed": "Échec de la mise à jour du GUID de machine Windows : {error}", + "windows_machine_id_updated": "ID de machine Windows mis à jour avec succès", + "update_windows_machine_id_failed": "Échec de la mise à jour de l'ID de machine Windows : {error}", + "sqm_client_key_not_found": "Clé de registre SQMClient introuvable", + "update_windows_system_ids_failed": "Échec de la mise à jour des ID système Windows : {error}", + "macos_platform_uuid_updated": "UUID de plateforme macOS mis à jour avec succès", + "failed_to_execute_plutil_command": "Échec d'exécution de la commande plutil", + "update_macos_system_ids_failed": "Échec de la mise à jour des ID système macOS : {error}", + "ids_to_restore": "ID de machine à restaurer", + "confirm": "Êtes-vous sûr de vouloir restaurer ces ID ?", + "success": "ID de machine restauré avec succès", + "process_error": "Erreur du processus de restauration : {error}", + "press_enter": "Appuyez sur Entrée pour continuer" } } \ No newline at end of file diff --git a/locales/nl.json b/locales/nl.json index 6da3d66..f37ed8b 100644 --- a/locales/nl.json +++ b/locales/nl.json @@ -29,7 +29,9 @@ "operation_cancelled_by_user": "Operatie geannuleerd door gebruiker", "exiting": "Afsluiten ……", "bypass_version_check": "Cursor Versiecontrole Overslaan", - "check_user_authorized": "Gebruikersautorisatie Controleren" + "check_user_authorized": "Gebruikersautorisatie Controleren", + "bypass_token_limit": "Token-limiet omzeilen", + "restore_machine_id": "Machine-ID herstellen vanaf backup" }, "languages": { "en": "Engels", @@ -403,5 +405,48 @@ "profile_selected": "Geselecteerd profiel: {profile}", "invalid_selection": "Ongeldige selectie. Probeer het opnieuw", "warning_chrome_close": "Waarschuwing: Dit zal alle actieve Chrome processen sluiten" + }, + "restore": { + "title": "Machine-ID herstellen vanaf backup", + "starting": "Herstelproces van machine-ID starten", + "no_backups_found": "Geen backups gevonden", + "available_backups": "Beschikbare backups", + "select_backup": "Selecteer een backup om te herstellen", + "to_cancel": "om te annuleren", + "operation_cancelled": "Bewerking geannuleerd", + "invalid_selection": "Ongeldige selectie", + "please_enter_number": "Voer een geldig nummer in", + "missing_id": "Ontbrekende ID: {id}", + "read_backup_failed": "Lezen van backupbestand mislukt: {error}", + "current_file_not_found": "Huidig opslagbestand niet gevonden", + "current_backup_created": "Backup van huidig opslagbestand gemaakt", + "storage_updated": "Opslagbestand succesvol bijgewerkt", + "update_failed": "Bijwerken van opslagbestand mislukt: {error}", + "sqlite_not_found": "SQLite-database niet gevonden", + "updating_sqlite": "SQLite-database bijwerken", + "updating_pair": "Sleutel-waardepaar bijwerken", + "sqlite_updated": "SQLite-database succesvol bijgewerkt", + "sqlite_update_failed": "Bijwerken van SQLite-database mislukt: {error}", + "machine_id_backup_created": "Backup van machineId-bestand gemaakt", + "backup_creation_failed": "Maken van backup mislukt: {error}", + "machine_id_updated": "MachineId-bestand succesvol bijgewerkt", + "machine_id_update_failed": "Bijwerken van machineId-bestand mislukt: {error}", + "updating_system_ids": "Systeem-ID's bijwerken", + "system_ids_update_failed": "Bijwerken van systeem-ID's mislukt: {error}", + "permission_denied": "Toegang geweigerd. Probeer als administrator uit te voeren", + "windows_machine_guid_updated": "Windows machine-GUID succesvol bijgewerkt", + "update_windows_machine_guid_failed": "Bijwerken van Windows machine-GUID mislukt: {error}", + "windows_machine_id_updated": "Windows machine-ID succesvol bijgewerkt", + "update_windows_machine_id_failed": "Bijwerken van Windows machine-ID mislukt: {error}", + "sqm_client_key_not_found": "SQMClient registersleutel niet gevonden", + "update_windows_system_ids_failed": "Bijwerken van Windows systeem-ID's mislukt: {error}", + "macos_platform_uuid_updated": "macOS platform-UUID succesvol bijgewerkt", + "failed_to_execute_plutil_command": "Uitvoeren van plutil opdracht mislukt", + "update_macos_system_ids_failed": "Bijwerken van macOS systeem-ID's mislukt: {error}", + "ids_to_restore": "Te herstellen machine-ID's", + "confirm": "Weet u zeker dat u deze ID's wilt herstellen?", + "success": "Machine-ID succesvol hersteld", + "process_error": "Fout bij herstelproces: {error}", + "press_enter": "Druk op Enter om door te gaan" } -} +} \ No newline at end of file diff --git a/locales/pt.json b/locales/pt.json index b867b8c..8a468e9 100644 --- a/locales/pt.json +++ b/locales/pt.json @@ -28,7 +28,9 @@ "operation_cancelled_by_user": "Operação cancelada pelo usuário", "exiting": "Saindo ......", "bypass_version_check": "Ignorar Verificação de Versão do Cursor", - "check_user_authorized": "Verificar Autorização do Usuário" + "check_user_authorized": "Verificar Autorização do Usuário", + "bypass_token_limit": "Contornar Limite de Tokens", + "restore_machine_id": "Restaurar ID da Máquina do Backup" }, "languages": { "en": "Inglês", @@ -404,5 +406,48 @@ "profile_selected": "Perfil selecionado: {profile}", "invalid_selection": "Seleção inválida. Por favor, tente novamente", "warning_chrome_close": "Aviso: Isso fechará todos os processos do Chrome em execução" + }, + "restore": { + "title": "Restaurar ID da Máquina do Backup", + "starting": "Iniciando processo de restauração de ID da máquina", + "no_backups_found": "Nenhum backup encontrado", + "available_backups": "Backups disponíveis", + "select_backup": "Selecione um backup para restaurar", + "to_cancel": "para cancelar", + "operation_cancelled": "Operação cancelada", + "invalid_selection": "Seleção inválida", + "please_enter_number": "Por favor, insira um número válido", + "missing_id": "ID ausente: {id}", + "read_backup_failed": "Falha ao ler arquivo de backup: {error}", + "current_file_not_found": "Arquivo de armazenamento atual não encontrado", + "current_backup_created": "Backup do arquivo de armazenamento atual criado", + "storage_updated": "Arquivo de armazenamento atualizado com sucesso", + "update_failed": "Falha ao atualizar arquivo de armazenamento: {error}", + "sqlite_not_found": "Banco de dados SQLite não encontrado", + "updating_sqlite": "Atualizando banco de dados SQLite", + "updating_pair": "Atualizando par chave-valor", + "sqlite_updated": "Banco de dados SQLite atualizado com sucesso", + "sqlite_update_failed": "Falha ao atualizar banco de dados SQLite: {error}", + "machine_id_backup_created": "Backup do arquivo machineId criado", + "backup_creation_failed": "Falha ao criar backup: {error}", + "machine_id_updated": "Arquivo machineId atualizado com sucesso", + "machine_id_update_failed": "Falha ao atualizar arquivo machineId: {error}", + "updating_system_ids": "Atualizando IDs do sistema", + "system_ids_update_failed": "Falha ao atualizar IDs do sistema: {error}", + "permission_denied": "Permissão negada. Tente executar como administrador", + "windows_machine_guid_updated": "GUID da máquina Windows atualizado com sucesso", + "update_windows_machine_guid_failed": "Falha ao atualizar GUID da máquina Windows: {error}", + "windows_machine_id_updated": "ID da máquina Windows atualizado com sucesso", + "update_windows_machine_id_failed": "Falha ao atualizar ID da máquina Windows: {error}", + "sqm_client_key_not_found": "Chave de registro SQMClient não encontrada", + "update_windows_system_ids_failed": "Falha ao atualizar IDs do sistema Windows: {error}", + "macos_platform_uuid_updated": "UUID da plataforma macOS atualizado com sucesso", + "failed_to_execute_plutil_command": "Falha ao executar comando plutil", + "update_macos_system_ids_failed": "Falha ao atualizar IDs do sistema macOS: {error}", + "ids_to_restore": "IDs da máquina para restaurar", + "confirm": "Tem certeza que deseja restaurar esses IDs?", + "success": "ID da máquina restaurado com sucesso", + "process_error": "Erro no processo de restauração: {error}", + "press_enter": "Pressione Enter para continuar" } -} +} \ No newline at end of file diff --git a/locales/ru.json b/locales/ru.json index bb2dced..7c85ff8 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -29,7 +29,9 @@ "exiting": "Выход ......", "bypass_version_check": "Пропустить проверку версии Cursor", "check_user_authorized": "Проверить авторизацию пользователя", - "select_chrome_profile": "Выбрать профиль Chrome" + "select_chrome_profile": "Выбрать профиль Chrome", + "bypass_token_limit": "Обход ограничения токенов", + "restore_machine_id": "Восстановить ID устройства из резервной копии" }, "languages": { "en": "Английский", @@ -405,5 +407,48 @@ "profile_selected": "Выбран профиль: {profile}", "invalid_selection": "Неверный выбор. Пожалуйста, попробуйте снова", "warning_chrome_close": "Предупреждение: Это закроет все запущенные процессы Chrome" + }, + "restore": { + "title": "Восстановить ID устройства из резервной копии", + "starting": "Запуск процесса восстановления ID устройства", + "no_backups_found": "Резервные копии не найдены", + "available_backups": "Доступные резервные копии", + "select_backup": "Выберите резервную копию для восстановления", + "to_cancel": "для отмены", + "operation_cancelled": "Операция отменена", + "invalid_selection": "Неверный выбор", + "please_enter_number": "Пожалуйста, введите корректный номер", + "missing_id": "Отсутствует ID: {id}", + "read_backup_failed": "Не удалось прочитать файл резервной копии: {error}", + "current_file_not_found": "Текущий файл хранилища не найден", + "current_backup_created": "Создана резервная копия текущего файла хранилища", + "storage_updated": "Файл хранилища успешно обновлен", + "update_failed": "Не удалось обновить файл хранилища: {error}", + "sqlite_not_found": "База данных SQLite не найдена", + "updating_sqlite": "Обновление базы данных SQLite", + "updating_pair": "Обновление пары ключ-значение", + "sqlite_updated": "База данных SQLite успешно обновлена", + "sqlite_update_failed": "Не удалось обновить базу данных SQLite: {error}", + "machine_id_backup_created": "Создана резервная копия файла machineId", + "backup_creation_failed": "Не удалось создать резервную копию: {error}", + "machine_id_updated": "Файл machineId успешно обновлен", + "machine_id_update_failed": "Не удалось обновить файл machineId: {error}", + "updating_system_ids": "Обновление системных ID", + "system_ids_update_failed": "Не удалось обновить системные ID: {error}", + "permission_denied": "Доступ запрещен. Попробуйте запустить с правами администратора", + "windows_machine_guid_updated": "GUID устройства Windows успешно обновлен", + "update_windows_machine_guid_failed": "Не удалось обновить GUID устройства Windows: {error}", + "windows_machine_id_updated": "ID устройства Windows успешно обновлен", + "update_windows_machine_id_failed": "Не удалось обновить ID устройства Windows: {error}", + "sqm_client_key_not_found": "Ключ реестра SQMClient не найден", + "update_windows_system_ids_failed": "Не удалось обновить системные ID Windows: {error}", + "macos_platform_uuid_updated": "UUID платформы macOS успешно обновлен", + "failed_to_execute_plutil_command": "Не удалось выполнить команду plutil", + "update_macos_system_ids_failed": "Не удалось обновить системные ID macOS: {error}", + "ids_to_restore": "ID устройства для восстановления", + "confirm": "Вы уверены, что хотите восстановить эти ID?", + "success": "ID устройства успешно восстановлен", + "process_error": "Ошибка процесса восстановления: {error}", + "press_enter": "Нажмите Enter для продолжения" } } \ No newline at end of file diff --git a/locales/tr.json b/locales/tr.json index 7b98a85..ae1f045 100644 --- a/locales/tr.json +++ b/locales/tr.json @@ -31,7 +31,9 @@ "operation_cancelled_by_user": "İşlem kullanıcı tarafından iptal edildi", "exiting": "Çıkılıyor ......", "bypass_version_check": "Cursor Sürüm Kontrolünü Atla", - "check_user_authorized": "Kullanıcı Yetkilendirmesini Kontrol Et" + "check_user_authorized": "Kullanıcı Yetkilendirmesini Kontrol Et", + "bypass_token_limit": "Token Limitini Atla", + "restore_machine_id": "Makine Kimliğini Yedekten Geri Yükle" }, "languages": { "en": "English", @@ -410,5 +412,48 @@ "profile_selected": "Seçilen profil: {profile}", "invalid_selection": "Geçersiz seçim. Lütfen tekrar deneyin", "warning_chrome_close": "Uyarı: Bu işlem tüm çalışan Chrome işlemlerini kapatacaktır" + }, + "restore": { + "title": "Makine Kimliğini Yedekten Geri Yükle", + "starting": "Makine kimliği geri yükleme işlemi başlatılıyor", + "no_backups_found": "Yedek bulunamadı", + "available_backups": "Mevcut yedekler", + "select_backup": "Geri yüklemek için bir yedek seçin", + "to_cancel": "iptal etmek için", + "operation_cancelled": "İşlem iptal edildi", + "invalid_selection": "Geçersiz seçim", + "please_enter_number": "Lütfen geçerli bir numara girin", + "missing_id": "Eksik kimlik: {id}", + "read_backup_failed": "Yedek dosyası okunamadı: {error}", + "current_file_not_found": "Mevcut depolama dosyası bulunamadı", + "current_backup_created": "Mevcut depolama dosyasının yedeği oluşturuldu", + "storage_updated": "Depolama dosyası başarıyla güncellendi", + "update_failed": "Depolama dosyası güncellenemedi: {error}", + "sqlite_not_found": "SQLite veritabanı bulunamadı", + "updating_sqlite": "SQLite veritabanı güncelleniyor", + "updating_pair": "Anahtar-değer çifti güncelleniyor", + "sqlite_updated": "SQLite veritabanı başarıyla güncellendi", + "sqlite_update_failed": "SQLite veritabanı güncellenemedi: {error}", + "machine_id_backup_created": "MachineId dosyasının yedeği oluşturuldu", + "backup_creation_failed": "Yedek oluşturulamadı: {error}", + "machine_id_updated": "MachineId dosyası başarıyla güncellendi", + "machine_id_update_failed": "MachineId dosyası güncellenemedi: {error}", + "updating_system_ids": "Sistem kimlikleri güncelleniyor", + "system_ids_update_failed": "Sistem kimlikleri güncellenemedi: {error}", + "permission_denied": "İzin reddedildi. Yönetici olarak çalıştırmayı deneyin", + "windows_machine_guid_updated": "Windows makine GUID'i başarıyla güncellendi", + "update_windows_machine_guid_failed": "Windows makine GUID'i güncellenemedi: {error}", + "windows_machine_id_updated": "Windows makine kimliği başarıyla güncellendi", + "update_windows_machine_id_failed": "Windows makine kimliği güncellenemedi: {error}", + "sqm_client_key_not_found": "SQMClient kayıt anahtarı bulunamadı", + "update_windows_system_ids_failed": "Windows sistem kimlikleri güncellenemedi: {error}", + "macos_platform_uuid_updated": "macOS platform UUID'si başarıyla güncellendi", + "failed_to_execute_plutil_command": "plutil komutu yürütülemedi", + "update_macos_system_ids_failed": "macOS sistem kimlikleri güncellenemedi: {error}", + "ids_to_restore": "Geri yüklenecek makine kimlikleri", + "confirm": "Bu kimlikleri geri yüklemek istediğinizden emin misiniz?", + "success": "Makine kimliği başarıyla geri yüklendi", + "process_error": "Geri yükleme işlemi hatası: {error}", + "press_enter": "Devam etmek için Enter tuşuna basın" } -} +} \ No newline at end of file diff --git a/locales/vi.json b/locales/vi.json index 5a67f65..98c49e6 100644 --- a/locales/vi.json +++ b/locales/vi.json @@ -31,7 +31,9 @@ "operation_cancelled_by_user": "Thao tác đã bị người dùng hủy", "exiting": "Đang thoát ……", "bypass_version_check": "Bỏ qua Kiểm tra Phiên bản Cursor", - "check_user_authorized": "Kiểm tra Quyền Người dùng" + "check_user_authorized": "Kiểm tra Quyền Người dùng", + "bypass_token_limit": "Bỏ qua giới hạn Token", + "restore_machine_id": "Khôi phục ID máy từ bản sao lưu" }, "languages": { "en": "Tiếng Anh", @@ -727,5 +729,48 @@ "checking_usage_information": "Đang kiểm tra thông tin sử dụng...", "check_usage_response": "Phản hồi kiểm tra sử dụng: {response}", "usage_response": "Phản hồi sử dụng: {response}" + }, + "restore": { + "title": "Khôi phục ID máy từ bản sao lưu", + "starting": "Bắt đầu quá trình khôi phục ID máy", + "no_backups_found": "Không tìm thấy bản sao lưu nào", + "available_backups": "Các bản sao lưu có sẵn", + "select_backup": "Chọn bản sao lưu để khôi phục", + "to_cancel": "để hủy", + "operation_cancelled": "Đã hủy thao tác", + "invalid_selection": "Lựa chọn không hợp lệ", + "please_enter_number": "Vui lòng nhập một số hợp lệ", + "missing_id": "Thiếu ID: {id}", + "read_backup_failed": "Không thể đọc tệp sao lưu: {error}", + "current_file_not_found": "Không tìm thấy tệp lưu trữ hiện tại", + "current_backup_created": "Đã tạo bản sao lưu của tệp lưu trữ hiện tại", + "storage_updated": "Tệp lưu trữ đã được cập nhật thành công", + "update_failed": "Không thể cập nhật tệp lưu trữ: {error}", + "sqlite_not_found": "Không tìm thấy cơ sở dữ liệu SQLite", + "updating_sqlite": "Đang cập nhật cơ sở dữ liệu SQLite", + "updating_pair": "Đang cập nhật cặp khóa-giá trị", + "sqlite_updated": "Cơ sở dữ liệu SQLite đã được cập nhật thành công", + "sqlite_update_failed": "Không thể cập nhật cơ sở dữ liệu SQLite: {error}", + "machine_id_backup_created": "Đã tạo bản sao lưu của tệp machineId", + "backup_creation_failed": "Không thể tạo bản sao lưu: {error}", + "machine_id_updated": "Tệp machineId đã được cập nhật thành công", + "machine_id_update_failed": "Không thể cập nhật tệp machineId: {error}", + "updating_system_ids": "Đang cập nhật ID hệ thống", + "system_ids_update_failed": "Không thể cập nhật ID hệ thống: {error}", + "permission_denied": "Quyền truy cập bị từ chối. Vui lòng thử chạy với quyền quản trị", + "windows_machine_guid_updated": "GUID máy Windows đã được cập nhật thành công", + "update_windows_machine_guid_failed": "Không thể cập nhật GUID máy Windows: {error}", + "windows_machine_id_updated": "ID máy Windows đã được cập nhật thành công", + "update_windows_machine_id_failed": "Không thể cập nhật ID máy Windows: {error}", + "sqm_client_key_not_found": "Không tìm thấy khóa đăng ký SQMClient", + "update_windows_system_ids_failed": "Không thể cập nhật ID hệ thống Windows: {error}", + "macos_platform_uuid_updated": "UUID nền tảng macOS đã được cập nhật thành công", + "failed_to_execute_plutil_command": "Không thể thực thi lệnh plutil", + "update_macos_system_ids_failed": "Không thể cập nhật ID hệ thống macOS: {error}", + "ids_to_restore": "ID máy cần khôi phục", + "confirm": "Bạn có chắc chắn muốn khôi phục những ID này không?", + "success": "ID máy đã được khôi phục thành công", + "process_error": "Lỗi quá trình khôi phục: {error}", + "press_enter": "Nhấn Enter để tiếp tục" } } \ No newline at end of file diff --git a/locales/zh_cn.json b/locales/zh_cn.json index 07d15d5..697fc57 100644 --- a/locales/zh_cn.json +++ b/locales/zh_cn.json @@ -32,7 +32,8 @@ "exiting": "退出中 ……", "bypass_version_check": "绕过 Cursor 版本检查", "check_user_authorized": "检查用户授权", - "bypass_token_limit": "绕过 Token 限制" + "bypass_token_limit": "绕过 Token 限制", + "restore_machine_id": "从备份恢复机器ID" }, "languages": { "en": "英语", @@ -744,5 +745,48 @@ "connection_error": "连接刷新服务器错误", "unexpected_error": "令牌刷新过程中出现意外错误: {error}", "extraction_error": "提取令牌时出错: {error}" + }, + "restore": { + "title": "从备份恢复机器ID", + "starting": "正在启动机器ID恢复进程", + "no_backups_found": "未找到备份文件", + "available_backups": "可用的备份文件", + "select_backup": "选择要恢复的备份", + "to_cancel": "取消操作", + "operation_cancelled": "操作已取消", + "invalid_selection": "选择无效", + "please_enter_number": "请输入有效的数字", + "missing_id": "缺少ID: {id}", + "read_backup_failed": "读取备份文件失败: {error}", + "current_file_not_found": "未找到当前存储文件", + "current_backup_created": "已创建当前存储文件的备份", + "storage_updated": "存储文件已成功更新", + "update_failed": "更新存储文件失败: {error}", + "sqlite_not_found": "未找到SQLite数据库", + "updating_sqlite": "正在更新SQLite数据库", + "updating_pair": "正在更新键值对", + "sqlite_updated": "SQLite数据库已成功更新", + "sqlite_update_failed": "更新SQLite数据库失败: {error}", + "machine_id_backup_created": "已创建machineId文件的备份", + "backup_creation_failed": "创建备份失败: {error}", + "machine_id_updated": "machineId文件已成功更新", + "machine_id_update_failed": "更新machineId文件失败: {error}", + "updating_system_ids": "正在更新系统ID", + "system_ids_update_failed": "更新系统ID失败: {error}", + "permission_denied": "权限被拒绝。请尝试以管理员身份运行", + "windows_machine_guid_updated": "Windows机器GUID已成功更新", + "update_windows_machine_guid_failed": "更新Windows机器GUID失败: {error}", + "windows_machine_id_updated": "Windows机器ID已成功更新", + "update_windows_machine_id_failed": "更新Windows机器ID失败: {error}", + "sqm_client_key_not_found": "未找到SQMClient注册表项", + "update_windows_system_ids_failed": "更新Windows系统ID失败: {error}", + "macos_platform_uuid_updated": "macOS平台UUID已成功更新", + "failed_to_execute_plutil_command": "执行plutil命令失败", + "update_macos_system_ids_failed": "更新macOS系统ID失败: {error}", + "ids_to_restore": "要恢复的机器ID", + "confirm": "您确定要恢复这些ID吗?", + "success": "机器ID已成功恢复", + "process_error": "恢复过程错误: {error}", + "press_enter": "按Enter键继续" } } \ No newline at end of file diff --git a/locales/zh_tw.json b/locales/zh_tw.json index 9b9573a..9f1bc89 100644 --- a/locales/zh_tw.json +++ b/locales/zh_tw.json @@ -32,7 +32,8 @@ "exiting": "退出中 ……", "bypass_version_check": "繞過 Cursor 版本檢查", "check_user_authorized": "檢查用戶授權", - "bypass_token_limit": "繞過 Token 限制" + "bypass_token_limit": "繞過 Token 限制", + "restore_machine_id": "從備份恢復機器ID" }, "languages": { "en": "英文", @@ -122,7 +123,6 @@ "update_windows_machine_guid_failed": "更新Windows機器GUID失敗: {error}", "file_not_found": "文件未找到: {path}" }, - "register": { "title": "Cursor 註冊工具", "start": "正在啟動註冊流程...", @@ -709,5 +709,48 @@ "title": "繞過 Token 限制工具", "description": "此工具修改 workbench.desktop.main.js 文件以繞過 token 限制", "press_enter": "按回車鍵繼續..." + }, + "restore": { + "title": "從備份恢復機器ID", + "starting": "正在啟動機器ID恢復進程", + "no_backups_found": "未找到備份文件", + "available_backups": "可用的備份文件", + "select_backup": "選擇要恢復的備份", + "to_cancel": "取消操作", + "operation_cancelled": "操作已取消", + "invalid_selection": "選擇無效", + "please_enter_number": "請輸入有效的數字", + "missing_id": "缺少ID: {id}", + "read_backup_failed": "讀取備份文件失敗: {error}", + "current_file_not_found": "未找到當前存儲文件", + "current_backup_created": "已創建當前存儲文件的備份", + "storage_updated": "存儲文件已成功更新", + "update_failed": "更新存儲文件失敗: {error}", + "sqlite_not_found": "未找到SQLite數據庫", + "updating_sqlite": "正在更新SQLite數據庫", + "updating_pair": "正在更新鍵值對", + "sqlite_updated": "SQLite數據庫已成功更新", + "sqlite_update_failed": "更新SQLite數據庫失敗: {error}", + "machine_id_backup_created": "已創建machineId文件的備份", + "backup_creation_failed": "創建備份失敗: {error}", + "machine_id_updated": "machineId文件已成功更新", + "machine_id_update_failed": "更新machineId文件失敗: {error}", + "updating_system_ids": "正在更新系統ID", + "system_ids_update_failed": "更新系統ID失敗: {error}", + "permission_denied": "權限被拒絕。請嘗試以管理員身份運行", + "windows_machine_guid_updated": "Windows機器GUID已成功更新", + "update_windows_machine_guid_failed": "更新Windows機器GUID失敗: {error}", + "windows_machine_id_updated": "Windows機器ID已成功更新", + "update_windows_machine_id_failed": "更新Windows機器ID失敗: {error}", + "sqm_client_key_not_found": "未找到SQMClient註冊表項", + "update_windows_system_ids_failed": "更新Windows系統ID失敗: {error}", + "macos_platform_uuid_updated": "macOS平台UUID已成功更新", + "failed_to_execute_plutil_command": "執行plutil命令失敗", + "update_macos_system_ids_failed": "更新macOS系統ID失敗: {error}", + "ids_to_restore": "要恢復的機器ID", + "confirm": "您確定要恢復這些ID嗎?", + "success": "機器ID已成功恢復", + "process_error": "恢復過程錯誤: {error}", + "press_enter": "按Enter鍵繼續" } } \ No newline at end of file diff --git a/main.py b/main.py index e42698f..408d89b 100644 --- a/main.py +++ b/main.py @@ -293,7 +293,8 @@ def print_menu(): 8: f"{Fore.GREEN}8{Style.RESET_ALL}. {EMOJI['SETTINGS']} {translator.get('menu.config')}", 9: f"{Fore.GREEN}9{Style.RESET_ALL}. {EMOJI['UPDATE']} {translator.get('menu.bypass_version_check', fallback='Bypass Cursor Version Check')}", 10: f"{Fore.GREEN}10{Style.RESET_ALL}. {EMOJI['UPDATE']} {translator.get('menu.check_user_authorized', fallback='Check User Authorized')}", - 11: f"{Fore.GREEN}11{Style.RESET_ALL}. {EMOJI['UPDATE']} {translator.get('menu.bypass_token_limit', fallback='Bypass Token Limit')}" + 11: f"{Fore.GREEN}11{Style.RESET_ALL}. {EMOJI['UPDATE']} {translator.get('menu.bypass_token_limit', fallback='Bypass Token Limit')}", + 12: f"{Fore.GREEN}12{Style.RESET_ALL}. {EMOJI['BACKUP']} {translator.get('menu.restore_machine_id', fallback='Restore Machine ID from Backup')}" } # Automatically calculate the number of menu items in the left and right columns @@ -566,7 +567,7 @@ def main(): while True: try: - choice_num = 11 + choice_num = 12 choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices=f'0-{choice_num}')}: {Style.RESET_ALL}") match choice: @@ -619,6 +620,10 @@ def main(): import bypass_token_limit bypass_token_limit.run(translator) print_menu() + case "12": + import restore_machine_id + restore_machine_id.run(translator) + print_menu() case _: print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}") print_menu() diff --git a/restore_machine_id.py b/restore_machine_id.py new file mode 100644 index 0000000..f240fd1 --- /dev/null +++ b/restore_machine_id.py @@ -0,0 +1,406 @@ +import os +import sys +import json +import uuid +import hashlib +import shutil +import sqlite3 +import platform +import re +import glob +import tempfile +from colorama import Fore, Style, init +from typing import Tuple +import configparser +import traceback +from config import get_config +from datetime import datetime + +# 导入共享函数 +from reset_machine_manual import get_cursor_machine_id_path, get_user_documents_path + +# 初始化 colorama +init() + +# 定义表情符号常量 +EMOJI = { + "FILE": "📄", + "BACKUP": "💾", + "SUCCESS": "✅", + "ERROR": "❌", + "INFO": "ℹ️", + "RESET": "🔄", + "WARNING": "⚠️", +} + +class ConfigError(Exception): + """配置错误异常""" + pass + +class MachineIDRestorer: + def __init__(self, translator=None): + self.translator = translator + + # 读取配置 + 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') + + # 根据操作系统获取路径 + 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'): + raise ConfigError("WindowsPaths section not found in config") + + 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'): + raise ConfigError("MacPaths section not found in config") + + 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'): + raise ConfigError("LinuxPaths section not found in config") + + self.db_path = config.get('LinuxPaths', 'storage_path') + self.sqlite_path = config.get('LinuxPaths', 'sqlite_path') + + else: + raise NotImplementedError(f"Not Supported OS: {sys.platform}") + + def find_backups(self): + """查找可用的备份文件""" + db_dir = os.path.dirname(self.db_path) + db_name = os.path.basename(self.db_path) + + # 查找格式为 {db_name}.bak.{timestamp} 的文件 + backup_pattern = f"{db_name}.bak.*" + backups = glob.glob(os.path.join(db_dir, backup_pattern)) + + # 按创建时间排序(最新的在前) + backups.sort(key=os.path.getctime, reverse=True) + + return backups + + def list_backups(self): + """列出所有可用备份""" + backups = self.find_backups() + + if not backups: + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('restore.no_backups_found')}{Style.RESET_ALL}") + return None + + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('restore.available_backups')}:{Style.RESET_ALL}") + for i, backup in enumerate(backups, 1): + # 获取备份文件信息 + timestamp_str = backup.split('.')[-1] + try: + # 尝试解析时间戳(如果格式为 YYYYmmdd_HHMMSS) + timestamp = datetime.strptime(timestamp_str, "%Y%m%d_%H%M%S") + date_str = timestamp.strftime("%Y-%m-%d %H:%M:%S") + except ValueError: + date_str = "未知日期" + + # 获取文件大小 + size = os.path.getsize(backup) + size_str = f"{size / 1024:.1f} KB" + + print(f"{i}. {Fore.GREEN}{os.path.basename(backup)}{Style.RESET_ALL} ({date_str}, {size_str})") + + return backups + + def select_backup(self): + """让用户选择要恢复的备份""" + backups = self.list_backups() + + if not backups: + return None + + while True: + try: + choice = input(f"{EMOJI['INFO']} {self.translator.get('restore.select_backup')} (1-{len(backups)}, 0 {self.translator.get('restore.to_cancel')}): ") + + if choice.strip() == '0': + print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('restore.operation_cancelled')}{Style.RESET_ALL}") + return None + + index = int(choice) - 1 + if 0 <= index < len(backups): + return backups[index] + else: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.invalid_selection')}{Style.RESET_ALL}") + except ValueError: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.please_enter_number')}{Style.RESET_ALL}") + + def extract_ids_from_backup(self, backup_path): + """从备份文件中提取机器ID""" + try: + with open(backup_path, "r", encoding="utf-8") as f: + backup_data = json.load(f) + + # 提取需要恢复的ID + ids = { + "telemetry.devDeviceId": backup_data.get("telemetry.devDeviceId", ""), + "telemetry.macMachineId": backup_data.get("telemetry.macMachineId", ""), + "telemetry.machineId": backup_data.get("telemetry.machineId", ""), + "telemetry.sqmId": backup_data.get("telemetry.sqmId", ""), + "storage.serviceMachineId": backup_data.get("storage.serviceMachineId", + backup_data.get("telemetry.devDeviceId", "")) + } + + # 确保所有ID都存在 + for key, value in ids.items(): + if not value: + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('restore.missing_id', id=key)}{Style.RESET_ALL}") + + return ids + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.read_backup_failed', error=str(e))}{Style.RESET_ALL}") + return None + + def update_current_file(self, ids): + """更新当前的storage.json文件""" + try: + if not os.path.exists(self.db_path): + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.current_file_not_found')}: {self.db_path}{Style.RESET_ALL}") + return False + + # 读取当前文件 + with open(self.db_path, "r", encoding="utf-8") as f: + current_data = json.load(f) + + # 创建当前文件的备份 + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + backup_path = f"{self.db_path}.restore_bak.{timestamp}" + shutil.copy2(self.db_path, backup_path) + print(f"{Fore.GREEN}{EMOJI['BACKUP']} {self.translator.get('restore.current_backup_created')}: {backup_path}{Style.RESET_ALL}") + + # 更新ID + current_data.update(ids) + + # 保存更新后的文件 + with open(self.db_path, "w", encoding="utf-8") as f: + json.dump(current_data, f, indent=4) + + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('restore.storage_updated')}{Style.RESET_ALL}") + return True + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.update_failed', error=str(e))}{Style.RESET_ALL}") + return False + + def update_sqlite_db(self, ids): + """更新SQLite数据库中的ID""" + try: + if not os.path.exists(self.sqlite_path): + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.sqlite_not_found')}: {self.sqlite_path}{Style.RESET_ALL}") + return False + + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('restore.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 + ) + """) + + for key, value in ids.items(): + cursor.execute(""" + INSERT OR REPLACE INTO ItemTable (key, value) + VALUES (?, ?) + """, (key, value)) + print(f"{EMOJI['INFO']} {Fore.CYAN} {self.translator.get('restore.updating_pair')}: {key}{Style.RESET_ALL}") + + conn.commit() + conn.close() + + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('restore.sqlite_updated')}{Style.RESET_ALL}") + return True + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.sqlite_update_failed', error=str(e))}{Style.RESET_ALL}") + return False + + def update_machine_id_file(self, dev_device_id): + """更新machineId文件""" + try: + machine_id_path = get_cursor_machine_id_path(self.translator) + + # 创建目录(如果不存在) + os.makedirs(os.path.dirname(machine_id_path), exist_ok=True) + + # 备份当前文件(如果存在) + if os.path.exists(machine_id_path): + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + backup_path = f"{machine_id_path}.restore_bak.{timestamp}" + try: + shutil.copy2(machine_id_path, backup_path) + print(f"{Fore.GREEN}{EMOJI['INFO']} {self.translator.get('restore.machine_id_backup_created')}: {backup_path}{Style.RESET_ALL}") + except Exception as e: + print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('restore.backup_creation_failed', error=str(e))}{Style.RESET_ALL}") + + # 写入新的ID + with open(machine_id_path, "w", encoding="utf-8") as f: + f.write(dev_device_id) + + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('restore.machine_id_updated')}{Style.RESET_ALL}") + return True + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.machine_id_update_failed', error=str(e))}{Style.RESET_ALL}") + return False + + def update_system_ids(self, ids): + """更新系统级ID(特定于操作系统)""" + try: + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('restore.updating_system_ids')}...{Style.RESET_ALL}") + + if sys.platform.startswith("win"): + self._update_windows_system_ids(ids) + elif sys.platform == "darwin": + self._update_macos_system_ids(ids) + + return True + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.system_ids_update_failed', error=str(e))}{Style.RESET_ALL}") + return False + + def _update_windows_system_ids(self, ids): + """更新Windows系统ID""" + try: + import winreg + + # 更新MachineGuid + guid = ids.get("telemetry.devDeviceId", "") + if guid: + try: + key = winreg.OpenKey( + winreg.HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Cryptography", + 0, + winreg.KEY_WRITE | winreg.KEY_WOW64_64KEY + ) + winreg.SetValueEx(key, "MachineGuid", 0, winreg.REG_SZ, guid) + winreg.CloseKey(key) + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('restore.windows_machine_guid_updated')}{Style.RESET_ALL}") + except PermissionError: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.permission_denied')}{Style.RESET_ALL}") + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.update_windows_machine_guid_failed', error=str(e))}{Style.RESET_ALL}") + + # 更新SQMClient MachineId + sqm_id = ids.get("telemetry.sqmId", "") + if sqm_id: + try: + key = winreg.OpenKey( + winreg.HKEY_LOCAL_MACHINE, + r"SOFTWARE\Microsoft\SQMClient", + 0, + winreg.KEY_WRITE | winreg.KEY_WOW64_64KEY + ) + winreg.SetValueEx(key, "MachineId", 0, winreg.REG_SZ, sqm_id) + winreg.CloseKey(key) + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('restore.windows_machine_id_updated')}{Style.RESET_ALL}") + except FileNotFoundError: + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('restore.sqm_client_key_not_found')}{Style.RESET_ALL}") + except PermissionError: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.permission_denied')}{Style.RESET_ALL}") + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.update_windows_machine_id_failed', error=str(e))}{Style.RESET_ALL}") + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.update_windows_system_ids_failed', error=str(e))}{Style.RESET_ALL}") + + def _update_macos_system_ids(self, ids): + """更新macOS系统ID""" + try: + uuid_file = "/var/root/Library/Preferences/SystemConfiguration/com.apple.platform.uuid.plist" + if os.path.exists(uuid_file): + mac_id = ids.get("telemetry.macMachineId", "") + if mac_id: + cmd = f'sudo plutil -replace "UUID" -string "{mac_id}" "{uuid_file}"' + result = os.system(cmd) + if result == 0: + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('restore.macos_platform_uuid_updated')}{Style.RESET_ALL}") + else: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.failed_to_execute_plutil_command')}{Style.RESET_ALL}") + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.update_macos_system_ids_failed', error=str(e))}{Style.RESET_ALL}") + + def restore_machine_ids(self): + """恢复之前备份的机器ID""" + try: + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('restore.starting')}...{Style.RESET_ALL}") + + # 选择要恢复的备份 + backup_path = self.select_backup() + if not backup_path: + return False + + # 从备份中提取ID + ids = self.extract_ids_from_backup(backup_path) + if not ids: + return False + + # 显示将要恢复的ID + print(f"\n{Fore.CYAN}{self.translator.get('restore.ids_to_restore')}:{Style.RESET_ALL}") + for key, value in ids.items(): + print(f"{EMOJI['INFO']} {key}: {Fore.GREEN}{value}{Style.RESET_ALL}") + + # 确认恢复 + confirm = input(f"\n{EMOJI['WARNING']} {self.translator.get('restore.confirm')} (y/n): ") + if confirm.lower() != 'y': + print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('restore.operation_cancelled')}{Style.RESET_ALL}") + return False + + # 更新当前文件 + if not self.update_current_file(ids): + return False + + # 更新SQLite数据库 + self.update_sqlite_db(ids) + + # 更新machineId文件 + self.update_machine_id_file(ids.get("telemetry.devDeviceId", "")) + + # 更新系统ID + self.update_system_ids(ids) + + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('restore.success')}{Style.RESET_ALL}") + return True + + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('restore.process_error', error=str(e))}{Style.RESET_ALL}") + return False + +def run(translator=None): + """恢复机器ID的主函数""" + 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('restore.title')}{Style.RESET_ALL}") + print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}") + + restorer = MachineIDRestorer(translator) + restorer.restore_machine_ids() + + print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}") + input(f"{EMOJI['INFO']} {translator.get('restore.press_enter')}...") + +if __name__ == "__main__": + from main import translator as main_translator + run(main_translator) \ No newline at end of file