#!/bin/bash ########## # Script # ########## remove=1; # 1 => Delete when torrent deleted, 2 => Delete always, 0 => Delete never forceRun=0; # Skip lock file test validate="-q"; # unused with pyropeters otrtool logMsgTypes=(" " "error" "warn" "info" "debug" "debugV") logMsgColor=("\033[37m" "\033[31m" "\033[33m" "\033[37m" "\033[37m" "\033[37m") logLevel=0 echoLevel=5 lastKodiCheck=0 cutAppendix="-cut.mkv" lastProcessingLogPrinted=0 lastProcessingEchoed=0 lastProcessingEchoedNL=0 warnUnknownLabel=true declare -A label2Dir declare -A label2SaneRename declare -A label2UseDirAsParent PwD=$(readlink -e $0) # Get the path to this script PwD=$(dirname "$PwD") #################### # Helper functions # #################### # trap signals and handle them trap t_sigint SIGINT # Ctrl+C trap t_sighup SIGHUP # Hangup on Terminal trap t_sigcont SIGCONT # Continue after stop function t_sigint { funcUnlock exit 2 } function t_sighup { # Do nothing, simply continue sleep 0 } function t_sigcont { if [ -n "$lastProcessingEcho" ]; then echo -e "$lastProcessingEcho" fi } # Log message to stdout and log file function funcLog { if [ $1 -eq 0 ]; then # this is a "Processing ..." message and will be stored until an event is logged lastProcessingLog="`date +"%d.%m.%y %T"` ${logMsgTypes[0]}\t$2" # store message lastProcessingLogPrinted=0; # was not printed yet to log lastProcessingEcho="${logMsgColor[0]}\t$2\033[37m" # store message lastProcessingEchoed=0; # was not printed to stdout lastProcessingEchoedNL=0; # no new line was printed to stdout else if [ $1 -le $logLevel ]; then # if we shall log this message if (( lastProcessingLogPrinted == 0 )); then # and have not yet logged the "Processing ..." message echo -e "$lastProcessingLog" >> $logFile lastProcessingLogPrinted=1; fi echo -e "`date +"%d.%m.%y %T"` ${logMsgTypes[$1]}\t$2" >> $logFile fi if [ $1 -le $echoLevel ]; then # if we shall echo this message if (( lastProcessingEchoed == 0 )); then # and have not yet echoed the "Processing ..." message if (( lastProcessingEchoedNL == 0 )); then echo lastProcessingEchoedNL=1 fi echo -e "$lastProcessingEcho" lastProcessingEchoed=1; fi if [ $1 -eq 1 ]; then echo -e "${logMsgColor[$1]}${logMsgTypes[$1]}:\t$2\033[37m" >&2 # redirect error to stderr else echo -e "${logMsgColor[$1]}${logMsgTypes[$1]}:\t$2\033[37m" fi fi fi } # Look for lock file and exit if it is existing and $forceRun == 0 function funcLock { if [ -f /tmp/.otrDecodeAll.lock -a "$forceRun" != "1" ]; then funcLog 1 "/tmp/.otrDecodeAll.lock existing! exiting..." exit 1 else funcLog 4 "Creating lock file /tmp/.otrDecodeAll.lock" touch /tmp/.otrDecodeAll.lock fi } # Delete lock file function funcUnlock { funcLog 4 "Removing lock file /tmp/.otrDecodeAll.lock" rm -f /tmp/.otrDecodeAll.lock } ############### # Config file # ############### # Add label to dictionary function addLabel { success=1; dir=1; case $# in [0-1]) funcLog 1 "Not enough arguments given for addLabel! Give at least name and directory" success=0;; 2) sr=0;; 4) case $4 in 0) ;& [fF]) ;& false) ;& no) dir=0;; 1) ;& [tT]) ;& true) ;& yes) dir=1;; *) funcLog 1 "addLabel: Could not understand fourth argument \"$4\"! Please give \"true\" or \"false\" to specify whether the name of the movie/episode shall be used as parent directory." success=0;; esac;& # goto 3) 3) case $3 in 0) ;& [fF]) ;& false) ;& no) sr=0;; 1) ;& [tT]) ;& true) ;& yes) sr=1;; *) funcLog 1 "addLabel: Could not understand third argument \"$3\"! Please give \"true\" or \"false\" to specify whether SaneRenamix shall be used for this label." success=0;; esac;; *) funcLog 1 "Too many arguments for addLabel! Give no more than name, directory and bool whether we shall use sanerenamix for this label" success=0;; esac if [ ! -d "$outDir/$2" ]; then funcLog 1 "addLabel: Directory $outDir/$2 does not exist. Please create it first!" success=0; fi if (( success == 1 )); then funcLog 5 "Adding label \"$1\" with dir = \"$2\" and sanerename = $sr" label2Dir["$1"]="$2"; label2SaneRename["$1"]=$sr; label2UseDirAsParent["$1"]=$dir; fi } # Read config file function funcGetConfig { if [ ! -r "$PwD/config" ]; then if [ ! -r "$PwD/config.sample" ]; then funcLog 1 "$PwD/config does not exist!" exit 1 else funcLog 2 "You should use $PwD/config insted of config.sample!" source "$PwD/config.sample" fi else source "$PwD/config" fi funcConfigPre } ########## # Checks # ########## # Check for installed tools function funcPerformChecks { local exet; exet=0 if ! type "$cmdDecode" >/dev/null 2>&1; then funcLog 1 "Please install otrtool" exet=1 fi if [ -n "$cmdCut" ] && ! type "$cmdCut" >/dev/null 2>&1; then funcLog 1 "Please check the path to multicutmkv" exet=1 fi if [ -n "$cmdSaneRenamix" ] && ! type "$cmdSaneRenamix" >/dev/null 2>&1; then funcLog 1 "Please check the path to SaneRenamix (set to empty if not wanted)" exet=1 fi if [ -n "$kodiUrl" ] && ! type "curl" >/dev/null 2>&1; then funcLog 1 "Please install curl to check the Kodi state" exet=1 fi if (( exet == 1 )); then funcUnlock exit 1 fi funcPerformKodiCheck } # Check whether Kodi is playing something function funcPerformKodiCheck { local curTimestamp; if (( forceRun == 0 )) && [ -n "$kodiUrl" ]; then # If we can and have to check whether Kodi is playing something curTimestamp=$(date +%s) if [ $(($curTimestamp-$lastKodiCheck)) -gt 10 ]; then # Only check all 10 seconds playerID="$(curl -s $kodiUrl/jsonrpc -H 'content-type: application/json;' --data-binary '{"jsonrpc": "2.0", "method": "Player.GetActivePlayers", "id": 1}' | grep -o "[0-9],.type.:.$1" | grep -o '[0-9]')" if [ -n "$playerID" ]; then funcLog 3 "Kodi is running, exiting now" funcUnlock exit fi lastKodiCheck=$curTimestamp funcLog 5 "Kodi is not running" fi fi } # Request Kodi to update its Video library function funcUpdateKodi { if [ -n "$kodiUrl" ]; then if (( scanKodi == 1 )); then scanOK="$(curl -s $kodiUrl/jsonrpc -H 'content-type: application/json;' --data-binary '{"jsonrpc": "2.0", "method": "VideoLibrary.Scan", "id": 1}' | egrep -o "\"[^\"]*\"}" | egrep -o [A-Za-z0-9]+)" if [ "$scanOK" != "OK" ]; then funcLog 2 "Kodi did not return OK on command VideoLibrary.Scan" else funcLog 5 "Kodi returned OK on command VideoLibrary.Scan" fi fi if (( cleanKodi == 1 )); then cleanOK="$(curl -s $kodiUrl/jsonrpc -H 'content-type: application/json;' --data-binary '{"jsonrpc": "2.0", "method": "VideoLibrary.Clean", "id": 1}' | egrep -o "\"[^\"]*\"}" | egrep -o [A-Za-z0-9]+)" if [ "$cleanOK" != "OK" ]; then funcLog 2 "Kodi did not return OK on command VideoLibrary.Clean" else funcLog 5 "Kodi returned OK on command VideoLibrary.Clean" fi fi fi } ################ # Command line # ################ # Parse parameters from command line function funcParam { while getopts "frkvh?e:p:i:o:t:l:" optval; do case $optval in "f") funcLog 4 "Set forceRun = 1" forceRun=1;; # ignore lock file "r") funcLog 4 "Set remove = 2 (always)" remove=2;; # delete the otrkey "k") funcLog 4 "Set remove = 0 (never)" remove=0;; # keep the otrkey "v") funcLog 4 "Set validate = '' (yes)" validate="";; # validate the output file after decoding. Not needed when downloaded via torrent "e") funcLog 4 "Set user = $OPTARG" user=$OPTARG;; # different user "p") funcLog 4 "Set pass = $OPTARG" pass=$OPTARG;; # different password "i") funcLog 4 "Set indir = $OPTARG" inDir=$OPTARG;; # different input dir "o") funcLog 4 "Set outDir = $OPTARG" outDir=$OPTARG;; # different output dir "t") funcLog 4 "Set tempDir = $OPTARG" tempDir=$OPTARG;; # different temp dir "l") funcLog 4 "Set labelFilter = $OPTARG" labelFilter=$OPTARG;; "h"|"?") funcHelp; # print help exit;; ":") echo "No argument value for option $OPTARG";; esac done funcConfigPost } # Print some help text and explain parameters function funcHelp { echo -e "\n\033[1;31m./otrDecodeAll.sh [-f -r -k -v -h] [-e user] [-p password] [-i inputDir] [-d decodedDir] [-o outputDir] [-l label]\033[0;37m" echo "-> FORCE" echo -e " \033[36m-f\033[37m Make this script ignore the lockfile and Kodi. This may result into decoding some files multiple times (perhaps corrupting them) and making Kodi less smooth." echo "-> REMOVE" echo -e " \033[36m-r\033[37m Make this script delete the original otrkey files." echo "-> KEEP" echo -e " \033[36m-k\033[37m Make this script keep the original otrkey files. If not given, the otrkey will be kept after decoding and when torrent file is not found." echo "-> NO VALIDATE" echo -e " \033[36m-v\033[37m Make otrdecoder validate the output file. This should not be neccessarry when you downloaded it via torrent." echo "-> USER" echo -e " \033[36m-e\033[37m Specify the OTR email address if you do not want to use the default." echo "-> PASSWORD" echo -e " \033[36m-p\033[37m Specify the OTR password if you do not want to use the default." echo "-> INPUTDIR" echo -e " \033[36m-i\033[37m Specify the input directory where the *.otrkey files are located." echo "-> DECODEDDIR" echo -e " \033[36m-d\033[37m Specify the output directory where the decoded file shall be put before cutting." echo "-> UNCUTDIR" echo -e " \033[36m-o\033[37m Specify the directory where the decoded and cut file shall be put." echo "-> LABEL" echo -e " \033[36m-l\033[37m Only decode movies with the specified label." echo "-> HELP" echo -e " \033[36m-h\033[37m Show this help." } ################## # File Functions # ################## # In here lives the main loop which processes all otrkeys function funcProcessFiles { local nextStep local status # 0 undef; 1 encoded; 2 decoded; 3 cut; local alrMoved # 0 not moved; 1 already moved; local files="`ls $inDir/*.otrkey 2> /dev/null`" # All otrkeys in input dir for file in $files; do # For each otrkey funcPerformKodiCheck # Check whether Kodi is running if (( echoLevel == 5 )); then echo -ne "\npress to continue..."; read; fi filename="$(basename $file)" # Determine the filename filename="${filename%.otrkey}" funcLog 0 "Processing $filename"; funcGetLabel # Read the label from the database if [ -z "$label" -a "$label" != "N\\A" ]; then # Empty label and labelDb does exist --> skip funcLog 1 "No label specified for this movie. Skipping" continue; fi if [ -n "$labelFilter" ] && [ "$labelFilter" != "$label" ]; then # This label shall not be handled --> skip funcLog 4 "Label did not match filter. Skipping"; continue; fi status=0; alrMoved=0; funcMakeVars # Make all path variables if [ -z "$label" ]; then continue; fi if (( lastProcessingEchoedNL == 0 )); then echo # create a newline to separate output lastProcessingEchoedNL=1 fi echo -e " >> \033[32m$sanename\033[37m"; status=1; # If file was already cut if [ -n "$pathAbsOutCutInsane" -a -f "$pathAbsOutCutInsane" ]; then # Sanerenamix could not name this file before, but now it cans funcLog 4 "Renamed $filename to $sanename" mv $pathAbsOutCutInsane $pathAbsOutCut status=3; alrMoved=1; scanKodi=1; cleanKodi=1; elif [ -f "$pathAbsOutCut" ]; then # The final output file already exists funcLog 4 "File was already decoded and cut." status=3; alrMoved=1; fi # If file was already decoded if (( status <= 2 )); then if [ -n "$pathAbsOutDecodedInsane" -a -f "$pathAbsOutDecodedInsane" ]; then # Sanerenamix could not name this file before, but now it cans funcLog 4 "Renamed decoded $filename to $sanename" # We were unable to cut the last time mv $pathAbsOutDecodedInsane $pathAbsOutDecoded scanKodi=1; cleanKodi=1; status=2; elif [ -f "$pathAbsOutDecoded" ]; then funcLog 4 "File was already decoded." status=2; fi if (( status == 2 )); then pathTmpAbsDecoded="$pathAbsOutDecoded" # Use the decoded file in the output dir directly funcLog 5 "pathTmpAbsDecoded: $pathTmpAbsDecoded" if [ "$sanename" != "$filename" ]; then # Our output file has a sanename pathTmpAbsCut="$tempDir/$sanename$cutAppendix" # so the cut file will also have this name funcLog 5 "pathTmpAbsCut: $pathTmpAbsCut" fi alrMoved=1; fi fi if (( status == 1 )); then # encoded # Decode the file if neccessary funcDecode "$pathAbsEncoded"; if (( success != 1 )); then # Decoding failed, we can skip the rest continue; fi status=2 fi if (( status == 2 )); then # Cut the file if neccessary funcCut "$pathTmpAbsDecoded" if (( success == 1 )); then # Cutting did not fail status=3; alrMoved=0; # Our new file is in tempDir else # Cutting did fail local sizeEnc local sizeDec sizeEnc=`stat -L -c%s "$pathAbsEncoded"` sizeDec=`stat -L -c%s "$pathTmpAbsDecoded"` if [ $(($sizeEnc-$sizeDec)) -ne 522 ]; then # If decoded file is different to encoded file funcLog 5 "Cutting failed. But the encoded file ($sizeEnc) is not the source of the decoded file ($sizeDec)." funcLog 5 "Searching cutlists for encoded file" funcLog 5 "$cmdCut -find-cl 522 \"$pathAbsEncoded\"" $cmdCut -find-cl 522 "$pathAbsEncoded" if [ $? -eq 0 ]; then # The (new) encoded file can be cut funcLog 3 "The new otrkey file can be cut. We will try it." ## What shall we do now? funcRemoveFile "$pathTmpAbsDecoded" # Next time the file will be decoded and cut. This is not the best way... else funcLog 5 "No cutlist found" fi fi fi fi # Move the final file to its destination if (( status == 2 )); then # only decoded pathMoveFrom="$pathTmpAbsDecoded" pathMoveTo="$pathAbsOutDecoded" elif (( status == 3 )); then # also cut pathMoveFrom="$pathTmpAbsCut" pathMoveTo="$pathAbsOutCut" fi if (( status >= 2 )); then funcMove "$pathMoveFrom" "$pathMoveTo" if (( success == 1 )); then # Moving the file failed, we can skip the rest alrMoved=1; fi fi # delete the otrkey if applicable funcRemove $file done } # Retreive the label for the current file function funcGetLabel { if [ -n "$labelDb" -a -r "$labelDb" ]; then label="$(LC_ALL=C fgrep -m 1 "$filename" $labelDb | grep -o ' [a-zA-Z0-9_-]*$' | grep -o '[a-zA-Z0-9_-]*$')" funcLog 5 "label: $label" else funcLog 5 "no/incorrect labelDb given" label="N\\A" fi } # Set all variables for the current file function funcMakeVars { local error; error=false; # This contains the OTR name of the file (e.g. Good_Wife_15.02.17_23-55_sixx_50_TVOON_DE.mpg.HQ.avi) funcLog 5 "filename: $filename" # This will be our name for the subfolder (movie name, e.g. Good.Wife) bibname=${filename%%_[0-9][0-9].*} bibname="${bibname%%_S[0-9][0-9]E[0-9][0-9]}" bibname="${bibname//_/.}" funcLog 5 "bibname: $bibname" # This is the absolute path to the encoded file (e.g. /stuff/Good_Wife_15.02.17_23-55_sixx_50_TVOON_DE.mpg.HQ.avi.otrkey) pathAbsEncoded="$inDir/$filename.otrkey" funcLog 5 "pathAbsEncoded: $pathAbsEncoded" # This is the absolute path to the decoded file (e.g. /stuff/Good_Wife_15.02.17_23-55_sixx_50_TVOON_DE.mpg.HQ.avi) pathTmpAbsDecoded="$tempDir/$filename" funcLog 5 "pathTmpAbsDecoded: $pathTmpAbsDecoded" # This is the absolute path to the cut file (e.g. /stuff/Good_Wife_15.02.17_23-55_sixx_50_TVOON_DE.mpg.HQ.avi-cut.mkv) pathTmpAbsCut="$tempDir/$filename$cutAppendix" funcLog 5 "pathTmpAbsCut: $pathTmpAbsCut" # Now we will determine the path where to put the file in the end (depends on label and saneRenamix) # sanename is normally the filename. In case of tv series the sanename will also contain the series and episode number and title sanename=$filename # Default value (in case of error) if [ ${#label2Dir[@]} -gt 0 -a "$label" != "N\\A" ]; then # if we want to use labels if [ -z "$label" ]; then # don't allow empty labels error=true; else pathAbsOutDecoded="${label2Dir["$label"]}" # get relative output directory for this label if [ -z "$pathAbsOutDecoded" ]; then if $warnUnknownLabel; then funcLog 2 "Unknown label: $label" fi error=true; elif [ ${label2SaneRename["$label"]} -eq 1 ]; then # call SaneRenamix if indicated tmp="$($cmdSaneRenamix $cmdSaneRenamixArgs $filename)" local err=$? error=true; case $err in # return value conversion 0) bibname="${tmp%%..*}" sanename="$tmp" error=false; funcLog 5 "sanename: $sanename";; 1) funcLog 1 "SaneRenamix: General error!";; 2) funcLog 1 "SaneRenamix: Specified language not recognized";; 3) funcLog 3 "SaneRenamix: Aborted (Ctrl+C)";; 10) funcLog 2 "SaneRenamix: Series not found in TvDB";; 11) funcLog 2 "SaneRenamix: Series not found in EPG";; 20) funcLog 2 "SaneRenamix: No info for this episode found";; 21) funcLog 2 "SaneRenamix: No episode title found in EPG";; 40) funcLog 1 "SaneRenamix: Downloading EPG data failed";; 41) funcLog 1 "SaneRenamix: Downloading list of episodes from TvDB failed";; *) funcLog 1 "SaneRenamix: Unknown error $err";; esac fi fi fi # if we do not want to use labels if $error; then label=""; else # Save the insane filename in case saneRenamix did not work once before if [ $sanename != $filename ]; then # No sanename bibnameInsane=${filename%%_[0-9][0-9].*} bibnameInsane="${bibnameInsane%%_S[0-9][0-9]E[0-9][0-9]}" bibnameInsane="${bibnameInsane//_/.}" pathAbsOutDecodedInsane="$outDir/$pathAbsOutDecoded/$bibnameInsane/$filename" funcLog 5 "pathAbsOutDecodedInsane: $pathAbsOutDecodedInsane" pathAbsOutCutInsane="$pathAbsOutDecodedInsane$cutAppendix" funcLog 5 "pathAbsOutCutInsane: $pathAbsOutCutInsane" fi if [ "${label2UseDirAsParent["$label"]}" -ne 0 ]; then pathAbsOutDecoded="$pathAbsOutDecoded/$bibname" # Append bibname: This is the series name or the movie name (Kodi likes this) fi # This will be the absolute path to the output file (e.g. /final/Good.Wife/Good.Wife..S05E14..Ein.paar.Worte.HQ.avi) pathAbsOutDecoded="$outDir/$pathAbsOutDecoded/$sanename" funcLog 5 "pathAbsOutDecoded: $pathAbsOutDecoded" # This will be the absolute path to the cut output file (e.g. /final/Good.Wife/Good.Wife..S05E14..Ein.paar.Worte.HQ.avi-cut.mkv) pathAbsOutCut="$pathAbsOutDecoded$cutAppendix" funcLog 5 "pathAbsOutCut: $pathAbsOutCut" fi } # Do the decoding stuff: Call decoder function funcDecode { local sizeEnc; local sizeDec; if [ -f "$pathTmpAbsDecoded" ]; then # If we decoded this file before sizeEnc=`stat -L -c%s "$pathAbsEncoded"` sizeDec=`stat -L -c%s "$pathTmpAbsDecoded"` if [ $(($sizeEnc-$sizeDec)) -eq 522 ]; then # If decoding was successful funcLog 3 "File was already decoded: $pathTmpAbsDecoded" # Simply do nothing else # Else decode it again funcLog 3 "Previous decoding was not successfull (filesize difference: $(($sizeEnc-$sizeDec)), should be 522)" rm "$pathTmpAbsDecoded" fi fi if [ -f "$pathTmpAbsDecoded" ]; then success=1 else # If we don't find the decoded file in $tempDir funcLog 4 "Decoding $filename" funcLog 5 " $cmdDecode $cmdDecodeArgs $pathAbsEncoded" $cmdDecode $cmdDecodeArgs "$pathAbsEncoded" # Deocde the file success=$? if (( success == 0 )); then # if otrdecoder exited successfully if [ -f "$pathTmpAbsDecoded" ]; then funcLog 4 "Successfully decoded" success=1; else funcLog 1 "Decoding failed but decoder exited with success status!" success=0; fi else funcLog 1 "Decoding failed (returned $success)!" success=0 fi fi } # Cut the decoded file function funcCut { funcLog 4 "Cutting $pathTmpAbsDecoded" funcLog 5 " $cmdCut $cmdCutArgs $pathTmpAbsDecoded" $cmdCut $cmdCutArgs "$pathTmpAbsDecoded" success=$? case $success in 0) if [ ! -f "$pathTmpAbsCut" ]; then success=1 funcLog 1 "multicutmkv: Returned success, but output file is missing!" else funcLog 4 "Successfully cut" fi;; 1) funcLog 1 "multicutmkv: General error!";; 2) funcLog 1 "multicutmkv: Missing arguments!";; 3) funcLog 1 "multicutmkv: Temporary folder could not be created!";; 4) funcLog 1 "multicutmkv: Specified file does not exist!";; 10) funcLog 3 "multicutmkv: No cutlist found.";; 11) funcLog 2 "multicutmkv: Downloading cutlist failed!";; 12) funcLog 2 "multicutmkv: Unknown cutlist format!";; 20) funcLog 2 "multicutmkv: ffmsindex failed!";; 21) funcLog 2 "multicutmkv: mkvmerge failed!";; 22) funcLog 2 "multicutmkv: x264 failed!";; 6) funcLog 1 "multicutmkv: Error code 6!";; 7) funcLog 1 "multicutmkv: Error code 7!";; 126) funcLog 1 "multicutmkv: Additional software needed!";; *) funcLog 1 "An unknown error occured while cutting: $success!";; esac if (( success == 0 )); then success=1 else success=0 fi } # Move the decoded/cut file to its destination function funcMove { if [ "$pathMoveFrom" != "$pathMoveTo" ]; then if [ -f "$pathMoveFrom" ]; then local dir="$(dirname $pathMoveTo)" if [ ! -d "$dir" ]; then mkdir -p "$dir" fi mv -f "$pathMoveFrom" "$pathMoveTo" success=1; scanKodi=1; else success=0; fi fi } # Remove all unneeded files function funcRemove { case $status in 3) # Cut -> remove decoded file funcRemoveFile "$pathTmpAbsCut" # temporary cut file (should not exist anymore) funcRemoveFile "$pathTmpAbsDecoded" # temporary decoded file funcRemoveFile "$pathAbsOutDecoded" # decoded file in output dir funcRemoveFile "$pathAbsOutDecodedInsane" # " ;& 2) # Decoded -> remove otrkey if (( alrMoved == 0 )); then funcRemoveFile "$pathTmpAbsDecoded" # temporary decoded file fi if (( remove == 2 )); then # force deleting funcRemoveFile "$pathAbsEncoded"; elif (( remove == 1 )); then # test torrent client ## Add more checks here, not only Deluge if [ -n "$delugeDir" ] && [ -d "$delugeDir/state" ]; then # If deluge config dir is defined if [ -n "`LC_ALL=C fgrep "$filename" "$delugeDir/state" -R --include=*.torrent`" ]; then funcLog 4 "Torrent still exists in Deluge" else funcRemoveFile "$pathAbsEncoded"; fi fi fi ;; esac success=1; } # Remove the specified file if it exists function funcRemoveFile { local file="$1" if [ -n "$file" -a -e "$file" ]; then funcLog 4 "Deleting $file" rm -f "$file"; fi } ################################# # This is our main program flow # ################################# funcGetConfig funcParam "$@" funcPerformChecks funcLock funcProcessFiles funcUpdateKodi funcUnlock