Major overhaul of nzbToMedia code base plus a whole restrucure

This commit is contained in:
echel0n 2014-04-03 03:04:04 -07:00
parent e7751b96c5
commit 85d8739512
67 changed files with 1687 additions and 1734 deletions

19
DeleteSamples.py Executable file → Normal file
View file

@ -29,9 +29,9 @@
### NZBGET POST-PROCESSING SCRIPT ### ### NZBGET POST-PROCESSING SCRIPT ###
############################################################################## ##############################################################################
import os import os
import sys import sys
from nzbtomedia.nzbToMediaConfig import config
def is_sample(filePath, inputName, maxSampleSize, SampleIDs): def is_sample(filePath, inputName, maxSampleSize, SampleIDs):
@ -53,25 +53,18 @@ def is_sample(filePath, inputName, maxSampleSize, SampleIDs):
if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5] < '11.0': if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5] < '11.0':
print "Script triggered from NZBGet (11.0 or later)." print "Script triggered from NZBGet (11.0 or later)."
# NZBGet argv: all passed as environment variables.
# Exit codes used by NZBGet
POSTPROCESS_PARCHECK=92
POSTPROCESS_SUCCESS=93
POSTPROCESS_ERROR=94
POSTPROCESS_NONE=95
# Check nzbget.conf options # Check nzbget.conf options
status = 0 status = 0
if os.environ['NZBOP_UNPACK'] != 'yes': if os.environ['NZBOP_UNPACK'] != 'yes':
print "Please enable option \"Unpack\" in nzbget configuration file, exiting." print "Please enable option \"Unpack\" in nzbget configuration file, exiting."
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)
# Check par status # Check par status
if os.environ['NZBPP_PARSTATUS'] == '3': if os.environ['NZBPP_PARSTATUS'] == '3':
print "Par-check successful, but Par-repair disabled, exiting." print "Par-check successful, but Par-repair disabled, exiting."
print "Please check your Par-repair settings for future downloads." print "Please check your Par-repair settings for future downloads."
sys.exit(POSTPROCESS_NONE) sys.exit(config.NZBGET_POSTPROCESS_NONE)
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4': if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4':
print "Par-repair failed, setting status \"failed\"." print "Par-repair failed, setting status \"failed\"."
@ -102,7 +95,7 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
# All checks done, now launching the script. # All checks done, now launching the script.
if status == 1: if status == 1:
sys.exit(POSTPROCESS_NONE) sys.exit(config.NZBGET_POSTPROCESS_NONE)
mediaContainer = os.environ['NZBPO_MEDIAEXTENSIONS'].split(',') mediaContainer = os.environ['NZBPO_MEDIAEXTENSIONS'].split(',')
SampleIDs = os.environ['NZBPO_SAMPLEIDS'].split(',') SampleIDs = os.environ['NZBPO_SAMPLEIDS'].split(',')
@ -119,8 +112,8 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
os.unlink(filePath) os.unlink(filePath)
except: except:
print "Error: unable to delete file", filePath print "Error: unable to delete file", filePath
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)
sys.exit(POSTPROCESS_SUCCESS) sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
else: else:
print "This script can only be called from NZBGet (11.0 or later)." print "This script can only be called from NZBGet (11.0 or later)."

24
ResetDateTime.py Executable file → Normal file
View file

@ -13,33 +13,27 @@
### NZBGET POST-PROCESSING SCRIPT ### ### NZBGET POST-PROCESSING SCRIPT ###
############################################################################## ##############################################################################
import os
import sys
# NZBGet V11+ # NZBGet V11+
# Check if the script is called from nzbget 11.0 or later # Check if the script is called from nzbget 11.0 or later
import os
import sys
from nzbtomedia.nzbToMediaConfig import config
if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5] < '11.0': if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5] < '11.0':
print "Script triggered from NZBGet (11.0 or later)." print "Script triggered from NZBGet (11.0 or later)."
# NZBGet argv: all passed as environment variables.
# Exit codes used by NZBGet
POSTPROCESS_PARCHECK=92
POSTPROCESS_SUCCESS=93
POSTPROCESS_ERROR=94
POSTPROCESS_NONE=95
# Check nzbget.conf options # Check nzbget.conf options
status = 0 status = 0
if os.environ['NZBOP_UNPACK'] != 'yes': if os.environ['NZBOP_UNPACK'] != 'yes':
print "Please enable option \"Unpack\" in nzbget configuration file, exiting." print "Please enable option \"Unpack\" in nzbget configuration file, exiting."
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)
# Check par status # Check par status
if os.environ['NZBPP_PARSTATUS'] == '3': if os.environ['NZBPP_PARSTATUS'] == '3':
print "Par-check successful, but Par-repair disabled, exiting." print "Par-check successful, but Par-repair disabled, exiting."
print "Please check your Par-repair settings for future downloads." print "Please check your Par-repair settings for future downloads."
sys.exit(POSTPROCESS_NONE) sys.exit(config.NZBGET_POSTPROCESS_NONE)
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4': if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4':
print "Par-repair failed, setting status \"failed\"." print "Par-repair failed, setting status \"failed\"."
@ -70,7 +64,7 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
# All checks done, now launching the script. # All checks done, now launching the script.
if status == 1: if status == 1:
sys.exit(POSTPROCESS_NONE) sys.exit(config.NZBGET_POSTPROCESS_NONE)
directory = os.path.normpath(os.environ['NZBPP_DIRECTORY']) directory = os.path.normpath(os.environ['NZBPP_DIRECTORY'])
for dirpath, dirnames, filenames in os.walk(directory): for dirpath, dirnames, filenames in os.walk(directory):
@ -82,8 +76,8 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
continue continue
except: except:
print "Error: unable to reset time for file", file print "Error: unable to reset time for file", file
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)
sys.exit(POSTPROCESS_SUCCESS) sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
else: else:
print "This script can only be called from NZBGet (11.0 or later)." print "This script can only be called from NZBGet (11.0 or later)."

View file

@ -1,24 +1,25 @@
#!/usr/bin/env python #!/usr/bin/env python
#System imports
import logging
import datetime import datetime
import logging
import os
import re
import sys
import shutil
from subprocess import Popen from subprocess import Popen
from nzbtomedia.autoProcess.autoProcessComics import autoProcessComics
# Custom imports from nzbtomedia.autoProcess.autoProcessGames import autoProcessGames
import autoProcess.migratecfg as migratecfg from nzbtomedia.autoProcess.autoProcessMovie import autoProcessMovie
import extractor.extractor as extractor from nzbtomedia.autoProcess.autoProcessMusic import autoProcessMusic
import autoProcess.autoProcessComics as autoProcessComics from nzbtomedia.autoProcess.autoProcessTV import autoProcessTV
import autoProcess.autoProcessGames as autoProcessGames from nzbtomedia.extractor import extractor
import autoProcess.autoProcessMusic as autoProcessMusic from nzbtomedia.migratecfg import migratecfg
import autoProcess.autoProcessMovie as autoProcessMovie from nzbtomedia.nzbToMediaAutoFork import autoFork
import autoProcess.autoProcessTV as autoProcessTV from nzbtomedia.nzbToMediaConfig import config
from autoProcess.nzbToMediaEnv import * from nzbtomedia.nzbToMediaUtil import category_search, safeName, is_sample, copy_link, WakeUp, parse_args, flatten, \
from autoProcess.nzbToMediaUtil import * nzbtomedia_configure_logging
from autoProcess.autoSickBeardFork import autoFork from nzbtomedia.synchronousdeluge.client import DelugeClient
from utorrent.client import UTorrentClient from nzbtomedia.utorrent.client import UTorrentClient
from transmissionrpc.client import Client as TransmissionClient from nzbtomedia.transmissionrpc.client import Client as TransmissionClient
from synchronousdeluge.client import DelugeClient
def main(inputDirectory, inputName, inputCategory, inputHash, inputID): def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
@ -31,6 +32,14 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
extractionSuccess = False extractionSuccess = False
copy_list = [] copy_list = []
useLink = useLink_in useLink = useLink_in
file = None
delugeClient = ""
utorrentClass = ""
TransmissionClass = ""
# init autoFork
fork, fork_params = autoFork(inputCategory)
Logger.debug("MAIN: Received Directory: %s | Name: %s | Category: %s", inputDirectory, inputName, inputCategory) Logger.debug("MAIN: Received Directory: %s | Name: %s | Category: %s", inputDirectory, inputName, inputCategory)
@ -38,12 +47,11 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
Logger.debug("MAIN: Determined Directory: %s | Name: %s | Category: %s", inputDirectory, inputName, inputCategory) Logger.debug("MAIN: Determined Directory: %s | Name: %s | Category: %s", inputDirectory, inputName, inputCategory)
sbFork, sbParams = autoFork() if inputCategory in sbCategory:
if fork in config.SICKBEARD_TORRENT and Torrent_ForceLink != 1:
if inputCategory in sbCategory and sbFork in SICKBEARD_TORRENT and Torrent_ForceLink != 1: Logger.info("MAIN: Calling SickBeard's %s branch to post-process: %s",fork ,inputName)
Logger.info("MAIN: Calling SickBeard's %s branch to post-process: %s",sbFork ,inputName) result = autoProcessTV().processEpisode(inputDirectory, inputName, 0)
result = autoProcessTV.processEpisode(inputDirectory, inputName, int(0)) if result != 0:
if result == 1:
Logger.info("MAIN: A problem was reported in the autoProcess* script.") Logger.info("MAIN: A problem was reported in the autoProcess* script.")
Logger.info("MAIN: All done.") Logger.info("MAIN: All done.")
sys.exit() sys.exit()
@ -91,14 +99,14 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
utorrentClass = UTorrentClient(uTorrentWEBui, uTorrentUSR, uTorrentPWD) utorrentClass = UTorrentClient(uTorrentWEBui, uTorrentUSR, uTorrentPWD)
except: except:
Logger.exception("MAIN: Failed to connect to uTorrent") Logger.exception("MAIN: Failed to connect to uTorrent")
utorrentClass = ""
if clientAgent == 'transmission': if clientAgent == 'transmission':
try: try:
Logger.debug("MAIN: Connecting to %s: http://%s:%s", clientAgent, TransmissionHost, TransmissionPort) Logger.debug("MAIN: Connecting to %s: http://%s:%s", clientAgent, TransmissionHost, TransmissionPort)
TransmissionClass = TransmissionClient(TransmissionHost, TransmissionPort, TransmissionUSR, TransmissionPWD) TransmissionClass = TransmissionClient(TransmissionHost, TransmissionPort, TransmissionUSR, TransmissionPWD)
except: except:
Logger.exception("MAIN: Failed to connect to Transmission") Logger.exception("MAIN: Failed to connect to Transmission")
TransmissionClass = ""
if clientAgent == 'deluge': if clientAgent == 'deluge':
try: try:
Logger.debug("MAIN: Connecting to %s: http://%s:%s", clientAgent, DelugeHost, DelugePort) Logger.debug("MAIN: Connecting to %s: http://%s:%s", clientAgent, DelugeHost, DelugePort)
@ -106,7 +114,6 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
delugeClient.connect(host = DelugeHost, port = DelugePort, username = DelugeUSR, password = DelugePWD) delugeClient.connect(host = DelugeHost, port = DelugePort, username = DelugeUSR, password = DelugePWD)
except: except:
Logger.exception("MAIN: Failed to connect to deluge") Logger.exception("MAIN: Failed to connect to deluge")
delugeClient = ""
# if we are using links with uTorrent it means we need to pause it in order to access the files # if we are using links with uTorrent 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("MAIN: Stoping torrent %s in %s while processing", inputName, clientAgent)
@ -116,7 +123,7 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
TransmissionClass.stop_torrent(inputID) TransmissionClass.stop_torrent(inputID)
if clientAgent == 'deluge' and delugeClient != "": if clientAgent == 'deluge' and delugeClient != "":
delugeClient.core.pause_torrent([inputID]) delugeClient.core.pause_torrent([inputID])
time.sleep(5) # Give Torrent client some time to catch up with the change datetime.time.sleep(5) # Give Torrent client some time to catch up with the change
Logger.debug("MAIN: Scanning files in directory: %s", inputDirectory) Logger.debug("MAIN: Scanning files in directory: %s", inputDirectory)
@ -125,7 +132,7 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
if useLink in ['sym','move']: # These don't work for HeadPhones. if useLink in ['sym','move']: # These don't work for HeadPhones.
useLink = 'no' # default to copy. useLink = 'no' # default to copy.
if inputCategory in sbCategory and sbFork in SICKBEARD_TORRENT: # Don't flatten when sending to SICKBEARD_TORRENT if inputCategory in sbCategory and fork in config.SICKBEARD_TORRENT: # Don't flatten when sending to SICKBEARD_TORRENT
noFlatten.extend(sbCategory) noFlatten.extend(sbCategory)
outputDestinationMaster = outputDestination # Save the original, so we can change this within the loop below, and reset afterwards. outputDestinationMaster = outputDestination # Save the original, so we can change this within the loop below, and reset afterwards.
@ -167,7 +174,7 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
else: else:
continue # This file has not been recently moved or created, skip it continue # This file has not been recently moved or created, skip it
if inputCategory in sbCategory and sbFork in SICKBEARD_TORRENT: # We want to link every file. if inputCategory in sbCategory and fork in config.SICKBEARD_TORRENT: # We want to link every file.
Logger.info("MAIN: Found file %s in %s", fileExtension, filePath) Logger.info("MAIN: Found file %s in %s", fileExtension, filePath)
try: try:
copy_link(filePath, targetDirectory, useLink, outputDestination) copy_link(filePath, targetDirectory, useLink, outputDestination)
@ -237,7 +244,7 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
flatten(outputDestination) flatten(outputDestination)
# Now check if movie files exist in destination: # Now check if movie files exist in destination:
if inputCategory in cpsCategory + sbCategory and not (inputCategory in sbCategory and sbFork in SICKBEARD_TORRENT): if inputCategory in cpsCategory + sbCategory and not (inputCategory in sbCategory and fork in config.SICKBEARD_TORRENT):
for dirpath, dirnames, filenames in os.walk(outputDestination): for dirpath, dirnames, filenames in os.walk(outputDestination):
for file in filenames: for file in filenames:
filePath = os.path.join(dirpath, file) filePath = os.path.join(dirpath, file)
@ -257,7 +264,7 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
else: else:
Logger.debug("MAIN: Found %s media files in output. %s were found in input", str(video2), str(video)) Logger.debug("MAIN: Found %s media files in output. %s were found in input", str(video2), str(video))
if inputCategory in sbCategory and sbFork in SICKBEARD_TORRENT: if inputCategory in sbCategory and fork in config.SICKBEARD_TORRENT:
if len(copy_list) > 0: if len(copy_list) > 0:
Logger.debug("MAIN: Found and linked %s files", str(len(copy_list))) Logger.debug("MAIN: Found and linked %s files", str(len(copy_list)))
status = int(0) status = int(0)
@ -274,22 +281,23 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
Logger.error("MAIN: Something failed! Please check logs. Exiting") Logger.error("MAIN: Something failed! Please check logs. Exiting")
sys.exit(-1) sys.exit(-1)
result = 0
if inputCategory in cpsCategory: if inputCategory in cpsCategory:
Logger.info("MAIN: Calling CouchPotatoServer to post-process: %s", inputName) Logger.info("MAIN: Calling CouchPotatoServer to post-process: %s", inputName)
download_id = inputHash download_id = inputHash
result = autoProcessMovie.process(outputDestination, inputName, status, clientAgent, download_id, inputCategory) result = autoProcessMovie().process(outputDestination, inputName, status, clientAgent, download_id, inputCategory)
elif inputCategory in sbCategory: elif inputCategory in sbCategory:
Logger.info("MAIN: Calling Sick-Beard to post-process: %s", inputName) Logger.info("MAIN: Calling Sick-Beard to post-process: %s", inputName)
result = autoProcessTV.processEpisode(outputDestination, inputName, status, clientAgent, inputCategory) result = autoProcessTV().processEpisode(outputDestination, inputName, status, clientAgent, inputCategory)
elif inputCategory in hpCategory: elif inputCategory in hpCategory:
Logger.info("MAIN: Calling HeadPhones to post-process: %s", inputName) Logger.info("MAIN: Calling HeadPhones to post-process: %s", inputName)
result = autoProcessMusic.process(inputDirectory, inputName, status, inputCategory) result = autoProcessMusic().process(inputDirectory, inputName, status, clientAgent, inputCategory)
elif inputCategory in mlCategory: elif inputCategory in mlCategory:
Logger.info("MAIN: Calling Mylar to post-process: %s", inputName) Logger.info("MAIN: Calling Mylar to post-process: %s", inputName)
result = autoProcessComics.processEpisode(outputDestination, inputName, status, inputCategory) result = autoProcessComics().processEpisode(outputDestination, inputName, status, clientAgent, inputCategory)
elif inputCategory in gzCategory: elif inputCategory in gzCategory:
Logger.info("MAIN: Calling Gamez to post-process: %s", inputName) Logger.info("MAIN: Calling Gamez to post-process: %s", inputName)
result = autoProcessGames.process(outputDestination, inputName, status, inputCategory) result = autoProcessGames().process(outputDestination, inputName, status, clientAgent, inputCategory)
if result == 1: if result == 1:
Logger.info("MAIN: A problem was reported in the autoProcess* script. If torrent was paused we will resume seeding") Logger.info("MAIN: A problem was reported in the autoProcess* script. If torrent was paused we will resume seeding")
@ -334,7 +342,7 @@ def main(inputDirectory, inputName, inputCategory, inputHash, inputID):
TransmissionClass.start_torrent(inputID) TransmissionClass.start_torrent(inputID)
if clientAgent == 'deluge' and delugeClient != "": if clientAgent == 'deluge' and delugeClient != "":
delugeClient.core.resume_torrent([inputID]) delugeClient.core.resume_torrent([inputID])
time.sleep(5) datetime.time.sleep(5)
#cleanup #cleanup
if inputCategory in processCategories and result == 0 and os.path.isdir(outputDestination): if inputCategory in processCategories and result == 0 and os.path.isdir(outputDestination):
num_files_new = int(0) num_files_new = int(0)
@ -411,11 +419,10 @@ def external_script(outputDestination,torrentName,torrentLabel):
result = int(1) result = int(1)
final_result = final_result + result final_result = final_result + result
time.sleep(user_delay) datetime.time.sleep(user_delay)
num_files_new = int(0) num_files_new = int(0)
for dirpath, dirnames, filenames in os.walk(outputDestination): for dirpath, dirnames, filenames in os.walk(outputDestination):
for file in filenames: for file in filenames:
filePath = os.path.join(dirpath, file) filePath = os.path.join(dirpath, file)
fileName, fileExtension = os.path.splitext(file) fileName, fileExtension = os.path.splitext(file)
@ -430,26 +437,19 @@ def external_script(outputDestination,torrentName,torrentLabel):
return final_result return final_result
if __name__ == "__main__": if __name__ == "__main__":
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
#check to migrate old cfg before trying to load. if migratecfg().migrate():
if os.path.isfile(os.path.join(os.path.dirname(sys.argv[0]), "autoProcessMedia.cfg.sample")): nzbtomedia_configure_logging(config.LOG_FILE)
migratecfg.migrate()
# Logging
nzbtomedia_configure_logging(LOG_FILE)
Logger = logging.getLogger(__name__) Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log Logger.info("====================") # Seperate old from new log
Logger.info("TorrentToMedia %s", VERSION) Logger.info("TorrentToMedia %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
WakeUp() WakeUp()
if not config():
Logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
sys.exit(-1)
# CONFIG FILE
Logger.info("MAIN: Loading config from %s", CONFIG_FILE)
# EXAMPLE VALUES: # EXAMPLE VALUES:
clientAgent = config().get("Torrent", "clientAgent") # utorrent | deluge | transmission | rtorrent | other clientAgent = config().get("Torrent", "clientAgent") # utorrent | deluge | transmission | rtorrent | other
useLink_in = config().get("Torrent", "useLink") # no | hard | sym useLink_in = config().get("Torrent", "useLink") # no | hard | sym
@ -480,9 +480,10 @@ if __name__ == "__main__":
minSampleSize = int(config().get("Extensions", "minSampleSize")) # 200 (in MB) minSampleSize = int(config().get("Extensions", "minSampleSize")) # 200 (in MB)
SampleIDs = (config().get("Extensions", "SampleIDs")).split(',') # sample,-s. SampleIDs = (config().get("Extensions", "SampleIDs")).split(',') # sample,-s.
Torrent_ForceLink = int(config().get("SickBeard", "Torrent_ForceLink")) # 1
cpsCategory = (config().get("CouchPotato", "cpsCategory")).split(',') # movie cpsCategory = (config().get("CouchPotato", "cpsCategory")).split(',') # movie
sbCategory = (config().get("SickBeard", "sbCategory")).split(',') # tv sbCategory = (config().get("SickBeard", "sbCategory")).split(',') # tv
Torrent_ForceLink = int(config().get("SickBeard", "Torrent_ForceLink")) # 1
hpCategory = (config().get("HeadPhones", "hpCategory")).split(',') # music hpCategory = (config().get("HeadPhones", "hpCategory")).split(',') # music
mlCategory = (config().get("Mylar", "mlCategory")).split(',') # comics mlCategory = (config().get("Mylar", "mlCategory")).split(',') # comics
gzCategory = (config().get("Gamez", "gzCategory")).split(',') # games gzCategory = (config().get("Gamez", "gzCategory")).split(',') # games
@ -509,10 +510,10 @@ if __name__ == "__main__":
Logger.debug("arg %s is: %s", n, arg) Logger.debug("arg %s is: %s", n, arg)
n = n+1 n = n+1
try: if not len(sys.argv) > 1:
inputDirectory, inputName, inputCategory, inputHash, inputID = parse_args(clientAgent)
except:
Logger.exception("MAIN: There was a problem loading variables") Logger.exception("MAIN: There was a problem loading variables")
sys.exit(-1) sys.exit(-1)
# process torrent
inputDirectory, inputName, inputCategory, inputHash, inputID = parse_args(clientAgent)
main(inputDirectory, inputName, inputCategory, inputHash, inputID) main(inputDirectory, inputName, inputCategory, inputHash, inputID)

View file

@ -1,143 +0,0 @@
import sys
import logging
import errno
from subprocess import call
from nzbToMediaConfig import *
Logger = logging.getLogger()
def Transcode_directory(dirName):
if os.name == 'nt':
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)
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)
return 1 # failure
else:
ffmpeg = 'ffmpeg'
else:
ffmpeg = 'ffmpeg'
useNiceness = True
Logger.info("Loading config from %s", CONFIG_FILE)
if not config():
Logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
return 1 # failure
mediaContainer = (config().get("Extensions", "mediaExtensions")).split(',')
duplicate = int(config().get("Transcoder", "duplicate"))
ignoreExtensions = (config().get("Transcoder", "ignoreExtensions")).split(',')
outputVideoExtension = config().get("Transcoder", "outputVideoExtension").strip()
outputVideoCodec = config().get("Transcoder", "outputVideoCodec").strip()
outputVideoPreset = config().get("Transcoder", "outputVideoPreset").strip()
outputVideoFramerate = config().get("Transcoder", "outputVideoFramerate").strip()
outputVideoBitrate = config().get("Transcoder", "outputVideoBitrate").strip()
outputAudioCodec = config().get("Transcoder", "outputAudioCodec").strip()
outputAudioBitrate = config().get("Transcoder", "outputAudioBitrate").strip()
outputSubtitleCodec = config().get("Transcoder", "outputSubtitleCodec").strip()
outputFastStart = int(config().get("Transcoder", "outputFastStart"))
outputQualityPercent = int(config().get("Transcoder", "outputQualityPercent"))
if useNiceness:
niceness = int(config().get("Transcoder", "niceness"))
map(lambda ext: ext.strip(), mediaContainer)
map(lambda ext: ext.strip(), ignoreExtensions)
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:
filePath = os.path.join(dirpath, file)
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)
continue
if ext == outputVideoExtension: # we need to change the name to prevent overwriting itself.
outputVideoExtension = '-transcoded' + outputVideoExtension # adds '-transcoded.ext'
newfilePath = os.path.normpath(name + outputVideoExtension)
command = [ffmpeg, '-loglevel', 'warning', '-i', filePath, '-map', '0'] # -map 0 takes all input streams
if useNiceness:
command = ['nice', '-%d' % niceness] + command
if len(outputVideoCodec) > 0:
command.append('-c:v')
command.append(outputVideoCodec)
if outputVideoCodec == 'libx264' and outputVideoPreset:
command.append('-preset')
command.append(outputVideoPreset)
else:
command.append('-c:v')
command.append('copy')
if len(outputVideoFramerate) > 0:
command.append('-r')
command.append(str(outputVideoFramerate))
if len(outputVideoBitrate) > 0:
command.append('-b:v')
command.append(str(outputVideoBitrate))
if len(outputAudioCodec) > 0:
command.append('-c:a')
command.append(outputAudioCodec)
if outputAudioCodec == 'aac': # Allow users to use the experimental AAC codec that's built into recent versions of ffmpeg
command.append('-strict')
command.append('-2')
else:
command.append('-c:a')
command.append('copy')
if len(outputAudioBitrate) > 0:
command.append('-b:a')
command.append(str(outputAudioBitrate))
if outputFastStart > 0:
command.append('-movflags')
command.append('+faststart')
if outputQualityPercent > 0:
command.append('-q:a')
command.append(str(outputQualityPercent))
if len(outputSubtitleCodec) > 0: # Not every subtitle codec can be used for every video container format!
command.append('-c:s')
command.append(outputSubtitleCodec) # http://en.wikibooks.org/wiki/FFMPEG_An_Intermediate_Guide/subtitle_options
else:
command.append('-sn') # Don't copy the subtitles over
command.append(newfilePath)
try: # Try to remove the file that we're transcoding to just in case. (ffmpeg will return an error if it already exists for some reason)
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)
except Exception, e:
Logger.debug("Error when removing transcoding target: %s", e)
Logger.info("Transcoding video: %s", file)
cmd = ""
for item in command:
cmd = cmd + " " + item
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)
if result == 0:
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)
# 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

@ -1,96 +0,0 @@
import urllib
import logging
from nzbToMediaEnv import *
from nzbToMediaUtil import *
Logger = logging.getLogger()
socket.setdefaulttimeout(int(TimeOut)) #initialize socket timeout.
class AuthURLOpener(urllib.FancyURLopener):
def __init__(self, user, pw):
self.username = user
self.password = pw
self.numTries = 0
urllib.FancyURLopener.__init__(self)
def prompt_user_passwd(self, host, realm):
if self.numTries == 0:
self.numTries = 1
return (self.username, self.password)
else:
return ('', '')
def openit(self, url):
self.numTries = 0
return urllib.FancyURLopener.open(self, url)
def processEpisode(dirName, nzbName=None, status=0, inputCategory=None):
Logger.info("Loading config from %s", CONFIG_FILE)
if not config():
Logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
return 1 # failure
section = "Mylar"
if inputCategory != None and config().has_section(inputCategory):
section = inputCategory
host = config().get(section, "host")
port = config().get(section, "port")
username = config().get(section, "username")
password = config().get(section, "password")
try:
ssl = int(config().get(section, "ssl"))
except (config.NoOptionError, ValueError):
ssl = 0
try:
web_root = config().get(section, "web_root")
except config.NoOptionError:
web_root = ""
try:
watch_dir = config().get(section, "watch_dir")
except config.NoOptionError:
watch_dir = ""
params = {}
nzbName, dirName = convert_to_ascii(nzbName, dirName)
if dirName == "Manual Run" and watch_dir != "":
dirName = watch_dir
params['nzb_folder'] = dirName
if nzbName != None:
params['nzb_name'] = nzbName
myOpener = AuthURLOpener(username, password)
if ssl:
protocol = "https://"
else:
protocol = "http://"
url = protocol + host + ":" + port + web_root + "/post_process?" + urllib.urlencode(params)
Logger.debug("Opening URL: %s", url)
try:
urlObj = myOpener.openit(url)
except:
Logger.exception("Unable to open URL")
return 1 # failure
result = urlObj.readlines()
for line in result:
Logger.info("%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,75 +0,0 @@
import urllib
import json
import logging
from nzbToMediaEnv import *
from nzbToMediaUtil import *
Logger = logging.getLogger()
socket.setdefaulttimeout(int(TimeOut)) #initialize socket timeout.
def process(dirName, nzbName=None, status=0, inputCategory=None):
status = int(status)
Logger.info("Loading config from %s", CONFIG_FILE)
if not config():
Logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
return 1 # failure
section = "Gamez"
if inputCategory != None and config().has_section(inputCategory):
section = inputCategory
host = config().get(section, "host")
port = config().get(section, "port")
apikey = config().get(section, "apikey")
try:
ssl = int(config().get(section, "ssl"))
except (config.NoOptionError, ValueError):
ssl = 0
try:
web_root = config().get(section, "web_root")
except config.NoOptionError:
web_root = ""
if ssl:
protocol = "https://"
else:
protocol = "http://"
nzbName, dirName = convert_to_ascii(nzbName, dirName)
baseURL = protocol + host + ":" + port + web_root + "/api?api_key=" + apikey + "&mode="
fields = nzbName.split("-")
gamezID = fields[0].replace("[","").replace("]","").replace(" ","")
downloadStatus = 'Wanted'
if status == 0:
downloadStatus = 'Downloaded'
url = baseURL + "UPDATEREQUESTEDSTATUS&db_id=" + gamezID + "&status=" + downloadStatus
Logger.debug("Opening URL: %s", url)
try:
urlObj = urllib.urlopen(url)
except:
Logger.exception("Unable to open URL")
return 1 # failure
result = json.load(urlObj)
Logger.info("Gamez returned %s", result)
if result['success']:
Logger.info("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)
return 1 # failure

View file

@ -1,325 +0,0 @@
import urllib
import datetime
import json
import logging
import Transcoder
from nzbToMediaEnv import *
from nzbToMediaUtil import *
from nzbToMediaSceneExceptions import process_all_exceptions
Logger = logging.getLogger()
socket.setdefaulttimeout(int(TimeOut)) #initialize socket timeout.
def get_imdb(nzbName, dirName):
imdbid = ""
a = nzbName.find('.cp(') + 4 #search for .cptt( in nzbName
b = nzbName[a:].find(')') + a
if a > 3: # a == 3 if not exist
imdbid = nzbName[a:b]
if imdbid:
Logger.info("Found movie id %s in name", imdbid)
return imdbid
a = dirName.find('.cp(') + 4 #search for .cptt( in dirname
b = dirName[a:].find(')') + a
if a > 3: # a == 3 if not exist
imdbid = dirName[a:b]
if imdbid:
Logger.info("Found movie id %s in directory", imdbid)
return imdbid
else:
Logger.debug("Could not find an imdb id in directory or name")
return ""
def get_movie_info(baseURL, imdbid, download_id):
movie_id = ""
movie_status = None
release_status = None
if not imdbid and not download_id:
return movie_id, imdbid, download_id, movie_status, release_status
releaselist = []
movieid = []
moviestatus = []
library = []
release = []
offset = int(0)
while True:
url = baseURL + "media.list/?status=active&release_status=snatched&limit_offset=50," + str(offset)
Logger.debug("Opening URL: %s", url)
try:
urlObj = urllib.urlopen(url)
except:
Logger.exception("Unable to open URL")
break
movieid2 = []
library2 = []
release2 = []
moviestatus2 = []
try:
result = json.load(urlObj)
movieid2 = [item["_id"] for item in result["movies"]]
for item in result["movies"]:
if "identifier" in item:
library2.append(item["identifier"])
else:
library2.append(item["identifiers"]["imdb"])
release2 = [item["releases"] for item in result["movies"]]
moviestatus2 = [item["status"] for item in result["movies"]]
except:
Logger.exception("Unable to parse json data for movies")
break
movieid.extend(movieid2)
moviestatus.extend(moviestatus2)
library.extend(library2)
release.extend(release2)
if len(movieid2) < int(50): # finished parsing list of movies. Time to break.
break
offset = offset + 50
result = None # reset
for index in range(len(movieid)):
releaselist1 = [item for item in release[index] if item["status"] == "snatched" and "download_info" in item]
if download_id:
releaselist = [item for item in releaselist1 if item["download_info"]["id"].lower() == download_id.lower()]
else:
releaselist = releaselist1
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)
if not download_id and len(releaselist) == 1:
download_id = releaselist[0]["download_info"]["id"]
elif not imdbid and download_id and len(releaselist) > 0:
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)
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)
break
if not movie_id:
Logger.exception("Could not parse database results to determine imdbid or movie id")
return movie_id, imdbid, download_id, movie_status, release_status
def get_status(baseURL, movie_id, download_id):
result = None
movie_status = None
release_status = None
if not movie_id:
return movie_status, release_status
Logger.debug("Looking for status of movie: %s", movie_id)
url = baseURL + "media.get/?id=" + str(movie_id)
Logger.debug("Opening URL: %s", url)
try:
urlObj = urllib.urlopen(url)
except:
Logger.exception("Unable to open URL")
return None, None
try:
result = json.load(urlObj)
movie_status = str(result["media"]["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")
try:
if len(result["media"]["releases"]) == 1 and result["media"]["releases"][0]["status"] == "done":
release_status = result["media"]["releases"][0]["status"]
else:
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)
except: # index out of range/doesn't exist?
Logger.exception("Could not find a status for this release")
return movie_status, release_status
def process(dirName, nzbName=None, status=0, clientAgent = "manual", download_id = "", inputCategory=None):
status = int(status)
Logger.info("Loading config from %s", CONFIG_FILE)
if not config():
Logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
return 1 # failure
section = "CouchPotato"
if inputCategory != None and config().has_section(inputCategory):
section = inputCategory
host = config().get(section, "host")
port = config().get(section, "port")
apikey = config().get(section, "apikey")
delay = float(config().get(section, "delay"))
method = config().get(section, "method")
delete_failed = int(config().get(section, "delete_failed"))
wait_for = int(config().get(section, "wait_for"))
try:
TimePerGiB = int(config().get(section, "TimePerGiB"))
except (config.NoOptionError, ValueError):
TimePerGiB = 60 # note, if using Network to transfer on 100Mbit LAN, expect ~ 600 MB/minute.
try:
ssl = int(config().get(section, "ssl"))
except (config.NoOptionError, ValueError):
ssl = 0
try:
web_root = config().get(section, "web_root")
except config.NoOptionError:
web_root = ""
try:
transcode = int(config().get("Transcoder", "transcode"))
except (config.NoOptionError, ValueError):
transcode = 0
try:
remoteCPS = int(config().get(section, "remoteCPS"))
except (config.NoOptionError, ValueError):
remoteCPS = 0
nzbName = str(nzbName) # make sure it is a string
imdbid = get_imdb(nzbName, dirName)
if ssl:
protocol = "https://"
else:
protocol = "http://"
# don't delay when we are calling this script manually.
if nzbName == "Manual Run":
delay = 0
baseURL = protocol + host + ":" + port + web_root + "/api/" + apikey + "/"
movie_id, imdbid, download_id, initial_status, initial_release_status = get_movie_info(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)
if status == 0:
if transcode == 1:
result = Transcoder.Transcode_directory(dirName)
if result == 0:
Logger.debug("Transcoding succeeded for files in %s", dirName)
else:
Logger.warning("Transcoding failed for files in %s", dirName)
if method == "manage":
command = "manage.update"
else:
command = "renamer.scan"
if clientAgent != "manual" and download_id != None:
if remoteCPS == 1:
command = command + "/?downloader=" + clientAgent + "&download_id=" + download_id
else:
command = command + "/?media_folder=" + urllib.quote(dirName) + "&downloader=" + clientAgent + "&download_id=" + download_id
dirSize = getDirectorySize(dirName) # get total directory size to calculate needed processing time.
TimeOut2 = int(TimePerGiB) * dirSize # Couchpotato needs to complete all moving and renaming before returning the status.
TimeOut2 += 60 # Add an extra minute for over-head/processing/metadata.
socket.setdefaulttimeout(int(TimeOut2)) #initialize socket timeout. We may now be able to remove the delays from the wait_for section below? If true, this should exit on first loop.
url = baseURL + command
Logger.info("Waiting for %s seconds to allow CPS to process newly extracted files", str(delay))
time.sleep(delay)
Logger.debug("Opening URL: %s", url)
try:
urlObj = urllib.urlopen(url)
except:
Logger.exception("Unable to open URL")
return 1 # failure
result = json.load(urlObj)
Logger.info("CouchPotatoServer returned %s", result)
if result['success']:
Logger.info("%s scan started on CouchPotatoServer for %s", method, nzbName)
else:
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")
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")
return 1 # failure
url = baseURL + "movie.searcher.try_next/?media_id=" + movie_id
Logger.debug("Opening URL: %s", url)
try:
urlObj = urllib.urlopen(url)
except:
Logger.exception("Unable to open URL")
return 1 # failure
result = urlObj.readlines()
for line in result:
Logger.info("%s", line)
Logger.info("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)
try:
shutil.rmtree(dirName)
except:
Logger.exception("Unable to delete folder %s", dirName)
return 0 # success
if nzbName == "Manual Run":
return 0 # success
if not download_id:
return 1 # just to be sure TorrentToMedia doesn't start deleting files as we havent verified changed status.
# we will now check to see if CPS has finished renaming before returning to TorrentToMedia and unpausing.
socket.setdefaulttimeout(int(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 = 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)
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)
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)
return 1 # failure

View file

@ -1,103 +0,0 @@
import urllib
import datetime
import logging
from nzbToMediaEnv import *
from nzbToMediaUtil import *
Logger = logging.getLogger()
def process(dirName, nzbName=None, status=0, clientAgent="manual", inputCategory=None):
status = int(status)
Logger.info("Loading config from %s", CONFIG_FILE)
if not config():
Logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
return 1 # failure
section = "HeadPhones"
if inputCategory != None and config().has_section(inputCategory):
section = inputCategory
host = config().get(section, "host")
port = config().get(section, "port")
apikey = config().get(section, "apikey")
delay = float(config().get(section, "delay"))
try:
ssl = int(config().get(section, "ssl"))
except (config.NoOptionError, ValueError):
ssl = 0
try:
web_root = config().get(section, "web_root")
except config.NoOptionError:
web_root = ""
try:
TimePerGiB = int(config().get(section, "TimePerGiB"))
except (config.NoOptionError, ValueError):
TimePerGiB = 60 # note, if using Network to transfer on 100Mbit LAN, expect ~ 600 MB/minute.
if ssl:
protocol = "https://"
else:
protocol = "http://"
# don't delay when we are calling this script manually.
if clientAgent == "manual":
delay = 0
nzbName, dirName = convert_to_ascii(nzbName, dirName)
dirSize = getDirectorySize(dirName) # get total directory size to calculate needed processing time.
TimeOut = int(TimePerGiB) * dirSize # HeadPhones needs to complete all moving/transcoding and renaming before returning the status.
TimeOut += 60 # Add an extra minute for over-head/processing/metadata.
socket.setdefaulttimeout(int(TimeOut)) #initialize socket timeout.
params = {}
params['apikey'] = apikey
params['cmd'] = "forceProcess"
params['dir'] = dirName
baseURL = protocol + host + ":" + port + web_root + "/api?" + urllib.urlencode(params)
if status == 0:
url = baseURL
Logger.info("Waiting for %s seconds to allow HeadPhones to process newly extracted files", str(delay))
time.sleep(delay)
Logger.debug("Opening URL: %s", url)
try:
urlObj = urllib.urlopen(url)
except:
Logger.exception("Unable to open URL")
return 1 # failure
result = urlObj.readlines()
Logger.info("HeadPhones returned %s", result)
if result[0] == "OK":
Logger.info("Post-processing started on HeadPhones for %s", nzbName)
else:
Logger.error("Post-processing has NOT started on HeadPhones for %s. Exiting", nzbName)
return 1 # failure
else:
Logger.info("The download failed. Nothing to process")
return 0 # Success (as far as this script is concerned)
if nzbName == "Manual Run":
return 0 # success
# we will now wait 1 minutes for this album to be processed before returning to TorrentToMedia and unpausing.
## Hopefully we can use a "getHistory" check in here to confirm processing complete...
start = datetime.datetime.now() # set time for timeout
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")
# return 1 # failure
return 0 # success for now.

View file

@ -1,216 +0,0 @@
import urllib
import logging
import copy
import Transcoder
from nzbToMediaSceneExceptions import process_all_exceptions
from autoProcess.autoSickBeardFork import autoFork
from nzbToMediaEnv import *
from nzbToMediaUtil import *
Logger = logging.getLogger()
class AuthURLOpener(urllib.FancyURLopener):
def __init__(self, user, pw):
self.username = user
self.password = pw
self.numTries = 0
urllib.FancyURLopener.__init__(self)
def prompt_user_passwd(self, host, realm):
if self.numTries == 0:
self.numTries = 1
return (self.username, self.password)
else:
return ('', '')
def openit(self, url):
self.numTries = 0
try:
return urllib.FancyURLopener.open(self, url)
except:
raise IOError("Unable to open URL")
def delete(dirName):
Logger.info("Deleting failed files and folder %s", dirName)
try:
shutil.rmtree(dirName, True)
except:
Logger.exception("Unable to delete folder %s", dirName)
def processEpisode(dirName, nzbName=None, failed=False, clientAgent = "manual", inputCategory=None):
status = int(failed)
Logger.info("Loading config from %s", CONFIG_FILE)
if not config():
Logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
return 1 # failure
section = "SickBeard"
if inputCategory != None and config().has_section(inputCategory):
section = inputCategory
host = config().get(section, "host")
port = config().get(section, "port")
username = config().get(section, "username")
password = config().get(section, "password")
try:
ssl = int(config().get(section, "ssl"))
except (config.NoOptionError, ValueError):
ssl = 0
try:
web_root = config().get(section, "web_root")
except config.NoOptionError:
web_root = ""
try:
watch_dir = config().get(section, "watch_dir")
except config.NoOptionError:
watch_dir = ""
try:
transcode = int(config().get("Transcoder", "transcode"))
except (config.NoOptionError, ValueError):
transcode = 0
try:
delete_failed = int(config().get(section, "delete_failed"))
except (config.NoOptionError, ValueError):
delete_failed = 0
try:
delay = float(config().get(section, "delay"))
except (config.NoOptionError, ValueError):
delay = 0
try:
TimePerGiB = int(config().get(section, "TimePerGiB"))
except (config.NoOptionError, ValueError):
TimePerGiB = 60 # note, if using Network to transfer on 100Mbit LAN, expect ~ 600 MB/minute.
try:
SampleIDs = (config().get("Extensions", "SampleIDs")).split(',')
except (config.NoOptionError, ValueError):
SampleIDs = ['sample','-s.']
try:
nzbExtractionBy = config().get(section, "nzbExtractionBy")
except (config.NoOptionError, ValueError):
nzbExtractionBy = "Downloader"
try:
process_method = config().get(section, "process_method")
except config.NoOptionError:
process_method = None
mediaContainer = (config().get("Extensions", "mediaExtensions")).split(',')
minSampleSize = int(config().get("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]
SpecificPath = os.path.join(dirName, str(nzbName))
cleanName = os.path.splitext(SpecificPath)
if cleanName[1] == ".nzb":
SpecificPath = cleanName[0]
if os.path.isdir(SpecificPath):
dirName = SpecificPath
# auto-detect fork type
fork, params = autoFork()
if fork not in 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)
# Now check if tv files exist in destination. Eventually extraction may be done here if nzbExtractionBy == TorrentToMedia
video = int(0)
for dirpath, dirnames, filenames in os.walk(dirName):
for file in filenames:
filePath = os.path.join(dirpath, file)
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)
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)
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)
status = int(1)
failed = True
dirSize = getDirectorySize(dirName) # get total directory size to calculate needed processing time.
TimeOut = int(TimePerGiB) * dirSize # SickBeard needs to complete all moving and renaming before returning the log sequence via url.
TimeOut += 60 # Add an extra minute for over-head/processing/metadata.
socket.setdefaulttimeout(int(TimeOut)) #initialize socket timeout.
# configure SB params to pass
params['quiet'] = 1
if nzbName is not None:
params['nzbName'] = nzbName
for param in copy.copy(params):
if param == "failed":
params[param] = failed
if param in ["dirName", "dir"]:
params[param] = dirName
if param == "process_method":
if process_method:
params[param] = process_method
else:
del params[param]
# delete any unused params so we don't pass them to SB by mistake
[params.pop(k) for k,v in params.items() if v is None]
if status == 0:
Logger.info("The download succeeded. Sending process request to SickBeard's %s branch", fork)
elif fork in SICKBEARD_FAILED:
Logger.info("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)
if delete_failed and os.path.isdir(dirName) and not dirName in ['sys.argv[0]','/','']:
Logger.info("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)
else:
Logger.warning("Transcoding failed for files in %s", dirName)
myOpener = AuthURLOpener(username, password)
if ssl:
protocol = "https://"
else:
protocol = "http://"
url = protocol + host + ":" + port + web_root + "/home/postprocess/processEpisode?" + urllib.urlencode(params)
if clientAgent == "manual":delay = 0
Logger.info("Waiting for %s seconds to allow SB to process newly extracted files", str(delay))
time.sleep(delay)
Logger.debug("Opening URL: %s", url)
try:
urlObj = myOpener.openit(url)
except:
Logger.exception("Unable to open URL")
return 1 # failure
result = urlObj.readlines()
for line in result:
Logger.info("%s", line.rstrip())
if status != 0 and delete_failed and not dirName in ['sys.argv[0]','/','']:
delete(dirName)
return 0 # Success

View file

@ -1,227 +0,0 @@
from nzbToMediaConfig import *
def migrate():
categories = []
confignew = config(SAMPLE_CONFIG_FILE)
configold = config(CONFIG_FILE)
section = "CouchPotato"
for option, value in configold.items(section) or config(MOVIE_CONFIG_FILE).items(section):
if option == "category": # change this old format
option = "cpsCategory"
if option == "outputDirectory": # move this to new location format
value = os.path.split(os.path.normpath(value))[0]
confignew.set("Torrent", option, value)
continue
if option in ["username", "password" ]: # these are no-longer needed.
continue
if option == "cpsCategory":
categories.extend(value.split(','))
confignew.set(section, option, value)
section = "SickBeard"
for option, value in configold.items(section) or config(TV_CONFIG_FILE).items(section):
if option == "category": # change this old format
option = "sbCategory"
if option == "wait_for": # remove old format
continue
if option == "failed_fork": # change this old format
option = "fork"
if value not in ["default", "failed", "failed-torrent", "auto"]:
value = "auto"
if option == "fork" and value not in ["default", "failed", "failed-torrent", "auto"]:
value = "auto"
if option == "outputDirectory": # move this to new location format
value = os.path.split(os.path.normpath(value))[0]
confignew.set("Torrent", option, value)
continue
if option == "sbCategory":
categories.extend(value.split(','))
confignew.set(section, option, value)
for section in configold.sections():
try:
for option, value in configold.items(section):
if section == "HeadPhones":
if option in ["username", "password" ]:
continue
if option == "hpCategory":
categories.extend(value.split(','))
confignew.set(section, option, value)
if section == "Mylar":
if option in "mlCategory":
categories.extend(value.split(','))
confignew.set(section, option, value)
if section == "Gamez":
if option in ["username", "password" ]: # these are no-longer needed.
continue
if option == "gzCategory":
categories.extend(value.split(','))
confignew.set(section, option, value)
if section == "Torrent":
if option in ["compressedExtensions", "mediaExtensions", "metaExtensions", "minSampleSize"]:
section = "Extensions" # these were moved
if option == "useLink": # Sym links supported now as well.
if isinstance(value, int):
num_value = int(value)
if num_value == 1:
value = "hard"
else:
value = "no"
confignew.set(section, option, value)
if section == "Extensions":
confignew.set(section, option, value)
if section == "Transcoder":
confignew.set(section, option, value)
if section == "WakeOnLan":
confignew.set(section, option, value)
if section == "UserScript":
confignew.set(section, option, value)
if section == "ASCII":
confignew.set(section, option, value)
if section == "passwords":
confignew.set(section, option, value)
if section == "loggers":
confignew.set(section, option, value)
if section == "handlers":
confignew.set(section, option, value)
if section == "formatters":
confignew.set(section, option, value)
if section == "logger_root":
confignew.set(section, option, value)
if section == "handler_console":
confignew.set(section, option, value)
if section == "formatter_generic":
confignew.set(section, option, value)
except config.InterpolationMissingOptionError:
pass
for section in categories:
try:
if configold.items(section):
confignew.add_section(section)
for option, value in configold.items(section):
confignew.set(section, option, value)
except config.NoSectionError:
continue
# create a backup of our old config
if os.path.isfile(CONFIG_FILE):
cfgbak_name = CONFIG_FILE + ".old"
if os.path.isfile(cfgbak_name): # remove older backups
os.unlink(cfgbak_name)
os.rename(CONFIG_FILE, cfgbak_name)
# writing our configuration file to 'autoProcessMedia.cfg'
with open(CONFIG_FILE, 'wb') as configFile:
confignew.write(configFile)
def addnzbget():
confignew = config()
section = "CouchPotato"
envKeys = ['CATEGORY', 'APIKEY', 'HOST', 'PORT', 'SSL', 'WEB_ROOT', 'DELAY', 'METHOD', 'DELETE_FAILED', 'REMOTECPS', 'WAIT_FOR', 'TIMEPERGIB']
cfgKeys = ['cpsCategory', 'apikey', 'host', 'port', 'ssl', 'web_root', 'delay', 'method', 'delete_failed', 'remoteCPS', 'wait_for', 'TimePerGiB']
for index in range(len(envKeys)):
key = 'NZBPO_CPS' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "SickBeard"
envKeys = ['CATEGORY', 'HOST', 'PORT', 'USERNAME', 'PASSWORD', 'SSL', 'WEB_ROOT', 'WATCH_DIR', 'FORK', 'DELETE_FAILED', 'DELAY', 'TIMEPERGIB', 'PROCESS_METHOD']
cfgKeys = ['sbCategory', 'host', 'port', 'username', 'password', 'ssl', 'web_root', 'watch_dir', 'fork', 'delete_failed', 'delay', 'TimePerGiB', 'process_method']
for index in range(len(envKeys)):
key = 'NZBPO_SB' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "HeadPhones"
envKeys = ['CATEGORY', 'APIKEY', 'HOST', 'PORT', 'SSL', 'WEB_ROOT', 'DELAY', 'TIMEPERGIB']
cfgKeys = ['hpCategory', 'apikey', 'host', 'port', 'ssl', 'web_root', 'delay', 'TimePerGiB']
for index in range(len(envKeys)):
key = 'NZBPO_HP' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "Mylar"
envKeys = ['CATEGORY', 'HOST', 'PORT', 'USERNAME', 'PASSWORD', 'SSL', 'WEB_ROOT']
cfgKeys = ['mlCategory', 'host', 'port', 'username', 'password', 'ssl', 'web_root']
for index in range(len(envKeys)):
key = 'NZBPO_MY' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "Gamez"
envKeys = ['CATEGORY', 'APIKEY', 'HOST', 'PORT', 'SSL', 'WEB_ROOT']
cfgKeys = ['gzCategory', 'apikey', 'host', 'port', 'ssl', 'web_root']
for index in range(len(envKeys)):
key = 'NZBPO_GZ' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "Extensions"
envKeys = ['COMPRESSEDEXTENSIONS', 'MEDIAEXTENSIONS', 'METAEXTENSIONS']
cfgKeys = ['compressedExtensions', 'mediaExtensions', 'metaExtensions']
for index in range(len(envKeys)):
key = 'NZBPO_' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "Transcoder"
envKeys = ['TRANSCODE', 'DUPLICATE', 'IGNOREEXTENSIONS', 'OUTPUTVIDEOEXTENSION', 'OUTPUTVIDEOCODEC', 'OUTPUTVIDEOPRESET', 'OUTPUTVIDEOFRAMERATE', 'OUTPUTVIDEOBITRATE', 'OUTPUTAUDIOCODEC', 'OUTPUTAUDIOBITRATE', 'OUTPUTSUBTITLECODEC']
cfgKeys = ['transcode', 'duplicate', 'ignoreExtensions', 'outputVideoExtension', 'outputVideoCodec', 'outputVideoPreset', 'outputVideoFramerate', 'outputVideoBitrate', 'outputAudioCodec', 'outputAudioBitrate', 'outputSubtitleCodec']
for index in range(len(envKeys)):
key = 'NZBPO_' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "WakeOnLan"
envKeys = ['WAKE', 'HOST', 'PORT', 'MAC']
cfgKeys = ['wake', 'host', 'port', 'mac']
for index in range(len(envKeys)):
key = 'NZBPO_WOL' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
# create a backup of our old config
if os.path.isfile(CONFIG_FILE):
cfgbak_name = CONFIG_FILE + ".old"
if os.path.isfile(cfgbak_name): # remove older backups
os.unlink(cfgbak_name)
os.rename(CONFIG_FILE, cfgbak_name)
# writing our configuration file to 'autoProcessMedia.cfg'
with open(CONFIG_FILE, 'wb') as configFile:
confignew.write(configFile)

View file

@ -1,24 +0,0 @@
# Make things easy and less error prone by centralising all common values
# Global Constants
VERSION = 'V9.3'
TimeOut = 60
# Constants pertinant to SabNzb
SABNZB_NO_OF_ARGUMENTS = 8
SABNZB_0717_NO_OF_ARGUMENTS = 9
# Constants pertaining to SickBeard Branches:
fork_default = "default"
fork_failed = "failed"
fork_failed_torrent = "failed-torrent"
forks = {}
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]

View file

@ -13,13 +13,13 @@ ssl = 0
web_root = web_root =
delay = 65 delay = 65
TimePerGiB = 60 TimePerGiB = 60
watch_dir =
method = renamer method = renamer
delete_failed = 0 delete_failed = 0
wait_for = 2 wait_for = 2
#### Set to 1 if CouchPotatoServer is running on a different server to your NZB client #### Set to 1 if CouchPotatoServer is running on a different server to your NZB client
remoteCPS = 0 remoteCPS = 0
[SickBeard] [SickBeard]
#### autoProcessing for TV Series #### autoProcessing for TV Series
#### sbCategory - category that gets called for post-processing with SB #### sbCategory - category that gets called for post-processing with SB
@ -40,7 +40,6 @@ nzbExtractionBy = Downloader
Torrent_ForceLink = 1 Torrent_ForceLink = 1
process_method = process_method =
[HeadPhones] [HeadPhones]
#### autoProcessing for Music #### autoProcessing for Music
#### hpCategory - category that gets called for post-processing with HP #### hpCategory - category that gets called for post-processing with HP
@ -53,7 +52,7 @@ ssl = 0
web_root = web_root =
delay = 65 delay = 65
TimePerGiB = 60 TimePerGiB = 60
watch_dir =
[Mylar] [Mylar]
#### autoProcessing for Comics #### autoProcessing for Comics
@ -68,7 +67,6 @@ web_root=
ssl=0 ssl=0
watch_dir = watch_dir =
[Gamez] [Gamez]
#### autoProcessing for Games #### autoProcessing for Games
#### gzCategory - category that gets called for post-processing with Gamez #### gzCategory - category that gets called for post-processing with Gamez
@ -79,7 +77,7 @@ port = 8085
###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ###### ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
ssl = 0 ssl = 0
web_root = web_root =
watch_dir =
[Torrent] [Torrent]
###### clientAgent - Supported clients: utorrent, transmission, deluge, rtorrent, other ###### clientAgent - Supported clients: utorrent, transmission, deluge, rtorrent, other

View file

@ -121,25 +121,32 @@
### NZBGET POST-PROCESSING SCRIPT ### ### NZBGET POST-PROCESSING SCRIPT ###
############################################################################## ##############################################################################
# Exit codes used by NZBGet
import logging import logging
import os
import sys
from nzbtomedia.autoProcess.autoProcessMovie import autoProcessMovie
from nzbtomedia.migratecfg import migratecfg
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import nzbtomedia_configure_logging, WakeUp, get_dirnames
import autoProcess.migratecfg as migratecfg # run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
import autoProcess.autoProcessMovie as autoProcessMovie if migratecfg().migrate():
from autoProcess.nzbToMediaEnv import *
from autoProcess.nzbToMediaUtil import *
#check to migrate old cfg before trying to load.
if os.path.isfile(os.path.join(os.path.dirname(sys.argv[0]), "autoProcessMedia.cfg.sample")):
migratecfg.migrate()
# check to write settings from nzbGet UI to autoProcessMedia.cfg. # check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'): if os.environ.has_key('NZBOP_SCRIPTDIR'):
migratecfg.addnzbget() migratecfg().addnzbget()
nzbtomedia_configure_logging(LOG_FILE) nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__) Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log Logger.info("====================") # Seperate old from new log
Logger.info("nzbToCouchPotato %s", VERSION) Logger.info("nzbToCouchPotato %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
# couchpotato category
cpsCategory = (config().get("CouchPotato", "cpsCategory")).split(',') # movie
WakeUp() WakeUp()
@ -150,24 +157,19 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
# NZBGet argv: all passed as environment variables. # NZBGet argv: all passed as environment variables.
clientAgent = "nzbget" clientAgent = "nzbget"
# Exit codes used by NZBGet
POSTPROCESS_PARCHECK=92
POSTPROCESS_SUCCESS=93
POSTPROCESS_ERROR=94
POSTPROCESS_NONE=95
# Check nzbget.conf options # Check nzbget.conf options
status = 0 status = 0
if os.environ['NZBOP_UNPACK'] != 'yes': if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting") Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)
# Check par status # Check par status
if os.environ['NZBPP_PARSTATUS'] == '3': if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting") Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.") Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(POSTPROCESS_NONE) sys.exit(config.NZBGET_POSTPROCESS_NONE)
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4': if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"") Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
@ -200,9 +202,9 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
if os.environ.has_key('NZBPR_COUCHPOTATO'): if os.environ.has_key('NZBPR_COUCHPOTATO'):
download_id = os.environ['NZBPR_COUCHPOTATO'] download_id = os.environ['NZBPR_COUCHPOTATO']
Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessMovie...") Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessMovie...")
result = autoProcessMovie.process(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBNAME'], status, clientAgent, download_id) result = autoProcessMovie().process(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBNAME'], status, clientAgent, download_id)
# SABnzbd Pre 0.7.17 # SABnzbd Pre 0.7.17
elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS: elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -213,9 +215,9 @@ elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS:
# 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2 # 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.info("MAIN: Script triggered from SABnzbd, starting autoProcessMovie...")
clientAgent = "sabnzbd" clientAgent = "sabnzbd"
result = autoProcessMovie.process(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent) result = autoProcessMovie().process(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent)
# SABnzbd 0.7.17+ # SABnzbd 0.7.17+
elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS: elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -227,18 +229,23 @@ elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS:
# 8 Failure URL # 8 Failure URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessMovie...") Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessMovie...")
clientAgent = "sabnzbd" clientAgent = "sabnzbd"
result = autoProcessMovie.process(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent) result = autoProcessMovie().process(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent)
else: else:
result = 0
Logger.warn("MAIN: Invalid number of arguments received from client.") Logger.warn("MAIN: Invalid number of arguments received from client.")
Logger.info("MAIN: Running autoProcessMovie as a manual run...") Logger.info("MAIN: Running autoProcessMovie as a manual run...")
clientAgent = "manual"
result = autoProcessMovie.process('Manual Run', 'Manual Run', 0, clientAgent) for dirName in get_dirnames("CouchPotato", cpsCategory[0]):
Logger.info("MAIN: Calling CouchPotato to post-process: %s", dirName)
result = autoProcessMovie().process(dirName, dirName, 0)
if result != 0: break
if result == 0: if result == 0:
Logger.info("MAIN: The autoProcessMovie script completed successfully.") Logger.info("MAIN: The autoProcessMovie script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_SUCCESS) sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
else: else:
Logger.info("MAIN: A problem was reported in the autoProcessMovie script.") Logger.info("MAIN: A problem was reported in the autoProcessMovie script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)

View file

@ -57,25 +57,33 @@
### NZBGET POST-PROCESSING SCRIPT ### ### NZBGET POST-PROCESSING SCRIPT ###
############################################################################## ##############################################################################
# Exit codes used by NZBGet
import logging import logging
import os
import sys
from nzbtomedia.autoProcess.autoProcessGames import autoProcessGames
from nzbtomedia.migratecfg import migratecfg
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import WakeUp, nzbtomedia_configure_logging, get_dirnames
import autoProcess.migratecfg as migratecfg # run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
import autoProcess.autoProcessGames as autoProcessGames if migratecfg().migrate():
from autoProcess.nzbToMediaEnv import *
from autoProcess.nzbToMediaUtil import *
#check to migrate old cfg before trying to load.
if os.path.isfile(os.path.join(os.path.dirname(sys.argv[0]), "autoProcessMedia.cfg.sample")):
migratecfg.migrate()
# check to write settings from nzbGet UI to autoProcessMedia.cfg. # check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'): if os.environ.has_key('NZBOP_SCRIPTDIR'):
migratecfg.addnzbget() migratecfg().addnzbget()
nzbtomedia_configure_logging(LOG_FILE) nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__) Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log Logger.info("====================") # Seperate old from new log
Logger.info("nzbToGamez %s", VERSION) Logger.info("nzbToGamez %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
# gamez category
gzCategory = (config().get("Gamez", "gzCategory")).split(',') # gamez
WakeUp() WakeUp()
@ -84,25 +92,18 @@ WakeUp()
if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5] < '11.0': 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.info("MAIN: Script triggered from NZBGet (11.0 or later).")
# NZBGet argv: all passed as environment variables.
# Exit codes used by NZBGet
POSTPROCESS_PARCHECK=92
POSTPROCESS_SUCCESS=93
POSTPROCESS_ERROR=94
POSTPROCESS_NONE=95
# Check nzbget.conf options # Check nzbget.conf options
status = 0 status = 0
if os.environ['NZBOP_UNPACK'] != 'yes': if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting") Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)
# Check par status # Check par status
if os.environ['NZBPP_PARSTATUS'] == '3': if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting") Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.") Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(POSTPROCESS_NONE) sys.exit(config.NZBGET_POSTPROCESS_NONE)
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4': if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"") Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
@ -132,9 +133,9 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
# All checks done, now launching the script. # All checks done, now launching the script.
Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessGames...") Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessGames...")
result = autoProcessGames.process(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBNAME'], status) result = autoProcessGames().process(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBNAME'], status)
# SABnzbd Pre 0.7.17 # SABnzbd Pre 0.7.17
elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS: elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -144,9 +145,9 @@ elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS:
# 6 Group that the NZB was posted in e.g. alt.binaries.x # 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 # 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.info("MAIN: Script triggered from SABnzbd, starting autoProcessGames...")
result = autoProcessGames.process(sys.argv[1], sys.argv[3], sys.argv[7]) result = autoProcessGames().process(sys.argv[1], sys.argv[3], sys.argv[7])
# SABnzbd 0.7.17+ # SABnzbd 0.7.17+
elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS: elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -157,16 +158,22 @@ elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS:
# 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2 # 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2
# 8 Failure URL # 8 Failure URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessGames...") Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessGames...")
result = autoProcessGames.process(sys.argv[1], sys.argv[3], sys.argv[7]) result = autoProcessGames().process(sys.argv[1], sys.argv[3], sys.argv[7])
else: else:
result = 0
Logger.warn("MAIN: Invalid number of arguments received from client. Exiting") Logger.warn("MAIN: Invalid number of arguments received from client. Exiting")
sys.exit(1) Logger.info("MAIN: Running autoProcessGames as a manual run...")
for dirName in get_dirnames("Gamez", gzCategory[0]):
Logger.info("MAIN: Calling Gamez to post-process: %s", dirName)
result = autoProcessGames().process(dirName, dirName, 0)
if result != 0: break
if result == 0: if result == 0:
Logger.info("MAIN: The autoProcessGames script completed successfully.") Logger.info("MAIN: The autoProcessGames script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_SUCCESS) sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
else: else:
Logger.info("MAIN: A problem was reported in the autoProcessGames script.") Logger.info("MAIN: A problem was reported in the autoProcessGames script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)

View file

@ -67,33 +67,32 @@
### NZBGET POST-PROCESSING SCRIPT ### ### NZBGET POST-PROCESSING SCRIPT ###
############################################################################## ##############################################################################
import logging
import autoProcess.migratecfg as migratecfg
import autoProcess.autoProcessMusic as autoProcessMusic
from autoProcess.nzbToMediaEnv import *
from autoProcess.nzbToMediaUtil import *
# NZBGet argv: all passed as environment variables. # NZBGet argv: all passed as environment variables.
# Exit codes used by NZBGet # Exit codes used by NZBGet
POSTPROCESS_PARCHECK = 92 import os
POSTPROCESS_SUCCESS = 93 import sys
POSTPROCESS_ERROR = 94 import logging
POSTPROCESS_NONE = 95 from nzbtomedia.autoProcess.autoProcessMusic import autoProcessMusic
from nzbtomedia.migratecfg import migratecfg
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import get_dirnames, WakeUp, nzbtomedia_configure_logging
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
#check to migrate old cfg before trying to load. if migratecfg().migrate():
if os.path.isfile(os.path.join(os.path.dirname(sys.argv[0]), "autoProcessMedia.cfg.sample")):
migratecfg.migrate()
# check to write settings from nzbGet UI to autoProcessMedia.cfg. # check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'): if os.environ.has_key('NZBOP_SCRIPTDIR'):
migratecfg.addnzbget() migratecfg().addnzbget()
nzbtomedia_configure_logging(LOG_FILE) nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__) Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log Logger.info("====================") # Seperate old from new log
Logger.info("nzbToHeadPhones %s", VERSION) Logger.info("nzbToHeadPhones %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
# headphones category
hpCategory = (config().get("HeadPhones", "hpCategory")).split(',') # music
WakeUp() WakeUp()
@ -107,13 +106,13 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
if os.environ['NZBOP_UNPACK'] != 'yes': if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting") Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)
# Check par status # Check par status
if os.environ['NZBPP_PARSTATUS'] == '3': if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting") Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.") Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(POSTPROCESS_NONE) sys.exit(config.NZBGET_POSTPROCESS_NONE)
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4': if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"") Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
@ -143,9 +142,9 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
# All checks done, now launching the script. # All checks done, now launching the script.
Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessMusic...") Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessMusic...")
result = autoProcessMusic.process(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBNAME'], status) result = autoProcessMusic().process(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBNAME'], status)
# SABnzbd Pre 0.7.17 # SABnzbd Pre 0.7.17
elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS: elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -155,9 +154,9 @@ elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS:
# 6 Group that the NZB was posted in e.g. alt.binaries.x # 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 # 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.info("MAIN: Script triggered from SABnzbd, starting autoProcessMusic...")
result = autoProcessMusic.process(sys.argv[1], sys.argv[2], sys.argv[7]) result = autoProcessMusic().process(sys.argv[1], sys.argv[2], sys.argv[7])
# SABnzbd 0.7.17+ # SABnzbd 0.7.17+
elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS: elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -168,24 +167,23 @@ elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS:
# 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2 # 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2
# 8 Failue URL # 8 Failue URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessMusic...") Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessMusic...")
result = autoProcessMusic.process(sys.argv[1], sys.argv[2], sys.argv[7]) result = autoProcessMusic().process(sys.argv[1], sys.argv[2], sys.argv[7])
else: else:
result = 0 result = 0
hpCategory = (config().get("HeadPhones", "hpCategory")).split(',') # music
dirNames = get_dirnames("SickBeard", hpCategory[0])
Logger.warn("MAIN: Invalid number of arguments received from client.") Logger.warn("MAIN: Invalid number of arguments received from client.")
Logger.info("MAIN: Running autoProcessMusic as a manual run...") Logger.info("MAIN: Running autoProcessMusic as a manual run...")
for dirName in dirNames: for dirName in get_dirnames("HeadPhones", hpCategory[0]):
Logger.info("MAIN: Calling Headphones to post-process: %s", dirName) Logger.info("MAIN: Calling Headphones to post-process: %s", dirName)
result = result = autoProcessMusic.process(dirName, dirName, 0) result = result = autoProcessMusic().process(dirName, dirName, 0)
if result != 0: break if result != 0: break
if result == 0: if result == 0:
Logger.info("MAIN: The autoProcessMusic script completed successfully.") Logger.info("MAIN: The autoProcessMusic script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_SUCCESS) sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
else: else:
Logger.info("MAIN: A problem was reported in the autoProcessMusic script.") Logger.info("MAIN: A problem was reported in the autoProcessMusic script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)

View file

@ -73,7 +73,7 @@
# SickBeard script category. # SickBeard script category.
# #
# category that gets called for post-processing with SickBeard. # category that gets called for post-processing with SickBeard.
#sbCategory=tv #config().sbCategory=tv
# SickBeard host. # SickBeard host.
#sbhost=localhost #sbhost=localhost
@ -271,54 +271,101 @@
### NZBGET POST-PROCESSING SCRIPT ### ### NZBGET POST-PROCESSING SCRIPT ###
############################################################################## ##############################################################################
import shutil import os
import sys
import logging import logging
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.migratecfg import migratecfg
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import nzbtomedia_configure_logging, WakeUp, get_dirnames
import autoProcess.autoProcessComics as autoProcessComics # post-processing
import autoProcess.autoProcessGames as autoProcessGames def process(nzbDir, inputName=None, status=0, clientAgent='manual', download_id=None, inputCategory=None):
import autoProcess.autoProcessMusic as autoProcessMusic if inputCategory in cpsCategory:
import autoProcess.autoProcessMovie as autoProcessMovie if isinstance(nzbDir, list):
import autoProcess.autoProcessTV as autoProcessTV for dirName in nzbDir:
import autoProcess.migratecfg as migratecfg Logger.info("MAIN: Calling CouchPotatoServer to post-process: %s", inputName)
from autoProcess.nzbToMediaEnv import * result = autoProcessMovie().process(dirName, dirName, status, clientAgent, download_id, inputCategory)
from autoProcess.nzbToMediaUtil import * if result != 0:
return result
# Exit codes used by NZBGet else:
POSTPROCESS_PARCHECK = 92 Logger.info("MAIN: Calling CouchPotatoServer to post-process: %s", inputName)
POSTPROCESS_SUCCESS = 93 return autoProcessMovie().process(nzbDir, inputName, status, clientAgent, download_id, inputCategory)
POSTPROCESS_ERROR = 94 elif inputCategory in sbCategory:
POSTPROCESS_NONE = 95 if isinstance(nzbDir, list):
for dirName in nzbDir:
Logger.info("MAIN: Calling Sick-Beard to post-process: %s", inputName)
result = autoProcessTV().processEpisode(dirName, dirName, status, clientAgent, inputCategory)
if result !=0:
return result
else:
Logger.info("MAIN: Calling Sick-Beard to post-process: %s", inputName)
return autoProcessTV().processEpisode(nzbDir, inputName, status, clientAgent, inputCategory)
elif inputCategory in hpCategory:
if isinstance(nzbDir, list):
for dirName in nzbDir:
Logger.info("MAIN: Calling Headphones to post-process: %s", dirName)
result = autoProcessMusic().process(dirName, dirName, status, clientAgent, inputCategory)
if result != 0:
return result
else:
Logger.info("MAIN: Calling HeadPhones to post-process: %s", inputName)
return autoProcessMusic().process(nzbDir, inputName, status, clientAgent, inputCategory)
elif inputCategory in mlCategory:
if isinstance(nzbDir, list):
for dirName in nzbDir:
Logger.info("MAIN: Calling Mylar to post-process: %s", dirName)
result = autoProcessComics().processEpisode(dirName, dirName, status, clientAgent, inputCategory)
if result != 0:
return result
else:
Logger.info("MAIN: Calling Mylar to post-process: %s", inputName)
return autoProcessComics().processEpisode(nzbDir, inputName, status, clientAgent, inputCategory)
elif inputCategory in gzCategory:
if isinstance(nzbDir, list):
for dirName in nzbDir:
Logger.info("MAIN: Calling Gamez to post-process: %s", dirName)
result = autoProcessGames().process(dirName, dirName, status, clientAgent, inputCategory)
if result != 0:
return result
else:
Logger.info("MAIN: Calling Gamez to post-process: %s", inputName)
return autoProcessGames().process(nzbDir, inputName, status, clientAgent, inputCategory)
else:
Logger.warning("MAIN: The download category %s does not match any category defined in autoProcessMedia.cfg. Exiting.", inputCategory)
return -1
########################################################################################################################
# run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options. # run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
if config(SAMPLE_CONFIG_FILE): if migratecfg().migrate():
migratecfg.migrate()
elif config():
shutil.copyfile(CONFIG_FILE, SAMPLE_CONFIG_FILE)
migratecfg.migrate()
# check to write settings from nzbGet UI to autoProcessMedia.cfg. # check to write settings from nzbGet UI to autoProcessMedia.cfg.
if config() and os.environ.has_key('NZBOP_SCRIPTDIR'): if os.environ.has_key('NZBOP_SCRIPTDIR'):
migratecfg.addnzbget() migratecfg().addnzbget()
nzbtomedia_configure_logging(LOG_FILE) nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__) Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log Logger.info("====================") # Seperate old from new log
Logger.info("nzbToMedia %s", VERSION) Logger.info("nzbToMedia %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
# setup categories
cpsCategory = (config().get("CouchPotato", "cpsCategory")).split(',') or []
sbCategory = (config().get("SickBeard", "sbCategory")).split(',') or []
hpCategory = (config().get("HeadPhones", "hpCategory")).split(',') or []
mlCategory = (config().get("Mylar", "mlCategory")).split(',') or []
gzCategory = (config().get("Gamez", "gzCategory")).split(',') or []
WakeUp() WakeUp()
if not config(): # Post-Processing Result
Logger.error("MAIN: You need an autoProcessMedia.cfg file - did you rename and edit the .sample?") result = 0
sys.exit(-1)
Logger.info("MAIN: Loading config from %s", CONFIG_FILE)
cpsCategory = (config().get("CouchPotato", "cpsCategory")).split(',') # movie
sbCategory = (config().get("SickBeard", "sbCategory")).split(',') # tv
hpCategory = (config().get("HeadPhones", "hpCategory")).split(',') # music
mlCategory = (config().get("Mylar", "mlCategory")).split(',') # comics
gzCategory = (config().get("Gamez", "gzCategory")).split(',') # games
# NZBGet V11+ # NZBGet V11+
# Check if the script is called from nzbget 11.0 or later # Check if the script is called from nzbget 11.0 or later
@ -333,13 +380,13 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
if os.environ['NZBOP_UNPACK'] != 'yes': if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting") Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)
# Check par status # Check par status
if os.environ['NZBPP_PARSTATUS'] == '3': if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting") Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.") Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(POSTPROCESS_NONE) sys.exit(config.NZBGET_POSTPROCESS_NONE)
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4': if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"") Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
@ -369,11 +416,11 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
# All checks done, now launching the script. # All checks done, now launching the script.
download_id = "" download_id = ""
if os.environ.has_key('NZBPR_COUCHPOTATO'): if os.environ.has_key('NZBPR_COUCHPOTATO'):download_id = os.environ['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'])
nzbDir, inputName, inputCategory = (os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBFILENAME'], os.environ['NZBPP_CATEGORY']) if result != 0: Logger.info("MAIN: A problem was reported in the autoProcess* script.")
# SABnzbd Pre 0.7.17 # SABnzbd Pre 0.7.17
elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS: elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -383,10 +430,10 @@ elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS:
# 6 Group that the NZB was posted in e.g. alt.binaries.x # 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 # 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2
Logger.info("MAIN: Script triggered from SABnzbd") Logger.info("MAIN: Script triggered from SABnzbd")
clientAgent = "sabnzbd" result = process(sys.argv[1], inputName=sys.argv[2], status=sys.argv[7], inputCategory=sys.argv[5], clientAgent = "sabnzbd", download_id='')
nzbDir, inputName, status, inputCategory, download_id = (sys.argv[1], sys.argv[2], sys.argv[7], sys.argv[5], '') if result != 0: Logger.info("MAIN: A problem was reported in the autoProcess* script.")
# SABnzbd 0.7.17+ # SABnzbd 0.7.17+
elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS: elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -397,61 +444,37 @@ elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS:
# 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2 # 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2
# 8 Failure URL # 8 Failure URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+") Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+")
clientAgent = "sabnzbd" result = process(sys.argv[1], inputName=sys.argv[2], status=sys.argv[7], inputCategory=sys.argv[5], clientAgent = "sabnzbd", download_id='')
nzbDir, inputName, status, inputCategory, download_id = (sys.argv[1], sys.argv[2], sys.argv[7], sys.argv[5], '') if result != 0:Logger.info("MAIN: A problem was reported in the autoProcess* script.")
else: # only CPS and SB supports this manual run for now. else:
clientAgent = "manual" # only CPS and SB supports this manual run for now.
Logger.warn("MAIN: Invalid number of arguments received from client.") Logger.warn("MAIN: Invalid number of arguments received from client.")
Logger.info("MAIN: Running autoProcessMovie as a manual run...") Logger.info("MAIN: Running autoProcessMovie as a manual run...")
nzbDir, inputName, status, inputCategory, download_id = ('Manual Run', 'Manual Run', 0, cpsCategory[0], '') if process(get_dirnames("CouchPotato", cpsCategory[0]), inputName=get_dirnames("CouchPotato", cpsCategory[0]), status=0, inputCategory=cpsCategory[0], clientAgent = "manual", download_id='') != 0:
Logger.info("MAIN: A problem was reported in the autoProcessMovie script.")
Logger.info("MAIN: Running autoProcessTV as a manual run...") Logger.info("MAIN: Running autoProcessTV as a manual run...")
dirNames = get_dirnames("SickBeard", sbCategory[0]) if process(get_dirnames("SickBeard", sbCategory[0]), inputName=get_dirnames("SickBeard", sbCategory[0]), status=0, clientAgent = "manual", inputCategory=sbCategory[0]) != 0:
nzbDir, inputName, status, inputCategory, = (dirNames, dirNames, 0, sbCategory[0]) Logger.info("MAIN: A problem was reported in the autoProcessTV script.")
Logger.info("MAIN: Running autoProcessMusic as a manual run...") Logger.info("MAIN: Running autoProcessMusic as a manual run...")
dirNames = get_dirnames("HeadPhones", hpCategory[0]) if process(get_dirnames("HeadPhones", hpCategory[0]), inputName=get_dirnames("HeadPhones", hpCategory[0]), status=0, clientAgent = "manual", inputCategory=hpCategory[0]) != 0:
nzbDir, inputName, status, inputCategory = (dirNames, dirNames, 0, sbCategory[0]) Logger.info("MAIN: A problem was reported in the autoProcessMusic script.")
if inputCategory in cpsCategory: Logger.info("MAIN: Running autoProcessComics as a manual run...")
Logger.info("MAIN: Calling CouchPotatoServer to post-process: %s", inputName) if process(get_dirnames("Mylar", mlCategory[0]), inputName=get_dirnames("Mylar", mlCategory[0]), status=0,clientAgent="manual", inputCategory=mlCategory[0]) != 0:
result = autoProcessMovie.process(nzbDir, inputName, status, clientAgent, download_id, inputCategory) Logger.info("MAIN: A problem was reported in the autoProcessComics script.")
elif inputCategory in sbCategory:
result = 0 Logger.info("MAIN: Running autoProcessGames as a manual run...")
if isinstance(nzbDir, list): if process(get_dirnames("Gamez", gzCategory[0]), inputName=get_dirnames("Gamez", gzCategory[0]), status=0,clientAgent="manual", inputCategory=gzCategory[0]) != 0:
for dirName in nzbDir: Logger.info("MAIN: A problem was reported in the autoProcessGames script.")
Logger.info("MAIN: Calling Sick-Beard to post-process: %s", inputName)
result = autoProcessTV.processEpisode(dirName, dirName, status, clientAgent, inputCategory)
if result !=0:break
else:
Logger.info("MAIN: Calling Sick-Beard to post-process: %s", inputName)
result = autoProcessTV.processEpisode(nzbDir, inputName, status, clientAgent, inputCategory)
elif inputCategory in hpCategory:
result = 0
if isinstance(nzbDir, list):
for dirName in nzbDir:
Logger.info("MAIN: Calling Headphones to post-process: %s", dirName)
result = autoProcessMusic.process(dirName, dirName, status, clientAgent, inputCategory)
if result != 0: break
else:
Logger.info("MAIN: Calling HeadPhones to post-process: %s", inputName)
result = autoProcessMusic.process(nzbDir, inputName, status, clientAgent, inputCategory)
elif inputCategory in mlCategory:
Logger.info("MAIN: Calling Mylar to post-process: %s", inputName)
result = autoProcessComics.processEpisode(nzbDir, inputName, status, inputCategory)
elif inputCategory in gzCategory:
Logger.info("MAIN: Calling Gamez to post-process: %s", inputName)
result = autoProcessGames.process(nzbDir, inputName, status, inputCategory)
else:
Logger.warning("MAIN: The download category %s does not match any category defined in autoProcessMedia.cfg. Exiting.", inputCategory)
sys.exit(POSTPROCESS_ERROR)
if result == 0: if result == 0:
Logger.info("MAIN: The autoProcess* script completed successfully.") Logger.info("MAIN: The nzbToMedia script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_SUCCESS) sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
else: else:
Logger.info("MAIN: A problem was reported in the autoProcess* script.") Logger.info("MAIN: A problem was reported in the nzbToMedia script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)

View file

@ -1,38 +0,0 @@
import os
import ConfigParser
# init paths
MY_FULLNAME = os.path.normpath(os.path.abspath(__file__))
MY_NAME = os.path.basename(MY_FULLNAME)
PROG_DIR = os.path.dirname(MY_FULLNAME)
# init config file names
CONFIG_FILE = os.path.join(PROG_DIR, "autoProcessMedia.cfg")
SAMPLE_CONFIG_FILE = os.path.join(PROG_DIR, "autoProcessMedia.cfg.sample")
MOVIE_CONFIG_FILE = os.path.join(PROG_DIR, "autoProcessMovie.cfg")
TV_CONFIG_FILE = os.path.join(PROG_DIR, "autoProcessTv.cfg")
LOG_FILE = os.path.join(PROG_DIR, "postprocess.log")
class config(object):
# link error handling classes
Error = ConfigParser.Error
NoSectionError = ConfigParser.NoSectionError
NoOptionError = ConfigParser.NoOptionError
DuplicateSectionError = ConfigParser.DuplicateSectionError
InterpolationError = ConfigParser.InterpolationError
InterpolationMissingOptionError = ConfigParser.InterpolationMissingOptionError
InterpolationSyntaxError = ConfigParser.InterpolationSyntaxError
InterpolationDepthError = ConfigParser.InterpolationDepthError
ParsingError = ConfigParser.ParsingError
MissingSectionHeaderError = ConfigParser.MissingSectionHeaderError
def __new__(cls, *file):
if not file:
file = CONFIG_FILE
# load config
config = ConfigParser.ConfigParser()
config.optionxform = str
if config.read(file):
return config

View file

@ -60,25 +60,32 @@
### NZBGET POST-PROCESSING SCRIPT ### ### NZBGET POST-PROCESSING SCRIPT ###
############################################################################## ##############################################################################
# Exit codes used by NZBGet
import logging import logging
import os
import sys
from nzbtomedia.autoProcess.autoProcessComics import autoProcessComics
from nzbtomedia.migratecfg import migratecfg
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import nzbtomedia_configure_logging, WakeUp, get_dirnames
import autoProcess.migratecfg as migratecfg # run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
import autoProcess.autoProcessComics as autoProcessComics if migratecfg().migrate():
from autoProcess.nzbToMediaEnv import *
from autoProcess.nzbToMediaUtil import *
#check to migrate old cfg before trying to load.
if os.path.isfile(os.path.join(os.path.dirname(sys.argv[0]), "autoProcessMedia.cfg.sample")):
migratecfg.migrate()
# check to write settings from nzbGet UI to autoProcessMedia.cfg. # check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'): if os.environ.has_key('NZBOP_SCRIPTDIR'):
migratecfg.addnzbget() migratecfg().addnzbget()
nzbtomedia_configure_logging(LOG_FILE) nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__) Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log Logger.info("====================") # Seperate old from new log
Logger.info("nzbToMylar %s", VERSION) Logger.info("nzbToMylar %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
# mylar category
mlCategory = (config().get("Mylar", "mlCategory")).split(',') # tv
WakeUp() WakeUp()
@ -87,25 +94,18 @@ WakeUp()
if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5] < '11.0': 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.info("MAIN: Script triggered from NZBGet (11.0 or later).")
# NZBGet argv: all passed as environment variables.
# Exit codes used by NZBGet
POSTPROCESS_PARCHECK=92
POSTPROCESS_SUCCESS=93
POSTPROCESS_ERROR=94
POSTPROCESS_NONE=95
# Check nzbget.conf options # Check nzbget.conf options
status = 0 status = 0
if os.environ['NZBOP_UNPACK'] != 'yes': if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting") Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)
# Check par status # Check par status
if os.environ['NZBPP_PARSTATUS'] == '3': if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting") Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.") Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(POSTPROCESS_NONE) sys.exit(config.NZBGET_POSTPROCESS_NONE)
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4': if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"") Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
@ -135,9 +135,9 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
# All checks done, now launching the script. # All checks done, now launching the script.
Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessComics...") Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessComics...")
result = autoProcessComics.processEpisode(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBNAME'], status) result = autoProcessComics().processEpisode(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBNAME'], status)
# SABnzbd Pre 0.7.17 # SABnzbd Pre 0.7.17
elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS: elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -147,9 +147,9 @@ elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS:
# 6 Group that the NZB was posted in e.g. alt.binaries.x # 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 # 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.info("MAIN: Script triggered from SABnzbd, starting autoProcessComics...")
result = autoProcessComics.processEpisode(sys.argv[1], sys.argv[3], sys.argv[7]) result = autoProcessComics().processEpisode(sys.argv[1], sys.argv[3], sys.argv[7])
# SABnzbd 0.7.17+ # SABnzbd 0.7.17+
elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS: elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -160,17 +160,23 @@ elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS:
# 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2 # 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2
# 8 Failure URL # 8 Failure URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessComics...") Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessComics...")
result = autoProcessComics.processEpisode(sys.argv[1], sys.argv[3], sys.argv[7]) result = autoProcessComics().processEpisode(sys.argv[1], sys.argv[3], sys.argv[7])
else: else:
result = 0
Logger.warn("MAIN: Invalid number of arguments received from client.") Logger.warn("MAIN: Invalid number of arguments received from client.")
Logger.info("MAIN: Running autoProcessComics as a manual run...") Logger.info("MAIN: Running autoProcessComics as a manual run...")
result = autoProcessComics.processEpisode('Manual Run', 'Manual Run', 0)
for dirName in get_dirnames("Mylar", mlCategory[0]):
Logger.info("MAIN: Calling Mylar to post-process: %s", dirName)
result = autoProcessComics().processEpisode(dirName, dirName, 0)
if result != 0: break
if result == 0: if result == 0:
Logger.info("MAIN: The autoProcessComics script completed successfully.") Logger.info("MAIN: The autoProcessComics script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_SUCCESS) sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
else: else:
Logger.info("MAIN: A problem was reported in the autoProcessComics script.") Logger.info("MAIN: A problem was reported in the autoProcessComics script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)

View file

@ -123,33 +123,31 @@
### NZBGET POST-PROCESSING SCRIPT ### ### NZBGET POST-PROCESSING SCRIPT ###
############################################################################## ##############################################################################
import os
import sys
import logging import logging
from nzbtomedia.autoProcess.autoProcessTV import autoProcessTV
from nzbtomedia.migratecfg import migratecfg
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import nzbtomedia_configure_logging, WakeUp, get_dirnames
import autoProcess.migratecfg as migratecfg # run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
import autoProcess.autoProcessTV as autoProcessTV if migratecfg().migrate():
from autoProcess.nzbToMediaEnv import *
from autoProcess.nzbToMediaUtil import *
# NZBGet argv: all passed as environment variables.
# Exit codes used by NZBGet
POSTPROCESS_PARCHECK = 92
POSTPROCESS_SUCCESS = 93
POSTPROCESS_ERROR = 94
POSTPROCESS_NONE = 95
#check to migrate old cfg before trying to load.
if os.path.isfile(os.path.join(os.path.dirname(sys.argv[0]), "autoProcessMedia.cfg.sample")):
migratecfg.migrate()
# check to write settings from nzbGet UI to autoProcessMedia.cfg. # check to write settings from nzbGet UI to autoProcessMedia.cfg.
if os.environ.has_key('NZBOP_SCRIPTDIR'): if os.environ.has_key('NZBOP_SCRIPTDIR'):
migratecfg.addnzbget() migratecfg().addnzbget()
nzbtomedia_configure_logging(LOG_FILE) nzbtomedia_configure_logging(config.LOG_FILE)
Logger = logging.getLogger(__name__) Logger = logging.getLogger(__name__)
Logger.info("====================") # Seperate old from new log Logger.info("====================") # Seperate old from new log
Logger.info("nzbToSickBeard %s", VERSION) Logger.info("nzbToSickBeard %s", config.NZBTOMEDIA_VERSION)
Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
else:
sys.exit(-1)
# sickbeard category
sbCategory = (config().get("SickBeard", "sbCategory")).split(',') # tv
WakeUp() WakeUp()
@ -163,13 +161,13 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
if os.environ['NZBOP_UNPACK'] != 'yes': if os.environ['NZBOP_UNPACK'] != 'yes':
Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting") Logger.error("MAIN: Please enable option \"Unpack\" in nzbget configuration file, exiting")
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)
# Check par status # Check par status
if os.environ['NZBPP_PARSTATUS'] == '3': if os.environ['NZBPP_PARSTATUS'] == '3':
Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting") Logger.warning("MAIN: Par-check successful, but Par-repair disabled, exiting")
Logger.info("MAIN: Please check your Par-repair settings for future downloads.") Logger.info("MAIN: Please check your Par-repair settings for future downloads.")
sys.exit(POSTPROCESS_NONE) sys.exit(config.NZBGET_POSTPROCESS_NONE)
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4': if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_PARSTATUS'] == '4':
Logger.warning("MAIN: Par-repair failed, setting status \"failed\"") Logger.warning("MAIN: Par-repair failed, setting status \"failed\"")
@ -200,9 +198,9 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
# All checks done, now launching the script. # All checks done, now launching the script.
Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessTV...") Logger.info("MAIN: Script triggered from NZBGet, starting autoProcessTV...")
clientAgent = "nzbget" clientAgent = "nzbget"
result = autoProcessTV.processEpisode(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBFILENAME'], status, clientAgent, os.environ['NZBPP_CATEGORY']) result = autoProcessTV().processEpisode(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBFILENAME'], status, clientAgent, os.environ['NZBPP_CATEGORY'])
# SABnzbd Pre 0.7.17 # SABnzbd Pre 0.7.17
elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS: elif len(sys.argv) == config.SABNZB_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -213,9 +211,9 @@ elif len(sys.argv) == SABNZB_NO_OF_ARGUMENTS:
# 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2 # 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.info("MAIN: Script triggered from SABnzbd, starting autoProcessTV...")
clientAgent = "sabnzbd" clientAgent = "sabnzbd"
result = autoProcessTV.processEpisode(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5]) result = autoProcessTV().processEpisode(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
# SABnzbd 0.7.17+ # SABnzbd 0.7.17+
elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS: elif len(sys.argv) >= config.SABNZB_0717_NO_OF_ARGUMENTS:
# SABnzbd argv: # SABnzbd argv:
# 1 The final directory of the job (full path) # 1 The final directory of the job (full path)
# 2 The original name of the NZB file # 2 The original name of the NZB file
@ -227,24 +225,23 @@ elif len(sys.argv) >= SABNZB_0717_NO_OF_ARGUMENTS:
# 8 Failure URL # 8 Failure URL
Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessTV...") Logger.info("MAIN: Script triggered from SABnzbd 0.7.17+, starting autoProcessTV...")
clientAgent = "sabnzbd" clientAgent = "sabnzbd"
result = autoProcessTV.processEpisode(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5]) result = autoProcessTV().processEpisode(sys.argv[1], sys.argv[2], sys.argv[7], clientAgent, sys.argv[5])
else: else:
result = 0 result = 0
sbCategory = (config().get("SickBeard", "sbCategory")).split(',') # tv
dirNames = get_dirnames("SickBeard", sbCategory[0])
Logger.debug("MAIN: Invalid number of arguments received from client.") Logger.debug("MAIN: Invalid number of arguments received from client.")
Logger.info("MAIN: Running autoProcessTV as a manual run...") Logger.info("MAIN: Running autoProcessTV as a manual run...")
for dirName in dirNames: for dirName in get_dirnames("SickBeard", sbCategory[0]):
Logger.info("MAIN: Calling Sick-Beard to post-process: %s", dirName) Logger.info("MAIN: Calling Sick-Beard to post-process: %s", dirName)
result = autoProcessTV.processEpisode(dirName, dirName, 0) result = autoProcessTV().processEpisode(dirName, dirName, 0)
if result != 0: break if result != 0: break
if result == 0: if result == 0:
Logger.info("MAIN: The autoProcessTV script completed successfully.") Logger.info("MAIN: The autoProcessTV script completed successfully.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_SUCCESS) sys.exit(config.NZBGET_POSTPROCESS_SUCCESS)
else: else:
Logger.info("MAIN: A problem was reported in the autoProcessTV script.") Logger.info("MAIN: A problem was reported in the autoProcessTV script.")
if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11
sys.exit(POSTPROCESS_ERROR) sys.exit(config.NZBGET_POSTPROCESS_ERROR)

144
nzbtomedia/Transcoder.py Normal file
View file

@ -0,0 +1,144 @@
import errno
import logging
import os
import sys
from subprocess import call
from nzbtomedia.nzbToMediaConfig import config
class Transcoder:
def Transcode_directory(self, dirName):
Logger = logging.getLogger()
if os.name == 'nt':
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)
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)
return 1 # failure
else:
ffmpeg = 'ffmpeg'
else:
ffmpeg = 'ffmpeg'
useNiceness = True
Logger.info("Loading config from %s", config.CONFIG_FILE)
if not config():
Logger.error("You need an autoProcessMedia.cfg file - did you rename and edit the .sample?")
return 1 # failure
mediaContainer = (config().get("Extensions", "mediaExtensions")).split(',')
duplicate = int(config().get("Transcoder", "duplicate"))
ignoreExtensions = (config().get("Transcoder", "ignoreExtensions")).split(',')
outputVideoExtension = config().get("Transcoder", "outputVideoExtension").strip()
outputVideoCodec = config().get("Transcoder", "outputVideoCodec").strip()
outputVideoPreset = config().get("Transcoder", "outputVideoPreset").strip()
outputVideoFramerate = config().get("Transcoder", "outputVideoFramerate").strip()
outputVideoBitrate = config().get("Transcoder", "outputVideoBitrate").strip()
outputAudioCodec = config().get("Transcoder", "outputAudioCodec").strip()
outputAudioBitrate = config().get("Transcoder", "outputAudioBitrate").strip()
outputSubtitleCodec = config().get("Transcoder", "outputSubtitleCodec").strip()
outputFastStart = int(config().get("Transcoder", "outputFastStart"))
outputQualityPercent = int(config().get("Transcoder", "outputQualityPercent"))
niceness = None
if useNiceness:niceness = int(config().get("Transcoder", "niceness"))
map(lambda ext: ext.strip(), mediaContainer)
map(lambda ext: ext.strip(), ignoreExtensions)
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:
filePath = os.path.join(dirpath, file)
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)
continue
if ext == outputVideoExtension: # we need to change the name to prevent overwriting itself.
outputVideoExtension = '-transcoded' + outputVideoExtension # adds '-transcoded.ext'
newfilePath = os.path.normpath(name + outputVideoExtension)
command = [ffmpeg, '-loglevel', 'warning', '-i', filePath, '-map', '0'] # -map 0 takes all input streams
if useNiceness:
command = ['nice', '-%d' % niceness] + command
if len(outputVideoCodec) > 0:
command.append('-c:v')
command.append(outputVideoCodec)
if outputVideoCodec == 'libx264' and outputVideoPreset:
command.append('-preset')
command.append(outputVideoPreset)
else:
command.append('-c:v')
command.append('copy')
if len(outputVideoFramerate) > 0:
command.append('-r')
command.append(str(outputVideoFramerate))
if len(outputVideoBitrate) > 0:
command.append('-b:v')
command.append(str(outputVideoBitrate))
if len(outputAudioCodec) > 0:
command.append('-c:a')
command.append(outputAudioCodec)
if outputAudioCodec == 'aac': # Allow users to use the experimental AAC codec that's built into recent versions of ffmpeg
command.append('-strict')
command.append('-2')
else:
command.append('-c:a')
command.append('copy')
if len(outputAudioBitrate) > 0:
command.append('-b:a')
command.append(str(outputAudioBitrate))
if outputFastStart > 0:
command.append('-movflags')
command.append('+faststart')
if outputQualityPercent > 0:
command.append('-q:a')
command.append(str(outputQualityPercent))
if len(outputSubtitleCodec) > 0: # Not every subtitle codec can be used for every video container format!
command.append('-c:s')
command.append(outputSubtitleCodec) # http://en.wikibooks.org/wiki/FFMPEG_An_Intermediate_Guide/subtitle_options
else:
command.append('-sn') # Don't copy the subtitles over
command.append(newfilePath)
try: # Try to remove the file that we're transcoding to just in case. (ffmpeg will return an error if it already exists for some reason)
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)
except Exception, e:
Logger.debug("Error when removing transcoding target: %s", e)
Logger.info("Transcoding video: %s", file)
cmd = ""
for item in command:
cmd = cmd + " " + item
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)
if result == 0:
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)
# 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,72 @@
import logging
import urllib
import requests
import socket
import time
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import convert_to_ascii
Logger = logging.getLogger()
class autoProcessComics:
def processEpisode(self, dirName, nzbName=None, status=0, clientAgent='manual', inputCategory=None):
if dirName is None:
Logger.error("No directory was given!")
return 1 # failure
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
Logger.info("Loading config from %s", config.CONFIG_FILE)
section = "Mylar"
if inputCategory != None and config().has_section(inputCategory):
section = inputCategory
host = config().get(section, "host")
port = config().get(section, "port")
username = config().get(section, "username")
password = config().get(section, "password")
try:
ssl = int(config().get(section, "ssl"))
except (config.NoOptionError, ValueError):
ssl = 0
try:
web_root = config().get(section, "web_root")
except config.NoOptionError:
web_root = ""
try:
watch_dir = config().get(section, "watch_dir")
except config.NoOptionError:
watch_dir = ""
params = {}
nzbName, dirName = convert_to_ascii(nzbName, dirName)
if dirName == "Manual Run" and watch_dir != "":
dirName = watch_dir
params['nzb_folder'] = dirName
if nzbName != None:
params['nzb_name'] = nzbName
if ssl:
protocol = "https://"
else:
protocol = "http://"
url = protocol + host + ":" + port + web_root + "/post_process?" + urllib.urlencode(params)
Logger.debug("Opening URL: %s", url)
try:
r = requests.get(url, auth=(username, password))
except requests.ConnectionError:
Logger.exception("Unable to open URL")
return 1 # failure
if r.ok:
Logger.info("%s", r.content)
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

@ -0,0 +1,72 @@
import json
import logging
import socket
import requests
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import convert_to_ascii
Logger = logging.getLogger()
class autoProcessGames:
def process(self, dirName, nzbName=None, status=0, clientAgent='manual', inputCategory=None):
if dirName is None:
Logger.error("No directory was given!")
return 1 # failure
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
Logger.info("Loading config from %s", config.CONFIG_FILE)
status = int(status)
section = "Gamez"
if inputCategory != None and config().has_section(inputCategory):
section = inputCategory
host = config().get(section, "host")
port = config().get(section, "port")
apikey = config().get(section, "apikey")
try:
ssl = int(config().get(section, "ssl"))
except (config.NoOptionError, ValueError):
ssl = 0
try:
web_root = config().get(section, "web_root")
except config.NoOptionError:
web_root = ""
if ssl:
protocol = "https://"
else:
protocol = "http://"
nzbName, dirName = convert_to_ascii(nzbName, dirName)
baseURL = protocol + host + ":" + port + web_root + "/api?api_key=" + apikey + "&mode="
fields = nzbName.split("-")
gamezID = fields[0].replace("[","").replace("]","").replace(" ","")
downloadStatus = 'Wanted'
if status == 0:
downloadStatus = 'Downloaded'
url = baseURL + "UPDATEREQUESTEDSTATUS&db_id=" + gamezID + "&status=" + downloadStatus
Logger.debug("Opening URL: %s", url)
try:
r = requests.get(url)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
return 1 # failure
result = json.load(r.content)
Logger.info("Gamez returned %s", result)
if result['success']:
Logger.info("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)
return 1 # failure

View file

@ -0,0 +1,324 @@
import time
import datetime
import logging
import socket
import urllib
import requests
import shutil
import json
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()
class autoProcessMovie:
def get_imdb(self, nzbName, dirName):
imdbid = ""
a = nzbName.find('.cp(') + 4 #search for .cptt( in nzbName
b = nzbName[a:].find(')') + a
if a > 3: # a == 3 if not exist
imdbid = nzbName[a:b]
if imdbid:
Logger.info("Found movie id %s in name", imdbid)
return imdbid
a = dirName.find('.cp(') + 4 #search for .cptt( in dirname
b = dirName[a:].find(')') + a
if a > 3: # a == 3 if not exist
imdbid = dirName[a:b]
if imdbid:
Logger.info("Found movie id %s in directory", imdbid)
return imdbid
else:
Logger.debug("Could not find an imdb id in directory or name")
return ""
def get_movie_info(self, baseURL, imdbid, download_id):
movie_id = ""
movie_status = None
release_status = None
if not imdbid and not download_id:
return movie_id, imdbid, download_id, movie_status, release_status
releaselist = []
movieid = []
moviestatus = []
library = []
release = []
offset = int(0)
while True:
url = baseURL + "media.list/?status=active&release_status=snatched&limit_offset=50," + str(offset)
Logger.debug("Opening URL: %s", url)
try:
r = requests.get(url)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
break
movieid2 = []
library2 = []
release2 = []
moviestatus2 = []
try:
result = json.load(r.content)
movieid2 = [item["_id"] for item in result["movies"]]
for item in result["movies"]:
if "identifier" in item:
library2.append(item["identifier"])
else:
library2.append(item["identifiers"]["imdb"])
release2 = [item["releases"] for item in result["movies"]]
moviestatus2 = [item["status"] for item in result["movies"]]
except:
Logger.exception("Unable to parse json data for movies")
break
movieid.extend(movieid2)
moviestatus.extend(moviestatus2)
library.extend(library2)
release.extend(release2)
if len(movieid2) < int(50): # finished parsing list of movies. Time to break.
break
offset = offset + 50
result = None # reset
for index in range(len(movieid)):
releaselist1 = [item for item in release[index] if item["status"] == "snatched" and "download_info" in item]
if download_id:
releaselist = [item for item in releaselist1 if item["download_info"]["id"].lower() == download_id.lower()]
else:
releaselist = releaselist1
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)
if not download_id and len(releaselist) == 1:
download_id = releaselist[0]["download_info"]["id"]
elif not imdbid and download_id and len(releaselist) > 0:
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)
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)
break
if not movie_id:
Logger.exception("Could not parse database results to determine imdbid or movie id")
return movie_id, imdbid, download_id, movie_status, release_status
def get_status(self, baseURL, movie_id, download_id):
result = None
movie_status = None
release_status = None
if not movie_id:
return movie_status, release_status
Logger.debug("Looking for status of movie: %s", movie_id)
url = baseURL + "media.get/?id=" + str(movie_id)
Logger.debug("Opening URL: %s", url)
try:
r = requests.get(url)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
return None, None
try:
result = json.load(r.content)
movie_status = str(result["media"]["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")
try:
if len(result["media"]["releases"]) == 1 and result["media"]["releases"][0]["status"] == "done":
release_status = result["media"]["releases"][0]["status"]
else:
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)
except: # index out of range/doesn't exist?
Logger.exception("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!")
return 1 # failure
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
Logger.info("Loading config from %s", config.CONFIG_FILE)
status = int(status)
section = "CouchPotato"
if inputCategory != None and config().has_section(inputCategory):
section = inputCategory
host = config().get(section, "host")
port = config().get(section, "port")
apikey = config().get(section, "apikey")
delay = float(config().get(section, "delay"))
method = config().get(section, "method")
delete_failed = int(config().get(section, "delete_failed"))
wait_for = int(config().get(section, "wait_for"))
try:
TimePerGiB = int(config().get(section, "TimePerGiB"))
except (config.NoOptionError, ValueError):
TimePerGiB = 60 # note, if using Network to transfer on 100Mbit LAN, expect ~ 600 MB/minute.
try:
ssl = int(config().get(section, "ssl"))
except (config.NoOptionError, ValueError):
ssl = 0
try:
web_root = config().get(section, "web_root")
except config.NoOptionError:
web_root = ""
try:
transcode = int(config().get("Transcoder", "transcode"))
except (config.NoOptionError, ValueError):
transcode = 0
try:
remoteCPS = int(config().get(section, "remoteCPS"))
except (config.NoOptionError, ValueError):
remoteCPS = 0
nzbName = str(nzbName) # make sure it is a string
imdbid = self.get_imdb(nzbName, dirName)
if ssl:
protocol = "https://"
else:
protocol = "http://"
# don't delay when we are calling this script manually.
if clientAgent == "manual":
delay = 0
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.
process_all_exceptions(nzbName.lower(), dirName)
nzbName, dirName = convert_to_ascii(nzbName, dirName)
if status == 0:
if transcode == 1:
result = Transcoder().Transcode_directory(dirName)
if result == 0:
Logger.debug("Transcoding succeeded for files in %s", dirName)
else:
Logger.warning("Transcoding failed for files in %s", dirName)
if method == "manage":
command = "manage.update"
else:
command = "renamer.scan"
if clientAgent != "manual" and download_id != None:
if remoteCPS == 1:
command = command + "/?downloader=" + clientAgent + "&download_id=" + download_id
else:
command = command + "/?media_folder=" + urllib.quote(dirName) + "&downloader=" + clientAgent + "&download_id=" + download_id
dirSize = getDirectorySize(dirName) # get total directory size to calculate needed processing time.
TIME_OUT2 = int(TimePerGiB) * dirSize # Couchpotato needs to complete all moving and renaming before returning the status.
TIME_OUT2 += 60 # Add an extra minute for over-head/processing/metadata.
socket.setdefaulttimeout(int(TIME_OUT2)) #initialize socket timeout. We may now be able to remove the delays from the wait_for section below? If true, this should exit on first loop.
url = baseURL + command
Logger.info("Waiting for %s seconds to allow CPS to process newly extracted files", str(delay))
time.sleep(delay)
Logger.debug("Opening URL: %s", url)
try:
r = requests.get(url)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
return 1 # failure
result = json.load(r.content)
Logger.info("CouchPotatoServer returned %s", result)
if result['success']:
Logger.info("%s scan started on CouchPotatoServer for %s", method, nzbName)
else:
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")
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")
return 1 # failure
url = baseURL + "movie.searcher.try_next/?media_id=" + movie_id
Logger.debug("Opening URL: %s", url)
try:
r = requests.get(url)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
return 1 # failure
Logger.info("%s", r.content)
Logger.info("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)
try:
shutil.rmtree(dirName)
except:
Logger.exception("Unable to delete folder %s", dirName)
return 0 # success
if clientAgent == "manual":
return 0 # success
if not download_id:
return 1 # just to be sure TorrentToMedia doesn't start deleting files as we havent verified changed status.
# 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)
return 0 # success
datetime.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)
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)
return 1 # failure

View file

@ -0,0 +1,100 @@
import datetime
import logging
import socket
import requests
from nzbtomedia.nzbToMediaConfig import config
from nzbtomedia.nzbToMediaUtil import convert_to_ascii, getDirectorySize
Logger = logging.getLogger()
class autoProcessMusic:
def process(self, dirName, nzbName=None, status=0, clientAgent="manual", inputCategory=None):
if dirName is None:
Logger.error("No directory was given!")
return 1 # failure
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
Logger.info("Loading config from %s", config.CONFIG_FILE)
status = int(status)
section = "HeadPhones"
if inputCategory != None and config().has_section(inputCategory):
section = inputCategory
host = config().get(section, "host")
port = config().get(section, "port")
apikey = config().get(section, "apikey")
delay = float(config().get(section, "delay"))
try:
ssl = int(config().get(section, "ssl"))
except (config.NoOptionError, ValueError):
ssl = 0
try:
web_root = config().get(section, "web_root")
except config.NoOptionError:
web_root = ""
try:
TimePerGiB = int(config().get(section, "TimePerGiB"))
except (config.NoOptionError, ValueError):
TimePerGiB = 60 # note, if using Network to transfer on 100Mbit LAN, expect ~ 600 MB/minute.
if ssl:
protocol = "https://"
else:
protocol = "http://"
# don't delay when we are calling this script manually.
if clientAgent == "manual":
delay = 0
nzbName, dirName = convert_to_ascii(nzbName, dirName)
dirSize = getDirectorySize(dirName) # get total directory size to calculate needed processing time.
TIME_OUT = int(TimePerGiB) * dirSize # HeadPhones needs to complete all moving/transcoding and renaming before returning the status.
TIME_OUT += 60 # Add an extra minute for over-head/processing/metadata.
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
baseURL = protocol + host + ":" + port + web_root + "/api?apikey=" + apikey + "&cmd="
if status == 0:
command = "forceProcess"
url = baseURL + command
Logger.info("Waiting for %s seconds to allow HeadPhones to process newly extracted files", str(delay))
datetime.time.sleep(delay)
Logger.debug("Opening URL: %s", url)
try:
r = requests.get(url)
except requests.ConnectionError:
Logger.exception("Unable to open URL")
return 1 # failure
Logger.info("HeadPhones returned %s", r.content)
if r.content[0] == "OK":
Logger.info("%s started on HeadPhones for %s", command, nzbName)
else:
Logger.error("%s has NOT started on HeadPhones for %s. Exiting", command, nzbName)
return 1 # failure
else:
Logger.info("The download failed. Nothing to process")
return 0 # Success (as far as this script is concerned)
if nzbName == "Manual Run":
return 0 # success
# we will now wait 1 minutes for this album to be processed before returning to TorrentToMedia and unpausing.
## Hopefully we can use a "getHistory" check in here to confirm processing complete...
start = datetime.datetime.now() # set time for timeout
while (datetime.datetime.now() - start) < datetime.timedelta(minutes=1): # only wait 2 minutes, then return to TorrentToMedia
datetime.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")
# return 1 # failure
return 0 # success for now.

View file

@ -0,0 +1,188 @@
import copy
import logging
import os
import socket
import urllib
import requests
import time
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()
class autoProcessTV:
def processEpisode(self, dirName, nzbName=None, failed=False, clientAgent = "manual", inputCategory=None):
if dirName is None:
Logger.error("No directory was given!")
return 1 # failure
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
Logger.info("Loading config from %s", config.CONFIG_FILE)
status = int(failed)
section = "SickBeard"
if inputCategory != None and config().has_section(inputCategory):
section = inputCategory
host = config().get(section, "host")
port = config().get(section, "port")
username = config().get(section, "username")
password = config().get(section, "password")
try:
ssl = int(config().get(section, "ssl"))
except (config.NoOptionError, ValueError):
ssl = 0
try:
web_root = config().get(section, "web_root")
except config.NoOptionError:
web_root = ""
try:
watch_dir = config().get(section, "watch_dir")
except config.NoOptionError:
watch_dir = ""
try:
transcode = int(config().get("Transcoder", "transcode"))
except (config.NoOptionError, ValueError):
transcode = 0
try:
delete_failed = int(config().get(section, "delete_failed"))
except (config.NoOptionError, ValueError):
delete_failed = 0
try:
delay = float(config().get(section, "delay"))
except (config.NoOptionError, ValueError):
delay = 0
try:
TimePerGiB = int(config().get(section, "TimePerGiB"))
except (config.NoOptionError, ValueError):
TimePerGiB = 60 # note, if using Network to transfer on 100Mbit LAN, expect ~ 600 MB/minute.
try:
SampleIDs = (config().get("Extensions", "SampleIDs")).split(',')
except (config.NoOptionError, ValueError):
SampleIDs = ['sample','-s.']
try:
nzbExtractionBy = config().get(section, "nzbExtractionBy")
except (config.NoOptionError, ValueError):
nzbExtractionBy = "Downloader"
try:
process_method = config().get(section, "process_method")
except config.NoOptionError:
process_method = None
mediaContainer = (config().get("Extensions", "mediaExtensions")).split(',')
minSampleSize = int(config().get("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]
SpecificPath = os.path.join(dirName, str(nzbName))
cleanName = os.path.splitext(SpecificPath)
if cleanName[1] == ".nzb":
SpecificPath = cleanName[0]
if os.path.isdir(SpecificPath):
dirName = SpecificPath
# auto-detect fork type
fork, params = autoFork(section)
if fork not in config.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)
# Now check if tv files exist in destination. Eventually extraction may be done here if nzbExtractionBy == TorrentToMedia
video = int(0)
for dirpath, dirnames, filenames in os.walk(dirName):
for file in filenames:
filePath = os.path.join(dirpath, file)
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)
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)
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)
status = int(1)
failed = True
dirSize = getDirectorySize(dirName) # get total directory size to calculate needed processing time.
TIME_OUT = int(TimePerGiB) * dirSize # SickBeard needs to complete all moving and renaming before returning the log sequence via url.
TIME_OUT += 60 # Add an extra minute for over-head/processing/metadata.
socket.setdefaulttimeout(int(config.NZBTOMEDIA_TIMEOUT)) #initialize socket timeout.
# configure SB params to pass
params['quiet'] = 1
if nzbName is not None:
params['nzbName'] = nzbName
for param in copy.copy(params):
if param == "failed":
params[param] = failed
if param in ["dirName", "dir"]:
params[param] = dirName
if param == "process_method":
if process_method:
params[param] = process_method
else:
del params[param]
# delete any unused params so we don't pass them to SB by mistake
[params.pop(k) for k,v in params.items() if v is None]
if status == 0:
Logger.info("The download succeeded. Sending process request to SickBeard's %s branch", fork)
elif fork in config.SICKBEARD_FAILED:
Logger.info("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)
if delete_failed and os.path.isdir(dirName) and not dirName in ['sys.argv[0]','/','']:
Logger.info("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)
else:
Logger.warning("Transcoding failed for files in %s", dirName)
if ssl:
protocol = "https://"
else:
protocol = "http://"
url = protocol + host + ":" + port + web_root + "/home/postprocess/processEpisode?" + urllib.urlencode(params)
if clientAgent == "manual":delay = 0
Logger.info("Waiting for %s seconds to allow SB to process newly extracted files", str(delay))
time.sleep(delay)
Logger.debug("Opening URL: %s", url)
try:
r = requests.get(url, auth=(username, password))
except requests.ConnectionError:
Logger.exception("Unable to open URL")
return 1 # failure
Logger.info("%s", r.content)
if status != 0 and delete_failed and not dirName in ['sys.argv[0]','/','']:
delete(dirName)
return 0 # Success

View file

@ -1,9 +1,9 @@
import sys import sys
import logging import logging
from nzbToMediaConfig import *
from subprocess import call, Popen from subprocess import call, Popen
from autoProcess.nzbToMediaUtil import create_destination
from nzbtomedia.nzbToMediaConfig import *
from nzbtomedia.nzbToMediaUtil import create_destination
Logger = logging.getLogger() Logger = logging.getLogger()
@ -111,7 +111,7 @@ def extract(filePath, outputDestination):
# Create outputDestination folder # Create outputDestination folder
create_destination(outputDestination) create_destination(outputDestination)
Logger.info("MAIN: Loading config from %s", CONFIG_FILE) Logger.info("MAIN: Loading config from %s", config.CONFIG_FILE)
passwordsfile = config().get("passwords", "PassWordFile") passwordsfile = config().get("passwords", "PassWordFile")
if passwordsfile != "" and os.path.isfile(os.path.normpath(passwordsfile)): if passwordsfile != "" and os.path.isfile(os.path.normpath(passwordsfile)):

244
nzbtomedia/migratecfg.py Normal file
View file

@ -0,0 +1,244 @@
import os
import shutil
from nzbtomedia.nzbToMediaConfig import config
class migratecfg:
def migrate(self):
categories = []
# check for autoProcessMedia.cfg and autoProcessMedia.cfg.sample and if they don't exist return and fail
if not config() and not config(config.SAMPLE_CONFIG_FILE):
return False
# check for autoProcessMedia.cfg and create if it does not exist
if not config(config.CONFIG_FILE):
shutil.copyfile(config.SAMPLE_CONFIG_FILE, config.CONFIG_FILE)
configold = config(config.CONFIG_FILE)
# check for autoProcessMedia.cfg.sample and create if it does not exist
if not config(config.SAMPLE_CONFIG_FILE):
shutil.copyfile(config.CONFIG_FILE, config.SAMPLE_CONFIG_FILE)
confignew = config(config.SAMPLE_CONFIG_FILE)
section = "CouchPotato"
for option, value in configold.items(section) or config(config.MOVIE_CONFIG_FILE).items(section):
if option == "category": # change this old format
option = "cpsCategory"
if option == "outputDirectory": # move this to new location format
value = os.path.split(os.path.normpath(value))[0]
confignew.set("Torrent", option, value)
continue
if option in ["username", "password" ]: # these are no-longer needed.
continue
if option == "cpsCategory":
categories.extend(value.split(','))
confignew.set(section, option, value)
section = "SickBeard"
for option, value in configold.items(section) or config(config.TV_CONFIG_FILE).items(section):
if option == "category": # change this old format
option = "sbCategory"
if option == "wait_for": # remove old format
continue
if option == "failed_fork": # change this old format
option = "fork"
if value not in ["default", "failed", "failed-torrent", "auto"]:
value = "auto"
if option == "fork" and value not in ["default", "failed", "failed-torrent", "auto"]:
value = "auto"
if option == "outputDirectory": # move this to new location format
value = os.path.split(os.path.normpath(value))[0]
confignew.set("Torrent", option, value)
continue
if option == "sbCategory":
categories.extend(value.split(','))
confignew.set(section, option, value)
for section in configold.sections():
try:
for option, value in configold.items(section):
if section == "HeadPhones":
if option in ["username", "password" ]:
continue
if option == "hpCategory":
categories.extend(value.split(','))
confignew.set(section, option, value)
if section == "Mylar":
if option in "mlCategory":
categories.extend(value.split(','))
confignew.set(section, option, value)
if section == "Gamez":
if option in ["username", "password" ]: # these are no-longer needed.
continue
if option == "gzCategory":
categories.extend(value.split(','))
confignew.set(section, option, value)
if section == "Torrent":
if option in ["compressedExtensions", "mediaExtensions", "metaExtensions", "minSampleSize"]:
section = "Extensions" # these were moved
if option == "useLink": # Sym links supported now as well.
if isinstance(value, int):
num_value = int(value)
if num_value == 1:
value = "hard"
else:
value = "no"
confignew.set(section, option, value)
if section == "Extensions":
confignew.set(section, option, value)
if section == "Transcoder":
confignew.set(section, option, value)
if section == "WakeOnLan":
confignew.set(section, option, value)
if section == "UserScript":
confignew.set(section, option, value)
if section == "ASCII":
confignew.set(section, option, value)
if section == "passwords":
confignew.set(section, option, value)
if section == "loggers":
confignew.set(section, option, value)
if section == "handlers":
confignew.set(section, option, value)
if section == "formatters":
confignew.set(section, option, value)
if section == "logger_root":
confignew.set(section, option, value)
if section == "handler_console":
confignew.set(section, option, value)
if section == "formatter_generic":
confignew.set(section, option, value)
except config.InterpolationMissingOptionError:
pass
for section in categories:
try:
if configold.items(section):
confignew.add_section(section)
for option, value in configold.items(section):
confignew.set(section, option, value)
except config.NoSectionError:
continue
# create a backup of our old config
if os.path.isfile(config.CONFIG_FILE):
cfgbak_name = config.CONFIG_FILE + ".old"
if os.path.isfile(cfgbak_name): # remove older backups
os.unlink(cfgbak_name)
os.rename(config.CONFIG_FILE, cfgbak_name)
# writing our configuration file to 'autoProcessMedia.cfg'
with open(config.CONFIG_FILE, 'wb') as configFile:
confignew.write(configFile)
return True
def addnzbget(self):
confignew = config()
section = "CouchPotato"
envKeys = ['CATEGORY', 'APIKEY', 'HOST', 'PORT', 'SSL', 'WEB_ROOT', 'DELAY', 'METHOD', 'DELETE_FAILED', 'REMOTECPS', 'WAIT_FOR', 'TIMEPERGIB']
cfgKeys = ['cpsCategory', 'apikey', 'host', 'port', 'ssl', 'web_root', 'delay', 'method', 'delete_failed', 'remoteCPS', 'wait_for', 'TimePerGiB']
for index in range(len(envKeys)):
key = 'NZBPO_CPS' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "SickBeard"
envKeys = ['CATEGORY', 'HOST', 'PORT', 'USERNAME', 'PASSWORD', 'SSL', 'WEB_ROOT', 'WATCH_DIR', 'FORK', 'DELETE_FAILED', 'DELAY', 'TIMEPERGIB', 'PROCESS_METHOD']
cfgKeys = ['sbCategory', 'host', 'port', 'username', 'password', 'ssl', 'web_root', 'watch_dir', 'fork', 'delete_failed', 'delay', 'TimePerGiB', 'process_method']
for index in range(len(envKeys)):
key = 'NZBPO_SB' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "HeadPhones"
envKeys = ['CATEGORY', 'APIKEY', 'HOST', 'PORT', 'SSL', 'WEB_ROOT', 'DELAY', 'TIMEPERGIB']
cfgKeys = ['hpCategory', 'apikey', 'host', 'port', 'ssl', 'web_root', 'delay', 'TimePerGiB']
for index in range(len(envKeys)):
key = 'NZBPO_HP' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "Mylar"
envKeys = ['CATEGORY', 'HOST', 'PORT', 'USERNAME', 'PASSWORD', 'SSL', 'WEB_ROOT']
cfgKeys = ['mlCategory', 'host', 'port', 'username', 'password', 'ssl', 'web_root']
for index in range(len(envKeys)):
key = 'NZBPO_MY' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "Gamez"
envKeys = ['CATEGORY', 'APIKEY', 'HOST', 'PORT', 'SSL', 'WEB_ROOT']
cfgKeys = ['gzCategory', 'apikey', 'host', 'port', 'ssl', 'web_root']
for index in range(len(envKeys)):
key = 'NZBPO_GZ' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "Extensions"
envKeys = ['COMPRESSEDEXTENSIONS', 'MEDIAEXTENSIONS', 'METAEXTENSIONS']
cfgKeys = ['compressedExtensions', 'mediaExtensions', 'metaExtensions']
for index in range(len(envKeys)):
key = 'NZBPO_' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "Transcoder"
envKeys = ['TRANSCODE', 'DUPLICATE', 'IGNOREEXTENSIONS', 'OUTPUTVIDEOEXTENSION', 'OUTPUTVIDEOCODEC', 'OUTPUTVIDEOPRESET', 'OUTPUTVIDEOFRAMERATE', 'OUTPUTVIDEOBITRATE', 'OUTPUTAUDIOCODEC', 'OUTPUTAUDIOBITRATE', 'OUTPUTSUBTITLECODEC']
cfgKeys = ['transcode', 'duplicate', 'ignoreExtensions', 'outputVideoExtension', 'outputVideoCodec', 'outputVideoPreset', 'outputVideoFramerate', 'outputVideoBitrate', 'outputAudioCodec', 'outputAudioBitrate', 'outputSubtitleCodec']
for index in range(len(envKeys)):
key = 'NZBPO_' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
section = "WakeOnLan"
envKeys = ['WAKE', 'HOST', 'PORT', 'MAC']
cfgKeys = ['wake', 'host', 'port', 'mac']
for index in range(len(envKeys)):
key = 'NZBPO_WOL' + envKeys[index]
if os.environ.has_key(key):
option = cfgKeys[index]
value = os.environ[key]
confignew.set(section, option, value)
# create a backup of our old config
if os.path.isfile(config.CONFIG_FILE):
cfgbak_name = config.CONFIG_FILE + ".old"
if os.path.isfile(cfgbak_name): # remove older backups
os.unlink(cfgbak_name)
os.rename(config.CONFIG_FILE, cfgbak_name)
# writing our configuration file to 'autoProcessMedia.cfg'
with open(config.CONFIG_FILE, 'wb') as configFile:
confignew.write(configFile)

View file

@ -1,33 +1,13 @@
import urllib
import logging import logging
import urllib
import requests
from nzbToMediaConfig import * from nzbToMediaConfig import config
from autoProcess.nzbToMediaEnv import *
def autoFork(section):
Logger = logging.getLogger() Logger = logging.getLogger()
class AuthURLOpener(urllib.FancyURLopener):
def __init__(self, user, pw):
self.username = user
self.password = pw
self.numTries = 0
urllib.FancyURLopener.__init__(self)
def prompt_user_passwd(self, host, realm):
if self.numTries == 0:
self.numTries = 1
return (self.username, self.password)
else:
return ('', '')
def openit(self, url):
self.numTries = 0
return urllib.FancyURLopener.open(self, url)
def autoFork():
# config settings # config settings
section = "SickBeard"
host = config().get(section, "host") host = config().get(section, "host")
port = config().get(section, "port") port = config().get(section, "port")
username = config().get(section, "username") username = config().get(section, "username")
@ -44,12 +24,10 @@ def autoFork():
web_root = "" web_root = ""
try: try:
fork = forks.items()[forks.keys().index(config().get(section, "fork"))] fork = config.FORKS.items()[config.FORKS.keys().index(config().get(section, "fork"))]
except: except:
fork = "auto" fork = "auto"
myOpener = AuthURLOpener(username, password)
if ssl: if ssl:
protocol = "https://" protocol = "https://"
else: else:
@ -58,17 +36,17 @@ def autoFork():
detected = False detected = False
if fork == "auto": if fork == "auto":
Logger.info("Attempting to auto-detect SickBeard fork") Logger.info("Attempting to auto-detect SickBeard fork")
for fork in sorted(forks.iteritems()): for fork in sorted(config.FORKS.iteritems()):
url = protocol + host + ":" + port + web_root + "/home/postprocess/processEpisode?" + urllib.urlencode(fork[1]) url = protocol + host + ":" + port + web_root + "/home/postprocess/processEpisode?" + urllib.urlencode(fork[1])
# attempting to auto-detect fork # attempting to auto-detect fork
try: try:
urlObj = myOpener.openit(url) r = requests.get(url, auth=(username, password))
except IOError, e: except requests.ConnectionError:
Logger.info("Could not connect to SickBeard to perform auto-fork detection!") Logger.info("Could not connect to SickBeard to perform auto-fork detection!")
break break
if urlObj.getcode() == 200: if r.ok:
detected = True detected = True
break break
@ -76,7 +54,7 @@ def autoFork():
Logger.info("SickBeard fork auto-detection successful ...") Logger.info("SickBeard fork auto-detection successful ...")
else: else:
Logger.info("SickBeard fork auto-detection failed") Logger.info("SickBeard fork auto-detection failed")
fork = forks.items()[forks.keys().index(fork_default)] fork = config.FORKS.items()[config.FORKS.keys().index(config.FORK_DEFAULT)]
Logger.info("SickBeard fork set to %s", fork[0]) Logger.info("SickBeard fork set to %s", fork[0])
return fork[0], fork[1] return fork[0], fork[1]

View file

@ -0,0 +1,61 @@
import os
import ConfigParser
class config(object):
# 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(__file__)))
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")
# config error handling classes
Error = ConfigParser.Error
NoSectionError = ConfigParser.NoSectionError
NoOptionError = ConfigParser.NoOptionError
DuplicateSectionError = ConfigParser.DuplicateSectionError
InterpolationError = ConfigParser.InterpolationError
InterpolationMissingOptionError = ConfigParser.InterpolationMissingOptionError
InterpolationSyntaxError = ConfigParser.InterpolationSyntaxError
InterpolationDepthError = ConfigParser.InterpolationDepthError
ParsingError = ConfigParser.ParsingError
MissingSectionHeaderError = ConfigParser.MissingSectionHeaderError
def __new__(cls, *file):
if not file:
file = cls.CONFIG_FILE
return cls.loadConfig(file)
@staticmethod
def loadConfig(file):
# load config
config = ConfigParser.ConfigParser()
config.optionxform = str
if config.read(file):
return config

View file

@ -1,26 +1,19 @@
# System imports
import os import os
import logging import logging
from nzbtomedia.nzbToMediaUtil import iterate_media_files
# Custom imports
from nzbToMediaUtil import iterate_media_files
Logger = logging.getLogger() Logger = logging.getLogger()
def process_all_exceptions(name, dirname): def process_all_exceptions(name, dirname):
for group, exception in __customgroups__.items(): for group, exception in __customgroups__.items():
if not (group in name or group in dirname): if not (group in name or group in dirname):
continue continue
process_exception(exception, name, dirname) process_exception(exception, name, dirname)
def process_exception(exception, name, dirname): def process_exception(exception, name, dirname):
for parentDir, filename in iterate_media_files(dirname): for parentDir, filename in iterate_media_files(dirname):
exception(filename, parentDir) exception(filename, parentDir)
def process_qoq(filename, dirname): 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)) head, fileExtension = os.path.splitext(os.path.basename(filename))

View file

@ -1,15 +1,17 @@
import os
import re
import socket
import struct
import shutil
import sys
import time
import requests
import logging import logging
import logging.config import logging.config
import re import logging.handlers
import sys
import shutil
import struct
import socket
import time
import linktastic.linktastic as linktastic
from nzbToMediaConfig import *
from nzbtomedia.linktastic import linktastic
from nzbtomedia.nzbToMediaConfig import config
Logger = logging.getLogger() Logger = logging.getLogger()
@ -30,8 +32,8 @@ def safeName(name):
def nzbtomedia_configure_logging(logfile=None): def nzbtomedia_configure_logging(logfile=None):
if not logfile: if not logfile:
logfile = LOG_FILE logfile = config.LOG_FILE
logging.config.fileConfig(CONFIG_FILE) logging.config.fileConfig(config.CONFIG_FILE)
fileHandler = logging.handlers.RotatingFileHandler(logfile, mode='a', maxBytes=1048576, backupCount=1, encoding='utf-8', delay=True) 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.formatter = logging.Formatter('%(asctime)s|%(levelname)-7.7s %(message)s', '%H:%M:%S')
fileHandler.level = logging.DEBUG fileHandler.level = logging.DEBUG
@ -315,7 +317,6 @@ def WakeOnLan(ethernet_address):
ss.sendto(msg, ('<broadcast>', 9)) ss.sendto(msg, ('<broadcast>', 9))
ss.close() ss.close()
#Test Connection function #Test Connection function
def TestCon(host, port): def TestCon(host, port):
try: try:
@ -324,7 +325,6 @@ def TestCon(host, port):
except: except:
return "Down" return "Down"
def WakeUp(): def WakeUp():
if not config(): if not config():
Logger.error("You need an autoProcessMedia.config() file - did you rename and edit the .sample?") Logger.error("You need an autoProcessMedia.config() file - did you rename and edit the .sample?")
@ -333,7 +333,7 @@ def WakeUp():
wake = int(config().get("WakeOnLan", "wake")) wake = int(config().get("WakeOnLan", "wake"))
if wake == 0: # just return if we don't need to wake anything. if wake == 0: # just return if we don't need to wake anything.
return return
Logger.info("Loading WakeOnLan config from %s", CONFIG_FILE) Logger.info("Loading WakeOnLan config from %s", config.CONFIG_FILE)
config().get("WakeOnLan", "host") config().get("WakeOnLan", "host")
host = config().get("WakeOnLan", "host") host = config().get("WakeOnLan", "host")
port = int(config().get("WakeOnLan", "port")) port = int(config().get("WakeOnLan", "port"))
@ -440,8 +440,8 @@ def parse_transmission(args):
inputID = os.getenv('TR_TORRENT_ID') inputID = os.getenv('TR_TORRENT_ID')
return inputDirectory, inputName, inputCategory, inputHash, inputID return inputDirectory, inputName, inputCategory, inputHash, inputID
def parse_args(clientAgent):
__ARG_PARSERS__ = { clients = {
'other': parse_other, 'other': parse_other,
'rtorrent': parse_rtorrent, 'rtorrent': parse_rtorrent,
'utorrent': parse_utorrent, 'utorrent': parse_utorrent,
@ -449,12 +449,7 @@ __ARG_PARSERS__ = {
'transmission': parse_transmission, 'transmission': parse_transmission,
} }
return clients[clientAgent](sys.argv)
def parse_args(clientAgent):
parseFunc = __ARG_PARSERS__.get(clientAgent, None)
if not parseFunc:
raise RuntimeError("Could not find client-agent")
return parseFunc(sys.argv)
def get_dirnames(section, category): def get_dirnames(section, category):
try: try:
@ -467,7 +462,7 @@ def get_dirnames(section, category):
outputDirectory = "" outputDirectory = ""
# set dirName # set dirName
dirNames = None dirNames = []
if watch_dir != "": if watch_dir != "":
if os.path.exists(watch_dir): if os.path.exists(watch_dir):
dirNames = [os.path.join(watch_dir, o) for o in os.listdir(watch_dir) if dirNames = [os.path.join(watch_dir, o) for o in os.listdir(watch_dir) if
@ -478,3 +473,15 @@ def get_dirnames(section, category):
os.path.isdir(os.path.join(outputDirectory, o))] os.path.isdir(os.path.join(outputDirectory, o))]
return dirNames return dirNames
def delete(dirName):
Logger.info("Deleting failed files and folder %s", dirName)
try:
shutil.rmtree(dirName, True)
except:
Logger.exception("Unable to delete folder %s", dirName)
def getURL(url, username, password):
r = requests.get(url, auth=(username, password))
return r

View file

@ -19,6 +19,5 @@ __title__ = "synchronous-deluge"
__version__ = "0.1" __version__ = "0.1"
__author__ = "Christian Dale" __author__ = "Christian Dale"
from synchronousdeluge.client import DelugeClient from nzbtomedia.synchronousdeluge.exceptions import DelugeRPCError
from synchronousdeluge.exceptions import DelugeRPCError

View file

@ -1,11 +1,11 @@
import os import os
import platform import platform
from collections import defaultdict from collections import defaultdict
from itertools import imap from itertools import imap
from exceptions import DelugeRPCError
from synchronousdeluge.exceptions import DelugeRPCError from protocol import DelugeRPCRequest, DelugeRPCResponse
from synchronousdeluge.protocol import DelugeRPCRequest, DelugeRPCResponse from transfer import DelugeTransfer
from synchronousdeluge.transfer import DelugeTransfer
__all__ = ["DelugeClient"] __all__ = ["DelugeClient"]

View file

@ -3,7 +3,7 @@ import struct
import socket import socket
import ssl import ssl
from synchronousdeluge import rencode from nzbtomedia.synchronousdeluge import rencode
__all__ = ["DelugeTransfer"] __all__ = ["DelugeTransfer"]

View file

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
# Licensed under the MIT license.
from nzbtomedia.transmissionrpc.constants import DEFAULT_PORT, DEFAULT_TIMEOUT, PRIORITY, RATIO_LIMIT, LOGGER
from nzbtomedia.transmissionrpc.error import TransmissionError, HTTPHandlerError
from nzbtomedia.transmissionrpc.httphandler import HTTPHandler, DefaultHTTPHandler
from nzbtomedia.transmissionrpc.torrent import Torrent
from nzbtomedia.transmissionrpc.session import Session
from nzbtomedia.transmissionrpc.client import Client
from nzbtomedia.transmissionrpc.utils import add_stdout_logger, add_file_logger
__author__ = 'Erik Svensson <erik.public@gmail.com>'
__version_major__ = 0
__version_minor__ = 11
__version__ = '{0}.{1}'.format(__version_major__, __version_minor__)
__copyright__ = 'Copyright (c) 2008-2013 Erik Svensson'
__license__ = 'MIT'

View file

@ -10,12 +10,12 @@ import os
import base64 import base64
import json import json
from transmissionrpc.constants import DEFAULT_PORT, DEFAULT_TIMEOUT from nzbtomedia.transmissionrpc.constants import DEFAULT_PORT, DEFAULT_TIMEOUT
from transmissionrpc.error import TransmissionError, HTTPHandlerError from nzbtomedia.transmissionrpc.error import TransmissionError, HTTPHandlerError
from transmissionrpc.utils import LOGGER, get_arguments, make_rpc_name, argument_value_convert, rpc_bool from nzbtomedia.transmissionrpc.utils import LOGGER, get_arguments, make_rpc_name, argument_value_convert, rpc_bool
from transmissionrpc.httphandler import DefaultHTTPHandler from nzbtomedia.transmissionrpc.httphandler import DefaultHTTPHandler
from transmissionrpc.torrent import Torrent from nzbtomedia.transmissionrpc.torrent import Torrent
from transmissionrpc.session import Session from nzbtomedia.transmissionrpc.session import Session
from six import PY3, integer_types, string_types, iteritems from six import PY3, integer_types, string_types, iteritems

View file

@ -4,7 +4,7 @@
import logging import logging
from six import iteritems from nzbtomedia.transmissionrpc.six import iteritems
LOGGER = logging.getLogger('transmissionrpc') LOGGER = logging.getLogger('transmissionrpc')

View file

@ -2,7 +2,7 @@
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com> # Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
# Licensed under the MIT license. # Licensed under the MIT license.
from six import string_types, integer_types from nzbtomedia.transmissionrpc.six import string_types, integer_types
class TransmissionError(Exception): class TransmissionError(Exception):
""" """

View file

@ -4,7 +4,7 @@
import sys import sys
from transmissionrpc.error import HTTPHandlerError from nzbtomedia.transmissionrpc.error import HTTPHandlerError
from six import PY3 from six import PY3
if PY3: if PY3:

View file

@ -2,9 +2,9 @@
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com> # Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
# Licensed under the MIT license. # Licensed under the MIT license.
from transmissionrpc.utils import Field from nzbtomedia.transmissionrpc.utils import Field
from six import iteritems, integer_types from nzbtomedia.transmissionrpc.six import iteritems, integer_types
class Session(object): class Session(object):
""" """

View file

@ -5,8 +5,8 @@
import sys import sys
import datetime import datetime
from transmissionrpc.constants import PRIORITY, RATIO_LIMIT, IDLE_LIMIT from nzbtomedia.transmissionrpc.constants import PRIORITY, RATIO_LIMIT, IDLE_LIMIT
from transmissionrpc.utils import Field, format_timedelta from nzbtomedia.transmissionrpc.utils import Field, format_timedelta
from six import integer_types, string_types, text_type, iteritems from six import integer_types, string_types, text_type, iteritems

View file

@ -2,16 +2,12 @@
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com> # Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
# Licensed under the MIT license. # Licensed under the MIT license.
import socket import socket, datetime, logging, constants
import datetime
import logging
from collections import namedtuple from collections import namedtuple
from constants import LOGGER
import transmissionrpc.constants as constants
from transmissionrpc.constants import LOGGER
from six import string_types, iteritems from six import string_types, iteritems
UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'] UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB']
def format_size(size): def format_size(size):

View file

View file

@ -10,7 +10,7 @@ try:
except ImportError: except ImportError:
import simplejson as json import simplejson as json
from upload import MultiPartForm from nzbtomedia.utorrent.upload import MultiPartForm
class UTorrentClient(object): class UTorrentClient(object):

1
tests/__init__.py Normal file
View file

@ -0,0 +1 @@
__author__ = 'Justin'

View file

@ -1,6 +1,3 @@
from autoProcess.nzbToMediaUtil import * from nzbtomedia import *
from autoProcess.autoSickBeardFork import autoFork
nzbtomedia_configure_logging(LOG_FILE)
fork, params = autoFork() fork, params = autoFork()
print fork, params print fork, params

View file

@ -1,18 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
# Licensed under the MIT license.
from transmissionrpc.constants import DEFAULT_PORT, DEFAULT_TIMEOUT, PRIORITY, RATIO_LIMIT, LOGGER
from transmissionrpc.error import TransmissionError, HTTPHandlerError
from transmissionrpc.httphandler import HTTPHandler, DefaultHTTPHandler
from transmissionrpc.torrent import Torrent
from transmissionrpc.session import Session
from transmissionrpc.client import Client
from transmissionrpc.utils import add_stdout_logger, add_file_logger
__author__ = 'Erik Svensson <erik.public@gmail.com>'
__version_major__ = 0
__version_minor__ = 11
__version__ = '{0}.{1}'.format(__version_major__, __version_minor__)
__copyright__ = 'Copyright (c) 2008-2013 Erik Svensson'
__license__ = 'MIT'