mirror of
https://github.com/clinton-hall/nzbToMedia.git
synced 2025-08-20 21:33:13 -07:00
commit
1869b0a3b4
13 changed files with 526 additions and 82 deletions
197
README.md
197
README.md
|
@ -18,17 +18,19 @@ The renamer of CouchPotatoServer caused broken downloads by interfering with NZB
|
|||
Failed download handling for SickBeard is available by using the development branch from fork [SickBeard-failed](https://github.com/Tolstyak/Sick-Beard.git "SickBeard-failed")
|
||||
To use this feature, in autoProcessTV.cfg set the parameter "failed_fork=1". Default is 0 and will work with standard version of SickBeard and just ignores failed downloads.
|
||||
|
||||
Torrent support has been added with the assistance of [jkaberg](https://github.com/jkaberg "jkaberg").
|
||||
|
||||
Installation
|
||||
------------
|
||||
### General
|
||||
|
||||
1. Put all files in a directory wherever you want to keep them (eg. /scripts/ in the home directory of your nzb client)
|
||||
and change the permission accordingly so the nzb client can access to this files.
|
||||
and change the permission accordingly so the nzb client can access these files.
|
||||
|
||||
### nzbToSickBeard
|
||||
|
||||
1. Rename the file autoProcessTV.cfg.sample to autoProcessTV.cfg and fill in the appropriate
|
||||
fields as they apply to your installation.
|
||||
1. Rename the file autoProcessMedia.cfg.sample to autoProcessMedia.cfg and fill in the appropriate
|
||||
fields in [SickBeard] as they apply to your installation.
|
||||
|
||||
host: Set this to "localhost" if SickBeard and your download client are on the same system. otherwise enter the ipaddress of the system SickBeard is insatlled on.
|
||||
|
||||
|
@ -46,10 +48,15 @@ Installation
|
|||
|
||||
failed_fork: Set this to "1" if you are using the failed fork branch. Otherwise set this to "0". (optional)
|
||||
|
||||
2. If you have added .py to your PATHEXT (in windows) or you have given nzbToSickBeard.py executable permissions, or you are using the compiled executables you can manually call this process outside of your nzb client for testing your configuration or in case a postprocessing event failed.
|
||||
To do this, execute nzbToSickBeard.py e.g. double-click in Windows or via ssh/shell issue the following command:
|
||||
$ ./nzbToSickBeard.py when in the directory where nzbToSickBeard.py is located.
|
||||
note: you must have watch_dir set to use nzbToSickBeard for a manual scan.
|
||||
|
||||
### nzbToCouchPotato
|
||||
|
||||
1. Rename the file autoProcessMovie.cfg.sample to autoProcessMovie.cfg and fill in the appropriate
|
||||
fields as they apply to your installation.
|
||||
1. Rename the file autoProcessMedia.cfg.sample to autoProcessMedia.cfg and fill in the appropriate
|
||||
fields in [CouchPotato] as they apply to your installation.
|
||||
|
||||
host: Set this to "localhost" if CouchPotatoServer and your download client are on the same system. otherwise enter the ipaddress of the system SickBeard is insatlled on.
|
||||
|
||||
|
@ -74,8 +81,12 @@ Installation
|
|||
Method "manage" will make CouchPotatoServer update the list of managed movies if manager is enabled but renamer is not enabled.
|
||||
In this case your nzb client must extract the files directly to your final movies folder (as configured in CouchPotatoServer manage settings) and Manage must be enabled.
|
||||
|
||||
3. If you have added .py to your PATHEXT (in windows) or you have given nzbToCouchPotato.py executable permissions, or you are using the compiled executables you can manually call this process outside of your nzb client for testing your configuration or in case a postprocessing event failed.
|
||||
To do this, execute nzbToCouchPotato.py e.g. via ssl issue the following command:
|
||||
delete_failed: Set this to "1" if you want this script to delete all files and folders related to a download that has failed.
|
||||
setting this to "0" will not delete any files.
|
||||
note. this is not given as an option for SickBeard since the failed_fork in SickBeard supports this feature.
|
||||
|
||||
2. If you have added .py to your PATHEXT (in windows) or you have given nzbToCouchPotato.py executable permissions, or you are using the compiled executables you can manually call this process outside of your nzb client for testing your configuration or in case a postprocessing event failed.
|
||||
To do this, execute nzbToCouchPotato.py e.g. double-click in Windows or via ssh/shell issue the following command:
|
||||
$ ./nzbToCouchPotato.py when in the directory where nzbToCouchPotato.py is located.
|
||||
|
||||
### SickBeard
|
||||
|
@ -96,7 +107,13 @@ The following must be configured in SickBeard:
|
|||
|
||||
vi. NZBGet Category - SABnzbd Category = A category that is used by your download client (e.g. "TV", or "SickBeard")
|
||||
|
||||
2. Settings -> Post Processing -> Post Processing
|
||||
2. Config -> Search Settings -> Search Torrents
|
||||
|
||||
i. Torrent Black Hole = Enter your Torrent downlaoder's BlackHole Directory + tv sub directory
|
||||
|
||||
/usr/local/blackhole/tv
|
||||
|
||||
3. Settings -> Post Processing -> Post Processing
|
||||
|
||||
i. TV Download Dir = blank
|
||||
|
||||
|
@ -108,13 +125,13 @@ The following must be configured in SickBeard:
|
|||
|
||||
v. Scan and Process = must be unticked.
|
||||
|
||||
3. Settings -> Post Processing -> Naming
|
||||
4. Settings -> Post Processing -> Naming
|
||||
|
||||
The naming must be specified as per user choice.
|
||||
|
||||
This naming will be applied to all shows processed via the postprocess script.
|
||||
|
||||
4. Settings -> Post Processing -> Metadata
|
||||
5. Settings -> Post Processing -> Metadata
|
||||
|
||||
The metadata wanted must be specified as per user choice.
|
||||
|
||||
|
@ -136,7 +153,40 @@ The following must be configured in CouchPotatoServer:
|
|||
|
||||
v. Delete Failed = Should be unticked (Sabnzbd only)
|
||||
|
||||
2. Settings -> Renamer -> "Rename downloaded movies" should be checked and the settings below applied:
|
||||
2. Settings -> Downloaders -> Transmission
|
||||
|
||||
i. Host = The url/host and port for Transmission.
|
||||
|
||||
ii. username = The user name required to log in to Transmission
|
||||
|
||||
iii. password = The password required to log in to Transmission
|
||||
|
||||
iv. Directory = The directory for completed/seeding files. NOT the renamer "from" directory.
|
||||
|
||||
/usr/local/Download/movies
|
||||
|
||||
3. Settings -> Downloaders -> uTorrent
|
||||
|
||||
i. Host = The url/host and port for uTorrent.
|
||||
|
||||
ii. username = The user name required to log in to uTorrent
|
||||
|
||||
iii. password = The password required to log in to uTorrent
|
||||
|
||||
iv. label = label/category to be used by the postprocessing script.
|
||||
|
||||
movies
|
||||
|
||||
4. Settings -> Downloaders -> BlackHole
|
||||
|
||||
i. Directory = Enter your Torrent downlaoder's BlackHole Directory + movies sub directory
|
||||
|
||||
/usr/local/blackhole/movies
|
||||
|
||||
ii. use for = Torrents, Usenet, or Both.
|
||||
If using SABnzbd of NZBget for Usenet, and balckhole for torrents, select "torrents" only.
|
||||
|
||||
5. Settings -> Renamer -> "Rename downloaded movies" should be checked and the settings below applied:
|
||||
|
||||
i. From = Must be set to the full path to your completed download movies (including any additional category paths)
|
||||
|
||||
|
@ -298,3 +348,128 @@ If you are using NZBGet perform the following steps to configure postprocessing
|
|||
Use \r\n for new line.
|
||||
|
||||
Email_Message='The download of <name> has <status>. \r\n This has been processed by the script <script> for category <cat>'
|
||||
|
||||
### µTorrent
|
||||
|
||||
If you are using µTorrent, perform the following steps to configure postprocessing for "TorrentToMedia":
|
||||
|
||||
1. Rename the autoProcessMedia.cfg.sample to autoProcessMedia.cfg and edit the parameters:
|
||||
|
||||
i. [Torrent} uselink = 1 to allow hard-linking of files
|
||||
quicker and less harddisk used, if download and final location are on the same hard-disk
|
||||
set uselink = 0 to use normal copy options.
|
||||
Windows systems and any movement across hard disks MUST use "0"
|
||||
|
||||
ii. [Torrent] extractiontool (Windows Only)
|
||||
'C:\\Program Files\\7-Zip\\7z.exe' (you will need to install 7-zip)
|
||||
|
||||
iii. [CouchPotato] & [SickBeard]
|
||||
Category = you must set the category that is passed from these applications
|
||||
If using "blackhole-subdirectory", this is the last folder name used in the blackhole.
|
||||
destination = you must set the absoluet path where you want movies extracted to.
|
||||
this destination, for CouchPotato, must match the CouchPotato Renamers, "from" directory.
|
||||
|
||||
iv. Configure the remaining settings as describes in nzbToCouchPotato and nzbToSickBeard above.
|
||||
|
||||
|
||||
2. In µTorrent go to preferences > Advanced > Run Program > Run this program when torrent finishes:
|
||||
|
||||
i. Set full path to script, pass paramaters as "%D" "%N" "%L".
|
||||
|
||||
/usr/local/utorrent/nzbToMedia/TorrentToMedia.py "%D" "%N" "%L"
|
||||
|
||||
3. In uTorrent set the following directories.
|
||||
|
||||
i. Download Directory = The directory where downloaded files stay while seeding.
|
||||
This is NOT the "FROM" directory in CouchPotato renamer.
|
||||
|
||||
/usr/local/Download
|
||||
|
||||
ii. Watch Direcetory = The balckhole directory used by CouchPotato and/or SickBeard
|
||||
|
||||
/usr/local/blackhole
|
||||
|
||||
4. Output from TorrentToMedia will be logged where the scripts reside, in a file called "postprocess.log"
|
||||
|
||||
### Transmission
|
||||
|
||||
If you are using Transmission, perform the following steps to configure postprocessing for "TorrentToMedia":
|
||||
|
||||
1. Rename the autoProcessMedia.cfg.sample to autoProcessMedia.cfg and edit the parameters:
|
||||
|
||||
i. [Torrent} uselink = 1 to allow hard-linking of files
|
||||
quicker and less harddisk used, if download and final location are on the same hard-disk
|
||||
set uselink = 0 to use normal copy options.
|
||||
Windows systems and any movement across hard disks MUST use "0"
|
||||
|
||||
ii. [Torrent] extractiontool (Windows Only)
|
||||
'C:\\Program Files\\7-Zip\\7z.exe' (you will need to install 7-zip)
|
||||
|
||||
iii. [CouchPotato] & [SickBeard]
|
||||
Category = you must set the category that is passed from these applications
|
||||
This is the last folder name in the directory path passed as "directory for completed downloads."
|
||||
If using "blackhole-subdirectory", this is the last folder name used in the blackhole.
|
||||
|
||||
destination = you must set the absoluet path where you want movies extracted to.
|
||||
this destination, for CouchPotato, must match the CouchPotato Renamers, "from" directory.
|
||||
/usr/local/extracted/movies
|
||||
/usr/local/extracted/tv
|
||||
|
||||
iv. Configure the remaining settings as describes in nzbToCouchPotato and nzbToSickBeard above.
|
||||
|
||||
|
||||
2. In Transmission add the TorrentToMedia.py script to run on downlaod complete.
|
||||
|
||||
i. On some systems go to Preferences->Transfers->Management
|
||||
Select the script to run on download complete.
|
||||
|
||||
/usr/local/transmission/nzbToMedia/TorrentToMedia.py
|
||||
|
||||
ii. On other systems you will need to edit settings.json
|
||||
(usually /etc/transmission-daemon/settings.json).
|
||||
Edit while the daemon is not running.
|
||||
|
||||
"script-torrent-done-enabled": true,
|
||||
"script-torrent-done-filename": "/usr/local/transmission/nzbToMedia/TorrentToMedia.py",
|
||||
|
||||
3. In Transmission set the following directories (settings.json, or interface).
|
||||
|
||||
i. Download Directory = The directory where downloaded files stay while seeding.
|
||||
This is NOT the "FROM" directory in CouchPotato renamer.
|
||||
|
||||
"download-dir": "/usr/local/Download",
|
||||
|
||||
ii. Watch Direcetory = The balckhole directory used by CouchPotato and/or SickBeard
|
||||
|
||||
"watch-dir": "/usr/local/blackhole',
|
||||
"watch-dir-enabled": true,
|
||||
|
||||
4. Output from TorrentToMedia will be logged where the scripts reside, in a file called "postprocess.log"
|
||||
|
||||
|
||||
### FOLDER STRUCTURE: Important for black-hole and Torrent.
|
||||
|
||||
This is just an example to illustrate how this can be achieved.
|
||||
|
||||
Watch Directory / Blackhole
|
||||
This is the root path where your downloader looks for nzbs/torrents.
|
||||
This will have 2 sub-directories, "tv" and "movies", which define the "categories".
|
||||
|
||||
/usr/local/blackhole
|
||||
/usr/local/blackhole/tv
|
||||
/usr/local/blackhole/movies
|
||||
|
||||
Download Directory
|
||||
This is the root path where your downloads are put when finished (and where files will be seeded from for Torrents).
|
||||
This will have 2 sub-directories, "tv" and "movies", which define the "categories".
|
||||
|
||||
/usr/local/Download
|
||||
/usr/local/Download/tv
|
||||
/usr/local/Download/movies
|
||||
|
||||
destination
|
||||
This is the directory specified for each category, where final files are moved to after extarction.
|
||||
For CouchPotato this will be the renamer "from" directory.
|
||||
|
||||
/usr/local/extracted/tv
|
||||
/usr/local/extracted/movies
|
||||
|
|
248
TorrentToMedia.py
Executable file
248
TorrentToMedia.py
Executable file
|
@ -0,0 +1,248 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import autoProcessMovie
|
||||
import autoProcessTV
|
||||
import sys, os, ConfigParser, shutil
|
||||
from subprocess import call
|
||||
|
||||
def removeEmptyFolders(path):
|
||||
if not os.path.isdir(path):
|
||||
return
|
||||
|
||||
# remove empty subfolders
|
||||
files = os.listdir(path)
|
||||
if len(files):
|
||||
for f in files:
|
||||
fullpath = os.path.join(path, f)
|
||||
if os.path.isdir(fullpath):
|
||||
removeEmptyFolders(fullpath)
|
||||
|
||||
# if folder empty, delete it
|
||||
files = os.listdir(path)
|
||||
if len(files) == 0:
|
||||
print "INFO: Removing empty folder: %s" % (path)
|
||||
os.rmdir(path)
|
||||
|
||||
old_stdout = sys.stdout #backup the default stdout
|
||||
log_file = open(os.path.join(os.path.dirname(sys.argv[0]), "postprocess.log"),"a+")
|
||||
sys.stdout = log_file #create a local log file, and direct all "print" to the log.
|
||||
print "INFO: TorrentToMedia V4.2"
|
||||
if len(sys.argv) == 4:
|
||||
##You can use the following parameters (UTORRENT):
|
||||
##
|
||||
##%F - Name of downloaded file (for single file torrents)
|
||||
##%D - Directory where files are saved
|
||||
##%N - Title of torrent
|
||||
##%P - Previous state of torrent
|
||||
##%L - Label
|
||||
##%T - Tracker
|
||||
##%M - Status message string (same as status column)
|
||||
##%I - hex encoded info-hash
|
||||
##%S - State of torrent
|
||||
##%K - kind of torrent (single|multi)
|
||||
##
|
||||
##Where State is one of:
|
||||
##
|
||||
##Error - 1
|
||||
##Checked - 2
|
||||
##Paused - 3
|
||||
##Super seeding - 4
|
||||
##Seeding - 5
|
||||
##Downloading - 6
|
||||
##Super seed [F] - 7
|
||||
##Seeding [F] - 8
|
||||
##Downloading [F] - 9
|
||||
##Queued seed - 10
|
||||
##Finished - 11
|
||||
##Queued - 12
|
||||
##Stopped - 13
|
||||
|
||||
## We will pass in %D, %N, %L from uTorrent
|
||||
print "INFO: Script called from utorrent"
|
||||
Directory = sys.argv[1] ## %D -- Example output: F:\path\to\dir\My.Series.S01E01.720p.HDTV.x264-2HD
|
||||
Name = sys.argv[2] ## %N -- Example output: My.Series.S01E01.720p.HDTV.x264-2HD
|
||||
Category = sys.argv[3] ## %L -- Example output: tvseries ## This is the label in uTorrent
|
||||
|
||||
elif len(sys.argv) > 1: #Doesn't match Transmission (1) or uTorrent (4).
|
||||
print "Error: The number of arguments passed is %s. Unable to determin the arguments to use; Exiting" % (len(sys.argv))
|
||||
sys.exit(-1)
|
||||
|
||||
else:
|
||||
##test for Transmission here.
|
||||
#TR_APP_VERSION
|
||||
#TR_TIME_LOCALTIME
|
||||
#TR_TORRENT_DIR
|
||||
#TR_TORRENT_HASH
|
||||
#TR_TORRENT_ID
|
||||
#TR_TORRENT_NAME
|
||||
try:
|
||||
Directory = os.getenv('TR_TORRENT_DIR')
|
||||
Name = os.getenv('TR_TORRENT_NAME')
|
||||
print "INFO: Script called from Transmission"
|
||||
except:
|
||||
print "Error: There was a problem loading variables from Transmission", "Exiting"
|
||||
sys.exit(-1)
|
||||
Category = os.path.basename(os.path.normpath(Directory)) #We assume the last directory is the category for now.
|
||||
|
||||
if not Category:
|
||||
Category = os.path.basename(os.path.normpath(Directory)) #Test for blackhole sub-directory.
|
||||
|
||||
status = 0
|
||||
packed = 0
|
||||
|
||||
config = ConfigParser.ConfigParser()
|
||||
configFilename = os.path.join(os.path.dirname(sys.argv[0]), "autoProcessMedia.cfg")
|
||||
|
||||
print "INFO: Loading config from %s" % (configFilename)
|
||||
|
||||
if not os.path.isfile(configFilename):
|
||||
print "ERROR: You need an autoProcessMedia.cfg file - did you rename and edit the .sample?"
|
||||
sys.exit(-1)
|
||||
|
||||
config.read(configFilename)
|
||||
|
||||
TV_Cat = config.get("SickBeard", "category")
|
||||
TV_dest = config.get("SickBeard", "destination")
|
||||
Movie_dest = config.get("CouchPotato", "destination")
|
||||
Movie_Cat = config.get("CouchPotato", "category")
|
||||
useLink = int(config.get("Torrent", "uselink"))
|
||||
extractionTool = config.get("Torrent", "extractiontool")
|
||||
|
||||
if Category == Movie_Cat:
|
||||
destination = os.path.join(Movie_dest, Name)
|
||||
elif Category == TV_Cat:
|
||||
destination = os.path.join(TV_dest, Name)
|
||||
else:
|
||||
print "INFO: Not assigned a label of either %s or %s: Exiting" %(Movie_Cat, TV_Cat)
|
||||
sys.exit(-1)
|
||||
|
||||
test = ['.zip', '.rar', '.7z', '.gz', '.bz', '.tar', '.arj']
|
||||
test2 = ['.mkv', '.avi', '.divx', '.xvid', '.mov', '.wmv', '.mp4', '.mpg', '.mpeg']
|
||||
f = [filenames for dirpath, dirnames, filenames in os.walk(Directory)]
|
||||
ext = [os.path.splitext(file)[1] for file in f[1]]
|
||||
if set(ext).intersection(set(test)):
|
||||
print "INFO: Found compressed archives, extracting"
|
||||
packed = 1
|
||||
## Check that files actully is .mkv / .avi etc, and not packed files or anything else
|
||||
elif set(ext).intersection(set(test2)):
|
||||
print "INFO: Found media files, moving"
|
||||
else:
|
||||
print "DEBUG: Found files with extensions %s." % (ext)
|
||||
print "DEBUG: Looking for extensions %s or %s." % (test, test2)
|
||||
print "INFO: Didn't find any compressed archives or media files to process, exiting"
|
||||
sys.exit(-1)
|
||||
|
||||
if useLink == 0 and packed == 0: ## copy
|
||||
print "INFO: Copying all files from %s to %s." % (Directory, destination)
|
||||
shutil.copytree(Directory, destination)
|
||||
|
||||
elif useLink == 1 and packed == 0: ## hardlink
|
||||
print "INFO: Creating hard link from %s to %s." % (Directory, destination)
|
||||
os.mkdir(destination)
|
||||
for dirpath, dirnames, filenames in os.walk(Directory):
|
||||
for file in filenames:
|
||||
os.link(os.path.join(dirpath, file), os.path.join(destination, file))
|
||||
|
||||
elif packed == 1: ## unpack
|
||||
## Using Windows?
|
||||
if os.name == 'nt':
|
||||
cmd_7zip = [extractionTool, 'x -y']
|
||||
ext_7zip = [".rar",".zip",".tar.gz","tgz",".tar.bz2",".tbz",".tar.lzma",".tlz",".7z",".xz"]
|
||||
EXTRACT_COMMANDS = dict.fromkeys(ext_7zip, cmd_7zip)
|
||||
print "INFO: We are using Windows"
|
||||
|
||||
## Using linux?
|
||||
elif os.name == 'posix':
|
||||
required_cmds=["unrar", "unzip", "tar", "unxz", "unlzma", "7zr"]
|
||||
EXTRACT_COMMANDS = {
|
||||
".rar": ["unrar", "x -o+ -y"],
|
||||
".zip": ["unzip", ""],
|
||||
".tar.gz": ["tar", "xzf"],
|
||||
".tgz": ["tar", "xzf"],
|
||||
".tar.bz2": ["tar", "xjf"],
|
||||
".tbz": ["tar", "xjf"],
|
||||
".tar.lzma": ["tar", "--lzma xf"],
|
||||
".tlz": ["tar", "--lzma xf"],
|
||||
".txz": ["tar", "--xz xf"],
|
||||
".7z": ["7zr", "x"],
|
||||
}
|
||||
print "INFO: We are using *nix"
|
||||
|
||||
## Need to add a check for which commands that can be utilized in *nix systems..
|
||||
else:
|
||||
print "ERROR: Unknown OS, exiting"
|
||||
|
||||
files = [ f for f in os.listdir(Directory) if os.path.isfile(os.path.join(Directory,f)) ]
|
||||
for f in files:
|
||||
ext = os.path.splitext(f)
|
||||
fp = os.path.join(Directory, os.path.normpath(f))
|
||||
if ext[1] in (".gz", ".bz2", ".lzma"):
|
||||
## Check if this is a tar
|
||||
if os.path.splitext(ext[0])[1] == ".tar":
|
||||
cmd = EXTRACT_COMMANDS[".tar" + ext[1]]
|
||||
else:
|
||||
if ext[1] in EXTRACT_COMMANDS:
|
||||
cmd = EXTRACT_COMMANDS[ext[1]]
|
||||
else:
|
||||
print "ERROR: Unknown file type: %s" % (ext[1])
|
||||
continue
|
||||
|
||||
## Create destination folder
|
||||
if not os.path.exists(destination):
|
||||
try:
|
||||
os.makedirs(destination)
|
||||
except Exception, e:
|
||||
print "ERROR: Not possible to create destination folder: %s" % (e)
|
||||
continue
|
||||
|
||||
print"INFO: Extracting to %s" % (destination)
|
||||
|
||||
## Running..
|
||||
print "INFO: Extracting %s %s %s %s" % (cmd[0], cmd[1], fp, destination)
|
||||
pwd = os.getcwd() # Get our Present Working Directory
|
||||
os.chdir(destination) #not all unpack commands accept full paths, so just extract into this directory.
|
||||
if os.name == 'nt': #Windows needs quotes around directory structure
|
||||
try:
|
||||
run = "\"" + cmd[0] + "\" " + cmd[1] + " \"" + fp + "\"" #windows needs quotes around directories.
|
||||
res = call(run)
|
||||
if res == 0:
|
||||
status = 0
|
||||
print "INFO: Extraction was successful for %s to %s" % (fp, destination)
|
||||
else:
|
||||
print "ERROR: Extraction failed for %s. 7zip result was %s" % (fp, res)
|
||||
except:
|
||||
print "ERROR: Extraction failed for %s. Could not call command %s %s" % (fp, run)
|
||||
else:
|
||||
try:
|
||||
if cmd[1] == "": #if calling unzip, we dont want to pass the ""
|
||||
res = call([cmd[0], fp])
|
||||
else:
|
||||
res = call([cmd[0], cmd[1], fp])
|
||||
if res == 0:
|
||||
status = 0
|
||||
print "INFO: Extraction was successful for %s to %s" % (fp, destination)
|
||||
else:
|
||||
print "ERROR: Extraction failed for %s. 7zip result was %s" % (fp, res)
|
||||
except:
|
||||
print "ERROR: Extraction failed for %s. Could not call command %s %s %s %s" % (fp, cmd[0], cmd[1], fp)
|
||||
os.chdir(pwd) # Go back to our Original Working Directory
|
||||
|
||||
for dirpath, dirnames, filenames in os.walk(destination): #flatten out the directory to make postprocessing easier.
|
||||
if dirpath == destination:
|
||||
continue #no need to try and move files in the root destination directory.
|
||||
for filename in filenames:
|
||||
try:
|
||||
shutil.move(os.path.join(dirpath, filename), destination)
|
||||
except OSError:
|
||||
print "INFO: Could not flatten %s " % (os.path.join(dirpath, filename))
|
||||
removeEmptyFolders(destination) #cleanup empty directories.
|
||||
|
||||
status = int(status)
|
||||
## Now we pass off to CouchPotato or SickBeard.
|
||||
if Category == Movie_Cat:
|
||||
autoProcessMovie.process(destination, Name, status)
|
||||
elif Category == TV_Cat:
|
||||
autoProcessTV.processEpisode(destination, Name, status)
|
||||
|
||||
sys.stdout = old_stdout #reset our stdout
|
||||
log_file.close() #close the log
|
30
autoProcessMedia.cfg.sample
Normal file
30
autoProcessMedia.cfg.sample
Normal file
|
@ -0,0 +1,30 @@
|
|||
[CouchPotato]
|
||||
host = localhost
|
||||
port = 5050
|
||||
username =
|
||||
password =
|
||||
ssl = 0
|
||||
web_root =
|
||||
apikey = xxxxxxxx
|
||||
delay = 60
|
||||
method = renamer
|
||||
delete_failed = 0
|
||||
category = movies
|
||||
destination = /abs/path/to/complete/movies
|
||||
|
||||
[SickBeard]
|
||||
host=localhost
|
||||
port=8081
|
||||
username=
|
||||
password=
|
||||
web_root=
|
||||
ssl=0
|
||||
watch_dir=
|
||||
failed_fork=0
|
||||
category = tv
|
||||
destination = /abs/path/to/complete/tv
|
||||
|
||||
[Torrent]
|
||||
uselink = 0
|
||||
extractiontool = 'C:\\Program Files\\7-Zip\\7z.exe'
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
[CouchPotato]
|
||||
host = localhost
|
||||
port = 5050
|
||||
username =
|
||||
password =
|
||||
ssl = 0
|
||||
web_root =
|
||||
apikey = xxxxxxxx
|
||||
delay = 60
|
||||
method = renamer
|
||||
|
||||
[Comments]
|
||||
host = (ip address for CouchPotato Server. Use "localhost" if SABnzbd and CPS on same system)
|
||||
port = (port for CouchPotato Server)
|
||||
username = (username if set for CouchPotato Server)
|
||||
password = (password if set for CouchPotato Server)
|
||||
ssl = 0 (set to 1 if you want to use ssl. -untested. Default is 0)
|
||||
web_root = (set URL base if needed.)
|
||||
apikey = (apikey for CouchPotato Server... Required)
|
||||
delay = (set delay in seconds before sending api call. Minimum 60)
|
||||
method = "renamer" or "manage". renamer is the default. Read the help file.
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import sys
|
||||
import urllib
|
||||
import os.path
|
||||
import shutil
|
||||
import ConfigParser
|
||||
import time
|
||||
import json
|
||||
|
@ -29,11 +30,11 @@ def process(dirName, nzbName=None, status=0):
|
|||
|
||||
status = int(status)
|
||||
config = ConfigParser.ConfigParser()
|
||||
configFilename = os.path.join(os.path.dirname(sys.argv[0]), "autoProcessMovie.cfg")
|
||||
configFilename = os.path.join(os.path.dirname(sys.argv[0]), "autoProcessMedia.cfg")
|
||||
print "Loading config from", configFilename
|
||||
|
||||
if not os.path.isfile(configFilename):
|
||||
print "ERROR: You need an autoProcessMovie.cfg file - did you rename and edit the .sample?"
|
||||
print "ERROR: You need an autoProcessMedia.cfg file - did you rename and edit the .sample?"
|
||||
sys.exit(-1)
|
||||
|
||||
config.read(configFilename)
|
||||
|
@ -45,6 +46,7 @@ def process(dirName, nzbName=None, status=0):
|
|||
apikey = config.get("CouchPotato", "apikey")
|
||||
delay = float(config.get("CouchPotato", "delay"))
|
||||
method = config.get("CouchPotato", "method")
|
||||
delete_failed = int(config.get("CouchPotato", "delete_failed"))
|
||||
|
||||
try:
|
||||
ssl = int(config.get("CouchPotato", "ssl"))
|
||||
|
@ -64,6 +66,10 @@ def process(dirName, nzbName=None, status=0):
|
|||
protocol = "https://"
|
||||
else:
|
||||
protocol = "http://"
|
||||
# don't delay when we are calling this script manually.
|
||||
if nzbName == "Manual Run":
|
||||
delay = 0
|
||||
|
||||
if status == 0:
|
||||
if method == "manage":
|
||||
command = "manage.update"
|
||||
|
@ -84,17 +90,18 @@ def process(dirName, nzbName=None, status=0):
|
|||
print "Unable to open URL: ", str(e)
|
||||
sys.exit(1)
|
||||
|
||||
result = urlObj.readlines()
|
||||
for line in result:
|
||||
print line
|
||||
|
||||
print command, "started on CouchPotatoServer for", nzbName1
|
||||
result = json.load(urlObj)
|
||||
print "CouchPotatoServer returned", result
|
||||
if result['success']:
|
||||
print command, "started on CouchPotatoServer for", nzbName1
|
||||
else:
|
||||
print "Error", command, "has NOT started on CouchPotatoServer for", nzbName1
|
||||
|
||||
else:
|
||||
print "download of", nzbName1, "has failed."
|
||||
print "trying to re-cue the next highest ranked release"
|
||||
a=nzbName1.find('.cp')+4
|
||||
b=nzbName1.find('.nzb')-1
|
||||
a=nzbName1.find('.cp(')+4
|
||||
b=nzbName1[a:].find(')')+a
|
||||
imdbid=nzbName1[a:b]
|
||||
#print imdbid
|
||||
|
||||
|
@ -141,3 +148,6 @@ def process(dirName, nzbName=None, status=0):
|
|||
print line
|
||||
|
||||
print "movie", movid, "set to try the next best release on CouchPotatoServer"
|
||||
if delete_failed:
|
||||
print "Deleting failed files and folder", dirName
|
||||
shutil.rmtree(dirName)
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
[SickBeard]
|
||||
host=localhost
|
||||
port=8081
|
||||
username=
|
||||
password=
|
||||
web_root=
|
||||
ssl=0
|
||||
watch_dir=
|
||||
failed_fork=0
|
|
@ -45,11 +45,11 @@ def processEpisode(dirName, nzbName=None, failed=False):
|
|||
|
||||
status = int(failed)
|
||||
config = ConfigParser.ConfigParser()
|
||||
configFilename = os.path.join(os.path.dirname(sys.argv[0]), "autoProcessTV.cfg")
|
||||
configFilename = os.path.join(os.path.dirname(sys.argv[0]), "autoProcessMedia.cfg")
|
||||
print "Loading config from", configFilename
|
||||
|
||||
if not os.path.isfile(configFilename):
|
||||
print "ERROR: You need an autoProcessTV.cfg file - did you rename and edit the .sample?"
|
||||
print "ERROR: You need an autoProcessMedia.cfg file - did you rename and edit the .sample?"
|
||||
sys.exit(-1)
|
||||
|
||||
try:
|
||||
|
@ -85,6 +85,10 @@ def processEpisode(dirName, nzbName=None, failed=False):
|
|||
except (ConfigParser.NoOptionError, ValueError):
|
||||
failed_fork = 0
|
||||
|
||||
#allows manual call of postprocess script if we have specified a watch_dir. Check that here.
|
||||
if nzbName == "Manual Run" and watch_dir == "":
|
||||
print "ERROR: In order to run this script manually you must specify a watch_dir in autoProcessTV.cfg"
|
||||
sys.exit(-1)
|
||||
#allows us to specify the default watch directory and call the postproecssing on another PC with different directory structure.
|
||||
if watch_dir != "":
|
||||
dirName = watch_dir
|
||||
|
|
|
@ -1,5 +1,19 @@
|
|||
Change_LOG / History
|
||||
|
||||
V4.2 12/02/2013
|
||||
|
||||
Fixes to TorrentToMedia
|
||||
|
||||
V4.1 02/02/2013
|
||||
|
||||
Added Torrent Support (µTorrent and Transmission).
|
||||
Added manual run option for nzbToSickBeard.
|
||||
Changed nzbGet script to use move not copy and remove.
|
||||
Merged all .cfg scripts into one (autoProcessMedia.cfg).
|
||||
Made all scripts execitable (755) on github.
|
||||
Added category limits for email support in nzbget.
|
||||
Fixed issue with replacements (of paths) in email messages in nzbget.
|
||||
|
||||
V4.0 21/12/2012
|
||||
|
||||
Changed name from nzbToCouchPotato to nzbToMedia; Now supports mltiple post-processing from two nzb download clients.
|
||||
|
|
2
nzbToCouchPotato.py
Normal file → Executable file
2
nzbToCouchPotato.py
Normal file → Executable file
|
@ -3,7 +3,7 @@
|
|||
import sys
|
||||
import autoProcessMovie
|
||||
|
||||
print "nzbToCouchPotato V4.0"
|
||||
print "nzbToCouchPotato V4.1"
|
||||
|
||||
# SABnzbd
|
||||
if len(sys.argv) == 8:
|
||||
|
|
5
nzbToSickBeard.py
Normal file → Executable file
5
nzbToSickBeard.py
Normal file → Executable file
|
@ -25,7 +25,7 @@
|
|||
import sys
|
||||
import autoProcessTV
|
||||
|
||||
print "nzbToSickBeard V4.0"
|
||||
print "nzbToSickBeard V4.1"
|
||||
|
||||
# SABnzbd
|
||||
if len(sys.argv) == 8:
|
||||
|
@ -52,4 +52,5 @@ elif len(sys.argv) == 4:
|
|||
|
||||
else:
|
||||
print "Invalid number of arguments received from client."
|
||||
sys.exit()
|
||||
print "Running autoProcessTV as a manual run..."
|
||||
autoProcessTV.processEpisode('Manual Run', 'Manual Run', 0)
|
||||
|
|
35
nzbget-postprocessing-files/9.0/bin/nzbget-postprocess.sh
Normal file → Executable file
35
nzbget-postprocessing-files/9.0/bin/nzbget-postprocess.sh
Normal file → Executable file
|
@ -160,7 +160,7 @@ replaceVarBy() {
|
|||
|
||||
# If we're not using Bash use sed, as we need to support as much as systems possible, also those running sh/dash etc
|
||||
if [ -n "${BASH_VERSION}" ]; then
|
||||
REPLACEDRESULT="${1/${2}/${3##*/}}" # get last part after slash for paths
|
||||
REPLACEDRESULT="${1/${2}/${3}}"
|
||||
else
|
||||
REPLACEDRESULT=$(echo "${1}" | sed "s^${2}^${3}^g")
|
||||
fi
|
||||
|
@ -184,7 +184,8 @@ do_exit() {
|
|||
replaceVarBy "${REPLACEDRESULT}" "<cat>" "${NZBPP_CATEGORY}"
|
||||
replaceVarBy "${REPLACEDRESULT}" "<script>" "${script}"
|
||||
Email_Message="${REPLACEDRESULT}"
|
||||
if [ "$Email_successful" = "yes" -a "$nzbStatus" = 0 ]; then
|
||||
for item in $Email_successful; do
|
||||
if [ "${NZBPP_CATEGORY}" = "$item" -a "$nzbStatus" = 0 ]; then
|
||||
User=""
|
||||
if [ -n "$Email_User" -a -n "$Email_Pass" ]; then User="-xu $Email_User -xp $Email_Pass" ; fi
|
||||
replaceVarBy "${Email_Subject}" "<status>" "completed"
|
||||
|
@ -192,8 +193,9 @@ do_exit() {
|
|||
replaceVarBy "${Email_Message}" "<status>" "completed"
|
||||
Email_Message="${REPLACEDRESULT}"
|
||||
$sendEmail -f "$Email_From" -t "$Email_To" -s "$Email_Server" $User -u "$Email_Subject" -m "$Email_Message"
|
||||
fi
|
||||
if [ "$Email_failed" = "yes" -a "$nzbStatus" != 0 ]; then
|
||||
fi; done
|
||||
for item in $Email_failed; do
|
||||
if [ "${NZBPP_CATEGORY}" = "$item" -a "$nzbStatus" != 0 ]; then
|
||||
User=""
|
||||
if [ -n "$Email_User" -a -n "$Email_Pass" ]; then User="-xu $Email_User -xp $Email_Pass" ; fi
|
||||
replaceVarBy "${Email_Subject}" "<status>" "failed"
|
||||
|
@ -201,7 +203,7 @@ do_exit() {
|
|||
replaceVarBy "${Email_Message}" "<status>" "failed"
|
||||
Email_Message="${REPLACEDRESULT}"
|
||||
$sendEmail -f "$Email_From" -t "$Email_To" -s "$Email_Server" $User -u "$Email_Subject" -m "$Email_Message"
|
||||
fi
|
||||
fi; done
|
||||
exit $1
|
||||
}
|
||||
|
||||
|
@ -445,45 +447,36 @@ fi
|
|||
# Test for category and ensure the passed directory exists as a directory.
|
||||
if [ "$NZBPP_CATEGORY" = "$SickBeardCategory" -a -d "$TvDownloadDir" ]; then
|
||||
echo "[INFO] Post-Process: Moving TV shows to $TvDownloadDir"
|
||||
cp -R "$NZBPP_DIRECTORY" "$TvDownloadDir"
|
||||
mv $NZBPP_DIRECTORY $TvDownloadDir
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo "[ERROR] Post-Process: Moving to $TvDownloadDir"
|
||||
exit $POSTPROCESS_ERROR
|
||||
else
|
||||
rm -fr *
|
||||
cd ..
|
||||
rmdir "$NZBPP_DIRECTORY"
|
||||
NZBPP_DIRECTORY="$TvDownloadDir"
|
||||
NZBPP_DIRECTORY=$TvDownloadDir
|
||||
cd "$NZBPP_DIRECTORY"
|
||||
fi
|
||||
fi
|
||||
# Test for category and ensure the passed directory exists as a directory.
|
||||
if [ "$NZBPP_CATEGORY" = "$CouchPotatoCategory" -a -d "$MoviesDownloadDir" ]; then
|
||||
echo "[INFO] Post-Process: Moving Movies to $MoviesDownloadDir"
|
||||
cp -R "$NZBPP_DIRECTORY" "$MoviesDownloadDir"
|
||||
mv $NZBPP_DIRECTORY $MoviesDownloadDir
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo "[ERROR] Post-Process: Moving to $MoviesDownloadDir"
|
||||
exit $POSTPROCESS_ERROR
|
||||
else
|
||||
rm -fr *
|
||||
cd ..
|
||||
rmdir "$NZBPP_DIRECTORY"
|
||||
NZBPP_DIRECTORY="$MoviesDownloadDir"
|
||||
NZBPP_DIRECTORY=$MoviesDownloadDir
|
||||
cd "$NZBPP_DIRECTORY"
|
||||
fi
|
||||
fi
|
||||
# Test for category and ensure the passed directory exists as a directory.
|
||||
if [ "$NZBPP_CATEGORY" = "$CustomCategory" -a -d "$CustomDownloadDir" ]; then
|
||||
echo "[INFO] Post-Process: Moving $CustomCategory to $CustomDownloadDir"
|
||||
cp -R "$NZBPP_DIRECTORY" "$CustomDownloadDir"
|
||||
mv $NZBPP_DIRECTORY $CustomDownloadDir
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo "[ERROR] Post-Process: Moving to $CustomDownloadDir"
|
||||
exit $POSTPROCESS_ERROR
|
||||
else
|
||||
rm -fr *
|
||||
cd ..
|
||||
rmdir "$NZBPP_DIRECTORY"
|
||||
NZBPP_DIRECTORY="$CustomDownloadDir"
|
||||
NZBPP_DIRECTORY=$CustomDownloadDir
|
||||
cd "$NZBPP_DIRECTORY"
|
||||
fi
|
||||
fi
|
||||
|
@ -501,7 +494,7 @@ if [ "$NZBPR_DestDir" != "" ]; then
|
|||
cd ..
|
||||
rmdir $NZBPP_DIRECTORY
|
||||
NZBPP_DIRECTORY=$NZBPR_DestDir
|
||||
cd "$NZBPP_DIRECTORY"
|
||||
cd $NZBPP_DIRECTORY
|
||||
fi
|
||||
|
||||
# All OK, requesting cleaning up of download queue
|
||||
|
|
|
@ -124,11 +124,11 @@ DestDir=
|
|||
# be sent via email.
|
||||
# This uses sendEmail as authored by Brandon Zehm <caspian@dotconf.net>
|
||||
|
||||
# Specify if you want emails to be sent for successful downloads (yes, no).
|
||||
Email_successful=yes
|
||||
# List Categories for successful download email, default 'tv movies'
|
||||
Email_successful='tv movies'
|
||||
|
||||
# Specify if you want emails to be sent for failed downloads (yes, no).
|
||||
Email_failed=yes
|
||||
# List Categories for failed download email, default 'tv movies'
|
||||
Email_failed='tv movies'
|
||||
|
||||
# Set the full path and file name for sendEmail application.
|
||||
sendEmail=/usr/local/nzbget/var/sendEmail/sendEmail
|
||||
|
|
0
nzbget-postprocessing-files/sendEmail/sendEmail
Normal file → Executable file
0
nzbget-postprocessing-files/sendEmail/sendEmail
Normal file → Executable file
Loading…
Add table
Add a link
Reference in a new issue