def _request(self, method, url, lang=None, **kwargs): self.config['headers'].update({'Content-type': 'application/json'}) self.config['headers']['Authorization'] = 'Bearer {}'.format( self.jwt_token) self.config['headers'].update( {'Accept-Language': lang or self.config['language']}) # get response from theTVDB try: resp = WebSession(cache=self.config['cache_enabled']).request( method, urlparse.urljoin(self.config['api']['base'], url), headers=self.config['headers'], timeout=sickrage.app.config.indexer_timeout, **kwargs) except Exception as e: raise tvdb_error(str(e)) # handle requests exceptions try: if resp.status_code == 401: raise tvdb_unauthorized(resp.json()['Error']) elif resp.status_code >= 400: raise tvdb_error(resp.json()['Error']) except JSONDecodeError: try: resp.raise_for_status() except RequestException as e: raise tvdb_error(str(e)) return to_lowercase(resp.json())
def _notify_emby(self, message, host=None, emby_apikey=None): """Handles notifying Emby host via HTTP API Returns: Returns True for no issue or False if there was an error """ # fill in omitted parameters if not host: host = sickrage.app.config.emby_host if not emby_apikey: emby_apikey = sickrage.app.config.emby_apikey url = 'http://%s/emby/Notifications/Admin' % (host) values = {'Name': 'SiCKRAGE', 'Description': message, 'ImageUrl': 'https://www.sickrage.ca/favicon.ico'} data = json.dumps(values) headers = { 'X-MediaBrowser-Token': emby_apikey, 'Content-Type': 'application/json' } resp = WebSession().get(url, data=data, headers=headers) try: resp.raise_for_status() sickrage.app.log.debug('EMBY: HTTP response: {}'.format(resp.text.replace('\n', ''))) except Exception as e: sickrage.app.log.warning('EMBY: Warning: Couldn\'t contact Emby at {}: {}'.format(url, e)) return False return True
def _request(self, method, url, lang=None, **kwargs): self.config['headers'].update({'Content-type': 'application/json'}) self.config['headers']['Authorization'] = 'Bearer {}'.format(self.jwt_token) self.config['headers'].update({'Accept-Language': lang or self.config['language']}) # get response from theTVDB try: resp = WebSession(cache=self.config['cache_enabled']).request( method, urlparse.urljoin(self.config['api']['base'], url), headers=self.config['headers'], timeout=sickrage.app.config.indexer_timeout, **kwargs ) except Exception as e: raise tvdb_error(str(e)) # handle requests exceptions try: if resp.status_code == 401: raise tvdb_unauthorized(resp.json()['Error']) elif resp.status_code >= 400: raise tvdb_error(resp.json()['Error']) except JSONDecodeError: try: resp.raise_for_status() except RequestException as e: raise tvdb_error(str(e)) return to_lowercase(resp.json())
def _request(self, method, url, lang=None, retries=3, **kwargs): self.config['headers'].update({'Authorization': 'Bearer {}'.format(self.jwt_token)}) self.config['headers'].update({'Content-type': 'application/json'}) self.config['headers'].update({'Accept-Language': lang or self.config['language']}) self.config['headers'].update({'Accept': 'application/vnd.thetvdb.v{}'.format(self.config['api']['version'])}) error_message = None for i in range(retries): try: # get response from theTVDB resp = WebSession(cache=self.config['cache_enabled']).request( method, urljoin(self.config['api']['base'], url), headers=self.config['headers'], timeout=sickrage.app.config.indexer_timeout, verify=False, **kwargs ) resp.raise_for_status() return to_lowercase(resp.json()) except requests.exceptions.HTTPError as e: status_code = e.response.status_code error_message = e.response.text if 'application/json' in e.response.headers.get('content-type', ''): error_message = e.response.json().get('Error', error_message) if status_code == 401: raise tvdb_unauthorized(error_message) elif status_code == 504: error_message = "Unable to connect to TheTVDB" except Exception as e: error_message = "{!r}".format(e) if error_message: raise tvdb_error(error_message)
def _send_to_plex(self, command, host, username=None, password=None): """Handles communication to Plex hosts via HTTP API Args: command: Dictionary of field/data pairs, encoded via urllib and passed to the legacy xbmcCmds HTTP API host: Plex host:port username: Plex API username password: Plex API password Returns: Returns 'OK' for successful commands or False if there was an error """ # fill in omitted parameters if not username: username = sickrage.app.config.plex_client_username if not password: password = sickrage.app.config.plex_client_password if not host: sickrage.app.log.warning( 'PLEX: No host specified, check your settings') return False enc_command = urlencode(command) sickrage.app.log.debug('PLEX: Encoded API command: ' + enc_command) url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command) headers = {} # if we have a password, use authentication if password: base64string = base64.b64encode( bytes('{}:{}'.format(username, password).replace('\n', ''), 'utf-8')) authheader = "Basic {}".format(base64string.decode('ascii')) headers['Authorization'] = authheader sickrage.app.log.debug( 'PLEX: Contacting (with auth header) via url: ' + url) else: sickrage.app.log.debug('PLEX: Contacting via url: ' + url) try: resp = WebSession().get(url, headers=headers) resp.raise_for_status() result = resp.text sickrage.app.log.debug('PLEX: HTTP response: ' + result.replace('\n', '')) # could return result response = re.compile('<html><li>(.+\w)</html>').findall(result) return 'OK' except Exception as e: sickrage.app.log.warning( 'PLEX: Warning: Couldn\'t contact Plex at {}: {}'.format( url, e)) return False
def _sendFreeMobileSMS(self, title, msg, id=None, apiKey=None): """ Sends a SMS notification msg: The message to send (unicode) title: The title of the message userKey: The pushover user id to send the message to (or to subscribe with) returns: True if the message succeeded, False otherwise """ if id is None: id = sickrage.app.config.freemobile_id if apiKey is None: apiKey = sickrage.app.config.freemobile_apikey sickrage.app.log.debug("Free Mobile in use with API KEY: " + apiKey) # build up the URL and parameters msg = msg.strip() msg_quoted = parse.quote(title + ": " + msg) URL = "https://smsapi.free-mobile.fr/sendmsg?user="******"&pass="******"&msg=" + msg_quoted resp = WebSession().get(URL) # send the request to Free Mobile try: resp.raise_for_status() except Exception as e: if resp.status_code == 400: message = "Missing parameter(s)." sickrage.app.log.error(message) return False, message if resp.status_code == 402: message = "Too much SMS sent in a short time." sickrage.app.log.error(message) return False, message if resp.status_code == 403: message = "API service isn't enabled in your account or ID / API key is incorrect." sickrage.app.log.error(message) return False, message if resp.status_code == 500: message = "Server error. Please retry in few moment." sickrage.app.log.error(message) return False, message message = "Error while sending SMS: {}".format(e) sickrage.app.log.error(message) return False, message message = "Free Mobile SMS successful." sickrage.app.log.info(message) return True, message
def notify_settings(self, host, dbloc, instance): """ Retrieves the NMJv2 database location from Popcorn hour host: The hostname/IP of the Popcorn Hour server dbloc: 'local' for PCH internal harddrive. 'network' for PCH network shares instance: Allows for selection of different DB in case of multiple databases Returns: True if the settings were retrieved successfully, False otherwise """ url_loc = "http://" + host + ":8008/file_operation?arg0=list_user_storage_file&arg1=&arg2=" + instance + "&arg3=20&arg4=true&arg5=true&arg6=true&arg7=all&arg8=name_asc&arg9=false&arg10=false" resp = WebSession().get(url_loc) try: resp.raise_for_status() response1 = resp.text xml = parseString(response1) time.sleep(300.0 / 1000.0) for node in xml.getElementsByTagName('path'): xmlTag = node.toxml() xmlData = xmlTag.replace('<path>', '').replace('</path>', '').replace('[=]', '') url_db = "http://" + host + ":8008/metadata_database?arg0=check_database&arg1=" + xmlData respdb = WebSession().get(url_db) respdb.raise_for_status() xmldb = parseString(respdb.text) returnvalue = xmldb.getElementsByTagName( 'returnValue')[0].toxml().replace('<returnValue>', '').replace( '</returnValue>', '') if returnvalue == "0": DB_path = xmldb.getElementsByTagName( 'database_path')[0].toxml().replace( '<database_path>', '').replace('</database_path>', '').replace('[=]', '') if dbloc == "local" and DB_path.find("localhost") > -1: sickrage.app.config.nmjv2_host = host sickrage.app.config.nmjv2_database = DB_path return True if dbloc == "network" and DB_path.find("://") > -1: sickrage.app.config.nmjv2_host = host sickrage.app.config.nmjv2_database = DB_path return True except Exception as e: sickrage.app.log.warning( "Warning: Couldn't contact popcorn hour on host %s: %s" % (host, e)) return False return False
def _sendProwl(self, prowl_api=None, prowl_priority=None, event=None, message=None, force=False): if not sickrage.app.config.use_prowl and not force: return False if prowl_api is None: prowl_api = sickrage.app.config.prowl_api if prowl_priority is None: prowl_priority = sickrage.app.config.prowl_priority title = "SiCKRAGE" sickrage.app.log.debug( "PROWL: Sending notice with details: event=\"%s\", message=\"%s\", priority=%s, api=%s" % (event, message, prowl_priority, prowl_api)) data = { 'apikey': prowl_api, 'application': title, 'event': event, 'description': message, 'priority': prowl_priority } resp = WebSession().post( "https://api.prowlapp.com/publicapi/add", headers={'Content-type': "application/x-www-form-urlencoded"}, data=urlencode(data)) try: resp.raise_for_status() request_status = resp.status_code if request_status == 200: sickrage.app.log.info("Prowl notifications sent.") return True elif request_status == 401: sickrage.app.log.error("Prowl auth failed: %s" % resp.reason) return False else: sickrage.app.log.error("Prowl notification failed.") return False except Exception: sickrage.app.log.error("Prowl notification failed.") return False
def _sendBoxcar2(self, msg, title, accesstoken): """ Sends a boxcar2 notification to the address provided msg: The message to send title: The title of the message accesstoken: to send to this device returns: True if the message succeeded, False otherwise """ # build up the URL and parameters more info goes here - # https://boxcar.uservoice.com/knowledgebase/articles/306788-how-to-send-your-boxcar-account-a-notification msg = msg.strip() data = urlencode({ 'user_credentials': accesstoken, 'notification[title]': "SiCKRAGE : " + title + ' : ' + msg, 'notification[long_message]': msg, 'notification[sound]': "notifier-2" }) # send the request to boxcar2 resp = WebSession().get(API_URL, data=data, timeout=60) try: resp.raise_for_status() except RequestException as e: # if we get an error back that doesn't have an error code then who knows what's really happening sickrage.app.log.warning( "Boxcar2 notification failed. Error code: {}".format( resp.status_code)) # HTTP status 404 if resp.status_code == 404: sickrage.app.log.warning("Access token is invalid. Check it.") return False # If you receive an HTTP status code of 400, it is because you failed to send the proper parameters elif resp.status_code == 400: sickrage.app.log.error("Wrong data send to boxcar2") return False sickrage.app.log.debug("Boxcar2 notification successful.") return True
def update_library(self, show=None): """Handles updating the Emby Media Server host via HTTP API Returns: True for no issue or False if there was an error """ if sickrage.app.config.use_emby: if not sickrage.app.config.emby_host: sickrage.app.log.debug('EMBY: No host specified, check your settings') return False if show: if show.indexer == 1: provider = 'tvdb' elif show.indexer == 2: sickrage.app.log.warning('EMBY: TVRage Provider no longer valid') return False else: sickrage.app.log.warning('EMBY: Provider unknown') return False query = '?%sid=%s' % (provider, show.indexer_id) else: query = '' url = 'http://%s/emby/Library/Series/Updated%s' % (sickrage.app.config.emby_host, query) values = {} data = urlencode(values) headers = { 'X-MediaBrowser-Token': sickrage.app.config.emby_apikey, 'Content-Type': 'application/json' } resp = WebSession().get(url, data=data, headers=headers) try: resp.raise_for_status() sickrage.app.log.debug('EMBY: HTTP response: ' + resp.text.replace('\n', '')) except Exception as e: sickrage.app.log.warning('EMBY: Warning: Couldn\'t contact Emby at {}: {}'.format(url, e)) return False return True
def _sendPushalot(self, pushalot_authorizationtoken=None, event=None, message=None, force=False): if not sickrage.app.config.use_pushalot and not force: return False sickrage.app.log.debug("Pushalot event: " + event) sickrage.app.log.debug("Pushalot message: " + message) sickrage.app.log.debug("Pushalot api: " + pushalot_authorizationtoken) data = { 'AuthorizationToken': pushalot_authorizationtoken, 'Title': event, 'Body': message } resp = WebSession().post( "https://pushalot.com/api/sendmessage", headers={'Content-type': "application/x-www-form-urlencoded"}, data=urlencode(data)) try: resp.raise_for_status() request_status = resp.status_code if request_status == 200: sickrage.app.log.debug("Pushalot notifications sent.") return True elif request_status == 410: sickrage.app.log.error("Pushalot auth failed: %s" % resp.reason) return False else: sickrage.app.log.error("Pushalot notification failed.") return False except Exception: sickrage.app.log.error("Pushalot notification failed.") return False
def _sendPushover(self, msg, title, sound=None, userKey=None, apiKey=None): """ Sends a pushover notification to the address provided msg: The message to send (unicode) title: The title of the message sound: The notification sound to use userKey: The pushover user id to send the message to (or to subscribe with) apiKey: The pushover api key to use returns: True if the message succeeded, False otherwise """ if userKey is None: userKey = sickrage.app.config.pushover_userkey if apiKey is None: apiKey = sickrage.app.config.pushover_apikey if sound is None: sound = sickrage.app.config.pushover_sound sickrage.app.log.debug("Pushover API KEY in use: " + apiKey) # build up the URL and parameters msg = msg.strip() # send the request to pushover if sickrage.app.config.pushover_sound != "default": args = { "token": apiKey, "user": userKey, "title": title, "message": msg, "timestamp": int(time.time()), "retry": 60, "expire": 3600, "sound": sound, } else: # sound is default, so don't send it args = { "token": apiKey, "user": userKey, "title": title, "message": msg, "timestamp": int(time.time()), "retry": 60, "expire": 3600, } if sickrage.app.config.pushover_device: args["device"] = sickrage.app.config.pushover_device resp = WebSession().post( "https://api.pushover.net/1/messages.json", data=urlencode(args), headers={"Content-type": "application/x-www-form-urlencoded"}) try: resp.raise_for_status() except Exception as e: sickrage.app.log.error( "Pushover notification failed. Error code: " + str(resp.status_code)) # HTTP status 404 if the provided email address isn't a Pushover user. if resp.status_code == 404: sickrage.app.log.warning( "Username is wrong/not a pushover email. Pushover will send an email to it" ) return False # For HTTP status code 401's, it is because you are passing in either an invalid token, or the user has # not added your service. elif resp.status_code == 401: # HTTP status 401 if the user doesn't have the service added subscribeNote = self._sendPushover(msg, title, sound=sound, userKey=userKey, apiKey=apiKey) if subscribeNote: sickrage.app.log.debug("Subscription sent") return True else: sickrage.app.log.error("Subscription could not be sent") return False # If you receive an HTTP status code of 400, it is because you failed to send the proper parameters elif resp.status_code == 400: sickrage.app.log.error("Wrong data sent to pushover") return False # If you receive a HTTP status code of 429, it is because the message limit has been reached (free limit # is 7,500) elif resp.status_code == 429: sickrage.app.log.error( "Pushover API message limit reached - try a different API key" ) return False sickrage.app.log.info("Pushover notification successful.") return True
def update_library(self, ep_obj): # Values from config if not sickrage.app.config.use_pytivo: return False host = sickrage.app.config.pytivo_host share_name = sickrage.app.config.pytivo_share_name tsn = sickrage.app.config.pytivo_tivo_name # There are two more values required, the container and file. # # container: The share name, show name and season # # file: The file name # # Some slicing and dicing of variables is required to get at these values. # # There might be better ways to arrive at the values, but this is the best I have been able to # come up with. # # Calculated values show_path = ep_obj.show.location show_name = ep_obj.show.name root_show_and_season = os.path.dirname(ep_obj.location) abs_path = ep_obj.location # Some show names have colons in them which are illegal in a path location, so strip them out. # (Are there other characters?) show_name = show_name.replace(":", "") root = show_path.replace(show_name, "") show_and_season = root_show_and_season.replace(root, "") container = share_name + "/" + show_and_season file = "/" + abs_path.replace(root, "") # Finally create the url and make request request_url = "http://{}/TiVoConnect?{}".format(host, urlencode( {'Command': 'Push', 'Container': container, 'File': file, 'tsn': tsn})) sickrage.app.log.debug("pyTivo notification: Requesting " + request_url) resp = WebSession().get(request_url) try: resp.raise_for_status() except HTTPError as e: if hasattr(e, 'reason'): sickrage.app.log.error("pyTivo notification: Error, failed to reach a server - " + e.reason) return False elif hasattr(e, 'code'): sickrage.app.log.error( "pyTivo notification: Error, the server couldn't fulfill the request - " + e.code) return False except Exception as e: sickrage.app.log.error("PYTIVO: Unknown exception: {}".format(e)) return False else: sickrage.app.log.info("pyTivo notification: Successfully requested transfer of file") return True
def update_library(self, ep_obj=None, host=None, username=None, password=None, plex_server_token=None, force=True): """Handles updating the Plex Media Server host via HTTP API Plex Media Server currently only supports updating the whole video library and not a specific path. Returns: Returns None for no issue, else a string of host with connection issues """ if sickrage.app.config.use_plex and sickrage.app.config.plex_update_library: if not sickrage.app.config.plex_server_host: sickrage.app.log.debug( 'PLEX: No Plex Media Server host specified, check your settings' ) return False if not host: host = sickrage.app.config.plex_server_host if not username: username = sickrage.app.config.plex_username if not password: password = sickrage.app.config.plex_password if not plex_server_token: plex_server_token = sickrage.app.config.plex_server_token # if username and password were provided, fetch the auth token from plex.tv token_arg = '' if plex_server_token: token_arg = '?X-Plex-Token=' + plex_server_token elif username and password: sickrage.app.log.debug( 'PLEX: fetching plex.tv credentials for user: '******'Authorization': 'Basic %s' % base64.b64encode( bytes( '{}:{}'.format(username, password).replace( '\n', ''), 'utf-8')).decode('ascii'), 'X-Plex-Device-Name': 'SiCKRAGE', 'X-Plex-Product': 'SiCKRAGE Notifier', 'X-Plex-Client-Identifier': sickrage.app.user_agent, 'X-Plex-Version': '1.0' } try: resp = WebSession().get( 'https://plex.tv/users/sign_in.xml', headers=headers) resp.raise_for_status() auth_tree = ElementTree.fromstring(resp.text) token = auth_tree.findall( './/authentication-token')[0].text token_arg = '?X-Plex-Token=' + token except Exception as e: sickrage.app.log.debug( 'PLEX: Error fetching credentials from from plex.tv for user %s: %s' % (username, e)) except (ValueError, IndexError) as e: sickrage.app.log.debug( 'PLEX: Error parsing plex.tv response: ' + e) file_location = '' if None is ep_obj else ep_obj.location host_list = [x.strip() for x in host.split(',')] hosts_all = {} hosts_match = {} hosts_failed = [] for cur_host in host_list: try: url = 'http://%s/library/sections%s' % (cur_host, token_arg) resp = WebSession().get(url) resp.raise_for_status() media_container = ElementTree.fromstring(resp.text) except IOError as e: sickrage.app.log.warning( 'PLEX: Error while trying to contact Plex Media Server: {}' .format(e)) hosts_failed.append(cur_host) continue except Exception as e: if 'invalid token' in str(e): sickrage.app.log.error( 'PLEX: Please set TOKEN in Plex settings: ') else: sickrage.app.log.error( 'PLEX: Error while trying to contact Plex Media Server: {}' .format(e)) continue sections = media_container.findall('.//Directory') if not sections: sickrage.app.log.debug( 'PLEX: Plex Media Server not running on: ' + cur_host) hosts_failed.append(cur_host) continue for section in sections: if 'show' == section.attrib['type']: keyed_host = [(str(section.attrib['key']), cur_host)] hosts_all.update(keyed_host) if not file_location: continue for section_location in section.findall('.//Location'): section_path = re.sub( r'[/\\]+', '/', section_location.attrib['path'].lower()) section_path = re.sub(r'^(.{,2})[/\\]', '', section_path) location_path = re.sub(r'[/\\]+', '/', file_location.lower()) location_path = re.sub(r'^(.{,2})[/\\]', '', location_path) if section_path in location_path: hosts_match.update(keyed_host) hosts_try = (hosts_all.copy(), hosts_match.copy())[bool(hosts_match)] host_list = [] for section_key, cur_host in hosts_try.items(): try: url = 'http://%s/library/sections/%s/refresh%s' % ( cur_host, section_key, token_arg) force and WebSession().get(url) host_list.append(cur_host) except Exception as e: sickrage.app.log.warning( 'PLEX: Error updating library section for Plex Media Server: {}' .format(e)) hosts_failed.append(cur_host) if hosts_match: sickrage.app.log.debug( 'PLEX: Updating hosts where TV section paths match the downloaded show: ' + ', '.join(set(host_list))) else: sickrage.app.log.debug( 'PLEX: Updating TV sections on these hosts: {}'.format( ', '.join(set(host_list)))) return (', '.join(set(hosts_failed)), None)[not len(hosts_failed)]
def _sendNMJ(self, host, database, mount=None): """ Sends a NMJ update command to the specified machine host: The hostname/IP to send the request to (no port) database: The database to send the requst to mount: The mount URL to use (optional) Returns: True if the request succeeded, False otherwise """ # if a mount URL is provided then attempt to open a handle to that URL if mount: sickrage.app.log.debug("Try to mount network drive via url: %s" % mount) resp = WebSession().get(mount) try: resp.raise_for_status() except Exception: sickrage.app.log.warning( "NMJ: Problem with Popcorn Hour on host %s: %s" % (host, resp.status_code)) return False # build up the request URL and parameters UPDATE_URL = "http://%(host)s:8008/metadata_database?%(params)s" params = { "arg0": "scanner_start", "arg1": database, "arg2": "background", "arg3": "" } params = urlencode(params) updateUrl = UPDATE_URL % {"host": host, "params": params} # send the request to the server sickrage.app.log.debug("Sending NMJ scan update command via url: %s" % updateUrl) resp = WebSession().get(updateUrl) try: resp.raise_for_status() except Exception: sickrage.app.log.warning( "NMJ: Problem with Popcorn Hour on host %s: %s" % (host, resp.status_code)) return False # try to parse the resulting XML try: et = ElementTree.fromstring(resp.text) result = et.findtext("returnValue") except SyntaxError as e: sickrage.app.log.error( "Unable to parse XML returned from the Popcorn Hour: {}". format(e)) return False # if the result was a number then consider that an error if int(result) > 0: sickrage.app.log.error( "Popcorn Hour returned an errorcode: {}".format(result)) return False else: sickrage.app.log.info("NMJ started background scan") return True
def _sendNMJ(self, host): """ Sends a NMJ update command to the specified machine host: The hostname/IP to send the request to (no port) database: The database to send the requst to mount: The mount URL to use (optional) Returns: True if the request succeeded, False otherwise """ # if a host is provided then attempt to open a handle to that URL try: url_scandir = "http://" + host + ":8008/metadata_database?arg0=update_scandir&arg1=" + sickrage.app.config.nmjv2_database + "&arg2=&arg3=update_all" sickrage.app.log.debug("NMJ scan update command sent to host: %s" % (host)) url_updatedb = "http://" + host + ":8008/metadata_database?arg0=scanner_start&arg1=" + sickrage.app.config.nmjv2_database + "&arg2=background&arg3=" sickrage.app.log.debug("Try to mount network drive via url: %s" % (host)) preresp = WebSession().get(url_scandir) preresp.raise_for_status() response1 = preresp.text time.sleep(300.0 / 1000.0) resp = WebSession().get(url_updatedb) resp.raise_for_status() response2 = resp.text except IOError as e: sickrage.app.log.warning( "Warning: Couldn't contact popcorn hour on host %s: %s" % (host, e)) return False try: et = ElementTree.fromstring(response1) result1 = et.findtext("returnValue") except SyntaxError as e: sickrage.app.log.error( "Unable to parse XML returned from the Popcorn Hour: update_scandir, {}" .format(e)) return False try: et = ElementTree.fromstring(response2) result2 = et.findtext("returnValue") except SyntaxError as e: sickrage.app.log.error( "Unable to parse XML returned from the Popcorn Hour: scanner_start, {}" .format(e)) return False # if the result was a number then consider that an error error_codes = ["8", "11", "22", "49", "50", "51", "60"] error_messages = [ "Invalid parameter(s)/argument(s)", "Invalid database path", "Insufficient size", "Database write error", "Database read error", "Open fifo pipe failed", "Read only file system" ] if int(result1) > 0: index = error_codes.index(result1) sickrage.app.log.error("Popcorn Hour returned an error: %s" % (error_messages[index])) return False else: if int(result2) > 0: index = error_codes.index(result2) sickrage.app.log.error("Popcorn Hour returned an error: %s" % (error_messages[index])) return False else: sickrage.app.log.info("NMJv2 started background scan") return True