def ex(e):
    # type: (BaseException) -> AnyStr
    """Returns a unicode string from the exception text if it exists"""

    if not PY2:
        return str(e)

    e_message = u''

    if not e or not e.args:
        return e_message

    for arg in e.args:

        if None is not arg:
            if isinstance(arg, string_types):
                fixed_arg = fixStupidEncodings(arg, True)

            else:
                try:
                    fixed_arg = u'error ' + fixStupidEncodings(str(arg), True)

                except (BaseException, Exception):
                    fixed_arg = None

            if fixed_arg:
                if not e_message:
                    e_message = fixed_arg

                else:
                    e_message = e_message + ' : ' + fixed_arg

    return e_message
Exemple #2
0
    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 not PY2 or type(command[key]) == text_type:
                command[key] = command[key].encode('utf-8')

        enc_command = urlencode(command)
        self._log_debug(u'Encoded API command: ' + enc_command)

        url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command)
        try:
            req = urllib.request.Request(url)
            # if we have a password, use authentication
            if password:
                req.add_header(
                    'Authorization', 'Basic %s' %
                    b64encodestring('%s:%s' % (username, password)))
                self._log_debug(u'Contacting (with auth header) via url: ' +
                                fixStupidEncodings(url))
            else:
                self._log_debug(u'Contacting via url: ' +
                                fixStupidEncodings(url))

            http_response_obj = urllib.request.urlopen(
                req)  # PY2 http_response_obj has no `with` context manager
            result = decode_str(http_response_obj.read(),
                                sickbeard.SYS_ENCODING)
            http_response_obj.close()

            self._log_debug(u'HTTP response: ' + result.replace('\n', ''))
            return result

        except (urllib.error.URLError, IOError) as e:
            self._log_warning(u'Couldn\'t contact HTTP at %s %s' %
                              (fixStupidEncodings(url), ex(e)))
            return False
Exemple #3
0
    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 not PY2 or type(command[key]) == text_type:
                command[key] = command[key].encode('utf-8')

        enc_command = urlencode(command)
        self._log_debug(u'Encoded API command: ' + enc_command)

        url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command)
        try:
            req = urllib.request.Request(url)
            if password:
                req.add_header(
                    'Authorization', 'Basic %s' %
                    b64encodestring('%s:%s' % (username, password)))
                self._log_debug(u'Contacting (with auth header) via url: ' +
                                url)
            else:
                self._log_debug(u'Contacting via url: ' + url)

            http_response_obj = urllib.request.urlopen(
                req)  # PY2 http_response_obj has no `with` context manager
            result = decode_str(http_response_obj.read(),
                                sickbeard.SYS_ENCODING)
            http_response_obj.close()

            self._log_debug(u'HTTP response: ' + result.replace('\n', ''))
            return True

        except (urllib.error.URLError, IOError) as e:
            self._log_warning(u'Couldn\'t contact Plex at ' +
                              fixStupidEncodings(url) + ' ' + ex(e))
            return False
Exemple #4
0
 def _recursiveSearch(self, entry, depth=0):
     """
     Searches files in the entry
     This will output a list of tuples (filename, languages)
     """
     if depth > self.max_depth and self.max_depth != 0:  # we do not want to search the whole file system except if max_depth = 0
         return []
     if ek.ek(os.path.isfile, entry):  # a file? scan it
         if depth != 0:  # only check for valid format if recursing, trust the user
             mimetypes.add_type("video/x-matroska", ".mkv")
             mimetype = mimetypes.guess_type(entry)[0]
             if mimetype not in SUPPORTED_FORMATS:
                 return []
         basepath = ek.fixStupidEncodings(ek.ek(os.path.splitext, entry)[0])
         # check for .xx.srt if needed
         if self.multi and self.languages:
             if self.force:
                 return [(self.languages, [ek.ek(os.path.normpath, entry)])]
             needed_languages = self.languages[:]
             for l in self.languages:
                 if ek.ek(os.path.exists, basepath + '.%s.srt' % l):
                     logger.info(u"Skipping language %s for file %s as it already exists. Use the --force option to force the download" % (l, entry))
                     needed_languages.remove(l)
             if needed_languages:
                 return [(needed_languages, [ek.ek(os.path.normpath, entry)])]
             return []
         # single subtitle download: .srt
         if self.force or not ek.ek(os.path.exists, basepath + '.srt'):
             return [(self.languages, [ek.ek(os.path.normpath, entry)])]
     if ek.ek(os.path.isdir, entry):  # a dir? recurse
         #TODO if hidden folder, don't keep going (how to handle windows/mac/linux ?)
         files = []
         for e in ek.ek(os.listdir, entry):
             files.extend(self._recursiveSearch(ek.ek(os.path.join, entry, e), depth + 1))
         files.sort()
         grouped_files = []
         for languages, group in groupby(files, lambda t: t[0]):
             filenames = []
             for t in group:
                 filenames.extend(t[1])
             grouped_files.append((languages, filenames))
         return grouped_files
     return []  # anything else, nothing.
Exemple #5
0
 def listSubtitles(self, entries):
     """
     Searches subtitles within the active plugins and returns all found matching subtitles.
     entries can be:
         - filepaths
         - folderpaths (N.B. internal recursive search function will be used)
         - filenames
     """
     search_results = []
     if isinstance(entries, basestring):
         entries = [ek.fixStupidEncodings(entries)]
     elif not isinstance(entries, list):
         raise TypeError('Entries should be a list or a string')
     for e in entries:
         search_results.extend(self._recursiveSearch(e))
     taskCount = 0
     for (l, f) in search_results:
         taskCount += self.searchSubtitlesThreaded(f, l)
     subtitles = []
     for i in range(taskCount):
         subtitles.extend(self.resultQueue.get(timeout=10))
     return subtitles
Exemple #6
0
    def _send_to_xbmc_json(self,
                           command,
                           host=None,
                           username=None,
                           password=None):
        # type: (...) -> Union[bool, Dict]
        """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 = urllib.request.Request(url, command)
            req.add_header('Content-type', 'application/json')
            # if we have a password, use authentication
            if password:
                req.add_header(
                    'Authorization', 'Basic %s' %
                    b64encodestring('%s:%s' % (username, password)))
                self._log_debug(u'Contacting (with auth header) via url: ' +
                                fixStupidEncodings(url))
            else:
                self._log_debug(u'Contacting via url: ' +
                                fixStupidEncodings(url))

            try:
                http_response_obj = urllib.request.urlopen(
                    req)  # PY2 http_response_obj has no `with` context manager
            except urllib.error.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(http_response_obj)
                http_response_obj.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: ' +
                                  http_response_obj)
                return False

        except IOError as e:
            self._log_warning(u'Couldn\'t contact JSON API at ' +
                              fixStupidEncodings(url) + ' ' + ex(e))
            return False