diff --git a/.gitignore b/.gitignore index a9ed5401..d47fee77 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,6 @@ autoProcessMedia.cfg *.pyc *.pyo -postprocess.log +postprocess.log* /.idea/ *.cfg.old diff --git a/DeleteSamples.py b/DeleteSamples.py index 4386af29..67e70550 100644 --- a/DeleteSamples.py +++ b/DeleteSamples.py @@ -31,8 +31,12 @@ ############################################################################## import os import sys -from nzbtomedia.nzbToMediaConfig import config +# NZBGet argv: all passed as environment variables. +# Exit codes used by NZBGet +POSTPROCESS_SUCCESS=93 +POSTPROCESS_ERROR=94 +POSTPROCESS_NONE=95 def is_sample(filePath, inputName, maxSampleSize, SampleIDs): # 200 MB in bytes @@ -58,13 +62,13 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5 if os.environ['NZBOP_UNPACK'] != 'yes': print "Please enable option \"Unpack\" in nzbget configuration file, exiting." - sys.exit(config.NZBGET_POSTPROCESS_ERROR) + sys.exit(POSTPROCESS_ERROR) # Check par status if os.environ['NZBPP_PARSTATUS'] == '3': print "Par-check successful, but Par-repair disabled, exiting." print "Please check your Par-repair settings for future downloads." - sys.exit(config.NZBGET_POSTPROCESS_NONE) + sys.exit(POSTPROCESS_NONE) if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4': print "Par-repair failed, setting status \"failed\"." @@ -95,7 +99,7 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5 # All checks done, now launching the script. if status == 1: - sys.exit(config.NZBGET_POSTPROCESS_NONE) + sys.exit(POSTPROCESS_NONE) mediaContainer = os.environ['NZBPO_MEDIAEXTENSIONS'].split(',') SampleIDs = os.environ['NZBPO_SAMPLEIDS'].split(',') @@ -112,8 +116,8 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5 os.unlink(filePath) except: print "Error: unable to delete file", filePath - sys.exit(config.NZBGET_POSTPROCESS_ERROR) - sys.exit(config.NZBGET_POSTPROCESS_SUCCESS) + sys.exit(POSTPROCESS_ERROR) + sys.exit(POSTPROCESS_SUCCESS) else: print "This script can only be called from NZBGet (11.0 or later)." diff --git a/ResetDateTime.py b/ResetDateTime.py index 20ac62ca..5d7c01c4 100644 --- a/ResetDateTime.py +++ b/ResetDateTime.py @@ -17,7 +17,12 @@ # Check if the script is called from nzbget 11.0 or later import os import sys -from nzbtomedia.nzbToMediaConfig import config + +# NZBGet argv: all passed as environment variables. +# Exit codes used by NZBGet +POSTPROCESS_SUCCESS=93 +POSTPROCESS_ERROR=94 +POSTPROCESS_NONE=95 if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5] < '11.0': print "Script triggered from NZBGet (11.0 or later)." @@ -27,13 +32,13 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5 if os.environ['NZBOP_UNPACK'] != 'yes': print "Please enable option \"Unpack\" in nzbget configuration file, exiting." - sys.exit(config.NZBGET_POSTPROCESS_ERROR) + sys.exit(POSTPROCESS_ERROR) # Check par status if os.environ['NZBPP_PARSTATUS'] == '3': print "Par-check successful, but Par-repair disabled, exiting." print "Please check your Par-repair settings for future downloads." - sys.exit(config.NZBGET_POSTPROCESS_NONE) + sys.exit(POSTPROCESS_NONE) if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4': print "Par-repair failed, setting status \"failed\"." @@ -64,7 +69,7 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5 # All checks done, now launching the script. if status == 1: - sys.exit(config.NZBGET_POSTPROCESS_NONE) + sys.exit(POSTPROCESS_NONE) directory = os.path.normpath(os.environ['NZBPP_DIRECTORY']) for dirpath, dirnames, filenames in os.walk(directory): @@ -76,8 +81,8 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5 continue except: print "Error: unable to reset time for file", file - sys.exit(config.NZBGET_POSTPROCESS_ERROR) - sys.exit(config.NZBGET_POSTPROCESS_SUCCESS) + sys.exit(POSTPROCESS_ERROR) + sys.exit(POSTPROCESS_SUCCESS) else: print "This script can only be called from NZBGet (11.0 or later)." diff --git a/TorrentToMedia.py b/TorrentToMedia.py index 322ee7bc..d8897b9f 100755 --- a/TorrentToMedia.py +++ b/TorrentToMedia.py @@ -140,14 +140,8 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID): Logger.debug("MAIN: Scanning files in directory: %s", inputDirectory) - if inputCategory in hpCategory: - noFlatten.extend(hpCategory) # Make sure we preserve folder structure for HeadPhones. - if useLink in ['sym','move']: # These don't work for HeadPhones. - useLink = 'no' # default to copy. - - if inputCategory in sbCategory and fork in config.SICKBEARD_TORRENT: # Don't flatten when sending to SICKBEARD_TORRENT - noFlatten.extend(sbCategory) - + noFlatten.extend(hpCategory) # Make sure we preserve folder structure for HeadPhones. + outputDestinationMaster = outputDestination # Save the original, so we can change this within the loop below, and reset afterwards. now = datetime.datetime.now() for dirpath, dirnames, filenames in os.walk(inputDirectory): @@ -187,15 +181,6 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID): else: continue # This file has not been recently moved or created, skip it - if inputCategory in sbCategory and fork in config.SICKBEARD_TORRENT: # We want to link every file. - Logger.info("MAIN: Found file %s in %s", fileExtension, filePath) - try: - copy_link(filePath, targetDirectory, useLink, outputDestination) - copy_list.append([filePath, os.path.join(outputDestination, file)]) - except: - Logger.exception("MAIN: Failed to link file: %s", file) - continue - if fileExtension in mediaContainer: # If the file is a video file if is_sample(filePath, inputName, minSampleSize, SampleIDs) and not inputCategory in hpCategory: # Ignore samples Logger.info("MAIN: Ignoring sample file: %s ", filePath) @@ -217,13 +202,6 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID): Logger.exception("MAIN: Failed to link file: %s", file) continue elif fileExtension in compressedContainer: - if inputCategory in hpCategory: # We need to link all files for HP in order to move these back to support seeding. - Logger.info("MAIN: Linking compressed archive file %s for file %s", fileExtension, filePath) - try: - copy_link(filePath, targetDirectory, useLink, outputDestination) - copy_list.append([filePath, os.path.join(outputDestination, file)]) - except: - Logger.exception("MAIN: Failed to link file: %s", file) # find part numbers in second "extension" from right, if we have more than 1 compressed file in the same directory. if re.search(r'\d+', os.path.splitext(fileName)[1]) and os.path.dirname(filePath) in extracted_folder and not any(item in os.path.splitext(fileName)[1] for item in ['.720p','.1080p','.x264']): part = int(re.search(r'\d+', os.path.splitext(fileName)[1]).group()) @@ -234,10 +212,7 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID): continue Logger.info("MAIN: Found compressed archive %s for file %s", fileExtension, filePath) try: - if inputCategory in hpCategory: # HP needs to scan the same dir as passed to downloader. - extractor.extract(filePath, inputDirectory) - else: - extractor.extract(filePath, outputDestination) + extractor.extract(filePath, outputDestination) extractionSuccess = True # we use this variable to determine if we need to pause a torrent or not in uTorrent (don't need to pause archived content) extracted_folder.append(os.path.dirname(filePath)) except: @@ -257,7 +232,7 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID): flatten(outputDestination) # Now check if movie files exist in destination: - if inputCategory in cpsCategory + sbCategory and not (inputCategory in sbCategory and fork in config.SICKBEARD_TORRENT): + if inputCategory in cpsCategory + sbCategory: for dirpath, dirnames, filenames in os.walk(outputDestination): for file in filenames: filePath = os.path.join(dirpath, file) @@ -277,11 +252,6 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID): else: Logger.debug("MAIN: Found %s media files in output. %s were found in input", str(video2), str(video)) - if inputCategory in sbCategory and fork in config.SICKBEARD_TORRENT: - if len(copy_list) > 0: - Logger.debug("MAIN: Found and linked %s files", str(len(copy_list))) - status = int(0) - processCategories = cpsCategory + sbCategory + hpCategory + mlCategory + gzCategory if (inputCategory in user_script_categories and not "NONE" in user_script_categories) or ("ALL" in user_script_categories and not inputCategory in processCategories): @@ -315,25 +285,6 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID): if result == 1: Logger.info("MAIN: A problem was reported in the autoProcess* script. If torrent was paused we will resume seeding") - if inputCategory in hpCategory: - # we need to move the output dir files back... - Logger.debug("MAIN: Moving temporary HeadPhones files back to allow seeding.") - for item in copy_list: - if os.path.isfile(os.path.normpath(item[1])): # check to ensure temp files still exist. - if os.path.isfile(os.path.normpath(item[0])): # both exist, remove temp version - Logger.debug("MAIN: File %s still present. Removing tempoary file %s", str(item[0]), str(item[1])) - os.unlink(os.path.normpath(item[1])) - continue - else: # move temp version back to allow seeding or Torrent removal. - Logger.debug("MAIN: Moving %s to %s", str(item[1]), str(item[0])) - newDestination = os.path.split(os.path.normpath(item[0])) - try: - copy_link(os.path.normpath(item[1]), os.path.normpath(item[0]), 'move', newDestination[0]) - except: - Logger.exception("MAIN: Failed to move file: %s", file) - continue - shutil.rmtree(outputDestination) - # Hardlink solution for uTorrent, need to implent support for deluge, transmission if clientAgent in ['utorrent', 'transmission', 'deluge'] and inputHash: # Delete torrent and torrentdata from Torrent client if processing was successful. @@ -493,10 +444,9 @@ if __name__ == "__main__": minSampleSize = int(config().get("Extensions", "minSampleSize")) # 200 (in MB) SampleIDs = (config().get("Extensions", "SampleIDs")).split(',') # sample,-s. - Torrent_ForceLink = int(config().get("SickBeard", "Torrent_ForceLink")) # 1 - cpsCategory = (config().get("CouchPotato", "cpsCategory")).split(',') # movie sbCategory = (config().get("SickBeard", "sbCategory")).split(',') # tv + Torrent_NoLink = int(config().get("SickBeard", "Torrent_NoLink")) # 0 hpCategory = (config().get("HeadPhones", "hpCategory")).split(',') # music mlCategory = (config().get("Mylar", "mlCategory")).split(',') # comics gzCategory = (config().get("Gamez", "gzCategory")).split(',') # games diff --git a/autoProcessMedia.cfg.sample b/autoProcessMedia.cfg.sample index 0c779f3b..a18d652e 100644 --- a/autoProcessMedia.cfg.sample +++ b/autoProcessMedia.cfg.sample @@ -37,7 +37,7 @@ watch_dir = fork = auto delete_failed = 0 nzbExtractionBy = Downloader -Torrent_ForceLink = 1 +Torrent_NoLink = 0 process_method = [HeadPhones] diff --git a/changelog.txt b/changelog.txt index 09efd408..2344c650 100644 --- a/changelog.txt +++ b/changelog.txt @@ -7,7 +7,9 @@ Allow Headphones to remove torrents and data after processing. Delete torrent if uselink = move Added forceClean for outputDir. Works in file permissions prevent CP/SB from moving files. Ignore .x264 from archive "part" checks. -Added dynamic timeout based on directory size. +Changed handling of TPB/Pistachitos SB forks. Default is to link/extract here. Disabled by Torrent_NoLink = 1. +Changed handling for HeadPhones Now that HeadPhones allows process directory to be defined. + Impacts NZBs Fix setting of Mylar config from NZBGet. @@ -16,6 +18,8 @@ Impacts All Changes to Couchpotato API for [nosql] added. Keeps aligned with current CouchPotato develop branch. Add Auto Detection of SickBeard Fork. Thanks @echel0n Added config class, re-coded migratecfg, misc bugfixes and code cleanup. Thanks @echel0n +Added dynamic timeout based on directory size. +Added process_Method for SickBeard. V9.2 05/03/2014 diff --git a/nzbToCouchPotato.py b/nzbToCouchPotato.py index 566e650c..effd3793 100755 --- a/nzbToCouchPotato.py +++ b/nzbToCouchPotato.py @@ -72,7 +72,7 @@ # Media Extensions # -# This is a list of media extensions that may be transcoded if transcoder is enabled below. +# This is a list of media extensions that are used to verify that the download does contain valid media. #mediaExtensions=.mkv,.avi,.divx,.xvid,.mov,.wmv,.mp4,.mpg,.mpeg,.vob,.iso ## Transcoder diff --git a/nzbToMedia.py b/nzbToMedia.py index 2ce69185..834c42a3 100755 --- a/nzbToMedia.py +++ b/nzbToMedia.py @@ -222,7 +222,7 @@ # Media Extensions # -# This is a list of media extensions that may be transcoded if transcoder is enabled below. +# This is a list of media extensions that are used to verify that the download does contain valid media. #mediaExtensions=.mkv,.avi,.divx,.xvid,.mov,.wmv,.mp4,.mpg,.mpeg,.vob,.iso ## Transcoder @@ -473,6 +473,8 @@ else: if process(get_dirnames("Gamez", gzCategory[0]), inputName=get_dirnames("Gamez", gzCategory[0]), status=0,clientAgent="manual", inputCategory=gzCategory[0]) != 0: Logger.info("MAIN: A problem was reported in the autoProcessGames script.") + result = 0 + if result == 0: Logger.info("MAIN: The nzbToMedia script completed successfully.") if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 @@ -480,4 +482,4 @@ if result == 0: else: Logger.info("MAIN: A problem was reported in the nzbToMedia script.") if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 - sys.exit(config.NZBGET_POSTPROCESS_ERROR) \ No newline at end of file + sys.exit(config.NZBGET_POSTPROCESS_ERROR) diff --git a/nzbToSickBeard.py b/nzbToSickBeard.py index d487fffa..08f59ac3 100755 --- a/nzbToSickBeard.py +++ b/nzbToSickBeard.py @@ -75,7 +75,7 @@ # Media Extensions # -# This is a list of media extensions that may be transcoded if transcoder is enabled below. +# This is a list of media extensions that are used to verify that the download does contain valid media. #mediaExtensions=.mkv,.avi,.divx,.xvid,.mov,.wmv,.mp4,.mpg,.mpeg,.vob,.iso ## Transcoder @@ -227,11 +227,11 @@ elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS: clientAgent = "sabnzbd" result = autoProcessTV().processEpisode(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5]) else: - result = 0 - Logger.debug("MAIN: Invalid number of arguments received from client.") Logger.info("MAIN: Running autoProcessTV as a manual run...") + sbCategory = (config().get("SickBeard", "sbCategory")).split(',') # tv + result = 1 for dirName in get_dirnames("SickBeard", sbCategory[0]): Logger.info("MAIN: Calling Sick-Beard to post-process: %s", dirName) result = autoProcessTV().processEpisode(dirName, dirName, 0) diff --git a/nzbtomedia/autoProcess/autoProcessMusic.py b/nzbtomedia/autoProcess/autoProcessMusic.py index 9a157797..2790ef8e 100644 --- a/nzbtomedia/autoProcess/autoProcessMusic.py +++ b/nzbtomedia/autoProcess/autoProcessMusic.py @@ -55,7 +55,7 @@ class autoProcessMusic: dirSize = getDirectorySize(dirName) # get total directory size to calculate needed processing time. TIME_OUT = int(TimePerGiB) * dirSize # HeadPhones needs to complete all moving/transcoding and renaming before returning the status. TIME_OUT += 60 # Add an extra minute for over-head/processing/metadata. - socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout. + socket.setdefaulttimeout(int(TIME_OUT)) #initialize socket timeout. baseURL = protocol + host + ":" + port + web_root + "/api?apikey=" + apikey + "&cmd=" diff --git a/nzbtomedia/autoProcess/autoProcessTV.py b/nzbtomedia/autoProcess/autoProcessTV.py index 40cb3f98..25645216 100644 --- a/nzbtomedia/autoProcess/autoProcessTV.py +++ b/nzbtomedia/autoProcess/autoProcessTV.py @@ -74,6 +74,11 @@ class autoProcessTV: process_method = config().get(section, "process_method") except config.NoOptionError: process_method = None + try: + Torrent_NoLink = int(config().get(section, "Torrent_NoLink")) + except (config.NoOptionError, ValueError): + Torrent_NoLink = 0 + mediaContainer = (config().get("Extensions", "mediaExtensions")).split(',') minSampleSize = int(config().get("Extensions", "minSampleSize")) @@ -121,7 +126,7 @@ class autoProcessTV: dirSize = getDirectorySize(dirName) # get total directory size to calculate needed processing time. TIME_OUT = int(TimePerGiB) * dirSize # SickBeard needs to complete all moving and renaming before returning the log sequence via url. TIME_OUT += 60 # Add an extra minute for over-head/processing/metadata. - socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout. + socket.setdefaulttimeout(int(TIME_OUT)) #initialize socket timeout. # configure SB params to pass params['quiet'] = 1 @@ -136,6 +141,8 @@ class autoProcessTV: params[param] = dirName if param == "process_method": + if fork in SICKBEARD_TORRENT and Torrent_NoLink == 1 and not clientAgent in ['nzbget','sabnzbd']: #use default SickBeard settings here. + del params[param] if process_method: params[param] = process_method else: diff --git a/nzbtomedia/migratecfg.py b/nzbtomedia/migratecfg.py index a407d6fb..6850c85e 100644 --- a/nzbtomedia/migratecfg.py +++ b/nzbtomedia/migratecfg.py @@ -52,6 +52,8 @@ class migratecfg: value = "auto" if option == "fork" and value not in ["default", "failed", "failed-torrent", "auto"]: value = "auto" + if option == "Torrent_ForceLink": + continue if option == "outputDirectory": # move this to new location format value = os.path.split(os.path.normpath(value))[0] confignew.set("Torrent", option, value) diff --git a/nzbtomedia/nzbToMediaAutoFork.py b/nzbtomedia/nzbToMediaAutoFork.py index 6c29e381..dc6f2306 100644 --- a/nzbtomedia/nzbToMediaAutoFork.py +++ b/nzbtomedia/nzbToMediaAutoFork.py @@ -6,7 +6,8 @@ from nzbToMediaConfig import config def autoFork(section): Logger = logging.getLogger() - + if not config().has_section(section): + section = "SickBeard" # config settings host = config().get(section, "host") port = config().get(section, "port") diff --git a/nzbtomedia/nzbToMediaUtil.py b/nzbtomedia/nzbToMediaUtil.py index 95a7110e..985b8ecc 100644 --- a/nzbtomedia/nzbToMediaUtil.py +++ b/nzbtomedia/nzbToMediaUtil.py @@ -465,12 +465,15 @@ def get_dirnames(section, category): dirNames = [] if watch_dir != "": if os.path.exists(watch_dir): - dirNames = [os.path.join(watch_dir, o) for o in os.listdir(watch_dir) if - os.path.isdir(os.path.join(watch_dir, o))] - elif outputDirectory != "": + dirNames.extend([os.path.join(watch_dir, o) for o in os.listdir(watch_dir) if + os.path.isdir(os.path.join(watch_dir, o))]) + if outputDirectory != "": if os.path.exists(outputDirectory): - dirNames = [os.path.join(outputDirectory, o) for o in os.listdir(outputDirectory) if - os.path.isdir(os.path.join(outputDirectory, o))] + dirNames.extend([os.path.join(outputDirectory, o) for o in os.listdir(outputDirectory) if + os.path.isdir(os.path.join(outputDirectory, o))]) + + if not dirNames: + Logger.warn("No Directories identified to Scan.") return dirNames