Example #1
0
    def _get_url(self, url, params=None, data=None, headers=None, cache_limit=1):
        if headers is None: headers = {}
        if data is not None:
            if isinstance(data, basestring):
                data = data
            else:
                data = urllib.urlencode(data, True)
        
        if not url.startswith('http'):
            url = '%s%s%s' % (self.protocol, self.BASE_URL, url)
        if params: url += '?' + urllib.urlencode(params)
        _created, cached_headers, html = db_connection.get_cached_url(url, data, cache_limit=cache_limit)
        if html:
            logger.log('Using Cached result for: %s' % (url))
            result = html
            res_headers = dict(cached_headers)
        else:
            try:
                headers['Accept-Encoding'] = 'gzip'
                logger.log('+++Image Scraper Call: %s, header: %s, data: %s cache_limit: %s' % (url, headers, data, cache_limit), log_utils.LOGDEBUG)
                request = urllib2.Request(url, data=data, headers=headers)
                response = urllib2.urlopen(request)
                result = ''
                while True:
                    data = response.read()
                    if not data: break
                    result += data
                res_headers = dict(response.info().items())
                if res_headers.get('content-encoding') == 'gzip':
                    result = utils2.ungz(result)
                db_connection.cache_url(url, result, data, res_header=res_headers)
            except (ssl.SSLError, socket.timeout) as e:
                logger.log('Image Scraper Timeout: %s' % (url))
                return {}
            except urllib2.HTTPError as e:
                if e.code != 404:
                    logger.log('HTTP Error (%s) during image scraper http get: %s' % (e, url), log_utils.LOGWARNING)
                return {}
            except Exception as e:
                logger.log('Error (%s) during image scraper http get: %s' % (str(e), url), log_utils.LOGWARNING)
                return {}

        try:
            if 'application/json' in res_headers.get('content-type', ''):
                return_data = utils.json_loads_as_str(result)
            else:
                # try/except to handle older responses that might be missing headers
                try: return_data = utils.json_loads_as_str(result)
                except ValueError: return_data = result
        except ValueError:
            return_data = ''
            if result:
                logger.log('Invalid JSON API Response: %s - |%s|' % (url, return_data), log_utils.LOGERROR)

        return return_data
Example #2
0
    def _get_url(self, url, params=None, data=None, headers=None, cache_limit=1):
        if headers is None: headers = {}
        if data is not None:
            if isinstance(data, basestring):
                data = data
            else:
                data = urllib.urlencode(data, True)
        
        if not url.startswith('http'):
            url = '%s%s%s' % (self.protocol, self.BASE_URL, url)
        if params: url += '?' + urllib.urlencode(params)
        _created, cached_headers, html = db_connection.get_cached_url(url, data, cache_limit=cache_limit)
        if html:
            logger.log('Using Cached result for: %s' % (url))
            result = html
            res_headers = dict(cached_headers)
        else:
            try:
                headers['Accept-Encoding'] = 'gzip'
                logger.log('+++Image Scraper Call: %s, header: %s, data: %s cache_limit: %s' % (url, headers, data, cache_limit), log_utils.LOGDEBUG)
                request = urllib2.Request(url, data=data, headers=headers)
                response = urllib2.urlopen(request)
                result = ''
                while True:
                    data = response.read()
                    if not data: break
                    result += data
                res_headers = dict(response.info().items())
                if res_headers.get('content-encoding') == 'gzip':
                    result = utils2.ungz(result)
                db_connection.cache_url(url, result, data, res_header=res_headers)
            except (ssl.SSLError, socket.timeout) as e:
                logger.log('Image Scraper Timeout: %s' % (url))
                return {}
            except urllib2.HTTPError as e:
                if e.code != 404:
                    logger.log('HTTP Error (%s) during image scraper http get: %s' % (e, url), log_utils.LOGWARNING)
                return {}
            except Exception as e:
                logger.log('Error (%s) during image scraper http get: %s' % (str(e), url), log_utils.LOGWARNING)
                return {}

        try:
            if 'application/json' in res_headers.get('content-type', ''):
                return_data = utils.json_loads_as_str(result)
            else:
                # try/except to handle older responses that might be missing headers
                try: return_data = utils.json_loads_as_str(result)
                except ValueError: return_data = result
        except ValueError:
            return_data = ''
            if result:
                logger.log('Invalid JSON API Response: %s - |%s|' % (url, return_data), log_utils.LOGERROR)

        return return_data
Example #3
0
def getTraktAsJson(url, post=None):
    try:
        r, res_headers = __getTrakt(url, post)
        r = utils.json_loads_as_str(r)
        if 'X-Sort-By' in res_headers and 'X-Sort-How' in res_headers:
            r = sort_list(res_headers['X-Sort-By'], res_headers['X-Sort-How'], r)
        return r
    except:
        pass
    def _get_url(self, url, params=None, data=None, headers=None):
        if headers is None:
            headers = {}
        if data is not None:
            if isinstance(data, basestring):
                data = data
            else:
                data = urllib.urlencode(data, True)

        url = "%s%s%s" % (self.protocol, self.BASE_URL, url)
        if params:
            url = url + "?" + urllib.urlencode(params)
        log_utils.log("Calling: %s" % (url))
        db_connection = _get_db_connection()
        _created, _res_header, html = db_connection.get_cached_url(url, data, cache_limit=1)
        if html:
            log_utils.log("Using Cached result for: %s" % (url))
            result = html
        else:
            try:
                request = urllib2.Request(url, data=data, headers=headers)
                response = urllib2.urlopen(request)
                result = ""
                while True:
                    data = response.read()
                    if not data:
                        break
                    result += data
                db_connection.cache_url(url, result, data)
            except (ssl.SSLError, socket.timeout) as e:
                log_utils.log("Image Scraper Timeout: %s" % (url))
                return {}
            except urllib2.HTTPError as e:
                if e.code != 404:
                    log_utils.log("HTTP Error (%s) during image scraper http get: %s" % (e, url))
                return {}
            except Exception as e:
                log_utils.log("Error (%s) during image scraper http get: %s" % (str(e), url), log_utils.LOGWARNING)
                return {}

        try:
            js_data = utils.json_loads_as_str(result)
        except ValueError:
            js_data = ""
            if result:
                log_utils.log("Invalid JSON API Response: %s - |%s|" % (url, js_data), log_utils.LOGERROR)

        return js_data
Example #5
0
def authTrakt():
    try:
        if getTraktCredentialsInfo() == True:
            if control.yesnoDialog(control.lang(32511).encode('utf-8'), control.lang(32512).encode('utf-8'), '', 'Trakt'):
                control.setSetting(id='trakt.user', value='')
                control.setSetting(id='trakt.token', value='')
                control.setSetting(id='trakt.refresh', value='')
            raise Exception()

        result = getTraktAsJson('/oauth/device/code', {'client_id': V2_API_KEY})
        verification_url = (control.lang(32513) % result['verification_url']).encode('utf-8')
        user_code = (control.lang(32514) % result['user_code']).encode('utf-8')
        expires_in = int(result['expires_in'])
        device_code = result['device_code']
        interval = result['interval']

        progressDialog = control.progressDialog
        progressDialog.create('Trakt', verification_url, user_code)

        for i in range(0, expires_in):
            try:
                if progressDialog.iscanceled(): break
                time.sleep(1)
                if not float(i) % interval == 0: raise Exception()
                r = getTraktAsJson('/oauth/device/token', {'client_id': V2_API_KEY, 'client_secret': CLIENT_SECRET, 'code': device_code})
                if 'access_token' in r: break
            except:
                pass

        try: progressDialog.close()
        except: pass

        token, refresh = r['access_token'], r['refresh_token']

        headers = {'Content-Type': 'application/json', 'trakt-api-key': V2_API_KEY, 'trakt-api-version': 2, 'Authorization': 'Bearer %s' % token}


        result = client.request(urlparse.urljoin(BASE_URL, '/users/me'), headers=headers)
        result = utils.json_loads_as_str(result)

        user = result['username']

        control.setSetting(id='trakt.user', value=user)
        control.setSetting(id='trakt.token', value=token)
        control.setSetting(id='trakt.refresh', value=refresh)
        raise Exception()
    except:
        control.openSettings('4.1')
Example #6
0
def __getTrakt(url, post=None):
    try:
        url = urlparse.urljoin(BASE_URL, url)
        post = json.dumps(post) if post else None
        headers = {'Content-Type': 'application/json', 'trakt-api-key': V2_API_KEY, 'trakt-api-version': 2}

        if getTraktCredentialsInfo():
            headers.update({'Authorization': 'Bearer %s' % control.setting('trakt.token')})

        result = client.request(url, post=post, headers=headers, output='extended', error=True)

        resp_code = result[1]
        resp_header = result[2]
        result = result[0]

        if resp_code in ['500', '502', '503', '504', '520', '521', '522', '524']:
            log_utils.log('Temporary Trakt Error: %s' % resp_code, log_utils.LOGWARNING)
            return
        elif resp_code in ['404']:
            log_utils.log('Object Not Found : %s' % resp_code, log_utils.LOGWARNING)
            return
#        elif resp_code in ['429']:
#            log_utils.log('Trakt Rate Limit Reached: %s' % resp_code, log_utils.LOGWARNING)
#            return

        if resp_code not in ['401', '405']:
            return result, resp_header

        oauth = urlparse.urljoin(BASE_URL, '/oauth/token')
        opost = {'client_id': V2_API_KEY, 'client_secret': CLIENT_SECRET, 'redirect_uri': REDIRECT_URI, 'grant_type': 'refresh_token', 'refresh_token': control.setting('trakt.refresh')}

        result = client.request(oauth, post=json.dumps(opost), headers=headers)
        result = utils.json_loads_as_str(result)

        token, refresh = result['access_token'], result['refresh_token']

        control.setSetting(id='trakt.token', value=token)
        control.setSetting(id='trakt.refresh', value=refresh)

        headers['Authorization'] = 'Bearer %s' % token

        result = client.request(url, post=post, headers=headers, output='extended', error=True)
        return result[0], result[2]
    except Exception as e:
        log_utils.log('Unknown Trakt Error: %s' % e, log_utils.LOGWARNING)
        pass
Example #7
0
def manager(name, imdb, tvdb, content):
    try:
        post = {"movies": [{"ids": {"imdb": imdb}}]} if content == 'movie' else {"shows": [{"ids": {"tvdb": tvdb}}]}

        items = [(control.lang(32516).encode('utf-8'), '/sync/collection')]
        items += [(control.lang(32517).encode('utf-8'), '/sync/collection/remove')]
        items += [(control.lang(32518).encode('utf-8'), '/sync/watchlist')]
        items += [(control.lang(32519).encode('utf-8'), '/sync/watchlist/remove')]
        items += [(control.lang(32520).encode('utf-8'), '/users/me/lists/%s/items')]

        result = getTraktAsJson('/users/me/lists')
        lists = [(i['name'], i['ids']['slug']) for i in result]
        lists = [lists[i//2] for i in range(len(lists)*2)]
        for i in range(0, len(lists), 2):
            lists[i] = ((control.lang(32521) % lists[i][0]).encode('utf-8'), '/users/me/lists/%s/items' % lists[i][1])
        for i in range(1, len(lists), 2):
            lists[i] = ((control.lang(32522) % lists[i][0]).encode('utf-8'), '/users/me/lists/%s/items/remove' % lists[i][1])
        items += lists

        select = control.selectDialog([i[0] for i in items], control.lang(32515).encode('utf-8'))

        if select == -1:
            return
        elif select == 4:
            t = control.lang(32520).encode('utf-8')
            k = control.keyboard('', t) ; k.doModal()
            new = k.getText() if k.isConfirmed() else None
            if (new == None or new == ''): return
            result = __getTrakt('/users/me/lists', post={"name": new, "privacy": "private"})[0]

            try: slug = utils.json_loads_as_str(result)['ids']['slug']
            except: return control.infoDialog(control.lang(32515).encode('utf-8'), heading=str(name), sound=True, icon='ERROR')
            result = __getTrakt(items[select][1] % slug, post=post)[0]
        else:
            result = __getTrakt(items[select][1], post=post)[0]

        icon = control.infoLabel('ListItem.Icon') if not result == None else 'ERROR'

        control.infoDialog(control.lang(32515).encode('utf-8'), heading=str(name), sound=True, icon=icon)
    except:
        return
Example #8
0
    def __call_trakt(self,
                     url,
                     method=None,
                     data=None,
                     params=None,
                     auth=True,
                     cache_limit=.25,
                     cached=True):
        res_headers = {}
        if not cached: cache_limit = 0
        if self.offline:
            db_cache_limit = int(time.time()) / 60 / 60
        else:
            if cache_limit > 8:
                db_cache_limit = cache_limit
            else:
                db_cache_limit = 8
        json_data = json.dumps(data) if data else None
        headers = {
            'Content-Type': 'application/json',
            'trakt-api-key': V2_API_KEY,
            'trakt-api-version': 2,
            'Accept-Encoding': 'gzip'
        }
        url = '%s%s%s' % (self.protocol, BASE_URL, url)
        if params: url += '?' + urllib.urlencode(params)

        db_connection = self.__get_db_connection()
        created, cached_headers, cached_result = db_connection.get_cached_url(
            url, json_data, db_cache_limit)
        if cached_result and (self.offline or (time.time() - created) <
                              (60 * 60 * cache_limit)):
            result = cached_result
            res_headers = dict(cached_headers)
            logger.log('***Using cached result for: %s' % (url),
                       log_utils.LOGDEBUG)
        else:
            auth_retry = False
            while True:
                try:
                    if auth:
                        headers.update(
                            {'Authorization': 'Bearer %s' % (self.token)})
                    logger.log(
                        '***Trakt Call: %s, header: %s, data: %s cache_limit: %s cached: %s'
                        % (url, headers, json_data, cache_limit, cached),
                        log_utils.LOGDEBUG)
                    request = urllib2.Request(url,
                                              data=json_data,
                                              headers=headers)
                    if method is not None:
                        request.get_method = lambda: method.upper()
                    response = urllib2.urlopen(request, timeout=self.timeout)
                    result = ''
                    while True:
                        data = response.read()
                        if not data: break
                        result += data

                    res_headers = dict(response.info().items())
                    if res_headers.get('content-encoding') == 'gzip':
                        result = utils2.ungz(result)

                    db_connection.cache_url(url, result, json_data,
                                            response.info().items())
                    break
                except (ssl.SSLError, socket.timeout) as e:
                    if cached_result:
                        result = cached_result
                        logger.log(
                            'Temporary Trakt Error (%s). Using Cached Page Instead.'
                            % (str(e)), log_utils.LOGWARNING)
                    else:
                        raise TransientTraktError('Temporary Trakt Error: ' +
                                                  str(e))
                except urllib2.URLError as e:
                    if isinstance(e, urllib2.HTTPError):
                        if e.code in TEMP_ERRORS:
                            if cached_result:
                                result = cached_result
                                logger.log(
                                    'Temporary Trakt Error (%s). Using Cached Page Instead.'
                                    % (str(e)), log_utils.LOGWARNING)
                                break
                            else:
                                raise TransientTraktError(
                                    'Temporary Trakt Error: ' + str(e))
                        elif e.code == 401 or e.code == 405:
                            # token is fine, profile is private
                            if e.info().getheader('X-Private-User') == 'true':
                                raise TraktAuthError(
                                    'Object is No Longer Available (%s)' %
                                    (e.code))
                            # auth failure retry or a token request
                            elif auth_retry or url.endswith('/oauth/token'):
                                self.token = None
                                kodi.set_setting('trakt_oauth_token', '')
                                kodi.set_setting('trakt_refresh_token', '')
                                raise TraktAuthError(
                                    'Trakt Call Authentication Failed (%s)' %
                                    (e.code))
                            # first try token fail, try to refresh token
                            else:
                                result = self.refresh_token(
                                    kodi.get_setting('trakt_refresh_token'))
                                self.token = result['access_token']
                                kodi.set_setting('trakt_oauth_token',
                                                 result['access_token'])
                                kodi.set_setting('trakt_refresh_token',
                                                 result['refresh_token'])
                                auth_retry = True
                        elif e.code == 404:
                            raise TraktNotFoundError(
                                'Object Not Found (%s): %s' % (e.code, url))
                        else:
                            raise
                    elif isinstance(e.reason, socket.timeout) or isinstance(
                            e.reason, ssl.SSLError):
                        if cached_result:
                            result = cached_result
                            logger.log(
                                'Temporary Trakt Error (%s). Using Cached Page Instead'
                                % (str(e)), log_utils.LOGWARNING)
                            break
                        else:
                            raise TransientTraktError(
                                'Temporary Trakt Error: ' + str(e))
                    else:
                        raise TraktError('Trakt Error: ' + str(e))
                except:
                    raise

        try:
            js_data = utils.json_loads_as_str(result)
            if 'x-sort-by' in res_headers and 'x-sort-how' in res_headers:
                js_data = utils2.sort_list(res_headers['x-sort-by'],
                                           res_headers['x-sort-how'], js_data)
        except ValueError:
            js_data = ''
            if result:
                logger.log(
                    'Invalid JSON Trakt API Response: %s - |%s|' %
                    (url, js_data), log_utils.LOGERROR)

        # logger.log('Trakt Response: %s' % (response), xbmc.LOGDEBUG)
        return js_data
Example #9
0
    def __call_trakt(self, url, method=None, data=None, params=None, auth=True, cache_limit=.25, cached=True):
        res_headers = {}
        if not cached: cache_limit = 0
        if self.offline:
            db_cache_limit = int(time.time()) / 60 / 60
        else:
            if cache_limit > 8:
                db_cache_limit = cache_limit
            else:
                db_cache_limit = 8
        json_data = json.dumps(data) if data else None
        headers = {'Content-Type': 'application/json', 'trakt-api-key': V2_API_KEY, 'trakt-api-version': 2, 'Accept-Encoding': 'gzip'}
        url = '%s%s%s' % (self.protocol, BASE_URL, url)
        if params: url += '?' + urllib.urlencode(params)

        db_connection = self.__get_db_connection()
        created, cached_headers, cached_result = db_connection.get_cached_url(url, json_data, db_cache_limit)
        if cached_result and (self.offline or (time.time() - created) < (60 * 60 * cache_limit)):
            result = cached_result
            res_headers = dict(cached_headers)
            logger.log('***Using cached result for: %s' % (url), log_utils.LOGDEBUG)
        else:
            auth_retry = False
            while True:
                try:
                    if auth: headers.update({'Authorization': 'Bearer %s' % (self.token)})
                    logger.log('***Trakt Call: %s, header: %s, data: %s cache_limit: %s cached: %s' % (url, headers, json_data, cache_limit, cached), log_utils.LOGDEBUG)
                    request = urllib2.Request(url, data=json_data, headers=headers)
                    if method is not None: request.get_method = lambda: method.upper()
                    response = urllib2.urlopen(request, timeout=self.timeout)
                    result = ''
                    while True:
                        data = response.read()
                        if not data: break
                        result += data

                    res_headers = dict(response.info().items())
                    if res_headers.get('content-encoding') == 'gzip':
                        result = utils2.ungz(result)

                    db_connection.cache_url(url, result, json_data, response.info().items())
                    break
                except (ssl.SSLError, socket.timeout) as e:
                    if cached_result:
                        result = cached_result
                        logger.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), log_utils.LOGWARNING)
                    else:
                        raise TransientTraktError('Temporary Trakt Error: ' + str(e))
                except urllib2.URLError as e:
                    if isinstance(e, urllib2.HTTPError):
                        if e.code in TEMP_ERRORS:
                            if cached_result:
                                result = cached_result
                                logger.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), log_utils.LOGWARNING)
                                break
                            else:
                                raise TransientTraktError('Temporary Trakt Error: ' + str(e))
                        elif e.code == 401 or e.code == 405:
                            # token is fine, profile is private
                            if e.info().getheader('X-Private-User') == 'true':
                                raise TraktAuthError('Object is No Longer Available (%s)' % (e.code))
                            # auth failure retry or a token request
                            elif auth_retry or url.endswith('/oauth/token'):
                                self.token = None
                                kodi.set_setting('trakt_oauth_token', '')
                                kodi.set_setting('trakt_refresh_token', '')
                                raise TraktAuthError('Trakt Call Authentication Failed (%s)' % (e.code))
                            # first try token fail, try to refresh token
                            else:
                                result = self.refresh_token(kodi.get_setting('trakt_refresh_token'))
                                self.token = result['access_token']
                                kodi.set_setting('trakt_oauth_token', result['access_token'])
                                kodi.set_setting('trakt_refresh_token', result['refresh_token'])
                                auth_retry = True
                        elif e.code == 404:
                            raise TraktNotFoundError('Object Not Found (%s): %s' % (e.code, url))
                        else:
                            raise
                    elif isinstance(e.reason, socket.timeout) or isinstance(e.reason, ssl.SSLError):
                        if cached_result:
                            result = cached_result
                            logger.log('Temporary Trakt Error (%s). Using Cached Page Instead' % (str(e)), log_utils.LOGWARNING)
                            break
                        else:
                            raise TransientTraktError('Temporary Trakt Error: ' + str(e))
                    else:
                        raise TraktError('Trakt Error: ' + str(e))
                except:
                    raise

        try:
            js_data = utils.json_loads_as_str(result)
            if 'x-sort-by' in res_headers and 'x-sort-how' in res_headers:
                js_data = utils2.sort_list(res_headers['x-sort-by'], res_headers['x-sort-how'], js_data)
        except ValueError:
            js_data = ''
            if result:
                logger.log('Invalid JSON Trakt API Response: %s - |%s|' % (url, js_data), log_utils.LOGERROR)

        # logger.log('Trakt Response: %s' % (response), xbmc.LOGDEBUG)
        return js_data
    def __call_trakt(self,
                     url,
                     method=None,
                     data=None,
                     params=None,
                     auth=True,
                     cache_limit=.25,
                     cached=True):
        if not cached: cache_limit = 0
        json_data = json.dumps(data) if data else None
        headers = {
            'Content-Type': 'application/json',
            'trakt-api-key': V2_API_KEY,
            'trakt-api-version': 2
        }
        url = '%s%s%s' % (self.protocol, BASE_URL, url)
        if params: url = url + '?' + urllib.urlencode(params)

        args = [url]
        kwargs = {
            'method': method,
            'data': data,
            'params': params,
            'auth': auth
        }
        func_name = '__call_trakt'
        cached, cached_result = cache._get_func(func_name,
                                                args=args,
                                                kwargs=kwargs,
                                                cache_limit=cache_limit)
        if cached:
            result = cached_result
            logger.log('***Using cached result for: %s' % (url),
                       log_utils.LOGDEBUG)
        else:
            auth_retry = False
            while True:
                try:
                    if auth:
                        headers.update(
                            {'Authorization': 'Bearer %s' % (self.token)})
                    logger.log(
                        '***Trakt Call: %s, header: %s, data: %s cache_limit: %s cached: %s'
                        % (url, headers, json_data, cache_limit, cached),
                        log_utils.LOGDEBUG)
                    request = urllib2.Request(url,
                                              data=json_data,
                                              headers=headers)
                    if method is not None:
                        request.get_method = lambda: method.upper()
                    response = urllib2.urlopen(request, timeout=self.timeout)
                    result = ''
                    while True:
                        data = response.read()
                        if not data: break
                        result += data
                    cache._save_func(func_name,
                                     args=args,
                                     kwargs=kwargs,
                                     result=result)
                    break
                except (ssl.SSLError, socket.timeout) as e:
                    if cached_result:
                        result = cached_result
                        logger.log(
                            'Temporary Trakt Error (%s). Using Cached Page Instead.'
                            % (str(e)), log_utils.LOGWARNING)
                    else:
                        raise TransientTraktError('Temporary Trakt Error: ' +
                                                  str(e))
                except urllib2.URLError as e:
                    if isinstance(e, urllib2.HTTPError):
                        if e.code in TEMP_ERRORS:
                            if cached_result:
                                result = cached_result
                                logger.log(
                                    'Temporary Trakt Error (%s). Using Cached Page Instead.'
                                    % (str(e)), log_utils.LOGWARNING)
                                break
                            else:
                                raise TransientTraktError(
                                    'Temporary Trakt Error: ' + str(e))
                        elif e.code == 401 or e.code == 405:
                            # token is fine, profile is private
                            if e.info().getheader('X-Private-User') == 'true':
                                raise TraktAuthError(
                                    'Object is No Longer Available (%s)' %
                                    (e.code))
                            # auth failure retry or a token request
                            elif auth_retry or url.endswith('/oauth/token'):
                                self.token = None
                                kodi.set_setting('trakt_oauth_token', '')
                                kodi.set_setting('trakt_refresh_token', '')
                                raise TraktAuthError(
                                    'Trakt Call Authentication Failed (%s)' %
                                    (e.code))
                            # first try token fail, try to refresh token
                            else:
                                result = self.refresh_token(
                                    kodi.get_setting('trakt_refresh_token'))
                                self.token = result['access_token']
                                kodi.set_setting('trakt_oauth_token',
                                                 result['access_token'])
                                kodi.set_setting('trakt_refresh_token',
                                                 result['refresh_token'])
                                auth_retry = True
                        elif e.code == 404:
                            raise TraktNotFoundError('Object Not Found (%s)' %
                                                     (e.code))
                        else:
                            raise
                    elif isinstance(e.reason, socket.timeout) or isinstance(
                            e.reason, ssl.SSLError):
                        if cached_result:
                            result = cached_result
                            logger.log(
                                'Temporary Trakt Error (%s). Using Cached Page Instead'
                                % (str(e)), log_utils.LOGWARNING)
                            break
                        else:
                            raise TransientTraktError(
                                'Temporary Trakt Error: ' + str(e))
                    else:
                        raise TraktError('Trakt Error: ' + str(e))
                except:
                    raise

        try:
            js_data = utils.json_loads_as_str(result)
        except ValueError:
            js_data = ''
            if result:
                logger.log(
                    'Invalid JSON Trakt API Response: %s - |%s|' %
                    (url, js_data), log_utils.LOGERROR)

        # logger.log('Trakt Response: %s' % (response), xbmc.LOGDEBUG)
        return js_data
    def __call_trakt(self, url, method=None, data=None, params=None, auth=True, cache_limit=.25, cached=True):
        if not cached: cache_limit = 0
        json_data = json.dumps(data) if data else None
        headers = {'Content-Type': 'application/json', 'trakt-api-key': V2_API_KEY, 'trakt-api-version': 2}
        url = '%s%s%s' % (self.protocol, BASE_URL, url)
        if params: url = url + '?' + urllib.urlencode(params)

        args = [url]
        kwargs = {'method': method, 'data': data, 'params': params, 'auth': auth}
        func_name = '__call_trakt'
        cached, cached_result = cache._get_func(func_name, args=args, kwargs=kwargs, cache_limit=cache_limit)
        if cached:
            result = cached_result
            log_utils.log('***Using cached result for: %s' % (url), log_utils.LOGDEBUG)
        else:
            auth_retry = False
            while True:
                try:
                    if auth: headers.update({'Authorization': 'Bearer %s' % (self.token)})
                    log_utils.log('***Trakt Call: %s, header: %s, data: %s cache_limit: %s cached: %s' % (url, headers, json_data, cache_limit, cached), log_utils.LOGDEBUG)
                    request = urllib2.Request(url, data=json_data, headers=headers)
                    if method is not None: request.get_method = lambda: method.upper()
                    response = urllib2.urlopen(request, timeout=self.timeout)
                    result = ''
                    while True:
                        data = response.read()
                        if not data: break
                        result += data
                    cache._save_func(func_name, args=args, kwargs=kwargs, result=result)
                    break
                except (ssl.SSLError, socket.timeout) as e:
                    if cached_result:
                        result = cached_result
                        log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), log_utils.LOGWARNING)
                    else:
                        raise TransientTraktError('Temporary Trakt Error: ' + str(e))
                except urllib2.URLError as e:
                    if isinstance(e, urllib2.HTTPError):
                        if e.code in TEMP_ERRORS:
                            if cached_result:
                                result = cached_result
                                log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead.' % (str(e)), log_utils.LOGWARNING)
                                break
                            else:
                                raise TransientTraktError('Temporary Trakt Error: ' + str(e))
                        elif e.code == 401 or e.code == 405:
                            # token is fine, profile is private
                            if e.info().getheader('X-Private-User') == 'true':
                                raise TraktAuthError('Object is No Longer Available (%s)' % (e.code))
                            # auth failure retry or a token request
                            elif auth_retry or url.endswith('/oauth/token'):
                                self.token = None
                                kodi.set_setting('trakt_oauth_token', '')
                                kodi.set_setting('trakt_refresh_token', '')
                                raise TraktAuthError('Trakt Call Authentication Failed (%s)' % (e.code))
                            # first try token fail, try to refresh token
                            else:
                                result = self.refresh_token(kodi.get_setting('trakt_refresh_token'))
                                self.token = result['access_token']
                                kodi.set_setting('trakt_oauth_token', result['access_token'])
                                kodi.set_setting('trakt_refresh_token', result['refresh_token'])
                                auth_retry = True
                        elif e.code == 404:
                            raise TraktNotFoundError('Object Not Found (%s)' % (e.code))
                        else:
                            raise
                    elif isinstance(e.reason, socket.timeout) or isinstance(e.reason, ssl.SSLError):
                        if cached_result:
                            result = cached_result
                            log_utils.log('Temporary Trakt Error (%s). Using Cached Page Instead' % (str(e)), log_utils.LOGWARNING)
                            break
                        else:
                            raise TransientTraktError('Temporary Trakt Error: ' + str(e))
                    else:
                        raise TraktError('Trakt Error: ' + str(e))
                except:
                    raise

        try:
            js_data = utils.json_loads_as_str(result)
        except ValueError:
            js_data = ''
            if result:
                log_utils.log('Invalid JSON Trakt API Response: %s - |%s|' % (url, js_data), log_utils.LOGERROR)

        # log_utils.log('Trakt Response: %s' % (response), xbmc.LOGDEBUG)
        return js_data