import os import time import shutil import hashlib import logging from datetime import datetime from files import FILES CHECK_INTERVAL = 60 # segundos # Rutas base (dentro del contenedor) DATA_DIR = "data" BACKUPS_ROOT = os.path.join(DATA_DIR, "backups") LOGS_DIR = os.path.join(DATA_DIR, "logs") os.makedirs(BACKUPS_ROOT, exist_ok=True) os.makedirs(LOGS_DIR, exist_ok=True) # Configuración de logging LOG_FILE = os.path.join(LOGS_DIR, "watcher.log") logging.basicConfig( filename=LOG_FILE, level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s" ) def log_info(msg): print(msg) logging.info(msg) def log_warn(msg): print(msg) logging.warning(msg) def log_error(msg): print(msg) logging.error(msg) def sha256sum(path): """Devuelve el hash SHA256 del fichero.""" h = hashlib.sha256() with open(path, "rb") as f: for chunk in iter(lambda: f.read(4096), b""): h.update(chunk) return h.hexdigest() def ensure_backup_dir(file_path): """Crea data/backups// si no existe.""" file_name = os.path.basename(file_path) name, _ = os.path.splitext(file_name) backup_dir = os.path.join(BACKUPS_ROOT, name) os.makedirs(backup_dir, exist_ok=True) return backup_dir def get_latest_backup(file_path): """Devuelve la ruta del backup más reciente o None si no hay.""" backup_dir = ensure_backup_dir(file_path) files = sorted(os.listdir(backup_dir), reverse=True) if not files: return None return os.path.join(backup_dir, files[0]) def backup_file(file_path): """Crea una copia con timestamp.""" backup_dir = ensure_backup_dir(file_path) file_name = os.path.basename(file_path) name, ext = os.path.splitext(file_name) timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") dest = os.path.join(backup_dir, f"{name}_{timestamp}{ext}") shutil.copy2(file_path, dest) log_info(f"[BACKUP] Copia creada: {dest}") def process_file(file_path): """Comprueba si hay cambios y crea backup si es necesario.""" if not os.path.isfile(file_path): log_warn(f"[WARN] No existe: {file_path}") return latest = get_latest_backup(file_path) if latest is None: log_info(f"[INIT] No hay copia previa de {file_path}, creando primera copia...") backup_file(file_path) return try: current_hash = sha256sum(file_path) latest_hash = sha256sum(latest) except Exception as e: log_error(f"[ERROR] Calculando hash: {e}") return if current_hash != latest_hash: log_info(f"[CHANGE] Detectado cambio en {file_path}, creando nueva copia...") backup_file(file_path) else: log_info(f"[OK] Sin cambios en {file_path}") def main(): log_info("Iniciando watcher de saves...") log_info(f"Backups en: {os.path.abspath(BACKUPS_ROOT)}") log_info(f"Logs en: {os.path.abspath(LOGS_DIR)}") while True: for f in FILES: process_file(f) time.sleep(CHECK_INTERVAL) if __name__ == "__main__": main()