#!/bin/bash # define colors for output NORMAL=$(tput sgr0) RED=$(tput setaf 1) GREEN=$(tput setaf 2) YELLOW=$(tput setaf 3) BLUE=$(tput setaf 4) UNDERLINE=$(tput smul) # include settings file config=~/scripts/rclone_script/rclone_script.ini source ${config} logLevel=2 # include emulator specific settings emu_settings=~/scripts/rclone_script/emulator_settings.xml # parameters direction="$1" system="$2" emulator="$3" rom="$4" command="$5" #################### # HELPER FUNCTIONS # #################### function log () # Prints messages of different severeties to a logfile # Each message will look something like this: # # needs a set variable $logLevel # -1 > No logging at all # 0 > prints ERRORS only # 1 > prints ERRORS and WARNINGS # 2 > prints ERRORS, WARNINGS and INFO # 3 > prints ERRORS, WARNINGS, INFO and DEBUGGING # needs a set variable $log pointing to a file # Usage # log 0 "This is an ERROR Message" # log 1 "This is a WARNING" # log 2 "This is just an INFO" # log 3 "This is a DEBUG message" { severity=$1 message=$2 if (( ${severity} <= ${logLevel} )) then case ${severity} in 0) level="ERROR" ;; 1) level="WARNING" ;; 2) level="INFO" ;; 3) level="DEBUG" ;; esac printf "$(date +%FT%T%:z):\t${level}\t${0##*/}\t${FUNCNAME[1]}\t${message}\n" >> ${logfile} fi } function killOtherNotification () { # get PID of other PNGVIEW process otherPID=$(pgrep --full pngview) if [ "${debug}" = "1" ]; then log 3 "Other PIDs: ${otherPID}"; fi if [ "${otherPID}" != "" ] then if [ "${debug}" = "1" ]; then log 3 "Kill other PNGVIEW ${otherPID}"; fi kill ${otherPID} fi } function showNotification () { # Quit here, if Notifications are not to be shown and they are not forced if [ "${showNotifications}" == "FALSE" ] && [ "$6" != "forced" ] then return fi message="$1" if [ "$2" = "" ] then color="yelloW" else color="$2" fi if [ "$3" = "" ] then timeout="10000" else timeout="$3" fi if [ "$4" = "" ] then posx="10" else posx="$4" fi if [ "$5" = "" ] then posy="10" else posy="$5" fi # create PNG using IMAGEMAGICK convert -size 1500x32 xc:"rgba(0,0,0,0)" -type truecolormatte -gravity NorthWest \ -pointsize 32 -font FreeMono -style italic \ -fill ${color} -draw "text 0,0 '${message}'" \ PNG32:- > ~/scripts/rclone_script/rclone_script-notification.png killOtherNotification # show PNG using PNGVIEW nohup pngview -b 0 -l 10000 ~/scripts/rclone_script/rclone_script-notification.png -x ${posx} -y ${posy} -t ${timeout} &>/dev/null & } function getROMFileName () { rompath="${rom%/*}" # directory containing $rom romfilename="${rom##*/}" # filename of $rom, including extension romfilebase="${romfilename%%.*}" # filename of $rom, excluding extension romfileext="${romfilename#*.}" # extension of $rom } function prepareFilter () { filter="${romfilebase//\[/\\[}" filter="${filter//\]/\\]}" } # Builds a filter compatible with Find function prepareLocalFilter () { # Create an array of save file extensions read -a exts <<< $(xmlstarlet sel -t -m "emulators/emulator[name='${emulator}']/saveFileExtensions" -v . "${emu_settings}") # If any custom save file extensions are defined if [ ${#exts[@]} -gt 0 ] then # Build the filter for the extensions log 3 "Custom save extentions defined for emulator: ${emulator}" localFilter="\( -iname '*.${exts[0]}'" for ext in ${exts[@]:1}; do localFilter="${localFilter} -o -iname '*.${ext}'" done localFilter="${localFilter} \)" else # Otherwise, default to ".*" localFilter="${romfilebase//\[/\\[}" localFilter="${localFilter//\]/\\]}" fi log 3 "Local save file filter: ${localFilter}" } function prepareRemoteFilter () { } function getSavePathForEmulator () { } function getTypeOfRemote () { # list all remotes and their type remotes=$(rclone listremotes --long) # get line with RETROPIE remote retval=$(grep -i "^retropie:" <<< ${remotes}) remoteType="${retval#*:}" remoteType=$(echo ${remoteType} | xargs) } function getAvailableConnection () # checks if the device is connected to a LAN / WLAN and the Internet # RETURN # 0 > device seems to be connected to the Internet # 1 > device seems to be connected to a LAN / WLAN without internet access # 2 > device doesn't seem to be connected at all { gatewayIP=$(ip r | grep default | cut -d " " -f 3) if [ "${gatewayIP}" == "" ] then log 2 "Gateway could not be detected" return 2 else log 2 "Gateway IP: ${gatewayIP}" fi ping -q -w 1 -c 1 ${gatewayIP} > /dev/null if [[ $? -eq 0 ]] then log 2 "Gateway PING successful" else log 2 "Gateway could not be PINGed" return 2 fi ping -q -w 1 -c 1 "8.8.8.8" > /dev/null if [[ $? -eq 0 ]] then log 2 "8.8.8.8 PING successful" return 0 else log 2 "8.8.8.8 could not be PINGed" return 1 fi } ################## # SYNC FUNCTIONS # ################## function downloadSaves () { if [ "${syncOnStartStop}" == "FALSE" ] then showNotification "!!! Synchronization is currently disabled !!!" "red" "" "" "" "forced" return fi log 2 "Started ${system}/${romfilename} " log 2 "Downloading saves and states for ${system}/${romfilename} from ${remoteType}..." showNotification "Downloading saves and states from ${remoteType}..." getAvailableConnection availableConnection=$? if [[ ${availableConnection} -gt ${neededConnection} ]] then log 0 "Needed Connection not available. Needed ${neededConnection}, available ${availableConnection}" case ${neededConnection} in 0) showNotification "Downloading saves and states from ${remoteType}... No Internet connection available" "red" "" "" "" "forced" ;; 1) showNotification "Downloading saves and states from ${remoteType}... No LAN / WLAN connection available" "red" "" "" "" "forced" ;; esac return fi # test for remote files remotefiles=$(rclone lsf retropie:${remotebasedir}/${system} --include "${filter}.*") retval=$? if [ "${retval}" = "0" ] then # no error with RCLONE if [ "${remotefiles}" = "" ] then # no remote files found log 2 "No remote files found" showNotification "Downloading saves and states from ${remoteType}... No remote files found" else # remote files found log 2 "Found remote files" # download saves and states to corresponding ROM rclone copy retropie:${remotebasedir}/${system} ~/RetroPie/saves/${system} --include "${filter}.*" --update >> ${logfile} retval=$? if [ "${retval}" = "0" ] then log 2 "Done" showNotification "Downloading saves and states from ${remoteType}... Done" "green" else log 2 "Saves and states could not be downloaded" showNotification "Downloading saves and states from ${remoteType}... ERROR" "red" "" "" "" "forced" fi fi else # error with RCLONE log 0 "Saves and states could not be downloaded" showNotification "Downloading saves and states from ${remoteType}... ERROR" "red" "" "" "" "forced" fi } function uploadSaves () { if [ "${syncOnStartStop}" == "FALSE" ] then showNotification "!!! Synchronization is currently disabled !!!" "red" "" "" "" "forced" return fi log 2 "Stopped ${system}/${romfilename} " log 2 "Uploading saves and states for ${system}/${romfilename} to ${remoteType}..." showNotification "Uploading saves and states to ${remoteType}..." getAvailableConnection availableConnection=$? if [[ ${availableConnection} -gt ${neededConnection} ]] then log 0 "Needed Connection not available. Needed ${neededConnection}, available ${availableConnection}" case ${neededConnection} in 0) showNotification "Uploading saves and states to ${remoteType}... No Internet connection available" "red" "" "" "" "forced" ;; 1) showNotification "Uploading saves and states to ${remoteType}... No LAN / WLAN connection available" "red" "" "" "" "forced" ;; esac return fi localfiles=$(find ~/RetroPie/saves/${system} -type f -iname "${filter}.*") if [ "${localfiles}" = "" ] then # no local files found log 2 "No local saves and states found" showNotification "Uploading saves and states to ${remoteType}... No local files found" else # local files found # upload saves and states to corresponding ROM rclone copy ~/RetroPie/saves/${system} retropie:${remotebasedir}/${system} --include "${filter}.*" --update >> ${logfile} retval=$? if [ "${retval}" = "0" ] then log 2 "Done" showNotification "Uploading saves and states to ${remoteType}... Done" "green" else log 2 "saves and states could not be uploaded" showNotification "Uploading saves and states to ${remoteType}... ERROR" "red" "" "" "" "forced" fi fi } function deleteFileFromRemote () # deletes a file from the remote # INPUT # $1 > relative filepath incl. name and extension to the local savepath # RETURN # 0 > file deteted successfully # 1 > connection not available # 2 > file could not be deleted { fileToDelete="$1" log 2 "File to delete: retropie:${remotebasedir}/${fileToDelete}" getAvailableConnection availableConnection=$? if [[ ${availableConnection} -gt ${neededConnection} ]] then log 0 "Needed Connection not available. Needed ${neededConnection}, available ${availableConnection}" return 1 fi rclone delete "retropie:${remotebasedir}/${fileToDelete}" 2>&1 >> ${logfile} if [[ $? -eq 0 ]] then log 2 "File deleted successfully" return 0 else log 0 "File could not be deleted. Error Code $?" return 1 fi } ######## # MAIN # ######## #if [ "${debug}" = "1" ]; then debug; fi log 3 "direction: ${direction}" log 3 "system: ${system}" log 3 "emulator: ${emulator}" log 3 "rom: ${rom}" log 3 "command: ${command}" log 3 "remotebasedir: ${remotebasedir}" log 3 "rompath: ${rompath}" log 3 "romfilename: ${romfilename}" log 3 "romfilebase: ${romfilebase}" log 3 "romfileext: ${romfileext}" if [ "${direction}" == "up" ] && [ "${system}" != "kodi" ] then getROMFileName prepareLocalFilter prepareFilter getTypeOfRemote uploadSaves fi if [ "${direction}" == "down" ] && [ "${system}" != "kodi" ] then getROMFileName prepareFilter getTypeOfRemote downloadSaves fi if [ "${direction}" == "delete" ] then deleteFileFromRemote "${2}" fi