def ex(e): """ Returns a unicode string from the exception text if it exists. """ e_message = u"" if not e or not e.args: return e_message for arg in e.args: if arg is not None: if isinstance(arg, (str, unicode)): fixed_arg = fixStupidEncodings(arg, True) else: try: fixed_arg = u"error " + fixStupidEncodings(str(arg), True) except: fixed_arg = None if fixed_arg: if not e_message: e_message = fixed_arg else: e_message = e_message + " : " + fixed_arg return e_message
def _send_to_xbmc_json(self, command, host=None, username=None, password=None): """Handles communication to XBMC servers via JSONRPC Args: command: Dictionary of field/data pairs, encoded via urllib and passed to the XBMC JSON-RPC via HTTP host: XBMC webserver host:port username: XBMC webserver username password: XBMC webserver password Returns: Returns response.result for successful commands or False if there was an error """ # fill in omitted parameters if not username: username = sickbeard.XBMC_USERNAME if not password: password = sickbeard.XBMC_PASSWORD if not host: logger.log(u"No XBMC host passed, aborting update", logger.DEBUG) return False command = command.encode("utf-8") logger.log(u"XBMC JSON command: " + command, logger.DEBUG) url = "http://%s/jsonrpc" % (host) try: req = urllib2.Request(url, command) req.add_header("Content-type", "application/json") # if we have a password, use authentication if password: base64string = base64.encodestring("%s:%s" % (username, password))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) logger.log(u"Contacting XBMC (with auth header) via url: " + fixStupidEncodings(url), logger.DEBUG) else: logger.log(u"Contacting XBMC via url: " + fixStupidEncodings(url), logger.DEBUG) try: response = urllib2.urlopen(req) except urllib2.URLError, e: logger.log( u"Error while trying to retrieve XBMC API version for " + host + ": " + ex(e), logger.WARNING ) return False # parse the json result try: result = json.load(response) response.close() logger.log(u"XBMC JSON response: " + str(result), logger.DEBUG) return result # need to return response for parsing except ValueError, e: logger.log(u"Unable to decode JSON: " + response, logger.WARNING) return False
def _send_to_xbmc_json(self, command, host=None, username=None, password=None): """Handles communication to XBMC servers via JSONRPC Args: command: Dictionary of field/data pairs, encoded via urllib and passed to the XBMC JSON-RPC via HTTP host: XBMC webserver host:port username: XBMC webserver username password: XBMC webserver password Returns: Returns response.result for successful commands or False if there was an error """ # fill in omitted parameters if not username: username = sickbeard.XBMC_USERNAME if not password: password = sickbeard.XBMC_PASSWORD if not host: logger.log(u'No XBMC host passed, aborting update', logger.DEBUG) return False command = command.encode('utf-8') logger.log(u"XBMC JSON command: " + command, logger.DEBUG) url = 'http://%s/jsonrpc' % (host) try: req = urllib2.Request(url, command) req.add_header("Content-type", "application/json") # if we have a password, use authentication if password: base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) logger.log(u"Contacting XBMC (with auth header) via url: " + fixStupidEncodings(url), logger.DEBUG) else: logger.log(u"Contacting XBMC via url: " + fixStupidEncodings(url), logger.DEBUG) try: response = urllib2.urlopen(req) except urllib2.URLError, e: logger.log(u"Error while trying to retrieve XBMC API version for " + host + ": " + ex(e), logger.WARNING) return False # parse the json result try: result = json.load(response) response.close() logger.log(u"XBMC JSON response: " + str(result), logger.DEBUG) return result # need to return response for parsing except ValueError, e: logger.log(u"Unable to decode JSON: " + response, logger.WARNING) return False
def _send_to_xbmc(self, command, host=None, username=None, password=None): """Handles communication to XBMC servers via HTTP API Args: command: Dictionary of field/data pairs, encoded via urllib and passed to the XBMC API via HTTP host: XBMC webserver host:port username: XBMC webserver username password: XBMC webserver password Returns: Returns response.result for successful commands or False if there was an error """ # fill in omitted parameters if not username: username = sickbeard.XBMC_USERNAME if not password: password = sickbeard.XBMC_PASSWORD if not host: logger.log(u"No XBMC host passed, aborting update", logger.DEBUG) return False for key in command: if type(command[key]) == unicode: command[key] = command[key].encode("utf-8") enc_command = urllib.urlencode(command) logger.log(u"XBMC encoded API command: " + enc_command, logger.DEBUG) url = "http://%s/xbmcCmds/xbmcHttp/?%s" % (host, enc_command) try: req = urllib2.Request(url) # if we have a password, use authentication if password: base64string = base64.encodestring("%s:%s" % (username, password))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) logger.log(u"Contacting XBMC (with auth header) via url: " + fixStupidEncodings(url), logger.DEBUG) else: logger.log(u"Contacting XBMC via url: " + fixStupidEncodings(url), logger.DEBUG) response = urllib2.urlopen(req) result = response.read().decode(sickbeard.SYS_ENCODING) response.close() logger.log(u"XBMC HTTP response: " + result.replace("\n", ""), logger.DEBUG) return result except (urllib2.URLError, IOError), e: logger.log( u"Warning: Couldn't contact XBMC HTTP at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING ) return False
def _send_to_xbmc_json(self, command, host=None, username=None, password=None): """Handles communication to XBMC servers via JSONRPC Args: command: Dictionary of field/data pairs, encoded via urllib and passed to the XBMC JSON-RPC via HTTP host: XBMC webserver host:port username: XBMC webserver username password: XBMC webserver password Returns: Returns response.result for successful commands or False if there was an error """ if not host: self._log_debug(u'No host passed, aborting update') return False username = self._choose(username, sickbeard.XBMC_USERNAME) password = self._choose(password, sickbeard.XBMC_PASSWORD) command = command.encode('utf-8') self._log_debug(u'JSON command: ' + command) url = 'http://%s/jsonrpc' % host try: req = urllib2.Request(url, command) req.add_header('Content-type', 'application/json') # if we have a password, use authentication if password: base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = 'Basic %s' % base64string req.add_header('Authorization', authheader) self._log_debug(u'Contacting (with auth header) via url: ' + fixStupidEncodings(url)) else: self._log_debug(u'Contacting via url: ' + fixStupidEncodings(url)) try: response = urllib2.urlopen(req) except urllib2.URLError as e: self._log_warning(u'Error while trying to retrieve API version for "%s": %s' % (host, ex(e))) return False # parse the json result try: result = json.load(response) response.close() self._log_debug(u'JSON response: ' + str(result)) return result # need to return response for parsing except ValueError: self._log_warning(u'Unable to decode JSON: ' + response) return False except IOError as e: self._log_warning(u'Couldn\'t contact JSON API at ' + fixStupidEncodings(url) + ' ' + ex(e)) return False
def _send_to_xbmc(self, command, host=None, username=None, password=None): """Handles communication to XBMC servers via HTTP API Args: command: Dictionary of field/data pairs, encoded via urllib and passed to the XBMC API via HTTP host: XBMC webserver host:port username: XBMC webserver username password: XBMC webserver password Returns: Returns response.result for successful commands or False if there was an error """ # fill in omitted parameters if not username: username = sickbeard.XBMC_USERNAME if not password: password = sickbeard.XBMC_PASSWORD if not host: logger.log(u'No XBMC host passed, aborting update', logger.DEBUG) return False for key in command: if type(command[key]) == unicode: command[key] = command[key].encode('utf-8') enc_command = urllib.urlencode(command) logger.log(u"XBMC encoded API command: " + enc_command, logger.DEBUG) url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command) try: req = urllib2.Request(url) # if we have a password, use authentication if password: base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) logger.log(u"Contacting XBMC (with auth header) via url: " + fixStupidEncodings(url), logger.DEBUG) else: logger.log(u"Contacting XBMC via url: " + fixStupidEncodings(url), logger.DEBUG) response = urllib2.urlopen(req) result = response.read().decode(sickbeard.SYS_ENCODING) response.close() logger.log(u"XBMC HTTP response: " + result.replace('\n', ''), logger.DEBUG) return result except (urllib2.URLError, IOError), e: logger.log(u"Warning: Couldn't contact XBMC HTTP at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING) return False
def _send_to_xbmc(self, command, host=None, username=None, password=None): """Handles communication to XBMC servers via HTTP API Args: command: Dictionary of field/data pairs, encoded via urllib and passed to the XBMC API via HTTP host: XBMC webserver host:port username: XBMC webserver username password: XBMC webserver password Returns: Returns response.result for successful commands or False if there was an error """ if not host: self._log_debug(u'No host passed, aborting update') return False username = self._choose(username, sickbeard.XBMC_USERNAME) password = self._choose(password, sickbeard.XBMC_PASSWORD) for key in command: if type(command[key]) == unicode: command[key] = command[key].encode('utf-8') enc_command = urllib.urlencode(command) self._log_debug(u'Encoded API command: ' + enc_command) url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command) try: req = urllib2.Request(url) # if we have a password, use authentication if password: base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = 'Basic %s' % base64string req.add_header('Authorization', authheader) self._log_debug(u'Contacting (with auth header) via url: ' + fixStupidEncodings(url)) else: self._log_debug(u'Contacting via url: ' + fixStupidEncodings(url)) response = urllib2.urlopen(req) result = response.read().decode(sickbeard.SYS_ENCODING) response.close() self._log_debug(u'HTTP response: ' + result.replace('\n', '')) return result except (urllib2.URLError, IOError) as e: self._log_warning(u'Couldn\'t contact HTTP at %s %s' % (fixStupidEncodings(url), ex(e))) return False
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 = sickbeard.PLEX_USERNAME if not password: password = sickbeard.PLEX_PASSWORD if not host: self.log(u'No host specified, check your settings', logger.ERROR) return False for key in command: if type(command[key]) == unicode: command[key] = command[key].encode('utf-8') enc_command = urllib.urlencode(command) self.log(u'Encoded API command: ' + enc_command, logger.DEBUG) url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command) try: req = urllib2.Request(url) # if we have a password, use authentication if password: base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = 'Basic %s' % base64string req.add_header('Authorization', authheader) self.log(u'Contacting (with auth header) via url: ' + url, logger.DEBUG) else: self.log(u'Contacting via url: ' + url, logger.DEBUG) response = urllib2.urlopen(req) result = response.read().decode(sickbeard.SYS_ENCODING) response.close() self.log(u'HTTP response: ' + result.replace('\n', ''), logger.DEBUG) # could return result response = re.compile('<html><li>(.+\w)</html>').findall(result) return 'OK' except (urllib2.URLError, IOError) as e: self.log( u'Couldn\'t contact Plex at ' + fixStupidEncodings(url) + ' ' + ex(e), logger.WARNING) return False
def _sendXBMCAPIRequest(self, host, url, username=None, password=None): ''' Handles HTTP communication with XBMC servers url - Preformatted HTTP / JSON API Url ''' if not username: username = self._username() if not password: password = self._password() try: # If we have a password, use authentication req = urllib2.Request(url) if password: logger.log(u"Adding Password to XBMC url", logger.DEBUG) base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) logger.log(u"Contacting XBMC via url: " + url, logger.DEBUG) handle = urllib2.urlopen(req, None, 5) response = handle.read() logger.log(u"response: " + response, logger.DEBUG) except IOError, e: logger.log(u"Warning: Couldn't contact XBMC HTTP server at " + fixStupidEncodings(host) + ": " + ex(e)) response = ''
def _send_to_plex(self, command, host, username=None, password=None): """Handles communication to Plex hosts via HTTP API def notify_subtitle_download(self, ep_name, lang): if sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD: self._notifyXBMC(ep_name + ": " + lang, common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD]) 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 = sickbeard.PLEX_USERNAME if not password: password = sickbeard.PLEX_PASSWORD if not host: logger.log(u"No Plex host specified, check your settings", logger.DEBUG) return False for key in command: if type(command[key]) == unicode: command[key] = command[key].encode('utf-8') enc_command = urllib.urlencode(command) logger.log(u"Plex encoded API command: " + enc_command, logger.DEBUG) url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command) try: req = urllib2.Request(url) # if we have a password, use authentication if password: base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) logger.log(u"Contacting Plex (with auth header) via url: " + url, logger.DEBUG) else: logger.log(u"Contacting Plex via url: " + url, logger.DEBUG) response = urllib2.urlopen(req) result = response.read().decode(sickbeard.SYS_ENCODING) response.close() logger.log(u"Plex HTTP response: " + result.replace('\n', ''), logger.DEBUG) # could return result response = re.compile('<html><li>(.+\w)</html>').findall(result) return 'OK' except (urllib2.URLError, IOError), e: logger.log(u"Warning: Couldn't contact Plex at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING) return False
def _send_to_kodi(self, command, host=None, username=None, password=None): # fill in omitted parameters if not username: username = sickbeard.KODI_USERNAME if not password: password = sickbeard.KODI_PASSWORD if not host: logger.log(u'KODI: No host specified, check your settings', logger.ERROR) return False data = json.dumps(command) logger.log(u'KODI: JSON command: %s' % data, logger.DEBUG) url = 'http://%s/jsonrpc' % host headers = {'Content-type': 'application/json'} # if we have a password, use authentication if password: base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = 'Basic %s' % base64string headers['Authorization'] = authheader logger.log(u'KODI: Contacting (with auth header) via url: %s' % fixStupidEncodings(url), logger.DEBUG) else: logger.log(u'KODI: Contacting via url: %s' % fixStupidEncodings(url), logger.DEBUG) try: response = requests.post(url, data=data, headers=headers) except Exception as e: logger.log(u'KODI: Warning: Couldn\'t contact Kodi at %s - %s' % (host, ex(e)), logger.WARNING) return False if response.status_code == 401: logger.log(u'KODI: Invalid login credentials', logger.ERROR) return False # parse the json result try: result = response.json() logger.log(u'KODI: JSON response: %s' % result, logger.DEBUG) return result # need to return response for parsing except ValueError as e: logger.log(u'KODI: Unable to decode JSON response: %s' % response.text, logger.WARNING) return False
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 = sickbeard.PLEX_USERNAME if not password: password = sickbeard.PLEX_PASSWORD if not host: logger.log(u"PLEX: No host specified, check your settings", logger.ERROR) return False for key in command: if type(command[key]) == unicode: command[key] = command[key].encode("utf-8") enc_command = urllib.urlencode(command) logger.log(u"PLEX: Encoded API command: " + enc_command, logger.DEBUG) url = "http://%s/xbmcCmds/xbmcHttp/?%s" % (host, enc_command) try: req = urllib2.Request(url) # if we have a password, use authentication if password: base64string = base64.encodestring("%s:%s" % (username, password))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) logger.log(u"PLEX: Contacting (with auth header) via url: " + url, logger.DEBUG) else: logger.log(u"PLEX: Contacting via url: " + url, logger.DEBUG) response = urllib2.urlopen(req) result = response.read().decode(sickbeard.SYS_ENCODING) response.close() logger.log(u"PLEX: HTTP response: " + result.replace("\n", ""), logger.DEBUG) # could return result response = re.compile('<html><li>(.+\w)</html>').findall(result) return "OK" except (urllib2.URLError, IOError), e: logger.log( u"PLEX: Warning: Couldn't contact Plex at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING ) return False
def _send_to_kodi(self, command, host=None, username=None, password=None): # fill in omitted parameters if not username: username = sickbeard.KODI_USERNAME if not password: password = sickbeard.KODI_PASSWORD if not host: logger.log(u'KODI: No host specified, check your settings', logger.ERROR) return False command = command.encode('utf-8') logger.log(u'KODI: JSON command: ' + command, logger.DEBUG) url = 'http://%s/jsonrpc' % (host) try: req = urllib2.Request(url, command) req.add_header('Content-type', 'application/json') # if we have a password, use authentication if password: base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = 'Basic %s' % base64string req.add_header('Authorization', authheader) logger.log(u'KODI: Contacting (with auth header) via url: ' + fixStupidEncodings(url), logger.DEBUG) else: logger.log(u'KODI: Contacting via url: ' + fixStupidEncodings(url), logger.DEBUG) try: response = urllib2.urlopen(req) except urllib2.URLError, e: logger.log(u'KODI: Warning: Couldn\'t contact Kodi at ' + host + '- ' + ex(e), logger.WARNING) return False # parse the json result try: result = json.load(response) response.close() logger.log(u'KODI: JSON response: ' + str(result), logger.DEBUG) return result # need to return response for parsing except ValueError, e: logger.log(u'KODI: Unable to decode JSON response: ' + response, logger.WARNING) return False
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 = sickbeard.PLEX_USERNAME if not password: password = sickbeard.PLEX_PASSWORD if not host: logger.log(u"PLEX: No host specified, check your settings", logger.ERROR) return False for key in command: if type(command[key]) == unicode: command[key] = command[key].encode('utf-8') enc_command = urllib.urlencode(command) logger.log(u"PLEX: Encoded API command: " + enc_command, logger.DEBUG) url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command) try: req = urllib2.Request(url) # if we have a password, use authentication if password: pw_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm() pw_mgr.add_password(None, url, username, password) else: pw_mgr = None response = sickbeard.helpers.getURLFileLike(req, password_mgr=pw_mgr) result = response.read().decode(sickbeard.SYS_ENCODING) response.close() logger.log(u"PLEX: HTTP response: " + result.replace('\n', ''), logger.DEBUG) # could return result response = re.compile('<html><li>(.+\w)</html>').findall(result) return 'OK' except (urllib2.URLError, IOError), e: logger.log(u"PLEX: Warning: Couldn't contact Plex at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING) return False
def _send_to_xbmc(self, command, host=None, username=None, password=None): """Handles communication to XBMC servers via HTTP API Args: command: Dictionary of field/data pairs, encoded via urllib and passed to the XBMC API via HTTP host: XBMC webserver host:port username: XBMC webserver username password: XBMC webserver password Returns: Returns response.result for successful commands or False if there was an error """ # fill in omitted parameters if not username: username = sickbeard.XBMC_USERNAME if not password: password = sickbeard.XBMC_PASSWORD if not host: logger.log(u"XBMC: No host specified, check your settings", logger.DEBUG) return False for key in command: if type(command[key]) == unicode: command[key] = command[key].encode('utf-8') enc_command = urllib.urlencode(command) logger.log(u"XBMC: Encoded API command: " + enc_command, logger.DEBUG) url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command) try: req = urllib2.Request(url) # if we have a password, use authentication if password: pw_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm() pw_mgr.add_password(None, url, username, password) else: pw_mgr = None response = sickbeard.helpers.getURLFileLike(req, password_mgr=pw_mgr, throw_exc=True) if response: result = response.read().decode(sickbeard.SYS_ENCODING) response.close() logger.log(u"XBMC: HTTP response: " + result.replace('\n', ''), logger.DEBUG) return result except (urllib2.URLError, IOError), e: logger.log(u"XBMC: Could not contact XBMC HTTP at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING)
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 True for successful commands or False if there was an error """ if not host: self._log_error(u'No host specified, check your settings') return False for key in command: if type(command[key]) == unicode: command[key] = command[key].encode('utf-8') enc_command = urllib.urlencode(command) self._log_debug(u'Encoded API command: ' + enc_command) url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command) try: req = urllib2.Request(url) if password: base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = 'Basic %s' % base64string req.add_header('Authorization', authheader) self._log_debug(u'Contacting (with auth header) via url: ' + url) else: self._log_debug(u'Contacting via url: ' + url) response = urllib2.urlopen(req) result = response.read().decode(sickbeard.SYS_ENCODING) response.close() self._log_debug(u'HTTP response: ' + result.replace('\n', '')) return True except (urllib2.URLError, IOError) as e: self._log_warning(u'Couldn\'t contact Plex at ' + fixStupidEncodings(url) + ' ' + ex(e)) return False
def ex(e): """ Returns a unicode string from the exception text if it exists. """ # sanity check if not e.args or not e.args[0]: return "" e_message = fixStupidEncodings(e.args[0], True) # if fixStupidEncodings doesn't fix it then maybe it's not a string, in which case we'll try printing it anyway if not e_message: try: e_message = str(e.args[0]) except: e_message = "" return e_message
def _sendToXBMC(self, command, host, username=None, password=None): ''' Handles communication with XBMC servers command - Dictionary of field/data pairs, encoded via urllib.urlencode and passed to /xbmcCmds/xbmcHttp host - host/ip + port (foo:8080) ''' if not username: username = self._username() if not password: password = self._password() for key in command: if type(command[key]) == unicode: command[key] = command[key].encode('utf-8') enc_command = urllib.urlencode(command) logger.log(u"Encoded command is " + enc_command, logger.DEBUG) # Web server doesn't like POST, GET is the way to go url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command) try: # If we have a password, use authentication req = urllib2.Request(url) if password: logger.log(u"Adding Password to XBMC url", logger.DEBUG) base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) logger.log(u"Contacting XBMC via url: " + url, logger.DEBUG) handle = urllib2.urlopen(req) response = handle.read().decode(sickbeard.SYS_ENCODING) logger.log(u"response: " + response, logger.DEBUG) except IOError, e: logger.log(u"Warning: Couldn't contact XBMC HTTP server at " + fixStupidEncodings(host) + ": " + ex(e)) response = ''
def _sendToXBMC(self, command, host, username=None, password=None): ''' Handles communication with XBMC servers command - Dictionary of field/data pairs, encoded via urllib.urlencode and passed to /xbmcCmds/xbmcHttp host - host/ip + port (foo:8080) ''' if not username: username = self._username() if not password: password = self._password() for key in command: if type(command[key]) == unicode: command[key] = command[key].encode('utf-8') enc_command = urllib.urlencode(command) logger.log(u"Encoded command is " + enc_command, logger.DEBUG) # Web server doesn't like POST, GET is the way to go url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command) try: # If we have a password, use authentication req = urllib2.Request(url) if password: logger.log(u"Adding Password to XBMC url", logger.DEBUG) base64string = base64.encodestring('%s:%s' % (username, password))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) logger.log(u"Contacting XBMC via url: " + url, logger.DEBUG) handle = urllib2.urlopen(req) response = handle.read() logger.log(u"response: " + response, logger.DEBUG) except IOError, e: logger.log(u"Warning: Couldn't contact XBMC HTTP server at " + fixStupidEncodings(host) + ": " + ex(e)) response = ''
pw_mgr = None response = sickbeard.helpers.getURLFileLike(req, password_mgr=pw_mgr, throw_exc=True) # parse the json result result = json.load(response) response.close() logger.log(u"XBMC: JSON response: " + str(result), logger.DEBUG) return result # need to return response for parsing except ValueError, e: logger.log(u"XBMC: Unable to decode JSON: " + response, logger.WARNING) except urllib2.URLError, e: logger.log(u"XBMC: Error while trying to retrieve XBMC API version for " + host + ": " + ex(e), logger.WARNING) except IOError, e: logger.log(u"XBMC: Could not contact XBMC JSON API at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING) except Exception, e: logger.log(u"XBMC: Exception occurred while trying to access " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING) return False def _update_library_json(self, host=None, showName=None): """Handles updating XBMC host via HTTP JSON-RPC Attempts to update the XBMC video library for a specific tv show if passed, otherwise update the whole library if enabled. Args: host: XBMC webserver host:port showName: Name of a TV show to specifically target the library update for Returns:
) return False # parse the json result try: result = json.load(response) response.close() logger.log(u"XBMC JSON response: " + str(result), logger.DEBUG) return result # need to return response for parsing except ValueError, e: logger.log(u"Unable to decode JSON: " + response, logger.WARNING) return False except IOError, e: logger.log( u"Warning: Couldn't contact XBMC JSON API at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING ) return False def _update_library_json(self, host=None, showName=None): """Handles updating XBMC host via HTTP JSON-RPC Attempts to update the XBMC video library for a specific tv show if passed, otherwise update the whole library if enabled. Args: host: XBMC webserver host:port showName: Name of a TV show to specifically target the library update for Returns: Returns True or False
# parse the json result try: result = json.load(response) response.close() logger.log(u"XBMC JSON response: " + str(result), logger.DEBUG) return result # need to return response for parsing except ValueError, e: logger.log(u"Unable to decode JSON: " + response, logger.WARNING) return False except IOError, e: logger.log( u"Warning: Couldn't contact XBMC JSON API at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING) return False def _update_library_json(self, host=None, showName=None): """Handles updating XBMC host via HTTP JSON-RPC Attempts to update the XBMC video library for a specific tv show if passed, otherwise update the whole library if enabled. Args: host: XBMC webserver host:port showName: Name of a TV show to specifically target the library update for Returns: Returns True or False
except urllib2.URLError, e: logger.log(u"XBMC: Error while trying to retrieve XBMC API version for " + host + ": " + ex(e), logger.WARNING) return False # parse the json result try: result = json.load(response) response.close() logger.log(u"XBMC: JSON response: " + str(result), logger.DEBUG) return result # need to return response for parsing except ValueError, e: logger.log(u"XBMC: Unable to decode JSON: " + response, logger.WARNING) return False except IOError, e: logger.log(u"XBMC: Could not contact XBMC JSON API at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING) return False def _update_library_json(self, host=None, showName=None): """Handles updating XBMC host via HTTP JSON-RPC Attempts to update the XBMC video library for a specific tv show if passed, otherwise update the whole library if enabled. Args: host: XBMC webserver host:port showName: Name of a TV show to specifically target the library update for Returns: Returns True or False
logger.log(u"Error while trying to retrieve XBMC API version for " + host + ": " + ex(e), logger.WARNING) return False # parse the json result try: result = json.load(response) response.close() logger.log(u"XBMC JSON response: " + str(result), logger.DEBUG) return result # need to return response for parsing except ValueError, e: logger.log(u"Unable to decode JSON: " + response, logger.WARNING) return False except IOError, e: logger.log(u"Warning: Couldn't contact XBMC JSON API at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING) return False def _update_library_json(self, host=None, showName=None): """Handles updating XBMC host via HTTP JSON-RPC Attempts to update the XBMC video library for a specific tv show if passed, otherwise update the whole library if enabled. Args: host: XBMC webserver host:port showName: Name of a TV show to specifically target the library update for Returns: Returns True or False
def run(self): """ Called every few seconds to handle any running/finished torrents """ if not LIBTORRENT_AVAILABLE: return if not self.loadedRunningTorrents: torrent_save_file = _get_running_torrents_pickle_path(False) if os.path.isfile(torrent_save_file): logger.log(u"Saved torrents found in %s, loading" % (torrent_save_file), logger.DEBUG) _load_saved_torrents() self.loadedRunningTorrents = True sess = _get_session(False) if sess is not None: while 1: a = sess.pop_alert() if not a: break if type(a) == str: logger.log(a, logger.DEBUG) else: logger.log(u"(%s): %s" % (type(a).__name__, ek.fixStupidEncodings(a.message(), True)), logger.DEBUG) logTorrentStatus = (time.time() - self.lastTorrentStatusLogTS) >= 600 for torrent_data in running_torrents: if torrent_data["handle"].has_metadata(): ti = torrent_data["handle"].get_torrent_info() name = ti.name() torrent_data["name"] = name torrent_data["total_size"] = ti.total_size() if not torrent_data["have_torrentFile"]: # if this was a magnet or url, and we now have downloaded the metadata # for it, best to save it locally in case we need to resume ti = torrent_data["handle"].get_torrent_info() torrentFile = lt.create_torrent(ti) torrent_data["torrent"] = lt.bencode(torrentFile.generate()) torrent_data["have_torrentFile"] = True logger.log( u"Created torrent file for %s as metadata d/l is now complete" % (name), logger.DEBUG ) else: name = "-" s = torrent_data["handle"].status() torrent_data["status"] = str(s.state) torrent_data["progress"] = s.progress torrent_data["rate_down"] = s.download_rate torrent_data["rate_up"] = s.upload_rate torrent_data["paused"] = s.paused torrent_data["error"] = s.error # currentRatio = 0.0 if s.total_download == 0 else float(s.total_upload)/float(s.total_download) currentRatio = ( 0.0 if s.all_time_download == 0 else float(s.all_time_upload) / float(s.all_time_download) ) torrent_data["ratio"] = currentRatio if s.state in [lt.torrent_status.seeding, lt.torrent_status.finished]: with torrent_data["lock"]: # this is the post-processing & removing code, so make sure that there's # only one thread doing either here, as the two could easily interfere with # one another if not torrent_data["post_processed"]: # torrent has just completed download, so we need to do # post-processing on it. ti = torrent_data["handle"].get_torrent_info() any_file_success = False for f in ti.files(): fullpath = os.path.join(sickbeard.LIBTORRENT_WORKING_DIR, "data", f.path) logger.log(u'Post-processing "%s"' % (fullpath), logger.DEBUG) if isMediaFile(fullpath): logger.log(u"this is a media file", logger.DEBUG) try: processor = postProcessor.PostProcessor(fullpath, name) if processor.process(forceKeepOriginalFiles=True): logger.log(u'Success post-processing "%s"' % (fullpath), logger.DEBUG) any_file_success = True except exceptions.PostProcessingFailed, e: logger.log( u'Failed post-processing file "%s" with error "%s"' % (fullpath, ex(e)), logger.ERROR, ) ## Richard Hills [email protected] 2013-07-20 : if your file is downloaded but does not match we remove torrent and leave files for manual processing. ## any file success can match a single file from a multi file torrent - we will lose some data regardless if we have 1 file in a multi file torrent which matches and the others fail if not any_file_success: logger.log( u'Post processing found no useful information for file "%s" please process this manually (rename/move and manually trigger processing)' % (fullpath), logger.ERROR, ) _remove_torrent_by_handle(torrent_data["handle"], False) else: torrent_data["post_processed"] = True else: # post-processing has already been performed. So we just # need to ensure check the ratio and delete the torrent # if we're good. if currentRatio >= sickbeard.LIBTORRENT_SEED_TO_RATIO: logger.log( u'Torrent "%s" has seeded to ratio %f. Removing it.' % (name, currentRatio), logger.MESSAGE, ) deleteFilesToo = True if not torrent_data["post_processed"]: logger.log(u"Torrent has not been post_processed. Keeping files.", logger.MESSAGE) deleteFilesToo = False _remove_torrent_by_handle(torrent_data["handle"], deleteFilesToo) else: if logTorrentStatus: self.lastTorrentStatusLogTS = time.time() logger.log(u'"%s" seeding %0.3f' % (name, currentRatio), logger.DEBUG) elif s.state == lt.torrent_status.downloading: if logTorrentStatus: self.lastTorrentStatusLogTS = time.time() logger.log(u'"%s" downloading %0.2f' % (name, s.progress * 100.0), logger.DEBUG)
def run(self): """ Called every few seconds to handle any running/finished torrents """ if not LIBTORRENT_AVAILABLE: return if not self.loadedRunningTorrents: torrent_save_file = _get_running_torrents_pickle_path(False) if os.path.isfile(torrent_save_file): logger.log(u'Saved torrents found in %s, loading' % (torrent_save_file), logger.DEBUG) _load_saved_torrents() self.loadedRunningTorrents = True sess = _get_session(False) if sess is not None: while 1: a = sess.pop_alert() if not a: break if type(a) == str: logger.log(a, logger.DEBUG) else: logger.log(u'(%s): %s' % (type(a).__name__, ek.fixStupidEncodings(a.message(), True)), logger.DEBUG) logTorrentStatus = (time.time() - self.lastTorrentStatusLogTS) >= 600 for torrent_data in running_torrents: if torrent_data['handle'].has_metadata(): ti = torrent_data['handle'].get_torrent_info() name = ti.name() torrent_data['name'] = name torrent_data['total_size'] = ti.total_size() if not torrent_data['have_torrentFile']: # if this was a magnet or url, and we now have downloaded the metadata # for it, best to save it locally in case we need to resume ti = torrent_data['handle'].get_torrent_info() torrentFile = lt.create_torrent(ti) torrent_data['torrent'] = lt.bencode(torrentFile.generate()) torrent_data['have_torrentFile'] = True logger.log(u'Created torrent file for %s as metadata d/l is now complete' % (name), logger.DEBUG) if not torrent_data['checkedForMedia']: with torrent_data['lock']: # Torrent has metadata, but hasn't been checked for valid media yet. Do so now. if not _torrent_has_any_media_files(ti): logger.log(u'Torrent %s has no media files! Deleting it.' % (name), logger.ERROR) _on_failed_torrent(torrent_data['key'], removeFromRunningTorrents=True, markEpisodesWanted=True) break # continue here would be nice, but safer to break b/c we have modified the list torrent_data['checkedForMedia'] = True else: name = '-' s = torrent_data['handle'].status() torrent_data['status'] = str(s.state) torrent_data['progress'] = s.progress torrent_data['rate_down'] = s.download_rate torrent_data['rate_up'] = s.upload_rate torrent_data['paused'] = s.paused torrent_data['error'] = s.error #currentRatio = 0.0 if s.total_download == 0 else float(s.total_upload)/float(s.total_download) currentRatio = 0.0 if s.all_time_download == 0 else float(s.all_time_upload)/float(s.all_time_download) torrent_data['ratio'] = currentRatio if s.state in [lt.torrent_status.seeding, lt.torrent_status.finished]: with torrent_data['lock']: # this is the post-processing & removing code, so make sure that there's # only one thread doing either here, as the two could easily interfere with # one another if not torrent_data['post_processed']: # torrent has just completed download, so we need to do # post-processing on it. ti = torrent_data['handle'].get_torrent_info() any_file_success = False for f in ti.files(): fullpath = os.path.join(sickbeard.LIBTORRENT_WORKING_DIR, 'data', f.path) logger.log(u'Post-processing "%s"' % (fullpath), logger.DEBUG) if isMediaFile(fullpath): logger.log(u'this is a media file', logger.DEBUG) try: processor = postProcessor.PostProcessor(fullpath, name) if processor.process(forceKeepOriginalFiles=True): logger.log(u'Success post-processing "%s"' % (fullpath), logger.DEBUG) any_file_success = True except exceptions.PostProcessingFailed, e: logger.log(u'Failed post-processing file "%s" with error "%s"' % (fullpath, ex(e)), logger.ERROR) if not any_file_success: logger.log(u'When post-processing the completed torrent %s, no useful files were found.' % (name), logger.ERROR) torrent_data['post_processed'] = True else: # post-processing has already been performed. So we just # need to ensure check the ratio and delete the torrent # if we're good. if currentRatio >= sickbeard.LIBTORRENT_SEED_TO_RATIO: logger.log(u'Torrent "%s" has seeded to ratio %f. Removing it.' % (name, currentRatio), logger.MESSAGE) deleteFilesToo = True if not torrent_data['post_processed']: logger.log(u'Torrent has not been post_processed. Keeping files.', logger.MESSAGE) deleteFilesToo = False _remove_torrent_by_handle(torrent_data['handle'], deleteFilesToo) else: if logTorrentStatus: self.lastTorrentStatusLogTS = time.time() logger.log(u'"%s" seeding %0.3f' % (name, currentRatio), logger.DEBUG) elif s.state == lt.torrent_status.downloading: if logTorrentStatus: self.lastTorrentStatusLogTS = time.time() logger.log(u'"%s" downloading %0.2f' % (name, s.progress * 100.0), logger.DEBUG)
def run(self): """ Called every few seconds to handle any running/finished torrents """ if not LIBTORRENT_AVAILABLE: return if not self.loadedRunningTorrents: torrent_save_file = _get_running_torrents_pickle_path(False) if os.path.isfile(torrent_save_file): logger.log( u'Saved torrents found in %s, loading' % (torrent_save_file), logger.DEBUG) _load_saved_torrents() self.loadedRunningTorrents = True sess = _get_session(False) if sess is not None: while 1: a = sess.pop_alert() if not a: break if type(a) == str: logger.log(a, logger.DEBUG) else: logger.log( u'(%s): %s' % (type(a).__name__, ek.fixStupidEncodings(a.message(), True)), logger.DEBUG) logTorrentStatus = (time.time() - self.lastTorrentStatusLogTS) >= 600 for torrent_data in running_torrents: if torrent_data['handle'].has_metadata(): ti = torrent_data['handle'].get_torrent_info() name = ti.name() torrent_data['name'] = name torrent_data['total_size'] = ti.total_size() if not torrent_data['have_torrentFile']: # if this was a magnet or url, and we now have downloaded the metadata # for it, best to save it locally in case we need to resume ti = torrent_data['handle'].get_torrent_info() torrentFile = lt.create_torrent(ti) torrent_data['torrent'] = lt.bencode( torrentFile.generate()) torrent_data['have_torrentFile'] = True logger.log( u'Created torrent file for %s as metadata d/l is now complete' % (name), logger.DEBUG) else: name = '-' s = torrent_data['handle'].status() torrent_data['status'] = str(s.state) torrent_data['progress'] = s.progress torrent_data['rate_down'] = s.download_rate torrent_data['rate_up'] = s.upload_rate torrent_data['paused'] = s.paused torrent_data['error'] = s.error #currentRatio = 0.0 if s.total_download == 0 else float(s.total_upload)/float(s.total_download) currentRatio = 0.0 if s.all_time_download == 0 else float( s.all_time_upload) / float(s.all_time_download) torrent_data['ratio'] = currentRatio if s.state in [ lt.torrent_status.seeding, lt.torrent_status.finished ]: with torrent_data['lock']: # this is the post-processing & removing code, so make sure that there's # only one thread doing either here, as the two could easily interfere with # one another if not torrent_data['post_processed']: # torrent has just completed download, so we need to do # post-processing on it. ti = torrent_data['handle'].get_torrent_info() any_file_success = False for f in ti.files(): fullpath = os.path.join( sickbeard.LIBTORRENT_WORKING_DIR, 'data', f.path) logger.log( u'Post-processing "%s"' % (fullpath), logger.DEBUG) if isMediaFile(fullpath): logger.log(u'this is a media file', logger.DEBUG) try: processor = postProcessor.PostProcessor( fullpath, name) if processor.process( forceKeepOriginalFiles=True): logger.log( u'Success post-processing "%s"' % (fullpath), logger.DEBUG) any_file_success = True except exceptions.PostProcessingFailed, e: logger.log( u'Failed post-processing file "%s" with error "%s"' % (fullpath, ex(e)), logger.ERROR) if not any_file_success: logger.log( u'When post-processing the completed torrent %s, no useful files were found.' % (name), logger.ERROR) torrent_data['post_processed'] = True else: # post-processing has already been performed. So we just # need to ensure check the ratio and delete the torrent # if we're good. if currentRatio >= sickbeard.LIBTORRENT_SEED_TO_RATIO: logger.log( u'Torrent "%s" has seeded to ratio %f. Removing it.' % (name, currentRatio), logger.MESSAGE) deleteFilesToo = True if not torrent_data['post_processed']: logger.log( u'Torrent has not been post_processed. Keeping files.', logger.MESSAGE) deleteFilesToo = False _remove_torrent_by_handle( torrent_data['handle'], deleteFilesToo) else: if logTorrentStatus: self.lastTorrentStatusLogTS = time.time() logger.log( u'"%s" seeding %0.3f' % (name, currentRatio), logger.DEBUG) elif s.state == lt.torrent_status.downloading: if logTorrentStatus: self.lastTorrentStatusLogTS = time.time() logger.log( u'"%s" downloading %0.2f' % (name, s.progress * 100.0), logger.DEBUG)