#! /usr/bin/env python2 import os import datetime import re import nzbtomedia from nzbtomedia.nzbToMediaAutoFork import autoFork from nzbtomedia import nzbToMediaDB from nzbtomedia.transcoder import transcoder from nzbtomedia.nzbToMediaUtil import get_downloadInfo, server_responding # Initialize the config nzbtomedia.initialize() if transcoder.isVideoGood(nzbtomedia.TEST_FILE, 0): print "FFPROBE Works" else: print "FFPROBE FAILED" test = nzbtomedia.CFG['SickBeard','NzbDrone']['tv'].isenabled() print test section = nzbtomedia.CFG.findsection('tv').isenabled() print section print len(section) fork, fork_params = autoFork('SickBeard', 'tv') if server_responding("http://127.0.0.1:5050"): print "CouchPotato Running" if server_responding("http://127.0.0.1:7073"): print "SickBeard Running" if server_responding("http://127.0.0.1:8181"): print "HeadPhones Running"
def process(self, section, dirName, inputName=None, status=0, clientAgent="manual", download_id="", inputCategory=None, failureLink=None): host = nzbtomedia.CFG[section][inputCategory]["host"] port = nzbtomedia.CFG[section][inputCategory]["port"] apikey = nzbtomedia.CFG[section][inputCategory]["apikey"] method = nzbtomedia.CFG[section][inputCategory]["method"] delete_failed = int(nzbtomedia.CFG[section][inputCategory]["delete_failed"]) wait_for = int(nzbtomedia.CFG[section][inputCategory]["wait_for"]) try: ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"]) except: ssl = 0 try: web_root = nzbtomedia.CFG[section][inputCategory]["web_root"] except: web_root = "" try: remote_path = int(nzbtomedia.CFG[section][inputCategory]["remote_path"]) except: remote_path = 0 try: extract = int(section[inputCategory]["extract"]) except: extract = 0 if ssl: protocol = "https://" else: protocol = "http://" baseURL = "%s%s:%s%s/api/%s" % (protocol, host, port, web_root, apikey) if not server_responding(baseURL): logger.error("Server did not respond. Exiting", section) return [1, "%s: Failed to post-process - %s did not respond." % (section, section) ] imdbid = find_imdbid(dirName, inputName) release = self.get_release(baseURL, imdbid, download_id) # pull info from release found if available release_id = None media_id = None downloader = None release_status_old = None if release: try: release_id = release.keys()[0] media_id = release[release_id]['media_id'] download_id = release[release_id]['download_info']['id'] downloader = release[release_id]['download_info']['downloader'] release_status_old = release[release_id]['status'] except: pass 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(inputName)) cleanName = os.path.splitext(SpecificPath) if cleanName[1] == ".nzb": SpecificPath = cleanName[0] if os.path.isdir(SpecificPath): dirName = SpecificPath process_all_exceptions(inputName, dirName) inputName, dirName = convert_to_ascii(inputName, dirName) if not listMediaFiles(dirName, media=True, audio=False, meta=False, archives=False) and listMediaFiles(dirName, media=False, audio=False, meta=False, archives=True) and extract: logger.debug('Checking for archives to extract in directory: %s' % (dirName)) nzbtomedia.extractFiles(dirName) inputName, dirName = convert_to_ascii(inputName, dirName) good_files = 0 num_files = 0 # Check video files for corruption status = int(status) for video in listMediaFiles(dirName, media=True, audio=False, meta=False, archives=False): num_files += 1 if transcoder.isVideoGood(video, status): import_subs(video) good_files += 1 if not release and not ".cp(tt" in video and imdbid: videoName, videoExt = os.path.splitext(video) video2 = "%s.cp(%s)%s" % (videoName, imdbid, videoExt) logger.debug('Renaming: %s to: %s' % (video, video2)) os.rename(video, video2) if num_files > 0 and good_files == num_files: if status: logger.info("Status shown as failed from Downloader, but %s valid video files found. Setting as success." % (str(good_files)), section) status = 0 elif num_files > 0 and good_files < num_files: logger.info("Status shown as success from Downloader, but corrupt video files found. Setting as failed.", section) if os.environ.has_key('NZBOP_VERSION') and os.environ['NZBOP_VERSION'][0:5] >= '14.0': print('[NZB] MARK=BAD') if failureLink: failureLink = failureLink + '&corrupt=true' status = 1 elif clientAgent == "manual": logger.warning("No media files found in directory %s to manually process." % (dirName), section) return [0, ""] # Success (as far as this script is concerned) else: logger.warning("No media files found in directory %s. Processing this as a failed download" % (dirName), section) status = 1 if status == 0: if nzbtomedia.TRANSCODE == 1: result, newDirName = transcoder.Transcode_directory(dirName) if result == 0: logger.debug("Transcoding succeeded for files in %s" % (dirName), section) dirName = newDirName else: logger.error("Transcoding failed for files in %s" % (dirName), section) return [1, "%s: Failed to post-process - Transcoding failed" % (section) ] if method == "manage": command = "/manage.update" else: command = "/renamer.scan" params = {} if download_id: params['downloader'] = downloader or clientAgent params['download_id'] = download_id params['media_folder'] = dirName if remote_path: params['media_folder'] = remoteDir(dirName) url = "%s%s" % (baseURL, command) logger.debug("Opening URL: %s with PARAMS: %s" % (url, params), section) logger.postprocess("Starting %s scan for %s" % (method, inputName), section) try: r = requests.get(url, params=params, verify=False) except requests.ConnectionError: logger.error("Unable to open URL", section) return [1, "%s: Failed to post-process - Unable to connect to %s" % (section, section) ] result = r.json() if not r.status_code in [requests.codes.ok, requests.codes.created, requests.codes.accepted]: logger.error("Server returned status %s" % (str(r.status_code)), section) return [1, "%s: Failed to post-process - Server returned status %s" % (section, str(r.status_code)) ] elif result['success']: logger.postprocess("SUCCESS: Finished %s scan for folder %s" % (method, dirName), section) else: logger.error("FAILED: %s scan was unable to finish for folder %s. exiting!" % (method, dirName), section) return [1, "%s: Failed to post-process - Server did not return success" % (section) ] else: logger.postprocess("FAILED DOWNLOAD DETECTED FOR %s" % (inputName), section) if failureLink: reportNzb(failureLink, clientAgent) if delete_failed and os.path.isdir(dirName) and not os.path.dirname(dirName) == dirName: logger.postprocess("Deleting failed files and folder %s" % dirName, section) rmDir(dirName) if not release_id and not media_id: logger.error("Could not find a downloaded movie in the database matching %s, exiting!" % inputName, section) return [1, "%s: Failed to post-process - Failed download not found in %s" % (section, section) ] if release_id: logger.postprocess("Setting failed release %s to ignored ..." % (inputName), section) url = baseURL + "/release.ignore" params = {'id': release_id} logger.debug("Opening URL: %s with PARAMS: %s" % (url, params), section) try: r = requests.get(url, params=params, verify=False) except requests.ConnectionError: logger.error("Unable to open URL %s" % (url), section) return [1, "%s: Failed to post-process - Unable to connect to %s" % (section, section) ] result = r.json() if not r.status_code in [requests.codes.ok, requests.codes.created, requests.codes.accepted]: logger.error("Server returned status %s" % (str(r.status_code)), section) return [1, "%s: Failed to post-process - Server returned status %s" % (section, str(r.status_code)) ] elif result['success']: logger.postprocess("SUCCESS: %s has been set to ignored ..." % (inputName), section) else: logger.warning("FAILED: Unable to set %s to ignored!" % (inputName), section) return [1, "%s: Failed to post-process - Unable to set %s to ignored" % (section, inputName) ] logger.postprocess("Trying to snatch the next highest ranked release.", section) url = "%s/movie.searcher.try_next" % (baseURL) logger.debug("Opening URL: %s" % (url), section) try: r = requests.get(url, params={'media_id': media_id}) except requests.ConnectionError: logger.error("Unable to open URL %s" % (url), section) return [1, "%s: Failed to post-process - Unable to connect to %s" % (section, section) ] result = r.json() if not r.status_code in [requests.codes.ok, requests.codes.created, requests.codes.accepted]: logger.error("Server returned status %s" % (str(r.status_code)), section) return [1, "%s: Failed to post-process - Server returned status %s" % (section, str(r.status_code)) ] elif result['success']: logger.postprocess("SUCCESS: Snatched the next highest release ...", section) return [0, "%s: Successfully snatched next highest release" % (section) ] else: logger.postprocess("SUCCESS: Unable to find a new release to snatch now. CP will keep searching!", section) return [0, "%s: No new release found now. %s will keep searching" % (section, section) ] # Added a releease that was not in the wanted list so confirm rename successful by finding this movie media.list. if not release: download_id = None # we don't want to filter new releases based on this. # we will now check to see if CPS has finished renaming before returning to TorrentToMedia and unpausing. timeout = time.time() + 60 * wait_for while (time.time() < timeout): # only wait 2 (default) minutes, then return. logger.postprocess("Checking for status change, please stand by ...", section) release = self.get_release(baseURL, imdbid, download_id, release_id) if release: try: if release_id is None and release_status_old is None: # we didn't have a release before, but now we do. logger.postprocess("SUCCESS: Movie %s has now been added to CouchPotato" % (imdbid), section) return [0, "%s: Successfully post-processed %s" % (section, inputName) ] release_status_new = release[release_id]['status'] if release_status_new != release_status_old: logger.postprocess("SUCCESS: Release %s has now been marked with a status of [%s]" % ( inputName, str(release_status_new).upper()), section) return [0, "%s: Successfully post-processed %s" % (section, inputName) ] except: pass if not os.path.isdir(dirName): logger.postprocess("SUCCESS: Input Directory [%s] has been processed and removed" % ( dirName), section) return [0, "%s: Successfully post-processed %s" % (section, inputName) ] elif not listMediaFiles(dirName, media=True, audio=False, meta=False, archives=True): logger.postprocess("SUCCESS: Input Directory [%s] has no remaining media files. This has been fully processed." % ( dirName), section) return [0, "%s: Successfully post-processed %s" % (section, inputName) ] # pause and let CouchPotatoServer catch its breath time.sleep(10 * wait_for) # The status hasn't changed. we have waited 2 minutes which is more than enough. uTorrent can resule seeding now. logger.warning( "%s does not appear to have changed status after %s minutes, Please check your logs." % (inputName, wait_for), section) return [1, "%s: Failed to post-process - No change in status" % (section) ]
import sys import datetime import re import nzbtomedia from nzbtomedia.nzbToMediaAutoFork import autoFork from nzbtomedia import nzbToMediaDB from nzbtomedia.transcoder import transcoder from nzbtomedia.nzbToMediaUtil import get_downloadInfo, server_responding # Initialize the config nzbtomedia.initialize() #label = nzbtomedia.TORRENT_CLASS.core.get_torrent_status("f33a9c4b15cbd9170722d700069af86746817ade", ["label"]).get()['label'] #print label if transcoder.isVideoGood(nzbtomedia.TEST_FILE, 0): print "FFPROBE Works" else: print "FFPROBE FAILED" test = nzbtomedia.CFG['SickBeard', 'NzbDrone']['tv'].isenabled() print test section = nzbtomedia.CFG.findsection('tv').isenabled() print section print len(section) fork, fork_params = autoFork('SickBeard', 'tv') if server_responding("http://127.0.0.1:5050"): print "CouchPotato Running" if server_responding("http://127.0.0.1:7073"): print "SickBeard Running"
def process(self, section, dirName, inputName=None, status=0, clientAgent="manual", download_id="", inputCategory=None, failureLink=None): host = nzbtomedia.CFG[section][inputCategory]["host"] port = nzbtomedia.CFG[section][inputCategory]["port"] apikey = nzbtomedia.CFG[section][inputCategory]["apikey"] method = nzbtomedia.CFG[section][inputCategory]["method"] delete_failed = int( nzbtomedia.CFG[section][inputCategory]["delete_failed"]) wait_for = int(nzbtomedia.CFG[section][inputCategory]["wait_for"]) try: ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"]) except: ssl = 0 try: web_root = nzbtomedia.CFG[section][inputCategory]["web_root"] except: web_root = "" try: remote_path = int( nzbtomedia.CFG[section][inputCategory]["remote_path"]) except: remote_path = 0 try: extract = int(section[inputCategory]["extract"]) except: extract = 0 if ssl: protocol = "https://" else: protocol = "http://" baseURL = "%s%s:%s%s/api/%s" % (protocol, host, port, web_root, apikey) if not server_responding(baseURL): logger.error("Server did not respond. Exiting", section) return [ 1, "%s: Failed to post-process - %s did not respond." % (section, section) ] imdbid = find_imdbid(dirName, inputName) release = self.get_release(baseURL, imdbid, download_id) # pull info from release found if available release_id = None media_id = None downloader = None release_status_old = None if release: try: release_id = release.keys()[0] media_id = release[release_id]['media_id'] download_id = release[release_id]['download_info']['id'] downloader = release[release_id]['download_info']['downloader'] release_status_old = release[release_id]['status'] except: pass 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(inputName)) cleanName = os.path.splitext(SpecificPath) if cleanName[1] == ".nzb": SpecificPath = cleanName[0] if os.path.isdir(SpecificPath): dirName = SpecificPath process_all_exceptions(inputName, dirName) inputName, dirName = convert_to_ascii(inputName, dirName) if not listMediaFiles( dirName, media=True, audio=False, meta=False, archives=False) and listMediaFiles(dirName, media=False, audio=False, meta=False, archives=True) and extract: logger.debug('Checking for archives to extract in directory: %s' % (dirName)) nzbtomedia.extractFiles(dirName) inputName, dirName = convert_to_ascii(inputName, dirName) good_files = 0 num_files = 0 # Check video files for corruption status = int(status) for video in listMediaFiles(dirName, media=True, audio=False, meta=False, archives=False): num_files += 1 if transcoder.isVideoGood(video, status): import_subs(video) good_files += 1 if num_files > 0 and good_files == num_files: if status: logger.info( "Status shown as failed from Downloader, but %s valid video files found. Setting as success." % (str(good_files)), section) status = 0 elif num_files > 0 and good_files < num_files: logger.info( "Status shown as success from Downloader, but corrupt video files found. Setting as failed.", section) if os.environ.has_key('NZBOP_VERSION') and os.environ[ 'NZBOP_VERSION'][0:5] >= '14.0': print('[NZB] MARK=BAD') if failureLink: failureLink = failureLink + '&corrupt=true' status = 1 elif clientAgent == "manual": logger.warning( "No media files found in directory %s to manually process." % (dirName), section) return [0, ""] # Success (as far as this script is concerned) else: logger.warning( "No media files found in directory %s. Processing this as a failed download" % (dirName), section) status = 1 if status == 0: if nzbtomedia.TRANSCODE == 1: result, newDirName = transcoder.Transcode_directory(dirName) if result == 0: logger.debug( "Transcoding succeeded for files in %s" % (dirName), section) dirName = newDirName else: logger.error( "Transcoding failed for files in %s" % (dirName), section) return [ 1, "%s: Failed to post-process - Transcoding failed" % (section) ] for video in listMediaFiles(dirName, media=True, audio=False, meta=False, archives=False): if not release and not ".cp(tt" in video and imdbid: videoName, videoExt = os.path.splitext(video) video2 = "%s.cp(%s)%s" % (videoName, imdbid, videoExt) logger.debug('Renaming: %s to: %s' % (video, video2)) os.rename(video, video2) params = {} if download_id: params['downloader'] = downloader or clientAgent params['download_id'] = download_id params['media_folder'] = dirName if remote_path: params['media_folder'] = remoteDir(dirName) if method == "manage": command = "/manage.update" params = {} else: command = "/renamer.scan" url = "%s%s" % (baseURL, command) logger.debug("Opening URL: %s with PARAMS: %s" % (url, params), section) logger.postprocess("Starting %s scan for %s" % (method, inputName), section) try: r = requests.get(url, params=params, verify=False) except requests.ConnectionError: logger.error("Unable to open URL", section) return [ 1, "%s: Failed to post-process - Unable to connect to %s" % (section, section) ] result = r.json() if not r.status_code in [ requests.codes.ok, requests.codes.created, requests.codes.accepted ]: logger.error( "Server returned status %s" % (str(r.status_code)), section) return [ 1, "%s: Failed to post-process - Server returned status %s" % (section, str(r.status_code)) ] elif result['success']: logger.postprocess( "SUCCESS: Finished %s scan for folder %s" % (method, dirName), section) if method == "manage": return [ 0, "%s: Successfully post-processed %s" % (section, inputName) ] else: logger.error( "FAILED: %s scan was unable to finish for folder %s. exiting!" % (method, dirName), section) return [ 1, "%s: Failed to post-process - Server did not return success" % (section) ] else: logger.postprocess("FAILED DOWNLOAD DETECTED FOR %s" % (inputName), section) if failureLink: reportNzb(failureLink, clientAgent) if delete_failed and os.path.isdir( dirName) and not os.path.dirname(dirName) == dirName: logger.postprocess( "Deleting failed files and folder %s" % dirName, section) rmDir(dirName) if not release_id and not media_id: logger.error( "Could not find a downloaded movie in the database matching %s, exiting!" % inputName, section) return [ 1, "%s: Failed to post-process - Failed download not found in %s" % (section, section) ] if release_id: logger.postprocess( "Setting failed release %s to ignored ..." % (inputName), section) url = baseURL + "/release.ignore" params = {'id': release_id} logger.debug("Opening URL: %s with PARAMS: %s" % (url, params), section) try: r = requests.get(url, params=params, verify=False) except requests.ConnectionError: logger.error("Unable to open URL %s" % (url), section) return [ 1, "%s: Failed to post-process - Unable to connect to %s" % (section, section) ] result = r.json() if not r.status_code in [ requests.codes.ok, requests.codes.created, requests.codes.accepted ]: logger.error( "Server returned status %s" % (str(r.status_code)), section) return [ 1, "%s: Failed to post-process - Server returned status %s" % (section, str(r.status_code)) ] elif result['success']: logger.postprocess( "SUCCESS: %s has been set to ignored ..." % (inputName), section) else: logger.warning( "FAILED: Unable to set %s to ignored!" % (inputName), section) return [ 1, "%s: Failed to post-process - Unable to set %s to ignored" % (section, inputName) ] logger.postprocess( "Trying to snatch the next highest ranked release.", section) url = "%s/movie.searcher.try_next" % (baseURL) logger.debug("Opening URL: %s" % (url), section) try: r = requests.get(url, params={'media_id': media_id}, verify=False) except requests.ConnectionError: logger.error("Unable to open URL %s" % (url), section) return [ 1, "%s: Failed to post-process - Unable to connect to %s" % (section, section) ] result = r.json() if not r.status_code in [ requests.codes.ok, requests.codes.created, requests.codes.accepted ]: logger.error( "Server returned status %s" % (str(r.status_code)), section) return [ 1, "%s: Failed to post-process - Server returned status %s" % (section, str(r.status_code)) ] elif result['success']: logger.postprocess( "SUCCESS: Snatched the next highest release ...", section) return [ 0, "%s: Successfully snatched next highest release" % (section) ] else: logger.postprocess( "SUCCESS: Unable to find a new release to snatch now. CP will keep searching!", section) return [ 0, "%s: No new release found now. %s will keep searching" % (section, section) ] # Added a releease that was not in the wanted list so confirm rename successful by finding this movie media.list. if not release: download_id = None # we don't want to filter new releases based on this. # we will now check to see if CPS has finished renaming before returning to TorrentToMedia and unpausing. timeout = time.time() + 60 * wait_for while (time.time() < timeout): # only wait 2 (default) minutes, then return. logger.postprocess( "Checking for status change, please stand by ...", section) release = self.get_release(baseURL, imdbid, download_id, release_id) if release: try: if release_id is None and release_status_old is None: # we didn't have a release before, but now we do. logger.postprocess( "SUCCESS: Movie %s has now been added to CouchPotato" % (imdbid), section) return [ 0, "%s: Successfully post-processed %s" % (section, inputName) ] release_status_new = release[release_id]['status'] if release_status_new != release_status_old: logger.postprocess( "SUCCESS: Release %s has now been marked with a status of [%s]" % (inputName, str(release_status_new).upper()), section) return [ 0, "%s: Successfully post-processed %s" % (section, inputName) ] except: pass if not os.path.isdir(dirName): logger.postprocess( "SUCCESS: Input Directory [%s] has been processed and removed" % (dirName), section) return [ 0, "%s: Successfully post-processed %s" % (section, inputName) ] elif not listMediaFiles( dirName, media=True, audio=False, meta=False, archives=True): logger.postprocess( "SUCCESS: Input Directory [%s] has no remaining media files. This has been fully processed." % (dirName), section) return [ 0, "%s: Successfully post-processed %s" % (section, inputName) ] # pause and let CouchPotatoServer catch its breath time.sleep(10 * wait_for) # The status hasn't changed. we have waited 2 minutes which is more than enough. uTorrent can resule seeding now. logger.warning( "%s does not appear to have changed status after %s minutes, Please check your logs." % (inputName, wait_for), section) return [ 1, "%s: Failed to post-process - No change in status" % (section) ]
class autoProcessTV: def command_complete(self, url, params, headers, section): r = None try: r = requests.get(url, params=params, headers=headers, stream=True, verify=False) except requests.ConnectionError: logger.error("Unable to open URL: %s" % (url1), section) return None if not r.status_code in [requests.codes.ok, requests.codes.created, requests.codes.accepted]: logger.error("Server returned status %s" % (str(r.status_code)), section) return None else: try: res = json.loads(r.content) return res['state'] except: logger.error("%s did not return expected json data." % section, section) return None def CDH(self, url2, headers): r = None try: r = requests.get(url2, params={}, headers=headers, stream=True, verify=False) except requests.ConnectionError: logger.error("Unable to open URL: %s" % (url2), section) return False if not r.status_code in [requests.codes.ok, requests.codes.created, requests.codes.accepted]: logger.error("Server returned status %s" % (str(r.status_code)), section) return False else: try: res = json.loads(r.content) return res["enableCompletedDownloadHandling"] except: return False def processEpisode(self, section, dirName, inputName=None, failed=False, clientAgent = "manual", download_id=None, inputCategory=None, failureLink=None): host = nzbtomedia.CFG[section][inputCategory]["host"] port = nzbtomedia.CFG[section][inputCategory]["port"] try: ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"]) except: ssl = 0 if ssl: protocol = "https://" else: protocol = "http://" try: web_root = nzbtomedia.CFG[section][inputCategory]["web_root"] except: web_root = "" if not server_responding("%s%s:%s%s" % (protocol,host,port,web_root)): logger.error("Server did not respond. Exiting", section) return [1, "%s: Failed to post-process - %s did not respond." % (section, section) ] # auto-detect correct fork fork, fork_params = autoFork(section, inputCategory) try: username = nzbtomedia.CFG[section][inputCategory]["username"] password = nzbtomedia.CFG[section][inputCategory]["password"] except: username = "" password = "" try: apikey = nzbtomedia.CFG[section][inputCategory]["apikey"] except: apikey = "" try: delete_failed = int(nzbtomedia.CFG[section][inputCategory]["delete_failed"]) except: delete_failed = 0 try: nzbExtractionBy = nzbtomedia.CFG[section][inputCategory]["nzbExtractionBy"] except: nzbExtractionBy = "Downloader" try: process_method = nzbtomedia.CFG[section][inputCategory]["process_method"] except: process_method = None try: remote_path = int(nzbtomedia.CFG[section][inputCategory]["remote_path"]) except: remote_path = 0 try: wait_for = int(nzbtomedia.CFG[section][inputCategory]["wait_for"]) except: wait_for = 2 try: force = int(nzbtomedia.CFG[section][inputCategory]["force"]) except: force = 0 try: extract = int(section[inputCategory]["extract"]) except: extract = 0 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(inputName)) cleanName = os.path.splitext(SpecificPath) if cleanName[1] == ".nzb": SpecificPath = cleanName[0] if os.path.isdir(SpecificPath): dirName = SpecificPath # Attempt to create the directory if it doesn't exist and ignore any # error stating that it already exists. This fixes a bug where SickRage # won't process the directory because it doesn't exist. try: os.makedirs(dirName) # Attempt to create the directory except OSError, e: # Re-raise the error if it wasn't about the directory not existing if e.errno != errno.EEXIST: raise # Check video files for corruption status = int(failed) good_files = 0 num_files = 0 for video in listMediaFiles(dirName, media=True, audio=False, meta=False, archives=False): num_files += 1 if transcoder.isVideoGood(video, status): good_files += 1 import_subs(video) if num_files > 0: if good_files == num_files and not status == 0: logger.info('Found Valid Videos. Setting status Success') status = 0 failed = 0 if good_files < num_files and status == 0: logger.info('Found corrupt videos. Setting status Failed') status = 1 failed = 1 if os.environ.has_key('NZBOP_VERSION') and os.environ['NZBOP_VERSION'][0:5] >= '14.0': print('[NZB] MARK=BAD') if failureLink: failureLink = failureLink + '&corrupt=true' elif clientAgent == "manual" and not listMediaFiles(dirName, media=True, audio=False, meta=False, archives=True): logger.warning("No media files found in directory %s to manually process." % (dirName), section) return [0, ""] # Success (as far as this script is concerned) if fork not in nzbtomedia.SICKBEARD_TORRENT or (clientAgent in ['nzbget','sabnzbd'] and nzbExtractionBy != "Destination"): if inputName: process_all_exceptions(inputName, dirName) inputName, dirName = convert_to_ascii(inputName, dirName) # Now check if tv files exist in destination. if listMediaFiles(dirName, media=True, audio=False, meta=False, archives=False): # Check that a video exists. if not, assume failed. flatten(dirName) # to make sure SickBeard can find the video (not in sub-folder) elif listMediaFiles(dirName, media=False, audio=False, meta=False, archives=True) and extract: logger.debug('Checking for archives to extract in directory: %s' % (dirName)) nzbtomedia.extractFiles(dirName) inputName, dirName = convert_to_ascii(inputName, dirName) good_files = 0 num_files = 0 for video in listMediaFiles(dirName, media=True, audio=False, meta=False, archives=False): num_files += 1 if transcoder.isVideoGood(video, status): good_files += 1 import_subs(video) if num_files > 0 and good_files == num_files: logger.info('Found Valid Videos. Setting status Success') status = 0 failed = 0 if listMediaFiles(dirName, media=True, audio=False, meta=False, archives=False): # Check that a video exists. if not, assume failed. flatten(dirName) elif clientAgent == "manual": logger.warning("No media files found in directory %s to manually process." % (dirName), section) return [0, ""] # Success (as far as this script is concerned) else: logger.warning("No media files found in directory %s. Processing this as a failed download" % (dirName), section) status = 1 failed = 1 if status == 0 and nzbtomedia.TRANSCODE == 1: # only transcode successful downlaods result, newDirName = transcoder.Transcode_directory(dirName) if result == 0: logger.debug("SUCCESS: Transcoding succeeded for files in %s" % (dirName), section) dirName = newDirName else: logger.error("FAILED: Transcoding failed for files in %s" % (dirName), section) return [1, "%s: Failed to post-process - Transcoding failed" % (section) ] # configure SB params to pass fork_params['quiet'] = 1 if inputName is not None: fork_params['nzbName'] = inputName for param in copy.copy(fork_params): if param == "failed": fork_params[param] = failed if param in ["dirName", "dir"]: fork_params[param] = dirName if remote_path: fork_params[param] = remoteDir(dirName) if param == "process_method": if process_method: fork_params[param] = process_method else: del fork_params[param] if param == "force": if force: fork_params[param] = force else: del fork_params[param] # delete any unused params so we don't pass them to SB by mistake [fork_params.pop(k) for k,v in fork_params.items() if v is None] if status == 0: logger.postprocess("SUCCESS: The download succeeded, sending a post-process request", section) else: if failureLink: reportNzb(failureLink, clientAgent) if fork in nzbtomedia.SICKBEARD_FAILED: logger.postprocess("FAILED: The download failed. Sending 'failed' process request to %s branch" % (fork), section) elif section == "NzbDrone": logger.postprocess("FAILED: The download failed. Sending failed download to %s for CDH processing" % (fork), section) return [1, "%s: Downlaod Failed. Sending back to %s" % (section, section) ] # Return as failed to flag this in the downloader. else: logger.postprocess("FAILED: The download failed. %s branch does not handle failed downloads. Nothing to process" % (fork), section) if delete_failed and os.path.isdir(dirName) and not os.path.dirname(dirName) == dirName: logger.postprocess("Deleting failed files and folder %s" % (dirName), section) rmDir(dirName) return [1, "%s: Failed to post-process. %s does not support failed downloads" % (section, section) ] # Return as failed to flag this in the downloader. url = None if section == "SickBeard": url = "%s%s:%s%s/home/postprocess/processEpisode" % (protocol,host,port,web_root) elif section == "NzbDrone": url = "%s%s:%s%s/api/command" % (protocol, host, port, web_root) url2 = "%s%s:%s%s/api/config/downloadClient" % (protocol, host, port, web_root) headers = {"X-Api-Key": apikey} params = {'sortKey': 'series.title', 'page': 1, 'pageSize': 1, 'sortDir': 'asc'} if remote_path: logger.debug("remote_path: %s" % (remoteDir(dirName)),section) data = {"name": "DownloadedEpisodesScan", "path": remoteDir(dirName), "downloadClientId": download_id} else: logger.debug("path: %s" % (dirName),section) data = {"name": "DownloadedEpisodesScan", "path": dirName, "downloadClientId": download_id} if not download_id: data.pop("downloadClientId") data = json.dumps(data) try: if section == "SickBeard": logger.debug("Opening URL: %s with params: %s" % (url, str(fork_params)), section) r = None s = requests.Session() login = "******" % (protocol,host,port,web_root) login_params = {'username': username, 'password': password} s.post(login, data=login_params, stream=True, verify=False) r = s.get(url, auth=(username, password), params=fork_params, stream=True, verify=False) elif section == "NzbDrone": logger.debug("Opening URL: %s with data: %s" % (url, str(data)), section) r = None r = requests.post(url, data=data, headers=headers, stream=True, verify=False) except requests.ConnectionError: logger.error("Unable to open URL: %s" % (url), section) return [1, "%s: Failed to post-process - Unable to connect to %s" % (section, section) ] if not r.status_code in [requests.codes.ok, requests.codes.created, requests.codes.accepted]: logger.error("Server returned status %s" % (str(r.status_code)), section) return [1, "%s: Failed to post-process - Server returned status %s" % (section, str(r.status_code)) ] Success = False Started = False if section == "SickBeard": for line in r.iter_lines(): if line: logger.postprocess("%s" % (line), section) if "Processing succeeded" in line or "Successfully processed" in line: Success = True elif section == "NzbDrone": try: res = json.loads(r.content) scan_id = int(res['id']) logger.debug("Scan started with id: %s" % (str(scan_id)), section) Started = True except Exception as e: logger.warning("No scan id was returned due to: %s" % (e), section) scan_id = None Started = False if status != 0 and delete_failed and not os.path.dirname(dirName) == dirName: logger.postprocess("Deleting failed files and folder %s" % (dirName),section) rmDir(dirName) if Success: return [0, "%s: Successfully post-processed %s" % (section, inputName) ] elif section == "NzbDrone" and Started: n = 0 params = {} url = url + "/" + str(scan_id) while n < 6: # set up wait_for minutes to see if command completes.. time.sleep(10 * wait_for) command_status = self.command_complete(url, params, headers, section) if command_status and command_status in ['completed', 'failed']: break n += 1 if command_status: logger.debug("The Scan command return status: %s" % (command_status), section) if not os.path.exists(dirName): logger.debug("The directory %s has been removed. Renaming was successful." % (dirName), section) return [0, "%s: Successfully post-processed %s" % (section, inputName) ] elif command_status and command_status in ['completed']: logger.debug("The Scan command has completed successfully. Renaming was successful.", section) return [0, "%s: Successfully post-processed %s" % (section, inputName) ] elif command_status and command_status in ['failed']: logger.debug("The Scan command has failed. Renaming was not successful.", section) #return [1, "%s: Failed to post-process %s" % (section, inputName) ] if self.CDH(url2, headers): logger.debug("The Scan command did not return status completed, but complete Download Handling is enabled. Passing back to %s." % (section), section) return [status, "%s: Complete DownLoad Handling is enabled. Passing back to %s" % (section, section) ] else: logger.warning("The Scan command did not return a valid status. Renaming was not successful.", section) return [1, "%s: Failed to post-process %s" % (section, inputName) ] else: return [1, "%s: Failed to post-process - Returned log from %s was not as expected." % (section, section) ] # We did not receive Success confirmation.
def processEpisode(self, section, dirName, inputName=None, failed=False, clientAgent="manual", inputCategory=None): # auto-detect correct fork fork, fork_params = autoFork(section, inputCategory) # Check video files for corruption status = int(failed) for video in listMediaFiles(dirName): if not transcoder.isVideoGood(video): status = 1 host = nzbtomedia.CFG[section][inputCategory]["host"] port = nzbtomedia.CFG[section][inputCategory]["port"] try: username = nzbtomedia.CFG[section][inputCategory]["username"] password = nzbtomedia.CFG[section][inputCategory]["password"] except: username = "" password = "" try: apikey = nzbtomedia.CFG[section][inputCategory]["apikey"] except: apikey = "" try: ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"]) except: ssl = 0 try: web_root = nzbtomedia.CFG[section][inputCategory]["web_root"] except: web_root = "" try: delete_failed = int( nzbtomedia.CFG[section][inputCategory]["delete_failed"]) except: delete_failed = 0 try: nzbExtractionBy = nzbtomedia.CFG[section][inputCategory][ "nzbExtractionBy"] except: nzbExtractionBy = "Downloader" try: process_method = nzbtomedia.CFG[section][inputCategory][ "process_method"] except: process_method = None try: remote_path = int( nzbtomedia.CFG[section][inputCategory]["remote_path"]) except: remote_path = 0 try: wait_for = int(nzbtomedia.CFG[section][inputCategory]["wait_for"]) except: wait_for = 2 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(inputName)) cleanName = os.path.splitext(SpecificPath) if cleanName[1] == ".nzb": SpecificPath = cleanName[0] if os.path.isdir(SpecificPath): dirName = SpecificPath if fork not in nzbtomedia.SICKBEARD_TORRENT or ( clientAgent in ['nzbget', 'sabnzbd'] and nzbExtractionBy != "Destination"): if inputName: process_all_exceptions(inputName.lower(), dirName) inputName, dirName = convert_to_ascii(inputName, dirName) # Now check if tv files exist in destination. Eventually extraction may be done here if nzbExtractionBy == TorrentToMedia if listMediaFiles( dirName ): # 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), section) return 0 # Success (as far as this script is concerned) else: logger.warning( "No media files found in directory %s. Processing this as a failed download" % (dirName), section) status = 1 failed = 1 # configure SB params to pass fork_params['quiet'] = 1 if inputName is not None: fork_params['nzbName'] = inputName for param in copy.copy(fork_params): if param == "failed": fork_params[param] = failed if param in ["dirName", "dir"]: fork_params[param] = dirName if remote_path: fork_params[param] = remoteDir(dirName) if param == "process_method": if process_method: fork_params[param] = process_method else: del fork_params[param] # delete any unused params so we don't pass them to SB by mistake [fork_params.pop(k) for k, v in fork_params.items() if v is None] if status == 0: logger.postprocess( "SUCCESS: The download succeeded, sending a post-process request", section) else: if fork in nzbtomedia.SICKBEARD_FAILED or section == "NzbDrone": logger.postprocess( "FAILED: The download failed. Sending 'failed' process request to %s branch" % (fork), section) else: logger.postprocess( "FAILED: The download failed. %s branch does not handle failed downloads. Nothing to process" % (fork), section) if delete_failed and os.path.isdir( dirName) and not os.path.dirname(dirName) == dirName: logger.postprocess( "Deleting failed files and folder %s" % (dirName), section) rmDir(dirName) return 0 # Success (as far as this script is concerned) if status == 0 and nzbtomedia.TRANSCODE == 1: # only transcode successful downlaods result = transcoder.Transcode_directory(dirName) if result == 0: logger.debug( "SUCCESS: Transcoding succeeded for files in %s" % (dirName), section) else: logger.warning( "FAILED: Transcoding failed for files in %s" % (dirName), section) if ssl: protocol = "https://" else: protocol = "http://" url = None if section == "SickBeard": url = "%s%s:%s%s/home/postprocess/processEpisode" % ( protocol, host, port, web_root) elif section == "NzbDrone": url = "%s%s:%s%s/api/command" % (protocol, host, port, web_root) url1 = "%s%s:%s%s/api/missing" % (protocol, host, port, web_root) headers = {"X-Api-Key": apikey} params = { 'sortKey': 'series.title', 'page': 1, 'pageSize': 1, 'sortDir': 'asc' } if remote_path: data = json.dumps({ "name": "DownloadedEpisodesScan", "path": remote_path }) else: data = json.dumps({ "name": "DownloadedEpisodesScan", "path": dirName }) logger.debug("Opening URL: %s" % (url), section) try: if section == "SickBeard": r = None r = requests.get(url, auth=(username, password), params=fork_params, stream=True, verify=False) elif section == "NzbDrone": start_numMissing = self.numMissing( url1, params, headers) # get current number of outstanding eppisodes. r = None r = requests.post(url, data=data, headers=headers, stream=True, verify=False) except requests.ConnectionError: logger.error("Unable to open URL: %s" % (url), section) return 1 # failure if not r.status_code in [ requests.codes.ok, requests.codes.created, requests.codes.accepted ]: logger.error("Server returned status %s" % (str(r.status_code)), section) return 1 Success = False Started = False for line in r.iter_lines(): if line: logger.postprocess("%s" % (line), section) if section == "SickBeard" and "Processing succeeded" in line: Success = True elif section == "NzbDrone" and "stateChangeTime" in line: Started = True if status != 0 and delete_failed and not os.path.dirname( dirName) == dirName: logger.postprocess( "Deleting failed files and folder %s" % (dirName), section) rmDir(dirName) if Success: return 0 elif section == "NzbDrone" and Started: n = 0 current_numMissing = start_numMissing while n < 6: # set up wait_for minutes of no change in numMissing. time.sleep(10 * wait_for) new_numMissing = self.numMissing(url1, params, headers) if new_numMissing == current_numMissing: # nothing processed since last call n += 1 else: n = 0 current_numMissing = new_numMissing # reset counter and start loop again with this many missing. if current_numMissing < start_numMissing: logger.debug( "The number of missing episodes changes from %s to %s and then remained the same for %s minutes. Consider this successful" % (str(start_numMissing), str(current_numMissing), str(wait_for)), section) return 0 else: # The status hasn't changed. we have waited 2 minutes which is more than enough. uTorrent can resume seeding now. logger.warning( "The number of missing episodes: %s does not appear to have changed status after %s minutes, Please check your logs." % (str(start_numMissing), str(wait_for)), section) return 1 else: return 1 # We did not receive Success confirmation.
def external_script(outputDestination, torrentName, torrentLabel, settings): final_result = 0 # start at 0. num_files = 0 try: nzbtomedia.USER_SCRIPT_MEDIAEXTENSIONS = settings["user_script_mediaExtensions"] if isinstance(nzbtomedia.USER_SCRIPT_MEDIAEXTENSIONS, str): nzbtomedia.USER_SCRIPT_MEDIAEXTENSIONS = nzbtomedia.USER_SCRIPT_MEDIAEXTENSIONS.split(',') except: nzbtomedia.USER_SCRIPT_MEDIAEXTENSIONS = [] try: nzbtomedia.USER_SCRIPT = settings["user_script_path"] except: nzbtomedia.USER_SCRIPT = None if nzbtomedia.USER_SCRIPT is None or nzbtomedia.USER_SCRIPT == "None": # do nothing and return success. return [0, ""] try: nzbtomedia.USER_SCRIPT_PARAM = settings["user_script_param"] if isinstance(nzbtomedia.USER_SCRIPT_PARAM, str): nzbtomedia.USER_SCRIPT_PARAM = nzbtomedia.USER_SCRIPT_PARAM.split(',') except: nzbtomedia.USER_SCRIPT_PARAM = [] try: nzbtomedia.USER_SCRIPT_SUCCESSCODES = settings["user_script_successCodes"] if isinstance(nzbtomedia.USER_SCRIPT_SUCCESSCODES, str): nzbtomedia.USER_SCRIPT_SUCCESSCODES = nzbtomedia.USER_SCRIPT_SUCCESSCODES.split(',') except: nzbtomedia.USER_SCRIPT_SUCCESSCODES = 0 try: nzbtomedia.USER_SCRIPT_CLEAN = int(settings["user_script_clean"]) except: nzbtomedia.USER_SCRIPT_CLEAN = 1 try: nzbtomedia.USER_SCRIPT_RUNONCE = int(settings["user_script_runOnce"]) except: nzbtomedia.USER_SCRIPT_RUNONCE = 1 if nzbtomedia.CHECK_MEDIA: for video in listMediaFiles(outputDestination, media=True, audio=False, meta=False, archives=False): if transcoder.isVideoGood(video, 0): import_subs(video) else: logger.info("Corrupt video file found %s. Deleting." % (video), "USERSCRIPT") os.unlink(video) for dirpath, dirnames, filenames in os.walk(outputDestination): for file in filenames: filePath = nzbtomedia.os.path.join(dirpath, file) fileName, fileExtension = os.path.splitext(file) if fileExtension in nzbtomedia.USER_SCRIPT_MEDIAEXTENSIONS or "ALL" in nzbtomedia.USER_SCRIPT_MEDIAEXTENSIONS: num_files = num_files + 1 if nzbtomedia.USER_SCRIPT_RUNONCE == 1 and num_files > 1: # we have already run once, so just continue to get number of files. continue command = [nzbtomedia.USER_SCRIPT] for param in nzbtomedia.USER_SCRIPT_PARAM: if param == "FN": command.append('%s' % file) continue elif param == "FP": command.append('%s' % filePath) continue elif param == "TN": command.append('%s' % torrentName) continue elif param == "TL": command.append('%s' % torrentLabel) continue elif param == "DN": if nzbtomedia.USER_SCRIPT_RUNONCE == 1: command.append('%s' % outputDestination) else: command.append('%s' % dirpath) continue else: command.append(param) continue cmd = "" for item in command: cmd = cmd + " " + item logger.info("Running script %s on file %s." % (cmd, filePath), "USERSCRIPT") try: p = Popen(command) res = p.wait() if str(res) in nzbtomedia.USER_SCRIPT_SUCCESSCODES: # Linux returns 0 for successful. logger.info("UserScript %s was successfull" % (command[0])) result = 0 else: logger.error("UserScript %s has failed with return code: %s" % (command[0], res), "USERSCRIPT") logger.info( "If the UserScript completed successfully you should add %s to the user_script_successCodes" % ( res), "USERSCRIPT") result = int(1) except: logger.error("UserScript %s has failed" % (command[0]), "USERSCRIPT") result = int(1) final_result = final_result + result num_files_new = 0 for dirpath, dirnames, filenames in os.walk(outputDestination): for file in filenames: filePath = nzbtomedia.os.path.join(dirpath, file) fileName, fileExtension = os.path.splitext(file) if fileExtension in nzbtomedia.USER_SCRIPT_MEDIAEXTENSIONS or nzbtomedia.USER_SCRIPT_MEDIAEXTENSIONS == "ALL": num_files_new = num_files_new + 1 if nzbtomedia.USER_SCRIPT_CLEAN == int(1) and num_files_new == 0 and final_result == 0: logger.info("All files have been processed. Cleaning outputDirectory %s" % (outputDestination)) rmDir(outputDestination) elif nzbtomedia.USER_SCRIPT_CLEAN == int(1) and num_files_new != 0: logger.info("%s files were processed, but %s still remain. outputDirectory will not be cleaned." % ( num_files, num_files_new)) return [final_result, '']
def process(self, section, dirName, inputName=None, status=0, clientAgent="manual", download_id="", inputCategory=None): # Check video files for corruption status = int(status) for video in listMediaFiles(dirName): if not transcoder.isVideoGood(video): status = 1 host = nzbtomedia.CFG[section][inputCategory]["host"] port = nzbtomedia.CFG[section][inputCategory]["port"] apikey = nzbtomedia.CFG[section][inputCategory]["apikey"] method = nzbtomedia.CFG[section][inputCategory]["method"] delete_failed = int( nzbtomedia.CFG[section][inputCategory]["delete_failed"]) wait_for = int(nzbtomedia.CFG[section][inputCategory]["wait_for"]) try: ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"]) except: ssl = 0 try: web_root = nzbtomedia.CFG[section][inputCategory]["web_root"] except: web_root = "" try: remote_path = int( nzbtomedia.CFG[section][inputCategory]["remote_path"]) except: remote_path = 0 if ssl: protocol = "https://" else: protocol = "http://" baseURL = "%s%s:%s%s/api/%s" % (protocol, host, port, web_root, apikey) imdbid = find_imdbid(dirName, inputName) release = self.get_release(baseURL, imdbid, download_id) # pull info from release found if available release_id = None media_id = None downloader = None release_status_old = None if release: try: release_id = release.keys()[0] media_id = release[release_id]['media_id'] download_id = release[release_id]['download_info']['id'] downloader = release[release_id]['download_info']['downloader'] release_status_old = release[release_id]['status'] except: pass process_all_exceptions(inputName.lower(), dirName) inputName, dirName = convert_to_ascii(inputName, dirName) if status == 0: if nzbtomedia.TRANSCODE == 1: result = transcoder.Transcode_directory(dirName) if result == 0: logger.debug( "Transcoding succeeded for files in %s" % (dirName), section) else: logger.warning( "Transcoding failed for files in %s" % (dirName), section) if method == "manage": command = "/manage.update" else: command = "/renamer.scan" params = {} if download_id: params['downloader'] = downloader or clientAgent params['download_id'] = download_id params['media_folder'] = dirName if remote_path: params['media_folder'] = remoteDir(dirName) url = "%s%s" % (baseURL, command) logger.debug("Opening URL: %s with PARAMS: %s" % (url, params), section) logger.postprocess("Starting %s scan for %s" % (method, inputName), section) try: r = requests.get(url, params=params, verify=False) except requests.ConnectionError: logger.error("Unable to open URL", section) return 1 # failure result = r.json() if not r.status_code in [ requests.codes.ok, requests.codes.created, requests.codes.accepted ]: logger.error( "Server returned status %s" % (str(r.status_code)), section) return 1 elif result['success']: logger.postprocess( "SUCCESS: Finished %s scan for folder %s" % (method, dirName), section) else: logger.error( "FAILED: %s scan was unable to finish for folder %s. exiting!" % (method, dirName), section) return 1 # failure # Added a releease that was not in the wanted list so no way to check status, exit without errors if not release: return 0 else: logger.postprocess("FAILED DOWNLOAD DETECTED FOR %s" % (inputName), section) if delete_failed and os.path.isdir( dirName) and not os.path.dirname(dirName) == dirName: logger.postprocess( "Deleting failed files and folder %s" % dirName, section) rmDir(dirName) if not download_id: logger.error( "Could not find a downloaded movie in the database matching %s, exiting!" % inputName, section) return 1 # failure logger.postprocess( "Setting failed release %s to ignored ..." % (inputName), section) url = baseURL + "/release.ignore" params = {'id': release_id} logger.debug("Opening URL: %s with PARAMS: %s" % (url, params), section) try: r = requests.get(url, params=params, verify=False) except requests.ConnectionError: logger.error("Unable to open URL %s" % (url), section) return 1 # failure result = r.json() if result['success']: logger.postprocess( "SUCCESS: %s has been set to ignored ..." % (inputName), section) else: logger.warning( "FAILED: Unable to set %s to ignored!" % (inputName), section) logger.postprocess( "Trying to snatch the next highest ranked release.", section) url = "%s/movie.searcher.try_next" % (baseURL) logger.debug("Opening URL: %s" % (url), section) try: r = requests.get(url, params={'media_id': media_id}) except requests.ConnectionError: logger.error("Unable to open URL %s" % (url), section) return 1 # failure result = r.json() if not r.status_code in [ requests.codes.ok, requests.codes.created, requests.codes.accepted ]: logger.error( "Server returned status %s" % (str(r.status_code)), section) return 1 elif result['success']: logger.postprocess( "SUCCESS: Snatched the next highest release ...", section) return 0 else: logger.postprocess( "FAILED: Unable to find a higher ranked release then %s to snatch!" % (inputName), section) return 1 # we will now check to see if CPS has finished renaming before returning to TorrentToMedia and unpausing. timeout = time.time() + 60 * wait_for while (time.time() < timeout): # only wait 2 (default) minutes, then return. logger.postprocess( "Checking for status change, please stand by ...", section) release = self.get_release(baseURL, imdbid, download_id, release_id) if release: try: release_status_new = release[release_id]['status'] if release_status_new != release_status_old: logger.postprocess( "SUCCESS: Release %s has now been marked with a status of [%s]" % (inputName, str(release_status_new).upper()), section) return 0 # success except: pass # pause and let CouchPotatoServer catch its breath time.sleep(10 * wait_for) # The status hasn't changed. we have waited 2 minutes which is more than enough. uTorrent can resule seeding now. logger.warning( "%s does not appear to have changed status after %s minutes, Please check your logs." % (inputName, wait_for), section) return 1 # failure
def process(self, section, dirName, inputName=None, status=0, clientAgent="manual", download_id="", inputCategory=None): # Check video files for corruption status = int(status) for video in listMediaFiles(dirName): if not transcoder.isVideoGood(video): status = 1 host = nzbtomedia.CFG[section][inputCategory]["host"] port = nzbtomedia.CFG[section][inputCategory]["port"] apikey = nzbtomedia.CFG[section][inputCategory]["apikey"] method = nzbtomedia.CFG[section][inputCategory]["method"] delete_failed = int(nzbtomedia.CFG[section][inputCategory]["delete_failed"]) wait_for = int(nzbtomedia.CFG[section][inputCategory]["wait_for"]) try: ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"]) except: ssl = 0 try: web_root = nzbtomedia.CFG[section][inputCategory]["web_root"] except: web_root = "" try: remote_path = int(nzbtomedia.CFG[section][inputCategory]["remote_path"]) except: remote_path = 0 if ssl: protocol = "https://" else: protocol = "http://" baseURL = "%s%s:%s%s/api/%s" % (protocol, host, port, web_root, apikey) imdbid = find_imdbid(dirName, inputName) release = self.get_release(baseURL, imdbid, download_id) # pull info from release found if available release_id = None media_id = None downloader = None release_status_old = None if release: try: release_id = release.keys()[0] media_id = release[release_id]['media_id'] download_id = release[release_id]['download_info']['id'] downloader = release[release_id]['download_info']['downloader'] release_status_old = release[release_id]['status'] except: pass process_all_exceptions(inputName.lower(), dirName) inputName, dirName = convert_to_ascii(inputName, dirName) if status == 0: if nzbtomedia.TRANSCODE == 1: result = transcoder.Transcode_directory(dirName) if result == 0: logger.debug("Transcoding succeeded for files in %s" % (dirName), section) else: logger.warning("Transcoding failed for files in %s" % (dirName), section) if method == "manage": command = "/manage.update" else: command = "/renamer.scan" params = {} if download_id: params['downloader'] = downloader or clientAgent params['download_id'] = download_id params['media_folder'] = dirName if remote_path: params['media_folder'] = remoteDir(dirName) url = "%s%s" % (baseURL, command) logger.debug("Opening URL: %s with PARAMS: %s" % (url, params), section) logger.postprocess("Starting %s scan for %s" % (method, inputName), section) try: r = requests.get(url, params=params, verify=False) except requests.ConnectionError: logger.error("Unable to open URL", section) return 1 # failure result = r.json() if not r.status_code in [requests.codes.ok, requests.codes.created, requests.codes.accepted]: logger.error("Server returned status %s" % (str(r.status_code)), section) return 1 elif result['success']: logger.postprocess("SUCCESS: Finished %s scan for folder %s" % (method, dirName), section) else: logger.error("FAILED: %s scan was unable to finish for folder %s. exiting!" % (method, dirName), section) return 1 # failure # Added a releease that was not in the wanted list so no way to check status, exit without errors if not release: return 0 else: logger.postprocess("FAILED DOWNLOAD DETECTED FOR %s" % (inputName), section) if delete_failed and os.path.isdir(dirName) and not os.path.dirname(dirName) == dirName: logger.postprocess("Deleting failed files and folder %s" % dirName, section) rmDir(dirName) if not download_id: logger.error("Could not find a downloaded movie in the database matching %s, exiting!" % inputName, section) return 1 # failure logger.postprocess("Setting failed release %s to ignored ..." % (inputName), section) url = baseURL + "/release.ignore" params = {'id': release_id} logger.debug("Opening URL: %s with PARAMS: %s" % (url, params), section) try: r = requests.get(url, params=params, verify=False) except requests.ConnectionError: logger.error("Unable to open URL %s" % (url), section) return 1 # failure result = r.json() if result['success']: logger.postprocess("SUCCESS: %s has been set to ignored ..." % (inputName), section) else: logger.warning("FAILED: Unable to set %s to ignored!" % (inputName), section) logger.postprocess("Trying to snatch the next highest ranked release.", section) url = "%s/movie.searcher.try_next" % (baseURL) logger.debug("Opening URL: %s" % (url), section) try: r = requests.get(url, params={'media_id': media_id}) except requests.ConnectionError: logger.error("Unable to open URL %s" % (url), section) return 1 # failure result = r.json() if not r.status_code in [requests.codes.ok, requests.codes.created, requests.codes.accepted]: logger.error("Server returned status %s" % (str(r.status_code)), section) return 1 elif result['success']: logger.postprocess("SUCCESS: Snatched the next highest release ...", section) return 0 else: logger.postprocess("FAILED: Unable to find a higher ranked release then %s to snatch!" % (inputName), section) return 1 # we will now check to see if CPS has finished renaming before returning to TorrentToMedia and unpausing. timeout = time.time() + 60 * wait_for while (time.time() < timeout): # only wait 2 (default) minutes, then return. logger.postprocess("Checking for status change, please stand by ...", section) release = self.get_release(baseURL, imdbid, download_id, release_id) if release: try: release_status_new = release[release_id]['status'] if release_status_new != release_status_old: logger.postprocess("SUCCESS: Release %s has now been marked with a status of [%s]" % ( inputName, str(release_status_new).upper()), section) return 0 # success except: pass # pause and let CouchPotatoServer catch its breath time.sleep(10 * wait_for) # The status hasn't changed. we have waited 2 minutes which is more than enough. uTorrent can resule seeding now. logger.warning( "%s does not appear to have changed status after %s minutes, Please check your logs." % (inputName, wait_for), section) return 1 # failure
def processEpisode(self, section, dirName, inputName=None, failed=False, clientAgent = "manual", inputCategory=None): # auto-detect correct fork fork, fork_params = autoFork(section, inputCategory) # Check video files for corruption status = int(failed) for video in listMediaFiles(dirName): if not transcoder.isVideoGood(video): status = 1 host = nzbtomedia.CFG[section][inputCategory]["host"] port = nzbtomedia.CFG[section][inputCategory]["port"] try: username = nzbtomedia.CFG[section][inputCategory]["username"] password = nzbtomedia.CFG[section][inputCategory]["password"] except: username = "" password = "" try: apikey = nzbtomedia.CFG[section][inputCategory]["apikey"] except: apikey = "" try: ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"]) except: ssl = 0 try: web_root = nzbtomedia.CFG[section][inputCategory]["web_root"] except: web_root = "" try: delete_failed = int(nzbtomedia.CFG[section][inputCategory]["delete_failed"]) except: delete_failed = 0 try: nzbExtractionBy = nzbtomedia.CFG[section][inputCategory]["nzbExtractionBy"] except: nzbExtractionBy = "Downloader" try: process_method = nzbtomedia.CFG[section][inputCategory]["process_method"] except: process_method = None try: remote_path = int(nzbtomedia.CFG[section][inputCategory]["remote_path"]) except: remote_path = 0 try: wait_for = int(nzbtomedia.CFG[section][inputCategory]["wait_for"]) except: wait_for = 2 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(inputName)) cleanName = os.path.splitext(SpecificPath) if cleanName[1] == ".nzb": SpecificPath = cleanName[0] if os.path.isdir(SpecificPath): dirName = SpecificPath if fork not in nzbtomedia.SICKBEARD_TORRENT or (clientAgent in ['nzbget','sabnzbd'] and nzbExtractionBy != "Destination"): if inputName: process_all_exceptions(inputName.lower(), dirName) inputName, dirName = convert_to_ascii(inputName, dirName) # Now check if tv files exist in destination. Eventually extraction may be done here if nzbExtractionBy == TorrentToMedia if listMediaFiles(dirName): # 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), section) return 0 # Success (as far as this script is concerned) else: logger.warning("No media files found in directory %s. Processing this as a failed download" % (dirName), section) status = 1 failed = 1 # configure SB params to pass fork_params['quiet'] = 1 if inputName is not None: fork_params['nzbName'] = inputName for param in copy.copy(fork_params): if param == "failed": fork_params[param] = failed if param in ["dirName", "dir"]: fork_params[param] = dirName if remote_path: fork_params[param] = remoteDir(dirName) if param == "process_method": if process_method: fork_params[param] = process_method else: del fork_params[param] # delete any unused params so we don't pass them to SB by mistake [fork_params.pop(k) for k,v in fork_params.items() if v is None] if status == 0: logger.postprocess("SUCCESS: The download succeeded, sending a post-process request", section) else: if fork in nzbtomedia.SICKBEARD_FAILED or section == "NzbDrone": logger.postprocess("FAILED: The download failed. Sending 'failed' process request to %s branch" % (fork), section) else: logger.postprocess("FAILED: The download failed. %s branch does not handle failed downloads. Nothing to process" % (fork), section) if delete_failed and os.path.isdir(dirName) and not os.path.dirname(dirName) == dirName: logger.postprocess("Deleting failed files and folder %s" % (dirName), section) rmDir(dirName) return 0 # Success (as far as this script is concerned) if status == 0 and nzbtomedia.TRANSCODE == 1: # only transcode successful downlaods result = transcoder.Transcode_directory(dirName) if result == 0: logger.debug("SUCCESS: Transcoding succeeded for files in %s" % (dirName), section) else: logger.warning("FAILED: Transcoding failed for files in %s" % (dirName), section) if ssl: protocol = "https://" else: protocol = "http://" url = None if section == "SickBeard": url = "%s%s:%s%s/home/postprocess/processEpisode" % (protocol,host,port,web_root) elif section == "NzbDrone": url = "%s%s:%s%s/api/command" % (protocol, host, port, web_root) url1 = "%s%s:%s%s/api/missing" % (protocol, host, port, web_root) headers = {"X-Api-Key": apikey} params = {'sortKey': 'series.title', 'page': 1, 'pageSize': 1, 'sortDir': 'asc'} if remote_path: data = json.dumps({"name": "DownloadedEpisodesScan", "path": remote_path}) else: data = json.dumps({"name": "DownloadedEpisodesScan", "path": dirName}) logger.debug("Opening URL: %s" % (url),section) try: if section == "SickBeard": r = None r = requests.get(url, auth=(username, password), params=fork_params, stream=True, verify=False) elif section == "NzbDrone": start_numMissing = self.numMissing(url1, params, headers) # get current number of outstanding eppisodes. r = None r = requests.post(url, data=data, headers=headers, stream=True, verify=False) except requests.ConnectionError: logger.error("Unable to open URL: %s" % (url), section) return 1 # failure if not r.status_code in [requests.codes.ok, requests.codes.created, requests.codes.accepted]: logger.error("Server returned status %s" % (str(r.status_code)), section) return 1 Success = False Started = False for line in r.iter_lines(): if line: logger.postprocess("%s" % (line), section) if section == "SickBeard" and "Processing succeeded" in line: Success = True elif section == "NzbDrone" and "stateChangeTime" in line: Started = True if status != 0 and delete_failed and not os.path.dirname(dirName) == dirName: logger.postprocess("Deleting failed files and folder %s" % (dirName),section) rmDir(dirName) if Success: return 0 elif section == "NzbDrone" and Started: n = 0 current_numMissing = start_numMissing while n < 6: # set up wait_for minutes of no change in numMissing. time.sleep(10 * wait_for) new_numMissing = self.numMissing(url1, params, headers) if new_numMissing == current_numMissing: # nothing processed since last call n += 1 else: n = 0 current_numMissing = new_numMissing # reset counter and start loop again with this many missing. if current_numMissing < start_numMissing: logger.debug( "The number of missing episodes changes from %s to %s and then remained the same for %s minutes. Consider this successful" % (str(start_numMissing), str(current_numMissing), str(wait_for)), section) return 0 else: # The status hasn't changed. we have waited 2 minutes which is more than enough. uTorrent can resume seeding now. logger.warning( "The number of missing episodes: %s does not appear to have changed status after %s minutes, Please check your logs." % (str(start_numMissing), str(wait_for)), section) return 1 else: return 1 # We did not receive Success confirmation.