Massive changes to the way we handle our config, its now loaded and stored in memory so that we don't keep loading it and possibly get corrupt values.

New logger class added,logger options removed from settings.
This commit is contained in:
echel0n 2014-04-11 20:09:00 -07:00
commit 18926d1db8
30 changed files with 1603 additions and 1058 deletions

View file

@ -62,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(nzbtomedia.NZBGET_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(nzbtomedia.NZBGET_POSTPROCESS_NONE)
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4':
print "Par-repair failed, setting status \"failed\"."
@ -99,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(nzbtomedia.NZBGET_POSTPROCESS_NONE)
mediaContainer = os.environ['NZBPO_MEDIAEXTENSIONS'].split(',')
SampleIDs = os.environ['NZBPO_SAMPLEIDS'].split(',')
@ -116,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(nzbtomedia.NZBGET_POSTPROCESS_ERROR)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_SUCCESS)
else:
print "This script can only be called from NZBGet (11.0 or later)."

View file

@ -29,13 +29,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(nzbtomedia.NZBGET_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(nzbtomedia.NZBGET_POSTPROCESS_NONE)
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4':
print "Par-repair failed, setting status \"failed\"."
@ -66,7 +66,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(nzbtomedia.NZBGET_POSTPROCESS_NONE)
directory = os.path.normpath(os.environ['NZBPP_DIRECTORY'])
for dirpath, dirnames, filenames in os.walk(directory):
@ -78,8 +78,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(nzbtomedia.NZBGET_POSTPROCESS_ERROR)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_SUCCESS)
else:
print "This script can only be called from NZBGet (11.0 or later)."

View file

@ -1,14 +1,12 @@
#!/usr/bin/env python
# adds lib directory to system path
import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib')))
import datetime
import os
import time
import logging
import re
import shutil
import sys
import nzbtomedia
from subprocess import Popen
from nzbtomedia.autoProcess.autoProcessComics import autoProcessComics
from nzbtomedia.autoProcess.autoProcessGames import autoProcessGames
@ -16,13 +14,11 @@ from nzbtomedia.autoProcess.autoProcessMovie import autoProcessMovie
from nzbtomedia.autoProcess.autoProcessMusic import autoProcessMusic
from nzbtomedia.autoProcess.autoProcessTV import autoProcessTV
from nzbtomedia.extractor import extractor
from nzbtomedia.nzbToMediaAutoFork import autoFork
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import category_search, safeName, is_sample, copy_link, WakeUp, parse_args, flatten, \
nzbtomedia_configure_logging, get_dirnames
from nzbtomedia.nzbToMediaUtil import category_search, safeName, is_sample, copy_link, parse_args, flatten, get_dirnames
from nzbtomedia.synchronousdeluge.client import DelugeClient
from nzbtomedia.utorrent.client import UTorrentClient
from nzbtomedia.transmissionrpc.client import Client as TransmissionClient
from nzbtomedia import logger
def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
@ -32,54 +28,51 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
archive = int(0)
foundFile = int(0)
extracted_folder = []
extractionSuccess = False
copy_list = []
file = None
Logger.debug("MAIN: 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, categories) # Confirm the category by parsing directory structure
inputDirectory, inputName, inputCategory, root, single = category_search(inputDirectory, inputName, inputCategory, root, nzbtomedia.CATEGORIES) # Confirm the category by parsing directory structure
Logger.debug("MAIN: Determined Directory: %s | Name: %s | Category: %s", inputDirectory, inputName, inputCategory)
logger.debug("Determined Directory: %s | Name: %s | Category: %s", inputDirectory, inputName, inputCategory)
TorrentClass = create_torrent_class(clientAgent, inputHash)
pause_torrent(clientAgent, TorrentClass, inputHash, inputID, inputName)
TorrentClass = create_torrent_class(nzbtomedia.CLIENTAGENT, inputHash)
pause_torrent(nzbtomedia.CLIENTAGENT, TorrentClass, inputHash, inputID, inputName)
processCategories = config()[sections].sections
processCategories = nzbtomedia.CFG[nzbtomedia.SECTIONS].sections
outputDestination = ""
if inputCategory == "":
inputCategory = "UNCAT"
outputDestination = os.path.normpath(os.path.join(outputDirectory, inputCategory, safeName(inputName)))
Logger.info("MAIN: Output directory set to: %s", outputDestination)
outputDestination = os.path.normpath(os.path.join(nzbtomedia.OUTPUTDIRECTORY, inputCategory, safeName(inputName)))
logger.postprocess("Output directory set to: %s", outputDestination)
if config()["SickBeard"].issubsection(inputCategory):
Torrent_NoLink = int(config()["SickBeard"][inputCategory]["Torrent_NoLink"]) # 0
if nzbtomedia.CFG["SickBeard"].issubsection(inputCategory):
Torrent_NoLink = int(nzbtomedia.CFG["SickBeard"][inputCategory]["Torrent_NoLink"]) # 0
if Torrent_NoLink == 1:
Logger.info("MAIN: Calling autoProcessTV to post-process: %s",inputName)
result = autoProcessTV().processEpisode(inputDirectory, inputName, 0, clientAgent=clientAgent, inputCategory=inputCategory)
logger.postprocess("Calling autoProcessTV to post-process: %s",inputName)
result = autoProcessTV().processEpisode(inputDirectory, inputName, 0, clientAgent=nzbtomedia.CLIENTAGENT, inputCategory=inputCategory)
if result != 0:
Logger.info("MAIN: A problem was reported in the autoProcessTV script.")
resume_torrent(clientAgent, TorrentClass, inputHash, inputID, result, inputName)
logger.error("A problem was reported in the autoProcessTV script.")
resume_torrent(nzbtomedia.CLIENTAGENT, TorrentClass, inputHash, inputID, result, inputName)
cleanup_output(inputCategory, processCategories, result, outputDestination)
Logger.info("MAIN: All done.")
logger.postprocess("All done.")
sys.exit()
processOnly = config()[sections].sections
if not "NONE" in user_script_categories: # if None, we only process the 5 listed.
if "ALL" in user_script_categories: # All defined categories
processOnly = categories
processOnly.extend(user_script_categories) # Adds all categories to be processed by userscript.
processOnly = nzbtomedia.CFG[nzbtomedia.SECTIONS].sections
if not "NONE" in nzbtomedia.USER_SCRIPT_CATEGORIES: # if None, we only process the 5 listed.
if "ALL" in nzbtomedia.USER_SCRIPT_CATEGORIES: # All defined categories
processOnly = nzbtomedia.CATEGORIES
processOnly.extend(nzbtomedia.USER_SCRIPT_CATEGORIES) # Adds all categories to be processed by userscript.
if not inputCategory in processOnly:
Logger.info("MAIN: No processing to be done for category: %s. Exiting", inputCategory)
Logger.info("MAIN: All done.")
logger.postprocess("No processing to be done for category: %s. Exiting", inputCategory)
logger.postprocess("All done.")
sys.exit()
Logger.debug("MAIN: Scanning files in directory: %s", inputDirectory)
logger.debug("Scanning files in directory: %s", inputDirectory)
if config()["HeadPhones"].issubsection(inputCategory):
noFlatten.extend(config()["HeadPhones"].sections) # Make sure we preserve folder structure for HeadPhones.
if nzbtomedia.CFG["HeadPhones"].issubsection(inputCategory):
nzbtomedia.NOFLATTEN.extend(nzbtomedia.CFG["HeadPhones"].sections) # 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()
@ -88,132 +81,133 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
if single:
dirnames[:] = []
filenames[:] = [filenames] # we just want to work with this one file if single = True
Logger.debug("MAIN: 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)
if inputCategory in noFlatten and not single:
if inputCategory in nzbtomedia.NOFLATTEN and not single:
newDir = dirpath # find the full path
newDir = newDir.replace(inputDirectory, "") #find the extra-depth directory
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("MAIN: 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("MAIN: 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("MAIN: 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
if root == 2:
if foundFile == int(0):
Logger.debug("MAIN: Looking for files with modified/created dates less than 5 minutes old.")
logger.debug("Looking for files with modified/created dates less than 5 minutes old.")
mtime_lapse = now - datetime.datetime.fromtimestamp(os.path.getmtime(os.path.join(dirpath, file)))
ctime_lapse = now - datetime.datetime.fromtimestamp(os.path.getctime(os.path.join(dirpath, file)))
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("MAIN: 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 mediaContainer and is_sample(filePath, inputName, minSampleSize, SampleIDs) and not config()["HeadPhones"].issubsection(inputCategory): # Ignore samples
Logger.info("MAIN: Ignoring sample file: %s ", filePath)
if fileExtension in nzbtomedia.MEDIACONTAINER and is_sample(filePath, inputName, nzbtomedia.MINSAMPLESIZE,
nzbtomedia.SAMPLEIDS) and not nzbtomedia.CFG["HeadPhones"].issubsection(inputCategory): # Ignore samples
logger.postprocess("Ignoring sample file: %s ", filePath)
continue
if fileExtension in compressedContainer:
if (config()["SickBeard"].issubsection(inputCategory) and config()["SickBeard"][inputCategory]["nzbExtractionBy"] == "Destination"):
if fileExtension in nzbtomedia.COMPRESSEDCONTAINER:
if (nzbtomedia.CFG["SickBeard"].issubsection(inputCategory) and nzbtomedia.CFG["SickBeard"][inputCategory]["nzbExtractionBy"] == "Destination"):
# 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())
if part == 1: # we only want to extract the primary part.
Logger.debug("MAIN: 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("MAIN: 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.info("MAIN: 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.exception("MAIN: Extraction failed for: %s", file)
logger.error("Extraction failed for: %s", file)
continue
try:
copy_link(filePath, targetDirectory, useLink, outputDestination)
copy_link(filePath, targetDirectory, nzbtomedia.USELINK, outputDestination)
copy_list.append([filePath, os.path.join(outputDestination, file)])
except:
Logger.exception("MAIN: Failed to link file: %s", file)
logger.error("Failed to link file: %s", file)
outputDestination = outputDestinationMaster # Reset here.
if not inputCategory in noFlatten: #don't flatten hp in case multi cd albums, and we need to copy this back later.
if not inputCategory in nzbtomedia.NOFLATTEN: #don't flatten hp in case multi cd albums, and we need to copy this back later.
flatten(outputDestination)
# Now check if video files exist in destination:
if config()["SickBeard","NzbDrone", "CouchPotato"].issubsection(inputCategory):
if nzbtomedia.CFG["SickBeard","NzbDrone", "CouchPotato"].issubsection(inputCategory):
for dirpath, dirnames, filenames in os.walk(outputDestination):
for file in filenames:
filePath = os.path.join(dirpath, file)
fileName, fileExtension = os.path.splitext(file)
if fileExtension in mediaContainer: # If the file is a video file
Logger.debug("MAIN: Found media file: %s", filePath)
if fileExtension in nzbtomedia.MEDIACONTAINER: # If the file is a video file
logger.debug("Found media file: %s", filePath)
video += 1
if fileExtension in compressedContainer: # If the file is an archive file
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("MAIN: Found %s media files", str(video))
logger.debug("Found %s media files", str(video))
status = int(0)
elif not (config()["SickBeard"].issubsection(inputCategory) and config()["SickBeard"][inputCategory]["nzbExtractionBy"] == "Destination") and archive > int(0):
Logger.debug("MAIN: Found %s archive files to be extracted by SickBeard", str(archive))
elif not (nzbtomedia.CFG["SickBeard"].issubsection(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))
status = int(0)
else:
Logger.warning("MAIN: Found no media files in output.")
logger.warning("Found no media files in output.")
if (inputCategory in user_script_categories and not "NONE" in user_script_categories) or ("ALL" in user_script_categories and not inputCategory in processCategories):
Logger.info("MAIN: Processing user script %s.", user_script)
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.", user_script)
result = external_script(outputDestination,inputName,inputCategory)
elif status == int(0) or (config()['HeadPhones','Mylar','Gamez'].issubsection(inputCategory)): # if movies linked/extracted or for other categories.
Logger.debug("MAIN: Calling autoProcess script for successful download.")
elif status == int(0) or (nzbtomedia.CFG['HeadPhones','Mylar','Gamez'].issubsection(inputCategory)): # if movies linked/extracted or for other categories.
logger.debug("Calling autoProcess script for successful download.")
status = int(0) # hp, my, gz don't support failed.
else:
Logger.error("MAIN: Something failed! Please check logs. Exiting")
logger.error("Something failed! Please check logs. Exiting")
sys.exit(-1)
result = 0
if config()['CouchPotato'].issubsection(inputCategory):
Logger.info("MAIN: Calling CouchPotato:" + inputCategory + " to post-process: %s", inputName)
if nzbtomedia.CFG['CouchPotato'].issubsection(inputCategory):
logger.postprocess("Calling CouchPotato:" + inputCategory + " to post-process: %s", inputName)
download_id = inputHash
result = autoProcessMovie().process(outputDestination, inputName, status, clientAgent, download_id, inputCategory)
elif config()['SickBeard'].issubsection(inputCategory):
Logger.info("MAIN: Calling Sick-Beard:" + inputCategory + " to post-process: %s", inputName)
result = autoProcessTV().processEpisode(outputDestination, inputName, status, clientAgent, inputCategory)
elif config()['NzbDrone'].issubsection(inputCategory):
Logger.info("MAIN: Calling NzbDrone:" + inputCategory + " to post-process: %s", inputName)
result = autoProcessTV().processEpisode(outputDestination, inputName, status, clientAgent, inputCategory)
elif config()['HeadPhones'].issubsection(inputCategory):
Logger.info("MAIN: Calling HeadPhones:" + inputCategory + " to post-process: %s", inputName)
result = autoProcessMusic().process(inputDirectory, inputName, status, clientAgent, inputCategory)
elif config()['Mylar'].issubsection(inputCategory):
Logger.info("MAIN: Calling Mylar:" + inputCategory + " to post-process: %s", inputName)
result = autoProcessComics().processEpisode(outputDestination, inputName, status, clientAgent, inputCategory)
elif config()['Gamez'].issubsection(inputCategory):
Logger.info("MAIN: Calling Gamez:" + inputCategory + " to post-process: %s", inputName)
result = autoProcessGames().process(outputDestination, inputName, status, clientAgent, inputCategory)
result = autoProcessMovie().process(outputDestination, inputName, status, nzbtomedia.CLIENTAGENT, download_id, inputCategory)
elif nzbtomedia.CFG['SickBeard'].issubsection(inputCategory):
logger.postprocess("Calling Sick-Beard:" + inputCategory + " to post-process: %s", inputName)
result = autoProcessTV().processEpisode(outputDestination, inputName, status, nzbtomedia.CLIENTAGENT, inputCategory)
elif nzbtomedia.CFG['NzbDrone'].issubsection(inputCategory):
logger.postprocess("Calling NzbDrone:" + inputCategory + " to post-process: %s", inputName)
result = autoProcessTV().processEpisode(outputDestination, inputName, status, nzbtomedia.CLIENTAGENT, inputCategory)
elif nzbtomedia.CFG['HeadPhones'].issubsection(inputCategory):
logger.postprocess("Calling HeadPhones:" + inputCategory + " to post-process: %s", inputName)
result = autoProcessMusic().process(inputDirectory, inputName, status, nzbtomedia.CLIENTAGENT, inputCategory)
elif nzbtomedia.CFG['Mylar'].issubsection(inputCategory):
logger.postprocess("Calling Mylar:" + inputCategory + " to post-process: %s", inputName)
result = autoProcessComics().processEpisode(outputDestination, inputName, status, nzbtomedia.CLIENTAGENT, inputCategory)
elif nzbtomedia.CFG['Gamez'].issubsection(inputCategory):
logger.postprocess("Calling Gamez:" + inputCategory + " to post-process: %s", inputName)
result = autoProcessGames().process(outputDestination, inputName, status, nzbtomedia.CLIENTAGENT, inputCategory)
if result == 1:
Logger.info("MAIN: A problem was reported in the autoProcess* script. If torrent was paused we will resume seeding")
logger.error("A problem was reported in the autoProcess* script. If torrent was paused we will resume seeding")
resume_torrent(clientAgent, TorrentClass, inputHash, inputID, result, inputName)
resume_torrent(nzbtomedia.CLIENTAGENT, TorrentClass, inputHash, inputID, result, inputName)
cleanup_output(inputCategory, processCategories, result, outputDestination)
Logger.info("MAIN: All done.")
logger.postprocess("All done.")
def create_torrent_class(clientAgent, inputHash):
# Hardlink solution for Torrents
@ -221,31 +215,34 @@ def create_torrent_class(clientAgent, inputHash):
if clientAgent in ['utorrent', 'transmission', 'deluge'] and inputHash:
if clientAgent == 'utorrent':
try:
Logger.debug("MAIN: Connecting to %s: %s", clientAgent, uTorrentWEBui)
TorrentClass = UTorrentClient(uTorrentWEBui, uTorrentUSR, uTorrentPWD)
logger.debug("Connecting to %s: %s", clientAgent, nzbtomedia.UTORRENTWEBUI)
TorrentClass = UTorrentClient(nzbtomedia.UTORRENTWEBUI, nzbtomedia.UTORRENTUSR, nzbtomedia.UTORRENTPWD)
except:
Logger.exception("MAIN: Failed to connect to uTorrent")
logger.error("Failed to connect to uTorrent")
if clientAgent == 'transmission':
try:
Logger.debug("MAIN: Connecting to %s: http://%s:%s", clientAgent, TransmissionHost, TransmissionPort)
TorrentClass = TransmissionClient(TransmissionHost, TransmissionPort, TransmissionUSR, TransmissionPWD)
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.exception("MAIN: Failed to connect to Transmission")
logger.error("Failed to connect to Transmission")
if clientAgent == 'deluge':
try:
Logger.debug("MAIN: Connecting to %s: http://%s:%s", clientAgent, DelugeHost, DelugePort)
logger.debug("Connecting to %s: http://%s:%s", clientAgent, nzbtomedia.DELUGEHOST,
nzbtomedia.DELUGEPORT)
TorrentClass = DelugeClient()
TorrentClass.connect(host = DelugeHost, port = DelugePort, username = DelugeUSR, password = DelugePWD)
TorrentClass.connect(host =nzbtomedia.DELUGEHOST, port =nzbtomedia.DELUGEPORT, username =nzbtomedia.DELUGEUSR, password =nzbtomedia.DELUGEPWD)
except:
Logger.exception("MAIN: Failed to connect to deluge")
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("MAIN: 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 !="":
@ -258,8 +255,8 @@ def resume_torrent(clientAgent, TorrentClass, inputHash, inputID, result, inputN
# 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(config()["Torrent"]["deleteOriginal"]) is 1 and result != 1) or useLink == 'move': # if we move files, nothing to resume seeding.
Logger.debug("MAIN: 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)
@ -269,7 +266,7 @@ def resume_torrent(clientAgent, TorrentClass, inputHash, inputID, result, inputN
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("MAIN: 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 !="":
@ -286,16 +283,16 @@ def cleanup_output(inputCategory, processCategories, result, outputDestination):
for file in filenames:
filePath = os.path.join(dirpath, file)
fileName, fileExtension = os.path.splitext(file)
if fileExtension in mediaContainer or fileExtension in metaContainer:
if fileExtension in nzbtomedia.MEDIACONTAINER or fileExtension in nzbtomedia.METACONTAINER:
num_files_new += 1
file_list.append(file)
if num_files_new is 0 or int(config()["Torrent"]["forceClean"]) is 1:
Logger.info("All files have been processed. Cleaning outputDirectory %s", outputDestination)
if num_files_new is 0 or int(nzbtomedia.CFG["Torrent"]["forceClean"]) is 1:
logger.postprocess("All files have been processed. Cleaning outputDirectory %s", outputDestination)
shutil.rmtree(outputDestination)
else:
Logger.info("outputDirectory %s still contains %s media and/or meta files. This directory will not be removed.", outputDestination, num_files_new)
logger.postprocess("outputDirectory %s still contains %s media and/or meta files. This directory will not be removed.", outputDestination, num_files_new)
for item in file_list:
Logger.debug("media/meta file found: %s", item)
logger.debug("media/meta file found: %s", item)
def external_script(outputDestination, torrentName, torrentLabel):
@ -337,19 +334,19 @@ def external_script(outputDestination, torrentName, torrentLabel):
cmd = ""
for item in command:
cmd = cmd + " " + item
Logger.info("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 user_script_successCodes: # Linux returns 0 for successful.
Logger.info("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.info("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.exception("UserScript %s has failed", command[0])
logger.error("UserScript %s has failed", command[0])
result = int(1)
final_result = final_result + result
@ -364,90 +361,49 @@ def external_script(outputDestination, torrentName, torrentLabel):
num_files_new = num_files_new + 1
if user_script_clean == int(1) and num_files_new == int(0) and final_result == int(0):
Logger.info("All files have been processed. Cleaning outputDirectory %s", outputDestination)
logger.postprocess("All files have been processed. Cleaning outputDirectory %s", outputDestination)
shutil.rmtree(outputDestination)
elif user_script_clean == int(1) and num_files_new != int(0):
Logger.info("%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
if __name__ == "__main__":
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
if config().migrate():
nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log
Logger.info("TorrentToMedia %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
WakeUp()
# Initialize the config
nzbtomedia.initialize()
# EXAMPLE VALUES:
clientAgent = config()["Torrent"]["clientAgent"] # utorrent | deluge | transmission | rtorrent | other
useLink = config()["Torrent"]["useLink"] # no | hard | sym
outputDirectory = config()["Torrent"]["outputDirectory"] # /abs/path/to/complete/
categories = (config()["Torrent"]["categories"]) # music,music_videos,pictures,software
noFlatten = (config()["Torrent"]["noFlatten"])
if not "NONE" in nzbtomedia.USER_SCRIPT_CATEGORIES:
user_script_mediaExtensions = (nzbtomedia.CFG["UserScript"]["user_script_mediaExtensions"])
user_script = nzbtomedia.CFG["UserScript"]["user_script_path"]
user_script_param = (nzbtomedia.CFG["UserScript"]["user_script_param"])
user_script_successCodes = (nzbtomedia.CFG["UserScript"]["user_script_successCodes"])
user_script_clean = int(nzbtomedia.CFG["UserScript"]["user_script_clean"])
user_delay = int(nzbtomedia.CFG["UserScript"]["delay"])
user_script_runOnce = int(nzbtomedia.CFG["UserScript"]["user_script_runOnce"])
uTorrentWEBui = config()["Torrent"]["uTorrentWEBui"] # http://localhost:8090/gui/
uTorrentUSR = config()["Torrent"]["uTorrentUSR"] # mysecretusr
uTorrentPWD = config()["Torrent"]["uTorrentPWD"] # mysecretpwr
TransmissionHost = config()["Torrent"]["TransmissionHost"] # localhost
TransmissionPort = config()["Torrent"]["TransmissionPort"] # 8084
TransmissionUSR = config()["Torrent"]["TransmissionUSR"] # mysecretusr
TransmissionPWD = config()["Torrent"]["TransmissionPWD"] # mysecretpwr
DelugeHost = config()["Torrent"]["DelugeHost"] # localhost
DelugePort = config()["Torrent"]["DelugePort"] # 8084
DelugeUSR = config()["Torrent"]["DelugeUSR"] # mysecretusr
DelugePWD = config()["Torrent"]["DelugePWD"] # mysecretpwr
compressedContainer = (config()["Extensions"]["compressedExtensions"]) # .zip,.rar,.7z
mediaContainer = (config()["Extensions"]["mediaExtensions"]) # .mkv,.avi,.divx
metaContainer = (config()["Extensions"]["metaExtensions"]) # .nfo,.sub,.srt
minSampleSize = int(config()["Extensions"]["minSampleSize"]) # 200 (in MB)
SampleIDs = (config()["Extensions"]["SampleIDs"]) # sample,-s.
sections = ("CouchPotato", "SickBeard", "NzbDrone", "HeadPhones", "Mylar", "Gamez")
subsections = config()[sections].subsections
categories += config()[sections].sections
user_script_categories = config()["UserScript"]["user_script_categories"] # NONE
if not "NONE" in user_script_categories:
user_script_mediaExtensions = (config()["UserScript"]["user_script_mediaExtensions"])
user_script = config()["UserScript"]["user_script_path"]
user_script_param = (config()["UserScript"]["user_script_param"])
user_script_successCodes = (config()["UserScript"]["user_script_successCodes"])
user_script_clean = int(config()["UserScript"]["user_script_clean"])
user_delay = int(config()["UserScript"]["delay"])
user_script_runOnce = int(config()["UserScript"]["user_script_runOnce"])
transcode = int(config()["Transcoder"]["transcode"])
transcode = int(nzbtomedia.CFG["Transcoder"]["transcode"])
n = 0
for arg in sys.argv:
Logger.debug("arg %s is: %s", n, arg)
logger.debug("arg %s is: %s", n, arg)
n = n+1
try:
inputDirectory, inputName, inputCategory, inputHash, inputID = parse_args(clientAgent)
inputDirectory, inputName, inputCategory, inputHash, inputID = parse_args(nzbtomedia.CLIENTAGENT)
except:
Logger.exception("MAIN: There was a problem loading variables")
logger.error("There was a problem loading variables")
sys.exit(-1)
# check if this is a manual run
if inputDirectory is None:
for section, subsection in subsections.items():
for section, subsection in nzbtomedia.SUBSECTIONS.items():
for category in subsection:
if config()[section].isenabled(category):
if nzbtomedia.CFG[section].isenabled(category):
dirNames = get_dirnames(section, category)
for dirName in dirNames:
Logger.info("MAIN: TorrentToMedia 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)
main(dirName, os.path.basename(dirName), category, inputHash, inputID)
else:
Logger.info("MAIN: nzbTo%s %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...",section, section, category)
logger.warning("%s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
else:
main(inputDirectory, inputName, inputCategory, inputHash, inputID)

View file

@ -1,23 +0,0 @@
[loggers]
keys = root
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = NOTSET
handlers = console
qualname =
[handler_console]
class = StreamHandler
args = (sys.stdout,)
level = INFO
formatter = generic
[formatter_generic]
format = %(asctime)s|%(levelname)-7.7s %(message)s
datefmt = %H:%M:%S

View file

@ -1,23 +0,0 @@
[loggers]
keys = root
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = NOTSET
handlers = console
qualname =
[handler_console]
class = StreamHandler
args = (sys.stdout,)
level = INFO
formatter = generic
[formatter_generic]
format = %(asctime)s|%(levelname)-7.7s %(message)s
datefmt = %H:%M:%S

100
logs/nzbtomedia.log Normal file
View file

@ -0,0 +1,100 @@
2014-04-11 15:52:44 INFO :: MAIN :: nzbToMedia None
2014-04-11 15:52:44 INFO :: MAIN :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 15:52:44 POSTPROCESS:: CouchPotato:movie is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:52:44 POSTPROCESS:: NzbDrone:tv is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:52:44 WARNING :: MAIN :: SickBeard:tv has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.
2014-04-11 15:52:44 WARNING :: MAIN :: SickBeard:tvs has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.
2014-04-11 15:52:44 POSTPROCESS:: HeadPhones:music is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:52:44 POSTPROCESS:: Gamez:games is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:52:44 POSTPROCESS:: Mylar:comics is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:53:23 INFO :: nzbToMedia None
2014-04-11 15:53:23 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 15:53:23 POSTPROCESS:: CouchPotato:movie is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:53:23 POSTPROCESS:: NzbDrone:tv is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:53:23 WARNING :: SickBeard:tv has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.
2014-04-11 15:53:23 WARNING :: SickBeard:tvs has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.
2014-04-11 15:53:23 POSTPROCESS:: HeadPhones:music is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:53:23 POSTPROCESS:: Gamez:games is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:53:23 POSTPROCESS:: Mylar:comics is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:59:32 INFO :: nzbToMedia None
2014-04-11 15:59:32 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 15:59:32 WARNING :: CouchPotato:movie is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:59:32 WARNING :: NzbDrone:tv is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:59:32 WARNING :: SickBeard:tv has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.
2014-04-11 15:59:32 WARNING :: SickBeard:tvs has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.
2014-04-11 15:59:32 WARNING :: HeadPhones:music is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:59:32 WARNING :: Gamez:games is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 15:59:32 WARNING :: Mylar:comics is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 16:02:05 INFO :: nzbToMedia None
2014-04-11 16:02:05 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 16:02:05 INFO :: Checking if nzbToMedia needs an update
2014-04-11 16:02:46 INFO :: nzbToMedia None
2014-04-11 16:02:46 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 16:02:46 INFO :: Checking if nzbToMedia needs an update
2014-04-11 16:03:52 INFO :: nzbToMedia None
2014-04-11 16:03:52 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 16:03:52 INFO :: Checking if nzbToMedia needs an update
2014-04-11 16:06:18 INFO :: nzbToMedia None
2014-04-11 16:06:18 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 16:06:18 INFO :: Checking if nzbToMedia needs an update
2014-04-11 16:07:29 INFO :: nzbToMedia None
2014-04-11 16:07:29 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 16:07:29 INFO :: Checking if nzbToMedia needs an update
2014-04-11 19:16:55 INFO :: nzbToMedia None
2014-04-11 19:16:55 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:16:55 INFO :: Checking if nzbToMedia needs an update
2014-04-11 19:18:48 INFO :: nzbToMedia None
2014-04-11 19:18:48 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:18:48 INFO :: Checking if nzbToMedia needs an update
2014-04-11 19:22:01 INFO :: nzbToMedia None
2014-04-11 19:22:04 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:22:09 INFO :: nzbToMedia None
2014-04-11 19:22:26 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:22:41 INFO :: nzbToMedia None
2014-04-11 19:23:02 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:23:44 INFO :: nzbToMedia None
2014-04-11 19:23:45 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:23:48 INFO :: Checking if nzbToMedia needs an update
2014-04-11 19:25:01 INFO :: nzbToMedia None
2014-04-11 19:25:01 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:25:01 INFO :: Checking if nzbToMedia needs an update
2014-04-11 19:25:14 INFO :: nzbToMedia None
2014-04-11 19:25:14 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:25:14 INFO :: Checking if nzbToMedia needs an update
2014-04-11 19:25:44 INFO :: nzbToMedia None
2014-04-11 19:25:44 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:29:50 INFO :: nzbToMedia None
2014-04-11 19:29:50 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:29:50 WARNING :: CouchPotato:movie is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 19:29:50 WARNING :: NzbDrone:tv is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 19:29:50 WARNING :: SickBeard:tv has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.
2014-04-11 19:29:50 WARNING :: SickBeard:tvs has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.
2014-04-11 19:29:50 WARNING :: HeadPhones:music is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 19:29:50 WARNING :: Gamez:games is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 19:29:50 WARNING :: Mylar:comics is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 19:33:19 INFO :: nzbToMedia None
2014-04-11 19:33:19 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:33:19 WARNING :: CouchPotato:movie is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 19:33:19 WARNING :: NzbDrone:tv is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 19:33:19 WARNING :: SickBeard:tv has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.
2014-04-11 19:33:19 WARNING :: SickBeard:tvs has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.
2014-04-11 19:33:19 WARNING :: HeadPhones:music is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 19:33:19 WARNING :: Gamez:games is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 19:33:19 WARNING :: Mylar:comics is DISABLED, you can enable this in autoProcessMedia.cfg ...
2014-04-11 19:33:27 INFO :: nzbToMedia None
2014-04-11 19:33:27 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:33:30 INFO :: Checking if nzbToMedia needs an update
2014-04-11 19:37:17 POSTPROCESS:: nzbToMedia None
2014-04-11 19:37:17 POSTPROCESS:: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:37:17 POSTPROCESS:: Checking if nzbToMedia needs an update
2014-04-11 19:38:15 INFO :: nzbToMedia None
2014-04-11 19:38:15 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:38:15 POSTPROCESS:: test
2014-04-11 19:38:15 INFO :: Checking if nzbToMedia needs an update
2014-04-11 19:38:55 INFO :: nzbToMedia None
2014-04-11 19:38:55 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:38:55 INFO :: Checking if nzbToMedia needs an update
2014-04-11 19:39:26 INFO :: nzbToMedia None
2014-04-11 19:39:26 INFO :: Loading config from C:\Users\Justin\Documents\Git Projects\nzbToMedia\autoProcessMedia.cfg
2014-04-11 19:39:26 INFO :: Checking if nzbToMedia needs an update
2014-04-11 19:39:27 INFO :: Unknown current version number, don't know if we should update or not

View file

@ -1,10 +1,4 @@
#!/usr/bin/env python
# adds lib directory to system path
import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib')))
#
##############################################################################
### NZBGET POST-PROCESSING SCRIPT ###
@ -128,31 +122,20 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib'
##############################################################################
import logging
import os
import sys
import nzbtomedia
from nzbtomedia.autoProcess.autoProcessMovie import autoProcessMovie
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import nzbtomedia_configure_logging, WakeUp, get_dirnames
from nzbtomedia.nzbToMediaUtil import get_dirnames
from nzbtomedia import logger
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
if config().migrate():
# check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'):
config().addnzbget()
nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log
Logger.info("nzbToCouchPotato %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
WakeUp()
# Initialize the config
nzbtomedia.initialize()
# 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.info("MAIN: Script triggered from NZBGet (11.0 or later).")
logger.postprocess("Script triggered from NZBGet (11.0 or later).")
# NZBGet argv: all passed as environment variables.
clientAgent = "nzbget"
@ -161,49 +144,49 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
status = 0
if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
logger.error("Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)
# Check par status
if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(config.NZBGET_POSTPROCESS_NONE)
logger.warning("Par-check successful, but Par-repair disabled, exiting")
logger.postprocess("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':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
logger.warning("Par-repair failed, setting status \"failed\"")
status = 1
# Check unpack status
if os.environ['NZBPP_UNPACKSTATUS'] == '1':
Logger.warning("MAIN: Unpack failed, setting status \"failed\"")
logger.warning("Unpack failed, setting status \"failed\"")
status = 1
if os.environ['NZBPP_UNPACKSTATUS'] == '0' and os.environ['NZBPP_PARSTATUS'] == '0':
# Unpack was skipped due to nzb-file properties or due to errors during par-check
if os.environ['NZBPP_HEALTH'] < 1000:
Logger.warning("MAIN: Download health is compromised and Par-check/repair disabled or no .par2 files found. Setting status \"failed\"")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
status = 1
else:
Logger.info("MAIN: Par-check/repair disabled or no .par2 files found, and Unpack not required. Health is ok so handle as though download successful")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
# Check if destination directory exists (important for reprocessing of history items)
if not os.path.isdir(os.environ['NZBPP_DIRECTORY']):
Logger.error("MAIN: 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
# All checks done, now launching the script.
download_id = ""
if os.environ.has_key('NZBPR_COUCHPOTATO'): download_id = os.environ['NZBPR_COUCHPOTATO']
Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessMovie...")
logger.postprocess("Script triggered from NZBGet, starting autoProcessMovie...")
result = autoProcessMovie().process(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBFILENAME'], clientAgent="nzbget", inputCategory=os.environ['NZBPP_CATEGORY'])
# SABnzbd Pre 0.7.17
elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
elif len(sys.argv) == nzbtomedia.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -212,10 +195,10 @@ elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# 5 User-defined category
# 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
Logger.info("MAIN: Script triggered from SABnzbd, starting autoProcessMovie...")
logger.postprocess("Script triggered from SABnzbd, starting autoProcessMovie...")
result = autoProcessMovie().process(sys.argv[1], sys.argv[2], status=sys.argv[7], inputCategory=sys.argv[5], clientAgent = "sabnzbd", download_id='')
# SABnzbd 0.7.17+
elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
elif len(sys.argv) >= nzbtomedia.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -225,31 +208,30 @@ elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# 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
# 8 Failure URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessMovie...")
logger.postprocess("Script triggered from SABnzbd 0.7.17+, starting autoProcessMovie...")
result = autoProcessMovie().process(sys.argv[1], sys.argv[2], status=sys.argv[7], inputCategory=sys.argv[5], clientAgent = "sabnzbd", download_id='')
else:
result = 0
subsections = config()["CouchPotato"].subsections
Logger.warn("MAIN: Invalid number of arguments received from client.")
for section, subsection in subsections.items():
logger.warning("Invalid number of arguments received from client.")
for section, subsection in nzbtomedia.SUBSECTIONS['CouchPotato'].items():
for category in subsection:
if config()[section].isenabled(category):
if nzbtomedia.CFG[section].isenabled(category):
dirNames = get_dirnames(section, category)
for dirName in dirNames:
Logger.info("MAIN: nzbToCouchPotato running %s:%s as a manual run on folder %s ...", section, category, dirName)
logger.postprocess("Running %s:%s as a manual run on folder %s ...", section, category, dirName)
results = autoProcessMovie().process(dirName, os.path.basename(dirName), 0, inputCategory=category)
if results != 0:
result = results
Logger.info("MAIN: A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
logger.error("A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
else:
Logger.info("MAIN: nzbToCouchPotato %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.info("MAIN: The autoProcessMovie script completed successfully.")
logger.postprocess("The script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_SUCCESS)
else:
Logger.info("MAIN: A problem was reported in the autoProcessMovie script.")
logger.error("A problem was reported in the script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)

View file

@ -1,10 +1,4 @@
#!/usr/bin/env python
# adds lib directory to system path
import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib')))
#
##############################################################################
### NZBGET POST-PROCESSING SCRIPT ###
@ -62,81 +56,67 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib'
### NZBGET POST-PROCESSING SCRIPT ###
##############################################################################
import logging
import os
import sys
import nzbtomedia
from nzbtomedia.autoProcess.autoProcessGames import autoProcessGames
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import WakeUp, nzbtomedia_configure_logging, get_dirnames
from nzbtomedia.nzbToMediaUtil import get_dirnames
from nzbtomedia import logger
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
if config().migrate():
# check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'):
config().addnzbget()
nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log
Logger.info("nzbToGamez %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
# gamez category
sections = config().get_subsections(['Gamez'])
WakeUp()
# Initialize the config
nzbtomedia.initialize()
# 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.info("MAIN: Script triggered from NZBGet (11.0 or later).")
logger.postprocess("Script triggered from NZBGet (11.0 or later).")
# Check nzbget.conf options
status = 0
if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
logger.error("Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)
# Check par status
if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(config.NZBGET_POSTPROCESS_NONE)
logger.warning("Par-check successful, but Par-repair disabled, exiting")
logger.postprocess("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':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
logger.warning("Par-repair failed, setting status \"failed\"")
status = 1
# Check unpack status
if os.environ['NZBPP_UNPACKSTATUS'] == '1':
Logger.warning("MAIN: Unpack failed, setting status \"failed\"")
logger.warning("Unpack failed, setting status \"failed\"")
status = 1
if os.environ['NZBPP_UNPACKSTATUS'] == '0' and os.environ['NZBPP_PARSTATUS'] == '0':
# Unpack was skipped due to nzb-file properties or due to errors during par-check
if os.environ['NZBPP_HEALTH'] < 1000:
Logger.warning("MAIN: Download health is compromised and Par-check/repair disabled or no .par2 files found. Setting status \"failed\"")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
status = 1
else:
Logger.info("MAIN: Par-check/repair disabled or no .par2 files found, and Unpack not required. Health is ok so handle as though download successful")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
# Check if destination directory exists (important for reprocessing of history items)
if not os.path.isdir(os.environ['NZBPP_DIRECTORY']):
Logger.error("MAIN: 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
# All checks done, now launching the script.
Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessGames...")
logger.postprocess("Script triggered from NZBGet, starting post-processing ...")
clientAgent = "nzbget"
result = autoProcessGames().process(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBFILENAME'], status, clientAgent, os.environ['NZBPP_CATEGORY'])
# SABnzbd Pre 0.7.17
elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
elif len(sys.argv) == nzbtomedia.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -145,11 +125,11 @@ elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# 5 User-defined category
# 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
Logger.info("MAIN: Script triggered from SABnzbd, starting autoProcessGames...")
logger.postprocess("Script triggered from SABnzbd, starting post-processing ...")
clientAgent = "sabnzbd"
result = autoProcessGames().process(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
# SABnzbd 0.7.17+
elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
elif len(sys.argv) >= nzbtomedia.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -159,32 +139,31 @@ elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# 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
# 8 Failure URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessGames...")
logger.postprocess("Script triggered from SABnzbd 0.7.17+, starting post-processing ...")
clientAgent = "sabnzbd"
result = autoProcessGames().process(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
else:
result = 0
subsections = config()["Gamez"].subsections
Logger.warn("MAIN: Invalid number of arguments received from client.")
for section, subsection in subsections.items():
logger.warning("Invalid number of arguments received from client.")
for section, subsection in nzbtomedia.SUBSECTIONS['Gamez'].items():
for category in subsection:
if config()[section].isenabled(category):
if nzbtomedia.CFG[section].isenabled(category):
dirNames = get_dirnames(section, category)
for dirName in dirNames:
Logger.info("MAIN: nzbToGamez running %s:%s as a manual run on folder %s ...", section, category, dirName)
logger.postprocess("Running %s:%s as a manual run on folder %s ...", section, category, dirName)
results = autoProcessGames().process(dirName, os.path.basename(dirName), 0, inputCategory=category)
if results != 0:
result = results
Logger.info("MAIN: A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
logger.error("A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
else:
Logger.info("MAIN: nzbToGamez %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.info("MAIN: The autoProcessGames script completed successfully.")
logger.postprocess("The script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_SUCCESS)
else:
Logger.info("MAIN: A problem was reported in the autoProcessGames script.")
logger.error("A problem was reported in the script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)

View file

@ -1,10 +1,4 @@
#!/usr/bin/env python
# adds lib directory to system path
import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib')))
#
##############################################################################
### NZBGET POST-PROCESSING SCRIPT ###
@ -72,81 +66,67 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib'
### NZBGET POST-PROCESSING SCRIPT ###
##############################################################################
import os
import sys
import nzbtomedia
# NZBGet argv: all passed as environment variables.
# Exit codes used by NZBGet
import logging
from nzbtomedia.autoProcess.autoProcessMusic import autoProcessMusic
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import get_dirnames, WakeUp, nzbtomedia_configure_logging
from nzbtomedia.nzbToMediaUtil import get_dirnames
from nzbtomedia import logger
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
if config().migrate():
# check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'):
config().addnzbget()
nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log
Logger.info("nzbToHeadPhones %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
WakeUp()
# Initialize the config
nzbtomedia.initialize()
# 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.info("MAIN: Script triggered from NZBGet (11.0 or later).")
logger.postprocess("Script triggered from NZBGet (11.0 or later).")
# Check nzbget.conf options
status = 0
if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
logger.error("Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)
# Check par status
if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(config.NZBGET_POSTPROCESS_NONE)
logger.warning("Par-check successful, but Par-repair disabled, exiting")
logger.postprocess("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':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
logger.warning("Par-repair failed, setting status \"failed\"")
status = 1
# Check unpack status
if os.environ['NZBPP_UNPACKSTATUS'] == '1':
Logger.warning("MAIN: Unpack failed, setting status \"failed\"")
logger.warning("Unpack failed, setting status \"failed\"")
status = 1
if os.environ['NZBPP_UNPACKSTATUS'] == '0' and os.environ['NZBPP_PARSTATUS'] == '0':
# Unpack was skipped due to nzb-file properties or due to errors during par-check
if os.environ['NZBPP_HEALTH'] < 1000:
Logger.warning("MAIN: Download health is compromised and Par-check/repair disabled or no .par2 files found. Setting status \"failed\"")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
status = 1
else:
Logger.info("MAIN: Par-check/repair disabled or no .par2 files found, and Unpack not required. Health is ok so handle as though download successful")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
# Check if destination directory exists (important for reprocessing of history items)
if not os.path.isdir(os.environ['NZBPP_DIRECTORY']):
Logger.error("MAIN: 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
# All checks done, now launching the script.
Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessMusic...")
logger.postprocess("Script triggered from NZBGet, starting autoProcessMusic...")
clientAgent = "nzbget"
result = autoProcessMusic().process(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBFILENAME'], status, clientAgent, os.environ['NZBPP_CATEGORY'])
# SABnzbd Pre 0.7.17
elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
elif len(sys.argv) == nzbtomedia.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -155,11 +135,11 @@ elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# 5 User-defined category
# 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
Logger.info("MAIN: Script triggered from SABnzbd, starting autoProcessMusic...")
logger.postprocess("Script triggered from SABnzbd, starting autoProcessMusic...")
clientAgent = "sabnzbd"
result = autoProcessMusic().process(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
# SABnzbd 0.7.17+
elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
elif len(sys.argv) >= nzbtomedia.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -169,33 +149,32 @@ elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# 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
# 8 Failue URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessMusic...")
logger.postprocess("Script triggered from SABnzbd 0.7.17+, starting autoProcessMusic...")
clientAgent = "sabnzbd"
result = autoProcessMusic().process(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
else:
result = 0
subsections = config()["HeadPhones"].subsections
Logger.warn("MAIN: Invalid number of arguments received from client.")
for section, subsection in subsections.items():
logger.warning("Invalid number of arguments received from client.")
for section, subsection in nzbtomedia.SUBSECTIONS['HeadPhones'].items():
for category in subsection:
if config()[section].isenabled(category):
if nzbtomedia.CFG[section].isenabled(category):
dirNames = get_dirnames(section, category)
for dirName in dirNames:
Logger.info("MAIN: nzbToHeadPhones running %s:%s as a manual run on folder %s ...", section, category, dirName)
logger.postprocess("nzbToHeadPhones running %s:%s as a manual run on folder %s ...", section, category, dirName)
results = autoProcessMusic().process(dirName, os.path.basename(dirName), 0, inputCategory=category)
if results != 0:
result = results
Logger.info("MAIN: A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
logger.error("A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
else:
Logger.info("MAIN: nzbToHeadPhones %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
logger.postprocess("nzbToHeadPhones %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
if result == 0:
Logger.info("MAIN: The autoProcessMusic script completed successfully.")
logger.postprocess("The autoProcessMusic script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_SUCCESS)
else:
Logger.info("MAIN: A problem was reported in the autoProcessMusic script.")
logger.error("A problem was reported in the autoProcessMusic script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)

View file

@ -1,10 +1,4 @@
#!/usr/bin/env python
# adds lib directory to system path
import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib')))
#
##############################################################################
### NZBGET POST-PROCESSING SCRIPT ###
@ -305,57 +299,44 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib'
### NZBGET POST-PROCESSING SCRIPT ###
##############################################################################
import logging
import os
import sys
import nzbtomedia
from nzbtomedia.autoProcess.autoProcessComics import autoProcessComics
from nzbtomedia.autoProcess.autoProcessGames import autoProcessGames
from nzbtomedia.autoProcess.autoProcessMovie import autoProcessMovie
from nzbtomedia.autoProcess.autoProcessMusic import autoProcessMusic
from nzbtomedia.autoProcess.autoProcessTV import autoProcessTV
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import nzbtomedia_configure_logging, WakeUp, get_dirnames
from nzbtomedia.nzbToMediaUtil import get_dirnames
from nzbtomedia import logger
# post-processing
def process(nzbDir, inputName=None, status=0, clientAgent='manual', download_id=None, inputCategory=None):
if config()["CouchPotato"].issubsection(inputCategory):
Logger.info("MAIN: Calling CouchPotatoServer to post-process: %s", inputName)
if nzbtomedia.CFG["CouchPotato"].issubsection(inputCategory):
logger.postprocess("Calling CouchPotatoServer to post-process: %s", logger.MESSAGE), inputName
return autoProcessMovie().process(nzbDir, inputName, status, clientAgent, download_id, inputCategory)
elif config()["SickBeard", "NzbDrone"].issubsection(inputCategory):
Logger.info("MAIN: Calling Sick-Beard to post-process: %s", inputName)
elif nzbtomedia.CFG["SickBeard", "NzbDrone"].issubsection(inputCategory):
logger.postprocess("Calling Sick-Beard to post-process: %s",logger.MESSAGE), inputName
return autoProcessTV().processEpisode(nzbDir, inputName, status, clientAgent, inputCategory)
elif config()["HeadPhones"].issubsection(inputCategory):
Logger.info("MAIN: Calling HeadPhones to post-process: %s", inputName)
elif nzbtomedia.CFG["HeadPhones"].issubsection(inputCategory):
logger.postprocess("Calling HeadPhones to post-process: %s", logger.MESSAGE), inputName
return autoProcessMusic().process(nzbDir, inputName, status, clientAgent, inputCategory)
elif config()["Mylar"].issubsection(inputCategory):
Logger.info("MAIN: Calling Mylar to post-process: %s", inputName)
elif nzbtomedia.CFG["Mylar"].issubsection(inputCategory):
logger.postprocess("Calling Mylar to post-process: %s",logger.MESSAGE), inputName
return autoProcessComics().processEpisode(nzbDir, inputName, status, clientAgent, inputCategory)
elif config()["Gamez"].issubsection(inputCategory):
Logger.info("MAIN: Calling Gamez to post-process: %s", inputName)
elif nzbtomedia.CFG["Gamez"].issubsection(inputCategory):
logger.postprocess("Calling Gamez to post-process: %s",logger.MESSAGE), inputName
return autoProcessGames().process(nzbDir, inputName, status, clientAgent, inputCategory)
else:
Logger.warning("MAIN: We could not find the section %s with a download category of %s in your autoProcessMedia.cfg. Exiting.", section, inputCategory)
logger.postprocess("We could not find the section %s with a download category of %s in your autoProcessMedia.cfg. Exiting.",logger.WARNING), section, inputCategory
return -1
########################################################################################################################
logger.postprocess("====================") # Seperate old from new log
logger.postprocess("nzbToMedia %s", nzbtomedia.NZBTOMEDIA_VERSION)
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
if config().migrate():
# check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'):
config().addnzbget()
nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger()
Logger.info("====================") # Seperate old from new log
Logger.info("nzbToMedia %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
print("Unable to find " + config.CONFIG_FILE + " or " + config.SAMPLE_CONFIG_FILE)
sys.exit(-1)
WakeUp()
logger.postprocess("Loading config from %s", nzbtomedia.CONFIG_FILE)
# Post-Processing Result
result = 0
@ -363,7 +344,7 @@ result = 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.info("MAIN: Script triggered from NZBGet (11.0 or later).")
logger.postprocess("Script triggered from NZBGet (11.0 or later).")
# NZBGet argv: all passed as environment variables.
clientAgent = "nzbget"
@ -372,48 +353,48 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
status = 0
if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
logger.error("Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)
# Check par status
if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(config.NZBGET_POSTPROCESS_NONE)
logger.warning("Par-check successful, but Par-repair disabled, exiting")
logger.postprocess("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':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
logger.warning("Par-repair failed, setting status \"failed\"")
status = 1
# Check unpack status
if os.environ['NZBPP_UNPACKSTATUS'] == '1':
Logger.warning("MAIN: Unpack failed, setting status \"failed\"")
logger.warning("Unpack failed, setting status \"failed\"")
status = 1
if os.environ['NZBPP_UNPACKSTATUS'] == '0' and os.environ['NZBPP_PARSTATUS'] == '0':
# Unpack was skipped due to nzb-file properties or due to errors during par-check
if os.environ['NZBPP_HEALTH'] < 1000:
Logger.warning("MAIN: Download health is compromised and Par-check/repair disabled or no .par2 files found. Setting status \"failed\"")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
status = 1
else:
Logger.info("MAIN: Par-check/repair disabled or no .par2 files found, and Unpack not required. Health is ok so handle as though download successful")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
# Check if destination directory exists (important for reprocessing of history items)
if not os.path.isdir(os.environ['NZBPP_DIRECTORY']):
Logger.error("MAIN: 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
# All checks done, now launching the script.
download_id = ""
if os.environ.has_key('NZBPR_COUCHPOTATO'):download_id = os.environ['NZBPR_COUCHPOTATO']
result = process(os.environ['NZBPP_DIRECTORY'], inputName=os.environ['NZBPP_NZBFILENAME'], clientAgent = "nzbget", inputCategory=os.environ['NZBPP_CATEGORY'])
if result != 0: Logger.info("MAIN: A problem was reported in the autoProcess* script.")
if result != 0: logger.error("A problem was reported in the autoProcess* script.")
# SABnzbd Pre 0.7.17
elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
elif len(sys.argv) == nzbtomedia.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -422,11 +403,11 @@ elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# 5 User-defined category
# 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
Logger.info("MAIN: Script triggered from SABnzbd")
logger.postprocess("Script triggered from SABnzbd")
result = process(sys.argv[1], inputName=sys.argv[2], status=sys.argv[7], inputCategory=sys.argv[5], clientAgent = "sabnzbd", download_id='')
if result != 0: Logger.info("MAIN: A problem was reported in the autoProcess* script.")
if result != 0: logger.error("A problem was reported in the autoProcess* script.")
# SABnzbd 0.7.17+
elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
elif len(sys.argv) >= nzbtomedia.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -436,33 +417,33 @@ elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# 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
# 8 Failure URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+")
logger.postprocess("Script triggered from SABnzbd 0.7.17+")
result = process(sys.argv[1], inputName=sys.argv[2], status=sys.argv[7], inputCategory=sys.argv[5], clientAgent = "sabnzbd", download_id='')
if result != 0:Logger.info("MAIN: A problem was reported in the autoProcess* script.")
if result != 0:logger.error("A problem was reported in the autoProcess* script.")
else:
result = 0
# init sub-sections
subsections = config()["CouchPotato", "SickBeard", "NzbDrone", "HeadPhones", "Mylar", "Gamez"].subsections
Logger.warn("MAIN: Invalid number of arguments received from client.")
subsections = nzbtomedia.CFG["CouchPotato", "SickBeard", "NzbDrone", "HeadPhones", "Mylar", "Gamez"].subsections
logger.warning("Invalid number of arguments received from client.")
for section, subsection in subsections.items():
for category in subsection:
if config()[section].isenabled(category):
if nzbtomedia.CFG[section].isenabled(category):
dirNames = get_dirnames(section, category)
for dirName in dirNames:
Logger.info("MAIN: nzbToMedia running %s:%s as a manual run on folder %s ...", section, category, dirName)
logger.postprocess("nzbToMedia running %s:%s as a manual run on folder %s ...", section, category, dirName)
results = process(dirName, os.path.basename(dirName), 0, inputCategory=category)
if results != 0:
result = results
Logger.info("MAIN: 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.info("MAIN: nzbToMedia %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
logger.postprocess("nzbToMedia %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
if result == 0:
Logger.info("MAIN: The nzbToMedia script completed successfully.")
logger.postprocess("The nzbToMedia script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_SUCCESS)
else:
Logger.info("MAIN: A problem was reported in the nzbToMedia script.")
logger.error("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)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)

View file

@ -67,78 +67,63 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib'
##############################################################################
# Exit codes used by NZBGet
import logging
import nzbtomedia
from nzbtomedia.autoProcess.autoProcessComics import autoProcessComics
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import nzbtomedia_configure_logging, WakeUp, get_dirnames
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
if config().migrate():
# check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'):
config().addnzbget()
nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log
Logger.info("nzbToMylar %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
WakeUp()
from nzbtomedia.nzbToMediaUtil import get_dirnames
from nzbtomedia import logger
# Initialize the config
nzbtomedia.initialize()
# 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.info("MAIN: Script triggered from NZBGet (11.0 or later).")
logger.postprocess("Script triggered from NZBGet (11.0 or later).")
# Check nzbget.conf options
status = 0
if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
logger.error("Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)
# Check par status
if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(config.NZBGET_POSTPROCESS_NONE)
logger.warning("Par-check successful, but Par-repair disabled, exiting")
logger.postprocess("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':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
logger.warning("Par-repair failed, setting status \"failed\"")
status = 1
# Check unpack status
if os.environ['NZBPP_UNPACKSTATUS'] == '1':
Logger.warning("MAIN: Unpack failed, setting status \"failed\"")
logger.warning("Unpack failed, setting status \"failed\"")
status = 1
if os.environ['NZBPP_UNPACKSTATUS'] == '0' and os.environ['NZBPP_PARSTATUS'] == '0':
# Unpack was skipped due to nzb-file properties or due to errors during par-check
if os.environ['NZBPP_HEALTH'] < 1000:
Logger.warning("MAIN: Download health is compromised and Par-check/repair disabled or no .par2 files found. Setting status \"failed\"")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
status = 1
else:
Logger.info("MAIN: Par-check/repair disabled or no .par2 files found, and Unpack not required. Health is ok so handle as though download successful")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
# Check if destination directory exists (important for reprocessing of history items)
if not os.path.isdir(os.environ['NZBPP_DIRECTORY']):
Logger.error("MAIN: 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
# All checks done, now launching the script.
Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessComics...")
logger.postprocess("Script triggered from NZBGet, starting autoProcessComics...")
clientAgent = "nzbget"
result = autoProcessComics().processEpisode(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBFILENAME'], status, clientAgent, os.environ['NZBPP_CATEGORY'])
# SABnzbd Pre 0.7.17
elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
elif len(sys.argv) == nzbtomedia.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -147,11 +132,11 @@ elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# 5 User-defined category
# 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
Logger.info("MAIN: Script triggered from SABnzbd, starting autoProcessComics...")
logger.postprocess("Script triggered from SABnzbd, starting autoProcessComics...")
clientAgent = "sabnzbd"
result = autoProcessComics().processEpisode(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
# SABnzbd 0.7.17+
elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
elif len(sys.argv) >= nzbtomedia.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -161,32 +146,32 @@ elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# 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
# 8 Failure URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessComics...")
logger.postprocess("Script triggered from SABnzbd 0.7.17+, starting autoProcessComics...")
clientAgent = "sabnzbd"
result = autoProcessComics().processEpisode(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
else:
result = 0
subsections = config()["Mylar"].subsections
Logger.warn("MAIN: Invalid number of arguments received from client.")
subsections = nzbtomedia.CFG["Mylar"].subsections
logger.warning("Invalid number of arguments received from client.")
for section, subsection in subsections.items():
for category in subsection:
if config()[section].isenabled(category):
if nzbtomedia.CFG[section].isenabled(category):
dirNames = get_dirnames(section, category)
for dirName in dirNames:
Logger.info("MAIN: nzbToMylar running %s:%s as a manual run on folder %s ...", section, category, dirName)
logger.postprocess("nzbToMylar running %s:%s as a manual run on folder %s ...", section, category, dirName)
results = autoProcessComics().processEpisode(dirName, os.path.basename(dirName), 0, inputCategory=category)
if results != 0:
result = results
Logger.info("MAIN: A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
logger.error("A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
else:
Logger.info("MAIN: nzbToMylar %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
logger.postprocess("nzbToMylar %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
if result == 0:
Logger.info("MAIN: The autoProcessComics script completed successfully.")
logger.postprocess("The autoProcessComics script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_SUCCESS)
else:
Logger.info("MAIN: A problem was reported in the autoProcessComics script.")
logger.error("A problem was reported in the autoProcessComics script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)

View file

@ -96,78 +96,64 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib'
### NZBGET POST-PROCESSING SCRIPT ###
##############################################################################
import logging
import nzbtomedia
from nzbtomedia.autoProcess.autoProcessTV import autoProcessTV
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import nzbtomedia_configure_logging, WakeUp, get_dirnames
from nzbtomedia.nzbToMediaUtil import get_dirnames
from nzbtomedia import logger
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
if config().migrate():
# check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'):
config().addnzbget()
nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log
Logger.info("nzbToNzbDrone %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
WakeUp()
# Initialize the config
nzbtomedia.initialize()
# 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.info("MAIN: Script triggered from NZBGet (11.0 or later).")
logger.postprocess("Script triggered from NZBGet (11.0 or later).")
# Check nzbget.conf options
status = 0
if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
logger.error("Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)
# Check par status
if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(config.NZBGET_POSTPROCESS_NONE)
logger.warning("Par-check successful, but Par-repair disabled, exiting")
logger.postprocess("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':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
logger.warning("Par-repair failed, setting status \"failed\"")
status = 1
# Check unpack status
if os.environ['NZBPP_UNPACKSTATUS'] == '1':
Logger.warning("MAIN: Unpack failed, setting status \"failed\"")
logger.warning("Unpack failed, setting status \"failed\"")
status = 1
if os.environ['NZBPP_UNPACKSTATUS'] == '0' and os.environ['NZBPP_PARSTATUS'] == '0':
# Unpack was skipped due to nzb-file properties or due to errors during par-check
if os.environ['NZBPP_HEALTH'] < 1000:
Logger.warning("MAIN: Download health is compromised and Par-check/repair disabled or no .par2 files found. Setting status \"failed\"")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
status = 1
else:
Logger.info("MAIN: Par-check/repair disabled or no .par2 files found, and Unpack not required. Health is ok so handle as though download successful")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
# Check if destination directory exists (important for reprocessing of history items)
if not os.path.isdir(os.environ['NZBPP_DIRECTORY']):
Logger.error("MAIN: 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
# All checks done, now launching the script.
Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessTV...")
logger.postprocess("Script triggered from NZBGet, starting autoProcessTV...")
clientAgent = "nzbget"
result = autoProcessTV().processEpisode(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBFILENAME'], status, clientAgent, os.environ['NZBPP_CATEGORY'])
# SABnzbd Pre 0.7.17
elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
elif len(sys.argv) == nzbtomedia.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -176,11 +162,11 @@ elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# 5 User-defined category
# 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
Logger.info("MAIN: Script triggered from SABnzbd, starting autoProcessTV...")
logger.postprocess("Script triggered from SABnzbd, starting autoProcessTV...")
clientAgent = "sabnzbd"
result = autoProcessTV().processEpisode(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
# SABnzbd 0.7.17+
elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
elif len(sys.argv) >= nzbtomedia.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -190,32 +176,32 @@ elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# 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
# 8 Failure URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessTV...")
logger.postprocess("Script triggered from SABnzbd 0.7.17+, starting autoProcessTV...")
clientAgent = "sabnzbd"
result = autoProcessTV().processEpisode(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
else:
result = 0
subsections = config()["NzbDrone"].subsections
Logger.warn("MAIN: Invalid number of arguments received from client.")
subsections = nzbtomedia.CFG["NzbDrone"].subsections
logger.warning("Invalid number of arguments received from client.")
for section, subsection in subsections.items():
for category in subsection:
if config()[section].isenabled(category):
if nzbtomedia.CFG[section].isenabled(category):
dirNames = get_dirnames(section, category)
for dirName in dirNames:
Logger.info("MAIN: nzbToNzbDrone running %s:%s as a manual run on folder %s ...", section, category, dirName)
logger.postprocess("nzbToNzbDrone running %s:%s as a manual run on folder %s ...", section, category, dirName)
results = autoProcessTV().processEpisode(dirName, os.path.basename(dirName), 0, inputCategory=category)
if results != 0:
result = results
Logger.info("MAIN: A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
logger.error("A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
else:
Logger.info("MAIN: nzbToNzbDrone %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
logger.postprocess("nzbToNzbDrone %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
if result == 0:
Logger.info("MAIN: The autoProcessTV script completed successfully.")
logger.postprocess("The autoProcessTV script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_SUCCESS)
else:
Logger.info("MAIN: A problem was reported in the autoProcessTV script.")
logger.error("A problem was reported in the autoProcessTV script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)

View file

@ -129,78 +129,64 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib'
### NZBGET POST-PROCESSING SCRIPT ###
##############################################################################
import logging
import nzbtomedia
from nzbtomedia.autoProcess.autoProcessTV import autoProcessTV
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import nzbtomedia_configure_logging, WakeUp, get_dirnames
from nzbtomedia.nzbToMediaUtil import get_dirnames
from nzbtomedia import logger
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
if config().migrate():
# check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'):
config().addnzbget()
nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log
Logger.info("nzbToSickBeard %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
WakeUp()
# Initialize the config
nzbtomedia.initialize()
# 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.info("MAIN: Script triggered from NZBGet (11.0 or later).")
logger.postprocess("Script triggered from NZBGet (11.0 or later).")
# Check nzbget.conf options
status = 0
if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
logger.error("Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)
# Check par status
if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(config.NZBGET_POSTPROCESS_NONE)
logger.warning("Par-check successful, but Par-repair disabled, exiting")
logger.postprocess("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':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
logger.warning("Par-repair failed, setting status \"failed\"")
status = 1
# Check unpack status
if os.environ['NZBPP_UNPACKSTATUS'] == '1':
Logger.warning("MAIN: Unpack failed, setting status \"failed\"")
logger.warning("Unpack failed, setting status \"failed\"")
status = 1
if os.environ['NZBPP_UNPACKSTATUS'] == '0' and os.environ['NZBPP_PARSTATUS'] == '0':
# Unpack was skipped due to nzb-file properties or due to errors during par-check
if os.environ['NZBPP_HEALTH'] < 1000:
Logger.warning("MAIN: Download health is compromised and Par-check/repair disabled or no .par2 files found. Setting status \"failed\"")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
status = 1
else:
Logger.info("MAIN: Par-check/repair disabled or no .par2 files found, and Unpack not required. Health is ok so handle as though download successful")
Logger.info("MAIN: Please check your Par-check/repair settings for future downloads.")
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.")
# Check if destination directory exists (important for reprocessing of history items)
if not os.path.isdir(os.environ['NZBPP_DIRECTORY']):
Logger.error("MAIN: 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
# All checks done, now launching the script.
Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessTV...")
logger.postprocess("Script triggered from NZBGet, starting autoProcessTV...")
clientAgent = "nzbget"
result = autoProcessTV().processEpisode(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBFILENAME'], status, clientAgent, os.environ['NZBPP_CATEGORY'])
# SABnzbd Pre 0.7.17
elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
elif len(sys.argv) == nzbtomedia.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -209,11 +195,11 @@ elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# 5 User-defined category
# 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
Logger.info("MAIN: Script triggered from SABnzbd, starting autoProcessTV...")
logger.postprocess("Script triggered from SABnzbd, starting autoProcessTV...")
clientAgent = "sabnzbd"
result = autoProcessTV().processEpisode(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
# SABnzbd 0.7.17+
elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
elif len(sys.argv) >= nzbtomedia.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv:
# 1 The final directory of the job (full path)
# 2 The original name of the NZB file
@ -223,32 +209,32 @@ elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# 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
# 8 Failure URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessTV...")
logger.postprocess("Script triggered from SABnzbd 0.7.17+, starting autoProcessTV...")
clientAgent = "sabnzbd"
result = autoProcessTV().processEpisode(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
else:
result = 0
subsections = config()["SickBeard"].subsections
Logger.warn("MAIN: Invalid number of arguments received from client.")
subsections = nzbtomedia.CFG["SickBeard"].subsections
logger.warning("Invalid number of arguments received from client.")
for section, subsection in subsections.items():
for category in subsection:
if config()[section].isenabled(category):
if nzbtomedia.CFG[section].isenabled(category):
dirNames = get_dirnames(section, category)
for dirName in dirNames:
Logger.info("MAIN: nzbToSickBeard running %s:%s as a manual run on folder %s ...", section, category, dirName)
logger.postprocess("nzbToSickBeard running %s:%s as a manual run on folder %s ...", section, category, dirName)
results = autoProcessTV().processEpisode(dirName, os.path.basename(dirName), 0, inputCategory=category)
if results != 0:
result = results
Logger.info("MAIN: A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
logger.error("A problem was reported when trying to manually run %s:%s on folder %s ...", section, category, dirName)
else:
Logger.info("MAIN: nzbToSickBeard %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
logger.postprocess("nzbToSickBeard %s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ...", section, category)
if result == 0:
Logger.info("MAIN: The autoProcessTV script completed successfully.")
logger.postprocess("The autoProcessTV script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_SUCCESS)
else:
Logger.info("MAIN: A problem was reported in the autoProcessTV script.")
logger.error("A problem was reported in the autoProcessTV script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(config.NZBGET_POSTPROCESS_ERROR)
sys.exit(nzbtomedia.NZBGET_POSTPROCESS_ERROR)

View file

@ -14,15 +14,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.error("Failed to install ffmpeg. Please install manually")
logger.info("Cannot transcode files in folder %s", dirName)
return 1 # failure
else:
ffmpeg = 'ffmpeg'
@ -30,33 +30,33 @@ class Transcoder:
ffmpeg = 'ffmpeg'
useNiceness = True
Logger.info("Loading config from %s", config.CONFIG_FILE)
logger.info("Loading config from %s", nzbtomedia.CONFIG_FILE)
if not config():
Logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
if not nzbtomedia.CFG:
logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
return 1 # failure
mediaContainer = (config()["Transcoder"]["duplicate"])
duplicate = int(config()["Transcoder"]["duplicate"])
ignoreExtensions = (config()["Transcoder"]["ignoreExtensions"])
outputVideoExtension = config()["Transcoder"]["outputVideoExtension"].strip()
outputVideoCodec = config()["Transcoder"]["outputVideoCodec"].strip()
outputVideoPreset = config()["Transcoder"]["outputVideoPreset"].strip()
outputVideoFramerate = config()["Transcoder"]["outputVideoFramerate"].strip()
outputVideoBitrate = config()["Transcoder"]["outputVideoBitrate"].strip()
outputAudioCodec = config()["Transcoder"]["outputAudioCodec"].strip()
outputAudioBitrate = config()["Transcoder"]["outputAudioBitrate"].strip()
outputSubtitleCodec = config()["Transcoder"]["outputSubtitleCodec"].strip()
outputFastStart = int(config()["Transcoder"]["outputFastStart"])
outputQualityPercent = int(config()["Transcoder"]["outputQualityPercent"])
mediaContainer = (nzbtomedia.CFG["Transcoder"]["duplicate"])
duplicate = int(nzbtomedia.CFG["Transcoder"]["duplicate"])
ignoreExtensions = (nzbtomedia.CFG["Transcoder"]["ignoreExtensions"])
outputVideoExtension = nzbtomedia.CFG["Transcoder"]["outputVideoExtension"].strip()
outputVideoCodec = nzbtomedia.CFG["Transcoder"]["outputVideoCodec"].strip()
outputVideoPreset = nzbtomedia.CFG["Transcoder"]["outputVideoPreset"].strip()
outputVideoFramerate = nzbtomedia.CFG["Transcoder"]["outputVideoFramerate"].strip()
outputVideoBitrate = nzbtomedia.CFG["Transcoder"]["outputVideoBitrate"].strip()
outputAudioCodec = nzbtomedia.CFG["Transcoder"]["outputAudioCodec"].strip()
outputAudioBitrate = nzbtomedia.CFG["Transcoder"]["outputAudioBitrate"].strip()
outputSubtitleCodec = nzbtomedia.CFG["Transcoder"]["outputSubtitleCodec"].strip()
outputFastStart = int(nzbtomedia.CFG["Transcoder"]["outputFastStart"])
outputQualityPercent = int(nzbtomedia.CFG["Transcoder"]["outputQualityPercent"])
niceness = None
if useNiceness:niceness = int(config()["Transcoder"]["niceness"])
if useNiceness:niceness = int(nzbtomedia.CFG["Transcoder"]["niceness"])
map(lambda ext: ext.strip(), mediaContainer)
map(lambda ext: ext.strip(), ignoreExtensions)
Logger.info("Checking for files to be transcoded")
logger.info("Checking for files to be transcoded")
final_result = 0 # initialize as successful
for dirpath, dirnames, filenames in os.walk(dirName):
for file in filenames:
@ -64,7 +64,7 @@ class Transcoder:
name, ext = os.path.splitext(filePath)
if ext in mediaContainer: # If the file is a video file
if ext in 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'
@ -119,26 +119,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.exception("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 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

@ -0,0 +1,163 @@
import os
import sys
from nzbtomedia import logger
from nzbtomedia.nzbToMediaConfig import config
# sabnzbd constants
from nzbtomedia.nzbToMediaUtil import WakeUp
SABNZB_NO_OF_ARGUMENTS = 8
SABNZB_0717_NO_OF_ARGUMENTS = 9
# sickbeard fork/branch constants
FORKS = {}
FORK_DEFAULT = "default"
FORK_FAILED = "failed"
FORK_FAILED_TORRENT = "failed-torrent"
FORKS[FORK_DEFAULT] = {"dir": None, "method": None}
FORKS[FORK_FAILED] = {"dirName": None, "failed": None}
FORKS[FORK_FAILED_TORRENT] = {"dir": None, "failed": None, "process_method": None}
SICKBEARD_FAILED = [FORK_FAILED, FORK_FAILED_TORRENT]
SICKBEARD_TORRENT = [FORK_FAILED_TORRENT]
# NZBGet Exit Codes
NZBGET_POSTPROCESS_PARCHECK = 92
NZBGET_POSTPROCESS_SUCCESS = 93
NZBGET_POSTPROCESS_ERROR = 94
NZBGET_POSTPROCESS_NONE = 95
# config constants
CFG = None
CFG_LOGGING = None
PROGRAM_DIR = ''
LOG_DIR = ''
LOG_FILE = ''
CONFIG_FILE = ''
CONFIG_SPEC_FILE = ''
CONFIG_MOVIE_FILE = ''
CONFIG_TV_FILE = ''
SYS_ENCODING = ''
# version constants
NZBTOMEDIA_VERSION = None
NEWEST_VERSION = None
NEWEST_VERSION_STRING = None
VERSION_NOTIFY = None
CLIENTAGENT = None
USELINK = None
OUTPUTDIRECTORY = None
CATEGORIES = []
NOFLATTEN = []
UTORRENTWEBUI = None
UTORRENTUSR = None
UTORRENTPWD = None
TRANSMISSIONHOST = None
TRANSMISSIONPORT = None
TRANSMISSIONUSR = None
TRANSMISSIONPWD = None
DELUGEHOST = None
DELUGEPORT = None
DELUGEUSR = None
DELUGEPWD = None
COMPRESSEDCONTAINER = None
MEDIACONTAINER = None
METACONTAINER = None
MINSAMPLESIZE = None
SAMPLEIDS = None
SECTIONS = []
SUBSECTIONS = {}
USER_SCRIPT_CATEGORIES = None
__INITIALIZED__ = False
def initialize():
global NZBGET_POSTPROCESS_ERROR, NZBGET_POSTPROCESS_NONE, NZBGET_POSTPROCESS_PARCHECK, NZBGET_POSTPROCESS_SUCCESS, \
NZBTOMEDIA_TIMEOUT, FORKS, FORK_DEFAULT, FORK_FAILED_TORRENT, FORK_FAILED, SICKBEARD_TORRENT, SICKBEARD_FAILED, \
PROGRAM_DIR, CFG, CFG_LOGGING, CONFIG_FILE, CONFIG_MOVIE_FILE, CONFIG_SPEC_FILE, LOG_DIR, \
CONFIG_TV_FILE, LOG_FILE, NZBTOMEDIA_VERSION, NEWEST_VERSION, NEWEST_VERSION_STRING, VERSION_NOTIFY, \
SABNZB_NO_OF_ARGUMENTS, SABNZB_0717_NO_OF_ARGUMENTS, CATEGORIES, CLIENTAGENT, USELINK, OUTPUTDIRECTORY, NOFLATTEN, \
UTORRENTPWD, UTORRENTUSR, UTORRENTWEBUI, DELUGEHOST, DELUGEPORT, DELUGEUSR, DELUGEPWD, TRANSMISSIONHOST, TRANSMISSIONPORT, \
TRANSMISSIONPWD, TRANSMISSIONUSR, COMPRESSEDCONTAINER, MEDIACONTAINER, METACONTAINER, MINSAMPLESIZE, SAMPLEIDS, \
SECTIONS, SUBSECTIONS, USER_SCRIPT_CATEGORIES, __INITIALIZED__
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 paths and filenames
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")
if not nzbToMediaUtil.makeDir(LOG_DIR):
logger.error("!!! No log folder, logging to screen only!")
# init logging
logger.ntm_log_instance.initLogging()
# 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 load config from %s", CONFIG_FILE)
sys.exit(-1)
if os.environ.has_key('NZBOP_SCRIPTDIR'):
config.addnzbget()
NZBTOMEDIA_VERSION = 'nzbToMedia ' + version.SICKBEARD_VERSION.replace(' ', '-') + ' (' + sys.platform.system() + '; ' + sys.platform.release()
logger.info("nzbToMedia %s", NZBTOMEDIA_VERSION)
logger.info("Loading config from %s", CONFIG_FILE)
WakeUp()
CLIENTAGENT = CFG["Torrent"]["clientAgent"] # utorrent | deluge | transmission | rtorrent | other
USELINK = CFG["Torrent"]["useLink"] # no | hard | sym
OUTPUTDIRECTORY = CFG["Torrent"]["outputDirectory"] # /abs/path/to/complete/
CATEGORIES = (CFG["Torrent"]["categories"]) # music,music_videos,pictures,software
NOFLATTEN = (CFG["Torrent"]["noFlatten"])
UTORRENTWEBUI = CFG["Torrent"]["uTorrentWEBui"] # http://localhost:8090/gui/
UTORRENTUSR = CFG["Torrent"]["uTorrentUSR"] # mysecretusr
UTORRENTPWD = CFG["Torrent"]["uTorrentPWD"] # mysecretpwr
TRANSMISSIONHOST = CFG["Torrent"]["TransmissionHost"] # localhost
TRANSMISSIONPORT = CFG["Torrent"]["TransmissionPort"] # 8084
TRANSMISSIONUSR = CFG["Torrent"]["TransmissionUSR"] # mysecretusr
TRANSMISSIONPWD = CFG["Torrent"]["TransmissionPWD"] # mysecretpwr
DELUGEHOST = CFG["Torrent"]["DelugeHost"] # localhost
DELUGEPORT = CFG["Torrent"]["DelugePort"] # 8084
DELUGEUSR = CFG["Torrent"]["DelugeUSR"] # mysecretusr
DELUGEPWD = CFG["Torrent"]["DelugePWD"] # mysecretpwr
COMPRESSEDCONTAINER = (CFG["Extensions"]["compressedExtensions"]) # .zip,.rar,.7z
MEDIACONTAINER = (CFG["Extensions"]["mediaExtensions"]) # .mkv,.avi,.divx
METACONTAINER = (CFG["Extensions"]["metaExtensions"]) # .nfo,.sub,.srt
MINSAMPLESIZE = int(CFG["Extensions"]["minSampleSize"]) # 200 (in MB)
SAMPLEIDS = (CFG["Extensions"]["SampleIDs"]) # sample,-s.
SECTIONS = ("CouchPotato", "SickBeard", "NzbDrone", "HeadPhones", "Mylar", "Gamez")
SUBSECTIONS = CFG[SECTIONS].subsections
CATEGORIES += CFG[SECTIONS].sections
USER_SCRIPT_CATEGORIES = CFG["UserScript"]["user_script_categories"] # NONE
__INITIALIZED__ = True
return True

View file

@ -1,47 +1,42 @@
import logging
import urllib
import socket
import time
import nzbtomedia
from lib import requests
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import convert_to_ascii
Logger = logging.getLogger()
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!")
logger.error("No directory was given!")
return 1 # failure
# auto-detect correct section
section = config().findsection(inputCategory)
section = nzbtomedia.CFG.findsection(inputCategory)
if not section:
Logger.error(
"MAIN: We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
return 1
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
logger.postprocess("Loading config from %s", nzbtomedia.CONFIG_FILE)
Logger.info("Loading config from %s", config.CONFIG_FILE)
host = config()[section][inputCategory]["host"]
port = config()[section][inputCategory]["port"]
username = config()[section][inputCategory]["username"]
password = config()[section][inputCategory]["password"]
host = nzbtomedia.CFG[section][inputCategory]["host"]
port = nzbtomedia.CFG[section][inputCategory]["port"]
username = nzbtomedia.CFG[section][inputCategory]["username"]
password = nzbtomedia.CFG[section][inputCategory]["password"]
try:
ssl = int(config()[section][inputCategory]["ssl"])
ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"])
except:
ssl = 0
try:
web_root = config()[section][inputCategory]["web_root"]
web_root = nzbtomedia.CFG[section][inputCategory]["web_root"]
except:
web_root = ""
try:
watch_dir = config()[section][inputCategory]["watch_dir"]
watch_dir = nzbtomedia.CFG[section][inputCategory]["watch_dir"]
except:
watch_dir = ""
params = {}
@ -62,16 +57,16 @@ class autoProcessComics:
url = protocol + host + ":" + port + web_root + "/post_process?" + urllib.urlencode(params)
Logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s", url)
try:
r = requests.get(url, auth=(username, password), stream=True)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
logger.error("Unable to open URL")
return 1 # failure
for line in r.iter_lines():
if line: Logger.info("%s", line)
if line: logger.postprocess("%s", line)
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

@ -1,42 +1,37 @@
import json
import logging
import socket
import nzbtomedia
from lib import requests
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import convert_to_ascii
Logger = logging.getLogger()
from nzbtomedia import logger
class autoProcessGames:
def process(self, dirName, nzbName=None, status=0, clientAgent='manual', inputCategory=None):
if dirName is None:
Logger.error("No directory was given!")
logger.error("No directory was given!")
return 1 # failure
# auto-detect correct section
section = config().findsection(inputCategory)
section = nzbtomedia.CFG.findsection(inputCategory)
if not section:
Logger.error(
"MAIN: We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
return 1
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
Logger.info("Loading config from %s", config.CONFIG_FILE)
logger.postprocess("Loading config from %s", nzbtomedia.CONFIG_FILE)
status = int(status)
host = config()[section][inputCategory]["host"]
port = config()[section][inputCategory]["port"]
apikey = config()[section][inputCategory]["apikey"]
host = nzbtomedia.CFG[section][inputCategory]["host"]
port = nzbtomedia.CFG[section][inputCategory]["port"]
apikey = nzbtomedia.CFG[section][inputCategory]["apikey"]
try:
ssl = int(config()[section][inputCategory]["ssl"])
ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"])
except:
ssl = 0
try:
web_root = config()[section][inputCategory]["web_root"]
web_root = nzbtomedia.CFG[section][inputCategory]["web_root"]
except:
web_root = ""
@ -57,23 +52,23 @@ class autoProcessGames:
url = baseURL + "UPDATEREQUESTEDSTATUS&db_id=" + gamezID + "&status=" + downloadStatus
Logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s", url)
try:
r = requests.get(url, stream=True)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
logger.error("Unable to open URL")
return 1 # failure
result = {}
for line in r.iter_lines():
if line:
Logger.info("%s", line)
logger.postprocess("%s", line)
result.update(json.load(line))
if result['success']:
Logger.info("Status for %s has been set to %s in Gamez", gamezID, downloadStatus)
logger.postprocess("Status for %s has been set to %s in Gamez", gamezID, downloadStatus)
return 0 # Success
else:
Logger.error("Status for %s has NOT been updated in Gamez", gamezID)
logger.error("Status for %s has NOT been updated in Gamez", gamezID)
return 1 # failure

View file

@ -1,17 +1,14 @@
import time
import datetime
import logging
import socket
import urllib
import shutil
import json
import nzbtomedia
from lib import requests
from nzbtomedia.Transcoder import Transcoder
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaSceneExceptions import process_all_exceptions
from nzbtomedia.nzbToMediaUtil import getDirectorySize, convert_to_ascii
Logger = logging.getLogger()
from nzbtomedia import logger
class autoProcessMovie:
@ -24,7 +21,7 @@ class autoProcessMovie:
imdbid = nzbName[a:b]
if imdbid:
Logger.info("Found movie id %s in name", imdbid)
logger.postprocess("Found movie id %s in name", imdbid)
return imdbid
a = dirName.find('.cp(') + 4 #search for .cptt( in dirname
@ -33,14 +30,14 @@ class autoProcessMovie:
imdbid = dirName[a:b]
if imdbid:
Logger.info("Found movie id %s in directory", imdbid)
logger.postprocess("Found movie id %s in directory", imdbid)
return imdbid
else:
Logger.debug("Could not find an imdb id in directory or name")
logger.debug("Could not find an imdb id in directory or name")
return ""
def get_movie_info(self, baseURL, imdbid, download_id):
def get_movie_postprocess(self, baseURL, imdbid, download_id):
movie_id = None
movie_status = None
@ -57,12 +54,12 @@ class autoProcessMovie:
while True:
url = baseURL + "media.list/?status=active&release_status=snatched&limit_offset=50," + str(offset)
Logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s", url)
try:
r = requests.get(url)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
logger.error("Unable to open URL")
break
library2 = []
@ -77,7 +74,7 @@ class autoProcessMovie:
release2 = [item["releases"] for item in result["movies"]]
moviestatus2 = [item["status"] for item in result["movies"]]
except Exception, e:
Logger.exception("Unable to parse json data for movies")
logger.error("Unable to parse json data for movies")
break
movieid.extend(movieid2)
@ -99,7 +96,7 @@ class autoProcessMovie:
if imdbid and library[index] == imdbid:
movie_id = str(movieid[index])
movie_status = str(moviestatus[index])
Logger.info("Found movie id %s with status %s in CPS database for movie %s", movie_id, movie_status, imdbid)
logger.postprocess("Found movie id %s with status %s in CPS database for movie %s", movie_id, movie_status, imdbid)
if not download_id and len(releaselist) == 1:
download_id = releaselist[0]["download_info"]["id"]
@ -107,19 +104,19 @@ class autoProcessMovie:
movie_id = str(movieid[index])
movie_status = str(moviestatus[index])
imdbid = str(library[index])
Logger.info("Found movie id %s and imdb %s with status %s in CPS database via download_id %s", movie_id, imdbid, movie_status, download_id)
logger.postprocess("Found movie id %s and imdb %s with status %s in CPS database via download_id %s", movie_id, imdbid, movie_status, download_id)
else:
continue
if len(releaselist) == 1:
release_status = releaselist[0]["status"]
Logger.debug("Found a single release with download_id: %s. Release status is: %s", download_id, release_status)
logger.debug("Found a single release with download_id: %s. Release status is: %s", download_id, release_status)
break
if not movie_id:
Logger.exception("Could not parse database results to determine imdbid or movie id")
logger.error("Could not parse database results to determine imdbid or movie id")
return movie_id, imdbid, download_id, movie_status, release_status
@ -130,22 +127,22 @@ class autoProcessMovie:
if not movie_id:
return movie_status, release_status
Logger.debug("Looking for status of movie: %s", movie_id)
logger.debug("Looking for status of movie: %s", movie_id)
url = baseURL + "media.get/?id=" + str(movie_id)
Logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s", url)
try:
r = requests.get(url)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
logger.error("Unable to open URL")
return None, None
try:
result = r.json()
movie_status = str(result["media"]["status"])
Logger.debug("This movie is marked as status %s in CouchPotatoServer", movie_status)
logger.debug("This movie is marked as status %s in CouchPotatoServer", movie_status)
except:
Logger.exception("Could not find a status for this movie")
logger.error("Could not find a status for this movie")
try:
if len(result["media"]["releases"]) == 1 and result["media"]["releases"][0]["status"] == "done":
@ -154,55 +151,54 @@ class autoProcessMovie:
release_status_list = [item["status"] for item in result["media"]["releases"] if "download_info" in item and item["download_info"]["id"].lower() == download_id.lower()]
if len(release_status_list) == 1:
release_status = release_status_list[0]
Logger.debug("This release is marked as status %s in CouchPotatoServer", release_status)
logger.debug("This release is marked as status %s in CouchPotatoServer", release_status)
except: # index out of range/doesn't exist?
Logger.exception("Could not find a status for this release")
logger.error("Could not find a status for this release")
return movie_status, release_status
def process(self, dirName, nzbName=None, status=0, clientAgent = "manual", download_id = "", inputCategory=None):
if dirName is None:
Logger.error("No directory was given!")
logger.error("No directory was given!")
return 1 # failure
# auto-detect correct section
section = config().findsection(inputCategory)
section = nzbtomedia.CFG.findsection(inputCategory)
if not section:
Logger.error(
"MAIN: We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
return 1
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
Logger.info("Loading config from %s", config.CONFIG_FILE)
logger.postprocess("Loading config from %s", nzbtomedia.CONFIG_FILE)
status = int(status)
host = config()[section][inputCategory]["host"]
port = config()[section][inputCategory]["port"]
apikey = config()[section][inputCategory]["apikey"]
delay = float(config()[section][inputCategory]["delay"])
method = config()[section][inputCategory]["method"]
delete_failed = int(config()[section][inputCategory]["delete_failed"])
wait_for = int(config()[section][inputCategory]["wait_for"])
host = nzbtomedia.CFG[section][inputCategory]["host"]
port = nzbtomedia.CFG[section][inputCategory]["port"]
apikey = nzbtomedia.CFG[section][inputCategory]["apikey"]
delay = float(nzbtomedia.CFG[section][inputCategory]["delay"])
method = nzbtomedia.CFG[section][inputCategory]["method"]
delete_failed = int(nzbtomedia.CFG[section][inputCategory]["delete_failed"])
wait_for = int(nzbtomedia.CFG[section][inputCategory]["wait_for"])
try:
TimePerGiB = int(config()[section][inputCategory]["TimePerGiB"])
TimePerGiB = int(nzbtomedia.CFG[section][inputCategory]["TimePerGiB"])
except:
TimePerGiB = 60 # note, if using Network to transfer on 100Mbit LAN, expect ~ 600 MB/minute.
try:
ssl = int(config()[section][inputCategory]["ssl"])
ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"])
except:
ssl = 0
try:
web_root = config()[section][inputCategory]["web_root"]
web_root = nzbtomedia.CFG[section][inputCategory]["web_root"]
except:
web_root = ""
try:
transcode = int(config()["Transcoder"]["transcode"])
transcode = int(nzbtomedia.CFG["Transcoder"]["transcode"])
except:
transcode = 0
try:
remoteCPS = int(config()[section][inputCategory]["remoteCPS"])
remoteCPS = int(nzbtomedia.CFG[section][inputCategory]["remoteCPS"])
except:
remoteCPS = 0
@ -221,7 +217,7 @@ class autoProcessMovie:
baseURL = protocol + host + ":" + port + web_root + "/api/" + apikey + "/"
movie_id, imdbid, download_id, initial_status, initial_release_status = self.get_movie_info(baseURL, imdbid, download_id) # get the CPS database movie id for this movie.
movie_id, imdbid, download_id, initial_status, initial_release_status = self.get_movie_postprocess(baseURL, imdbid, download_id) # get the CPS database movie id for this movie.
process_all_exceptions(nzbName.lower(), dirName)
nzbName, dirName = convert_to_ascii(nzbName, dirName)
@ -230,9 +226,9 @@ class autoProcessMovie:
if 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)
else:
Logger.warning("Transcoding failed for files in %s", dirName)
logger.warning("Transcoding failed for files in %s", dirName)
if method == "manage":
command = "manage.update"
@ -251,55 +247,55 @@ class autoProcessMovie:
url = baseURL + command
Logger.info("Waiting for %s seconds to allow CPS to process newly extracted files", str(delay))
logger.postprocess("Waiting for %s seconds to allow CPS to process newly extracted files", str(delay))
time.sleep(delay)
Logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s", url)
try:
r = requests.get(url)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
logger.error("Unable to open URL")
return 1 # failure
result = r.json()
Logger.info("CouchPotatoServer returned %s", result)
logger.postprocess("CouchPotatoServer returned %s", result)
if result['success']:
Logger.info("%s scan started on CouchPotatoServer for %s", method, nzbName)
logger.postprocess("%s scan started on CouchPotatoServer for %s", method, nzbName)
else:
Logger.error("%s scan has NOT started on CouchPotatoServer for %s. Exiting", method, nzbName)
logger.error("%s scan has NOT started on CouchPotatoServer for %s. Exiting", method, nzbName)
return 1 # failure
else:
Logger.info("Download of %s has failed.", nzbName)
Logger.info("Trying to re-cue the next highest ranked release")
logger.postprocess("Download of %s has failed.", nzbName)
logger.postprocess("Trying to re-cue the next highest ranked release")
if not movie_id:
Logger.warning("Cound not find a movie in the database for release %s", nzbName)
Logger.warning("Please manually ignore this release and refresh the wanted movie")
Logger.error("Exiting autoProcessMovie script")
logger.warning("Cound not find a movie in the database for release %s", nzbName)
logger.warning("Please manually ignore this release and refresh the wanted movie")
logger.error("Exiting autoProcessMovie script")
return 1 # failure
url = baseURL + "movie.searcher.try_next/?media_id=" + movie_id
Logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s", url)
try:
r = requests.get(url, stream=True)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
logger.error("Unable to open URL")
return 1 # failure
for line in r.iter_lines():
if line: Logger.info("%s", line)
Logger.info("Movie %s set to try the next best release on CouchPotatoServer", movie_id)
if line: logger.postprocess("%s", line)
logger.postprocess("Movie %s set to try the next best release on CouchPotatoServer", movie_id)
if delete_failed and not dirName in ['sys.argv[0]','/','']:
Logger.info("Deleting failed files and folder %s", dirName)
logger.postprocess("Deleting failed files and folder %s", dirName)
try:
shutil.rmtree(dirName)
except:
Logger.exception("Unable to delete folder %s", dirName)
logger.error("Unable to delete folder %s", dirName)
return 0 # success
if clientAgent == "manual":
@ -311,21 +307,19 @@ class autoProcessMovie:
return 0 # success
# we will now check to see if CPS has finished renaming before returning to TorrentToMedia and unpausing.
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
release_status = None
start = datetime.datetime.now() # set time for timeout
pause_for = int(wait_for) * 10 # keep this so we only ever have 6 complete loops. This may not be necessary now?
while (datetime.datetime.now() - start) < datetime.timedelta(minutes=wait_for): # only wait 2 (default) minutes, then return.
movie_status, release_status = self.get_status(baseURL, movie_id, download_id) # get the current status fo this movie.
if movie_status and initial_status and movie_status != initial_status: # Something has changed. CPS must have processed this movie.
Logger.info("SUCCESS: This movie is now marked as status %s in CouchPotatoServer", movie_status)
logger.postprocess("SUCCESS: This movie is now marked as status %s in CouchPotatoServer", movie_status)
return 0 # success
time.sleep(pause_for) # Just stop this looping infinitely and hogging resources for 2 minutes ;)
else:
if release_status and initial_release_status and release_status != initial_release_status: # Something has changed. CPS must have processed this movie.
Logger.info("SUCCESS: This release is now marked as status %s in CouchPotatoServer", release_status)
logger.postprocess("SUCCESS: This release is now marked as status %s in CouchPotatoServer", release_status)
return 0 # success
else: # 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("The movie does not appear to have changed status after %s minutes. Please check CouchPotato Logs", wait_for)
return 1 # failure

View file

@ -1,48 +1,44 @@
import time
import datetime
import logging
import socket
import urllib
import nzbtomedia
from lib import requests
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import convert_to_ascii, getDirectorySize
Logger = logging.getLogger()
from nzbtomedia import logger
class autoProcessMusic:
def process(self, dirName, nzbName=None, status=0, clientAgent="manual", inputCategory=None):
if dirName is None:
Logger.error("No directory was given!")
logger.error("No directory was given!")
return 1 # failure
# auto-detect correct section
section = config().findsection(inputCategory)
section = nzbtomedia.CFG.findsection(inputCategory)
if len(section) == 0:
Logger.error(
"MAIN: We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
return 1
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
Logger.info("Loading config from %s", config.CONFIG_FILE)
logger.postprocess("Loading config from %s", nzbtomedia.CONFIG_FILE)
status = int(status)
host = config()[section][inputCategory]["host"]
port = config()[section][inputCategory]["port"]
apikey = config()[section][inputCategory]["apikey"]
delay = float(config()[section][inputCategory]["delay"])
host = nzbtomedia.CFG[section][inputCategory]["host"]
port = nzbtomedia.CFG[section][inputCategory]["port"]
apikey = nzbtomedia.CFG[section][inputCategory]["apikey"]
delay = float(nzbtomedia.CFG[section][inputCategory]["delay"])
try:
ssl = int(config()[section][inputCategory]["ssl"])
ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"])
except:
ssl = 0
try:
web_root = config()[section][inputCategory]["web_root"]
web_root = nzbtomedia.CFG[section][inputCategory]["web_root"]
except:
web_root = ""
try:
TimePerGiB = int(config()[section][inputCategory]["TimePerGiB"])
TimePerGiB = int(nzbtomedia.CFG[section][inputCategory]["TimePerGiB"])
except:
TimePerGiB = 60 # note, if using Network to transfer on 100Mbit LAN, expect ~ 600 MB/minute.
@ -72,27 +68,27 @@ class autoProcessMusic:
url = baseURL + urllib.urlencode(params)
Logger.info("Waiting for %s seconds to allow HeadPhones to process newly extracted files", str(delay))
logger.postprocess("Waiting for %s seconds to allow HeadPhones to process newly extracted files", str(delay))
time.sleep(delay)
Logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s", url)
try:
r = requests.get(url)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
logger.error("Unable to open URL")
return 1 # failure
Logger.info("HeadPhones returned %s", r.text)
logger.postprocess("HeadPhones returned %s", r.text)
if r.text == "OK":
Logger.info("Post-processing started on HeadPhones for %s in folder %s", nzbName, dirName)
logger.postprocess("Post-processing started on HeadPhones for %s in folder %s", nzbName, dirName)
else:
Logger.error("Post-proecssing has NOT started on HeadPhones for %s in folder %s. Exiting", nzbName, dirName)
logger.error("Post-proecssing has NOT started on HeadPhones for %s in folder %s. Exiting", nzbName, dirName)
return 1 # failure
else:
Logger.info("The download failed. Nothing to process")
logger.postprocess("The download failed. Nothing to process")
return 0 # Success (as far as this script is concerned)
if clientAgent == "manual":
@ -104,7 +100,7 @@ class autoProcessMusic:
while (datetime.datetime.now() - start) < datetime.timedelta(minutes=1): # only wait 2 minutes, then return to TorrentToMedia
time.sleep(20) # Just stop this looping infinitely and hogging resources for 2 minutes ;)
else: # The status hasn't changed. we have waited 2 minutes which is more than enough. uTorrent can resume seeding now.
Logger.info("This album should have completed processing. Please check HeadPhones Logs")
# Logger.warning("The album does not appear to have changed status after 2 minutes. Please check HeadPhones Logs")
logger.postprocess("This album should have completed processing. Please check HeadPhones Logs")
# logger.warning("The album does not appear to have changed status after 2 minutes. Please check HeadPhones Logs")
# return 1 # failure
return 0 # success for now.

View file

@ -1,99 +1,95 @@
import copy
import json
import logging
import os
import socket
import urllib
import time
import nzbtomedia
from lib import requests
from nzbtomedia.Transcoder import Transcoder
from nzbtomedia.nzbToMediaAutoFork import autoFork
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaSceneExceptions import process_all_exceptions
from nzbtomedia.nzbToMediaUtil import convert_to_ascii, is_sample, flatten, getDirectorySize, delete
Logger = logging.getLogger()
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!")
logger.error("No directory was given!")
return 1 # failure
# auto-detect correct section
section = config().findsection(inputCategory)
section = nzbtomedia.CFG.findsection(inputCategory)
if not section:
Logger.error(
"MAIN: We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
return 1
# auto-detect correct fork
fork, fork_params = autoFork(inputCategory)
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
Logger.info("Loading config from %s", config.CONFIG_FILE)
logger.postprocess("Loading config from %s", nzbtomedia.CONFIG_FILE)
status = int(failed)
host = config()[section][inputCategory]["host"]
port = config()[section][inputCategory]["port"]
username = config()[section][inputCategory]["username"]
password = config()[section][inputCategory]["password"]
host = nzbtomedia.CFG[section][inputCategory]["host"]
port = nzbtomedia.CFG[section][inputCategory]["port"]
username = nzbtomedia.CFG[section][inputCategory]["username"]
password = nzbtomedia.CFG[section][inputCategory]["password"]
try:
apikey = config()[section][inputCategory]["apikey"]
apikey = nzbtomedia.CFG[section][inputCategory]["apikey"]
except:
apikey = ""
try:
ssl = int(config()[section][inputCategory]["ssl"])
ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"])
except:
ssl = 0
try:
web_root = config()[section][inputCategory]["web_root"]
web_root = nzbtomedia.CFG[section][inputCategory]["web_root"]
except:
web_root = ""
try:
watch_dir = config()[section][inputCategory]["watch_dir"]
watch_dir = nzbtomedia.CFG[section][inputCategory]["watch_dir"]
except:
watch_dir = ""
try:
transcode = int(config()["Transcoder"]["transcode"])
transcode = int(nzbtomedia.CFG["Transcoder"]["transcode"])
except:
transcode = 0
try:
delete_failed = int(config()[section][inputCategory]["delete_failed"])
delete_failed = int(nzbtomedia.CFG[section][inputCategory]["delete_failed"])
except:
delete_failed = 0
try:
delay = float(config()[section][inputCategory]["delay"])
delay = float(nzbtomedia.CFG[section][inputCategory]["delay"])
except:
delay = 0
try:
TimePerGiB = int(config()[section][inputCategory]["TimePerGiB"])
TimePerGiB = int(nzbtomedia.CFG[section][inputCategory]["TimePerGiB"])
except:
TimePerGiB = 60 # note, if using Network to transfer on 100Mbit LAN, expect ~ 600 MB/minute.
try:
SampleIDs = (config()["Extensions"]["SampleIDs"])
SampleIDs = (nzbtomedia.CFG["Extensions"]["SampleIDs"])
except:
SampleIDs = ['sample','-s.']
try:
nzbExtractionBy = config()[section][inputCategory]["nzbExtractionBy"]
nzbExtractionBy = nzbtomedia.CFG[section][inputCategory]["nzbExtractionBy"]
except:
nzbExtractionBy = "Downloader"
try:
process_method = config()[section][inputCategory]["process_method"]
process_method = nzbtomedia.CFG[section][inputCategory]["process_method"]
except:
process_method = None
try:
Torrent_NoLink = int(config()[section][inputCategory]["Torrent_NoLink"])
Torrent_NoLink = int(nzbtomedia.CFG[section][inputCategory]["Torrent_NoLink"])
except:
Torrent_NoLink = 0
mediaContainer = (config()["Extensions"]["mediaExtensions"])
minSampleSize = int(config()["Extensions"]["minSampleSize"])
mediaContainer = (nzbtomedia.CFG["Extensions"]["mediaExtensions"])
minSampleSize = int(nzbtomedia.CFG["Extensions"]["minSampleSize"])
if not os.path.isdir(dirName) and os.path.isfile(dirName): # If the input directory is a file, assume single file download and split dir/name.
dirName = os.path.split(os.path.normpath(dirName))[0]
@ -105,7 +101,7 @@ class autoProcessTV:
if os.path.isdir(SpecificPath):
dirName = SpecificPath
if fork not in config.SICKBEARD_TORRENT or (clientAgent in ['nzbget','sabnzbd'] and nzbExtractionBy != "Destination"):
if fork not in nzbtomedia.SICKBEARD_TORRENT or (clientAgent in ['nzbget','sabnzbd'] and nzbExtractionBy != "Destination"):
if nzbName:
process_all_exceptions(nzbName.lower(), dirName)
nzbName, dirName = convert_to_ascii(nzbName, dirName)
@ -118,17 +114,17 @@ class autoProcessTV:
fileExtension = os.path.splitext(file)[1]
if fileExtension in mediaContainer: # If the file is a video file
if is_sample(filePath, nzbName, minSampleSize, SampleIDs):
Logger.debug("Removing sample file: %s", filePath)
logger.debug("Removing sample file: %s", filePath)
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)
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)
status = int(1)
failed = True
@ -150,7 +146,7 @@ class autoProcessTV:
fork_params[param] = dirName
if param == "process_method":
if fork in config.SICKBEARD_TORRENT and Torrent_NoLink == 1 and not clientAgent in ['nzbget','sabnzbd']: #use default SickBeard settings here.
if fork in nzbtomedia.SICKBEARD_TORRENT and Torrent_NoLink == 1 and not clientAgent in ['nzbget','sabnzbd']: #use default SickBeard settings here.
del fork_params[param]
if process_method:
fork_params[param] = process_method
@ -161,22 +157,22 @@ class autoProcessTV:
[fork_params.pop(k) for k,v in fork_params.items() if v is None]
if status == 0:
Logger.info("The download succeeded. Sending process request to %s", section)
elif fork in config.SICKBEARD_FAILED:
Logger.info("The download failed. Sending 'failed' process request to SickBeard's %s branch", fork)
logger.postprocess("The download succeeded. Sending process request to %s", section)
elif fork in nzbtomedia.SICKBEARD_FAILED:
logger.postprocess("The download failed. Sending 'failed' process request to SickBeard's %s branch", fork)
else:
Logger.info("The download failed. SickBeard's %s branch does not handle failed downloads. Nothing to process", fork)
logger.postprocess("The download failed. SickBeard's %s branch does not handle failed downloads. Nothing to process", fork)
if delete_failed and os.path.isdir(dirName) and not dirName in ['sys.argv[0]','/','']:
Logger.info("Deleting directory: %s", dirName)
logger.postprocess("Deleting directory: %s", dirName)
delete(dirName)
return 0 # Success (as far as this script is concerned)
if status == 0 and 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("Transcoding succeeded for files in %s", dirName)
else:
Logger.warning("Transcoding failed for files in %s", dirName)
logger.warning("Transcoding failed for files in %s", dirName)
if ssl:
protocol = "https://"
@ -191,13 +187,14 @@ class autoProcessTV:
url = protocol + host + ":" + port + web_root + "/api/command"
if clientAgent == "manual":delay = 0
Logger.info("Waiting for %s seconds to allow %s to process newly extracted files", str(delay), section)
logger.postprocess("Waiting for %s seconds to allow %s to process newly extracted files", str(delay), section)
time.sleep(delay)
Logger.debug("Opening URL: %s", url)
logger.debug("Opening URL: %s", url)
try:
r = None
if section == "SickBeard":
r = requests.get(url, auth=(username, password), stream=True)
elif section == "NzbDrone":
@ -205,11 +202,11 @@ class autoProcessTV:
headers = {"X-Api-Key": apikey}
r = requests.get(url, data=data, headers=headers, stream=True)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
logger.error("Unable to open URL")
return 1 # failure
for line in r.iter_lines():
if line: Logger.info("%s", line)
if line: logger.postprocess("%s", line)
if status != 0 and delete_failed and not dirName in ['sys.argv[0]','/','']:
delete(dirName)

View file

@ -37,7 +37,7 @@ def extract(filePath, outputDestination):
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")
logger.error("EXTRACTOR: Could not find 7-zip, Exiting")
return False
else:
if not os.path.exists(chplocation):
@ -72,7 +72,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.warn("EXTRACTOR: Cannot determine which tool to use when called from Transmission")
@ -91,22 +91,22 @@ def extract(filePath, outputDestination):
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
create_destination(outputDestination)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
logger.info("Loading config from %s", nzbtomedia.CONFIG_FILE)
passwordsfile = config()["passwords"]["PassWordFile"]
passwordsfile = nzbtomedia.CFG["passwords"]["PassWordFile"]
if passwordsfile != "" and os.path.isfile(os.path.normpath(passwordsfile)):
passwords = [line.strip() for line in open(os.path.normpath(passwordsfile))]
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
@ -116,9 +116,9 @@ def extract(filePath, outputDestination):
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)
logger.info("EXTRACTOR: Extraction was successful for %s to %s", filePath, outputDestination)
elif len(passwords) > 0:
Logger.info("EXTRACTOR: Attempting to extract with passwords")
logger.info("EXTRACTOR: Attempting to extract with passwords")
pass_success = int(0)
for password in passwords:
if password == "": # if edited in windows or otherwise if blank lines.
@ -130,14 +130,14 @@ def extract(filePath, outputDestination):
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)
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.exception("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

62
nzbtomedia/gh_api.py Normal file
View file

@ -0,0 +1,62 @@
import json
from lib import requests
class GitHub(object):
"""
Simple api wrapper for the Github API v3.
"""
def __init__(self, github_repo_user, github_repo, branch='master'):
self.github_repo_user = github_repo_user
self.github_repo = github_repo
self.branch = branch
def _access_API(self, path, params=None):
"""
Access the API at the path given and with the optional params given.
"""
url = 'https://api.github.com/' + '/'.join(path)
if params and type(params) is dict:
url += '?' + '&'.join([str(x) + '=' + str(params[x]) for x in params.keys()])
data = requests.get(url)
if data.ok:
json_data = data.json()
return json_data
else:
return []
def commits(self):
"""
Uses the API to get a list of the 100 most recent commits from the specified user/repo/branch, starting from HEAD.
user: The github username of the person whose repo you're querying
repo: The repo name to query
branch: Optional, the branch name to show commits from
Returns a deserialized json object containing the commit info. See http://developer.github.com/v3/repos/commits/
"""
access_API = self._access_API(['repos', self.github_repo_user, self.github_repo, 'commits'],
params={'per_page': 100, 'sha': self.branch})
return access_API
def compare(self, base, head, per_page=1):
"""
Uses the API to get a list of compares between base and head.
user: The github username of the person whose repo you're querying
repo: The repo name to query
base: Start compare from branch
head: Current commit sha or branch name to compare
per_page: number of items per page
Returns a deserialized json object containing the compare info. See http://developer.github.com/v3/repos/commits/
"""
access_API = self._access_API(
['repos', self.github_repo_user, self.github_repo, 'compare', base + '...' + head],
params={'per_page': per_page})
return access_API

245
nzbtomedia/logger.py Normal file
View file

@ -0,0 +1,245 @@
from __future__ import with_statement
import os
import sys
import threading
import logging
import nzbtomedia
# number of log files to keep
NUM_LOGS = 3
# log size in bytes
LOG_SIZE = 10000000 # 10 megs
ERROR = logging.ERROR
WARNING = logging.WARNING
MESSAGE = logging.INFO
DEBUG = logging.DEBUG
POSTPROCESS = 5
reverseNames = {u'ERROR': ERROR,
u'WARNING': WARNING,
u'INFO': MESSAGE,
u'DEBUG': DEBUG,
u'POSTPROCESS': POSTPROCESS}
class NTMRotatingLogHandler(object):
def __init__(self, log_file, num_files, num_bytes):
self.num_files = num_files
self.num_bytes = num_bytes
self.log_file = log_file
self.log_file_path = log_file
self.cur_handler = None
self.writes_since_check = 0
self.console_logging = True
self.log_lock = threading.Lock()
def close_log(self, handler=None):
if not handler:
handler = self.cur_handler
if handler:
ntm_logger = logging.getLogger('nzbtomedia')
pp_logger = logging.getLogger('postprocess')
ntm_logger.removeHandler(handler)
pp_logger.removeHandler(handler)
handler.flush()
handler.close()
def initLogging(self, consoleLogging=True):
if consoleLogging:
self.console_logging = consoleLogging
old_handler = None
# get old handler in case we want to close it
if self.cur_handler:
old_handler = self.cur_handler
else:
#Add a new logging level POSTPROCESS
logging.addLevelName(5, 'POSTPROCESS')
# only start consoleLogging on first initialize
if self.console_logging:
# define a Handler which writes INFO messages or higher to the sys.stderr
console = logging.StreamHandler()
# 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')
},
logging.Formatter('%(message)s'), ))
# add the handler to the root logger
logging.getLogger('nzbtomedia').addHandler(console)
logging.getLogger('postprocess').addHandler(console)
self.log_file_path = os.path.join(nzbtomedia.LOG_DIR, self.log_file)
self.cur_handler = self._config_handler()
logging.getLogger('nzbtomedia').addHandler(self.cur_handler)
logging.getLogger('postprocess').addHandler(self.cur_handler)
logging.getLogger('nzbtomedia').setLevel(logging.INFO)
logging.getLogger('postprocess').setLevel(POSTPROCESS)
# already logging in new log folder, close the old handler
if old_handler:
self.close_log(old_handler)
def _config_handler(self):
"""
Configure a file handler to log at file_name and return it.
"""
file_handler = logging.FileHandler(self.log_file_path, encoding='utf-8')
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')
},
logging.Formatter('%(message)s'), ))
return file_handler
def _log_file_name(self, i):
"""
Returns a numbered log file name depending on i. If i==0 it just uses logName, if not it appends
it to the extension (blah.log.3 for i == 3)
i: Log number to ues
"""
return self.log_file_path + ('.' + str(i) if i else '')
def _num_logs(self):
"""
Scans the log folder and figures out how many log files there are already on disk
Returns: The number of the last used file (eg. mylog.log.3 would return 3). If there are no logs it returns -1
"""
cur_log = 0
while os.path.isfile(self._log_file_name(cur_log)):
cur_log += 1
return cur_log - 1
def _rotate_logs(self):
ntm_logger = logging.getLogger('nzbtomedia')
pp_logger = logging.getLogger('postprocess')
# delete the old handler
if self.cur_handler:
self.close_log()
# rename or delete all the old log files
for i in range(self._num_logs(), -1, -1):
cur_file_name = self._log_file_name(i)
try:
if i >= NUM_LOGS:
os.remove(cur_file_name)
else:
os.rename(cur_file_name, self._log_file_name(i + 1))
except OSError:
pass
# the new log handler will always be on the un-numbered .log file
new_file_handler = self._config_handler()
self.cur_handler = new_file_handler
ntm_logger.addHandler(new_file_handler)
pp_logger.addHandler(new_file_handler)
def log(self, toLog, logLevel=MESSAGE):
with self.log_lock:
# check the size and see if we need to rotate
if self.writes_since_check >= 10:
if os.path.isfile(self.log_file_path) and os.path.getsize(self.log_file_path) >= LOG_SIZE:
self._rotate_logs()
self.writes_since_check = 0
else:
self.writes_since_check += 1
message = u"" + toLog
out_line = message
ntm_logger = logging.getLogger('nzbtomedia')
pp_logger = logging.getLogger('postprocess')
setattr(pp_logger, 'postprocess', lambda *args: pp_logger.log(POSTPROCESS, *args))
try:
if logLevel == DEBUG:
ntm_logger.debug(out_line)
elif logLevel == MESSAGE:
ntm_logger.info(out_line)
elif logLevel == WARNING:
ntm_logger.warning(out_line)
elif logLevel == ERROR:
ntm_logger.error(out_line)
elif logLevel == POSTPROCESS:
pp_logger.postprocess(out_line)
else:
ntm_logger.info(logLevel, out_line)
except ValueError:
pass
def log_error_and_exit(self, error_msg):
log(error_msg, ERROR)
if not self.console_logging:
sys.exit(error_msg.encode(nzbtomedia.SYS_ENCODING, 'xmlcharrefreplace'))
else:
sys.exit(1)
class DispatchingFormatter:
def __init__(self, formatters, default_formatter):
self._formatters = formatters
self._default_formatter = default_formatter
def format(self, record):
formatter = self._formatters.get(record.name, self._default_formatter)
return formatter.format(record)
ntm_log_instance = NTMRotatingLogHandler("nzbtomedia.log", NUM_LOGS, LOG_SIZE)
def log(toLog, logLevel=MESSAGE):
ntm_log_instance.log(toLog, logLevel)
def info(toLog, *args):
toLog = toLog % args
ntm_log_instance.log(toLog, MESSAGE)
def error(toLog, *args):
toLog = toLog % args
ntm_log_instance.log(toLog, ERROR)
def warning(toLog, *args):
toLog = toLog % args
ntm_log_instance.log(toLog, WARNING)
def debug(toLog, *args):
toLog = toLog % args
ntm_log_instance.log(toLog, DEBUG)
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

@ -1,8 +1,9 @@
import logging
import urllib
from lib import requests
import nzbtomedia
from lib import requests
from nzbToMediaConfig import config
def autoFork(inputCategory):
@ -10,39 +11,39 @@ def autoFork(inputCategory):
Logger = logging.getLogger()
# auto-detect correct section
section = config().findsection(inputCategory)
section = nzbtomedia.CFG.findsection(inputCategory)
if not section:
Logger.error(
"MAIN: We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
logger.error(
"We were unable to find a section for category %s, please check your autoProcessMedia.cfg file.", inputCategory)
return 1
# config settings
try:
host = config()[section][inputCategory]["host"]
port = config()[section][inputCategory]["port"]
host = nzbtomedia.CFG[section][inputCategory]["host"]
port = nzbtomedia.CFG[section][inputCategory]["port"]
except:
host = None
port = None
try:
username = config()[section][inputCategory]["username"]
password = config()[section][inputCategory]["password"]
username = nzbtomedia.CFG[section][inputCategory]["username"]
password = nzbtomedia.CFG[section][inputCategory]["password"]
except:
username = None
password = None
try:
ssl = int(config()[section][inputCategory]["ssl"])
ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"])
except (config, ValueError):
ssl = 0
try:
web_root = config()[section][inputCategory]["web_root"]
web_root = nzbtomedia.CFG[section][inputCategory]["web_root"]
except config:
web_root = ""
try:
fork = config.FORKS.items()[config.FORKS.keys().index(config()[section][inputCategory]["fork"])]
fork = nzbtomedia.FORKS.items()[nzbtomedia.FORKS.keys().index(nzbtomedia.CFG[section][inputCategory]["fork"])]
except:
fork = "auto"
@ -53,8 +54,8 @@ def autoFork(inputCategory):
detected = False
if fork == "auto":
Logger.info("Attempting to auto-detect " + section + " fork")
for fork in sorted(config.FORKS.iteritems()):
logger.info("Attempting to auto-detect " + section + " fork")
for fork in sorted(nzbtomedia.FORKS.iteritems()):
url = protocol + host + ":" + port + web_root + "/home/postprocess/processEpisode?" + urllib.urlencode(fork[1])
# attempting to auto-detect fork
@ -64,7 +65,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 " + section + ":" + inputCategory + " to perform auto-fork detection!")
break
if r.ok:
@ -72,10 +73,10 @@ def autoFork(inputCategory):
break
if detected:
Logger.info("" + section + ":" + inputCategory + " fork auto-detection successful ...")
logger.info("" + section + ":" + inputCategory + " fork auto-detection successful ...")
else:
Logger.info("" + section + ":" + inputCategory + " fork auto-detection failed")
fork = config.FORKS.items()[config.FORKS.keys().index(config.FORK_DEFAULT)]
logger.info("" + section + ":" + inputCategory + " fork auto-detection failed")
fork = nzbtomedia.FORKS.items()[nzbtomedia.FORKS.keys().index(nzbtomedia.FORK_DEFAULT)]
Logger.info("" + section + ":" + inputCategory + " fork set to %s", fork[0])
logger.info("" + section + ":" + inputCategory + " fork set to %s", fork[0])
return fork[0], fork[1]

View file

@ -1,5 +1,6 @@
import os
import shutil
import nzbtomedia
import lib.configobj
from itertools import chain
@ -66,52 +67,9 @@ class Section(lib.configobj.Section):
return subsection
class ConfigObj(lib.configobj.ConfigObj, Section):
# constants for nzbtomedia
NZBTOMEDIA_VERSION = 'V9.3'
NZBTOMEDIA_TIMEOUT = 60
# Constants pertinant to SabNzb
SABNZB_NO_OF_ARGUMENTS = 8
SABNZB_0717_NO_OF_ARGUMENTS = 9
# Constants pertaining to SickBeard Branches:
FORKS = {}
FORK_DEFAULT = "default"
FORK_FAILED = "failed"
FORK_FAILED_TORRENT = "failed-torrent"
FORKS[FORK_DEFAULT] = {"dir": None, "method": None}
FORKS[FORK_FAILED] = {"dirName": None, "failed": None}
FORKS[FORK_FAILED_TORRENT] = {"dir": None, "failed": None, "process_method": None}
SICKBEARD_FAILED = [FORK_FAILED, FORK_FAILED_TORRENT]
SICKBEARD_TORRENT = [FORK_FAILED_TORRENT]
# NZBGet Exit Codes
NZBGET_POSTPROCESS_PARCHECK = 92
NZBGET_POSTPROCESS_SUCCESS = 93
NZBGET_POSTPROCESS_ERROR = 94
NZBGET_POSTPROCESS_NONE = 95
# config files
PROGRAM_DIR = os.path.dirname(os.path.normpath(os.path.abspath(os.path.join(__file__, os.pardir))))
CONFIG_FILE = os.path.join(PROGRAM_DIR, "autoProcessMedia.cfg")
SAMPLE_CONFIG_FILE = os.path.join(PROGRAM_DIR, "autoProcessMedia.cfg.sample")
MOVIE_CONFIG_FILE = os.path.join(PROGRAM_DIR, "autoProcessMovie.cfg")
TV_CONFIG_FILE = os.path.join(PROGRAM_DIR, "autoProcessTv.cfg")
LOG_FILE = os.path.join(PROGRAM_DIR, "postprocess.log")
LOG_CONFIG = os.path.join(PROGRAM_DIR, "logging.cfg")
SAMPLE_LOG_CONFIG = os.path.join(PROGRAM_DIR, "logging.cfg.sample")
try:
repo = check_output(["git", "config", "--get", "remote.origin.url"]).splitlines()[0]
branch = check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]).splitlines()[0]
hash = check_output(["git", "rev-parse", "--short", "HEAD"]).splitlines()[0]
NZBTOMEDIA_VERSION = 'repo:' + repo + ' branch:' + branch + ' hash: ' + hash
except CalledProcessError:
pass
def __init__(self, *args, **kw):
if len(args) == 0:
args = (self.CONFIG_FILE,)
args = (nzbtomedia.CONFIG_FILE,)
super(lib.configobj.ConfigObj, self).__init__(*args, **kw)
self.interpolation = False
@ -127,53 +85,55 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
#result.update({key: val})
return val
def migrate(self):
global config_new, config_old
config_new = config_old = None
@staticmethod
def migrate():
global CFG_NEW, CFG_OLD
CFG_NEW = None
CFG_OLD = None
try:
# check for autoProcessMedia.cfg and create if it does not exist
if not config():
shutil.copyfile(self.SAMPLE_CONFIG_FILE, self.CONFIG_FILE)
config_old = config()
if not os.path.isfile(nzbtomedia.CONFIG_FILE):
shutil.copyfile(nzbtomedia.CONFIG_SPEC_FILE, nzbtomedia.CONFIG_FILE)
CFG_OLD = config(nzbtomedia.CONFIG_FILE)
except:
pass
try:
# check for autoProcessMedia.cfg.sample and create if it does not exist
if not config(self.SAMPLE_CONFIG_FILE):
shutil.copyfile(self.CONFIG_FILE, self.SAMPLE_CONFIG_FILE)
config_new = config(self.SAMPLE_CONFIG_FILE)
# check for autoProcessMedia.cfg.spec and create if it does not exist
if not os.path.isfile(nzbtomedia.CONFIG_SPEC_FILE):
shutil.copyfile(nzbtomedia.CONFIG_FILE, nzbtomedia.CONFIG_SPEC_FILE)
CFG_NEW = config(nzbtomedia.CONFIG_SPEC_FILE)
except:
pass
# check for autoProcessMedia.cfg and autoProcessMedia.cfg.sample and if they don't exist return and fail
if not config() and not config(self.SAMPLE_CONFIG_FILE) or not config_new or not config_old:
# check for autoProcessMedia.cfg and autoProcessMedia.cfg.spec and if they don't exist return and fail
if not CFG_NEW or not CFG_OLD:
return False
subsections = {}
# gather all new-style and old-style sub-sections
for newsection, newitems in config_new.items():
if config_new[newsection].sections:
subsections.update({newsection: config_new[newsection].sections})
for section, items in config_old.items():
if config_old[section].sections:
subsections.update({section: config_old[section].sections})
for option, value in config_old[section].items():
for newsection, newitems in CFG_NEW.items():
if CFG_NEW[newsection].sections:
subsections.update({newsection: CFG_NEW[newsection].sections})
for section, items in CFG_OLD.items():
if CFG_OLD[section].sections:
subsections.update({section: CFG_OLD[section].sections})
for option, value in CFG_OLD[section].items():
if option in ["category", "cpsCategory", "sbCategory", "hpCategory", "mlCategory", "gzCategory"]:
if not isinstance(value, list):
value = [value]
# add subsection
subsections.update({section: value})
config_old[section].pop(option)
CFG_OLD[section].pop(option)
continue
def cleanup_values(values, section):
for option, value in values.iteritems():
if section in ['CouchPotato']:
if option == ['outputDirectory']:
config_new['Torrent'][option] = os.path.split(os.path.normpath(value))[0]
CFG_NEW['Torrent'][option] = os.path.split(os.path.normpath(value))[0]
values.pop(option)
if section in ['CouchPotato', 'HeadPhones', 'Gamez']:
if option in ['username', 'password']:
@ -188,11 +148,11 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
values['Torrent_NoLink'] = value
values.pop(option)
if option == "outputDirectory": # move this to new location format
config_new['Torrent'][option] = os.path.split(os.path.normpath(value))[0]
CFG_NEW['Torrent'][option] = os.path.split(os.path.normpath(value))[0]
values.pop(option)
if section in ["Torrent"]:
if option in ["compressedExtensions", "mediaExtensions", "metaExtensions", "minSampleSize"]:
config_new['Extensions'][option] = value
CFG_NEW['Extensions'][option] = value
values.pop(option)
if option == "useLink": # Sym links supported now as well.
if isinstance(value, int):
@ -206,27 +166,27 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
def process_section(section, subsections=None):
if subsections:
for subsection in subsections:
if subsection in config_old.sections:
values = config_old[subsection]
if subsection not in config_new[section].sections:
config_new[section][subsection] = {}
if subsection in CFG_OLD.sections:
values = CFG_OLD[subsection]
if subsection not in CFG_NEW[section].sections:
CFG_NEW[section][subsection] = {}
for option, value in values.items():
config_new[section][subsection][option] = value
elif subsection in config_old[section].sections:
values = config_old[section][subsection]
if subsection not in config_new[section].sections:
config_new[section][subsection] = {}
CFG_NEW[section][subsection][option] = value
elif subsection in CFG_OLD[section].sections:
values = CFG_OLD[section][subsection]
if subsection not in CFG_NEW[section].sections:
CFG_NEW[section][subsection] = {}
for option, value in values.items():
config_new[section][subsection][option] = value
CFG_NEW[section][subsection][option] = value
else:
values = config_old[section]
if section not in config_new.sections:
config_new[section] = {}
values = CFG_OLD[section]
if section not in CFG_NEW.sections:
CFG_NEW[section] = {}
for option, value in values.items():
config_new[section][option] = value
CFG_NEW[section][option] = value
# convert old-style categories to new-style sub-sections
for section in config_old.keys():
for section in CFG_OLD.keys():
subsection = None
if section in list(chain.from_iterable(subsections.values())):
subsection = section
@ -237,24 +197,28 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
subsection = subsections[section]
process_section(section, subsection)
#[[v.remove(c) for c in v if c in subsection] for k,v in subsections.items() if k == section]
elif section in config_old.keys():
elif section in CFG_OLD.keys():
process_section(section, subsection)
# create a backup of our old config
if os.path.isfile(self.CONFIG_FILE):
cfgbak_name = self.CONFIG_FILE + ".old"
if os.path.isfile(nzbtomedia.CONFIG_FILE):
cfgbak_name = nzbtomedia.CONFIG_FILE + ".old"
if os.path.isfile(cfgbak_name): # remove older backups
os.unlink(cfgbak_name)
os.rename(self.CONFIG_FILE, cfgbak_name)
os.rename(nzbtomedia.CONFIG_FILE, cfgbak_name)
# writing our configuration file to 'autoProcessMedia.cfg'
with open(self.CONFIG_FILE, 'wb') as configFile:
config_new.write(configFile)
with open(nzbtomedia.CONFIG_FILE, 'wb') as configFile:
CFG_NEW.write(configFile)
# reload config
nzbtomedia.CFG = CFG_NEW
return True
def addnzbget(self):
config_new = config()
@staticmethod
def addnzbget():
CFG_NEW = nzbtomedia.CFG
section = "CouchPotato"
envCatKey = 'NZBPO_CPSCATEGORY'
envKeys = ['ENABLED', 'APIKEY', 'HOST', 'PORT', 'SSL', 'WEB_ROOT', 'DELAY', 'METHOD', 'DELETE_FAILED', 'REMOTECPS', 'WAIT_FOR', 'TIMEPERGIB']
@ -265,10 +229,10 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
if os.environ[envCatKey] not in config_new[section].sections:
config_new[section][os.environ[envCatKey]] = {}
config_new[section][os.environ[envCatKey]][option] = value
config_new[section][os.environ[envCatKey]]['enabled'] = 1
if os.environ[envCatKey] not in CFG_NEW[section].sections:
CFG_NEW[section][os.environ[envCatKey]] = {}
CFG_NEW[section][os.environ[envCatKey]][option] = value
CFG_NEW[section][os.environ[envCatKey]]['enabled'] = 1
section = "SickBeard"
envCatKey = 'NZBPO_SBCATEGORY'
@ -280,10 +244,10 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
if os.environ[envCatKey] not in config_new[section].sections:
config_new[section][os.environ[envCatKey]] = {}
config_new[section][os.environ[envCatKey]][option] = value
config_new[section][os.environ[envCatKey]]['enabled'] = 1
if os.environ[envCatKey] not in CFG_NEW[section].sections:
CFG_NEW[section][os.environ[envCatKey]] = {}
CFG_NEW[section][os.environ[envCatKey]][option] = value
CFG_NEW[section][os.environ[envCatKey]]['enabled'] = 1
section = "HeadPhones"
envCatKey = 'NZBPO_HPCATEGORY'
@ -295,10 +259,10 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
if os.environ[envCatKey] not in config_new[section].sections:
config_new[section][os.environ[envCatKey]] = {}
config_new[section][os.environ[envCatKey]][option] = value
config_new[section][os.environ[envCatKey]]['enabled'] = 1
if os.environ[envCatKey] not in CFG_NEW[section].sections:
CFG_NEW[section][os.environ[envCatKey]] = {}
CFG_NEW[section][os.environ[envCatKey]][option] = value
CFG_NEW[section][os.environ[envCatKey]]['enabled'] = 1
section = "Mylar"
envCatKey = 'NZBPO_MYCATEGORY'
@ -310,10 +274,10 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
if os.environ[envCatKey] not in config_new[section].sections:
config_new[section][os.environ[envCatKey]] = {}
config_new[section][os.environ[envCatKey]][option] = value
config_new[section][os.environ[envCatKey]]['enabled'] = 1
if os.environ[envCatKey] not in CFG_NEW[section].sections:
CFG_NEW[section][os.environ[envCatKey]] = {}
CFG_NEW[section][os.environ[envCatKey]][option] = value
CFG_NEW[section][os.environ[envCatKey]]['enabled'] = 1
section = "Gamez"
envCatKey = 'NZBPO_GZCATEGORY'
@ -325,10 +289,10 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
if os.environ[envCatKey] not in config_new[section].sections:
config_new[section][os.environ[envCatKey]] = {}
config_new[section][os.environ[envCatKey]][option] = value
config_new[section][os.environ[envCatKey]]['enabled'] = 1
if os.environ[envCatKey] not in CFG_NEW[section].sections:
CFG_NEW[section][os.environ[envCatKey]] = {}
CFG_NEW[section][os.environ[envCatKey]][option] = value
CFG_NEW[section][os.environ[envCatKey]]['enabled'] = 1
section = "NzbDrone"
envCatKey = 'NZBPO_NDCATEGORY'
@ -340,10 +304,10 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
if os.environ[envCatKey] not in config_new[section].sections:
config_new[section][os.environ[envCatKey]] = {}
config_new[section][os.environ[envCatKey]][option] = value
config_new[section][os.environ[envCatKey]]['enabled'] = 1
if os.environ[envCatKey] not in CFG_NEW[section].sections:
CFG_NEW[section][os.environ[envCatKey]] = {}
CFG_NEW[section][os.environ[envCatKey]][option] = value
CFG_NEW[section][os.environ[envCatKey]]['enabled'] = 1
section = "Extensions"
envKeys = ['COMPRESSEDEXTENSIONS', 'MEDIAEXTENSIONS', 'METAEXTENSIONS']
@ -353,7 +317,7 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
config_new[section][option] = value
CFG_NEW[section][option] = value
section = "Transcoder"
envKeys = ['TRANSCODE', 'DUPLICATE', 'IGNOREEXTENSIONS', 'OUTPUTVIDEOEXTENSION', 'OUTPUTVIDEOCODEC', 'OUTPUTVIDEOPRESET', 'OUTPUTVIDEOFRAMERATE', 'OUTPUTVIDEOBITRATE', 'OUTPUTAUDIOCODEC', 'OUTPUTAUDIOBITRATE', 'OUTPUTSUBTITLECODEC']
@ -363,7 +327,7 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
config_new[section][option] = value
CFG_NEW[section][option] = value
section = "WakeOnLan"
envKeys = ['WAKE', 'HOST', 'PORT', 'MAC']
@ -373,19 +337,22 @@ class ConfigObj(lib.configobj.ConfigObj, Section):
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
config_new[section][option] = value
CFG_NEW[section][option] = value
# create a backup of our old config
if os.path.isfile(self.CONFIG_FILE):
cfgbak_name = self.CONFIG_FILE + ".old"
if os.path.isfile(nzbtomedia.CONFIG_FILE):
cfgbak_name = nzbtomedia.CONFIG_FILE + ".old"
if os.path.isfile(cfgbak_name): # remove older backups
os.unlink(cfgbak_name)
os.rename(self.CONFIG_FILE, cfgbak_name)
os.rename(nzbtomedia.CONFIG_FILE, cfgbak_name)
# writing our configuration file to 'autoProcessMedia.cfg'
with open(self.CONFIG_FILE, 'wb') as configFile:
config_new.write(configFile)
with open(nzbtomedia.CONFIG_FILE, 'wb') as configFile:
CFG_NEW.write(configFile)
# reload config
nzbtomedia.CFG = CFG_NEW
lib.configobj.Section = Section
lib.configobj.ConfigObj = ConfigObj
config = ConfigObj

View file

@ -15,13 +15,13 @@ def process_exception(exception, name, dirname):
exception(filename, parentDir)
def process_qoq(filename, dirname):
Logger.debug("Reversing the file name for a QoQ release %s", filename)
logger.debug("Reversing the file name for a QoQ release %s", filename)
head, fileExtension = os.path.splitext(os.path.basename(filename))
newname = head[::-1]
newfile = newname + fileExtension
newfilePath = os.path.join(dirname, newfile)
os.rename(filename, newfilePath)
Logger.debug("New file name is %s", newfile)
logger.debug("New file name is %s", newfile)
# dict for custom groups
# we can add more to this list

View file

@ -5,14 +5,10 @@ import struct
import shutil
import sys
import time
import logging
import logging.config
import logging.handlers
import nzbtomedia
from nzbtomedia.linktastic import linktastic
from nzbtomedia.nzbToMediaConfig import config
Logger = logging.getLogger()
from nzbtomedia import logger
def getDirectorySize(directory):
dir_size = 0
@ -28,28 +24,24 @@ def safeName(name):
safename = re.sub(r"[\/\\\:\*\?\"\<\>\|]", "", name) #make this name safe for use in directories for windows etc.
return safename
def nzbtomedia_configure_logging(logfile=None):
if not logfile:
logfile = config.LOG_FILE
logging.config.fileConfig(config.LOG_CONFIG)
fileHandler = logging.handlers.RotatingFileHandler(logfile, mode='a', maxBytes=1048576, backupCount=1, encoding='utf-8', delay=True)
fileHandler.formatter = logging.Formatter('%(asctime)s|%(levelname)-7.7s %(message)s', '%H:%M:%S')
fileHandler.level = logging.DEBUG
logging.getLogger().addHandler(fileHandler)
def create_destination(outputDestination):
if os.path.exists(outputDestination):
return
try:
Logger.info("CREATE DESTINATION: Creating destination folder: %s", outputDestination)
logger.info("CREATE DESTINATION: Creating destination folder: %s", outputDestination)
os.makedirs(outputDestination)
except:
Logger.exception("CREATE DESTINATION: Not possible to create destination folder. Exiting")
logger.error("CREATE DESTINATION: Not possible to create destination folder. Exiting")
sys.exit(-1)
def makeDir(path):
if not os.path.isdir(path):
try:
os.makedirs( path)
except OSError:
return False
return True
def category_search(inputDirectory, inputName, inputCategory, root, categories):
single = False
tordir = False
@ -61,10 +53,10 @@ def category_search(inputDirectory, inputName, inputCategory, root, categories):
try:
inputCategory = list(set(pathlist) & set(categories))[-1] # assume last match is most relevant category.
Logger.debug("SEARCH: Found Category: %s in directory structure", inputCategory)
logger.debug("SEARCH: Found Category: %s in directory structure", inputCategory)
except IndexError:
inputCategory = ""
Logger.debug("SEARCH: Could not find a category in the directory structure")
logger.debug("SEARCH: Could not find a category in the directory structure")
if not os.path.isdir(inputDirectory) and os.path.isfile(inputDirectory): # If the input directory is a file
single = True
@ -72,18 +64,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)
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)
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)
logger.info("SEARCH: Setting inputDirectory to %s", inputDirectory)
tordir = True
imdbid = [item for item in pathlist if '.cp(tt' in item] # This looks for the .cp(tt imdb id in the path.
@ -96,14 +88,14 @@ 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])
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
if inputName and not tordir:
if inputName in pathlist or safeName(inputName) in pathlist:
Logger.info("SEARCH: Found torrent directory %s in the directory structure", inputName)
logger.info("SEARCH: Found torrent directory %s in the directory structure", inputName)
tordir = True
else:
root = 1
@ -111,8 +103,8 @@ def category_search(inputDirectory, inputName, inputCategory, root, categories):
root = 2
if root > 0:
Logger.info("SEARCH: Could not find a unique directory for this download. Assume a common directory.")
Logger.info("SEARCH: We will try and determine which files to process, individually")
logger.info("SEARCH: Could not find a unique directory for this download. Assume a common directory.")
logger.info("SEARCH: We will try and determine which files to process, individually")
return inputDirectory, inputName, inputCategory, root, single
@ -132,47 +124,47 @@ def is_sample(filePath, inputName, minSampleSize, SampleIDs):
def copy_link(filePath, targetDirectory, useLink, outputDestination):
if os.path.isfile(targetDirectory):
Logger.info("COPYLINK: target file already exists. Nothing to be done")
logger.info("COPYLINK: target file already exists. Nothing to be done")
return True
create_destination(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.exception("COPYLINK")
logger.error("COPYLINK")
if os.path.isfile(targetDirectory):
Logger.warn("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.warn("COPYLINK: Something went wrong in linktastic.link, copying instead")
Logger.debug("COPYLINK: Copying %s to %s", filePath, targetDirectory)
logger.warning("COPYLINK: Something went wrong in linktastic.link, copying instead")
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.exception("COPYLINK")
logger.error("COPYLINK")
if os.path.isfile(targetDirectory):
Logger.warn("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.info("COPYLINK: Something went wrong in linktastic.link, copying instead")
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)
logger.info("FLATTEN: Flattening directory: %s", outputDestination)
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
@ -182,12 +174,12 @@ def flatten(outputDestination):
try:
shutil.move(source, target)
except:
Logger.exception("FLATTEN: Could not flatten %s", source)
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)
logger.info("REMOVER: Removing empty folders in: %s", path)
if not os.path.isdir(path):
return
@ -202,7 +194,7 @@ def removeEmptyFolders(path):
# If folder empty, delete it
files = os.listdir(path)
if len(files) == 0:
Logger.debug("REMOVER: Removing empty folder: %s", path)
logger.debug("REMOVER: Removing empty folder: %s", path)
os.rmdir(path)
def iterate_media_files(dirname):
@ -248,49 +240,49 @@ def TestCon(host, port):
return "Down"
def WakeUp():
if not config():
Logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
if not nzbtomedia.CFG:
logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
return
wake = int(config()["WakeOnLan"]["wake"])
wake = int(nzbtomedia.CFG["WakeOnLan"]["wake"])
if wake == 0: # just return if we don't need to wake anything.
return
Logger.info("Loading WakeOnLan config from %s", config.CONFIG_FILE)
host = config()["WakeOnLan"]["host"]
port = int(config()["WakeOnLan"]["port"])
mac = config()["WakeOnLan"]["mac"]
logger.info(("Loading WakeOnLan config from %s", nzbtomedia.CONFIG_FILE))
host = nzbtomedia.CFG["WakeOnLan"]["host"]
port = int(nzbtomedia.CFG["WakeOnLan"]["port"])
mac = nzbtomedia.CFG["WakeOnLan"]["mac"]
i=1
while TestCon(host, port) == "Down" and i < 4:
Logger.info("Sending WakeOnLan Magic Packet for mac: %s", mac)
logger.info(("Sending WakeOnLan Magic Packet for mac: %s", mac))
WakeOnLan(mac)
time.sleep(20)
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)
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)
logger.info("System with mac: %s has been woken. Continuing with the rest of the script.", mac)
def convert_to_ascii(nzbName, dirName):
if not config():
Logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
if not nzbtomedia.CFG:
logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
return nzbName, dirName
ascii_convert = int(config()["ASCII"]["convert"])
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!.
return 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
@ -380,21 +372,21 @@ def get_dirnames(section, subsections=None):
dirNames = []
if subsections is None:
subsections = config.get_subsections(section).values()
subsections = nzbtomedia.get_subsections(section).values()
if not isinstance(subsections, list):
subsections = [subsections]
for subsection in subsections:
try:
watch_dir = config()[section][subsection]["watch_dir"]
watch_dir = nzbtomedia.CFG[section][subsection]["watch_dir"]
if not os.path.exists(watch_dir):
watch_dir = None
except:
watch_dir = None
try:
outputDirectory = os.path.join(config()["Torrent"]["outputDirectory"], subsection)
outputDirectory = os.path.join(nzbtomedia.CFG["Torrent"]["outputDirectory"], subsection)
if not os.path.exists(outputDirectory):
outputDirectory = None
except:
@ -404,22 +396,22 @@ def get_dirnames(section, subsections=None):
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 not dirNames:
Logger.warn("%s:%s has no directories identified to scan inside %s", section, subsection, watch_dir)
logger.warning("%s:%s has no directories identified to scan inside %s", section, subsection, watch_dir)
if outputDirectory:
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("%s:%s has no directories identified to scan inside %s", section, subsection, outputDirectory)
logger.warning("%s:%s has no directories identified to scan inside %s", section, subsection, outputDirectory)
if watch_dir is None and outputDirectory is None:
Logger.warn("%s:%s has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.", section, subsection)
logger.warning("%s:%s has no watch_dir or outputDirectory setup to be Scanned, go fix you autoProcessMedia.cfg file.", section, subsection)
return dirNames
def delete(dirName):
Logger.info("Deleting failed files and folder %s", dirName)
logger.info("Deleting failed files and folder %s", dirName)
try:
shutil.rmtree(dirName, True)
except:
Logger.exception("Unable to delete folder %s", dirName)
logger.error("Unable to delete folder %s", dirName)

243
nzbtomedia/versionCheck.py Normal file
View file

@ -0,0 +1,243 @@
import os
import shutil
import urllib
import tarfile
import stat
import traceback
import gh_api as github
import nzbtomedia
from nzbtomedia import logger
class CheckVersion():
"""
Version check class meant to run as a thread object with the SB scheduler.
"""
def __init__(self):
self.updater = SourceUpdateManager()
def run(self):
self.check_for_new_version()
def check_for_new_version(self, force=False):
"""
Checks the internet for a newer version.
returns: bool, True for new version or False for no new version.
force: if true the VERSION_NOTIFY setting will be ignored and a check will be forced
"""
logger.info("Checking if nzbToMedia needs an update")
if not self.updater.need_update():
NEWEST_VERSION_STRING = None
logger.info("No update needed")
if force:
logger.info("No update needed")
return False
if not self.updater._cur_commit_hash:
logger.info("Unknown current version number, don't know if we should update or not")
elif self.updater._num_commits_behind > 0:
logger.info("There is a newer version available, (you're " + str(self.updater._num_commits_behind) + " commit(s) behind")
return True
def update(self):
if self.updater.need_update():
return self.updater.update()
class UpdateManager():
def get_github_repo_user(self):
return 'clinton-hall'
def get_github_repo(self):
return 'nzbToMedia'
# def get_update_url(self):
# return nzbtomedia.WEB_ROOT + "/home/update/?pid=" + str(nzbtomedia.PID)
class SourceUpdateManager(UpdateManager):
def __init__(self):
self.github_repo_user = self.get_github_repo_user()
self.github_repo = self.get_github_repo()
self.branch = 'master'
self._cur_commit_hash = None
self._newest_commit_hash = None
self._num_commits_behind = 0
def _find_installed_version(self):
version_file = os.path.join(nzbtomedia.PROGRAM_DIR, u'version.txt')
if not os.path.isfile(version_file):
self._cur_commit_hash = None
return
try:
with open(version_file, 'r') as fp:
self._cur_commit_hash = fp.read().strip(' \n\r')
except EnvironmentError, e:
logger.debug("Unable to open 'version.txt': " + str(e))
if not self._cur_commit_hash:
self._cur_commit_hash = None
def need_update(self):
self._find_installed_version()
try:
self._check_github_for_update()
except Exception, e:
logger.error("Unable to contact github, can't check for update: " + repr(e))
return False
if not self._cur_commit_hash or self._num_commits_behind > 0:
return True
return False
def _check_github_for_update(self):
"""
Uses pygithub to ask github if there is a newer version that the provided
commit hash. If there is a newer version it sets Sick Beard's version text.
commit_hash: hash that we're checking against
"""
self._num_commits_behind = 0
self._newest_commit_hash = None
gh = github.GitHub(self.github_repo_user, self.github_repo, self.branch)
# try to get newest commit hash and commits behind directly by comparing branch and current commit
if self._cur_commit_hash:
branch_compared = gh.compare(base=self.branch, head=self._cur_commit_hash)
if 'base_commit' in branch_compared:
self._newest_commit_hash = branch_compared['base_commit']['sha']
if 'behind_by' in branch_compared:
self._num_commits_behind = int(branch_compared['behind_by'])
# fall back and iterate over last 100 (items per page in gh_api) commits
if not self._newest_commit_hash:
for curCommit in gh.commits():
if not self._newest_commit_hash:
self._newest_commit_hash = curCommit['sha']
if not self._cur_commit_hash:
break
if curCommit['sha'] == self._cur_commit_hash:
break
# when _cur_commit_hash doesn't match anything _num_commits_behind == 100
self._num_commits_behind += 1
logger.debug("cur_commit = " + str(self._cur_commit_hash) + ", newest_commit = " + str(self._newest_commit_hash)
+ ", num_commits_behind = " + str(self._num_commits_behind))
def set_newest_text(self):
# if we're up to date then don't set this
nzbtomedia.NEWEST_VERSION_STRING = None
if not self._cur_commit_hash:
logger.info("Unknown current version number, don't know if we should update or not")
elif self._num_commits_behind > 0:
logger.info("There is a newer version available, (you're " + str(self._num_commits_behind) + " commit(s) behind")
def update(self):
"""
Downloads the latest source tarball from github and installs it over the existing version.
"""
base_url = 'https://github.com/' + self.github_repo_user + '/' + self.github_repo
tar_download_url = base_url + '/tarball/' + self.branch
version_path = os.path.join(nzbtomedia.PROGRAM_DIR, u'version.txt')
try:
# prepare the update dir
sb_update_dir = os.path.join(nzbtomedia.PROGRAM_DIR, u'sb-update')
if os.path.isdir(sb_update_dir):
logger.info("Clearing out update folder " + sb_update_dir + " before extracting")
shutil.rmtree(sb_update_dir)
logger.info("Creating update folder " + sb_update_dir + " before extracting")
os.makedirs(sb_update_dir)
# retrieve file
logger.info("Downloading update from " + repr(tar_download_url))
tar_download_path = os.path.join(sb_update_dir, u'sb-update.tar')
urllib.urlretrieve(tar_download_url, tar_download_path)
if not str(os.path.isfile, tar_download_path):
logger.error("Unable to retrieve new version from " + tar_download_url + ", can't update")
return False
if not str(tarfile.is_tarfile, tar_download_path):
logger.error("Retrieved version from " + tar_download_url + " is corrupt, can't update")
return False
# extract to sb-update dir
logger.info("Extracting file " + tar_download_path)
tar = tarfile.open(tar_download_path)
tar.extractall(sb_update_dir)
tar.close()
# delete .tar.gz
logger.info("Deleting file " + tar_download_path)
os.remove(tar_download_path)
# find update dir name
update_dir_contents = [x for x in os.listdir(sb_update_dir) if
os.path.isdir(os.path.join(sb_update_dir, x))]
if len(update_dir_contents) != 1:
logger.error("Invalid update data, update failed: " + str(update_dir_contents))
return False
content_dir = os.path.join(sb_update_dir, update_dir_contents[0])
# walk temp folder and move files to main folder
logger.info("Moving files from " + content_dir + " to " + nzbtomedia.PROGRAM_DIR)
for dirname, dirnames, filenames in os.walk(content_dir): # @UnusedVariable
dirname = dirname[len(content_dir) + 1:]
for curfile in filenames:
old_path = os.path.join(content_dir, dirname, curfile)
new_path = os.path.join(nzbtomedia.PROGRAM_DIR, dirname, curfile)
#Avoid DLL access problem on WIN32/64
#These files needing to be updated manually
#or find a way to kill the access from memory
if curfile in ('unrar.dll', 'unrar64.dll'):
try:
os.chmod(new_path, stat.S_IWRITE)
os.remove(new_path)
os.renames(old_path, new_path)
except Exception, e:
logger.debug("Unable to update " + new_path + ': ' + str(e))
os.remove(old_path) # Trash the updated file without moving in new path
continue
if os.path.isfile(new_path):
os.remove(new_path)
os.renames(old_path, new_path)
# update version.txt with commit hash
try:
with open(version_path, 'w') as ver_file:
ver_file.write(self._newest_commit_hash)
except EnvironmentError, e:
logger.error("Unable to write version file, update not complete: " + str(e))
return False
except Exception, e:
logger.error("Error while trying to update: " + str(e))
logger.debug("Traceback: " + traceback.format_exc())
return False
return True

View file

@ -1,21 +1,28 @@
from nzbtomedia.nzbToMediaConfig import config
import nzbtomedia
from nzbtomedia.versionCheck import CheckVersion
from nzbtomedia import logger
print config().findsection('tv').isenabled()
# Initialize the config
nzbtomedia.initialize()
test = CheckVersion().check_for_new_version()
print nzbtomedia.CFG.findsection('tv')
print
print config().sections
print nzbtomedia.CFG.sections
print
sections = ("CouchPotato", "SickBeard", "NzbDrone", "HeadPhones", "Mylar", "Gamez")
print config()[sections].subsections
print config()['SickBeard'].subsections
print nzbtomedia.CFG[sections].subsections
print nzbtomedia.CFG['SickBeard'].subsections
print
print config()[sections].sections
print config()['SickBeard'].sections
print nzbtomedia.CFG[sections].sections
print nzbtomedia.CFG['SickBeard'].sections
print
print config()['SickBeard','NzbDrone']
print config()['SickBeard']
print nzbtomedia.CFG['SickBeard','NzbDrone']
print nzbtomedia.CFG['SickBeard']
print
print config()['SickBeard','NzbDrone','CouchPotato'].issubsection('tv', True)
print config()['SickBeard'].issubsection('tv', True)
print nzbtomedia.CFG['SickBeard','NzbDrone','CouchPotato'].issubsection('tv', True)
print nzbtomedia.CFG['SickBeard'].issubsection('tv', True)
print
print config()['SickBeard','NzbDrone'].isenabled('tv')
print config()['SickBeard'].isenabled('tv')
print nzbtomedia.CFG['SickBeard','NzbDrone'].isenabled('tv')
print nzbtomedia.CFG['SickBeard'].isenabled('tv')