#!/bin/ash # shellcheck shell=ash # --- Configuration --- . /recalbox/share/system/configs/savesync/savesync.conf log() { local level="$1" local msg="$2" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') local log_line="[$timestamp] [$level] $msg" if [ "$level" = "ERROR" ]; then mkdir -p "$(dirname "$ERROR_LOG")" printf "%s\n" "$log_line" >>"$ERROR_LOG" fi # FIX: Corrected port to 1883 and added -m mosquitto_pub -h 127.0.0.1 -p 1883 -q 0 -t "$LOG_TOPIC" -m "SaveLog=$log_line" 2>/dev/null [ "${DEBUG_MODE:-0}" -eq 1 ] && printf "%s\n" "$log_line" } sleep 2 log "INFO" "--- ES Event Daemon Started ---" # --- Main Listener Loop --- mosquitto_sub -h 127.0.0.1 -p 1883 -q 0 -t "$TOPIC" | while IFS="=" read -r key value; do # 1. Clean input value=$(echo "$value" | tr -d '\r') case "$key" in "SystemId") this_system_id="$value" ;; "GamePath") this_game_path="$value" # Corrected logic for paths this_save_path=$(echo "$value" | sed 's|roms|saves|; s|\.[^.]*$|.srm|') this_backup_path=$(echo "$this_save_path" | sed 's|saves|archives|') ;; "Action") this_action="$value" ;; "State") this_state="$value" if [ "$this_state" = "playing" ] && [ "$this_action" = "rungame" ]; then # We wrap the whole operation in ( ) & to background the entire sequence ( log "INFO" "Game Started: $(basename "$this_game_path")" filename=$(basename "$this_save_path") remote_full="$REMOTE_BASE/$this_system_id/$filename" local_size=$(stat -c %s "$this_save_path" 2>/dev/null || echo 0) remote_size=$(rclone lsjson "$remote_full" 2>/dev/null | grep -o '"Size":[0-9]*' | cut -d: -f2) : "${remote_size:=0}" if [ "$local_size" -lt "$remote_size" ]; then log "WARN" "Cloud save LARGER. Restoring..." mkdir -p "$(dirname "$this_backup_path")" rclone copyto "$remote_full" "$this_save_path" --backup-dir "$(dirname "$this_backup_path")" else log "INFO" "Local save safe. Updating..." rclone update "$remote_full" "$this_save_path" fi # Signal that sync is done mosquitto_pub -h 127.0.0.1 -p 1883 -t "$TOPIC" -m "SaveContinue=0" ) & log "DEBUG" "Sync process backgrounded for Start Game." elif [ "$this_state" = "endgame" ]; then ( log "INFO" "Game Ended. Syncing..." rclone update "$this_save_path" "$REMOTE_BASE/$this_system_id/" log "INFO" "Sync Complete." mosquitto_pub -h 127.0.0.1 -p 1883 -t "$TOPIC" -m "SaveContinue=0" ) & log "DEBUG" "Sync process backgrounded for End Game." fi # Reset variables immediately so the loop is ready for the next line this_system_id="" this_game_path="" this_save_path="" this_action="" this_backup_path="" ;; esac done