import os import re import time import datetime import urllib import shutil import sys import platform import nzbtomedia from lib import requests from nzbtomedia.Transcoder import Transcoder from nzbtomedia.nzbToMediaSceneExceptions import process_all_exceptions from nzbtomedia.nzbToMediaUtil import convert_to_ascii, delete, create_torrent_class from nzbtomedia import logger from nzbtomedia.transmissionrpc.client import Client as TransmissionClient class autoProcessMovie: def find_release_info(self, baseURL, download_id, dirName, nzbName, clientAgent): imdbid = None release_id = None media_id = None release_status = None matched_release = None while(True): # find imdbid in nzbName a = nzbName.find('.cp(') + 4 b = nzbName[a:].find(')') + a if a > 3: # a == 3 if not exist if nzbName[a:b]: imdbid = nzbName[a:b] logger.postprocess("Found imdbid %s in name", imdbid) break # find imdbid in dirName a = dirName.find('.cp(') + 4 b = dirName[a:].find(')') + a if a > 3: # a == 3 if not exist if dirName[a:b]: imdbid = dirName[a:b] logger.postprocess("Found movie id %s in directory", imdbid) break break url = baseURL + "/media.list/?release_status=snatched" logger.debug("Opening URL: %s", url) try: r = requests.get(url) except requests.ConnectionError: logger.error("Unable to open URL") return results = r.json() def search_results(results, clientAgent): last_edit = {} for movie in results['movies']: if imdbid: if imdbid != movie['identifiers']['imdb']: continue for i, release in enumerate(movie['releases']): if release['status'] != 'snatched': continue if clientAgent != 'manual': if release['download_info']['download'] == clientAgent: return release else: date = datetime.datetime.fromtimestamp(release['last_edit']) last_edit[date] = {} last_edit[date].update(release) if download_id: if release['download_info']['id'] == download_id: return release if last_edit: last_edit = sorted(last_edit.items()) release = last_edit[0][1] return release matched_release = search_results(results, clientAgent) if matched_release: try: release_id = matched_release['_id'] media_id = matched_release['media_id'] release_status = matched_release['status'] download_id = matched_release['download_info']['id'] except:pass return media_id, download_id, release_id, release_status def get_status(self, baseURL, media_id, release_id): logger.debug("Attempting to get current status for movie:%s", media_id) url = baseURL + "/media.get" logger.debug("Opening URL: %s", url) try: r = requests.get(url, params={'id':media_id}) except requests.ConnectionError: logger.error("Unable to open URL") return try: result = r.json() for release in result["media"]['releases']: if release['_id'] == release_id: return release["status"] except:pass def process(self, dirName, nzbName=None, status=0, clientAgent = "manual", download_id = "", inputCategory=None): if dirName is None: logger.error("No directory was given!") return 1 # failure # 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 logger.postprocess("#########################################################") logger.postprocess("## ..::[%s]::.. :: CATEGORY:[%s]", section, inputCategory) logger.postprocess("#########################################################") status = int(status) 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: transcode = int(nzbtomedia.CFG["Transcoder"]["transcode"]) except: transcode = 0 try: remote_path = nzbtomedia.CFG[section][inputCategory]["remote_path"] except: remote_path = None nzbName = str(nzbName) # make sure it is a string if ssl: protocol = "https://" else: protocol = "http://" baseURL = protocol + host + ":" + port + web_root + "/api/" + apikey media_id, download_id, release_id, release_status = self.find_release_info(baseURL, download_id, dirName, nzbName, clientAgent) if release_status: if release_status != "snatched": logger.warning("%s is marked with a status of %s on CouchPotato, skipping ...", nzbName, release_status) return 0 else: if clientAgent != 'manual': logger.error("Could not find a status for %s on CouchPotato, skipping ...", nzbName) return 1 process_all_exceptions(nzbName.lower(), dirName) nzbName, dirName = convert_to_ascii(nzbName, dirName) if status == 0: if transcode == 1: result = Transcoder().Transcode_directory(dirName) if result == 0: logger.debug("Transcoding succeeded for files in %s", dirName) else: logger.warning("Transcoding failed for files in %s", dirName) if method == "manage": command = "/manage.update" else: command = "/renamer.scan" params = {} if download_id: params['downloader'] = nzbtomedia.CLIENTAGENT params['download_id'] = download_id params['media_folder'] = urllib.quote(dirName) if remote_path: dirName_new = os.path.join(remote_path, os.path.basename(dirName)).replace("\\", "/") params['media_folder'] = urllib.quote(dirName_new) url = baseURL + command logger.debug("Opening URL: %s", url) try: r = requests.get(url, params=params) except requests.ConnectionError: logger.error("Unable to open URL") return 1 # failure result = r.json() logger.postprocess("CouchPotatoServer returned %s", result) if result['success']: logger.postprocess("%s scan started on CouchPotatoServer for %s", method, nzbName) else: logger.error("%s scan has NOT started on CouchPotatoServer for %s. Exiting", method, nzbName) return 1 # failure else: logger.postprocess("Download of %s has failed.", nzbName) logger.postprocess("Trying to re-cue the next highest ranked release") if not download_id: logger.warning("Cound not find a movie in the database for release %s", nzbName) logger.warning("Please manually ignore this release and refresh the wanted movie") logger.error("Exiting autoProcessMovie script") return 1 # failure url = baseURL + "movie.searcher.try_next/?media_id=" + media_id logger.debug("Opening URL: %s", url) try: r = requests.get(url, stream=True) except requests.ConnectionError: logger.error("Unable to open URL") return 1 # failure for line in r.iter_lines(): if line: logger.postprocess("%s", line) logger.postprocess("%s FAILED!, Trying the next best release on CouchPotatoServer", nzbName) if delete_failed and not os.path.dirname(dirName) == dirName: logger.postprocess("Deleting failed files and folder %s", dirName) delete(dirName) return 0 # success if not (download_id or media_id or release_id): if clientAgent != 'manual': return 1 else: return 0 # we will now check to see if CPS has finished renaming before returning to TorrentToMedia and unpausing. timeout = time.time() + 60 * int(wait_for) while (time.time() < timeout): # only wait 2 (default) minutes, then return. current_status = self.get_status(baseURL, media_id, release_id) 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] in CouchPotatoServer", current_status.upper()) return 0 # success # pause and let CouchPotatoServer catch its breath time.sleep(10 * int(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 movie does not appear to have changed status after %s minutes. Please check CouchPotato Logs", wait_for) return 1 # failure