Updated logger code to now include the section, formatting has been modified as well.

Logging of debug messages is now optional via log_debug option location in autoProcessMedia.cfg

Lots of code cleanup has been performed including cleanup log messages and corrections of spelling errors.

Improved release lookup code for autoProcessMovie, narrows search results down by making API calls to the download clients to compare results in CouchPotato's database.
This commit is contained in:
echel0n 2014-04-18 13:16:18 -07:00
parent dd41ff3b2f
commit eb7822b60b
16 changed files with 420 additions and 441 deletions

View file

@ -28,11 +28,11 @@ def processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID,
extracted_folder = []
copy_list = []
logger.debug("Received Directory: %s | Name: %s | Category: %s", inputDirectory, inputName, inputCategory)
logger.debug("Received Directory: %s | Name: %s | Category: %s" % (inputDirectory, inputName, inputCategory))
inputDirectory, inputName, inputCategory, root, single = category_search(inputDirectory, inputName, inputCategory, root, nzbtomedia.CATEGORIES) # Confirm the category by parsing directory structure
logger.debug("Determined Directory: %s | Name: %s | Category: %s", inputDirectory, inputName, inputCategory)
logger.debug("Determined Directory: %s | Name: %s | Category: %s" % (inputDirectory, inputName, inputCategory))
TorrentClass = None
if clientAgent != 'manual':
@ -44,7 +44,7 @@ def processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID,
if inputCategory == "":
inputCategory = "UNCAT"
outputDestination = os.path.normpath(os.path.join(nzbtomedia.OUTPUTDIRECTORY, inputCategory, safeName(inputName)))
logger.postprocess("Output directory set to: %s", outputDestination)
logger.postprocess("Output directory set to: %s" % (outputDestination))
if nzbtomedia.CFG["SickBeard"][inputCategory]:
Torrent_NoLink = int(nzbtomedia.CFG["SickBeard"][inputCategory]["Torrent_NoLink"]) # 0
@ -67,10 +67,10 @@ def processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID,
processOnly.extend(nzbtomedia.USER_SCRIPT_CATEGORIES) # Adds all categories to be processed by userscript.
if not inputCategory in processOnly:
logger.postprocess("No processing to be done for category: %s. Exiting", inputCategory)
logger.postprocess("No processing to be done for category: %s. Exiting" % (inputCategory))
return
logger.debug("Scanning files in directory: %s", inputDirectory)
logger.debug("Scanning files in directory: %s" % (inputDirectory))
if nzbtomedia.CFG["HeadPhones"][inputCategory]:
nzbtomedia.NOFLATTEN.extend(nzbtomedia.CFG["HeadPhones"].sections) # Make sure we preserve folder structure for HeadPhones.
@ -82,7 +82,7 @@ def processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID,
if single:
dirnames[:] = []
filenames[:] = [filenames] # we just want to work with this one file if single = True
logger.debug("Found %s files in %s", str(len(filenames)), dirpath)
logger.debug("Found %s files in %s" % (str(len(filenames)), dirpath))
for file in filenames:
filePath = os.path.join(dirpath, file)
fileName, fileExtension = os.path.splitext(file)
@ -92,17 +92,17 @@ def processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID,
if len(newDir) > 0 and newDir[0] == "/":
newDir = newDir[1:] # remove leading "/" to enable join to work.
outputDestination = os.path.join(outputDestinationMaster, newDir) # join this extra directory to output.
logger.debug("Setting outputDestination to %s to preserve folder structure", outputDestination)
logger.debug("Setting outputDestination to %s to preserve folder structure" % (outputDestination))
targetDirectory = os.path.join(outputDestination, file)
if root == 1:
if foundFile == int(0):
logger.debug("Looking for %s in: %s", inputName, file)
logger.debug("Looking for %s in: %s" % (inputName, file))
if (safeName(inputName) in safeName(file)) or (safeName(fileName) in safeName(inputName)):
#pass # This file does match the Torrent name
foundFile = 1
logger.debug("Found file %s that matches Torrent Name %s", file, inputName)
logger.debug("Found file %s that matches Torrent Name %s" % (file, inputName))
else:
continue # This file does not match the Torrent name, skip it
@ -114,13 +114,13 @@ def processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID,
if (mtime_lapse < datetime.timedelta(minutes=5)) or (ctime_lapse < datetime.timedelta(minutes=5)):
#pass # This file does match the date time criteria
foundFile = 1
logger.debug("Found file %s with date modifed/created less than 5 minutes ago.", file)
logger.debug("Found file %s with date modifed/created less than 5 minutes ago." % (file))
else:
continue # This file has not been recently moved or created, skip it
if fileExtension in nzbtomedia.MEDIACONTAINER and is_sample(filePath, inputName, nzbtomedia.MINSAMPLESIZE,
nzbtomedia.SAMPLEIDS) and not nzbtomedia.CFG["HeadPhones"][inputCategory]: # Ignore samples
logger.postprocess("Ignoring sample file: %s ", filePath)
logger.postprocess("Ignoring sample file: %s " % (filePath))
continue
if fileExtension in nzbtomedia.COMPRESSEDCONTAINER:
@ -129,24 +129,24 @@ def processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID,
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())
if part == 1: # we only want to extract the primary part.
logger.debug("Found primary part of a multi-part archive %s. Extracting", file)
logger.debug("Found primary part of a multi-part archive %s. Extracting" % (file))
else:
logger.debug("Found part %s of a multi-part archive %s. Ignoring", part, file)
logger.debug("Found part %s of a multi-part archive %s. Ignoring" % (part, file))
continue
logger.postprocess("Found compressed archive %s for file %s", fileExtension, filePath)
logger.postprocess("Found compressed archive %s for file %s" % (fileExtension, filePath))
try:
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:
logger.error("Extraction failed for: %s", file)
logger.error("Extraction failed for: %s" % (file))
continue
try:
copy_link(filePath, targetDirectory, nzbtomedia.USELINK, outputDestination)
copy_list.append([filePath, os.path.join(outputDestination, file)])
except:
logger.error("Failed to link file: %s", file)
logger.error("Failed to link file: %s" % (file))
outputDestination = outputDestinationMaster # Reset here.
if not inputCategory in nzbtomedia.NOFLATTEN: #don't flatten hp in case multi cd albums, and we need to copy this back later.
@ -162,21 +162,21 @@ def processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID,
filePath = os.path.join(dirpath, file)
fileName, fileExtension = os.path.splitext(file)
if fileExtension in nzbtomedia.MEDIACONTAINER: # If the file is a video file
logger.debug("Found media file: %s", filePath)
logger.debug("Found media file: %s" % (filePath))
video += 1
if fileExtension in nzbtomedia.COMPRESSEDCONTAINER: # If the file is an archive file
archive += 1
if video > int(0): # Check that media files exist
logger.debug("Found %s media files", str(video))
logger.debug("Found %s media files" % (str(video)))
status = int(0)
elif not (nzbtomedia.CFG["SickBeard"][inputCategory] and nzbtomedia.CFG["SickBeard"][inputCategory]["nzbExtractionBy"] == "Destination") and archive > int(0):
logger.debug("Found %s archive files to be extracted by SickBeard", str(archive))
logger.debug("Found %s archive files to be extracted by SickBeard" % (str(archive)))
status = int(0)
else:
logger.warning("Found no media files in output.")
if (inputCategory in nzbtomedia.USER_SCRIPT_CATEGORIES and not "NONE" in nzbtomedia.USER_SCRIPT_CATEGORIES) or ("ALL" in nzbtomedia.USER_SCRIPT_CATEGORIES and not inputCategory in processCategories):
logger.postprocess("Processing user script %s.", nzbtomedia.USER_SCRIPT)
logger.postprocess("Processing user script %s." % (nzbtomedia.USER_SCRIPT))
result = external_script(outputDestination,inputName,inputCategory)
elif status == int(0) or (nzbtomedia.CFG['HeadPhones','Mylar','Gamez'][inputCategory]): # if movies linked/extracted or for other categories.
logger.debug("Calling autoProcess script for successful download.")
@ -187,23 +187,23 @@ def processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID,
result = 0
if nzbtomedia.CFG['CouchPotato'][inputCategory]:
logger.postprocess("Calling CouchPotato:" + inputCategory + " to post-process: %s", inputName)
logger.postprocess("Calling CouchPotato:" + inputCategory + " to post-process: %s" % (inputName))
download_id = inputHash
result = autoProcessMovie().process(outputDestination, inputName, status, clientAgent, download_id, inputCategory)
elif nzbtomedia.CFG['SickBeard'][inputCategory]:
logger.postprocess("Calling Sick-Beard:" + inputCategory + " to post-process: %s", inputName)
logger.postprocess("Calling Sick-Beard:" + inputCategory + " to post-process: %s" % (inputName))
result = autoProcessTV().processEpisode(outputDestination, inputName, status, clientAgent, inputCategory)
elif nzbtomedia.CFG['NzbDrone'][inputCategory]:
logger.postprocess("Calling NzbDrone:" + inputCategory + " to post-process: %s", inputName)
logger.postprocess("Calling NzbDrone:" + inputCategory + " to post-process: %s" % (inputName))
result = autoProcessTV().processEpisode(outputDestination, inputName, status, clientAgent, inputCategory)
elif nzbtomedia.CFG['HeadPhones'][inputCategory]:
logger.postprocess("Calling HeadPhones:" + inputCategory + " to post-process: %s", inputName)
logger.postprocess("Calling HeadPhones:" + inputCategory + " to post-process: %s" % (inputName))
result = autoProcessMusic().process(outputDestination, inputName, status, clientAgent, inputCategory)
elif nzbtomedia.CFG['Mylar'][inputCategory]:
logger.postprocess("Calling Mylar:" + inputCategory + " to post-process: %s", inputName)
logger.postprocess("Calling Mylar:" + inputCategory + " to post-process: %s" % (inputName))
result = autoProcessComics().processEpisode(outputDestination, inputName, status, clientAgent, inputCategory)
elif nzbtomedia.CFG['Gamez'][inputCategory]:
logger.postprocess("Calling Gamez:" + inputCategory + " to post-process: %s", inputName)
logger.postprocess("Calling Gamez:" + inputCategory + " to post-process: %s" % (inputName))
result = autoProcessGames().process(outputDestination, inputName, status, clientAgent, inputCategory)
if result == 1 and clientAgent != 'manual':
@ -255,19 +255,19 @@ def external_script(outputDestination, torrentName, torrentLabel):
cmd = ""
for item in command:
cmd = cmd + " " + item
logger.postprocess("Running script %s on file %s.", cmd, filePath)
logger.postprocess("Running script %s on file %s." % (cmd, filePath))
try:
p = Popen(command)
res = p.wait()
if str(res) in nzbtomedia.USER_SCRIPT_SUCCESSCODES: # Linux returns 0 for successful.
logger.postprocess("UserScript %s was successfull", command[0])
logger.postprocess("UserScript %s was successfull" % (command[0]))
result = int(0)
else:
logger.error("UserScript %s has failed with return code: %s", command[0], res)
logger.postprocess("If the UserScript completed successfully you should add %s to the user_script_successCodes", res)
logger.error("UserScript %s has failed with return code: %s" % (command[0], res))
logger.postprocess("If the UserScript completed successfully you should add %s to the user_script_successCodes" % (res))
result = int(1)
except:
logger.error("UserScript %s has failed", command[0])
logger.error("UserScript %s has failed" % (command[0]))
result = int(1)
final_result = final_result + result
@ -282,10 +282,10 @@ def external_script(outputDestination, torrentName, torrentLabel):
num_files_new = num_files_new + 1
if nzbtomedia.USER_SCRIPT_CLEAN == int(1) and num_files_new == int(0) and final_result == int(0):
logger.postprocess("All files have been processed. Cleaning outputDirectory %s", outputDestination)
logger.postprocess("All files have been processed. Cleaning outputDirectory %s" % (outputDestination))
shutil.rmtree(outputDestination)
elif nzbtomedia.USER_SCRIPT_CLEAN == int(1) and num_files_new != int(0):
logger.postprocess("%s files were processed, but %s still remain. outputDirectory will not be cleaned.", num_files, num_files_new)
logger.postprocess("%s files were processed, but %s still remain. outputDirectory will not be cleaned." % (num_files, num_files_new))
return final_result
def main(args):
@ -296,11 +296,11 @@ def main(args):
clientAgent = nzbtomedia.TORRENT_CLIENTAGENT
logger.postprocess("#########################################################")
logger.postprocess("## ..::[%s]::.. CLIENT:%s ## STARTING", args[0], clientAgent)
logger.postprocess("## ..::[%s]::.. CLIENT:%s ## STARTING" % (args[0], clientAgent))
logger.postprocess("#########################################################")
# debug command line options
logger.debug("Options passed into TorrentToMedia: %s", args)
logger.debug("Options passed into TorrentToMedia: %s" % (args))
# Post-Processing Result
result = 0
@ -325,18 +325,18 @@ def main(args):
if nzbtomedia.CFG[section][category].isenabled():
dirNames = get_dirnames(section, category)
for dirName in dirNames:
logger.postprocess("Running %s:%s as a manual run for folder %s ...", section, category, dirName)
logger.postprocess("Running %s:%s as a manual run for folder %s ..." % (section, category, dirName))
results = processTorrent(dirName, os.path.basename(dirName), category, inputHash, inputID, clientAgent)
if results != 0:
result = results
logger.error("A problem was reported when trying to manually run %s:%s.", section, category)
logger.error("A problem was reported when trying to manually run %s:%s." % (section, category))
else:
logger.warning("%s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
logger.warning("%s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ..." % (section, category))
if result == 0:
logger.postprocess("The %s script completed successfully.", args[0])
logger.postprocess("The %s script completed successfully." % (args[0]))
else:
logger.error("A problem was reported in the %s script.", args[0])
logger.error("A problem was reported in the %s script." % (args[0]))
sys.exit(result)

View file

@ -8,6 +8,7 @@
git_user =
git_branch =
force_clean = 0
log_debug = 0
[CouchPotato]
#### autoProcessing for Movies

View file

@ -286,27 +286,25 @@ from nzbtomedia import logger
# post-processing
def process(nzbDir, inputName=None, status=0, clientAgent='manual', download_id=None, inputCategory=None):
result = 0
# auto-detect section
section = nzbtomedia.CFG.findsection(inputCategory)
if section:
logger.info("Sending %s to %s for post-processing ..." % (inputName, str(section).upper()))
else:
logger.error("We could not find a section with containing a download category labeled %s in your autoProcessMedia.cfg, Exiting!" % inputCategory)
if nzbtomedia.CFG["CouchPotato"][inputCategory]:
logger.postprocess("Calling CouchPotatoServer to post-process: %s", inputName)
result = autoProcessMovie().process(nzbDir, inputName, status, clientAgent, download_id, inputCategory)
elif nzbtomedia.CFG["SickBeard", "NzbDrone"][inputCategory]:
logger.postprocess("Calling Sick-Beard to post-process: %s", inputName)
result = autoProcessTV().processEpisode(nzbDir, inputName, status, clientAgent, inputCategory)
elif nzbtomedia.CFG["HeadPhones"][inputCategory]:
logger.postprocess("Calling HeadPhones to post-process: %s", inputName)
result = autoProcessMusic().process(nzbDir, inputName, status, clientAgent, inputCategory)
elif nzbtomedia.CFG["Mylar"][inputCategory]:
logger.postprocess("Calling Mylar to post-process: %s", inputName)
result = autoProcessComics().processEpisode(nzbDir, inputName, status, clientAgent, inputCategory)
elif nzbtomedia.CFG["Gamez"][inputCategory]:
logger.postprocess("Calling Gamez to post-process: %s", inputName)
result = autoProcessGames().process(nzbDir, inputName, status, clientAgent, inputCategory)
else:
logger.postprocess("We could not find a section with the download category of %s in your autoProcessMedia.cfg. Exiting.", inputCategory)
result = -1
if result == 0:
# Clean up any leftover files
@ -321,22 +319,21 @@ def main(args, section=None):
# clientAgent for NZBs
clientAgent = nzbtomedia.NZB_CLIENTAGENT
logger.postprocess("#########################################################")
logger.postprocess("## ..::[%s]::.. CLIENT:%s ## STARTING", args[0], clientAgent)
logger.postprocess("#########################################################")
logger.info("#########################################################")
logger.info("## ..::[%s]::.. ##" % os.path.basename(__file__))
logger.info("#########################################################")
# debug command line options
logger.debug("Options passed into nzbToMedia: %s", args)
logger.debug("Options passed into nzbToMedia: %s" % args)
# Post-Processing Result
result = 0
status = 0
# NZBGet V11+
# Check if the script is called from nzbget 11.0 or later
if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5] < '11.0':
logger.postprocess("Script triggered from NZBGet (11.0 or later).")
logger.info("Script triggered from NZBGet (11.0 or later).")
if os.environ['NZBOP_UNPACK'] != 'yes':
logger.error("Please enable option \"Unpack\" in nzbget configuration file, exiting")
@ -345,7 +342,7 @@ def main(args, section=None):
# Check par status
if os.environ['NZBPP_PARSTATUS'] == '3':
logger.warning("Par-check successful, but Par-repair disabled, exiting")
logger.postprocess("Please check your Par-repair settings for future downloads.")
logger.info("Please check your Par-repair settings for future downloads.")
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_NONE)
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4':
@ -362,16 +359,16 @@ def main(args, section=None):
if os.environ['NZBPP_HEALTH'] < 1000:
logger.warning("Download health is compromised and Par-check/repair disabled or no .par2 files found. Setting status \"failed\"")
logger.postprocess("Please check your Par-check/repair settings for future downloads.")
logger.info("Please check your Par-check/repair settings for future downloads.")
status = 1
else:
logger.postprocess("Par-check/repair disabled or no .par2 files found, and Unpack not required. Health is ok so handle as though download successful")
logger.postprocess("Please check your Par-check/repair settings for future downloads.")
logger.info("Par-check/repair disabled or no .par2 files found, and Unpack not required. Health is ok so handle as though download successful")
logger.info("Please check your Par-check/repair settings for future downloads.")
# Check if destination directory exists (important for reprocessing of history items)
if not os.path.isdir(os.environ['NZBPP_DIRECTORY']):
logger.error("Nothing to post-process: destination directory %s doesn't exist. Setting status \"failed\"", os.environ['NZBPP_DIRECTORY'])
logger.error("Nothing to post-process: destination directory %s doesn't exist. Setting status failed" % (os.environ['NZBPP_DIRECTORY']))
status = 1
# Check for download_id to pass to CouchPotato
@ -393,7 +390,7 @@ def main(args, section=None):
# 6 Group that the NZB was posted in e.g. alt.binaries.x
# 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2
clientAgent = 'sabnzbd'
logger.postprocess("Script triggered from SABnzbd")
logger.info("Script triggered from SABnzbd")
result = process(args[1], inputName=args[2], status=args[7], inputCategory=args[5], clientAgent=clientAgent, download_id='')
# SABnzbd 0.7.17+
elif len(args) >= nzbtomedia.SABNZB_0717_NO_OF_ARGUMENTS:
@ -407,7 +404,7 @@ def main(args, section=None):
# 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2
# 8 Failure URL
clientAgent = 'sabnzbd'
logger.postprocess("Script triggered from SABnzbd 0.7.17+")
logger.info("Script triggered from SABnzbd 0.7.17+")
result = process(args[1], inputName=args[2], status=args[7], inputCategory=args[5], clientAgent=clientAgent, download_id='')
else:
# Perform Manual Run
@ -420,21 +417,20 @@ def main(args, section=None):
if nzbtomedia.CFG[section][category].isenabled():
dirNames = get_dirnames(section, category)
for dirName in dirNames:
logger.postprocess("nzbToMedia running %s:%s as a manual run on folder %s ...", section, category, dirName)
logger.info("Starting manual run for %s:%s - Folder:%s" % (section, category, dirName))
results = process(dirName, os.path.basename(dirName), 0, clientAgent=clientAgent, inputCategory=category)
if results != 0:
logger.error("A problem was reported when trying to manually run %s:%s.", section, category)
logger.error("A problem was reported when trying to perform a manual run for %s:%s." % (section, category))
result = results
else:
logger.postprocess("nzbToMedia %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
logger.debug("nzbToMedia %s:%s is DISABLED" % (section, category))
if result == 0:
logger.postprocess("The %s script completed successfully.", args[0])
logger.info("The %s script completed successfully." % args[0])
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_SUCCESS)
else:
logger.error("A problem was reported in the %s script.", args[0])
logger.error("A problem was reported in the %s script." % args[0])
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)

View file

@ -11,15 +11,15 @@ class Transcoder:
ffmpeg = os.path.join(os.path.dirname(sys.argv[0]), 'ffmpeg\\bin\\ffmpeg.exe') # note, will need to package in this dir.
useNiceness = False
if not os.path.isfile(ffmpeg): # problem
logger.error("ffmpeg not found. ffmpeg needs to be located at: %s", ffmpeg)
logger.info("Cannot transcode files in folder %s", dirName)
logger.error("ffmpeg not found. ffmpeg needs to be located at: %s" % (ffmpeg))
logger.info("Cannot transcode files in folder %s" % (dirName))
return 1 # failure
else:
if call(['which', 'ffmpeg']) != 0:
res = call([os.path.join(os.path.dirname(sys.argv[0]),'getffmpeg.sh')])
if res or call(['which', 'ffmpeg']) != 0: # did not install or ffmpeg still not found.
logger.error("Failed to install ffmpeg. Please install manually")
logger.info("Cannot transcode files in folder %s", dirName)
logger.info("Cannot transcode files in folder %s" % (dirName))
return 1 # failure
else:
ffmpeg = 'ffmpeg'
@ -41,7 +41,7 @@ class Transcoder:
name, ext = os.path.splitext(filePath)
if ext in nzbtomedia.MEDIACONTAINER: # If the file is a video file
if ext in nzbtomedia.IGNOREEXTENSIONS:
logger.info("No need to transcode video type %s", ext)
logger.info("No need to transcode video type %s" % (ext))
continue
if ext == outputVideoExtension: # we need to change the name to prevent overwriting itself.
outputVideoExtension = '-transcoded' + outputVideoExtension # adds '-transcoded.ext'
@ -96,26 +96,26 @@ class Transcoder:
os.remove(newfilePath)
except OSError, e:
if e.errno != errno.ENOENT: # Ignore the error if it's just telling us that the file doesn't exist
logger.debug("Error when removing transcoding target: %s", e)
logger.debug("Error when removing transcoding target: %s" % (e))
except Exception, e:
logger.debug("Error when removing transcoding target: %s", e)
logger.debug("Error when removing transcoding target: %s" % (e))
logger.info("Transcoding video: %s", file)
logger.info("Transcoding video: %s" % (file))
cmd = ""
for item in command:
cmd = cmd + " " + item
logger.debug("calling command:%s", cmd)
logger.debug("calling command:%s" % (cmd))
result = 1 # set result to failed in case call fails.
try:
result = call(command)
except:
logger.error("Transcoding of video %s has failed", filePath)
logger.error("Transcoding of video %s has failed" % (filePath))
if result == 0:
logger.info("Transcoding of video %s to %s succeeded", filePath, newfilePath)
logger.info("Transcoding of video %s to %s succeeded" % (filePath, newfilePath))
if nzbtomedia.DUPLICATE == 0: # we get rid of the original file
os.unlink(filePath)
else:
logger.error("Transcoding of video %s to %s failed", filePath, newfilePath)
logger.error("Transcoding of video %s to %s failed" % (filePath, newfilePath))
# this will be 0 (successful) it all are successful, else will return a positive integer for failure.
final_result = final_result + result
return final_result

View file

@ -31,15 +31,16 @@ NZBGET_POSTPROCESS_NONE = 95
# config constants
CFG = None
CFG_LOGGING = None
APP_FILENAME = ''
APP_NAME = ''
PROGRAM_DIR = ''
LOG_DIR = ''
LOG_FILE = ''
CONFIG_FILE = ''
CONFIG_SPEC_FILE = ''
CONFIG_MOVIE_FILE = ''
CONFIG_TV_FILE = ''
APP_FILENAME = None
APP_NAME = None
PROGRAM_DIR = None
LOG_DIR = None
LOG_FILE = None
LOG_DEBUG = None
CONFIG_FILE = None
CONFIG_SPEC_FILE = None
CONFIG_MOVIE_FILE = None
CONFIG_TV_FILE = None
SYS_ENCODING = None
SYS_ARGV = None
@ -129,14 +130,11 @@ def initialize(section=None):
TRANSCODE, GIT_PATH, GIT_USER, GIT_BRANCH, GIT_REPO, SYS_ENCODING, NZB_CLIENTAGENT, SABNZBDHOST, SABNZBDPORT, SABNZBDAPIKEY, \
DUPLICATE, IGNOREEXTENSIONS, OUTPUTVIDEOEXTENSION, OUTPUTVIDEOCODEC, OUTPUTVIDEOPRESET, OUTPUTVIDEOFRAMERATE, \
OUTPUTVIDEOBITRATE, OUTPUTAUDIOCODEC, OUTPUTAUDIOBITRATE, OUTPUTSUBTITLECODEC, OUTPUTFASTSTART, OUTPUTQUALITYPERCENT, \
NICENESS, MEDIAEXTENSIONS
NICENESS, MEDIAEXTENSIONS, LOG_DEBUG
if __INITIALIZED__:
return False
# add our custom libs to the system path
sys.path.insert(0, os.path.abspath(os.path.join(PROGRAM_DIR, 'lib')))
# init preliminaries
SYS_ARGV = sys.argv[1:]
APP_FILENAME = sys.argv[0]
@ -144,10 +142,13 @@ def initialize(section=None):
PROGRAM_DIR = os.path.dirname(os.path.normpath(os.path.abspath(os.path.join(__file__, os.pardir))))
LOG_DIR = os.path.join(PROGRAM_DIR, 'logs')
LOG_FILE = os.path.join(LOG_DIR, 'postprocess.log')
CONFIG_FILE = os.path.join(PROGRAM_DIR, "autoProcessMedia.cfg")
CONFIG_SPEC_FILE = os.path.join(PROGRAM_DIR, "autoProcessMedia.cfg.spec")
CONFIG_MOVIE_FILE = os.path.join(PROGRAM_DIR, "autoProcessMovie.cfg")
CONFIG_TV_FILE = os.path.join(PROGRAM_DIR, "autoProcessTv.cfg")
CONFIG_FILE = os.path.join(PROGRAM_DIR, 'autoProcessMedia.cfg')
CONFIG_SPEC_FILE = os.path.join(PROGRAM_DIR, 'autoProcessMedia.cfg.spec')
CONFIG_MOVIE_FILE = os.path.join(PROGRAM_DIR, 'autoProcessMovie.cfg')
CONFIG_TV_FILE = os.path.join(PROGRAM_DIR, 'autoProcessTv.cfg')
# add our custom libs to the system path
sys.path.insert(0, os.path.abspath(os.path.join(PROGRAM_DIR, 'lib')))
try:
locale.setlocale(locale.LC_ALL, "")
@ -179,19 +180,22 @@ def initialize(section=None):
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
if not config.migrate():
logger.error("Unable to migrate config file %s, exiting ...", CONFIG_FILE)
logger.error("Unable to migrate config file %s, exiting ..." % (CONFIG_FILE))
sys.exit(-1)
# run migrate to convert NzbGet data from old cfg style to new cfg style
if os.environ.has_key('NZBOP_SCRIPTDIR'):
if not config.addnzbget():
logger.error("Unable to migrate NzbGet config file %s, exiting ...", CONFIG_FILE)
logger.error("Unable to migrate NzbGet config file %s, exiting ..." % (CONFIG_FILE))
sys.exit(-1)
# load newly migrated config
logger.info("Loading config from %s", CONFIG_FILE)
logger.info("Loading config from %s" % CONFIG_FILE)
CFG = config()
# Enable/Disable DEBUG Logging
LOG_DEBUG = int(CFG['General']['log_debug'])
# Set Version and GIT variables
NZBTOMEDIA_VERSION = '9.3'
VERSION_NOTIFY = int(CFG['General']['version_notify'])

View file

@ -7,21 +7,13 @@ from nzbtomedia import logger
class autoProcessComics:
def processEpisode(self, dirName, nzbName=None, status=0, clientAgent='manual', inputCategory=None):
if dirName is None:
logger.error("No directory was given!")
return 1 # failure
# auto-detect correct section
section = nzbtomedia.CFG.findsection(inputCategory)
if not section:
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file." % inputCategory)
return 1
logger.postprocess("#########################################################")
logger.postprocess("## ..::[%s]::.. :: CATEGORY:[%s]", section, inputCategory)
logger.postprocess("#########################################################")
host = nzbtomedia.CFG[section][inputCategory]["host"]
port = nzbtomedia.CFG[section][inputCategory]["port"]
username = nzbtomedia.CFG[section][inputCategory]["username"]
@ -59,16 +51,16 @@ class autoProcessComics:
protocol = "http://"
url = "%s%s:%s%s/post_process" % (protocol, host, port, web_root)
logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s" % (url), section)
try:
r = requests.get(url, params=params, auth=(username, password), stream=True)
except requests.ConnectionError:
logger.error("Unable to open URL")
logger.error("Unable to open URL", section)
return 1 # failure
for line in r.iter_lines():
if line: logger.postprocess("%s", line)
if line: logger.postprocess("%s" % (line), section)
time.sleep(60) #wait 1 minute for now... need to see just what gets logged and how long it takes to process
return 0 # Success

View file

@ -13,13 +13,9 @@ class autoProcessGames:
section = nzbtomedia.CFG.findsection(inputCategory)
if not section:
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file." % inputCategory)
return 1
logger.postprocess("#########################################################")
logger.postprocess("## ..::[%s]::.. :: CATEGORY:[%s]", section, inputCategory)
logger.postprocess("#########################################################")
status = int(status)
host = nzbtomedia.CFG[section][inputCategory]["host"]
@ -59,7 +55,7 @@ class autoProcessGames:
params['db_id'] = gamezID
params['status'] = downloadStatus
logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s" % (url),section)
try:
r = requests.get(url, params=params)
@ -68,11 +64,11 @@ class autoProcessGames:
return 1 # failure
result = r.json()
logger.postprocess("%s", result)
logger.postprocess("%s" % (result),section)
if result['success']:
logger.postprocess("Status for %s has been set to %s in Gamez", gamezID, downloadStatus)
logger.postprocess("SUCCESS: Status for %s has been set to %s in Gamez" % (gamezID, downloadStatus),section)
return 0 # Success
else:
logger.error("Status for %s has NOT been updated in Gamez", gamezID)
logger.error("FAILED: Status for %s has NOT been updated in Gamez" % (gamezID),section)
return 1 # failure

View file

@ -1,102 +1,62 @@
import os
import re
import time
import nzbtomedia
from lib import requests
from nzbtomedia.Transcoder import Transcoder
from nzbtomedia.nzbToMediaSceneExceptions import process_all_exceptions
from nzbtomedia.nzbToMediaUtil import convert_to_ascii, delete, create_torrent_class, clean_nzbname
from nzbtomedia.nzbToMediaUtil import convert_to_ascii, delete, find_imdbid, find_download
from nzbtomedia import logger
class autoProcessMovie:
def find_imdbid(self, dirName, nzbName):
imdbid = None
nzbName = clean_nzbname(nzbName)
# find imdbid in dirName
m = re.search('(tt\d{7})', dirName)
if m:
imdbid = m.group(1)
logger.postprocess("Found movie id %s in directory", imdbid)
return imdbid
# find imdbid in nzbName
m = re.search('(tt\d{7})', nzbName)
if m:
imdbid = m.group(1)
logger.postprocess("Found imdbid %s in name", imdbid)
return imdbid
m = re.search("^(.+)\W(\d{4})", os.path.basename(dirName))
if m:
title = m.group(1)
year = m.group(2)
url = "http://www.omdbapi.com"
logger.debug("Opening URL: %s", url)
try:
r = requests.get(url, params={'y':year, 't':title})
except requests.ConnectionError:
logger.error("Unable to open URL")
return
results = r.json()
try:
imdbid = results['imdbID']
except:pass
if imdbid:
return imdbid
def get_releases(self, baseURL, download_id, dirName, nzbName):
releases = {}
def get_releases(self, baseURL, imdbid=None, download_id=None):
results = {}
params = {}
imdbid = self.find_imdbid(dirName, nzbName)
# determin cmd and params to send to CouchPotato to get our results
section = 'movies'
cmd = "/media.list"
params['status'] = 'active,done'
if imdbid:
section = 'media'
cmd = "/media.get"
params['id'] = imdbid
if download_id:
params['release_status'] = 'snatched,downloaded'
url = baseURL + cmd
logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s" % url)
try:
r = requests.get(url, params=params)
except requests.ConnectionError:
logger.error("Unable to open URL")
logger.error("Unable to open URL %s" % url)
return
results = r.json()
movies = results[section]
result = r.json()
movies = result[section]
if not isinstance(movies, list):
movies = [movies]
for movie in movies:
if movie['status'] not in ['active','done']:
continue
releases = movie['releases']
if not isinstance(releases, list):
releases = [releases]
for release in releases:
if release['status'] not in ['snatched','downloaded']:
continue
try:
if download_id:
if download_id != release['download_info']['id']:
continue
id = release['_id']
releases[id] = release
results[id] = release
except:continue
return releases
# Search downloads on clients for a match to try and narrow our results down to 1
for id, x in results.items():
try:
if not find_download(str(x['download_info']['downloader']).lower(),x['download_info']['id']):
results.pop(id)
except:continue
return results
def releases_diff(self, dict_a, dict_b):
return dict([
@ -109,21 +69,13 @@ class autoProcessMovie:
])
def process(self, dirName, nzbName=None, status=0, clientAgent = "manual", download_id = "", inputCategory=None):
if dirName is None:
logger.error("No directory was given!")
return 1 # failure
# auto-detect correct section
section = nzbtomedia.CFG.findsection(inputCategory)
if not section:
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file." % inputCategory)
return 1
logger.postprocess("#########################################################")
logger.postprocess("## ..::[%s]::.. :: CATEGORY:[%s]", section, inputCategory)
logger.postprocess("#########################################################")
status = int(status)
host = nzbtomedia.CFG[section][inputCategory]["host"]
@ -141,17 +93,11 @@ class autoProcessMovie:
web_root = nzbtomedia.CFG[section][inputCategory]["web_root"]
except:
web_root = ""
try:
transcode = int(nzbtomedia.CFG["Transcoder"]["transcode"])
except:
transcode = 0
try:
remote_path = nzbtomedia.CFG[section][inputCategory]["remote_path"]
except:
remote_path = None
nzbName = str(nzbName) # make sure it is a string
if ssl:
protocol = "https://"
else:
@ -159,10 +105,11 @@ class autoProcessMovie:
baseURL = "%s%s:%s%s/api/%s" % (protocol, host, port, web_root, apikey)
releases = self.get_releases(baseURL, download_id, dirName, nzbName)
imdbid = find_imdbid(dirName,nzbName)
releases = self.get_releases(baseURL, imdbid, download_id)
if not releases:
logger.error("Could not find any releases marked as WANTED on CouchPotato to compare changes against %s, skipping ...", nzbName)
logger.error("Could not find any releases marked as WANTED matching %s, skipping ..." % nzbName, section)
return 1
# try to get release_id, media_id, and download_id if one was not passed in
@ -172,19 +119,19 @@ class autoProcessMovie:
try:
release_id = releases.keys()[0]
media_id = releases[release_id]['media_id']
download_id = releases['download_info']['id']
download_id = releases[release_id]['download_info']['id']
except:pass
process_all_exceptions(nzbName.lower(), dirName)
nzbName, dirName = convert_to_ascii(nzbName, dirName)
if status == 0:
if transcode == 1:
if nzbtomedia.TRANSCODE == 1:
result = Transcoder().Transcode_directory(dirName)
if result == 0:
logger.debug("Transcoding succeeded for files in %s", dirName)
logger.debug("Transcoding succeeded for files in %s" % (dirName),section)
else:
logger.warning("Transcoding failed for files in %s", dirName)
logger.warning("Transcoding failed for files in %s" % (dirName),section)
if method == "manage":
command = "/manage.update"
@ -201,86 +148,88 @@ class autoProcessMovie:
dirName_new = os.path.join(remote_path, os.path.basename(dirName)).replace("\\", "/")
params['media_folder'] = dirName_new
url = baseURL + command
url = "%s%s" % (baseURL, command)
logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s" % (url), section)
logger.postprocess("Attempting to perform a %s scan on CouchPotato for %s", method, nzbName)
logger.postprocess("Attempting to perform a %s scan for %s" % (method, nzbName), section)
try:
r = requests.get(url, params=params)
except requests.ConnectionError:
logger.error("Unable to open URL")
logger.error("Unable to open URL", section)
return 1 # failure
result = r.json()
if result['success']:
logger.postprocess("SUCCESS: %s scan started on CouchPotatoServer for %s", method, nzbName)
logger.postprocess("SUCCESS: Started %s scan on folder %s, please wait ..." % (method, dirName), section)
else:
logger.error("FAILED: %s scan has NOT started on CouchPotato for %s. Exiting ...", method, nzbName)
logger.error("FAILED: %s scan was unable to start for folder %s. exiting!" % (method, dirName), section)
return 1 # failure
else:
logger.postprocess("Download of %s has failed.", nzbName)
logger.postprocess("FAILED DOWNLOAD DETECTED FOR %s" % (nzbName), section)
if delete_failed and os.path.isdir(dirName) and not os.path.dirname(dirName) == dirName:
logger.postprocess("Deleting failed files and folder %s", dirName)
logger.postprocess("Deleting failed files and folder %s" % dirName, section)
delete(dirName)
if not download_id:
logger.warning("Could not find a movie in the database for release %s", nzbName)
logger.warning("Please manually ignore this release and refresh the wanted movie from CouchPotato, Exiting ...")
logger.error("Could not find a downloaded movie in the database matching %s, exiting!" % nzbName, section)
return 1 # failure
logger.postprocess("Ignoring current failed release %s ...", nzbName)
logger.postprocess("Setting failed release %s to ignored ..." % (nzbName), section)
url = baseURL + "/release.ignore"
logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s" % (url), section)
try:
r = requests.get(url, params={'id': release_id})
except requests.ConnectionError:
logger.error("Unable to open URL")
logger.error("Unable to open URL %s" % (url), section)
return 1 # failure
result = r.json()
if result['success']:
logger.postprocess("%s has been set to ignored on CouchPotato", nzbName)
logger.postprocess("SUCCESS: %s has been set to ignored ..." % (nzbName), section)
else:
logger.warning("Failed to ignore %s on CouchPotato ...", nzbName)
logger.warning("FAILED: Unable to set %s to ignored!" % (nzbName), section)
logger.postprocess("Snatching next highest ranked release on CouchPotato ...")
logger.postprocess("Trying to snatch the next highest ranked release.", section)
url = baseURL + "/movie.searcher.try_next"
logger.debug("Opening URL: %s", url)
url = "%s/movie.searcher.try_next" % (baseURL)
logger.debug("Opening URL: %s" % (url), section)
try:
r = requests.get(url, params={'media_id': media_id})
except requests.ConnectionError:
logger.error("Unable to open URL")
logger.error("Unable to open URL %s" % (url), section)
return 1 # failure
result = r.json()
if result['success']:
logger.postprocess("CouchPotato successfully snatched the next highest release above %s ...", nzbName)
logger.postprocess("SUCCESS: Snatched the next highest release ...", section)
return 0
else:
logger.postprocess("CouchPotato was unable to find a higher release then %s to snatch ...", nzbName)
logger.postprocess("FAILED: Unable to find a higher ranked release then %s to snatch!" % (nzbName), section)
return 1
# we will now check to see if CPS has finished renaming before returning to TorrentToMedia and unpausing.
timeout = time.time() + 60 * wait_for
while (time.time() < timeout): # only wait 2 (default) minutes, then return.
releases_current = self.get_releases(baseURL, download_id, dirName, nzbName)
releases_current = self.get_releases(baseURL, imdbid, download_id)
releasesDiff = self.releases_diff(releases, releases_current)
logger.postprocess("Checking for status change, please stand by ...", section)
if releasesDiff: # Something has changed. CPS must have processed this movie.
try:
release_status = releasesDiff[releasesDiff.keys()[0]]['status']
logger.postprocess("SUCCESS: Release %s marked as [%s] on CouchPotato", nzbName, release_status)
logger.postprocess("SUCCESS: Release %s has now been marked with a status of [%s]" % (nzbName, str(release_status).upper()), section)
return 0 # success
except:pass
# pause and let CouchPotatoServer catch its breath
time.sleep(10 * wait_for)
# The status hasn't changed. we have waited 2 minutes which is more than enough. uTorrent can resule seeding now.
logger.warning("The movie does not appear to have changed status after %s minutes. Please check CouchPotato Logs", wait_for)
logger.warning("%s does not appear to have changed status after %s minutes, Please check your logs." % (nzbName, wait_for), section)
return 1 # failure

View file

@ -7,7 +7,7 @@ from nzbtomedia import logger
class autoProcessMusic:
def get_status(self, baseURL, apikey, dirName):
logger.debug("Attempting to get current status for release:%s", os.path.basename(dirName))
logger.debug("Attempting to get current status for release:%s" % (os.path.basename(dirName)))
url = baseURL
@ -15,7 +15,7 @@ class autoProcessMusic:
params['apikey'] = apikey
params['cmd'] = "getHistory"
logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s" % (url))
try:
r = requests.get(url, params=params)
@ -31,21 +31,13 @@ class autoProcessMusic:
except:pass
def process(self, dirName, nzbName=None, status=0, clientAgent="manual", inputCategory=None):
if dirName is None:
logger.error("No directory was given!")
return 1 # failure
# auto-detect correct section
section = nzbtomedia.CFG.findsection(inputCategory)
if len(section) == 0:
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file." % (inputCategory))
return 1
logger.postprocess("#########################################################")
logger.postprocess("## ..::[%s]::.. :: CATEGORY:[%s]", section, inputCategory)
logger.postprocess("#########################################################")
status = int(status)
host = nzbtomedia.CFG[section][inputCategory]["host"]
@ -92,29 +84,29 @@ class autoProcessMusic:
if release_status:
if release_status not in ["unprocessed", "snatched"]:
logger.warning("%s is marked with a status of %s on HeadPhones, skipping ...", nzbName, release_status)
logger.warning("%s is marked with a status of %s, skipping ..." % (nzbName, release_status),section)
return 0
else:
logger.error("Could not find a status for %s on HeadPhones", nzbName)
logger.error("Could not find a status for %s" % (nzbName),section)
return 1
logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s" % (url),section)
try:
r = requests.get(url, params=params)
except requests.ConnectionError:
logger.error("Unable to open URL")
logger.error("Unable to open URL %s" % (url),section)
return 1 # failure
logger.postprocess("HeadPhones returned %s", r.text)
logger.debug("Result: %s" % (r.text),section)
if r.text == "OK":
logger.postprocess("Post-processing started on HeadPhones for %s in folder %s", nzbName, dirName)
logger.postprocess("SUCCESS: Post-Processing started for %s in folder %s ..." % (nzbName, dirName),section)
else:
logger.error("Post-proecssing has NOT started on HeadPhones for %s in folder %s. Exiting", nzbName, dirName)
logger.error("FAILED: Post-Processing has NOT started for %s in folder %s. exiting!" % (nzbName, dirName),section)
return 1 # failure
else:
logger.postprocess("The download failed. Nothing to process")
logger.warning("FAILED DOWNLOAD DETECTED", section)
return 0 # Success (as far as this script is concerned)
# we will now wait 1 minutes for this album to be processed before returning to TorrentToMedia and unpausing.
@ -122,11 +114,11 @@ class autoProcessMusic:
while (time.time() < timeout): # only wait 2 (default) minutes, then return.
current_status = self.get_status(url, apikey, dirName)
if current_status is not None and current_status != release_status: # Something has changed. CPS must have processed this movie.
logger.postprocess("SUCCESS: This release is now marked as status [%s] in HeadPhones",current_status)
logger.postprocess("SUCCESS: This release is now marked as status [%s]" % (current_status),section)
return 0
time.sleep(10 * wait_for)
# The status hasn't changed. we have waited 2 minutes which is more than enough. uTorrent can resule seeding now.
logger.warning("The music album does not appear to have changed status after %s minutes. Please check HeadPhones Logs",2)
logger.warning("The music album does not appear to have changed status after %s minutes. Please check your Logs" % (wait_for))
return 1 # failure

View file

@ -10,21 +10,13 @@ from nzbtomedia import logger
class autoProcessTV:
def processEpisode(self, dirName, nzbName=None, failed=False, clientAgent = "manual", inputCategory=None):
if dirName is None:
logger.error("No directory was given!")
return 1 # failure
# auto-detect correct section
section = nzbtomedia.CFG.findsection(inputCategory)
if not section:
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file." % inputCategory)
return 1
logger.postprocess("#########################################################")
logger.postprocess("## ..::[%s]::.. :: CATEGORY:[%s]", section, inputCategory)
logger.postprocess("#########################################################")
# auto-detect correct fork
fork, fork_params = autoFork(inputCategory)
@ -47,18 +39,10 @@ class autoProcessTV:
web_root = nzbtomedia.CFG[section][inputCategory]["web_root"]
except:
web_root = ""
try:
transcode = int(nzbtomedia.CFG["Transcoder"]["transcode"])
except:
transcode = 0
try:
delete_failed = int(nzbtomedia.CFG[section][inputCategory]["delete_failed"])
except:
delete_failed = 0
try:
SampleIDs = (nzbtomedia.CFG["Extensions"]["SampleIDs"])
except:
SampleIDs = ['sample','-s.']
try:
nzbExtractionBy = nzbtomedia.CFG[section][inputCategory]["nzbExtractionBy"]
except:
@ -98,18 +82,18 @@ class autoProcessTV:
filePath = os.path.join(dirpath, file)
fileExtension = os.path.splitext(file)[1]
if fileExtension in nzbtomedia.MEDIACONTAINER: # If the file is a video file
if is_sample(filePath, nzbName, nzbtomedia.MINSAMPLESIZE, SampleIDs):
logger.debug("Removing sample file: %s", filePath)
if is_sample(filePath, nzbName, nzbtomedia.MINSAMPLESIZE, nzbtomedia.SAMPLEIDS):
logger.debug("Removing sample file: %s" % (filePath), section)
os.unlink(filePath) # remove samples
else:
video = video + 1
if video > 0: # Check that a video exists. if not, assume failed.
flatten(dirName) # to make sure SickBeard can find the video (not in sub-folder)
elif clientAgent == "manual":
logger.warning("No media files found in directory %s to manually process.", dirName)
logger.warning("No media files found in directory %s to manually process." % (dirName), section)
return 0 # Success (as far as this script is concerned)
else:
logger.warning("No media files found in directory %s. Processing this as a failed download", dirName)
logger.warning("No media files found in directory %s. Processing this as a failed download" % (dirName), section)
status = int(1)
failed = True
@ -140,37 +124,36 @@ class autoProcessTV:
[fork_params.pop(k) for k,v in fork_params.items() if v is None]
if status == 0:
logger.postprocess("The download succeeded. Sending process request to %s", section)
logger.postprocess("SUCCESS: The download succeeded, sending a post-process request", section)
else:
if fork in nzbtomedia.SICKBEARD_FAILED:
logger.postprocess("The download failed. Sending 'failed' process request to SickBeard's %s branch", fork)
logger.postprocess("FAILED: The download failed. Sending 'failed' process request to %s branch" % (fork), section)
else:
logger.postprocess("The download failed. SickBeard's %s branch does not handle failed downloads. Nothing to process", fork)
logger.postprocess("FAILED: The download failed. %s branch does not handle failed downloads. Nothing to process" % (fork), section)
if delete_failed and os.path.isdir(dirName) and not os.path.dirname(dirName) == dirName:
logger.postprocess("Deleting failed files and folder %s", dirName)
logger.postprocess("Deleting failed files and folder %s" % (dirName), section)
delete(dirName)
return 0 # Success (as far as this script is concerned)
if status == 0 and transcode == 1: # only transcode successful downlaods
if status == 0 and nzbtomedia.TRANSCODE == 1: # only transcode successful downlaods
result = Transcoder().Transcode_directory(dirName)
if result == 0:
logger.debug("Transcoding succeeded for files in %s", dirName)
logger.debug("SUCCESS: Transcoding succeeded for files in %s" % (dirName), section)
else:
logger.warning("Transcoding failed for files in %s", dirName)
logger.warning("FAILED: Transcoding failed for files in %s" % (dirName), section)
if ssl:
protocol = "https://"
else:
protocol = "http://"
url = None
if section == "SickBeard":
url = "%s%s:%s%s/home/postprocess/processEpisode" % (protocol,host,port,web_root)
elif section == "NzbDrone":
url = "%s%s:%s%s/api/command" % (protocol, host, port, web_root)
logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s" % (url),section)
try:
r = None
@ -181,13 +164,13 @@ class autoProcessTV:
headers = {"X-Api-Key": apikey}
r = requests.get(url, params=params, headers=headers, stream=True)
except requests.ConnectionError:
logger.error("Unable to open URL")
logger.error("Unable to open URL: %s" % (url), section)
return 1 # failure
for line in r.iter_lines():
if line: logger.postprocess("%s", line)
if line: logger.postprocess("%s" % (line))
if status != 0 and delete_failed and not os.path.dirname(dirName) == dirName:
logger.postprocess("Deleting failed files and folder %s", dirName)
logger.postprocess("Deleting failed files and folder %s" % (dirName),section)
delete(dirName)
return 0 # Success

View file

@ -27,10 +27,13 @@ def extract(filePath, outputDestination):
platform = 'x86'
if not os.path.dirname(sys.argv[0]):
chplocation = os.path.normpath(os.path.join(os.getcwd(), 'nzbtomedia/extractor/bin/chp.exe'))
sevenzipLocation = os.path.normpath(os.path.join(os.getcwd(), 'nzbtomedia/extractor/bin/' + platform + '/7z.exe'))
sevenzipLocation = os.path.normpath(
os.path.join(os.getcwd(), 'nzbtomedia/extractor/bin/' + platform + '/7z.exe'))
else:
chplocation = os.path.normpath(os.path.join(os.path.dirname(sys.argv[0]), 'nzbtomedia/extractor/bin/chp.exe'))
sevenzipLocation = os.path.normpath(os.path.join(os.path.dirname(sys.argv[0]), 'nzbtomedia/extractor/bin/' + platform + '/7z.exe'))
chplocation = os.path.normpath(
os.path.join(os.path.dirname(sys.argv[0]), 'nzbtomedia/extractor/bin/chp.exe'))
sevenzipLocation = os.path.normpath(
os.path.join(os.path.dirname(sys.argv[0]), 'nzbtomedia/extractor/bin/' + platform + '/7z.exe'))
if not os.path.exists(sevenzipLocation):
logger.error("EXTRACTOR: Could not find 7-zip, Exiting")
return False
@ -39,11 +42,11 @@ def extract(filePath, outputDestination):
cmd_7zip = [sevenzipLocation, "x", "-y"]
else:
cmd_7zip = [chplocation, sevenzipLocation, "x", "-y"]
ext_7zip = [".rar",".zip",".tar.gz","tgz",".tar.bz2",".tbz",".tar.lzma",".tlz",".7z",".xz"]
ext_7zip = [".rar", ".zip", ".tar.gz", "tgz", ".tar.bz2", ".tbz", ".tar.lzma", ".tlz", ".7z", ".xz"]
EXTRACT_COMMANDS = dict.fromkeys(ext_7zip, cmd_7zip)
# Using unix
else:
required_cmds=["unrar", "unzip", "tar", "unxz", "unlzma", "7zr", "bunzip2"]
required_cmds = ["unrar", "unzip", "tar", "unxz", "unlzma", "7zr", "bunzip2"]
## Possible future suport:
# gunzip: gz (cmd will delete original archive)
## the following do not extract to dest dir
@ -67,7 +70,7 @@ def extract(filePath, outputDestination):
if call(['which', cmd]): #note, returns 0 if exists, or 1 if doesn't exist.
for k, v in EXTRACT_COMMANDS.items():
if cmd in v[0]:
logger.error("EXTRACTOR: %s not found, disabling support for %s", cmd, k)
logger.error("EXTRACTOR: %s not found, disabling support for %s" % (cmd, k))
del EXTRACT_COMMANDS[k]
else:
logger.warning("EXTRACTOR: Cannot determine which tool to use when called from Transmission")
@ -81,13 +84,13 @@ def extract(filePath, outputDestination):
# Check if this is a tar
if os.path.splitext(ext[0])[1] == ".tar":
cmd = EXTRACT_COMMANDS[".tar" + ext[1]]
elif ext[1] in (".1", ".01", ".001") and os.path.splitext(ext[0])[1] in (".rar", ".zip", ".7z"): #support for *.zip.001, *.zip.002 etc.
elif ext[1] in (".1", ".01", ".001") and os.path.splitext(ext[0])[1] in (".rar", ".zip", ".7z"):
cmd = EXTRACT_COMMANDS[os.path.splitext(ext[0])[1]]
else:
if ext[1] in EXTRACT_COMMANDS:
cmd = EXTRACT_COMMANDS[ext[1]]
else:
logger.debug("EXTRACTOR: Unknown file type: %s", ext[1])
logger.debug("EXTRACTOR: Unknown file type: %s" % ext[1])
return False
# Create outputDestination folder
@ -99,8 +102,8 @@ def extract(filePath, outputDestination):
else:
passwords = []
logger.info("Extracting %s to %s", filePath, outputDestination)
logger.debug("Extracting %s %s %s", cmd, filePath, outputDestination)
logger.info("Extracting %s to %s" % (filePath, outputDestination))
logger.debug("Extracting %s %s %s" % (cmd, filePath, outputDestination))
pwd = os.getcwd() # Get our Present Working Directory
os.chdir(outputDestination) # Not all unpack commands accept full paths, so just extract into this directory
try: # now works same for nt and *nix
@ -109,8 +112,9 @@ def extract(filePath, outputDestination):
cmd2.append("-p-") # don't prompt for password.
p = Popen(cmd2) # should extract files fine.
res = p.wait()
if (res >= 0 and os.name == 'nt') or res == 0: # for windows chp returns process id if successful or -1*Error code. Linux returns 0 for successful.
logger.info("EXTRACTOR: Extraction was successful for %s to %s", filePath, outputDestination)
if (
res >= 0 and os.name == 'nt') or res == 0: # for windows chp returns process id if successful or -1*Error code. Linux returns 0 for successful.
logger.info("EXTRACTOR: Extraction was successful for %s to %s" % (filePath, outputDestination))
elif len(passwords) > 0:
logger.info("EXTRACTOR: Attempting to extract with passwords")
pass_success = int(0)
@ -123,15 +127,17 @@ def extract(filePath, outputDestination):
cmd2.append(passcmd)
p = Popen(cmd2) # should extract files fine.
res = p.wait()
if (res >= 0 and os.name == 'nt') or res == 0: # for windows chp returns process id if successful or -1*Error code. Linux returns 0 for successful.
logger.info("EXTRACTOR: Extraction was successful for %s to %s using password: %s", filePath, outputDestination, password)
if (
res >= 0 and os.name == 'nt') or res == 0: # for windows chp returns process id if successful or -1*Error code. Linux returns 0 for successful.
logger.info("EXTRACTOR: Extraction was successful for %s to %s using password: %s" % (
filePath, outputDestination, password))
pass_success = int(1)
break
else:
continue
if pass_success == int(0):
logger.error("EXTRACTOR: Extraction failed for %s. 7zip result was %s", filePath, res)
logger.error("EXTRACTOR: Extraction failed for %s. 7zip result was %s" % (filePath, res))
except:
logger.error("EXTRACTOR: Extraction failed for %s. Could not call command %s", filePath, cmd)
logger.error("EXTRACTOR: Extraction failed for %s. Could not call command %s" % (filePath, cmd))
os.chdir(pwd) # Go back to our Original Working Directory
return True

View file

@ -76,8 +76,8 @@ class NTMRotatingLogHandler(object):
# set a format which is simpler for console use
console.setFormatter(DispatchingFormatter(
{'nzbtomedia': logging.Formatter('%(asctime)s %(levelname)s:: %(message)s', '%H:%M:%S'),
'postprocess': logging.Formatter('%(asctime)s %(levelname)s:: %(message)s', '%H:%M:%S')
{'nzbtomedia': logging.Formatter('[%(asctime)s] [%(levelname)s]::%(message)s', '%H:%M:%S'),
'postprocess': logging.Formatter('[%(asctime)s] [%(levelname)s]::%(message)s', '%H:%M:%S')
},
logging.Formatter('%(message)s'), ))
@ -109,8 +109,8 @@ class NTMRotatingLogHandler(object):
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(DispatchingFormatter(
{'nzbtomedia': logging.Formatter('%(asctime)s %(levelname)-8s:: %(message)s', '%Y-%m-%d %H:%M:%S'),
'postprocess': logging.Formatter('%(asctime)s %(levelname)-8s:: %(message)s', '%Y-%m-%d %H:%M:%S')
{'nzbtomedia': logging.Formatter('%(asctime)s %(levelname)-8s::%(message)s', '%Y-%m-%d %H:%M:%S'),
'postprocess': logging.Formatter('%(asctime)s %(levelname)-8s::%(message)s', '%Y-%m-%d %H:%M:%S')
},
logging.Formatter('%(message)s'), ))
@ -166,7 +166,7 @@ class NTMRotatingLogHandler(object):
ntm_logger.addHandler(new_file_handler)
pp_logger.addHandler(new_file_handler)
def log(self, toLog, logLevel=MESSAGE):
def log(self, toLog, logLevel=MESSAGE, section='MAIN'):
with self.log_lock:
@ -178,7 +178,7 @@ class NTMRotatingLogHandler(object):
else:
self.writes_since_check += 1
message = u"" + toLog
message = u"%s:: %s" % (str(section).upper(), toLog)
out_line = message
@ -188,6 +188,7 @@ class NTMRotatingLogHandler(object):
try:
if logLevel == DEBUG:
if nzbtomedia.LOG_DEBUG == 1:
ntm_logger.debug(out_line)
elif logLevel == MESSAGE:
ntm_logger.info(out_line)
@ -221,31 +222,26 @@ class DispatchingFormatter:
ntm_log_instance = NTMRotatingLogHandler("nzbtomedia.log", NUM_LOGS, LOG_SIZE)
def log(toLog, logLevel=MESSAGE):
ntm_log_instance.log(toLog, logLevel)
def log(toLog, logLevel=MESSAGE, section='MAIN'):
ntm_log_instance.log(toLog, logLevel, section)
def info(toLog, *args):
toLog = toLog % args
ntm_log_instance.log(toLog, MESSAGE)
def info(toLog, section='MAIN'):
log(toLog, MESSAGE, section)
def error(toLog, *args):
toLog = toLog % args
ntm_log_instance.log(toLog, ERROR)
def error(toLog, section='MAIN'):
log(toLog, ERROR, section)
def warning(toLog, *args):
toLog = toLog % args
ntm_log_instance.log(toLog, WARNING)
def warning(toLog, section='MAIN'):
log(toLog, WARNING, section)
def debug(toLog, *args):
toLog = toLog % args
ntm_log_instance.log(toLog, DEBUG)
def debug(toLog, section='MAIN'):
log(toLog, DEBUG, section)
def postprocess(toLog, section='MAIN'):
log(toLog, POSTPROCESS, section)
def log_error_and_exit(error_msg):
ntm_log_instance.log_error_and_exit(error_msg)
def postprocess(toLog, *args):
toLog = toLog % args
ntm_log_instance.log(toLog, POSTPROCESS)
def close():
ntm_log_instance.close_log()

View file

@ -7,7 +7,7 @@ def autoFork(inputCategory):
section = nzbtomedia.CFG.findsection(inputCategory)
if not section:
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file." % inputCategory)
return 1
# config settings
@ -47,9 +47,9 @@ def autoFork(inputCategory):
detected = False
if fork == "auto":
logger.info("Attempting to auto-detect " + section + " fork")
logger.info("Attempting to auto-detect %s fork" % inputCategory)
for fork in sorted(nzbtomedia.FORKS.iteritems(), reverse=False):
url = protocol + host + ":" + port + web_root + "/home/postprocess/processEpisode?" + urllib.urlencode(fork[1])
url = "%s%s:%s%s/home/postprocess/processEpisode?%s" % (protocol,host,port,web_root,urllib.urlencode(fork[1]))
# attempting to auto-detect fork
try:
@ -58,7 +58,7 @@ def autoFork(inputCategory):
else:
r = requests.get(url)
except requests.ConnectionError:
logger.info("Could not connect to " + section + ":" + inputCategory + " to perform auto-fork detection!")
logger.info("Could not connect to %s:%s to perform auto-fork detection!" % (section, inputCategory))
break
if r.ok:
@ -66,10 +66,10 @@ def autoFork(inputCategory):
break
if detected:
logger.info("" + section + ":" + inputCategory + " fork auto-detection successful ...")
logger.info("%s:%s fork auto-detection successful ..." % (section, inputCategory))
else:
logger.info("" + section + ":" + inputCategory + " fork auto-detection failed")
logger.info("%s:%s fork auto-detection failed" % (section, inputCategory))
fork = nzbtomedia.FORKS.items()[nzbtomedia.FORKS.keys().index(nzbtomedia.FORK_DEFAULT)]
logger.info("" + section + ":" + inputCategory + " fork set to %s", fork[0])
logger.info("%s:%s inputCategory fork set to %s" % (section, inputCategory, fork[0]))
return fork[0], fork[1]

View file

@ -4,7 +4,6 @@ import socket
import stat
import struct
import shutil
import sys
import time
from lib import requests
import nzbtomedia
@ -15,9 +14,10 @@ from nzbtomedia.synchronousdeluge.client import DelugeClient
from nzbtomedia.utorrent.client import UTorrentClient
from nzbtomedia.transmissionrpc.client import Client as TransmissionClient
def safeName(name):
safename = re.sub(r"[\/\\\:\*\?\"\<\>\|]", "", name) #make this name safe for use in directories for windows etc.
return safename
return re.sub(r"[\/\\\:\*\?\"\<\>\|]", "", name) #make this name safe for use in directories for windows etc.
def makeDir(path):
if not os.path.isdir(path):
@ -27,6 +27,7 @@ def makeDir(path):
return False
return True
def category_search(inputDirectory, inputName, inputCategory, root, categories):
single = False
tordir = False
@ -49,16 +50,18 @@ def category_search(inputDirectory, inputName, inputCategory, root, categories):
return inputDirectory, inputName, inputCategory, root, single
if inputCategory and os.path.isdir(os.path.join(inputDirectory, inputCategory)):
logger.info("SEARCH: Found category directory %s in input directory directory %s", inputCategory, inputDirectory)
logger.info(
"SEARCH: Found category directory %s in input directory directory %s" % (inputCategory, inputDirectory))
inputDirectory = os.path.join(inputDirectory, inputCategory)
logger.info("SEARCH: Setting inputDirectory to %s", inputDirectory)
if inputName and os.path.isdir(os.path.join(inputDirectory, inputName)):
logger.info("SEARCH: Found torrent directory %s in input directory directory %s", inputName, inputDirectory)
logger.info("SEARCH: Found torrent directory %s in input directory directory %s" % (inputName, inputDirectory))
inputDirectory = os.path.join(inputDirectory, inputName)
logger.info("SEARCH: Setting inputDirectory to %s", inputDirectory)
tordir = True
if inputName and os.path.isdir(os.path.join(inputDirectory, safeName(inputName))):
logger.info("SEARCH: Found torrent directory %s in input directory directory %s", safeName(inputName), inputDirectory)
logger.info("SEARCH: Found torrent directory %s in input directory directory %s" % (
safeName(inputName), inputDirectory))
inputDirectory = os.path.join(inputDirectory, safeName(inputName))
logger.info("SEARCH: Setting inputDirectory to %s", inputDirectory)
tordir = True
@ -73,8 +76,8 @@ def category_search(inputDirectory, inputName, inputCategory, root, categories):
index = pathlist.index(inputCategory)
if index + 1 < len(pathlist):
tordir = True
logger.info("SEARCH: Found a unique directory %s in the category directory", pathlist[index+1])
if not inputName: inputName = pathlist[index+1]
logger.info("SEARCH: Found a unique directory %s in the category directory", pathlist[index + 1])
if not inputName: inputName = pathlist[index + 1]
except ValueError:
pass
@ -93,6 +96,7 @@ def category_search(inputDirectory, inputName, inputCategory, root, categories):
return inputDirectory, inputName, inputCategory, root, single
def is_sample(filePath, inputName, minSampleSize, SampleIDs):
# 200 MB in bytes
SIZE_CUTOFF = minSampleSize * 1024 * 1024
@ -115,41 +119,45 @@ def copy_link(filePath, targetDirectory, useLink, outputDestination):
makeDir(outputDestination)
if useLink == "hard":
try:
logger.info("COPYLINK: Hard linking %s to %s", filePath, targetDirectory)
logger.info("COPYLINK: Hard linking %s to %s" % (filePath, targetDirectory))
linktastic.link(filePath, targetDirectory)
except:
logger.error("COPYLINK")
if os.path.isfile(targetDirectory):
logger.warning("COPYLINK: Something went wrong in linktastic.link, but the destination file was created")
logger.warning(
"COPYLINK: Something went wrong in linktastic.link, but the destination file was created")
else:
logger.warning("COPYLINK: Something went wrong in linktastic.link, copying instead")
logger.debug("COPYLINK: Copying %s to %s", filePath, targetDirectory)
logger.debug("COPYLINK: Copying %s to %s" % (filePath, targetDirectory))
shutil.copy(filePath, targetDirectory)
elif useLink == "sym":
try:
logger.info("COPYLINK: Moving %s to %s before sym linking", filePath, targetDirectory)
logger.info("COPYLINK: Moving %s to %s before sym linking" % (filePath, targetDirectory))
shutil.move(filePath, targetDirectory)
logger.info("COPYLINK: Sym linking %s to %s", targetDirectory, filePath)
logger.info("COPYLINK: Sym linking %s to %s" % (targetDirectory, filePath))
linktastic.symlink(targetDirectory, filePath)
except:
logger.error("COPYLINK")
if os.path.isfile(targetDirectory):
logger.warning("COPYLINK: Something went wrong in linktastic.link, but the destination file was created")
logger.warning(
"COPYLINK: Something went wrong in linktastic.link, but the destination file was created")
else:
logger.info("COPYLINK: Something went wrong in linktastic.link, copying instead")
logger.debug("COPYLINK: Copying %s to %s", filePath, targetDirectory)
logger.debug("COPYLINK: Copying %s to %s" % (filePath, targetDirectory))
shutil.copy(filePath, targetDirectory)
elif useLink == "move":
logger.debug("Moving %s to %s", filePath, targetDirectory)
logger.debug("Moving %s to %s" % (filePath, targetDirectory))
shutil.move(filePath, targetDirectory)
else:
logger.debug("Copying %s to %s", filePath, targetDirectory)
logger.debug("Copying %s to %s" % (filePath, targetDirectory))
shutil.copy(filePath, targetDirectory)
return True
def flatten(outputDestination):
logger.info("FLATTEN: Flattening directory: %s", outputDestination)
for dirpath, dirnames, filenames in os.walk(outputDestination): # Flatten out the directory to make postprocessing easier
for dirpath, dirnames, filenames in os.walk(
outputDestination): # Flatten out the directory to make postprocessing easier
if dirpath == outputDestination:
continue # No need to try and move files in the root destination directory
for filename in filenames:
@ -161,6 +169,7 @@ def flatten(outputDestination):
logger.error("FLATTEN: Could not flatten %s", source)
removeEmptyFolders(outputDestination) # Cleanup empty directories
def removeEmptyFolders(path):
logger.info("REMOVER: Removing empty folders in: %s", path)
if not os.path.isdir(path):
@ -180,6 +189,7 @@ def removeEmptyFolders(path):
logger.debug("REMOVER: Removing empty folder: %s", path)
os.rmdir(path)
def remove_read_only(path):
if not os.path.isdir(path):
return
@ -188,9 +198,9 @@ def remove_read_only(path):
logger.debug("Removing Read Only Flag for: %s", filename)
os.chmod(os.path.join(dirpath, filename), stat.S_IWRITE)
#Wake function
def WakeOnLan(ethernet_address):
addr_byte = ethernet_address.split(':')
hw_addr = struct.pack('BBBBBB', int(addr_byte[0], 16),
int(addr_byte[1], 16),
@ -210,6 +220,7 @@ def WakeOnLan(ethernet_address):
ss.sendto(msg, ('<broadcast>', 9))
ss.close()
#Test Connection function
def TestCon(host, port):
try:
@ -218,6 +229,7 @@ def TestCon(host, port):
except:
return "Down"
def WakeUp():
wake = int(nzbtomedia.CFG["WakeOnLan"]["wake"])
if wake == 0: # just return if we don't need to wake anything.
@ -227,18 +239,20 @@ def WakeUp():
port = int(nzbtomedia.CFG["WakeOnLan"]["port"])
mac = nzbtomedia.CFG["WakeOnLan"]["mac"]
i=1
i = 1
while TestCon(host, port) == "Down" and i < 4:
logger.info(("Sending WakeOnLan Magic Packet for mac: %s", mac))
WakeOnLan(mac)
time.sleep(20)
i=i+1
i = i + 1
if TestCon(host,port) == "Down": # final check.
logger.warning("System with mac: %s has not woken after 3 attempts. Continuing with the rest of the script.", mac)
if TestCon(host, port) == "Down": # final check.
logger.warning("System with mac: %s has not woken after 3 attempts. Continuing with the rest of the script.",
mac)
else:
logger.info("System with mac: %s has been woken. Continuing with the rest of the script.", mac)
def convert_to_ascii(nzbName, dirName):
ascii_convert = int(nzbtomedia.CFG["ASCII"]["convert"])
if ascii_convert == 0 or os.name == 'nt': # just return if we don't want to convert or on windows os and "\" is replaced!.
@ -247,21 +261,23 @@ def convert_to_ascii(nzbName, dirName):
nzbName2 = str(nzbName.decode('ascii', 'replace').replace(u'\ufffd', '_'))
dirName2 = str(dirName.decode('ascii', 'replace').replace(u'\ufffd', '_'))
if dirName != dirName2:
logger.info("Renaming directory:%s to: %s.", dirName, dirName2)
logger.info("Renaming directory:%s to: %s." % (dirName, dirName2))
shutil.move(dirName, dirName2)
for dirpath, dirnames, filesnames in os.walk(dirName2):
for filename in filesnames:
filename2 = str(filename.decode('ascii', 'replace').replace(u'\ufffd', '_'))
if filename != filename2:
logger.info("Renaming file:%s to: %s.", filename, filename2)
logger.info("Renaming file:%s to: %s." % (filename, filename2))
shutil.move(filename, filename2)
nzbName = nzbName2
dirName = dirName2
return nzbName, dirName
def parse_other(args):
return os.path.normpath(args[1]), '', '', '', ''
def parse_rtorrent(args):
# rtorrent usage: system.method.set_key = event.download.finished,TorrentToMedia,
# "execute={/path/to/nzbToMedia/TorrentToMedia.py,\"$d.get_base_path=\",\"$d.get_name=\",\"$d.get_custom1=\",\"$d.get_hash=\"}"
@ -285,6 +301,7 @@ def parse_rtorrent(args):
return inputDirectory, inputName, inputCategory, inputHash, inputID
def parse_utorrent(args):
# uTorrent usage: call TorrentToMedia.py "%D" "%N" "%L" "%I"
inputDirectory = os.path.normpath(args[1])
@ -324,6 +341,7 @@ def parse_transmission(args):
inputID = os.getenv('TR_TORRENT_ID')
return inputDirectory, inputName, inputCategory, inputHash, inputID
def parse_args(clientAgent, args):
clients = {
'other': parse_other,
@ -335,10 +353,11 @@ def parse_args(clientAgent, args):
try:
return clients[clientAgent](args)
except:return None, None, None, None, None
except:
return None, None, None, None, None
def get_dirnames(section, subsections=None):
dirNames = []
if subsections is None:
@ -389,10 +408,11 @@ def get_dirnames(section, subsections=None):
os.path.isdir(os.path.join(outputDirectory, o))])
if not dirNames:
logger.warning("%s:%s has no directories identified for post-processing", section, subsection)
logger.warning("%s:%s has no directories identified for post-processing" % (section, subsection))
return list(set(dirNames))
def delete(dirName):
logger.info("Deleting %s", dirName)
try:
@ -400,6 +420,7 @@ def delete(dirName):
except:
logger.error("Unable to delete folder %s", dirName)
def cleanup_directories(inputCategory, processCategories, result, directory):
if inputCategory in processCategories and result == 0 and os.path.isdir(directory):
num_files_new = int(0)
@ -415,90 +436,97 @@ def cleanup_directories(inputCategory, processCategories, result, directory):
logger.info("All files have been processed. Cleaning directory %s", directory)
shutil.rmtree(directory)
else:
logger.info("Directory %s still contains %s media and/or meta files. This directory will not be removed.", directory, num_files_new)
logger.info(
"Directory %s still contains %s media and/or meta files. This directory will not be removed." % (
directory, num_files_new))
for item in file_list:
logger.debug("media/meta file found: %s", item)
def create_torrent_class(clientAgent):
# Hardlink solution for Torrents
TorrentClass = None
if clientAgent == 'utorrent':
try:
logger.debug("Connecting to %s: %s", clientAgent, nzbtomedia.UTORRENTWEBUI)
logger.debug("Connecting to %s: %s" % (clientAgent, nzbtomedia.UTORRENTWEBUI))
TorrentClass = UTorrentClient(nzbtomedia.UTORRENTWEBUI, nzbtomedia.UTORRENTUSR, nzbtomedia.UTORRENTPWD)
except:
logger.error("Failed to connect to uTorrent")
if clientAgent == 'transmission':
try:
logger.debug("Connecting to %s: http://%s:%s", clientAgent, nzbtomedia.TRANSMISSIONHOST,
nzbtomedia.TRANSMISSIONPORT)
TorrentClass = TransmissionClient(nzbtomedia.TRANSMISSIONHOST, nzbtomedia.TRANSMISSIONPORT, nzbtomedia.TRANSMISSIONUSR,
logger.debug("Connecting to %s: http://%s:%s" % (
clientAgent, nzbtomedia.TRANSMISSIONHOST, nzbtomedia.TRANSMISSIONPORT))
TorrentClass = TransmissionClient(nzbtomedia.TRANSMISSIONHOST, nzbtomedia.TRANSMISSIONPORT,
nzbtomedia.TRANSMISSIONUSR,
nzbtomedia.TRANSMISSIONPWD)
except:
logger.error("Failed to connect to Transmission")
if clientAgent == 'deluge':
try:
logger.debug("Connecting to %s: http://%s:%s", clientAgent, nzbtomedia.DELUGEHOST,
nzbtomedia.DELUGEPORT)
logger.debug("Connecting to %s: http://%s:%s" % (clientAgent, nzbtomedia.DELUGEHOST, nzbtomedia.DELUGEPORT))
TorrentClass = DelugeClient()
TorrentClass.connect(host =nzbtomedia.DELUGEHOST, port =nzbtomedia.DELUGEPORT, username =nzbtomedia.DELUGEUSR, password =nzbtomedia.DELUGEPWD)
TorrentClass.connect(host=nzbtomedia.DELUGEHOST, port=nzbtomedia.DELUGEPORT, username=nzbtomedia.DELUGEUSR,
password=nzbtomedia.DELUGEPWD)
except:
logger.error("Failed to connect to Deluge")
return TorrentClass
def pause_torrent(clientAgent, TorrentClass, inputHash, inputID, inputName):
# if we are using links with Torrents it means we need to pause it in order to access the files
logger.debug("Stoping torrent %s in %s while processing", inputName, clientAgent)
logger.debug("Stoping torrent %s in %s while processing" % (inputName, clientAgent))
if clientAgent == 'utorrent' and TorrentClass != "":
TorrentClass.stop(inputHash)
if clientAgent == 'transmission' and TorrentClass !="":
if clientAgent == 'transmission' and TorrentClass != "":
TorrentClass.stop_torrent(inputID)
if clientAgent == 'deluge' and TorrentClass != "":
TorrentClass.core.pause_torrent([inputID])
time.sleep(5) # Give Torrent client some time to catch up with the change
def resume_torrent(clientAgent, TorrentClass, inputHash, inputID, result, inputName):
# 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.
if (int(nzbtomedia.CFG["Torrent"]["deleteOriginal"]) is 1 and result != 1) or nzbtomedia.USELINK == 'move': # if we move files, nothing to resume seeding.
logger.debug("Deleting torrent %s from %s", inputName, clientAgent)
if (int(nzbtomedia.CFG["Torrent"][
"deleteOriginal"]) is 1 and result != 1) or nzbtomedia.USELINK == 'move': # if we move files, nothing to resume seeding.
logger.debug("Deleting torrent %s from %s" % (inputName, clientAgent))
if clientAgent == 'utorrent' and TorrentClass != "":
TorrentClass.removedata(inputHash)
TorrentClass.remove(inputHash)
if clientAgent == 'transmission' and TorrentClass !="":
if clientAgent == 'transmission' and TorrentClass != "":
TorrentClass.remove_torrent(inputID, True)
if clientAgent == 'deluge' and TorrentClass != "":
TorrentClass.core.remove_torrent(inputID, True)
# we always want to resume seeding, for now manually find out what is wrong when extraction fails
else:
logger.debug("Starting torrent %s in %s", inputName, clientAgent)
logger.debug("Starting torrent %s in %s" % (inputName, clientAgent))
if clientAgent == 'utorrent' and TorrentClass != "":
TorrentClass.start(inputHash)
if clientAgent == 'transmission' and TorrentClass !="":
if clientAgent == 'transmission' and TorrentClass != "":
TorrentClass.start_torrent(inputID)
if clientAgent == 'deluge' and TorrentClass != "":
TorrentClass.core.resume_torrent([inputID])
time.sleep(5)
def find_download(clientAgent, nzbName, download_id):
def find_download(clientAgent, download_id):
tc = create_torrent_class(clientAgent)
logger.debug("Searching for Download on %s ...", clientAgent)
if clientAgent == 'utorrent':
torrents = tc.list()[1]['torrents']
if torrents:
for torrent in torrents:
if nzbName in torrent and download_id in torrent:
if download_id in torrent:
return True
if clientAgent == 'transmission':
torrent = tc.get_torrent(download_id)
if torrent:
name = torrent.name
if name == nzbName:
torrents = tc.get_torrents()
for torrent in torrents:
hash = torrent.hashString
if hash == download_id:
return True
if clientAgent == 'deluge':
pass
@ -507,9 +535,9 @@ def find_download(clientAgent, nzbName, download_id):
url = baseURL
params = {}
params['apikey'] = nzbtomedia.SABNZBDAPIKEY
params['mode'] = "history"
params['mode'] = "get_files"
params['output'] = 'json'
params['value'] = download_id
try:
r = requests.get(url, params=params)
except requests.ConnectionError:
@ -517,7 +545,8 @@ def find_download(clientAgent, nzbName, download_id):
return 1 # failure
result = r.json()
pass
if result['files']:
return True
def clean_nzbname(nzbname):
@ -537,6 +566,7 @@ def clean_nzbname(nzbname):
nzbname = re.sub("^\[.*\]", "", nzbname)
return nzbname.strip()
def isMediaFile(filename):
# ignore samples
if re.search('(^|[\W_])(sample\d*)[\W_]', filename, re.I):
@ -556,6 +586,7 @@ def isMediaFile(filename):
else:
return False
def listMediaFiles(path):
if not dir or not os.path.isdir(path):
return []
@ -572,3 +603,55 @@ def listMediaFiles(path):
files.append(fullCurFile)
return files
def find_imdbid(dirName, nzbName):
imdbid = None
nzbName = clean_nzbname(nzbName)
logger.info('Attemping imdbID lookup for %s' % (nzbName))
# find imdbid in dirName
logger.info('Searching folder name for imdbID ...')
m = re.search('(tt\d{7})', dirName)
if m:
imdbid = m.group(1)
logger.info("Found movie id %s in directory" % imdbid)
return imdbid
# find imdbid in nzbName
logger.info('Searching filename for imdbID ...')
m = re.search('(tt\d{7})', nzbName)
if m:
imdbid = m.group(1)
logger.info("Found imdbid %s in name" % imdbid)
return imdbid
logger.info('Searching IMDB for imdbID ...')
m = re.search("^(.+)(\d{4})\W", nzbName)
if m:
title = m.group(1)
year = m.group(2)
url = "http://www.omdbapi.com"
logger.debug("Opening URL: %s" % url)
try:
r = requests.get(url, params={'y': year, 't': title})
except requests.ConnectionError:
logger.error("Unable to open URL %s" % url)
return
results = r.json()
try:
imdbid = results['imdbID']
except:
pass
if imdbid:
return imdbid
else:
logger.warning('Unable to find a imdbID for %s' % (nzbName))

View file

@ -225,7 +225,7 @@ class GitUpdateManager(UpdateManager):
branch = branch_info.strip().replace('refs/heads/', '', 1)
if branch:
nzbtomedia.NZBTOMEDIA_BRANCH = branch
return nzbtomedia.NZBTOMEDIA_BRANCH
return nzbtomedia.GIT_BRANCH
def _check_github_for_update(self):
"""
@ -273,7 +273,7 @@ class GitUpdateManager(UpdateManager):
logger.log(u"git didn't return numbers for behind and ahead, not using it", logger.DEBUG)
return
logger.log(u"cur_commit = " + str(self._cur_commit_hash) + u", newest_commit = " + str(self._newest_commit_hash)
logger.log(u"cur_commit = " + str(self._cur_commit_hash) + u" % (newest_commit)= " + str(self._newest_commit_hash)
+ u", num_commits_behind = " + str(self._num_commits_behind) + u", num_commits_ahead = " + str(
self._num_commits_ahead), logger.DEBUG)
@ -405,7 +405,7 @@ class SourceUpdateManager(UpdateManager):
# when _cur_commit_hash doesn't match anything _num_commits_behind == 100
self._num_commits_behind += 1
logger.log(u"cur_commit = " + str(self._cur_commit_hash) + u", newest_commit = " + str(self._newest_commit_hash)
logger.log(u"cur_commit = " + str(self._cur_commit_hash) + u" % (newest_commit)= " + str(self._newest_commit_hash)
+ u", num_commits_behind = " + str(self._num_commits_behind), logger.DEBUG)
def set_newest_text(self):

View file

@ -4,29 +4,10 @@ import nzbtomedia
import TorrentToMedia
from nzbtomedia.nzbToMediaUtil import find_download, clean_nzbname, listMediaFiles
os.environ['TR_TORRENT_DIR']="z:/downloads/complete/movie/The.Art.of.the.Steal.2013.LIMITED.1080p.BRRip.h264.AAC-RARBG"
os.environ['TR_TORRENT_NAME']="The.Art.of.the.Steal.2013.LIMITED.1080p.BRRip.h264.AAC-RARBG"
os.environ['TR_TORRENT_ID']="154206e6390a03bbf01e61f013e1a52494a52dfa"
os.environ['TR_TORRENT_HASH']="154206e6390a03bbf01e61f013e1a52494a52dfa"
#TorrentToMedia.main(sys.argv)
test = 'The.Art.of.the.Steal.2013.LIMITED.1080p.BRRip.h264.AAC-RARBG'
cleaned = clean_nzbname(test)
# Initialize the config
nzbtomedia.initialize()
dirName = 'Z:/complete/tv/'
test = listMediaFiles('Z:/complete/tv/')
for filename in test:
parentDir = os.path.dirname(filename)
if parentDir == dirName:
pass
clientAgent = nzbtomedia.NZB_CLIENTAGENT
nzbName = 'Anger.Management.S02E57.HDTV.x264-KILLERS'
#download_id = '51C9B415382894727C5C7D8442554D3AC08B390F'
download_id = 'SABnzbd_nzo_uBYaGb'
if find_download(clientAgent, nzbName, download_id):
download_id = 'SABnzbd_nzo_qhoQ7m'
if find_download('sabnzbd', download_id):
print 'found'
else:
print 'no luck'