def main(inputDirectory, inputName, inputCategory, inputHash): status = int(1) # 1 = failed | 0 = success root = int(0) video = int(0) video2 = int(0) foundFile = int(0) deleteOriginal = int(0) numCompressed = int(0) extractionSuccess = False Logger.debug("MAIN: Received Directory: %s | Name: %s | Category: %s", inputDirectory, inputName, inputCategory) inputDirectory, inputName, inputCategory, root = category_search(inputDirectory, inputName, inputCategory, root, categories) # Confirm the category by parsing directory structure for category in categories: if category == inputCategory: outputDestination = os.path.normpath(os.path.join(outputDirectory, category, safeName(inputName))) Logger.info("MAIN: Output directory set to: %s", outputDestination) break else: continue Logger.debug("MAIN: Scanning files in directory: %s", inputDirectory) now = datetime.datetime.now() for dirpath, dirnames, filenames in os.walk(inputDirectory): for file in filenames: filePath = os.path.join(dirpath, file) fileName, fileExtension = os.path.splitext(file) targetDirectory = os.path.join(outputDestination, file) if root == 1: if not foundFile: Logger.debug("MAIN: Looking for %s in: %s", inputName, file) if (safeName(inputName) in safeName(file)) or (safeName(os.path.splitext(file)[0]) in safeName(inputName)) and foundFile == 0: pass # This file does match the Torrent name foundFile = 1 Logger.debug("MAIN: Found file %s that matches Torrent Name %s", file, inputName) else: continue # This file does not match the Torrent name, skip it if root == 2: Logger.debug("MAIN: Looking for files with modified/created dates less than 5 minutes old.") mtime_lapse = now - datetime.datetime.fromtimestamp(os.path.getmtime(os.path.join(dirpath, file))) ctime_lapse = now - datetime.datetime.fromtimestamp(os.path.getctime(os.path.join(dirpath, file))) if (mtime_lapse < datetime.timedelta(minutes=5)) or (ctime_lapse < datetime.timedelta(minutes=5)) and foundFile == 0: pass # This file does match the date time criteria foundFile = 1 Logger.debug("MAIN: Found file %s with date modifed/created less than 5 minutes ago.", file) else: continue # This file has not been recently moved or created, skip it if not (inputCategory == cpsCategory or inputCategory == sbCategory): #process all for non-video categories. Logger.info("MAIN: Found file %s for category %s", filepath, inputCategory) copy_link(filePath, targetDirectory, useLink, outputDestination) elif fileExtension in mediaContainer: # If the file is a video file if is_sample(filePath, inputName, minSampleSize): # Ignore samples Logger.info("MAIN: Ignoring sample file: %s ", filePath) continue else: video = video + 1 Logger.info("MAIN: Found video file %s in %s", fileExtension, filePath) try: copy_link(filePath, targetDirectory, useLink, outputDestination) except Exception as e: Logger.error("MAIN: Failed to link file: %s", file) Logger.debug(e) elif fileExtension in metaContainer: Logger.info("MAIN: Found metadata file %s for file %s", fileExtension, filePath) try: copy_link(filePath, targetDirectory, useLink, outputDestination) except Exception as e: Logger.error("MAIN: Failed to link file: %s", file) Logger.debug(e) elif fileExtension in compressedContainer: numCompressed = numCompressed + 1 if re.search(r'\d+', os.path.splitext(fileName)[1]) and numCompressed > 1: # find part numbers in second "extension" from right, if we have more than 1 compressed file. part = int(re.search(r'\d+', os.path.splitext(fileName)[1]).group()) if part == 1: # we only want to extract the primary part. Logger.debug("MAIN: Found primary part of a multi-part archive %s. Extracting", file) else: Logger.debug("MAIN: Found part %s of a multi-part archive %s. Ignoring", part, file) continue Logger.info("MAIN: Found compressed archive %s for file %s", fileExtension, filePath) try: extractor.extract(filePath, outputDestination) extractionSuccess = True # we use this variable to determine if we need to pause a torrent or not in uTorrent (dont need to pause archived content) except Exception as e: Logger.warn("MAIN: Extraction failed for: %s", file) Logger.debug(e) else: Logger.debug("MAIN: Ignoring unknown filetype %s for file %s", fileExtension, filePath) continue flatten(outputDestination) # Now check if movie files exist in destination: for dirpath, dirnames, filenames in os.walk(outputDestination): for file in filenames: filePath = os.path.join(dirpath, file) fileExtension = os.path.splitext(file)[1] if fileExtension in mediaContainer: # If the file is a video file if is_sample(filePath, inputName, minSampleSize): Logger.debug("MAIN: Removing sample file: %s", filePath) os.unlink(filePath) # remove samples else: video2 = video2 + 1 if video2 >= video and video2 > 0: # Check that all video files were moved status = 0 # Hardlink solution for uTorrent, need to implent support for deluge, transmission if clientAgent == 'utorrent' and extractionSuccess == False and inputHash: try: Logger.debug("MAIN: Connecting to uTorrent: %s", uTorrentWEBui) utorrentClass = UTorrentClient(uTorrentWEBui, uTorrentUSR, uTorrentPWD) except Exception as e: Logger.error("MAIN: Failed to connect to uTorrent: %s", e) # if we are using links with uTorrent it means we need to pause it in order to access the files if useLink == 1: Logger.debug("MAIN: Stoping torrent %s in uTorrent while processing", inputName) utorrentClass.stop(inputHash) time.sleep(5) # Give uTorrent some time to catch up with the change # Delete torrent and torrentdata from uTorrent if deleteOriginal == 1: Logger.debug("MAIN: Deleting torrent %s from uTorrent", inputName) utorrentClass.removedata(inputHash) utorrentClass.remove(inputHash) time.sleep(5) processCategories = {cpsCategory, sbCategory, hpCategory, mlCategory, gzCategory} if inputCategory and not (inputCategory in processCategories): # no extra processign to be done... yet. Logger.info("MAIN: No further processing to be done for category %s.", inputCategory) result = 1 elif status == 0: Logger.debug("MAIN: Calling autoProcess script for successful download.") else: Logger.error("MAIN: Something failed! Please check logs. Exiting") sys.exit(-1) if inputCategory == cpsCategory: Logger.info("MAIN: Calling CouchPotatoServer to post-process: %s", inputName) result = autoProcessMovie.process(outputDestination, inputName, status) elif inputCategory == sbCategory: Logger.info("MAIN: Calling Sick-Beard to post-process: %s", inputName) result = autoProcessTV.processEpisode(outputDestination, inputName, status) elif inputCategory == hpCategory: Logger.info("MAIN: Calling HeadPhones to post-process: %s", inputName) result = autoProcessMusic.process(outputDestination, inputName, status) elif inputCategory == mlCategory: Logger.info("MAIN: Calling Mylar to post-process: %s", inputName) result = autoProcessComics.processEpisode(outputDestination, inputName, status) elif inputCategory == gzCategory: Logger.info("MAIN: Calling Gamez to post-process: %s", inputName) result = autoProcessGames.process(outputDestination, inputName, status) if result == 1: Logger.info("MAIN: A problem was reported in the autoProcess* script. If torrent was pasued we will resume seeding") # Hardlink solution for uTorrent, need to implent support for deluge, transmission if clientAgent == 'utorrent' and extractionSuccess == False and inputHash and useLink == 1 and deleteOriginal == 0: # we always want to resume seeding, for now manually find out what is wrong when extraction fails Logger.debug("MAIN: Starting torrent %s in uTorrent", inputName) utorrentClass.start(inputHash) Logger.info("MAIN: All done.")
# 2 The original name of the NZB file # 3 The status of the download: 0 == successful # 4 User-defined category Logger.info("MAIN: Script triggered from NZBGet") nzbDir, inputName, status, inputCategory = (sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]) else: # only CPS supports this manual run for now. Logger.warn("MAIN: Invalid number of arguments received from client.") Logger.info("MAIN: Running autoProcessMovie as a manual run...") nzbDir, inputName, status, inputCategory = ('Manual Run', 'Manual Run', 0, cpsCategory) if inputCategory == cpsCategory: Logger.info("MAIN: Calling CouchPotatoServer to post-process: %s", inputName) result = autoProcessMovie.process(nzbDir, inputName, status) elif inputCategory == sbCategory: Logger.info("MAIN: Calling Sick-Beard to post-process: %s", inputName) result = autoProcessTV.processEpisode(nzbDir, inputName, status) elif inputCategory == hpCategory: Logger.info("MAIN: Calling HeadPhones to post-process: %s", inputName) result = autoProcessMusic.process(nzbDir, inputName, status) elif inputCategory == mlCategory: Logger.info("MAIN: Calling Mylar to post-process: %s", inputName) result = autoProcessComics.processEpisode(nzbDir, inputName, status) elif inputCategory == gzCategory: Logger.info("MAIN: Calling Gamez to post-process: %s", inputName) result = autoProcessGames.process(nzbDir, inputName, status) if result == 0: Logger.info("MAIN: The autoProcess* script completed successfully.") else: Logger.info("MAIN: A problem was reported in the autoProcess* script.")
def nzbToMedia(nzbStatus): script = "" result = "" if Debug == "yes": Logger.debug("Post-Process: Executing external postprocessing with argument %s", nzbStatus) PostProcessStatus = nzbStatus # 200 MB in bytes SIZE_CUTOFF = 200 * 1024 * 1024 # Ignore 'sample' in files unless 'sample' in Torrent Name for dirpath, dirnames, filenames in os.walk(NZBPP_DIRECTORY): for file in filenames: filePath = os.path.join(dirpath, file) if ('sample' in filePath.lower()) and (not 'sample' in NZBPP_NZBNAME) and (os.path.getsize(filePath) < SIZE_CUTOFF): Logger.info("Post-Process: Deleting sample file %s", filePath) os.unlink(filePath) if NZBPP_CATEGORY == CouchPotatoCategory: if CouchPotato == "yes": script = "autoProcessMovie" # Call Couchpotato's postprocessing script Logger.info("Post-Process: Running CouchPotato's postprocessing script") if Debug == "yes": Logger.debug("Post-Process: CouchPotato-Script-ARGV1= %s", NZBPP_DIRECTORY) Logger.debug("Post-Process: CouchPotato-Script-ARGV2= %s", NZBPP_NZBFILENAME) Logger.debug("Post-Process: CouchPotato-Script-ARGV3= %s", PostProcessStatus) result = autoProcessMovie.process(NZBPP_DIRECTORY, NZBPP_NZBFILENAME, PostProcessStatus) else: Logger.debug("Post-Process: Ignored to run CouchPotato's postprocessing script as it is disabled by user") if NZBPP_CATEGORY == SickBeardCategory: if SickBeard == "yes": script = "autoProcessTv" # Call SickBeard's postprocessing script Logger.info("Post-Process: Running SickBeard's postprocessing script") if Debug == "yes": Logger.debug("Post-Process: SickBeard-Script-ARGV1= %s", NZBPP_DIRECTORY) Logger.debug("Post-Process: SickBeard-Script-ARGV2= %s", NZBPP_NZBFILENAME) Logger.debug("Post-Process: SickBeard-Script-ARGV3= %s", PostProcessStatus) result = autoProcessTV.processEpisode(NZBPP_DIRECTORY, NZBPP_NZBFILENAME, PostProcessStatus) else: Logger.debug("Post-Process: Ignored to run SickBeard's postprocessing script as it is disabled by user") if NZBPP_CATEGORY == HeadPhonesCategory: if HeadPhones == "yes": script = "autoProcessMusic" # Call HeadPhones' postprocessing script Logger.info("Post-Process: Running HeadPhones' postprocessing script") if Debug == "yes": Logger.debug("Post-Process: HeadPhones-Script-ARGV1= %s", NZBPP_DIRECTORY) Logger.debug("Post-Process: HeadPhones-Script-ARGV2= %s", NZBPP_NZBFILENAME) Logger.debug("Post-Process: HeadPhones-Script-ARGV3= %s", PostProcessStatus) result = autoProcessMusic.process(NZBPP_DIRECTORY, NZBPP_NZBFILENAME, PostProcessStatus) else: Logger.debug("Post-Process: Ignored to run HeadPhones' postprocessing script as it is disabled by user") if NZBPP_CATEGORY == MylarCategory: if Mylar == "yes": script = "autoProcessComics" # Call Mylar's postprocessing script Logger.info("Post-Process: Running Mylar's postprocessing script") if Debug == "yes": Logger.debug("Post-Process: Mylar-Script-ARGV1= %s", NZBPP_DIRECTORY) Logger.debug("Post-Process: Mylar-Script-ARGV2= %s", NZBPP_NZBFILENAME) Logger.debug("Post-Process: Mylar-Script-ARGV3= %s", PostProcessStatus) result = autoProcessComics.processEpisode(NZBPP_DIRECTORY, NZBPP_NZBFILENAME, PostProcessStatus) else: Logger.debug("Post-Process: Ignored to run Mylar's postprocessing script as it is disabled by user") if NZBPP_CATEGORY == GamezCategory: if Gamez == "yes": script = "autoProcessGames" # Call Gamez's postprocessing script Logger.info("Post-Process: Running Gamez's postprocessing script") if Debug == "yes": Logger.debug("Post-Process: Gamez-Script-ARGV1= %s", NZBPP_DIRECTORY) Logger.debug("Post-Process: Gamez-Script-ARGV2= %s", NZBPP_NZBFILENAME) Logger.debug("Post-Process: Gamez-Script-ARGV3= %s", PostProcessStatus) result = autoProcessGames.process(NZBPP_DIRECTORY, NZBPP_NZBFILENAME, PostProcessStatus) else: Logger.debug("Post-Process: Ignored to run Gamez's postprocessing script as it is disabled by user") return script, result
nzbtomedia_configure_logging(os.path.dirname(sys.argv[0])) Logger = logging.getLogger(__name__) Logger.info("====================") # Seperate old from new log Logger.info("nzbToHeadPhones %s", VERSION) # SABnzbd if len(sys.argv) == SABNZB_NO_OF_ARGUMENTS: # SABnzbd argv: # 1 The final directory of the job (full path) # 2 The original name of the NZB file # 3 Clean version of the job name (no path info and ".nzb" removed) # 4 Indexer's report number (if supported) # 5 User-defined category # 6 Group that the NZB was posted in e.g. alt.binaries.x # 7 Status of post processing. 0 = OK, 1=failed verification, 2=failed unpack, 3=1+2 Logger.info("Script triggered from SABnzbd, starting autoProcessMusic...") result = autoProcessMusic.process(sys.argv[1], sys.argv[2], sys.argv[7]) # NZBGet elif len(sys.argv) == NZBGET_NO_OF_ARGUMENTS: # NZBGet argv: # 1 The final directory of the job (full path) # 2 The original name of the NZB file # 3 The status of the download: 0 == successful Logger.info("Script triggered from NZBGet, starting autoProcessMusic...") result = autoProcessMusic.process(sys.argv[1], sys.argv[2], sys.argv[3]) else: Logger.warn("Invalid number of arguments received from client.") Logger.info("Running autoProcessMusic as a manual run...") result = autoProcessMusic.process('Manual Run', 'Manual Run', 0)