def get_nzoid(inputName): nzoid = None logger.debug("Searching for nzoid from SAbnzbd ...") baseURL = "http://%s:%s/api" % (nzbtomedia.SABNZBDHOST, nzbtomedia.SABNZBDPORT) url = baseURL params = {} params['apikey'] = nzbtomedia.SABNZBDAPIKEY params['mode'] = "queue" params['output'] = 'json' try: r = requests.get(url, params=params, verify=False) except requests.ConnectionError: logger.error("Unable to open URL") return nzoid # failure try: result = r.json() cleanName = os.path.splitext(os.path.split(inputName)[1])[0] for slot in result['queue']['slots']: if slot['filename'] in [inputName, cleanName]: nzoid = slot['nzo_id'] logger.debug("Found nzoid: %s" % nzoid) break except: logger.warning("Data from SABnzbd could not be parsed") return nzoid
def find_download(clientAgent, download_id): logger.debug("Searching for Download on %s ..." % (clientAgent)) if clientAgent == 'utorrent': torrents = nzbtomedia.TORRENT_CLASS.list()[1]['torrents'] for torrent in torrents: if download_id in torrent: return True if clientAgent == 'transmission': torrents = nzbtomedia.TORRENT_CLASS.get_torrents() for torrent in torrents: hash = torrent.hashString if hash == download_id: return True if clientAgent == 'deluge': return False if clientAgent == 'sabnzbd': baseURL = "http://%s:%s/api" % (nzbtomedia.SABNZBDHOST, nzbtomedia.SABNZBDPORT) url = baseURL params = {} params['apikey'] = nzbtomedia.SABNZBDAPIKEY params['mode'] = "get_files" params['output'] = 'json' params['value'] = download_id try: r = requests.get(url, params=params, verify=False) except requests.ConnectionError: logger.error("Unable to open URL") return False # failure result = r.json() if result['files']: return True return False
def reverse_filename(filename, dirname, name): head, fileExtension = os.path.splitext(os.path.basename(filename)) na_parts = season_pattern.search(head) if na_parts is not None: word_p = word_pattern.findall(na_parts.group(2)) if word_p: new_words = "" for wp in word_p: if wp[0] == ".": new_words += "." new_words += re.sub(r"\W","",wp) else: new_words = na_parts.group(2) for cr in char_replace: new_words = re.sub(cr[0],cr[1],new_words) newname = new_words[::-1] + na_parts.group(1)[::-1] else: newname = head[::-1].title() newname = newname.replace(' ', '.') logger.debug("Reversing filename %s to %s" % (head, newname), "EXCEPTION") newfile = newname + fileExtension newfilePath = os.path.join(dirname, newfile) try: os.rename(filename, newfilePath) except Exception,e: logger.error("Unable to rename file due to: %s" % (str(e)), "EXCEPTION")
def numMissing(self, url1, params, headers): r = None missing = 0 try: r = requests.get(url1, params=params, headers=headers, stream=True, verify=False) except requests.ConnectionError: logger.error("Unable to open URL: %s" % (url1), section) return missing 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) else: try: res = json.loads(r.content) missing = int(res['totalRecords']) except: pass return missing
def cleanDir(path, section, subsection): if not os.path.exists(path): logger.info('Directory %s has been processed and removed ...' % (path), 'CLEANDIR') return if nzbtomedia.FORCE_CLEAN: logger.info('Doing Forceful Clean of %s' % (path), 'CLEANDIR') rmDir(path) return try: minSize = int(nzbtomedia.CFG[section][subsection]['minSize']) except:minSize = 0 try: delete_ignored = int(nzbtomedia.CFG[section][subsection]['delete_ignored']) except:delete_ignored = 0 try: num_files = len(listMediaFiles(path, minSize=minSize, delete_ignored=delete_ignored)) except: num_files = 'unknown' if num_files > 0: logger.info( "Directory %s still contains %s unprocessed file(s), skipping ..." % (path, num_files), 'CLEANDIRS') return logger.info("Directory %s has been processed, removing ..." % (path), 'CLEANDIRS') try: shutil.rmtree(path, onerror=onerror) except: logger.error("Unable to delete directory %s" % (path))
def getVideoDetails(videofile): video_details = {} result = 1 if not nzbtomedia.FFPROBE: return video_details, result if 'avprobe' in nzbtomedia.FFPROBE: print_format = '-of' else: print_format = '-print_format' try: command = [nzbtomedia.FFPROBE, '-v', 'quiet', print_format, 'json', '-show_format', '-show_streams', '-show_error', videofile] proc = subprocess.Popen(command, stdout=subprocess.PIPE) out, err = proc.communicate() result = proc.returncode video_details = json.loads(out) except: pass if not video_details: try: command = [nzbtomedia.FFPROBE, '-v', 'quiet', print_format, 'json', '-show_format', '-show_streams', videofile] proc = subprocess.Popen(command, stdout=subprocess.PIPE) out, err = proc.communicate() result = proc.returncode video_details = json.loads(out) except: logger.error("Checking [%s] has failed" % (videofile), 'TRANSCODER') return video_details, result
def rename_script(dirname): rename_file = "" for dir, dirs, files in os.walk(dirname): for file in files: if re.search('(rename\S*\.(sh|bat))', file): rename_file = os.path.join(dir, file) dirname = dir break if rename_file: rename_lines = [line.strip() for line in open(rename_file)] for line in rename_lines: cmd = filter(None, re.split('mv|Move\s(\S*)\s(\S*)', line)) if len(cmd) == 2 and os.path.isfile(os.path.join(dirname, cmd[0])): orig = os.path.join(dirname, cmd[0]) dest = os.path.join(dirname, cmd[1].split('\\')[-1].split('/')[-1]) if os.path.isfile(dest): continue logger.debug("Renaming file %s to %s" % (orig, dest), "EXCEPTION") try: os.rename(orig, dest) except Exception, e: logger.error("Unable to rename file due to: %s" % (str(e)), "EXCEPTION")
def isVideoGood(videofile): fileNameExt = os.path.basename(videofile) fileName, fileExt = os.path.splitext(fileNameExt) if fileExt not in nzbtomedia.MEDIACONTAINER: return True if platform.system() == 'Windows': bitbucket = open('NUL') else: bitbucket = open('/dev/null') if not nzbtomedia.FFPROBE: return True command = [nzbtomedia.FFPROBE, videofile] try: logger.info('Checking [%s] for corruption, please stand by ...' % (fileNameExt), 'TRANSCODER') result = call(command, stdout=bitbucket, stderr=bitbucket) except: logger.error("Checking [%s] for corruption has failed" % (fileNameExt), 'TRANSCODER') return False if result == 0: logger.info("SUCCESS: [%s] has no corruption." % (fileNameExt), 'TRANSCODER') return True else: logger.error("FAILED: [%s] is corrupted!" % (fileNameExt), 'TRANSCODER') return False
def extract_subs(file, newfilePath, bitbucket): video_details = getVideoDetails(file) if not video_details: return subStreams = [item for item in video_details["streams"] if item["codec_type"] == "subtitle"] if nzbtomedia.SUBSDIR: subdir = nzbtomedia.SUBSDIR else: subdir = os.path.split(newfilePath)[0] name = os.path.splitext(os.path.split(newfilePath)[1])[0] for n in range(len(subStreams)): sub = subStreams[n] lan = sub["tags"]["language"] outputFile = os.path.join(subdir, "%s(%s).srt" %(name, lan)) if os.path.isfile(outputFile): outputFile = os.path.join(subdir, "%s(%s)%s.srt" %(name, n, lan)) command = [nzbtomedia.FFMPEG, '-loglevel', 'warning', '-i', sub, '-vn', '-an', '-codec:s:' + str(n), 'srt', outputFile] if platform.system() != 'Windows': command = ['nice', '-%d' % nzbtomedia.NICENESS] + command logger.info("Extracting %s Subtitle from: %s" % (lan, 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, stdout=bitbucket, stderr=bitbucket) except: logger.error("Extracting subtitles has failed") if result == 0: logger.info("Extracting %s Subtitle from %s has succeeded" % (lan, file)) else: logger.error("Extracting subtitles has failed")
def isVideoGood(videofile, status): fileNameExt = os.path.basename(videofile) fileName, fileExt = os.path.splitext(fileNameExt) if fileExt not in nzbtomedia.MEDIACONTAINER or not nzbtomedia.FFPROBE: if status: # if the download was "failed", assume bad. If it was successful, assume good. return False else: return True logger.info('Checking [%s] for corruption, please stand by ...' % (fileNameExt), 'TRANSCODER') video_details, result = getVideoDetails(videofile) if result != 0: logger.error("FAILED: [%s] is corrupted!" % (fileNameExt), 'TRANSCODER') return False if video_details.get("error"): logger.info("FAILED: [%s] returned error [%s]." % (fileNameExt, str(video_details.get("error"))), 'TRANSCODER') return False if video_details.get("streams"): videoStreams = [item for item in video_details["streams"] if item["codec_type"] == "video"] audioStreams = [item for item in video_details["streams"] if item["codec_type"] == "audio"] if len(videoStreams) > 0 and len(audioStreams) > 0: logger.info("SUCCESS: [%s] has no corruption." % (fileNameExt), 'TRANSCODER') return True else: logger.info("FAILED: [%s] has %s video streams and %s audio streams. Assume corruption." % (fileNameExt, str(len(videoStreams)), str(len(audioStreams))), 'TRANSCODER') return False
def process(nzbDir, inputName=None, status=0, clientAgent='manual', download_id=None, inputCategory=None): result = 0 # auto-detect section section = nzbtomedia.CFG.findsection(inputCategory) if section: logger.info("Sending %s to %s for post-processing ..." % (inputName, str(section).upper())) else: logger.error("We could not find a section with containing a download category labeled %s in your autoProcessMedia.cfg, Exiting!" % inputCategory) if nzbtomedia.CFG["CouchPotato"][inputCategory]: result = autoProcessMovie().process(nzbDir, inputName, status, clientAgent, download_id, inputCategory) elif nzbtomedia.CFG["SickBeard", "NzbDrone"][inputCategory]: result = autoProcessTV().processEpisode(nzbDir, inputName, status, clientAgent, inputCategory) elif nzbtomedia.CFG["HeadPhones"][inputCategory]: result = autoProcessMusic().process(nzbDir, inputName, status, clientAgent, inputCategory) elif nzbtomedia.CFG["Mylar"][inputCategory]: result = autoProcessComics().processEpisode(nzbDir, inputName, status, clientAgent, inputCategory) elif nzbtomedia.CFG["Gamez"][inputCategory]: result = autoProcessGames().process(nzbDir, inputName, status, clientAgent, inputCategory) if result == 0: # Clean up any leftover files cleanup_directories(inputCategory, section, result, nzbDir) return result
def zip_out(file, img, bitbucket): procin = None cmd = [nzbtomedia.SEVENZIP, '-so', 'e', img, file] try: procin = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=bitbucket) except: logger.error("Extracting [%s] has failed" % (file), 'TRANSCODER') return procin
def processEpisode(self, dirName, nzbName=None, status=0, clientAgent='manual', inputCategory=None): # auto-detect correct section section = nzbtomedia.CFG.findsection(inputCategory) if not section: logger.error( "We were unable to find a section for category %s, please check your autoProcessMedia.cfg file." % inputCategory) return 1 host = nzbtomedia.CFG[section][inputCategory]["host"] port = nzbtomedia.CFG[section][inputCategory]["port"] username = nzbtomedia.CFG[section][inputCategory]["username"] password = nzbtomedia.CFG[section][inputCategory]["password"] try: ssl = int(nzbtomedia.CFG[section][inputCategory]["ssl"]) except: ssl = 0 try: web_root = nzbtomedia.CFG[section][inputCategory]["web_root"] except: web_root = "" try: remote_path = nzbtomedia.CFG[section][inputCategory]["remote_path"] except: remote_path = None nzbName, dirName = convert_to_ascii(nzbName, dirName) params = {} params['nzb_folder'] = dirName if remote_path: dirName_new = os.path.join(remote_path, os.path.basename(dirName)).replace("\\", "/") params['nzb_folder'] = dirName_new if nzbName != None: params['nzb_name'] = nzbName if ssl: protocol = "https://" else: protocol = "http://" url = "%s%s:%s%s/post_process" % (protocol, host, port, web_root) logger.debug("Opening URL: %s" % (url), section) try: r = requests.get(url, params=params, auth=(username, password), stream=True) except requests.ConnectionError: logger.error("Unable to open URL", section) return 1 # failure for line in r.iter_lines(): if line: logger.postprocess("%s" % (line), section) time.sleep(60) #wait 1 minute for now... need to see just what gets logged and how long it takes to process return 0 # Success
def processList(List, newDir, bitbucket): remList = [] newList = [] delList = [] combine = [] vtsPath = None success = True for item in List: newfile = None ext = os.path.splitext(item)[1].lower() if ext in ['.iso', '.bin'] and not ext in nzbtomedia.IGNOREEXTENSIONS: logger.debug("Attempting to rip disk image: %s" % (item), "TRANSCODER") newList.extend(ripISO(item, newDir, bitbucket)) remList.append(item) elif re.match(".+VTS_[0-9][0-9]_[0-9].[Vv][Oo][Bb]", item) and not '.vob' in nzbtomedia.IGNOREEXTENSIONS: logger.debug("Found VIDEO_TS image file: %s" % (item), "TRANSCODER") if not vtsPath: try: vtsPath = re.match("(.+VIDEO_TS)", item).groups()[0] except: vtsPath = os.path.split(item)[0] remList.append(item) elif re.match(".+VIDEO_TS.", item) or re.match( ".+VTS_[0-9][0-9]_[0-9].", item): remList.append(item) elif nzbtomedia.CONCAT and re.match(".+[cC][dD][0-9].", item): remList.append(item) combine.append(item) else: continue if vtsPath: newList.extend(combineVTS(vtsPath)) if combine: newList.extend(combineCD(combine)) for file in newList: if isinstance( file, str) and not 'concat:' in file and not os.path.isfile(file): success = False break if success and newList: List.extend(newList) for item in remList: List.remove(item) logger.debug( "Successfully extracted .vob file %s from disk image" % (newList[0]), "TRANSCODER") elif newList and not success: newList = [] remList = [] logger.error( "Failed extracting .vob files from disk image. Stopping transcoding.", "TRANSCODER") return List, remList, newList, success
def rename_file(filename, newfilePath): logger.debug( "Replacing file name %s with download name %s" % (filename, newfilePath), "EXCEPTION") try: os.rename(filename, newfilePath) except Exception, e: logger.error("Unable to rename file due to: %s" % (str(e)), "EXCEPTION")
def extract_subs(file, newfilePath, bitbucket): video_details, result = getVideoDetails(file) if not video_details: return if nzbtomedia.SUBSDIR: subdir = nzbtomedia.SUBSDIR else: subdir = os.path.split(newfilePath)[0] name = os.path.splitext(os.path.split(newfilePath)[1])[0] try: subStreams = [item for item in video_details["streams"] if item["codec_type"] == "subtitle" and item["tags"]["language"] in nzbtomedia.SLANGUAGES and item["codec_name"] != "hdmv_pgs_subtitle" and item["codec_name"] != "pgssub"] except: subStreams = [item for item in video_details["streams"] if item["codec_type"] == "subtitle" and item["codec_name"] != "hdmv_pgs_subtitle" and item["codec_name"] != "pgssub"] num = len(subStreams) for n in range(num): sub = subStreams[n] idx = sub["index"] try: lan = sub["tags"]["language"] except: lan = "unk" if num == 1: outputFile = os.path.join(subdir, "%s.srt" %(name)) if os.path.isfile(outputFile): outputFile = os.path.join(subdir, "%s.%s.srt" %(name, n)) else: outputFile = os.path.join(subdir, "%s.%s.srt" %(name, lan)) if os.path.isfile(outputFile): outputFile = os.path.join(subdir, "%s.%s.%s.srt" %(name, lan, n)) command = [nzbtomedia.FFMPEG, '-loglevel', 'warning', '-i', file, '-vn', '-an', '-codec:' + str(idx), 'srt', outputFile] if platform.system() != 'Windows': command = nzbtomedia.NICENESS + command logger.info("Extracting %s subtitle from: %s" % (lan, file)) cmd = "" for item in command: cmd = cmd + " " + str(item) logger.debug("Calling command: %s" % (cmd)) result = 1 # set result to failed in case call fails. try: result = call(command, stdout=bitbucket, stderr=bitbucket) except: logger.error("Extracting subtitle has failed") if result == 0: try: shutil.copymode(file, outputFile) except: pass logger.info("Extracting %s subtitle from %s has succeeded" % (lan, file)) else: logger.error("Extracting subtitles has failed")
def getVideoDetails(videofile, img=None, bitbucket=None): video_details = {} result = 1 file = videofile if not nzbtomedia.FFPROBE: return video_details, result if 'avprobe' in nzbtomedia.FFPROBE: print_format = '-of' else: print_format = '-print_format' try: if img: videofile = '-' command = [ nzbtomedia.FFPROBE, '-v', 'quiet', print_format, 'json', '-show_format', '-show_streams', '-show_error', videofile ] print_cmd(command) if img: procin = zip_out(file, img, bitbucket) proc = subprocess.Popen(command, stdout=subprocess.PIPE, stdin=procin.stdout) procin.stdout.close() else: proc = subprocess.Popen(command, stdout=subprocess.PIPE) out, err = proc.communicate() result = proc.returncode video_details = json.loads(out) except: pass if not video_details: try: command = [ nzbtomedia.FFPROBE, '-v', 'quiet', print_format, 'json', '-show_format', '-show_streams', videofile ] if img: procin = zip_out(file, img) proc = subprocess.Popen(command, stdout=subprocess.PIPE, stdin=procin.stdout) procin.stdout.close() else: proc = subprocess.Popen(command, stdout=subprocess.PIPE) out, err = proc.communicate() result = proc.returncode video_details = json.loads(out) except: logger.error("Checking [%s] has failed" % (file), 'TRANSCODER') return video_details, result
def flatten(outputDestination): logger.info("FLATTEN: Flattening directory: %s" % (outputDestination)) for dirpath, dirnames, filenames in os.walk( outputDestination): # Flatten out the directory to make postprocessing easier if dirpath == outputDestination: continue # No need to try and move files in the root destination directory for filename in filenames: source = os.path.join(dirpath, filename) target = os.path.join(outputDestination, filename) try: shutil.move(source, target) except: logger.error("FLATTEN: Could not flatten %s" % (source)) removeEmptyFolders(outputDestination) # Cleanup empty directories
def replaceExtensions(path): for dirpath, dirnames, filesnames in os.walk(path): for filename in filesnames: name, ext = os.path.splitext(filename) if ext in nzbtomedia.EXT_REPLACE: file = os.path.join(dirpath, filename) target = os.path.join(dirpath, name + nzbtomedia.EXT_REPLACE[ext]) try: logger.debug("Renaming %s to %s" % (file, target), 'RENAME') shutil.move(file, target) except: logger.error("Could not rename %s to %s" % (file, target), 'RENAME') else: continue
def reportNzb(failure_link, clientAgent): # Contact indexer site logger.info("Sending failure notification to indexer site") if clientAgent == 'nzbget': headers = {'User-Agent' : 'NZBGet / nzbToMedia.py'} elif clientAgent == 'sabnzbd': headers = {'User-Agent' : 'SABnzbd / nzbToMedia.py'} else: return try: r = requests.post(failure_link, headers=headers) except Exception as e: logger.error("Unable to open URL %s due to %s" % (failure_link, e)) return
def get_status(self, url, apikey, dirName): logger.debug("Attempting to get current status for release:%s" % (os.path.basename(dirName))) params = {} params['apikey'] = apikey params['cmd'] = "getHistory" logger.debug("Opening URL: %s with PARAMS: %s" % (url, params)) try: r = requests.get(url, params=params, verify=False) except Exception, e: logger.error("Unable to open URL") return None
def get_status(self, url, apikey, dirName): logger.debug("Attempting to get current status for release:%s" % (os.path.basename(dirName))) params = {} params['apikey'] = apikey params['cmd'] = "getHistory" logger.debug("Opening URL: %s with PARAMS: %s" % (url, params)) try: r = requests.get(url, params=params, verify=False) except Exception, e: logger.error("Unable to open URL") return
def extractFiles(src, dst=None): extracted_folder = [] for inputFile in listMediaFiles(src, media=False, audio=False, meta=False, archives=True): dirPath = os.path.dirname(inputFile) fullFileName = os.path.basename(inputFile) if dirPath in extracted_folder: break try: if extractor.extract(inputFile, dirPath or dst): extracted_folder.append(dirPath or dst) except Exception, e: logger.error("Extraction failed for: %s" % (fullFileName))
def find_imdbid(dirName, inputName): imdbid = None logger.info('Attemping imdbID lookup for %s' % (inputName)) # find imdbid in dirName logger.info('Searching folder and file names for imdbID ...') m = re.search('(tt\d{7})', dirName + inputName) if m: imdbid = m.group(1) logger.info("Found imdbID [%s]" % imdbid) return imdbid logger.info('Searching IMDB for imdbID ...') guess = guessit.guess_movie_info(inputName) if guess: # Movie Title title = None if 'title' in guess: title = guess['title'] # Movie Year year = None if 'year' in guess: year = guess['year'] url = "http://www.omdbapi.com" logger.debug("Opening URL: %s" % url) try: r = requests.get(url, params={'y': year, 't': title}, verify=False) except requests.ConnectionError: logger.error("Unable to open URL %s" % url) return results = r.json() try: imdbid = results['imdbID'] except: pass if imdbid: logger.info("Found imdbID [%s]" % imdbid) return imdbid logger.warning('Unable to find a imdbID for %s' % (inputName))
def find_imdbid(dirName, inputName): imdbid = None logger.info('Attemping imdbID lookup for %s' % (inputName)) # find imdbid in dirName logger.info('Searching folder and file names for imdbID ...') m = re.search('(tt\d{7})', dirName+inputName) if m: imdbid = m.group(1) logger.info("Found imdbID [%s]" % imdbid) return imdbid logger.info('Searching IMDB for imdbID ...') guess = guessit.guess_movie_info(inputName) if guess: # Movie Title title = None if 'title' in guess: title = guess['title'] # Movie Year year = None if 'year' in guess: year = guess['year'] url = "http://www.omdbapi.com" logger.debug("Opening URL: %s" % url) try: r = requests.get(url, params={'y': year, 't': title}, verify=False) except requests.ConnectionError: logger.error("Unable to open URL %s" % url) return results = r.json() try: imdbid = results['imdbID'] except: pass if imdbid: logger.info("Found imdbID [%s]" % imdbid) return imdbid logger.warning('Unable to find a imdbID for %s' % (inputName))
def need_update(self): if not self._find_installed_version(): logger.error("Unable to determine installed version via git, please check your logs!") return False if not self._cur_commit_hash: return True else: try: self._check_github_for_update() except Exception, e: logger.log(u"Unable to contact github, can't check for update: " + repr(e), logger.ERROR) return False if self._num_commits_behind > 0: return True
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 is_minSize(inputName, minSize): fileName, fileExt = os.path.splitext(os.path.basename(inputName)) # audio files we need to check directory size not file size inputSize = os.path.getsize(inputName) if fileExt in (nzbtomedia.AUDIOCONTAINER): try: inputSize = getDirSize(os.path.dirname(inputName)) except: logger.error("Failed to get file size for %s" % (inputName), 'MINSIZE') return True # Ignore files under a certain size if inputSize > minSize * 1048576: return True
def flatten(outputDestination): logger.info("FLATTEN: Flattening directory: %s" % (outputDestination)) for outputFile in listMediaFiles(outputDestination): dirPath = os.path.dirname(outputFile) fileName = os.path.basename(outputFile) if dirPath == outputDestination: continue target = os.path.join(outputDestination, fileName) try: shutil.move(outputFile, target) except: logger.error("Could not flatten %s" % (outputFile), 'FLATTEN') removeEmptyFolders(outputDestination) # Cleanup empty directories
def replace_filename(filename, dirname, name): head, fileExtension = os.path.splitext(os.path.basename(filename)) if media_pattern.search(os.path.basename(dirname).replace(' ','.')) is not None: newname = os.path.basename(dirname).replace(' ', '.') logger.debug("Replacing file name %s with directory name %s" % (head, newname), "EXCEPTION") elif media_pattern.search(name.replace(' ','.').lower()) is not None: newname = name.replace(' ', '.') logger.debug("Replacing file name %s with download name %s" % (head, newname), "EXCEPTION") else: logger.warning("No name replacement determined for %s" % (head), "EXCEPTION") return newfile = newname + fileExtension newfilePath = os.path.join(dirname, newfile) try: os.rename(filename, newfilePath) except Exception,e: logger.error("Unable to rename file due to: %s" % (str(e)), "EXCEPTION")
def processList(List, newDir, bitbucket): remList = [] newList = [] delList = [] combine = [] vtsPath = None success = True for item in List: newfile = None ext = os.path.splitext(item)[1].lower() if ext in ['.iso', '.bin'] and not ext in nzbtomedia.IGNOREEXTENSIONS: logger.debug("Attempting to rip disk image: %s" % (item), "TRANSCODER") newList.extend(ripISO(item, newDir, bitbucket)) remList.append(item) elif re.match(".+VTS_[0-9][0-9]_[0-9].[Vv][Oo][Bb]", item) and not '.vob' in nzbtomedia.IGNOREEXTENSIONS: logger.debug("Found VIDEO_TS image file: %s" % (item), "TRANSCODER") if not vtsPath: try: vtsPath = re.match("(.+VIDEO_TS)",item).groups()[0] except: vtsPath = os.path.split(item)[0] remList.append(item) elif re.match(".+VIDEO_TS.", item) or re.match(".+VTS_[0-9][0-9]_[0-9].", item): remList.append(item) elif nzbtomedia.CONCAT and re.match(".+[cC][dD][0-9].", item): remList.append(item) combine.append(item) else: continue if vtsPath: newList.extend(combineVTS(vtsPath)) if combine: newList.extend(combineCD(combine)) for file in newList: if isinstance(file, str) and not 'concat:' in file and not os.path.isfile(file): success = False break if success and newList: List.extend(newList) for item in remList: List.remove(item) logger.debug("Successfully extracted .vob file %s from disk image" % (newList[0]), "TRANSCODER") elif newList and not success: newList = [] remList = [] logger.error("Failed extracting .vob files from disk image. Stopping transcoding.", "TRANSCODER") return List, remList, newList, success
def numMissing(self, url1, params, headers, section): r = None missing = 0 try: r = requests.get(url1, params=params, headers=headers, stream=True, verify=False) except requests.ConnectionError: logger.error("Unable to open URL: %s" % (url1), section) return missing 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) else: try: res = json.loads(r.content) missing = int(res['totalRecords']) except: pass return missing
def extractFiles(src, dst=None): extracted_folder = [] extracted_archive = [] for inputFile in listMediaFiles(src, media=False, audio=False, meta=False, archives=True): dirPath = os.path.dirname(inputFile) fullFileName = os.path.basename(inputFile) archiveName = os.path.splitext(fullFileName)[0] archiveName = re.sub(r"part[0-9]+", "", archiveName) if dirPath in extracted_folder and archiveName in extracted_archive: continue # no need to extract this, but keep going to look for other archives and sub directories. try: if extractor.extract(inputFile, dirPath or dst): extracted_folder.append(dirPath or dst) extracted_archive.append(archiveName) except Exception, e: logger.error("Extraction failed for: %s" % (fullFileName))
def getVideoDetails(videofile): video_details = {} result = 1 if not nzbtomedia.FFPROBE: return video_details, result try: command = [ nzbtomedia.FFPROBE, "-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", "-show_error", videofile, ] proc = subprocess.Popen(command, stdout=subprocess.PIPE) out, err = proc.communicate() result = proc.returncode video_details = json.loads(out) except: pass if not video_details: try: command = [ nzbtomedia.FFPROBE, "-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", videofile, ] proc = subprocess.Popen(command, stdout=subprocess.PIPE) out, err = proc.communicate() result = proc.returncode video_details = json.loads(out) except: logger.error("Checking [%s] has failed" % (videofile), "TRANSCODER") return video_details, result
def copy_link(filePath, targetDirectory, useLink, outputDestination): if os.path.isfile(targetDirectory): logger.info("COPYLINK: target file already exists. Nothing to be done") return True makeDir(outputDestination) if useLink == "hard": try: logger.info("COPYLINK: Hard linking %s to %s" % (filePath, targetDirectory)) linktastic.link(filePath, targetDirectory) except: logger.error("COPYLINK") if os.path.isfile(targetDirectory): logger.warning( "COPYLINK: Something went wrong in linktastic.link, but the destination file was created") else: logger.warning("COPYLINK: Something went wrong in linktastic.link, copying instead") logger.debug("COPYLINK: Copying %s to %s" % (filePath, targetDirectory)) shutil.copy(filePath, targetDirectory) elif useLink == "sym": try: logger.info("COPYLINK: Moving %s to %s before sym linking" % (filePath, targetDirectory)) shutil.move(filePath, targetDirectory) logger.info("COPYLINK: Sym linking %s to %s" % (targetDirectory, filePath)) linktastic.symlink(targetDirectory, filePath) except: logger.error("COPYLINK") if os.path.isfile(targetDirectory): logger.warning( "COPYLINK: Something went wrong in linktastic.link, but the destination file was created") else: logger.info("COPYLINK: Something went wrong in linktastic.link, copying instead") logger.debug("COPYLINK: Copying %s to %s" % (filePath, targetDirectory)) shutil.copy(filePath, targetDirectory) elif useLink == "move": logger.debug("Moving %s to %s" % (filePath, targetDirectory)) shutil.move(filePath, targetDirectory) else: logger.debug("Copying %s to %s" % (filePath, targetDirectory)) shutil.copy(filePath, targetDirectory) return True
def isVideoGood(videofile, status): fileNameExt = os.path.basename(videofile) fileName, fileExt = os.path.splitext(fileNameExt) disable = False if fileExt not in nzbtomedia.MEDIACONTAINER or not nzbtomedia.FFPROBE or not nzbtomedia.CHECK_MEDIA or fileExt in ['.iso']: disable = True else: test_details, res = getVideoDetails(nzbtomedia.TEST_FILE) if res !=0 or test_details.get("error"): disable = True logger.info("DISABLED: ffprobe failed to analyse test file. Stopping corruption check.", 'TRANSCODER') if test_details.get("streams"): vidStreams = [item for item in test_details["streams"] if item["codec_type"] == "video"] audStreams = [item for item in test_details["streams"] if item["codec_type"] == "audio"] if not (len(vidStreams) > 0 and len(audStreams) > 0): disable = True logger.info("DISABLED: ffprobe failed to analyse streams from test file. Stopping corruption check.", 'TRANSCODER') if disable: if status: # if the download was "failed", assume bad. If it was successful, assume good. return False else: return True logger.info('Checking [%s] for corruption, please stand by ...' % (fileNameExt), 'TRANSCODER') video_details, result = getVideoDetails(videofile) if result != 0: logger.error("FAILED: [%s] is corrupted!" % (fileNameExt), 'TRANSCODER') return False if video_details.get("error"): logger.info("FAILED: [%s] returned error [%s]." % (fileNameExt, str(video_details.get("error"))), 'TRANSCODER') return False if video_details.get("streams"): videoStreams = [item for item in video_details["streams"] if item["codec_type"] == "video"] audioStreams = [item for item in video_details["streams"] if item["codec_type"] == "audio"] if len(videoStreams) > 0 and len(audioStreams) > 0: logger.info("SUCCESS: [%s] has no corruption." % (fileNameExt), 'TRANSCODER') return True else: logger.info("FAILED: [%s] has %s video streams and %s audio streams. Assume corruption." % (fileNameExt, str(len(videoStreams)), str(len(audioStreams))), 'TRANSCODER') return False
def process(nzbDir, inputName=None, status=0, clientAgent='manual', download_id=None, inputCategory=None): result = 0 # auto-detect section section = nzbtomedia.CFG.findsection(inputCategory) if section: logger.info("Sending %s to %s for post-processing ..." % (inputName, str(section).upper())) else: logger.error( "We could not find a section with containing a download category labeled %s in your autoProcessMedia.cfg, Exiting!" % inputCategory) if nzbtomedia.CFG["CouchPotato"][inputCategory]: result = autoProcessMovie().process(nzbDir, inputName, status, clientAgent, download_id, inputCategory) elif nzbtomedia.CFG["SickBeard", "NzbDrone"][inputCategory]: result = autoProcessTV().processEpisode(nzbDir, inputName, status, clientAgent, inputCategory) elif nzbtomedia.CFG["HeadPhones"][inputCategory]: result = autoProcessMusic().process(nzbDir, inputName, status, clientAgent, inputCategory) elif nzbtomedia.CFG["Mylar"][inputCategory]: result = autoProcessComics().processEpisode(nzbDir, inputName, status, clientAgent, inputCategory) elif nzbtomedia.CFG["Gamez"][inputCategory]: result = autoProcessGames().process(nzbDir, inputName, status, clientAgent, inputCategory) if result == 0: # Clean up any leftover files cleanup_directories(inputCategory, section, result, nzbDir) return result
def create_torrent_class(clientAgent): # Hardlink solution for Torrents tc = None if clientAgent == 'utorrent': try: logger.debug("Connecting to %s: %s" % (clientAgent, nzbtomedia.UTORRENTWEBUI)) tc = UTorrentClient(nzbtomedia.UTORRENTWEBUI, nzbtomedia.UTORRENTUSR, nzbtomedia.UTORRENTPWD) except: logger.error("Failed to connect to uTorrent") if clientAgent == 'transmission': try: logger.debug("Connecting to %s: http://%s:%s" % ( clientAgent, nzbtomedia.TRANSMISSIONHOST, nzbtomedia.TRANSMISSIONPORT)) tc = TransmissionClient(nzbtomedia.TRANSMISSIONHOST, nzbtomedia.TRANSMISSIONPORT, nzbtomedia.TRANSMISSIONUSR, nzbtomedia.TRANSMISSIONPWD) except: logger.error("Failed to connect to Transmission") if clientAgent == 'deluge': try: logger.debug("Connecting to %s: http://%s:%s" % (clientAgent, nzbtomedia.DELUGEHOST, nzbtomedia.DELUGEPORT)) tc = DelugeClient() tc.connect(host=nzbtomedia.DELUGEHOST, port=nzbtomedia.DELUGEPORT, username=nzbtomedia.DELUGEUSR, password=nzbtomedia.DELUGEPWD) except: logger.error("Failed to connect to Deluge") return tc
def get_status(self, baseURL, apikey, dirName): logger.debug("Attempting to get current status for release:%s" % (os.path.basename(dirName))) url = baseURL params = {} params['apikey'] = apikey params['cmd'] = "getHistory" logger.debug("Opening URL: %s" % (url)) try: r = requests.get(url, params=params) except requests.ConnectionError: logger.error("Unable to open URL") return None, None try: result = r.json() for album in result: if os.path.basename(dirName) == album['FolderName']: return album["Status"].lower() except:pass
def import_subs(filename): if not nzbtomedia.GETSUBS: return try: subliminal.cache_region.configure('dogpile.cache.memory') except: pass languages = set() for item in nzbtomedia.SLANGUAGES: try: languages.add(Language(item)) except: pass if not languages: return logger.debug("Attempting to download subtitles for %s" %(filename), 'SUBTITLES') try: video = subliminal.scan_video(filename, subtitles=True, embedded_subtitles=True) subtitles = subliminal.download_best_subtitles([video], languages, hearing_impaired=False) subliminal.save_subtitles(subtitles) except Exception as e: logger.error("Failed to download subtitles for %s due to: %s" %(filename, e), 'SUBTITLES')
def ripISO(item, newDir, bitbucket): newFiles = [] failure_dir = 'failure' # Mount the ISO in your OS and call combineVTS. if not nzbtomedia.SEVENZIP: logger.error("No 7zip installed. Can't extract image file %s" % (item), "TRANSCODER") newFiles = [failure_dir] return newFiles cmd = [nzbtomedia.SEVENZIP, 'l', item] try: logger.debug("Attempting to extract .vob from image file %s" % (item), "TRANSCODER") print_cmd(cmd) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=bitbucket) out, err = proc.communicate() result = proc.returncode fileList = [ re.match(".+(VIDEO_TS[\\\/]VTS_[0-9][0-9]_[0-9].[Vv][Oo][Bb])", line).groups()[0] for line in out.splitlines() if re.match( ".+VIDEO_TS[\\\/]VTS_[0-9][0-9]_[0-9].[Vv][Oo][Bb]", line) ] combined = [] for n in range(99): concat = [] m = 1 while True: vtsName = 'VIDEO_TS%sVTS_%02d_%d.VOB' % (os.sep, n + 1, m) if vtsName in fileList: concat.append(vtsName) m += 1 else: break if not concat: break if nzbtomedia.CONCAT: combined.extend(concat) continue name = '%s.cd%s' % (os.path.splitext( os.path.split(item)[1])[0], str(n + 1)) newFiles.append({item: {'name': name, 'files': concat}}) if nzbtomedia.CONCAT: name = os.path.splitext(os.path.split(item)[1])[0] newFiles.append({item: {'name': name, 'files': combined}}) if not newFiles: logger.error("No VIDEO_TS folder found in image file %s" % (item), "TRANSCODER") newFiles = [failure_dir] except: logger.error("Failed to extract from image file %s" % (item), "TRANSCODER") newFiles = [failure_dir] return newFiles
def main(args): # Initialize the config nzbtomedia.initialize() # clientAgent for Torrents clientAgent = nzbtomedia.TORRENT_CLIENTAGENT logger.info("#########################################################") logger.info("## ..::[%s]::.. CLIENT:%s ## STARTING" % (args[0], clientAgent)) logger.info("#########################################################") # debug command line options logger.debug("Options passed into TorrentToMedia: %s" % (args)) # Post-Processing Result result = 0 try: inputDirectory, inputName, inputCategory, inputHash, inputID = parse_args(clientAgent, args) except: logger.error("There was a problem loading variables") return -1 if inputDirectory and inputName and inputHash and inputID: result = processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID, clientAgent) else: # Perform Manual Run logger.warning("Invalid number of arguments received from client, Switching to manual run mode ...") # Loop and auto-process clientAgent = 'manual' for section, subsection in nzbtomedia.SUBSECTIONS.items(): for category in subsection: if nzbtomedia.CFG[section][category].isenabled(): dirNames = get_dirnames(section, category) for dirName in dirNames: logger.info("Running %s:%s as a manual run for folder %s ..." % (section, category, dirName)) results = processTorrent(dirName, os.path.basename(dirName), category, inputHash, inputID, clientAgent) if results != 0: result = results logger.error("A problem was reported when trying to manually run %s:%s." % (section, category)) else: logger.warning("%s:%s is DISABLED, you can enable this in autoProcessMedia.cfg ..." % (section, category)) if result == 0: logger.info("The %s script completed successfully." % (args[0])) else: logger.error("A problem was reported in the %s script." % (args[0])) sys.exit(result)
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 process(self, dirName, nzbName=None, status=0, clientAgent="manual", inputCategory=None): # auto-detect correct section section = nzbtomedia.CFG.findsection(inputCategory) if len(section) == 0: logger.error( "We were unable to find a section for category %s, please check your autoProcessMedia.cfg file." % (inputCategory)) return 1 status = int(status) host = nzbtomedia.CFG[section][inputCategory]["host"] port = nzbtomedia.CFG[section][inputCategory]["port"] apikey = nzbtomedia.CFG[section][inputCategory]["apikey"] 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 = nzbtomedia.CFG[section][inputCategory]["remote_path"] except: remote_path = None if ssl: protocol = "https://" else: protocol = "http://" nzbName, dirName = convert_to_ascii(nzbName, dirName) url = "%s%s:%s%s/api" % (protocol,host,port,web_root) if status == 0: params = {} params['apikey'] = apikey params['cmd'] = "forceProcess" params['dir'] = os.path.dirname(dirName) if remote_path: dirName_new = os.path.join(remote_path, os.path.basename(os.path.dirname(dirName))).replace("\\", "/") params['dir'] = dirName_new release_status = self.get_status(url, apikey, dirName) if release_status: if release_status not in ["unprocessed", "snatched"]: logger.warning("%s is marked with a status of %s, skipping ..." % (nzbName, release_status),section) return 0 else: logger.error("Could not find a status for %s" % (nzbName),section) return 1 logger.debug("Opening URL: %s" % (url),section) try: r = requests.get(url, params=params) except requests.ConnectionError: logger.error("Unable to open URL %s" % (url),section) return 1 # failure logger.debug("Result: %s" % (r.text),section) if r.text == "OK": logger.postprocess("SUCCESS: Post-Processing started for %s in folder %s ..." % (nzbName, dirName),section) else: logger.error("FAILED: Post-Processing has NOT started for %s in folder %s. exiting!" % (nzbName, dirName),section) return 1 # failure else: logger.warning("FAILED DOWNLOAD DETECTED", section) return 0 # Success (as far as this script is concerned) # we will now wait 1 minutes for this album to be processed before returning to TorrentToMedia and unpausing. timeout = time.time() + 60 * wait_for while (time.time() < timeout): # only wait 2 (default) minutes, then return. current_status = self.get_status(url, apikey, dirName) if current_status is not None and current_status != release_status: # Something has changed. CPS must have processed this movie. logger.postprocess("SUCCESS: This release is now marked as status [%s]" % (current_status),section) return 0 time.sleep(10 * wait_for) # The status hasn't changed. we have waited 2 minutes which is more than enough. uTorrent can resule seeding now. logger.warning("The music album does not appear to have changed status after %s minutes. Please check your Logs" % (wait_for)) return 1 # failure
def main(args): # Initialize the config nzbtomedia.initialize() # clientAgent for Torrents clientAgent = nzbtomedia.TORRENT_CLIENTAGENT logger.info("#########################################################") logger.info("## ..::[%s]::.. ##" % os.path.basename(__file__)) logger.info("#########################################################") # debug command line options logger.debug("Options passed into TorrentToMedia: %s" % (args)) # Post-Processing Result result = 0 try: inputDirectory, inputName, inputCategory, inputHash, inputID = nzbtomedia.parse_args( clientAgent, args) except: logger.error("There was a problem loading variables") return -1 if inputDirectory and inputName and inputHash and inputID: result = processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID, clientAgent) else: # Perform Manual Post-Processing logger.warning( "Invalid number of arguments received from client, Switching to manual run mode ..." ) for section, subsections in nzbtomedia.SECTIONS.items(): for subsection in subsections: for dirName in nzbtomedia.getDirs(section, subsection): logger.info("Starting manual run for %s:%s - Folder:%s" % (section, subsection, dirName)) logger.info( "Checking database for download info for %s ..." % (os.path.basename(dirName))) nzbtomedia.DOWNLOADINFO = nzbtomedia.get_downloadInfo( os.path.basename(dirName), 0) if nzbtomedia.DOWNLOADINFO: logger.info( "Found download info for %s, setting variables now ..." % (os.path.basename(dirName))) else: logger.info( 'Unable to locate download info for %s, continuing to try and process this release ...' % (os.path.basename(dirName))) try: clientAgent = str( nzbtomedia.DOWNLOADINFO[0]['client_agent']) except: clientAgent = 'manual' try: inputHash = str( nzbtomedia.DOWNLOADINFO[0]['input_hash']) except: inputHash = None try: inputID = str(nzbtomedia.DOWNLOADINFO[0]['input_id']) except: inputID = None if clientAgent.lower( ) not in nzbtomedia.TORRENT_CLIENTS and clientAgent != 'manual': continue results = processTorrent(dirName, os.path.basename(dirName), subsection, inputHash, inputID, clientAgent) if results != 0: logger.error( "A problem was reported when trying to perform a manual run for %s:%s." % (section, subsection)) result = results if result == 0: logger.info("The %s script completed successfully." % (args[0])) else: logger.error("A problem was reported in the %s script." % (args[0])) return result