Skip to content

Instantly share code, notes, and snippets.

@paul-chambers
Last active November 8, 2023 06:13
Show Gist options
  • Save paul-chambers/71ef48e40449ec73eef95430b9e4e6c7 to your computer and use it in GitHub Desktop.
Save paul-chambers/71ef48e40449ec73eef95430b9e4e6c7 to your computer and use it in GitHub Desktop.
Helper script for deluge or qBittorrent. It hardlinks completed torrents into a destination folder. It also unrars it, if it includes a rar archive.
#!/bin/bash
# Helper script for deluge or qBittorrent bittorrent clients
# Intended to be run when the torrent download completes
#
# for qBittorrent, enable 'Run external program on torrent completion' under 'Downloads' in the options dialog.
# in the text field, enter:
#
# <path to>/torrent-complete.sh "%K" "%N" "%D"
#
# %K: Torrent ID
# %N: Torrent name
# %D: Save path
#
# This provides the same parameters to this script that deluge provides to 'torrent complete' scripts.
#
# The basic idea is to hardlink the files that the bittorrent client has just finished downloading to a second directory.
# This allows you to configure qBittorrent to automatically pause or delete torrents when they reach a given seed ratio,
# while also keeping a copy around for further processing.
#
# For example, SyncThing could be used to propagate new downloads to a remote machine to be processed further. When remote
# processing has finished, and the file is deleted/moved out of the remote downloads folder, the remote Syncthing will
# propagate a deletion back to the original Synchting (on the machine running this bittorrent client).
#
# This approach works equally well for rclone.
#
# The end result is that the lifetime of files involved both in the torrent client's seeding process and the 'transfer
# to somewhere else' process (e.g. via reclone or Syncthing) are decoupled, and can safely execute in parallel without
# needing to be aware of what the other is doing. And yet the net result is that the files will still be cleaned up
# automagically when both have finished their respective tasks.
#
# Paul Chambers, Copyright (c) 2019-2023.
#
# Made available under the Creative Commons 'BY' license
# https://creativecommons.org/licenses/by/4.0/
#
set -x
torrentID=$1
torrentName=$2
torrentPath=$3
baseDir="/home/video"
srcDir="${baseDir}/downloads"
destDir="${baseDir}/toUpload"
# either empty, or has a leading slash
label="${torrentPath#$srcDir}"
# note that srcPath may be a file, not necessarily a
# directory. In which case, the same is true for destPath.
srcPath="${torrentPath}/${torrentName}"
destPath="${destDir}${label}/${torrentName}"
mkdir -p "~/logs/"
echo "${torrentID} \"${torrentName}\" \"${torrentPath}\" ${label}" >> ~/logs/torrent-complete.log
# Non-rar files are always hardlinked to the destination.
mkdir -p "${destPath}${label}"
cp -vrl -t "${destDir}${label}" "${srcPath}"
# We may be given a file or a directory. If it's a directory, it may contain one or more rar files, in which case
# we unpack each one directly into the destination hierarchy.
if [ -d "${destPath}" ]
then
# multiple rar files may be found in subdirectories, so handle each one, preserving hierarchy
find "${destPath}" -name '*.rar' -print0 | while read -d $'\0' rarFile
do
# unrar does not delete the rar file(s) after it's finished extracting. But it does tell us
# on stdout which files it is parsing as it expands the archive. With a little sed magic,
# we parse out those filenames from stdout and remember them. If unrar completes without
# error, we then use that list to delete the file(s) that made up the rar archive.
rarFileList=$(mktemp)
path="$(dirname "${rarFile}")"
unrar x -idp -o+ "${rarFile}" "${path}" | \
sed -n -e "s/^Extracting from \(.*\.r[a0-9][r0-9]\)$/\1/ w ${rarFileList}" \
&& xargs --no-run-if-empty --arg-file="${rarFileList}" rm \
&& rm "${rarFileList}"
done
fi
# We could unpack other archives here too (e.g. .zip files), but it's preferable to transfer archives
# to a remote machine in their compressed form, and decompress them there.
# remove any files we don't need from {destPath}, to avoid wasting bandwidth transferring them.
# this is a personal preference - adjust to taste
find "${destPath}" -name 'BDMV' -printf "%h\0" | xargs -0 --no-run-if-empty rm -r
torrent-upload "${destpath}"
#
# torrent is ready to transfer to its final destination
#
# $1 = path to the torrent to transfer (a path to either a folder or file)
#
rclone move "$1" destination:
@Theangelofspace15
Copy link

I see, but the label in the script is a variable that you created it is not? label="${torrentPath#$srcDir}"
Or would that get the label assigned on the torrent using the label or label plus plugin?

@Koyakami
Copy link

Koyakami commented Jan 9, 2020

Hi mate, complete beginner - Deluge -> Plugins -> Execute. Select Add, Event=Torrent Completed and what do I put in the command?

Do I need to transfer this .sh file over to my Deluge FTP and then type the file name into that?

OR do I copy and paste everything in the .sh file?

Cheers Paul

@TinTin192
Copy link

Haven't been able to get this running for some reason. Perms are correct etc etc.. But just isn't executing...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment