se_ga f7fab0f636 Добавлен Конфигуратор v2
Собирает конфиг в один json файл и шифрует ключом FISHKArrCONFIG
2026-03-16 14:12:17 +03:00

126 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
import os
import base64
from typing import Dict, Any
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
class ConfigManager:
"""Класс для работы с зашифрованным конфигом"""
def __init__(self, key_string: str = "FISHKArrCONFIG", config_file: str = "Config.rr"):
self.key_string = key_string
self.config_file = config_file
self.config_dir = self._get_config_directory()
self.config_path = os.path.join(self.config_dir, config_file)
self.current_config = self.load_config()
self._observers = []
def _get_config_directory(self) -> str:
"""Возвращает путь к директории для сохранения конфига"""
# Путь: C:\Users\[USERNAME]\AppData\LocalLow\Robotic Retailers\Robonect4
appdata = os.environ.get('LOCALAPPDATA', '')
if appdata:
# Заменяем 'Local' на 'LocalLow' в пути
# Обычно LOCALAPPDATA указывает на ...\AppData\Local
# Нам нужно ...\AppData\LocalLow
base_path = appdata.replace('Local', 'LocalLow')
config_dir = os.path.join(base_path, 'Robotic Retailers', 'Robonect4')
else:
# Fallback для Linux/Mac
base_path = os.path.expanduser('~')
config_dir = os.path.join(base_path, '.config', 'Robotic Retailers', 'Robonect4')
# Создаем директорию, если она не существует
try:
os.makedirs(config_dir, exist_ok=True)
print(f"Директория для конфига: {config_dir}")
except Exception as e:
print(f"Ошибка создания директории: {e}")
# В случае ошибки используем текущую директорию
config_dir = os.getcwd()
return config_dir
def add_observer(self, callback):
"""Добавляет наблюдателя для обновлений конфига"""
self._observers.append(callback)
def notify_observers(self):
"""Уведомляет наблюдателей об изменении конфига"""
for callback in self._observers:
callback()
def _derive_key(self) -> bytes:
"""Создает ключ Fernet из строки"""
# Соль фиксированная для обратной совместимости
salt = b'fishka_salt_1234'
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
key = base64.urlsafe_b64encode(kdf.derive(self.key_string.encode()))
return key
def encrypt_data(self, data: Dict[str, Any]) -> bytes:
"""Шифрует словарь в строку JSON и затем шифрует"""
json_str = json.dumps(data, ensure_ascii=False, indent=2)
fernet = Fernet(self._derive_key())
encrypted = fernet.encrypt(json_str.encode('utf-8'))
return encrypted
def decrypt_data(self, encrypted_data: bytes) -> Dict[str, Any]:
"""Расшифровывает данные"""
try:
fernet = Fernet(self._derive_key())
decrypted = fernet.decrypt(encrypted_data)
return json.loads(decrypted.decode('utf-8'))
except Exception as e:
print(f"Ошибка расшифровки: {e}")
return {}
def save_config(self, data: Dict[str, Any]) -> bool:
"""Сохраняет конфиг в файл в AppData/LocalLow"""
try:
encrypted = self.encrypt_data(data)
# Убеждаемся, что директория существует
os.makedirs(self.config_dir, exist_ok=True)
# Сохраняем файл
with open(self.config_path, 'wb') as f:
f.write(encrypted)
print(f"Конфиг сохранен: {self.config_path}")
self.current_config = data
self.notify_observers()
return True
except Exception as e:
print(f"Ошибка сохранения: {e}")
return False
def load_config(self) -> Dict[str, Any]:
"""Загружает конфиг из файла в AppData/LocalLow"""
if not os.path.exists(self.config_path):
print(f"Файл конфига не найден: {self.config_path}")
return {}
try:
with open(self.config_path, 'rb') as f:
encrypted = f.read()
config = self.decrypt_data(encrypted)
print(f"Конфиг загружен: {self.config_path}")
return config
except Exception as e:
print(f"Ошибка загрузки: {e}")
return {}
def get_config_path(self) -> str:
"""Возвращает полный путь к файлу конфига"""
return self.config_path