Page 1 of 1

Guide: Tranmission on Synology, postprocess..

Posted: Fri Oct 26, 2012 5:32 pm
by larza
I do not take any credit for the below scripts

I have some serious issues with making Transmission trigger scripts upon completion. I use Transmission from Synocommunity, 2.7. I cannot locate any log file either which makes it even harder.

However I made a workaround solving most of the parts I want to be done after download. Since I have noted other people having similar issues I wanted to share this solution. What I do lack still is the possibility to remove the torrent from Tranmission download que, which I cannot seem to be able to solve without getting Transmission to trigger a script.

Please note that you need bash installed, and therefore also IPKG. Furthermore you need to install Filebot which is available as a package through Missilehugger, http://missilehugger.com/735/synology-package-filebot/.

I realize that my solution is far from nice looking, but due to lack of knowledge in scripting it´s a lot of copy paste.. I guess one day I will sit down, clean up and make one script handle everything. Right now I´m just happy that I got it to work.

What my setup does
1. Unrar any potential RAR files
2. Sorts and moves files into other folder with subfolder “Movies” and “TV-Shows”.
3. Download subtitles
4. Cleans up initial download folder
5. Removes any empty directories.

Overview of my structure
I have the following file structure:

/volume1/transmission/download (download folder, where new files are stored and as well the scripts)
/volume1/transmission/incomplete (where Transmission stores file until complete, very important to change this in Transmission settings)
/volume1/transmission/sorted (Where my sorted files end up, in subfolders Movies, TV-shows)

To the solution
I have several scripts and I will run them through one be one, but first an overview:
1. script.sh (only to trigger the other scripts in the correct order, one command added)
2. unrarallmod.sh (a slightly modified version of unrarall, https://github.com/arfoll/unrarall)
3. utorrent-postprocess.groovy (http://filebot.sourceforge.net/scripts/ ... ess.groovy)
4. cleaner.groovy (http://filebot.sourceforge.net/scripts/cleaner.groovy)

So all the files are stored in /volume1/transmission/download.

script.sh
(please note that bash on my synology is stored in /opt/bin/bash.

Code: Select all

#!/opt/bin/bash 

#No copyright from my side.. :) /Larza
#Copyright for other scripts used can be find in each scriptfile
##########

/volume1/transmission/download/unrarallmod.sh -d /volume1/transmission/download
filebot -script "/volume1/transmission/download/utorrent-postprocess.groovy" "/volume1/transmission/download/" --output "/volume1/transmission/sorted/" --action move --conflict override -non-strict --def subtitles=y
filebot -script "/volume1/transmission/download/cleaner.groovy" "/volume1/transmission/download/"
sleep 10
filebot -script "/volume1/transmission/download/cleaner.groovy" "/volume1/transmission/download/"
find /volume1/transmission/download -type d -print0 | xargs -0 rmdir -p
The last row is the only one worth mentioning, the rest are just triggering other scripts. Since Synology creates invisible subfolders in folders containing media I needed to turn this function of. Since I´m not using Itunes this is not an issue for me. How to do this, please check out this guide: http://literatitech.blogspot.no/2011/06 ... ology.html.
Might also mention that I chose to have the cleaner groovy launched twice, for some reason it sometimes missed some folders..

unrarallmod.sh

Code: Select all

#!/opt/bin/bash 

#unrarall
# Copyright (C) 2011, 2012 Brendan Le Foll <brendan@fridu.net>
# Copyright (C) 2011, 2012  Dan Liew <dan@su-root.co.uk>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
##########################################################################

# Set some defaults
declare -x DIR="`pwd`"
declare -ix CLEAN=0
declare -rx UNRARALL_VERSION="0.2.9"
declare -ix FORCE_CLEAN=0
declare -ix VERBOSE=0
declare -ix QUIET=0
declare -x UNRAR_METHOD="e"
declare -x UNRARALL_BIN="" #Leave empty to let unrarall to loop through UNRAR_BINARIES, setting this will disable searching through UNRAR_BINARIES
declare -x UNRAR_BINARIES=(unrar 7z) #Array of binaries to try and use, the order here is the order of precedence
declare -Ax UNRAR_BINARY_FLAGS=( \
    [unrar]='-o+ -y' \
    [7z]='-y' \
    ) #Flags for different binaries

function usage()
{
  echo "Usage: unrarall [ --dir DIRECTORY ] [ --clean | --force ] [ --full-path ] [ --verbose | --quiet ] [--7zip]
               unrarall --help
         unrarall --version

  Usage (short options):
           unrarall [ -d DIRECTORY ] [ -c | -f ] [ -v | -q ] [-7]
         unrarall -h
DESCRIPTON
unrarall is a utility to unrar and cleanup (delete) all rar files within a directory DIRECTORY. Sub-directories are automatically recursed and if a rar file exists in a sub-directory then the rar file is extracted into that subdirectory.

Use --clean if you want to cleanup. Otherwise no cleaning is done. It can also be used to delete rar files that have already been used for extraction with --force. Use with caution!

OPTIONS

-7, --7zip       Force using 7zip instead of trying to automatically find a program to extract the rar files.
-c, --clean      Clean after unrar. If the extraction fails then the directory will NOT be cleaned. Use --force to override this.
-d, --dir        Use directory DIRECTORY. If this argument is not supplied the current working directory is used.
-f, --force      Force clean even if unrar fails. Implies --clean. Use this if you've already used unrarall on the directory before
                 and now you want to remove the rar files. This should be pretty fast as unrar is set to not overwrite already extracted files.
--full-path      Extract full path inside rar files instead of just extracting the files in the rar file which is the default behaviour.
-h, --help       Displays this help message and exits.
-v, --verbose    Show extraction progress as unrarall executes. This is not done by default
-q, --quiet      Be completely quiet. No output will be written to the screen
--version        Give version information version.

VERSION: $UNRARALL_VERSION

"
}

function clean-up
{
	#perform any necessary clean up

	message error "unrarall is exiting"
	exit 1;
}

#Catch exit signals
trap clean-up SIGQUIT SIGINT SIGTERM

#function to display pretty messages
function message()
{
  #Assume $1 is message type & $2 is message
  #See http://www.frexx.de/xterm-256-notes/ for information on xterm colour codes

  if [ "$QUIET" -ne 1 ]; then
    case "$1" in
      error)
        #use escape sequence to show red text
        echo -e "\033[31m${2}\033[0m" 1>&2
      ;;
      ok)
        #use escape sequence to show green text
        echo -e "\033[32m${2}\033[0m"
      ;;
      nnl)
        #use echo -n to avoid new line
        echo -n "$2"
        ;;
      info)
        echo "$2"
        ;;
      *)
        echo "$2"
    esac
  fi
}

# Parse command line arguments
while [ -n "$1" ]; do
  case "$1" in
    -h | --help )
      usage
      exit 0
      ;;
    --version )
      echo "$UNRARALL_VERSION"
      exit 0
      ;;
    -d | --dir )
      shift
      DIR="$1"
      ;;
    -c | --clean )
      CLEAN=1
      ;;
    -f | --force )
      FORCE_CLEAN=1
      CLEAN=1
      ;;
    -v | --verbose )
      VERBOSE=1
      ;;
    -q | --quiet )
      VERBOSE=0
      QUIET=1
      ;;
    --full-path )
      UNRAR_METHOD="x"
      ;;
    -7 | --7zip)
      UNRARALL_BIN=7z
      ;;
    *)
      # user issued unrecognised option
      message error "Unrecognised option: $1"
      usage
      exit 1
      ;;
  esac
  shift
done

# Current Dir check
if [ "${DIR}" == "." ]; then
  DIR="`pwd`"
fi


#If No user specified binary, cycle through array and try and find a binary that can be used
if [ -z "${UNRARALL_BIN}" ]; then
  for (( index=0; index < ${#UNRAR_BINARIES[@]}; index++)); do
    #Check for binary
    [ $VERBOSE -eq 1 ] && message nnl "Looking for ${UNRAR_BINARIES[$index]}..."
    if type -P ${UNRAR_BINARIES[$index]} 2>&1 > /dev/null ; then
      #Binary found
      UNRARALL_BIN="${UNRAR_BINARIES[$index]}"
      [ $VERBOSE -eq 1 ] && message ok "found"
      break;
    else
    	[ $VERBOSE -eq 1 ] && message error "not found"
    fi

    #check if end of list
    if [ $index -eq $(( ${#UNRAR_BINARIES[@]} -1)) ]; then
	message error "Failed to find binary to perform rar extraction. The following binaries were looked for ${UNRAR_BINARIES[*]}"
	exit 1;
    fi
  done
else
  #check the manually specified binary exists
  if ! type -P ${UNRARALL_BIN} 2>&1 > /dev/null ; then
  	message error "The manually specified binary ${UNRARALL_BIN} cannot be found"
	exit 1;
  fi
fi

#Inform the user about the binary chosen
[ $VERBOSE -eq 1 ] && message info "Using \"${UNRARALL_BIN}\" to extract rar files" ;

# Check $DIR exists and is a directory
if [ -d "$DIR" ]; then
  message normal "Working over directory \"${DIR}\""
else
  message error "Cannot find directory \"${DIR}\""
  exit 1;
fi

# Check if there is an "unrar" running already, if so, exit
if ps -ef | grep -v grep | grep -v unrarall | grep ${UNRARALL_BIN} ; then
  message error "unrarall or ${UNRARALL_BIN} is allready running. Please only run this script once"
  exit 0
fi

CURRENT_DIR=`pwd`

#find all files
COUNT=0

#modify IFS for new lines so filenames with spaces do not get split
IFS_TEMP=$IFS
IFS=$(echo -en "\n\b")

#assuming only the .rar files are of interest
for file in $(find "$DIR" -name '*.rar'); do
  let COUNT=COUNT+1
  message nnl "Extracting (${UNRAR_METHOD}) \"$file\"..."
  filename=`basename "$file"`
  dirname=`dirname "$file"`
  filexname=`basename "$file"`
  #Strip .rar extension off filename
  sfilename="${filename%.rar}"

  # move to directory
  cd "$dirname";
#LARZAs modifications
	mkdir -p original;
	mv * "$dirname/original" &> /dev/null;
	mkdir -p "$dirname/repacked";
	sleep 10
	# Figure out which the first rar archive is, part01 or r00 versions doesn't matter that much.
	#relname=$(ls $dirname/original/*.rar|head -n1);
     unrar e -inul $dirname/original/$filexname $dirname/repacked;
	 #unrar e -inul /original/$filexname $dirname/repacked;
	
	# Delete everything in original folder
	rm -rf "$dirname/original";
	# Move back unpacked file
	cd "$dirname/repacked";
	mv * "$dirname" &> /dev/null;
	# Remove create temp folder
	cd "$dirname";
	rm -rf "$dirname/repacked";
	
#END OF LARZAs modifications, below is commented out for a reason.. :)	

  # unrar file with unrar e
  #if [ "$VERBOSE" -eq 1 ]; then
   # ${UNRARALL_BIN} ${UNRAR_METHOD} ${UNRAR_BINARY_FLAGS[${UNRARALL_BIN}]} "$filename"
  #else
   # ${UNRARALL_BIN} ${UNRAR_METHOD} ${UNRAR_BINARY_FLAGS[${UNRARALL_BIN}]} "$filename" >/dev/null
  #fi
  #SUCCESS=$?

  # if fail remove from count
  #if [ "$SUCCESS" -eq 0 ]; then
  #  message ok "ok";
  #else
  #  let COUNT=COUNT-1
  #  message error "failed"
  #fi
  

  
  # cleanup all rar files in the current directory
  if [ "$CLEAN" -eq 1 ] ; then
    if [ "$SUCCESS" -eq "0" ] || [ "$FORCE_CLEAN" -eq 1 ]; then
      message info "Cleaning $file"
      #-maxdepth 1 is very important, we only want to delete rar files in the current directory!
      find . -maxdepth 1 -type f -regex '\./'"$sfilename"'.r\([0-9]+\|ar\)$' -exec rm $( [ $VERBOSE -eq 1 ] && echo '-v') '{}' \;

    else
      message error "Couldn't do requested clean because ${UNRARALL_BIN} extracted unsuccessfully. Use --force to override this behaviour"
    fi
  fi
  cd "$CURRENT_DIR"
done
IFS=$IFS_TEMP

if [ "$QUIET" -ne 1 ]; then
  if [ "$COUNT" -ne 0 ]; then
    EXIT_PHRASE="found and extracted"
    if [ "$CLEAN" -eq 1 ]; then
      EXIT_PHRASE="found, extracted and removed"
    fi
    message info "$COUNT rar files $EXIT_PHRASE"
  else
    message error "no rar files extracted"
  fi
fi
As you might have noted there is a part added, row 225 to 244. This was the way I choose to make sure that original files are removed.. Might not be the nicest scripting, but works.. ;)

utorrent-postprocess.groovy

Code: Select all

// filebot -script "fn:utorrent-postprocess" --output "X:/media" --action copy --conflict override --def subtitles=true artwork=true xbmc=localhost plex=10.0.0.1 gmail=username:password "ut_dir=%D" "ut_file=%F" "ut_kind=%K" "ut_title=%N" "ut_label=%L" "ut_state=%S"
def input = []
def failOnError = _args.conflict == 'fail'

// print input parameters
_args.bindings?.each{ _log.finest("Parameter: $it.key = $it.value") }
args.each{ _log.finest("Argument: $it") }

// enable/disable features as specified via --def parameters
def subtitles = tryQuietly{ subtitles.toBoolean() }
def artwork   = tryQuietly{ artwork.toBoolean() }

// array of xbmc/plex hosts
def xbmc = tryQuietly{ xbmc.split(/[ ,|]+/) }
def plex = tryQuietly{ plex.split(/[ ,|]+/) }

// email notifications
def gmail = tryQuietly{ gmail.split(':', 2) }


// series/anime/movie format expressions
def format = [
	tvs:   '''TV Shows/{n}/{episode.special ? "Special" : "Season "+s}/{n} - {episode.special ? "S00E"+special.pad(2) : s00e00} - {t}''',
	anime: '''Anime/{n}/{n} - {sxe} - {t}''',
	mov:   '''Movies/{n} ({y})/{n} ({y}){" CD$pi"}{".$lang"}'''
]


// force movie/series/anime logic
def forceMovie(f) {
	tryQuietly{ ut_label } =~ /^(?i:Movie|Couch.Potato)/
}

def forceSeries(f) {
	parseEpisodeNumber(f) || parseDate(f) || tryQuietly{ ut_label } =~ /^(?i:TV)/
}

def forceAnime(f) {
	tryQuietly{ ut_label } =~ /^(?i:Anime)/
}

def forceIgnore(f) {
	tryQuietly{ ut_label } =~ /^(?i:Music|Audio|Ebook|other|tracker.example.com|tracker.example.com.fm)/
}


// collect input fileset as specified by the given --def parameters
if (args.empty) {
	// assume we're called with utorrent parameters
	if (ut_kind == 'single') {
		input += new File(ut_dir, ut_file) // single-file torrent
	} else {
		input += new File(ut_dir).getFiles() // multi-file torrent
	}
} else {
	// assume we're called normally with arguments
	input += args.getFiles()
}


// extract archives (zip, rar, etc) that contain at least one video file
input += extract(file: input.findAll{ it.isArchive() }, output: null, conflict: 'override', filter: { it.isVideo() }, forceExtractAll: true)

// sanitize input
input = input.findAll{ it?.exists() }.collect{ it.canonicalFile }.unique()

// process only media files
input = input.findAll{ it.isVideo() || it.isSubtitle() }

// ignore clutter files
input = input.findAll{ !(it.path =~ /\b(?i:sample|trailer|extras|deleted.scenes|music.video|scrapbook)\b/) }

// print input fileset
input.each{ f -> _log.finest("Input: $f") }

// artwork/nfo utility
include("lib/htpc")

// group episodes/movies and rename according to XBMC standards
def groups = input.groupBy{ f ->
	// skip auto-detection if possible
	if (forceIgnore(f))
		return []
	if (forceMovie(f))
		return [mov:   detectMovie(f, false)]
	if (forceSeries(f))
		return [tvs:   detectSeriesName(f) ?: detectSeriesName(f.dir.listFiles{ it.isVideo() })]
	if (forceAnime(f))
		return [anime: detectSeriesName(f) ?: detectSeriesName(f.dir.listFiles{ it.isVideo() })]
	
	
	def tvs = detectSeriesName(f)
	def mov = detectMovie(f, false)
	println "$f.name [series: $tvs, movie: $mov]"
	
	// DECIDE EPISODE VS MOVIE (IF NOT CLEAR)
	if (tvs && mov) {
		def norm = { s -> s.lower().space(' ') }
		def dn = norm(guessMovieFolder(f)?.name ?: '')
		def fn = norm(f.nameWithoutExtension)
		def sn = norm(tvs)
		def mn = norm(mov.name)
		
		// S00E00 | 2012.07.21 | One Piece 217 | Firefly - Serenity | [Taken 1, Taken 2, Taken 3, Taken 4, ..., Taken 10]
		if (parseEpisodeNumber(fn, true) || parseDate(fn) || (fn =~ sn && parseEpisodeNumber(fn.after(sn), false)) || fn.after(sn) =~ / - .+/ || f.dir.listFiles{ it.isVideo() && norm(it.name) =~ sn && it.name =~ /\b\d{1,3}\b/}.size() >= 10) {
			println "Exclude Movie: $mov"
			mov = null
		} else if ((detectMovie(f, true) && [dn, fn].find{ it =~ /(19|20)\d{2}/ }) || [dn, fn].find{ it =~ mn && !(it.after(mn) =~ /\b\d{1,3}\b/) }) {
			println "Exclude Series: $tvs"
			tvs = null
		}
	}
	
	// CHECK CONFLICT
	if (((mov && tvs) || (!mov && !tvs)) && failOnError) {
		throw new Exception("Media detection failed")
	}
	
	return [tvs: tvs, mov: mov, anime: null]
}

// log movie/series/anime detection results
groups.each{ group, files -> _log.finest("Group: $group => ${files*.name}") }

// process each batch
groups.each{ group, files ->
	// fetch subtitles
	if (subtitles) {
		files += getMissingSubtitles(file:files, output:"srt", encoding:"utf-8")
	}
	
	// EPISODE MODE
	if ((group.tvs || group.anime) && !group.mov) {
		// choose series / anime config
		def config = group.tvs ? [name:group.tvs, format:format.tvs, db:'TheTVDB']
					           : [name:group.anime, format:format.anime, db:'AniDB']
		def dest = rename(file: files, format: config.format, db: config.db)
		if (dest && artwork) {
			dest.mapByFolder().each{ dir, fs ->
				println "Fetching artwork for $dir from TheTVDB"
				def sxe = fs.findResult{ eps -> parseEpisodeNumber(eps) }
				def options = TheTVDB.search(config.name)
				if (options.isEmpty()) {
					println "TV Series not found: $config.name"
					return
				}
				options = options.sortBySimilarity(config.name, { s -> s.name })
				fetchSeriesArtworkAndNfo(dir.dir, dir, options[0], sxe && sxe.season > 0 ? sxe.season : 1)
			}
		}
		if (dest == null && failOnError) {
			throw new Exception("Failed to rename series: $config.name")
		}
	}
	
	// MOVIE MODE
	if (group.mov && !group.tvs && !group.anime) {
		def dest = rename(file:files, format:format.mov, db:'TheMovieDB')
		if (dest && artwork) {
			dest.mapByFolder().each{ dir, fs ->
				println "Fetching artwork for $dir from TheMovieDB"
				fetchMovieArtworkAndNfo(dir, group.mov, fs.findAll{ it.isVideo() }.sort{ it.length() }.reverse().findResult{ it })
			}
		}
		if (dest == null && failOnError) {
			throw new Exception("Failed to rename movie: $group.mov")
		}
	}
}



// make xbmc or plex scan for new content
xbmc?.each{
	println "Notify XBMC: $it"
	invokeScanVideoLibrary(it)
}

plex?.each{
	println "Notify Plex: $it"
	refreshPlexLibrary(it)
}

// send status email
if (gmail && !getRenameLog().isEmpty()) {
	// ant/mail utility
	include('lib/ant')
	
	// send html mail
	def renameLog = getRenameLog()
	
	sendGmail(
		subject: '[FileBot] ' + ut_title,
		message: XML {
			html {
				body {
					p("FileBot finished processing ${ut_title} (${renameLog.size()} files).");
					hr(); table {
						th("Parameter"); th("Value")
						_args.bindings.findAll{ param -> param.key =~ /^ut_/ }.each{ param ->
							tr { [param.key, param.value].each{ td(it)} }
						}
					}
					hr(); table {
						th("Original Name"); th("New Name"); th("New Location")
						renameLog.each{ from, to ->
							tr { [from.name, to.name, to.parent].each{ cell -> td{ nobr{ code(cell) } } } }
						}
					}
					hr(); small("// Generated by ${net.sourceforge.filebot.Settings.applicationIdentifier} on ${new Date().dateString} at ${new Date().timeString}")
				}
			}
		},
		messagemimetype: "text/html",
		to: tryQuietly{ mailto } ?: gmail[0] + '@gmail.com', // mail to self by default
		user: gmail[0], password: gmail[1]
	)
}

cleaner.groovy
(Please note that I have made some changes in blacklist)

Code: Select all

// filebot -script fn:cleaner [--action test] /path/to/media/

/*
 * Delete orphaned "clutter" files like nfo, jpg, etc and sample files
 */
def isClutter(f) {
	def blacklist = f.path =~ /\b(?i:sample|trailer|extras|deleted.scenes|music.video|scrapbook|@eaDir)\b/ && f.length() < 100 * 1024 * 1024  
	def extension = f.hasExtension("jpg", "jpeg", "png", "gif", "nfo", "xml", "htm", "html", "log", "srt", "sub", "idx", "md5", "sfv", "txt", "rtf", "url", "db", "dna", "r00",	"r01", "r02",	"r03",	"r04",	"r05",	"r06",	"r07",	"r08",	"r09",	"r10",	"r11",	"r12",	"r13",	"r14",	"r15",	"r16",	"r17",	"r18",	"r19",	"r20",	"r21",	"r22",	"r23",	"r24",	"r25",	"r26",	"r27",	"r28",	"r29",	"r30",	"r31",	"r32",	"r33",	"r34",	"r35",	"r36",	"r37",	"r38",	"r39",	"r40",	"r41",	"r42",	"r43",	"r44",	"r45",	"r46",	"r47",	"r48",	"r49",	"r50",	"r51",	"r52",	"r53",	"r54",	"r55",	"r56",	"r57",	"r58",	"r59",	"r60",	"r61",	"r62",	"r63",	"r64",	"r65",	"r66",	"r67",	"r68",	"r69",	"r70",	"r71",	"r72",	"r73",	"r74",	"r75",	"r76",	"r77",	"r78",	"r79",	"r80",	"r81",	"r82",	"r83",	"r84",	"r85",	"r86",	"r87",	"r88",	"r89",	"r90",	"r91",	"r92",	"r93",	"r94",	"r95",	"r96",	"r97",	"r98",	"r99", "rar")
	return blacklist || extension // path contains blacklisted terms or extension is blacklisted
}


def clean(f) {
	println "Delete $f"
	
	// do a dry run via --action test
	if (_args.action == 'test') { 
		return false
	}
	
	return f.isDirectory() ? f.deleteDir() : f.delete()
}


// delete clutter files in orphaned media folders
args.getFiles{ isClutter(it) && !it.dir.hasFile{ (it.isVideo() || it.isAudio()) && !isClutter(it) }}.each { clean(it) }

// delete empty folders but exclude given args
args.getFolders{ it.listFiles().length == 0 && !args.contains(it) }.each { clean(it) }
So with all these scripts saved under /volume1/transmission/download you need to add a launch of script.sh in Cron.
On Synology do as follows (in terminal logged in as root):

Code: Select all

/usr/syno/etc/rc.d/S04crond.sh stop

(to stop cron from running)

Code: Select all

vi /etc/crontab 
(to launch editor)

Add this row (use I to enter edit mode)

Code: Select all

0       *       *       *       *       root    /volume1/transmission/download/script.sh 
Please not that it is TABs between the different columns. I have chosen to run the script once per hour.

Save the file and exit (ESC, :wq)

Code: Select all

/usr/syno/etc/rc.d/S04crond.sh stop && /usr/syno/etc/rc.d/S04crond.sh start 
(to start crond again)

I think I covered everything… 

Of course any assistance with making this nicer looking is more than welcome as well if anyone has a solution with Tranmission triggering scripts in Synology.