mirror of
https://github.com/SickGear/SickGear.git
synced 2024-11-27 15:13:38 +00:00
385 lines
12 KiB
Batchfile
385 lines
12 KiB
Batchfile
|
@ECHO OFF
|
||
|
GOTO :main
|
||
|
*******************************************************************************
|
||
|
|
||
|
onTxComplete.bat v1.1 for SickGear
|
||
|
|
||
|
Script to copy select files to a location for SickGear to post process.
|
||
|
|
||
|
This is used with the 'Move' post process episode method
|
||
|
so that seeding files are not post processed over and over.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Supported clients
|
||
|
-----------------
|
||
|
* Deluge clients 1.3.15 and newer clients
|
||
|
* qBittorrent 4.13 and newer clients
|
||
|
* Transmission 2.84 and newer clients
|
||
|
* uTorrent 2.2.1
|
||
|
|
||
|
Supported OS
|
||
|
------------
|
||
|
* Windows 10, 8, 7, Vista
|
||
|
|
||
|
|
||
|
How this works
|
||
|
--------------
|
||
|
Completed downloads are copied from a seeding location to an isolated location.
|
||
|
SG will 'Move' processed content from isolation to the final show location.
|
||
|
|
||
|
The four parameters;
|
||
|
param1 = Isolation path where to copy completed downloads for SG to process.
|
||
|
This value *must* ..
|
||
|
1) be different to the path where the client saves completed downloads
|
||
|
2) be configured in SG (see later, step a)
|
||
|
This path should be created on first run, if not, create it yourself.
|
||
|
|
||
|
param2 = This filter value is compared with either a client set label, or the
|
||
|
tail of the path where the client downloaded seeding file is located.
|
||
|
Matching downloads are copied into isolation.
|
||
|
|
||
|
param3 = Client set downloaded item category or label (e.g. "%L")
|
||
|
|
||
|
param4 = Client set downloaded item content path (e.g. "%F", "%D\%F" etc)
|
||
|
|
||
|
Token values for params 3 and 4 are found documented in the download client or
|
||
|
at the client website. Other clients may be able to replace param3 and param4
|
||
|
to fit (see examples).
|
||
|
|
||
|
|
||
|
To set up SickGear
|
||
|
------------------
|
||
|
a) Set /config/postProcessing/Post Processing -> "Completed TV downloads"
|
||
|
.. to match param1
|
||
|
|
||
|
b) Set /config/postProcessing/Post Processing -> "Process episode method"
|
||
|
.. to 'Move'
|
||
|
|
||
|
c) Enable /config/postProcessing/Post Processing -> "Scan and post process"
|
||
|
|
||
|
d) Enable /config/postProcessing/Post Processing -> "Postpone post processing"
|
||
|
|
||
|
e) Set /config/search/Torrent Results -> "Set torrent label/category"
|
||
|
If using "Black hole" method or if there is no label field, then you must use
|
||
|
client auto labeller or a torrent completed save path that ends with param2,
|
||
|
for Transmission, see note(2) in that section below.
|
||
|
|
||
|
|
||
|
To set up the download client
|
||
|
-----------------------------
|
||
|
|
||
|
For Deluge
|
||
|
----------
|
||
|
Deluge clients call scripts with fixed params that prevent passing params,
|
||
|
rename onTxComplete.sample.cfg as onTxComplete.cfg and edit parameters there.
|
||
|
|
||
|
A Deluge label is used to isolate SG downloads from everything else.
|
||
|
|
||
|
1) Enable the "Label" plugin
|
||
|
|
||
|
2) Enable the "Execute" plugin
|
||
|
|
||
|
3) In the "Execute" plugin settings /Add Command/Event/Torrent Complete
|
||
|
set command to ... [script dir]\onTxComplete.bat
|
||
|
|
||
|
4) Add the label set in step (e) to Deluge, right click the label and select
|
||
|
"Label Options"/Location/Move completed to/Other/ .. choose a folder created
|
||
|
where its name is identical to this label e.g. [path]\[label], (F:\Files\SG)
|
||
|
|
||
|
Reference: http://dev.deluge-torrent.org/wiki/Plugins/Execute
|
||
|
|
||
|
|
||
|
For qBittorrent
|
||
|
---------------
|
||
|
The above four parameters are used to configure and run the script.
|
||
|
|
||
|
Use one cmd from below replacing "[script dir]" with the path to this script
|
||
|
|
||
|
Set Options/Downloads/Run an external program on torrent completion
|
||
|
|
||
|
.. to run in windowless mode (the normal run mode used)
|
||
|
cmd /c start "" /B [script dir]\onTxComplete.bat "F:\sg_pp" "SG" "%L" "%F"
|
||
|
|
||
|
OR ..
|
||
|
.. to run in console window mode (test mode to see console output)
|
||
|
cmd /c start "" /min [script dir]\onTxComplete.bat "F:\sg_pp" "SG" "%L" "%F"
|
||
|
|
||
|
|
||
|
For Transmission
|
||
|
----------------
|
||
|
Transmission clients call scripts with fixed params that prevent passing params,
|
||
|
rename onTxComplete.sample.cfg as onTxComplete.cfg and edit parameters there.
|
||
|
|
||
|
Transmission does not contain labels, instead, the set path(2) is compared
|
||
|
to the config file param2 value to isolate SG downloads from everything else.
|
||
|
|
||
|
1) Edit/Preferences/Downloading/Call script when torrent is completed
|
||
|
... Navigate to this script location and select it
|
||
|
|
||
|
2) Follow "To set up SickGear" instruction but at step (e),
|
||
|
set "Downloaded files location" to a created folder with name ending in the
|
||
|
config file value of param2 e.g. [path]\[param2]
|
||
|
|
||
|
Reference: https://web.archive.org/web/20171009055508/https://trac.transmissionbt.com/wiki/Scripts#OnTorrentCompletion
|
||
|
|
||
|
|
||
|
For uTorrent
|
||
|
------------
|
||
|
The above four parameters are used to configure and run the script.
|
||
|
|
||
|
Use one cmd below replacing "[script dir]" with the path to this script
|
||
|
|
||
|
1) Set Preferences/Advanced/Run program/Run this program when a torrent finishes
|
||
|
cmd /c start "" /B [script dir]\onTxComplete.bat "F:\sg_pp" "SG" "%L" "%D\%F"
|
||
|
|
||
|
It is advised to not use the uTorrent "Move completed downloads" feature because
|
||
|
it runs scripts before move actions complete, bad. Consider switching clients.
|
||
|
|
||
|
Reference: https://stackoverflow.com/a/29071224
|
||
|
|
||
|
:main
|
||
|
rem ***************************************************************************
|
||
|
rem Set 1 to enable test mode output (default: blank)
|
||
|
SET testmode=
|
||
|
SET keeptmp=
|
||
|
rem ***************************************************************************
|
||
|
chcp 65001 >NUL 2>NUL
|
||
|
SETLOCAL
|
||
|
SETLOCAL ENABLEEXTENSIONS
|
||
|
SETLOCAL ENABLEDELAYEDEXPANSION
|
||
|
|
||
|
rem Get install dir stripped of trailing slash
|
||
|
SET "install_dir=%~dp0"
|
||
|
|
||
|
IF "" NEQ "%~4" (
|
||
|
|
||
|
rem Use the four input parameters
|
||
|
rem This also strips quotes used to safely pass values containing spaces
|
||
|
SET "sg_path=%~1"
|
||
|
SET "sg_label=%~2"
|
||
|
SET "client_label=%~3"
|
||
|
SET "content_path=%~4"
|
||
|
IF "1" NEQ "!testmode!" IF "" NEQ "%~5" SET "testmode=1"
|
||
|
SET "check_label_path_tail="
|
||
|
|
||
|
) ELSE (
|
||
|
|
||
|
rem Process config file
|
||
|
SET "cfgfile=!install_dir!onTxComplete.cfg"
|
||
|
FOR /F "eol=; tokens=1,2 delims==" %%a IN (!cfgfile!) DO (
|
||
|
SET "%%a=%%b"
|
||
|
CALL:Log "Config ... %%a = %%b"
|
||
|
)
|
||
|
|
||
|
SET "nullvar="
|
||
|
IF NOT DEFINED param1 SET "nullvar=1"
|
||
|
IF NOT DEFINED param2 SET "nullvar=1"
|
||
|
IF DEFINED nullvar (
|
||
|
CALL:Log "Error: Issue while reading file !cfgfile!" "force"
|
||
|
GOTO:exit
|
||
|
)
|
||
|
SET "sg_path=!param1!"
|
||
|
SET "sg_label=!param2!"
|
||
|
|
||
|
rem Attempt to read Transmission environment variables
|
||
|
SET "client_name=%TR_TORRENT_NAME%"
|
||
|
SET "client_path=%TR_TORRENT_DIR%"
|
||
|
|
||
|
SET "nullvar="
|
||
|
IF "" == "!client_name!" SET "nullvar=1"
|
||
|
IF "" == "!client_path!" SET "nullvar=1"
|
||
|
|
||
|
IF DEFINED nullvar (
|
||
|
|
||
|
rem With no Transmission vars, attempt to read input parameters from Deluge
|
||
|
rem Deluge sends id, name, and path
|
||
|
IF "" == "%~3" (
|
||
|
|
||
|
CALL:Log "Error: not enough input params, read comments in %0 for usage" "force"
|
||
|
GOTO :exit
|
||
|
|
||
|
)
|
||
|
|
||
|
rem Deluge input parameters (i.e. "TorrentID" "Torrent Name" "Torrent Path")
|
||
|
rem This also strips quotes used to safely pass values containing spaces
|
||
|
SET "client_name=%~2"
|
||
|
SET "client_path=%~3"
|
||
|
|
||
|
)
|
||
|
|
||
|
SET "content_path=!client_path!\!client_name!"
|
||
|
SET "check_label_path_tail=1"
|
||
|
)
|
||
|
|
||
|
|
||
|
rem Replace any double slashes in path with single slash
|
||
|
SET "sg_path=!sg_path:\\=\!"
|
||
|
SET "content_path=!content_path:\\=\!"
|
||
|
|
||
|
rem Remove long path switch for most compatibility, newer OSes may omit this
|
||
|
IF "\?\" == "!sg_path:~0,3!" SET "sg_path=!sg_path:~3!"
|
||
|
IF "\?\" == "!content_path:~0,3!" SET "content_path=!content_path:~3!"
|
||
|
|
||
|
rem Remove any trailing slashes from paths
|
||
|
IF "\" == "!sg_path:~-1!" SET "sg_path=!sg_path:~0,-1!"
|
||
|
IF "\" == "!content_path:~-1!" SET "content_path=!content_path:~0,-1!"
|
||
|
IF "\" == "!client_path:~-1!" SET "client_path=!client_path:~0,-1!"
|
||
|
|
||
|
|
||
|
IF DEFINED check_label_path_tail (
|
||
|
|
||
|
rem Enable the copy action if path ends with user defined label
|
||
|
|
||
|
SET "client_label=!sg_label!"
|
||
|
|
||
|
:loop -- label strlen
|
||
|
IF NOT "" == "!sg_label:~%len%!" SET /A len+=1 & GOTO :loop
|
||
|
SET /A len+=1
|
||
|
|
||
|
IF "\!sg_label!" NEQ "!client_path:~-%len%!" SET "client_label=skip copy"
|
||
|
|
||
|
)
|
||
|
|
||
|
|
||
|
rem Create ".!sync" filename
|
||
|
SET "syncext=^!sync"
|
||
|
SET "basefile=!sg_path!\copying"
|
||
|
SET "syncfile=!basefile!.!syncext!" & SET "files=!basefile!.files.txt" & SET "tmp=!basefile!.tmp"
|
||
|
SET num=2
|
||
|
:loopnum
|
||
|
IF EXIST "!syncfile!" (
|
||
|
SET "syncfile=!basefile!-!num!.!syncext!" & SET "files=!basefile!-!num!.files.txt" & SET "tmp=!basefile!-!num!.tmp"
|
||
|
SET /A num+=1 & GOTO :loopnum
|
||
|
)
|
||
|
|
||
|
IF "1" == "!testmode!" CALL:Log "Running in ***test mode*** - files will not be copied"
|
||
|
CALL:Log "**** cmd = ""%~f0"""
|
||
|
CALL:Log " param1 = ""!sg_path!"""
|
||
|
CALL:Log " param2 = ""!sg_label!"""
|
||
|
CALL:Log " param3 = ""!client_label!"""
|
||
|
CALL:Log " param4 = ""!content_path!"""
|
||
|
CALL:Log "syncfile = ""!syncfile!"""
|
||
|
|
||
|
|
||
|
CALL:StartsWith "!client_label!" "!sg_label!" && (
|
||
|
|
||
|
IF NOT EXIST "!sg_path!" MKDIR "!sg_path!"
|
||
|
|
||
|
IF EXIST "!sg_path!" (
|
||
|
|
||
|
rem Determine file/folder as these need to be handled differently
|
||
|
FOR %%f IN ("!content_path!") DO SET attr=%%~af & SET attr=!attr:~0,1!ir
|
||
|
IF /I "dir" == "!attr!" (
|
||
|
|
||
|
rem Create a file to prevent SG premature post processing (ref: step (d)) ..
|
||
|
ECHO Copying folder "!content_path!" to "!sg_path!">"!syncfile!"
|
||
|
|
||
|
PUSHD "!content_path!"
|
||
|
|
||
|
rem Copy from; `parent/` to `{pp}/parent/` and `parent/.../child/` to `{pp}/parent/child/`
|
||
|
FOR %%f IN ("!content_path!.") DO SET "parent=\%%~nxf"
|
||
|
|
||
|
rem Sort by largest to smallest filesize for copy
|
||
|
SET "delim= "
|
||
|
FORFILES /P "!content_path!" /S /C "CMD /C IF FALSE == @isdir ECHO @fsize!delim!@relpath!delim!@file" > "!files!"
|
||
|
(
|
||
|
FOR /F "tokens=1,2* delims= " %%a IN ('TYPE "!files!"') DO (
|
||
|
SET "size=...............%%a"
|
||
|
SET "relpath=%%b"
|
||
|
ECHO !size:~-15!!delim!!relpath:%%~c=!!delim!%%c
|
||
|
)
|
||
|
)>"!tmp!"
|
||
|
(
|
||
|
FOR /F "tokens=1* delims=. " %%a IN ('SORT /R "!tmp!"') DO ECHO %%b
|
||
|
)>"!files!"
|
||
|
IF "1" NEQ "!keeptmp!" IF EXIST "!tmp!" DEL "!tmp!"
|
||
|
|
||
|
FOR /F "tokens=1* delims= " %%a IN ('TYPE "!files!"') DO (
|
||
|
rem Copy
|
||
|
SET "child="
|
||
|
SET "relpath=%%~a"
|
||
|
IF ".\" NEQ "!relpath!" FOR %%f IN ("!relpath:~0,-1!.") DO SET "child=\%%~nxf"
|
||
|
SET "filename=%%~b"
|
||
|
SET "dstdir=!sg_path!!parent!!child!"
|
||
|
SET "dstfile=!dstdir!\!filename!"
|
||
|
SET "srcfile=!relpath!!filename!"
|
||
|
|
||
|
IF "1" == "!testmode!" (
|
||
|
|
||
|
IF NOT EXIST "!dstdir!" CALL:Log "MKDIR ""!dstdir!"""
|
||
|
IF NOT EXIST "!dstfile!" ( CALL:Log "XCOPY ""!srcfile!"" ""!dstfile!*"" /H /Y /J >NUL 2>NUL"
|
||
|
) ELSE ( CALL:Log "Skipping, file exists ""!dstfile!""" )
|
||
|
|
||
|
) ELSE (
|
||
|
|
||
|
IF NOT EXIST "!dstdir!" MKDIR "!dstdir!"
|
||
|
IF NOT EXIST "!dstfile!" XCOPY "!srcfile!" "!dstfile!*" /H /Y /J >NUL 2>NUL
|
||
|
|
||
|
)
|
||
|
|
||
|
)
|
||
|
|
||
|
IF "1" NEQ "!keeptmp!" IF EXIST "!files!" DEL "!files!"
|
||
|
IF "1" NEQ "!testmode!" IF EXIST "!syncfile!" DEL "!syncfile!"
|
||
|
POPD
|
||
|
|
||
|
) ELSE (
|
||
|
|
||
|
rem Create a file to prevent SG premature post processing (ref: step (d)) ..
|
||
|
ECHO Copying file "!content_path!" to "!sg_path!">"!syncfile!"
|
||
|
|
||
|
IF "1" == "!testmode!" (
|
||
|
|
||
|
CALL:Log "COPY ""!content_path!"" ""!sg_path!\"" /Y"
|
||
|
|
||
|
) ELSE (
|
||
|
|
||
|
COPY "!content_path!" "!sg_path!\" /Y >NUL 2>NUL
|
||
|
IF EXIST "!syncfile!" DEL "!syncfile!"
|
||
|
|
||
|
)
|
||
|
|
||
|
)
|
||
|
|
||
|
)
|
||
|
|
||
|
)
|
||
|
GOTO :exit
|
||
|
|
||
|
rem ****************
|
||
|
rem Helper functions
|
||
|
rem ****************
|
||
|
:StartsWith text string -- Test if text starts with string
|
||
|
SETLOCAL
|
||
|
SET "txt=%~1"
|
||
|
SET "str=%~2"
|
||
|
IF DEFINED str CALL SET "s=%str%%%txt:*%str%=%%"
|
||
|
IF /I "%txt%" NEQ "%s%" SET=2>NUL
|
||
|
EXIT /B
|
||
|
|
||
|
:Log text -- Append text to logfile, and output text to stdio if testmode is "1"
|
||
|
SETLOCAL
|
||
|
SET "logfile=!install_dir!onTxComplete.log"
|
||
|
SET "txt=%~1"
|
||
|
SET "txt=!txt:""="!"
|
||
|
IF "1" == "!testmode!" (
|
||
|
ECHO !txt!
|
||
|
) ELSE IF "" NEQ "%~2" (
|
||
|
ECHO !txt!
|
||
|
)
|
||
|
|
||
|
SET "TS=%DATE% %TIME%"
|
||
|
IF EXIST "!logfile!" (
|
||
|
ECHO !TS! !txt!>>"!logfile!"
|
||
|
) ELSE (
|
||
|
ECHO !TS! !txt!>"!logfile!"
|
||
|
)
|
||
|
EXIT /B
|
||
|
rem ****************
|
||
|
rem ****************
|
||
|
|
||
|
:exit
|
||
|
IF "1" == "!testmode!" PAUSE
|
||
|
IF "1" NEQ "!testmode!" EXIT
|